155 files changed, 54649 insertions, 0 deletions
diff --git a/microkde/KDGanttMinimizeSplitter.cpp b/microkde/KDGanttMinimizeSplitter.cpp new file mode 100644 index 0000000..60b8bc7 --- a/dev/null +++ b/microkde/KDGanttMinimizeSplitter.cpp @@ -0,0 +1,1636 @@ +/* -*- Mode: C++ -*- + $Id$ +*/ + +/**************************************************************************** + ** Copyright (C) 2002-2004 Klarälvdalens Datakonsult AB. All rights reserved. + ** + ** This file is part of the KDGantt library. + ** + ** This file may be distributed and/or modified under the terms of the + ** GNU General Public License version 2 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. + ** + ** Licensees holding valid commercial KDGantt licenses may use this file in + ** accordance with the KDGantt Commercial License Agreement provided with + ** the Software. + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ** See http://www.klaralvdalens-datakonsult.se/Public/products/ for + ** information about KDGantt Commercial License Agreements. + ** + ** Contact info@klaralvdalens-datakonsult.se if any conditions of this + ** licensing are not clear to you. + ** + ** As a special exception, permission is given to link this program + ** with any edition of Qt, and distribute the resulting executable, + ** without including the source code for Qt in the source distribution. + ** + **********************************************************************/ + +#include "KDGanttMinimizeSplitter.h" +#ifndef QT_NO_SPLITTER___ + +#include "qpainter.h" +#include "qdrawutil.h" +#include "qbitmap.h" +#if QT_VERSION >= 300 +#include "qptrlist.h" +#include "qmemarray.h" +#else +#include <qlist.h> +#include <qarray.h> +#define QPtrList QList +#define QMemArray QArray +#endif +#include "qlayoutengine_p.h" +#include "qobjectlist.h" +#include "qstyle.h" +#include "qapplication.h" //sendPostedEvents +#include <qvaluelist.h> +#include <qcursor.h> +#ifndef KDGANTT_MASTER_CVS +//#include "KDGanttMinimizeSplitter.moc" +#endif + + + +#ifndef DOXYGEN_SKIP_INTERNAL + +#if QT_VERSION >= 232 +static int mouseOffset; +static int opaqueOldPos = -1; //### there's only one mouse, but this is a bit risky + + +KDGanttSplitterHandle::KDGanttSplitterHandle( Qt::Orientation o, + KDGanttMinimizeSplitter *parent, const char * name ) + : QWidget( parent, name ), _activeButton( 0 ), _collapsed( false ) +{ + + if ( QApplication::desktop()->width() > 320 && QApplication::desktop()->width() < 650 ) { + mSizeHint = QSize(7,7); + mUseOffset = true; + } else { + mSizeHint = QSize(6,6); + mUseOffset = false; + } + s = parent; + setOrientation(o); + setMouseTracking( true ); + //setMaximumHeight( 5 ); // test only +} + +QSize KDGanttSplitterHandle::sizeHint() const +{ + return mSizeHint; +} + +void KDGanttSplitterHandle::setOrientation( Qt::Orientation o ) +{ + orient = o; +#ifndef QT_NO_CURSOR + if ( o == KDGanttMinimizeSplitter::Horizontal ) + setCursor( splitHCursor ); + else + setCursor( splitVCursor ); +#endif +} + + +void KDGanttSplitterHandle::mouseMoveEvent( QMouseEvent *e ) +{ + updateCursor( e->pos() ); + if ( !(e->state()&LeftButton) ) + return; + + if ( _activeButton != 0) + return; + + QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos())) + - mouseOffset; + if ( true /*opaque()*/ ) { + s->moveSplitter( pos, id() ); + } else { + int min = pos; int max = pos; + s->getRange( id(), &min, &max ); + s->setRubberband( QMAX( min, QMIN(max, pos ))); + } + _collapsed = false; +} + +void KDGanttSplitterHandle::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) { + _activeButton = onButton( e->pos() ); + mouseOffset = s->pick(e->pos()); + if ( _activeButton != 0) + repaint(); + updateCursor( e->pos() ); + } +} + +void KDGanttSplitterHandle::updateCursor( const QPoint& p) +{ + if ( onButton( p ) != 0 ) { + setCursor( arrowCursor ); + } + else { + if ( orient == KDGanttMinimizeSplitter::Horizontal ) + setCursor( splitHCursor ); + else + setCursor( splitVCursor ); + } +} +void KDGanttSplitterHandle::toggle() +{ + int pos; + int min, max; + if ( !_collapsed ) { + s->expandPos( id(), &min, &max ); + if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Left + || s->minimizeDirection() == KDGanttMinimizeSplitter::Up ) { + pos = min; + } + else { + pos = max; + } + + _origPos = s->pick(mapToParent( QPoint( 0,0 ) )); + s->moveSplitter( pos, id() ); + _collapsed = true; + } + else { + s->moveSplitter( _origPos, id() ); + _collapsed = false; + } +} + +void KDGanttSplitterHandle::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( _activeButton != 0 ) { + if ( onButton( e->pos() ) == _activeButton ) + { + toggle(); + } + _activeButton = 0; + updateCursor( e->pos() ); + } + else { + if ( !opaque() && e->button() == LeftButton ) { + QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos())) + - mouseOffset; + s->setRubberband( -1 ); + s->moveSplitter( pos, id() ); + } + } + repaint(); +} + +int KDGanttSplitterHandle::onButton( const QPoint& p ) +{ + QValueList<QPointArray> list = buttonRegions(); + int index = 1; + int add = 12; + for( QValueList<QPointArray>::Iterator it = list.begin(); it != list.end(); ++it ) { + QRect rect = (*it).boundingRect(); + rect.setLeft( rect.left()- add ); + rect.setRight( rect.right() + add); + rect.setTop( rect.top()- add ); + rect.setBottom( rect.bottom() + add); + if ( rect.contains( p ) ) { + return index; + } + index++; + } + return 0; +} + + +QValueList<QPointArray> KDGanttSplitterHandle::buttonRegions() +{ + QValueList<QPointArray> list; + + int sw = 8; + int yyy = 1; + int xxx = 1; + int voffset[] = { (int) -sw*3, (int) sw*3 }; + for ( int i = 0; i < 2; i++ ) { + QPointArray arr; + if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Right || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Left) { + int mid = height()/2 + voffset[i]; + arr.setPoints( 3, + 1-xxx, mid - sw + 4, + sw-3-xxx, mid, + 1-xxx, mid + sw -4); + } + else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Left || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Right ) { + int mid = height()/2 + voffset[i]; + arr.setPoints( 3, + sw-4, mid - sw + 4, + 0, mid, + sw-4, mid + sw - 4); + } + else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Up || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Down) { + int mid = width()/2 + voffset[i]; + arr.setPoints( 3, + mid - sw + 4, sw-4, + mid, 0, + mid + sw - 4, sw-4 ); + } + else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Down || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Up ) { + int mid = width()/2 + voffset[i]; + arr.setPoints( 3, + mid - sw + 4, 1-yyy, + mid, sw-3-yyy, + mid + sw -4, 1-yyy); + } + list.append( arr ); + } + return list; +} + +void KDGanttSplitterHandle::paintEvent( QPaintEvent * ) +{ + QPixmap buffer( size() ); + QPainter p( &buffer ); + + //LR + // Draw the splitter rectangle + p.setBrush( colorGroup().background() ); + p.setPen( colorGroup().foreground() ); + //p.drawRect( rect() ); + buffer.fill( colorGroup().background() ); + //buffer.fill( backgroundColor() ); + // parentWidget()->style().drawPrimitive( QStyle::PE_Panel, &p, rect(), parentWidget()->colorGroup()); + + int sw = 8; // Hardcoded, given I didn't use styles anymore, I didn't like to use their size + + // arrow color + QColor col; + if ( _activeButton ) + col = colorGroup().background().dark( 250 ); + else + col = colorGroup().background().dark( 150 ); + //QColor col = backgroundColor().dark( 130 ); + p.setBrush( col ); + p.setPen( col ); + + QValueList<QPointArray> list = buttonRegions(); + int index = 1; + if ( mUseOffset ) + p.translate( 0, 1 ); + for ( QValueList<QPointArray>::Iterator it = list.begin(); it != list.end(); ++it ) { + if ( index == _activeButton ) { + + /* + if ( ! _collapsed ) { + p.save(); + // p.translate( parentWidget()->style().pixelMetric( QStyle::PM_ButtonShiftHorizontal ), + // parentWidget()->style().pixelMetric( QStyle::PM_ButtonShiftVertical ) ); + p.translate( -1, 0 ); + p.drawPolygon( *it, true ); + p.restore(); } else + */ + p.drawPolygon( *it, true ); + + } + else { + /* + if ( ! _collapsed ) { + p.save(); + p.translate( -1, 0 ); + p.drawPolygon( *it, true ); + p.restore(); + } else + */ + p.drawPolygon( *it, true ); + + } + index++; + } + + // Draw the lines between the arrows + if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Left || + s->minimizeDirection() == KDGanttMinimizeSplitter::Right ) { + int mid = height()/2; + p.drawLine ( 1, mid - sw, 1, mid + sw ); + p.drawLine ( 3, mid - sw, 3, mid + sw ); + } + else if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Up || + s->minimizeDirection() == KDGanttMinimizeSplitter::Down ) { + int mid = width()/2; + p.drawLine( mid -sw, 1, mid +sw, 1 ); + p.drawLine( mid -sw, 3, mid +sw, 3 ); + } + bitBlt( this, 0, 0, &buffer ); + +} +#endif + +class QSplitterLayoutStruct +{ +public: + KDGanttMinimizeSplitter::ResizeMode mode; + QCOORD sizer; + bool isSplitter; + QWidget *wid; +}; + +class QSplitterData +{ +public: + QSplitterData() : opaque( FALSE ), firstShow( TRUE ) {} + + QPtrList<QSplitterLayoutStruct> list; + bool opaque; + bool firstShow; +}; + +void kdganttGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos, + int space, int spacer ); +#endif // DOXYGEN_SKIP_INTERNAL + + +/*! + \class KDGanttMinimizeSplitter KDGanttMinimizeSplitter.h + \brief The KDGanttMinimizeSplitter class implements a splitter + widget with minimize buttons. + + This class (and its documentation) is largely a copy of Qt's + QSplitter; the copying was necessary because QSplitter is not + extensible at all. QSplitter and its documentation are licensed + according to the GPL and the Qt Professional License (if you hold + such a license) and are (C) Trolltech AS. + + A splitter lets the user control the size of child widgets by + dragging the boundary between the children. Any number of widgets + may be controlled. + + To show a QListBox, a QListView and a QTextEdit side by side: + + \code + KDGanttMinimizeSplitter *split = new KDGanttMinimizeSplitter( parent ); + QListBox *lb = new QListBox( split ); + QListView *lv = new QListView( split ); + QTextEdit *ed = new QTextEdit( split ); + \endcode + + In KDGanttMinimizeSplitter, the boundary can be either horizontal or + vertical. The default is horizontal (the children are side by side) + but you can use setOrientation( QSplitter::Vertical ) to set it to + vertical. + + Use setResizeMode() to specify + that a widget should keep its size when the splitter is resized. + + Although KDGanttMinimizeSplitter normally resizes the children only + at the end of a resize operation, if you call setOpaqueResize( TRUE + ) the widgets are resized as often as possible. + + The initial distribution of size between the widgets is determined + by the initial size of each widget. You can also use setSizes() to + set the sizes of all the widgets. The function sizes() returns the + sizes set by the user. + + If you hide() a child, its space will be distributed among the other + children. It will be reinstated when you show() it again. It is also + possible to reorder the widgets within the splitter using + moveToFirst() and moveToLast(). +*/ + + + +static QSize minSize( const QWidget* /*w*/ ) +{ + return QSize(0,0); +} + +// This is the original version of minSize +static QSize minSizeHint( const QWidget* w ) +{ + QSize min = w->minimumSize(); + QSize s; + if ( min.height() <= 0 || min.width() <= 0 ) + s = w->minimumSizeHint(); + if ( min.height() > 0 ) + s.setHeight( min.height() ); + if ( min.width() > 0 ) + s.setWidth( min.width() ); + return s.expandedTo(QSize(0,0)); +} + + + +/*! + Constructs a horizontal splitter with the \a parent and \a + name arguments being passed on to the QFrame constructor. +*/ +KDGanttMinimizeSplitter::KDGanttMinimizeSplitter( QWidget *parent, const char *name ) + :QFrame(parent,name,WPaintUnclipped) +{ + mFirstHandle = 0; +#if QT_VERSION >= 232 + orient = Horizontal; + init(); +#endif +} + +/*! + Constructs a splitter with orientation \a o with the \a parent + and \a name arguments being passed on to the QFrame constructor. +*/ +KDGanttMinimizeSplitter::KDGanttMinimizeSplitter( Orientation o, QWidget *parent, const char *name ) + :QFrame(parent,name,WPaintUnclipped) +{ + mFirstHandle = 0; +#if QT_VERSION >= 232 + orient = o; + init(); +#endif +} + +/*! + Destroys the splitter and any children. +*/ +KDGanttMinimizeSplitter::~KDGanttMinimizeSplitter() +{ +#if QT_VERSION >= 232 + data->list.setAutoDelete( TRUE ); + delete data; +#endif +} + + +#if QT_VERSION >= 232 +void KDGanttMinimizeSplitter::init() +{ + data = new QSplitterData; + if ( orient == Horizontal ) + setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum) ); + else + setSizePolicy( QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Expanding) ); +} +#endif + + + +/*! + \brief the orientation of the splitter + + By default the orientation is horizontal (the widgets are side by side). + The possible orientations are Qt:Vertical and Qt::Horizontal (the default). +*/ +void KDGanttMinimizeSplitter::setOrientation( Orientation o ) +{ +#if QT_VERSION >= 232 + if ( orient == o ) + return; + orient = o; + + if ( orient == Horizontal ) + setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + else + setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) ); + + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->isSplitter ) + ((KDGanttSplitterHandle*)s->wid)->setOrientation( o ); + s = data->list.next(); // ### next at end of loop, no iterator + } + recalc( isVisible() ); +#endif +} + + +#if QT_VERSION >= 232 +/*! + \reimp +*/ +void KDGanttMinimizeSplitter::resizeEvent( QResizeEvent * ) +{ + doResize(); +} + + +/* + Inserts the widget \a w at the end (or at the beginning if \a first + is TRUE) of the splitter's list of widgets. + + It is the responsibility of the caller of this function to make sure + that \a w is not already in the splitter and to call recalcId if + needed. (If \a first is TRUE, then recalcId is very probably + needed.) +*/ +QSplitterLayoutStruct *KDGanttMinimizeSplitter::addWidget( QWidget *w, bool first ) +{ + QSplitterLayoutStruct *s; + KDGanttSplitterHandle *newHandle = 0; + if ( data->list.count() > 0 ) { + s = new QSplitterLayoutStruct; + s->mode = KeepSize; + QString tmp = "qt_splithandle_"; + tmp += w->name(); + newHandle = new KDGanttSplitterHandle( orientation(), this, tmp.latin1() ); + if ( ! mFirstHandle ) + mFirstHandle = newHandle; + s->wid = newHandle; + newHandle->setId(data->list.count()); + s->isSplitter = TRUE; + s->sizer = pick( newHandle->sizeHint() ); + if ( first ) + data->list.insert( 0, s ); + else + data->list.append( s ); + } + s = new QSplitterLayoutStruct; + s->mode = Stretch; + s->wid = w; + if ( !testWState( WState_Resized ) && w->sizeHint().isValid() ) + s->sizer = pick( w->sizeHint() ); + else + s->sizer = pick( w->size() ); + s->isSplitter = FALSE; + if ( first ) + data->list.insert( 0, s ); + else + data->list.append( s ); + if ( newHandle && isVisible() ) + newHandle->show(); //will trigger sending of post events + return s; +} + + +/*! + Tells the splitter that a child widget has been inserted or removed. + The event is passed in \a c. +*/ +void KDGanttMinimizeSplitter::childEvent( QChildEvent *c ) +{ + if ( c->type() == QEvent::ChildInserted ) { + if ( !c->child()->isWidgetType() ) + return; + + if ( ((QWidget*)c->child())->testWFlags( WType_TopLevel ) ) + return; + + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == c->child() ) + return; + s = data->list.next(); + } + addWidget( (QWidget*)c->child() ); + recalc( isVisible() ); + + } else if ( c->type() == QEvent::ChildRemoved ) { + QSplitterLayoutStruct *p = 0; + if ( data->list.count() > 1 ) + p = data->list.at(1); //remove handle _after_ first widget. + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == c->child() ) { + data->list.removeRef( s ); + delete s; + if ( p && p->isSplitter ) { + data->list.removeRef( p ); + delete p->wid; //will call childEvent + delete p; + } + recalcId(); + doResize(); + return; + } + p = s; + s = data->list.next(); + } + } +} + + +/*! + Shows a rubber band at position \a p. If \a p is negative, the + rubber band is removed. +*/ +void KDGanttMinimizeSplitter::setRubberband( int p ) +{ + QPainter paint( this ); + paint.setPen( gray ); + paint.setBrush( gray ); + paint.setRasterOp( XorROP ); + QRect r = contentsRect(); + const int rBord = 3; //Themable???? +#if QT_VERSION >= 300 + int sw = style().pixelMetric(QStyle::PM_SplitterWidth, this); +#else + int sw = style().splitterWidth(); +#endif + if ( orient == Horizontal ) { + if ( opaqueOldPos >= 0 ) + paint.drawRect( opaqueOldPos + sw/2 - rBord , r.y(), + 2*rBord, r.height() ); + if ( p >= 0 ) + paint.drawRect( p + sw/2 - rBord, r.y(), 2*rBord, r.height() ); + } else { + if ( opaqueOldPos >= 0 ) + paint.drawRect( r.x(), opaqueOldPos + sw/2 - rBord, + r.width(), 2*rBord ); + if ( p >= 0 ) + paint.drawRect( r.x(), p + sw/2 - rBord, r.width(), 2*rBord ); + } + opaqueOldPos = p; +} + + +/*! \reimp */ +bool KDGanttMinimizeSplitter::event( QEvent *e ) +{ + if ( e->type() == QEvent::LayoutHint || ( e->type() == QEvent::Show && data->firstShow ) ) { + recalc( isVisible() ); + if ( e->type() == QEvent::Show ) + data->firstShow = FALSE; + } + return QWidget::event( e ); +} + + +/*! + \obsolete + + Draws the splitter handle in the rectangle described by \a x, \a y, + \a w, \a h using painter \a p. + \sa QStyle::drawPrimitive() +*/ +void KDGanttMinimizeSplitter::drawSplitter( QPainter *p, + QCOORD x, QCOORD y, QCOORD w, QCOORD h ) +{ +#if 0 + // LR + style().drawPrimitive(QStyle::PE_Splitter, p, QRect(x, y, w, h), colorGroup(), + (orientation() == Qt::Horizontal ? + QStyle::Style_Horizontal : 0)); +#endif +} + + +/*! + Returns the id of the splitter to the right of or below the widget \a w, + or 0 if there is no such splitter + (i.e. it is either not in this KDGanttMinimizeSplitter or it is at the end). +*/ +int KDGanttMinimizeSplitter::idAfter( QWidget* w ) const +{ + QSplitterLayoutStruct *s = data->list.first(); + bool seen_w = FALSE; + while ( s ) { + if ( s->isSplitter && seen_w ) + return data->list.at(); + if ( !s->isSplitter && s->wid == w ) + seen_w = TRUE; + s = data->list.next(); + } + return 0; +} + + +/*! + Moves the left/top edge of the splitter handle with id \a id as + close as possible to position \a p, which is the distance from the + left (or top) edge of the widget. + + For Arabic and Hebrew the layout is reversed, and using this + function to set the position of the splitter might lead to + unexpected results, since in Arabic and Hebrew the position of + splitter one is to the left of the position of splitter zero. + + \sa idAfter() +*/ +void KDGanttMinimizeSplitter::moveSplitter( QCOORD p, int id ) +{ + p = adjustPos( p, id ); + QSplitterLayoutStruct *s = data->list.at(id); + int oldP = orient == Horizontal ? s->wid->x() : s->wid->y(); + bool upLeft; + if ( false && orient == Horizontal ) { + p += s->wid->width(); + upLeft = p > oldP; + } else + upLeft = p < oldP; + + moveAfter( p, id, upLeft ); + moveBefore( p-1, id-1, upLeft ); + + storeSizes(); +} + + +void KDGanttMinimizeSplitter::setG( QWidget *w, int p, int s, bool isSplitter ) +{ + if ( orient == Horizontal ) { + if ( false && orient == Horizontal && !isSplitter ) + p = contentsRect().width() - p - s; + w->setGeometry( p, contentsRect().y(), s, contentsRect().height() ); + } else + w->setGeometry( contentsRect().x(), p, contentsRect().width(), s ); +} + + +/* + Places the right/bottom edge of the widget at \a id at position \a pos. + + \sa idAfter() +*/ +void KDGanttMinimizeSplitter::moveBefore( int pos, int id, bool upLeft ) +{ + if( id < 0 ) + return; + QSplitterLayoutStruct *s = data->list.at(id); + if ( !s ) + return; + QWidget *w = s->wid; + if ( w->isHidden() ) { + moveBefore( pos, id-1, upLeft ); + } else if ( s->isSplitter ) { + int pos1, pos2; + int dd = s->sizer; + if( false && orient == Horizontal ) { + pos1 = pos; + pos2 = pos + dd; + } else { + pos2 = pos - dd; + pos1 = pos2 + 1; + } + if ( upLeft ) { + setG( w, pos1, dd, TRUE ); + moveBefore( pos2, id-1, upLeft ); + } else { + moveBefore( pos2, id-1, upLeft ); + setG( w, pos1, dd, TRUE ); + } + } else { + int dd, newLeft, nextPos; + if( false && orient == Horizontal ) { + dd = w->geometry().right() - pos; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + newLeft = pos+1; + nextPos = newLeft + dd; + } else { + dd = pos - pick( w->pos() ) + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + newLeft = pos-dd+1; + nextPos = newLeft - 1; + } + setG( w, newLeft, dd, TRUE ); + moveBefore( nextPos, id-1, upLeft ); + } +} + + +/* + Places the left/top edge of the widget at \a id at position \a pos. + + \sa idAfter() +*/ +void KDGanttMinimizeSplitter::moveAfter( int pos, int id, bool upLeft ) +{ + QSplitterLayoutStruct *s = id < int(data->list.count()) ? + data->list.at(id) : 0; + if ( !s ) + return; + QWidget *w = s->wid; + if ( w->isHidden() ) { + moveAfter( pos, id+1, upLeft ); + } else if ( pick( w->pos() ) == pos ) { + //No need to do anything if it's already there. + return; + } else if ( s->isSplitter ) { + int dd = s->sizer; + int pos1, pos2; + if( false && orient == Horizontal ) { + pos2 = pos - dd; + pos1 = pos2 + 1; + } else { + pos1 = pos; + pos2 = pos + dd; + } + if ( upLeft ) { + setG( w, pos1, dd, TRUE ); + moveAfter( pos2, id+1, upLeft ); + } else { + moveAfter( pos2, id+1, upLeft ); + setG( w, pos1, dd, TRUE ); + } + } else { + int left = pick( w->pos() ); + int right, dd,/* newRight,*/ newLeft, nextPos; + if ( false && orient == Horizontal ) { + dd = pos - left + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + newLeft = pos-dd+1; + nextPos = newLeft - 1; + } else { + right = pick( w->geometry().bottomRight() ); + dd = right - pos + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + /*newRight = pos+dd-1;*/ + newLeft = pos; + nextPos = newLeft + dd; + } + setG( w, newLeft, dd, TRUE ); + /*if( right != newRight )*/ + moveAfter( nextPos, id+1, upLeft ); + } +} + + +void KDGanttMinimizeSplitter::expandPos( int id, int* min, int* max ) +{ + QSplitterLayoutStruct *s = data->list.at(id-1); + QWidget* w = s->wid; + *min = pick( w->mapToParent( QPoint(0,0) ) ); + + if ( (uint) id == data->list.count() ) { + pick( size() ); + } + else { + QSplitterLayoutStruct *s = data->list.at(id+1); + QWidget* w = s->wid; + *max = pick( w->mapToParent( QPoint( w->width(), w->height() ) ) ) -8; + } +} + + +/*! + Returns the valid range of the splitter with id \a id in \a *min and \a *max. + + \sa idAfter() +*/ + +void KDGanttMinimizeSplitter::getRange( int id, int *min, int *max ) +{ + int minB = 0; //before + int maxB = 0; + int minA = 0; + int maxA = 0; //after + int n = data->list.count(); + if ( id < 0 || id >= n ) + return; + int i; + for ( i = 0; i < id; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + //ignore + } else if ( s->isSplitter ) { + minB += s->sizer; + maxB += s->sizer; + } else { + minB += pick( minSize(s->wid) ); + maxB += pick( s->wid->maximumSize() ); + } + } + for ( i = id; i < n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + //ignore + } else if ( s->isSplitter ) { + minA += s->sizer; + maxA += s->sizer; + } else { + minA += pick( minSize(s->wid) ); + maxA += pick( s->wid->maximumSize() ); + } + } + QRect r = contentsRect(); + if ( orient == Horizontal && false ) { +#if QT_VERSION >= 300 + int splitterWidth = style().pixelMetric(QStyle::PM_SplitterWidth, this); +#else + int splitterWidth = style().splitterWidth(); +#endif + + if ( min ) + *min = pick(r.topRight()) - QMIN( maxB, pick(r.size())-minA ) - splitterWidth; + if ( max ) + *max = pick(r.topRight()) - QMAX( minB, pick(r.size())-maxA ) - splitterWidth; + } else { + if ( min ) + *min = pick(r.topLeft()) + QMAX( minB, pick(r.size())-maxA ); + if ( max ) + *max = pick(r.topLeft()) + QMIN( maxB, pick(r.size())-minA ); + } +} + + +/*! + Returns the closest legal position to \a p of the splitter with id \a id. + + \sa idAfter() +*/ + +int KDGanttMinimizeSplitter::adjustPos( int p, int id ) +{ + int min = 0; + int max = 0; + getRange( id, &min, &max ); + p = QMAX( min, QMIN( p, max ) ); + + return p; +} + + +void KDGanttMinimizeSplitter::doResize() +{ + QRect r = contentsRect(); + int i; + int n = data->list.count(); + QMemArray<QLayoutStruct> a( n ); + for ( i = 0; i< n; i++ ) { + a[i].init(); + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + a[i].stretch = 0; + a[i].sizeHint = a[i].minimumSize = 0; + a[i].maximumSize = 0; + } else if ( s->isSplitter ) { + a[i].stretch = 0; + a[i].sizeHint = a[i].minimumSize = a[i].maximumSize = s->sizer; + a[i].empty = FALSE; + } else if ( s->mode == KeepSize ) { + a[i].stretch = 0; + a[i].minimumSize = pick( minSize(s->wid) ); + a[i].sizeHint = s->sizer; + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].empty = FALSE; + } else if ( s->mode == FollowSizeHint ) { + a[i].stretch = 0; + a[i].minimumSize = a[i].sizeHint = pick( s->wid->sizeHint() ); + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].empty = FALSE; + } else { //proportional + a[i].stretch = s->sizer; + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].sizeHint = a[i].minimumSize = pick( minSize(s->wid) ); + a[i].empty = FALSE; + } + } + + kdganttGeomCalc( a, 0, n, pick( r.topLeft() ), pick( r.size() ), 0 ); + + for ( i = 0; i< n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + setG( s->wid, a[i].pos, a[i].size ); + } + +} + + +void KDGanttMinimizeSplitter::recalc( bool update ) +{ + int fi = 2*frameWidth(); + int maxl = fi; + int minl = fi; + int maxt = QWIDGETSIZE_MAX; + int mint = fi; + int n = data->list.count(); + bool first = TRUE; + /* + The splitter before a hidden widget is always hidden. + The splitter before the first visible widget is hidden. + The splitter before any other visible widget is visible. + */ + for ( int i = 0; i< n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( !s->isSplitter ) { + QSplitterLayoutStruct *p = (i > 0) ? p = data->list.at( i-1 ) : 0; + if ( p && p->isSplitter ) + if ( first || s->wid->isHidden() ) + p->wid->hide(); //may trigger new recalc + else + p->wid->show(); //may trigger new recalc + if ( !s->wid->isHidden() ) + first = FALSE; + } + } + + bool empty=TRUE; + for ( int j = 0; j< n; j++ ) { + QSplitterLayoutStruct *s = data->list.at(j); + if ( !s->wid->isHidden() ) { + empty = FALSE; + if ( s->isSplitter ) { + minl += s->sizer; + maxl += s->sizer; + } else { + QSize minS = minSize(s->wid); + minl += pick( minS ); + maxl += pick( s->wid->maximumSize() ); + mint = QMAX( mint, trans( minS )); + int tm = trans( s->wid->maximumSize() ); + if ( tm > 0 ) + maxt = QMIN( maxt, tm ); + } + } + } + if ( empty ) { + if ( parentWidget() != 0 && parentWidget()->inherits("KDGanttMinimizeSplitter") ) { + // nested splitters; be nice + maxl = maxt = 0; + } else { + // KDGanttMinimizeSplitter with no children yet + maxl = QWIDGETSIZE_MAX; + } + } else { + maxl = QMIN( maxl, QWIDGETSIZE_MAX ); + } + if ( maxt < mint ) + maxt = mint; + + if ( orient == Horizontal ) { + setMaximumSize( maxl, maxt ); + setMinimumSize( minl, mint ); + } else { + setMaximumSize( maxt, maxl ); + setMinimumSize( mint, minl ); + } + if ( update ) + doResize(); +} + +/*! + Sets resize mode of \a w to \a mode. + + \sa ResizeMode +*/ + +void KDGanttMinimizeSplitter::setResizeMode( QWidget *w, ResizeMode mode ) +{ + processChildEvents(); + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + s->mode = mode; + return; + } + s = data->list.next(); + } + s = addWidget( w, TRUE ); + s->mode = mode; +} + + +/*! + Returns TRUE if opaque resize is on; otherwise returns FALSE. + + \sa setOpaqueResize() +*/ + +bool KDGanttMinimizeSplitter::opaqueResize() const +{ + return data->opaque; +} + + +/*! + If \a on is TRUE then opaque resizing is turned on; otherwise + opaque resizing is turned off. + Opaque resizing is initially turned off. + + \sa opaqueResize() +*/ + +void KDGanttMinimizeSplitter::setOpaqueResize( bool on ) +{ + data->opaque = on; +} + + +/*! + Moves widget \a w to the leftmost/top position. +*/ + +void KDGanttMinimizeSplitter::moveToFirst( QWidget *w ) +{ + processChildEvents(); + bool found = FALSE; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + found = TRUE; + QSplitterLayoutStruct *p = data->list.prev(); + if ( p ) { // not already at first place + data->list.take(); //take p + data->list.take(); // take s + data->list.insert( 0, p ); + data->list.insert( 0, s ); + } + break; + } + s = data->list.next(); + } + if ( !found ) + addWidget( w, TRUE ); + recalcId(); +} + + +/*! + Moves widget \a w to the rightmost/bottom position. +*/ + +void KDGanttMinimizeSplitter::moveToLast( QWidget *w ) +{ + processChildEvents(); + bool found = FALSE; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + found = TRUE; + data->list.take(); // take s + QSplitterLayoutStruct *p = data->list.current(); + if ( p ) { // the splitter handle after s + data->list.take(); //take p + data->list.append( p ); + } + data->list.append( s ); + break; + } + s = data->list.next(); + } + if ( !found ) + addWidget( w); + recalcId(); +} + + +void KDGanttMinimizeSplitter::recalcId() +{ + int n = data->list.count(); + for ( int i = 0; i < n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->isSplitter ) + ((KDGanttSplitterHandle*)s->wid)->setId(i); + } +} + + +/*!\reimp +*/ +QSize KDGanttMinimizeSplitter::sizeHint() const +{ + constPolish(); + int l = 0; + int t = 0; + if ( children() ) { + const QObjectList * c = children(); + QObjectListIt it( *c ); + QObject * o; + + while( (o=it.current()) != 0 ) { + ++it; + if ( o->isWidgetType() && + !((QWidget*)o)->isHidden() ) { + QSize s = ((QWidget*)o)->sizeHint(); + if ( s.isValid() ) { + l += pick( s ); + t = QMAX( t, trans( s ) ); + } + } + } + } + return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l ); +} + + +/*! +\reimp +*/ + +QSize KDGanttMinimizeSplitter::minimumSizeHint() const +{ + constPolish(); + int l = 0; + int t = 0; + if ( children() ) { + const QObjectList * c = children(); + QObjectListIt it( *c ); + QObject * o; + + while( (o=it.current()) != 0 ) { + ++it; + if ( o->isWidgetType() && + !((QWidget*)o)->isHidden() ) { + QSize s = minSizeHint((QWidget*)o); + if ( s.isValid() ) { + l += pick( s ); + t = QMAX( t, trans( s ) ); + } + } + } + } + return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l ); +} + + +/* + Calculates stretch parameters from current sizes +*/ + +void KDGanttMinimizeSplitter::storeSizes() +{ + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( !s->isSplitter ) + s->sizer = pick( s->wid->size() ); + s = data->list.next(); + } +} + + +#if 0 // ### remove this code ASAP + +/*! + Hides \a w if \a hide is TRUE and updates the splitter. + + \warning Due to a limitation in the current implementation, + calling QWidget::hide() will not work. +*/ + +void KDGanttMinimizeSplitter::setHidden( QWidget *w, bool hide ) +{ + if ( w == w1 ) { + w1show = !hide; + } else if ( w == w2 ) { + w2show = !hide; + } else { +#ifdef QT_CHECK_RANGE + qWarning( "KDGanttMinimizeSplitter::setHidden(), unknown widget" ); +#endif + return; + } + if ( hide ) + w->hide(); + else + w->show(); + recalc( TRUE ); +} + + +/*! + Returns the hidden status of \a w +*/ + +bool KDGanttMinimizeSplitter::isHidden( QWidget *w ) const +{ + if ( w == w1 ) + return !w1show; + else if ( w == w2 ) + return !w2show; +#ifdef QT_CHECK_RANGE + else + qWarning( "KDGanttMinimizeSplitter::isHidden(), unknown widget" ); +#endif + return FALSE; +} +#endif + + +/*! + Returns a list of the size parameters of all the widgets in this + splitter. + + Giving the values to another splitter's setSizes() function will + produce a splitter with the same layout as this one. + + Note that if you want to iterate over the list, you should + iterate over a copy, e.g. + \code + QValueList<int> list = mySplitter.sizes(); + QValueList<int>::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + \sa setSizes() +*/ + +QValueList<int> KDGanttMinimizeSplitter::sizes() const +{ + if ( !testWState(WState_Polished) ) { + QWidget* that = (QWidget*) this; + that->polish(); + } + QValueList<int> list; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( !s->isSplitter ) + list.append( s->sizer ); + s = data->list.next(); + } + return list; +} + + + +/*! + Sets the size parameters to the values given in \a list. + If the splitter is horizontal, the values set the sizes from + left to right. If it is vertical, the sizes are applied from + top to bottom. + Extra values in \a list are ignored. + + If \a list contains too few values, the result is undefined + but the program will still be well-behaved. + + \sa sizes() +*/ + +void KDGanttMinimizeSplitter::setSizes( QValueList<int> list ) +{ + processChildEvents(); + QValueList<int>::Iterator it = list.begin(); + QSplitterLayoutStruct *s = data->list.first(); + while ( s && it != list.end() ) { + if ( !s->isSplitter ) { + s->sizer = *it; + ++it; + } + s = data->list.next(); + } + doResize(); +} + + +/*! + Gets all posted child events, ensuring that the internal state of + the splitter is consistent. +*/ + +void KDGanttMinimizeSplitter::processChildEvents() +{ + QApplication::sendPostedEvents( this, QEvent::ChildInserted ); +} + + +/*! + \reimp +*/ + +void KDGanttMinimizeSplitter::styleChange( QStyle& old ) +{ + +#if QT_VERSION >= 300 + int sw = style().pixelMetric(QStyle::PM_SplitterWidth, this); +#else + int sw = style().splitterWidth(); +#endif + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->isSplitter ) + s->sizer = sw; + s = data->list.next(); + } + doResize(); + QFrame::styleChange( old ); +} + +#endif + +/*! + Specifies the direction of the minimize buttons. + If the orientation of the splitter is horizontal then with + KDGanttMinimizeSplitter::Left or KDGanttMinimizeSplitter::Right should be used, + otherwise either KDGanttMinimizeSplitter::Up or KDGanttMinimizeSplitter::Down + should be used. +*/ +void KDGanttMinimizeSplitter::setMinimizeDirection( Direction direction ) +{ + _direction = direction; +} + +/*! + Returns the direction of the minimize buttons. +*/ +KDGanttMinimizeSplitter::Direction KDGanttMinimizeSplitter::minimizeDirection() const +{ + return _direction; +} + +/* + This is a copy of qGeomCalc() in qlayoutengine.cpp which + unfortunately isn't exported. +*/ +static inline int toFixed( int i ) { return i * 256; } +static inline int fRound( int i ) { + return ( i % 256 < 128 ) ? i / 256 : 1 + i / 256; +} +void kdganttGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos, + int space, int spacer ) +{ + typedef int fixed; + int cHint = 0; + int cMin = 0; + int cMax = 0; + int sumStretch = 0; + int spacerCount = 0; + + bool wannaGrow = FALSE; // anyone who really wants to grow? + // bool canShrink = FALSE; // anyone who could be persuaded to shrink? + + int i; + for ( i = start; i < start + count; i++ ) { + chain[i].done = FALSE; + cHint += chain[i].sizeHint; + cMin += chain[i].minimumSize; + cMax += chain[i].maximumSize; + sumStretch += chain[i].stretch; + if ( !chain[i].empty ) + spacerCount++; + wannaGrow = wannaGrow || chain[i].expansive; + } + + int extraspace = 0; + if ( spacerCount ) + spacerCount--; // only spacers between things + if ( space < cMin + spacerCount * spacer ) { + // qDebug("not enough space"); + for ( i = start; i < start+count; i++ ) { + chain[i].size = chain[i].minimumSize; + chain[i].done = TRUE; + } + } else if ( space < cHint + spacerCount*spacer ) { + // Less space than sizeHint, but more than minimum. + // Currently take space equally from each, like in Qt 2.x. + // Commented-out lines will give more space to stretchier items. + int n = count; + int space_left = space - spacerCount*spacer; + int overdraft = cHint - space_left; + //first give to the fixed ones: + for ( i = start; i < start+count; i++ ) { + if ( !chain[i].done && chain[i].minimumSize >= chain[i].sizeHint) { + chain[i].size = chain[i].sizeHint; + chain[i].done = TRUE; + space_left -= chain[i].sizeHint; + // sumStretch -= chain[i].stretch; + n--; + } + } + bool finished = n == 0; + while ( !finished ) { + finished = TRUE; + fixed fp_over = toFixed( overdraft ); + fixed fp_w = 0; + + for ( i = start; i < start+count; i++ ) { + if ( chain[i].done ) + continue; + // if ( sumStretch <= 0 ) + fp_w += fp_over / n; + // else + // fp_w += (fp_over * chain[i].stretch) / sumStretch; + int w = fRound( fp_w ); + chain[i].size = chain[i].sizeHint - w; + fp_w -= toFixed( w ); //give the difference to the next + if ( chain[i].size < chain[i].minimumSize ) { + chain[i].done = TRUE; + chain[i].size = chain[i].minimumSize; + finished = FALSE; + overdraft -= chain[i].sizeHint - chain[i].minimumSize; + // sumStretch -= chain[i].stretch; + n--; + break; + } + } + } + } else { //extra space + int n = count; + int space_left = space - spacerCount*spacer; + // first give to the fixed ones, and handle non-expansiveness + for ( i = start; i < start + count; i++ ) { + if ( !chain[i].done && (chain[i].maximumSize <= chain[i].sizeHint + || wannaGrow && !chain[i].expansive) ) { + chain[i].size = chain[i].sizeHint; + chain[i].done = TRUE; + space_left -= chain[i].sizeHint; + sumStretch -= chain[i].stretch; + n--; + } + } + extraspace = space_left; + /* + Do a trial distribution and calculate how much it is off. + If there are more deficit pixels than surplus pixels, give + the minimum size items what they need, and repeat. + Otherwise give to the maximum size items, and repeat. + + I have a wonderful mathematical proof for the correctness + of this principle, but unfortunately this comment is too + small to contain it. + */ + int surplus, deficit; + do { + surplus = deficit = 0; + fixed fp_space = toFixed( space_left ); + fixed fp_w = 0; + for ( i = start; i < start+count; i++ ) { + if ( chain[i].done ) + continue; + extraspace = 0; + if ( sumStretch <= 0 ) + fp_w += fp_space / n; + else + fp_w += (fp_space * chain[i].stretch) / sumStretch; + int w = fRound( fp_w ); + chain[i].size = w; + fp_w -= toFixed( w ); // give the difference to the next + if ( w < chain[i].sizeHint ) { + deficit += chain[i].sizeHint - w; + } else if ( w > chain[i].maximumSize ) { + surplus += w - chain[i].maximumSize; + } + } + if ( deficit > 0 && surplus <= deficit ) { + // give to the ones that have too little + for ( i = start; i < start+count; i++ ) { + if ( !chain[i].done && + chain[i].size < chain[i].sizeHint ) { + chain[i].size = chain[i].sizeHint; + chain[i].done = TRUE; + space_left -= chain[i].sizeHint; + sumStretch -= chain[i].stretch; + n--; + } + } + } + if ( surplus > 0 && surplus >= deficit ) { + // take from the ones that have too much + for ( i = start; i < start+count; i++ ) { + if ( !chain[i].done && + chain[i].size > chain[i].maximumSize ) { + chain[i].size = chain[i].maximumSize; + chain[i].done = TRUE; + space_left -= chain[i].maximumSize; + sumStretch -= chain[i].stretch; + n--; + } + } + } + } while ( n > 0 && surplus != deficit ); + if ( n == 0 ) + extraspace = space_left; + } + + // as a last resort, we distribute the unwanted space equally + // among the spacers (counting the start and end of the chain). + + //### should do a sub-pixel allocation of extra space + int extra = extraspace / ( spacerCount + 2 ); + int p = pos + extra; + for ( i = start; i < start+count; i++ ) { + chain[i].pos = p; + p = p + chain[i].size; + if ( !chain[i].empty ) + p += spacer+extra; + } +} + +#endif + +/*! + \enum KDGanttMinimizeSplitter::Direction + + The values of this enumeration describe into which direction the + splitter will collapse its child widgets. By extension, it also + specifies the orientation of the splitter; collapsing to the left or + to the right results in a horizontal splitter, collapsing to the top + or bottom in a vertical splitter. +*/ + +/*! + \fn Orientation KDGanttMinimizeSplitter::orientation() const + + Returns the orientation of the splitter. +*/ + +/*! \enum KDGanttMinimizeSplitter::ResizeMode + + This enum type describes how KDGanttMinimizeSplitter will resize each of its child widgets. The currently defined values are: + + Stretch: the widget will be resized when the splitter + itself is resized. + + KeepSize: KDGanttMinimizeSplitter will try to keep this widget's size + unchanged. + + FollowSizeHint: KDGanttMinimizeSplitter will resize the widget when the + widget's size hint changes. +*/ + diff --git a/microkde/KDGanttMinimizeSplitter.h b/microkde/KDGanttMinimizeSplitter.h new file mode 100644 index 0000000..75e0443 --- a/dev/null +++ b/microkde/KDGanttMinimizeSplitter.h @@ -0,0 +1,186 @@ +/* -*- Mode: C++ -*- + $Id$ +*/ + +/**************************************************************************** + ** Copyright (C) 2001-2004 Klarälvdalens Datakonsult AB. All rights reserved. + ** + ** This file is part of the KDGantt library. + ** + ** This file may be distributed and/or modified under the terms of the + ** GNU General Public License version 2 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. + ** + ** Licensees holding valid commercial KDGantt licenses may use this file in + ** accordance with the KDGantt Commercial License Agreement provided with + ** the Software. + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ** See http://www.klaralvdalens-datakonsult.se/Public/products/ for + ** information about KDGantt Commercial License Agreements. + ** + ** Contact info@klaralvdalens-datakonsult.se if any conditions of this + ** licensing are not clear to you. + ** + ** As a special exception, permission is given to link this program + ** with any edition of Qt, and distribute the resulting executable, + ** without including the source code for Qt in the source distribution. + ** + **********************************************************************/ + +#ifndef KDGANTTMINIMIZESPLITTER_H +#define KDGANTTMINIMIZESPLITTER_H + +#ifndef QT_H +#include "qframe.h" +#include "qvaluelist.h" +#endif // QT_H + +#ifndef QT_NO_SPLITTER___ +class QSplitterData; +class QSplitterLayoutStruct; +class KDGanttSplitterHandle; +class KDGanttMinimizeSplitter : public QFrame +{ + Q_OBJECT + // Q_ENUMS( Direction ) + // Q_PROPERTY( Orientation orientation READ orientation WRITE setOrientation ) + // Q_PROPERTY( Direction minimizeDirection READ minimizeDirection WRITE setMinimizeDirection ) + +public: + enum ResizeMode { Stretch, KeepSize, FollowSizeHint }; + enum Direction { Left, Right, Up, Down }; + + KDGanttMinimizeSplitter( QWidget* parent=0, const char* name=0 ); + KDGanttMinimizeSplitter( Orientation, QWidget* parent=0, const char* name=0 ); + ~KDGanttMinimizeSplitter(); + + virtual void setOrientation( Orientation ); + Orientation orientation() const { return orient; } + + void setMinimizeDirection( Direction ); + Direction minimizeDirection() const; + +#if QT_VERSION >= 232 + virtual void setResizeMode( QWidget *w, ResizeMode ); + virtual void setOpaqueResize( bool = TRUE ); + bool opaqueResize() const; + + void moveToFirst( QWidget * ); + void moveToLast( QWidget * ); + + void refresh() { recalc( TRUE ); } + QSize sizeHint() const; + QSize minimumSizeHint() const; + + QValueList<int> sizes() const; + void setSizes( QValueList<int> ); + KDGanttSplitterHandle* firstHandle(){ return mFirstHandle;} + void expandPos( int id, int* min, int* max ); +protected: + void childEvent( QChildEvent * ); + + bool event( QEvent * ); + void resizeEvent( QResizeEvent * ); + + int idAfter( QWidget* ) const; + + void moveSplitter( QCOORD pos, int id ); + virtual void drawSplitter( QPainter*, QCOORD x, QCOORD y, + QCOORD w, QCOORD h ); + void styleChange( QStyle& ); + int adjustPos( int , int ); + virtual void setRubberband( int ); + void getRange( int id, int*, int* ); + +private: + void init(); + void recalc( bool update = FALSE ); + void doResize(); + void storeSizes(); + void processChildEvents(); + QSplitterLayoutStruct *addWidget( QWidget*, bool first = FALSE ); + void recalcId(); + void moveBefore( int pos, int id, bool upLeft ); + void moveAfter( int pos, int id, bool upLeft ); + void setG( QWidget *w, int p, int s, bool isSplitter = FALSE ); + + QCOORD pick( const QPoint &p ) const + { return orient == Horizontal ? p.x() : p.y(); } + QCOORD pick( const QSize &s ) const + { return orient == Horizontal ? s.width() : s.height(); } + + QCOORD trans( const QPoint &p ) const + { return orient == Vertical ? p.x() : p.y(); } + QCOORD trans( const QSize &s ) const + { return orient == Vertical ? s.width() : s.height(); } + KDGanttSplitterHandle* mFirstHandle; + QSplitterData *data; +#endif + +private: + Orientation orient; + Direction _direction; +#ifndef DOXYGEN_SKIP_INTERNAL + friend class KDGanttSplitterHandle; +#endif +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + KDGanttMinimizeSplitter( const KDGanttMinimizeSplitter & ); + KDGanttMinimizeSplitter& operator=( const KDGanttMinimizeSplitter & ); +#endif +}; + +#ifndef DOXYGEN_SKIP_INTERNAL +// This class was continued from a verbatim copy of the +// QSplitterHandle pertaining to the Qt Enterprise License and the +// GPL. It has only been renamed to KDGanttSplitterHandler in order to +// avoid a symbol clash on some platforms. +class KDGanttSplitterHandle : public QWidget +{ + Q_OBJECT +#if QT_VERSION >= 232 +public: + KDGanttSplitterHandle( Qt::Orientation o, + KDGanttMinimizeSplitter *parent, const char* name=0 ); + void setOrientation( Qt::Orientation o ); + Qt::Orientation orientation() const { return orient; } + + bool opaque() const { return s->opaqueResize(); } + + QSize sizeHint() const; + void toggle(); + + int id() const { return myId; } // data->list.at(id())->wid == this + void setId( int i ) { myId = i; } + +protected: + QValueList<QPointArray> buttonRegions(); + void paintEvent( QPaintEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + int onButton( const QPoint& p ); + void updateCursor( const QPoint& p ); + +private: + QSize mSizeHint; + bool mUseOffset; + Qt::Orientation orient; + bool opaq; + int myId; + + KDGanttMinimizeSplitter *s; + int _activeButton; + bool _collapsed; + int _origPos; +#endif +}; +#endif + +#endif // QT_NO_SPLITTER + +#endif // KDGANTTMINIMIZESPLITTER_H diff --git a/microkde/kapplication.cpp b/microkde/kapplication.cpp new file mode 100644 index 0000000..a1d00a8 --- a/dev/null +++ b/microkde/kapplication.cpp @@ -0,0 +1,26 @@ +#include <stdlib.h> + +#include "kapplication.h" + +int KApplication::random() +{ + return rand(); +} + +//US +QString KApplication::randomString(int length) +{ + if (length <=0 ) return QString::null; + + QString str; + while (length--) + { + int r=random() % 62; + r+=48; + if (r>57) r+=7; + if (r>90) r+=6; + str += char(r); + // so what if I work backwards? + } + return str; +} diff --git a/microkde/kapplication.h b/microkde/kapplication.h new file mode 100644 index 0000000..47e64e7 --- a/dev/null +++ b/microkde/kapplication.h @@ -0,0 +1,21 @@ +#ifndef MINIKDE_KAPPLICATION_H +#define MINIKDE_KAPPLICATION_H + +#include "qstring.h" + +class KApplication +{ + public: + static int random(); + +//US + /** + * Generates a random string. It operates in the range [A-Za-z0-9] + * @param length Generate a string of this length. + * @return the random string + */ + static QString randomString(int length); +}; + + +#endif diff --git a/microkde/kaudioplayer.h b/microkde/kaudioplayer.h new file mode 100644 index 0000000..ff196cf --- a/dev/null +++ b/microkde/kaudioplayer.h @@ -0,0 +1,10 @@ +#ifndef MICROKDE_KAUDIOPLAYER_H +#define MICROKDE_KAUDIOPLAYER_H + +class KAudioPlayer +{ + public: + static void play( const QString & ) {} +}; + +#endif diff --git a/microkde/kcalendarsystem.cpp b/microkde/kcalendarsystem.cpp new file mode 100644 index 0000000..530010d --- a/dev/null +++ b/microkde/kcalendarsystem.cpp @@ -0,0 +1,52 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// Gregorian calendar system implementation factory for creation of kde calendar +// systems. +// Also default gregorian and factory classes + +#include <kglobal.h> + +#include "kcalendarsystem.h" + +class KCalendarSystemPrivate +{ +public: + const KLocale * locale; +}; + +KCalendarSystem::KCalendarSystem(const KLocale * locale) + : d(new KCalendarSystemPrivate) +{ + d->locale = locale; +} + +KCalendarSystem::~KCalendarSystem() +{ + delete d; +} + +const KLocale * KCalendarSystem::locale() const +{ + if ( d->locale ) + return d->locale; + + return KGlobal::locale(); +} diff --git a/microkde/kcalendarsystem.h b/microkde/kcalendarsystem.h new file mode 100644 index 0000000..37af33e --- a/dev/null +++ b/microkde/kcalendarsystem.h @@ -0,0 +1,297 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002-2003 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCALENDARSYSTEM_H +#define KCALENDARSYSTEM_H + +#include <qdatetime.h> +#include <qstring.h> + +class KLocale; + +class KCalendarSystemPrivate; + +/** + * CalendarSystem abstract class, default derived kde gregorian class and + * factory class. Provides support for different calendar types for kde + * calendar widget and related stuff. + * + * Derived classes must be created through KCalendarFactory class + * + * @author Carlos Moro <cfmoro@correo.uniovi.es> + * @licence GNU-GPL v.2 + * @version $Id$ + * @since 3.2 + */ +class KCalendarSystem +{ +public: + /** + * Constructor of abstract calendar class. This will be called by the derived classes. + * + * @param locale It will use this locale for translations, 0 means global. + */ + KCalendarSystem(const KLocale * locale = 0); + + /** + * Descructor. + */ + virtual ~KCalendarSystem(); + + /** + * Gets specific calendar type year for a given gregorian date + * + * @param date gregorian date + * @return year + */ + virtual int year (const QDate & date) const = 0; + + /** + * Gets specific calendar type month for a given gregorian date + * + * @param date gregorian date + * @return month number + */ + virtual int month (const QDate & date) const = 0; + + /** + * Gets specific calendar type day number of month for a given date + * + * @param date gregorian date equivalent to the specific one + * @return day of the month + */ + virtual int day (const QDate & date) const = 0; + + /** + * Gets specific calendar type number of day of week number for a given + * date + * + * @param date gregorian date + * @return day of week + */ + virtual int dayOfWeek (const QDate & date) const = 0; + + /** + * Gets specific calendar type day number of year for a given date + * + * @param date gregorian date equivalent to the specific one + * @return day number + */ + virtual int dayOfYear (const QDate & date) const = 0; + + /** + * Changes the date's year, month and day. The range of the year, month + * and day depends on which calendar is being used. + * + * @param date Date to change + * @param y Year + * @param m Month number + * @param d Day of month + * @return TRUE if the date is valid; otherwise returns FALSE. + */ + virtual bool setYMD(QDate & date, int y, int m, int d) const = 0; + + /** + * Returns a QDate object containing a date nyears later. + * + * @param date The old date + * @param nyears The number of years to add + * @return The new date + */ + virtual QDate addYears(const QDate & date, int nyears) const = 0; + + /** + * Returns a QDate object containing a date nmonths later. + * + * @param date The old date + * @param nmonths The number of months to add + * @return The new date + */ + virtual QDate addMonths(const QDate & date, int nmonths) const = 0; + + /** + * Returns a QDate object containing a date ndays later. + * + * @param date The old date + * @param ndays The number of days to add + * @return The new date + */ + virtual QDate addDays(const QDate & date, int ndays) const = 0; + + /** + * Gets specific calendar type number of month for a given year + * + * @param date The date whose year to use + * @return The number of months in that year + */ + virtual int monthsInYear (const QDate & date) const = 0; + + /** + * Gets the number of days in date whose years specified. + * + * @param date Gregorian date equivalent to the specific one + * @return The number of days in year + */ + virtual int daysInYear (const QDate & date) const = 0; + + /** + * Gets specific calendar type number of days in month for a given date + * + * @param date gregorian date + * @return number of days for month in date + */ + virtual int daysInMonth (const QDate & date) const = 0; + + /** + * Gets the number of weeks in year + * + * @param year the year + * @return number of weeks in year + */ + virtual int weeksInYear(int year) const = 0; + + /** + * Gets specific calendar type week number for a given date + * + * @param date gregorian date + * @return week number + */ + virtual int weekNumber(const QDate& date, int * yearNum = 0) const = 0; + + /** + * Gets specific calendar type month name for a given month number + * If an invalid month is specified, QString::null is returned. + * + * @param month The month number + * @param shortName Specifies if the short month name should be used + * @return The name of the month + */ + virtual QString monthName (int month, bool shortName = false) const = 0; + + /** + * Gets specific calendar type month name for a given gregorian date + * + * @param date Gregorian date + * @param shortName Specifies if the short month name should be used + * @return The name of the month + */ + virtual QString monthName (const QDate & date, bool shortName = false ) const = 0; + + /** + * Returns a string containing the possessive form of the month name. + * ("of January", "of February", etc.) + * It's needed in long format dates in some languages. + * If an invalid month is specified, QString::null is returned. + * + * @param month The month number + * @param shortName Specifies if the short month name should be used + * + * @return The possessive form of the name of the month + */ + virtual QString monthNamePossessive(int month, bool shortName = false) const = 0; + + /** + * Returns a string containing the possessive form of the month name. + * ("of January", "of February", etc.) + * It's needed in long format dates in some languages. + * + * @param date Gregorian date + * @param shortName Specifies if the short month name should be used + * + * @return The possessive form of the name of the month + */ + virtual QString monthNamePossessive(const QDate & date, bool shortName = false) const = 0; + + /** + * Gets specific calendar type week day name + * If an invalid week day is specified, QString::null is returned. + * + * @param weekDay number of day in week (1 -> Monday) + * @param shortName short or complete day name + * @return day name + */ + virtual QString weekDayName (int weekDay, bool shortName = false) const = 0; + + /** + * Gets specific calendar type week day name + * + * @param date the date + * @param shortName short or complete day name + * @return day name + */ + virtual QString weekDayName (const QDate & date, bool shortName = false) const = 0; + + /** + * Gets the first year value supported by specific calendar type + * algorithms. + * + * @return first year supported + */ + virtual int minValidYear () const = 0; + + /** + * Gets the maximum year value supported by specific calendar type + * algorithms (QDate, 8000) + * + * @return maximum year supported + */ + virtual int maxValidYear () const = 0; + + /** + * Gets the day of the week traditionaly associated with pray + * + * @return day number + */ + virtual int weekDayOfPray () const = 0; + + /** + * Gets the string representing the calendar + */ + virtual QString calendarName() const = 0; + + /** + * Gets if the calendar is lunar based + * + * @return if the calendar is lunar based + */ + virtual bool isLunar() const = 0; + + /** + * Gets if the calendar is lunisolar based + * + * @return if the calendar is lunisolar based + */ + virtual bool isLunisolar() const = 0; + + /** + * Gets if the calendar is solar based + * + * @return if the calendar is solar based + */ + virtual bool isSolar() const = 0; + +protected: + const KLocale * locale() const; + +private: + KCalendarSystemPrivate * d; +}; + +#endif diff --git a/microkde/kcalendarsystemgregorian.cpp b/microkde/kcalendarsystemgregorian.cpp new file mode 100644 index 0000000..7c5b62a --- a/dev/null +++ b/microkde/kcalendarsystemgregorian.cpp @@ -0,0 +1,359 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// Derived gregorian kde calendar class +// Just a schema. + +#include <qdatetime.h> +#include <qstring.h> + +#include <klocale.h> +#include <kdebug.h> + +#include "kcalendarsystemgregorian.h" + +KCalendarSystemGregorian::KCalendarSystemGregorian(const KLocale * locale) + : KCalendarSystem(locale) +{ + kdDebug(5400) << "Created gregorian calendar" << endl; +} + +KCalendarSystemGregorian::~KCalendarSystemGregorian() +{ +} + +int KCalendarSystemGregorian::year(const QDate& date) const +{ +// kdDebug(5400) << "Gregorian year..." << endl; + return date.year(); +} + +int KCalendarSystemGregorian::monthsInYear( const QDate & ) const +{ +// kdDebug(5400) << "Gregorian monthsInYear" << endl; + + return 12; +} + +int KCalendarSystemGregorian::weeksInYear(int year) const +{ +#if QT_VERSION >= 300 + QDate temp; + temp.setYMD(year, 12, 31); + + // If the last day of the year is in the first week, we have to check the + // week before + if ( temp.weekNumber() == 1 ) + temp.addDays(-7); + + return temp.weekNumber(); +#else + return 52; +#endif +} + +int KCalendarSystemGregorian::weekNumber(const QDate& date, + int * yearNum) const +{ +#if QT_VERSION >= 300 + return date.weekNumber(yearNum); +#else + return 1; +#endif +} + +QString KCalendarSystemGregorian::monthName(const QDate& date, + bool shortName) const +{ + return monthName(month(date), shortName); +} + +QString KCalendarSystemGregorian::monthNamePossessive(const QDate& date, bool shortName) const +{ + return monthNamePossessive(month(date), shortName); +} + +QString KCalendarSystemGregorian::monthName(int month, bool shortName) const +{ +// kdDebug(5400) << "Gregorian getMonthName" << endl; + + if ( shortName ) + switch ( month ) + { + case 1: + return locale()->translate("January", "Jan"); + case 2: + return locale()->translate("February", "Feb"); + case 3: + return locale()->translate("March", "Mar"); + case 4: + return locale()->translate("April", "Apr"); + case 5: + return locale()->translate("May short", "May"); + case 6: + return locale()->translate("June", "Jun"); + case 7: + return locale()->translate("July", "Jul"); + case 8: + return locale()->translate("August", "Aug"); + case 9: + return locale()->translate("September", "Sep"); + case 10: + return locale()->translate("October", "Oct"); + case 11: + return locale()->translate("November", "Nov"); + case 12: + return locale()->translate("December", "Dec"); + } + else + switch ( month ) + { + case 1: + return locale()->translate("January"); + case 2: + return locale()->translate("February"); + case 3: + return locale()->translate("March"); + case 4: + return locale()->translate("April"); + case 5: + return locale()->translate("May long", "May"); + case 6: + return locale()->translate("June"); + case 7: + return locale()->translate("July"); + case 8: + return locale()->translate("August"); + case 9: + return locale()->translate("September"); + case 10: + return locale()->translate("October"); + case 11: + return locale()->translate("November"); + case 12: + return locale()->translate("December"); + } + + return QString::null; +} + +QString KCalendarSystemGregorian::monthNamePossessive(int month, + bool shortName) const +{ +// kdDebug(5400) << "Gregorian getMonthName" << endl; + + if ( shortName ) + switch ( month ) + { + case 1: + return locale()->translate("of January", "of Jan"); + case 2: + return locale()->translate("of February", "of Feb"); + case 3: + return locale()->translate("of March", "of Mar"); + case 4: + return locale()->translate("of April", "of Apr"); + case 5: + return locale()->translate("of May short", "of May"); + case 6: + return locale()->translate("of June", "of Jun"); + case 7: + return locale()->translate("of July", "of Jul"); + case 8: + return locale()->translate("of August", "of Aug"); + case 9: + return locale()->translate("of September", "of Sep"); + case 10: + return locale()->translate("of October", "of Oct"); + case 11: + return locale()->translate("of November", "of Nov"); + case 12: + return locale()->translate("of December", "of Dec"); + } + else + switch ( month ) + { + case 1: + return locale()->translate("of January"); + case 2: + return locale()->translate("of February"); + case 3: + return locale()->translate("of March"); + case 4: + return locale()->translate("of April"); + case 5: + return locale()->translate("of May long", "of May"); + case 6: + return locale()->translate("of June"); + case 7: + return locale()->translate("of July"); + case 8: + return locale()->translate("of August"); + case 9: + return locale()->translate("of September"); + case 10: + return locale()->translate("of October"); + case 11: + return locale()->translate("of November"); + case 12: + return locale()->translate("of December"); + } + + return QString::null; +} + +bool KCalendarSystemGregorian::setYMD(QDate & date, int y, int m, int d) const +{ + // We don't want Qt to add 1900 to them + if ( y >= 0 && y <= 99 ) + return false; + + // QDate supports gregorian internally + return date.setYMD(y, m, d); +} + +QDate KCalendarSystemGregorian::addYears(const QDate & date, int nyears) const +{ +#if QT_VERSION >= 300 + return date.addYears(nyears); +#else + int year = date.year() + nyears; + int month = date.month(); + int day = date.day(); + QDate newDate( year, month, 1 ); + if ( day > newDate.daysInMonth() ) day = newDate.daysInMonth(); + return QDate( year, month, day ); +#endif +} + +QDate KCalendarSystemGregorian::addMonths(const QDate & date, int nmonths) const +{ +#if QT_VERSION >= 300 + return date.addMonths(nmonths); +#else + int month = date.month(); + int nyears; + if ( nmonths >= 0 ) { + month += nmonths; + nyears = ( month - 1 ) / 12; + month = ( ( month - 1 ) % 12 ) + 1; + } else { + nyears = nmonths / 12; + // nmonths += nyears * 12; + nmonths = nmonths % 12; + month += nmonths; + if ( month <= 0 ) { + month += 12; + --nyears; + } + } + int year = date.year() + nyears; + int day = date.day(); + QDate newDate( year, month, 1 ); + if ( day > newDate.daysInMonth() ) day = newDate.daysInMonth(); + return QDate( year, month, day ); +#endif +} + +QDate KCalendarSystemGregorian::addDays(const QDate & date, int ndays) const +{ + return date.addDays(ndays); +} + +QString KCalendarSystemGregorian::weekDayName(int col, bool shortName) const +{ + // ### Should this really be different to each calendar system? Or are we + // only going to support weeks with 7 days? + + //kdDebug(5400) << "Gregorian wDayName" << endl; + return locale()->weekDayName(col, shortName); +} + +QString KCalendarSystemGregorian::weekDayName(const QDate& date, bool shortName) const +{ + return weekDayName(dayOfWeek(date), shortName); +} + + +int KCalendarSystemGregorian::dayOfWeek(const QDate& date) const +{ + return date.dayOfWeek(); +} + +int KCalendarSystemGregorian::dayOfYear(const QDate & date) const +{ + return date.dayOfYear(); +} + +int KCalendarSystemGregorian::daysInMonth(const QDate& date) const +{ +// kdDebug(5400) << "Gregorian daysInMonth" << endl; + return date.daysInMonth(); +} + +int KCalendarSystemGregorian::minValidYear() const +{ + return 1753; // QDate limit +} + +int KCalendarSystemGregorian::maxValidYear() const +{ + return 8000; // QDate limit +} + +int KCalendarSystemGregorian::day(const QDate& date) const +{ + return date.day(); +} + +int KCalendarSystemGregorian::month(const QDate& date) const +{ + return date.month(); +} + +int KCalendarSystemGregorian::daysInYear(const QDate& date) const +{ + return date.daysInYear(); +} + +int KCalendarSystemGregorian::weekDayOfPray() const +{ + return 7; // sunday +} + +QString KCalendarSystemGregorian::calendarName() const +{ + return QString::fromLatin1("gregorian"); +} + +bool KCalendarSystemGregorian::isLunar() const +{ + return false; +} + +bool KCalendarSystemGregorian::isLunisolar() const +{ + return false; +} + +bool KCalendarSystemGregorian::isSolar() const +{ + return true; +} diff --git a/microkde/kcalendarsystemgregorian.h b/microkde/kcalendarsystemgregorian.h new file mode 100644 index 0000000..2eff625 --- a/dev/null +++ b/microkde/kcalendarsystemgregorian.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCALENDARSYSTEMGREGORIAN_H +#define KCALENDARSYSTEMGREGORIAN_H + +#include <qdatetime.h> +#include <qstring.h> + +#include "kcalendarsystem.h" + +class KCalendarSystemGregorianPrivate; + +/** + * This is the Gregorian calendar implementation. + * + * The Gregorian calender is the most used calendar today. The first year in + * the calendar is set to the birth of Christ. + * + * @see KLocale,KCalendarSystem,KCalendarSystemFactory + * + * @author Carlos Moro <cfmoro@correo.uniovi.es> + * @licence GNU-GPL v.2 + * @version $Id$ + * @since 3.2 + */ +class KCalendarSystemGregorian: public KCalendarSystem +{ +public: + KCalendarSystemGregorian (const KLocale * locale = 0); + virtual ~KCalendarSystemGregorian (); + + virtual int year (const QDate & date) const; + virtual int month (const QDate & date) const; + virtual int day (const QDate & date) const; + virtual int dayOfWeek (const QDate & date) const; + virtual int dayOfYear (const QDate & date) const; + + virtual bool setYMD(QDate & date, int y, int m, int d) const; + + virtual QDate addYears(const QDate & date, int nyears) const; + virtual QDate addMonths(const QDate & date, int nmonths) const; + virtual QDate addDays(const QDate & date, int ndays) const; + + virtual int monthsInYear (const QDate & date) const; + + virtual int daysInYear (const QDate & date) const; + virtual int daysInMonth (const QDate & date) const; + virtual int weeksInYear(int year) const; + virtual int weekNumber(const QDate& date, int * yearNum = 0) const; + + virtual QString monthName (int month, bool shortName = false) const; + virtual QString monthName (const QDate & date, bool shortName = false ) const; + virtual QString monthNamePossessive(int month, bool shortName = false) const; + virtual QString monthNamePossessive(const QDate & date, bool shortName = false ) const; + virtual QString weekDayName (int weekDay, bool shortName = false) const; + virtual QString weekDayName (const QDate & date, bool shortName = false) const; + + virtual int minValidYear () const; + virtual int maxValidYear () const; + virtual int weekDayOfPray () const; + + virtual QString calendarName() const; + + virtual bool isLunar() const; + virtual bool isLunisolar() const; + virtual bool isSolar() const; + +private: + KCalendarSystemGregorianPrivate * d; +}; + +#endif diff --git a/microkde/kcolorbutton.cpp b/microkde/kcolorbutton.cpp new file mode 100644 index 0000000..433f909 --- a/dev/null +++ b/microkde/kcolorbutton.cpp @@ -0,0 +1,36 @@ +#include "kcolorbutton.h" +#include "kcolordialog.h" +#include "qapplication.h" + + +#include "qlayout.h" + +void KColorButton:: edit() +{ + + KColorDialog* k = new KColorDialog( this ); + k->setColor( mColor ); + int res = k->exec(); + if ( res ) { + mColor = k->getColor(); + setColor ( mColor ); + emit changed ( mColor ); + } + delete k; +} +KColorButton::KColorButton( QWidget *p ):QPushButton( p ) +{ + int size = 24; + if( QApplication::desktop()->width() < 480 ) + size = 18; + setFixedSize( size,size ); + connect ( this, SIGNAL( clicked() ), this ,SLOT (edit() )); + +} +void KColorButton::setColor ( const QColor & c) +{ + mColor = c; + QPixmap pix ( height() - 4, width() - 4 ); + pix.fill( c ); + setPixmap ( pix ); +} diff --git a/microkde/kcolorbutton.h b/microkde/kcolorbutton.h new file mode 100644 index 0000000..88b3774 --- a/dev/null +++ b/microkde/kcolorbutton.h @@ -0,0 +1,26 @@ +#ifndef MICROKDE_KCOLORBUTTON_H +#define MICROKDE_KCOLORBUTTON_H + +#include <qpushbutton.h> +#include <qcolor.h> +#include <kglobal.h> +#include <qpixmap.h> +#include <qlabel.h> + + +class KColorButton : public QPushButton +{ +Q_OBJECT +public: + KColorButton( QWidget *p ); + void setColor ( const QColor &); + QColor color() const { return mColor ; } + signals: + void changed(const QColor &); +private slots: + void edit(); + private: + QColor mColor; +}; + +#endif diff --git a/microkde/kcolordialog.cpp b/microkde/kcolordialog.cpp new file mode 100644 index 0000000..9a76e5e --- a/dev/null +++ b/microkde/kcolordialog.cpp @@ -0,0 +1,92 @@ +#include "kcolordialog.h" +#include <qdialog.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qslider.h> +#include <qhbox.h> +#include <qapplication.h> +#include <qpushbutton.h> + +#include <kglobal.h> +QColor KColorDialog::getColor( ) const +{ + QColor c ( r->value(), g->value(), b->value() ); + lar->setText ( "R: " + QString::number ( c.red() ) ); + lag->setText ( "G: " + QString::number ( c.green() ) ); + lab->setText ( "B: " + QString::number ( c.blue() ) ); + return c; +} +void KColorDialog::setColor( const QColor & d ) +{ + r->setValue(d.red() ); + g->setValue(d.green() ); + b->setValue(d.blue() ); + old_color->setPalette( QPalette( d.dark(), d ) ); + lar->setText ( "R: " + QString::number ( d.red() ) ); + lag->setText ( "G: " + QString::number ( d.green() ) ); + lab->setText ( "B: " + QString::number ( d.blue() ) ); + +} +KColorDialog::KColorDialog( QWidget *p ):QDialog( p, "input-dialog", true ) +{ + setCaption( i18n("Choose Color") ); + + setMaximumSize( QApplication::desktop()->width() - 20, QApplication::desktop()->height() - 40 ); // for zaurus 5500er. + QGridLayout* lay = new QGridLayout ( this, 4, 2 ); + lay->setSpacing( 6 ); + lay->setMargin( 11 ); + + old_color = new QLabel("Old color",this); + old_color->setFrameStyle( QFrame::Panel | QFrame::Plain ); + old_color->setLineWidth( 1 ); + lay->addWidget(old_color, 0, 0); + + new_color = new QLabel("New color", this); + new_color->setFrameStyle( QFrame::Panel | QFrame::Plain ); + new_color->setLineWidth( 1 ); + lay->addWidget(new_color, 0, 1); + new_color->setAlignment( AlignCenter ); + + QHBox* hb = new QHBox ( this ); + lar = new QLabel( hb ); + lag = new QLabel( hb ); + lab = new QLabel( hb ); + lay->addMultiCellWidget( hb,1,1, 0,1 ); + + QLabel* lr = new QLabel ( "Red:", this ); + lay->addWidget( lr,2,0 ); + r = new QSlider ( 0, 255, 1, 1, Horizontal, this ); + lay->addWidget(r ,2,1 ); + + QLabel* lg = new QLabel( "Green:",this ); + lay->addWidget(lg ,3,0 ); + g = new QSlider ( 0, 255, 1, 1, Horizontal, this ); + lay->addWidget( g ,3,1 ); + + QLabel* lb = new QLabel ( "Blue:",this ); + lay->addWidget( lb,4,0 ); + b = new QSlider ( 0, 255, 1, 1, Horizontal, this ); + lay->addWidget(b ,4,1 ); + + QColor d = backgroundColor(); + r->setValue(d.red() ); + g->setValue(d.green() ); + b->setValue(d.blue() ); + old_color->setPalette( QPalette( d.dark() , d ) ); + // kannst du wieder reinnehmen, aber es geht auch so. + QPushButton * ok = new QPushButton (i18n(" OK "), this ); + QPushButton * cancel = new QPushButton (i18n(" Cancel "), this ); + + lay->addWidget(ok ,5,0 ); + lay->addWidget(cancel ,5,1 ); + connect (ok, SIGNAL( clicked() ), this ,SLOT (accept() )); + connect (cancel, SIGNAL( clicked() ), this ,SLOT (reject() )); + connect (r, SIGNAL( valueChanged ( int ) ), this ,SLOT (updateColor( int ) )); + connect (g, SIGNAL( valueChanged ( int ) ), this ,SLOT (updateColor( int ) )); + connect (b, SIGNAL( valueChanged ( int ) ), this ,SLOT (updateColor( int ) )); +} +void KColorDialog::updateColor( int ) +{ + QColor c = getColor( ) ; + new_color->setPalette( QPalette( c.dark(), c ) ); +} diff --git a/microkde/kcolordialog.h b/microkde/kcolordialog.h new file mode 100644 index 0000000..bb2045d --- a/dev/null +++ b/microkde/kcolordialog.h @@ -0,0 +1,25 @@ +#ifndef MINIKDE_KCOLORDIALOG_H +#define MINIKDE_KCOLORDIALOG_H + +#include <qcolor.h> + +#include <qdialog.h> +#include <qslider.h> +#include <qlabel.h> +class KColorDialog : public QDialog +{ +Q_OBJECT + public: + KColorDialog( QWidget *p ); + QColor getColor( ) const; + void setColor( const QColor &); + private: + QSlider *r, *g, *b; + QLabel * old_color, *new_color; + QLabel *lar, *lag, *lab; +private slots: + void updateColor( int ); +}; + + +#endif diff --git a/microkde/kcombobox.h b/microkde/kcombobox.h new file mode 100644 index 0000000..1a21344 --- a/dev/null +++ b/microkde/kcombobox.h @@ -0,0 +1,12 @@ +#ifndef MICROKDE_KCOMBOBOX_H +#define MICROKDE_KCOMBOBOX_H + +#include <qcombobox.h> + +class KComboBox : public QComboBox +{ + public: + KComboBox( QWidget *parent ) : QComboBox( parent ) {} +}; + +#endif diff --git a/microkde/kconfig.cpp b/microkde/kconfig.cpp new file mode 100644 index 0000000..3f23ed2 --- a/dev/null +++ b/microkde/kconfig.cpp @@ -0,0 +1,467 @@ +#include <qfile.h> +#include <qtextstream.h> +#include <qwidget.h> + +#include "kdebug.h" + +#include "kurl.h" +#include "kstandarddirs.h" +#include "kconfig.h" + +QString KConfig::mGroup = ""; +//QString KConfig::mGroup = "General"; + +KConfig::KConfig( const QString &fileName ) + : mFileName( fileName ), mDirty( false ) +{ + kdDebug() << "KConfig::KConfig(): '" << fileName << "'" << endl; + + load(); + +} + + +KConfig::~KConfig() +{ + sync(); +} + +void KConfig::setGroup( const QString &group ) +{ + kdDebug() << "KConfig::setGroup(): '" << group << "'" << endl; + + mGroup = group; + + if ( mGroup.right( 1 ) != "/" ) mGroup += "/"; +} + +//US +QString KConfig::group() const { + return mGroup; +} + +//US added method +QValueList<int> KConfig::readIntListEntry( const QString & key) +{ +// qDebug("KConfig::readIntListEntry key=%s:", key.latin1()); + + QValueList<int> result; + + QMap<QString,QString>::ConstIterator mit = mStringMap.find( mGroup + key ); + + if ( mit == mStringMap.end() ) { + return result; + } + + QStringList valuesAsStrings = QStringList::split(":", *mit ); + bool ok = false; + bool ok2 = true; + int val; + + for ( QStringList::Iterator sit = valuesAsStrings.begin(); sit != valuesAsStrings.end(); ++sit ) { + val = (*sit).toInt(&ok); + result << val; + if (ok == false) { + qDebug("KConfig::readIntListEntry str=%s , int=%n:", (*sit).latin1(), &val); + ok2 = false; + } + } + + if (ok2 == false) + { + kdDebug() << "KConfig::readIntListEntry: error while reading one of the intvalues." << endl; + qDebug("KConfig::readIntListEntry: error while reading one of the intvalues."); + } + + return result; +} + +int KConfig::readNumEntry( const QString & key, int def ) +{ + QString res = readEntry(key, QString::number(def ) ); + bool ok = false; + int result = res.toInt(&ok); + if ( ok ) + return result; + return def; +} + +QString KConfig::readEntry( const QString &key, const QString &def ) +{ + QMap<QString,QString>::ConstIterator it = mStringMap.find( mGroup + key ); + + if ( it == mStringMap.end() ) { + return def; + } + + return *it; +} + +QStringList KConfig::readListEntry( const QString &key ) +{ + QMap<QString,QString>::ConstIterator it = mStringMap.find( mGroup + key ); + + if ( it == mStringMap.end() ) { + return QStringList(); + } + return QStringList::split(":", *it ); + +} + +bool KConfig::readBoolEntry( const QString &key, bool def ) +{ + QMap<QString,bool>::ConstIterator it = mBoolMap.find( mGroup + key ); + + if ( it == mBoolMap.end() ) { + return def; + } + + return *it; +} + +QColor KConfig::readColorEntry( const QString & e, QColor *def ) +{ + + QStringList l; + l = readListEntry( e ); + if (l.count() != 3 ) { + if ( def ) + return *def; + else + return QColor(); + } + QColor c ( l[0].toInt(), l[1].toInt(), l[2].toInt() ); + return c; +} + +QFont KConfig::readFontEntry( const QString & e, QFont *def ) +{ + QStringList font = readListEntry( e ); + if ( font.isEmpty() ) + return *def; + QFont f; + f.setFamily( font[0]); + f.setBold ( font[1] == "bold"); + f.setPointSize ( font[2].toInt()); + f.setItalic( font[1] == "italic" ); + return f; +} + +QDateTime KConfig::readDateTimeEntry( const QString &key, const QDateTime *def ) +{ + QMap<QString,QDateTime>::ConstIterator it = mDateTimeMap.find( mGroup + key ); + + if ( it == mDateTimeMap.end() ) { + if ( def ) return *def; + else return QDateTime(); + } + + return *it; +} + +//US added method +void KConfig::writeEntry( const QString &key, const QValueList<int> &value) +{ + QStringList valuesAsStrings; + + QValueList<int>::ConstIterator it; + + for( it = value.begin(); it != value.end(); ++it ) + { + valuesAsStrings << QString::number(*it); + } + + mStringMap.insert( mGroup + key, valuesAsStrings.join(":") ); + mDirty = true; +} + +void KConfig::writeEntry( const QString & key , int num ) +{ + writeEntry( key, QString::number ( num ) ); +} + +void KConfig::writeEntry( const QString &key, const QString &value ) +{ + mStringMap.insert( mGroup + key, value ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString &key, const QStringList &value ) +{ + mStringMap.insert( mGroup + key, value.join(":") ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString &key, bool value) +{ + mBoolMap.insert( mGroup + key, value ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString & e, const QColor & c ) +{ + QStringList l; + l.append( QString::number ( c.red() ) ); + l.append( QString::number ( c.green() ) ); + l.append( QString::number ( c.blue() ) ); + writeEntry( e, l ); +} + +void KConfig::writeEntry( const QString & e , const QFont & f ) +{ + QStringList font; + font.append( f.family()); + font.append( (!f.bold ()?"nonbold":"bold") ); + font.append( QString::number ( f.pointSize () ) ); + font.append( !f.italic ()?"nonitalic":"italic" ); + writeEntry( e, font ); +} + +void KConfig::writeEntry( const QString &key, const QDateTime &dt ) +{ + mDateTimeMap.insert( mGroup + key, dt ); +} + +void KConfig::load() +{ + kdDebug() << "KConfig::load(): " << mFileName << endl; + + QFile f( mFileName ); + if ( !f.open( IO_ReadOnly ) ) { + qDebug("KConfig: could not open file %s ",mFileName.latin1() ); + return; + } + + mBoolMap.clear(); + mStringMap.clear(); + + QTextStream t( &f ); + + QString line = t.readLine(); + + while ( !line.isNull() ) { + QStringList tokens = QStringList::split( ",", line ); + if ( tokens[0] == "bool" ) { + bool value = false; + if ( tokens[2] == "1" ) value = true; + mBoolMap.insert( tokens[1], value ); + } else if ( tokens[0] == "QString" ) { + QString value = tokens[2]; + mStringMap.insert( tokens[1], value ); + } else if ( tokens[0] == "QDateTime" ) { +#if 0 + int year = tokens[2].toInt(); + QDateTime dt( QDate( year, + tokens[3].toInt(), + tokens[4].toInt() ), + QTime( tokens[5].toInt(), tokens[6].toInt(), + tokens[7].toInt() ) ); + mDateTimeMap.insert( tokens[1], dt ); +#endif + } + + line = t.readLine(); + } +} + +void KConfig::sync() +{ + + if ( !mDirty ) return; + //qDebug("KConfig::sync() %s ",mFileName.latin1() ); + //kdDebug() << "KConfig::sync(): " << mFileName << endl; + +//US I took the following code from a newer version of KDE + // Create the containing dir if needed + KURL path; + path.setPath(mFileName); + QString dir=path.directory(); + KStandardDirs::makeDir(dir); + + QFile f( mFileName ); + if ( !f.open( IO_WriteOnly ) ) { + + qDebug("KConfig::sync() Can't open file %s ",mFileName.latin1() ); + + return; + } + + QTextStream t( &f ); + + QMap<QString,bool>::ConstIterator itBool; + for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) { + t << "bool," << itBool.key() << "," << ( *itBool ? "1" : "0" ) << endl; + } + + QMap<QString,QString>::ConstIterator itString; + for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) { + t << "QString," << itString.key() << "," << (*itString ) << endl; + } + + QMap<QString,QDateTime>::ConstIterator itDateTime; + for( itDateTime = mDateTimeMap.begin(); itDateTime != mDateTimeMap.end(); ++itDateTime ) { + QDateTime dt = *itDateTime; + t << "QDateTime," << itDateTime.key() << "," + << dt.date().year() << "," + << dt.date().month() << "," + << dt.date().day() << "," + << dt.time().hour() << "," + << dt.time().minute() << "," + << dt.time().second() << endl; + } + + f.close(); + + mDirty = false; +} + + +//US I took the following deleteGroup method from a newer version from KDE. +/** + * Deletes a configuration entry group + * + * If the group is not empty and bDeep is false, nothing gets + * deleted and false is returned. + * If this group is the current group and it is deleted, the + * current group is undefined and should be set with setGroup() + * before the next operation on the configuration object. + * + * @param group The name of the group + * returns true if we deleted at least one entry. + */ +bool KConfig::deleteGroup( const QString& group) +{ + bool dirty = false; + int pos; + + QMap<QString,bool>::Iterator itBool; + for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) + { + pos = itBool.key().find( group ); + if (pos == 0) { + mBoolMap.remove(itBool); + dirty = true; + } + } + + QMap<QString,QString>::Iterator itString; + for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) + { + pos = itString.key().find( group ); + if (pos == 0) { + mStringMap.remove(itString); + dirty = true; + } + } + + QMap<QString,QDateTime>::Iterator itDateTime; + for( itDateTime = mDateTimeMap.begin(); itDateTime != mDateTimeMap.end(); ++itDateTime ) + { + pos = itDateTime.key().find( group ); + if (pos == 0) { + mDateTimeMap.remove(itDateTime); + dirty = true; + } + } + + if (dirty) + mDirty = true; + + return dirty; + +} + +//US I took the following hasGroup method from a newer version from KDE. + /** + * Returns true if the specified group is known about. + * + * @param group The group to search for. + * @return Whether the group exists. + */ +bool KConfig::hasGroup(const QString &group) const +{ + QMap<QString,bool>::ConstIterator itBool; + for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) + { + if (itBool.key().find( group ) == 0) { + return true; + } + } + + QMap<QString,QString>::ConstIterator itString; + for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) + { + if (itString.key().find( group ) == 0) { + return true; + } + } + + QMap<QString,QDateTime>::ConstIterator itDateTime; + for( itDateTime = mDateTimeMap.begin(); itDateTime != mDateTimeMap.end(); ++itDateTime ) + { + if (itDateTime.key().find( group ) == 0) { + return true; + } + } + + return false; +} + +void KConfig::deleteEntry( const QString &key) +{ + bool dirty = false; + + QMap<QString,bool>::Iterator itBool = mBoolMap.find( mGroup + key ); + if ( itBool != mBoolMap.end() ) { + mBoolMap.remove(itBool); + dirty = true; + } + + + QMap<QString,QString>::Iterator itString = mStringMap.find( mGroup + key ); + if ( itString != mStringMap.end() ) { + mStringMap.remove(itString); + dirty = true; + } + + + QMap<QString,QDateTime>::Iterator itDateTime = mDateTimeMap.find( mGroup + key ); + if ( itDateTime != mDateTimeMap.end() ) { + mDateTimeMap.remove(itDateTime); + dirty = true; + } + + if (dirty) + mDirty = true; + +} + +//US +QString KConfig::getFileName() +{ + return mFileName; +} + +bool KConfig::hasKey( const QString &key) +{ + QMap<QString,bool>::Iterator itBool = mBoolMap.find( mGroup + key ); + if ( itBool != mBoolMap.end() ) { + return true; + } + + QMap<QString,QString>::Iterator itString = mStringMap.find( mGroup + key ); + if ( itString != mStringMap.end() ) { + return true; + } + + QMap<QString,QDateTime>::Iterator itDateTime = mDateTimeMap.find( mGroup + key ); + if ( itDateTime != mDateTimeMap.end() ) { + return true; + } + + return false; +} + diff --git a/microkde/kconfig.h b/microkde/kconfig.h new file mode 100644 index 0000000..bfedf53 --- a/dev/null +++ b/microkde/kconfig.h @@ -0,0 +1,100 @@ +#ifndef MINIKDE_KCONFIG_H +#define MINIKDE_KCONFIG_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qcolor.h> +#include <qfont.h> +#include <qmap.h> +#include <qdatetime.h> + +class KConfig +{ + public: + KConfig( const QString & ); + ~KConfig(); + + void setGroup( const QString & ); + +//US + /** + * Returns the name of the group in which we are + * searching for keys and from which we are retrieving entries. + * + * @return The current group. + */ + QString group() const; + +//US I took the following deleteGroup method from a newer version from KDE. +/** + * Deletes a configuration entry group + * + * If the group is not empty and bDeep is false, nothing gets + * deleted and false is returned. + * If this group is the current group and it is deleted, the + * current group is undefined and should be set with setGroup() + * before the next operation on the configuration object. + * + * @param group The name of the group + * returns true if we deleted at least one entry. + */ + bool deleteGroup( const QString& group); + +//US I took the following hasGroup method from a newer version from KDE. + /** + * Returns true if the specified group is known about. + * + * @param group The group to search for. + * @return Whether the group exists. + */ + bool hasGroup(const QString &group) const; + + + QString getFileName(); + +//US added method readIntListEntry + QValueList<int> readIntListEntry( const QString &); + + int readNumEntry( const QString &, int def=0 ); + QString readEntry( const QString &, const QString &def=QString::null ); + QStringList readListEntry( const QString & ); + bool readBoolEntry( const QString &, bool def=false ); + QColor readColorEntry( const QString &, QColor * ); + QFont readFontEntry( const QString &, QFont * ); + QDateTime readDateTimeEntry( const QString &, const QDateTime *pDefault = 0 ); + + bool hasKey( const QString &); + + void writeEntry( const QString &, const QValueList<int>& ); + void writeEntry( const QString &, int ); + void writeEntry( const QString &key , unsigned int value) { writeEntry( key, int( value ) ); } + void writeEntry( const char *key , unsigned int value) { writeEntry( QString( key ), value ); } + void writeEntry( const char *key, int value ) { writeEntry( QString( key ), value ); } + void writeEntry( const QString &, const QString & ); + void writeEntry( const char *key, const QString &value ) { writeEntry( QString( key ), value ); } + void writeEntry( const QString &, const QStringList & ); + void writeEntry( const QString &, bool ); + void writeEntry( const char *key, bool value ) { writeEntry( QString( key ), value ); } + void writeEntry( const QString &, const QColor & ); + void writeEntry( const QString &, const QFont & ); + void writeEntry( const QString &, const QDateTime & ); + + void deleteEntry( const QString &); + + void load(); + void sync(); + + private: + static QString mGroup; + + QString mFileName; + + QMap<QString,bool> mBoolMap; + QMap<QString,QString> mStringMap; + QMap<QString,QDateTime> mDateTimeMap; + + bool mDirty; +}; + +#endif diff --git a/microkde/kconfigtest.cpp b/microkde/kconfigtest.cpp new file mode 100644 index 0000000..373d674 --- a/dev/null +++ b/microkde/kconfigtest.cpp @@ -0,0 +1,14 @@ +#include "kconfig.h" +#include "kdebug.h" + +#include <qdatetime.h> + +int main() +{ + QDateTime dt = QDateTime::currentDateTime(); + kdDebug() << "Before: " << dt.toString() << endl; + KConfig cfg( "huhu" ); + cfg.writeEntry( "123", dt ); + QDateTime newDt = cfg.readDateTimeEntry( "123" ); + kdDebug() << "After: " << newDt.toString() << endl; +} diff --git a/microkde/kdatepickernew.cpp b/microkde/kdatepickernew.cpp new file mode 100644 index 0000000..f60a422 --- a/dev/null +++ b/microkde/kdatepickernew.cpp @@ -0,0 +1,485 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qlayout.h> +#include <qframe.h> +#include <qpainter.h> +#include <qdialog.h> +#include <qstyle.h> +#include <qtoolbutton.h> +#include <qcombobox.h> +#include <qtooltip.h> +#include <qfont.h> +#include <qvalidator.h> +#include <qpopupmenu.h> + +#include "kdatepicker.h" +#include <kglobal.h> +#include <kapplication.h> +#include <klocale.h> +#include <kiconloader.h> +#include <ktoolbar.h> +#include <klineedit.h> +#include <kdebug.h> +#include <knotifyclient.h> +#include <kcalendarsystem.h> + +#include "kdatetbl.h" +#include "kdatepicker.moc" + +class KDatePicker::KDatePickerPrivate +{ +public: + KDatePickerPrivate() : closeButton(0L), selectWeek(0L), todayButton(0), navigationLayout(0) {} + + void fillWeeksCombo(const QDate &date); + + KToolBar *tb; + QToolButton *closeButton; + QComboBox *selectWeek; + QToolButton *todayButton; + QBoxLayout *navigationLayout; +}; + +void KDatePicker::fillWeeksCombo(const QDate &date) +{ + // every year can have a different number of weeks + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + int i, weeks = calendar->weeksInYear(calendar->year(date)); + + if ( d->selectWeek->count() == weeks ) return; // we already have the correct number + + d->selectWeek->clear(); + + for (i = 1; i <= weeks; i++) + d->selectWeek->insertItem(i18n("Week %1").arg(i)); +} + +KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name) + : QFrame(parent,name) +{ + init( dt ); +} + +KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name, WFlags f) + : QFrame(parent,name, f) +{ + init( dt ); +} + +KDatePicker::KDatePicker( QWidget *parent, const char *name ) + : QFrame(parent,name) +{ + init( QDate::currentDate() ); +} + +void KDatePicker::init( const QDate &dt ) +{ + d = new KDatePickerPrivate(); + + d->tb = new KToolBar(this); + + yearBackward = new QToolButton(d->tb); + monthBackward = new QToolButton(d->tb); + selectMonth = new QToolButton(d->tb); + selectYear = new QToolButton(d->tb); + monthForward = new QToolButton(d->tb); + yearForward = new QToolButton(d->tb); + line = new KLineEdit(this); + val = new KDateValidator(this); + table = new KDateTable(this); + fontsize = 12;//KGlobalSettings::generalFont().pointSize(); + + + fontsize++; // Make a little bigger + + d->selectWeek = new QComboBox(false, this); // read only week selection + d->todayButton = new QToolButton(this); + d->todayButton->setIconSet(SmallIconSet("today")); + + QToolTip::add(yearForward, i18n("Next year")); + QToolTip::add(yearBackward, i18n("Previous year")); + QToolTip::add(monthForward, i18n("Next month")); + QToolTip::add(monthBackward, i18n("Previous month")); + QToolTip::add(d->selectWeek, i18n("Select a week")); + QToolTip::add(selectMonth, i18n("Select a month")); + QToolTip::add(selectYear, i18n("Select a year")); + QToolTip::add(d->todayButton, i18n("Select the current day")); + + // ----- + setFontSize(fontsize); + line->setValidator(val); + line->installEventFilter( this ); +// yearForward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow"))); +// yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow"))); +// monthForward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow"))); +// monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow"))); + setDate(dt); // set button texts + connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate))); + connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot())); + connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked())); + connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked())); + connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked())); + connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked())); + connect(d->selectWeek, SIGNAL(activated(int)), SLOT(weekSelected(int))); + connect(d->todayButton, SIGNAL(clicked()), SLOT(todayButtonClicked())); + connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked())); + connect(selectYear, SIGNAL(clicked()), SLOT(selectYearClicked())); + connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed())); + table->setFocus(); + + QBoxLayout * topLayout = new QVBoxLayout(this); + + d->navigationLayout = new QHBoxLayout(topLayout); + d->navigationLayout->addWidget(d->tb); + + topLayout->addWidget(table); + + QBoxLayout * bottomLayout = new QHBoxLayout(topLayout); + bottomLayout->addWidget(d->todayButton); + bottomLayout->addWidget(line); + bottomLayout->addWidget(d->selectWeek); +} + +KDatePicker::~KDatePicker() +{ + delete d; +} + +bool +KDatePicker::eventFilter(QObject *o, QEvent *e ) +{ + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *k = (QKeyEvent *)e; + + if ( (k->key() == Qt::Key_Prior) || + (k->key() == Qt::Key_Next) || + (k->key() == Qt::Key_Up) || + (k->key() == Qt::Key_Down) ) + { + QApplication::sendEvent( table, e ); + table->setFocus(); + return true; // eat event + } + } + return QFrame::eventFilter( o, e ); +} + +void +KDatePicker::resizeEvent(QResizeEvent* e) +{ + QWidget::resizeEvent(e); +} + +void +KDatePicker::dateChangedSlot(QDate date) +{ + kdDebug(298) << "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl; + + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + line->setText(KGlobal::locale()->formatDate(date, true)); + selectMonth->setText(calendar->monthName(date, false)); + fillWeeksCombo(date); + d->selectWeek->setCurrentItem(calendar->weekNumber(date) - 1); + selectYear->setText(calendar->yearString(date, false)); + + emit(dateChanged(date)); +} + +void +KDatePicker::tableClickedSlot() +{ + kdDebug(298) << "KDatePicker::tableClickedSlot: table clicked." << endl; + emit(dateSelected(table->getDate())); + emit(tableClicked()); +} + +const QDate& +KDatePicker::getDate() const +{ + return table->getDate(); +} + +const QDate & +KDatePicker::date() const +{ + return table->getDate(); +} + +bool +KDatePicker::setDate(const QDate& date) +{ + if(date.isValid()) + { + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + table->setDate(date); + fillWeeksCombo(date); + d->selectWeek->setCurrentItem(calendar->weekNumber(date) - 1); + selectMonth->setText(calendar->monthName(date, false)); + selectYear->setText(calendar->yearString(date, true)); + line->setText(KGlobal::locale()->formatDate(date, true)); + return true; + } + else + { + kdDebug(298) << "KDatePicker::setDate: refusing to set invalid date." << endl; + return false; + } +} + +void +KDatePicker::monthForwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), 1 ); + + setDate( temp ); +} + +void +KDatePicker::monthBackwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), -1 ); + + setDate( temp ); +} + +void +KDatePicker::yearForwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addYears( table->getDate(), 1 ); + + setDate( temp ); +} + +void +KDatePicker::yearBackwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addYears( table->getDate(), -1 ); + + setDate( temp ); +} + +void KDatePicker::selectWeekClicked() {} // ### in 3.2 obsolete; kept for binary compatibility + +void +KDatePicker::weekSelected(int week) +{ + week++; // week number starts with 1 + + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + QDate date = table->getDate(); + int year = calendar->year(date); + + calendar->setYMD(date, year, 1, 1); + date = calendar->addDays(date, -7); + while (calendar->weekNumber(date) != 1) + date = calendar->addDays(date, 1); + + // date is now first day in week 1 some day in week 1 + date = calendar->addDays(date, (week - calendar->weekNumber(date)) * 7); + + setDate(date); +} + +void +KDatePicker::selectMonthClicked() +{ + // every year can have different month names (in some calendar systems) + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + QDate date = table->getDate(); + int i, month, months = calendar->monthsInYear(date); + + QPopupMenu popup(selectMonth); + + for (i = 1; i <= months; i++) + popup.insertItem(calendar->monthName(i, calendar->year(date)), i); + + popup.setActiveItem(calendar->month(date) - 1); + + if ( (month = popup.exec(selectMonth->mapToGlobal(QPoint(0, 0)), calendar->month(date) - 1)) == -1 ) return; // canceled + + int day = calendar->day(date); + // ----- construct a valid date in this month: + //date.setYMD(date.year(), month, 1); + //date.setYMD(date.year(), month, QMIN(day, date.daysInMonth())); + calendar->setYMD(date, calendar->year(date), month, + QMIN(day, calendar->daysInMonth(date))); + // ----- set this month + setDate(date); +} + +void +KDatePicker::selectYearClicked() +{ + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + int year; + KPopupFrame* popup = new KPopupFrame(this); + KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup); + // ----- + picker->resize(picker->sizeHint()); + popup->setMainWidget(picker); + connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); + picker->setFocus(); + if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height())))) + { + QDate date; + int day; + // ----- + year=picker->getYear(); + date=table->getDate(); + day=calendar->day(date); + // ----- construct a valid date in this month: + //date.setYMD(year, date.month(), 1); + //date.setYMD(year, date.month(), QMIN(day, date.daysInMonth())); + calendar->setYMD(date, year, calendar->month(date), + QMIN(day, calendar->daysInMonth(date))); + // ----- set this month + setDate(date); + } else { + KNotifyClient::beep(); + } + delete popup; +} + +void +KDatePicker::setEnabled(bool enable) +{ + QWidget *widgets[]= { + yearForward, yearBackward, monthForward, monthBackward, + selectMonth, selectYear, + line, table, d->selectWeek, d->todayButton }; + const int Size=sizeof(widgets)/sizeof(widgets[0]); + int count; + // ----- + for(count=0; count<Size; ++count) + { + widgets[count]->setEnabled(enable); + } +} + +void +KDatePicker::lineEnterPressed() +{ + QDate temp; + // ----- + if(val->date(line->text(), temp)==QValidator::Acceptable) + { + kdDebug(298) << "KDatePicker::lineEnterPressed: valid date entered." << endl; + emit(dateEntered(temp)); + setDate(temp); + } else { + KNotifyClient::beep(); + kdDebug(298) << "KDatePicker::lineEnterPressed: invalid date entered." << endl; + } +} + +void +KDatePicker::todayButtonClicked() +{ + setDate(QDate::currentDate()); +} + +QSize +KDatePicker::sizeHint() const +{ + return QWidget::sizeHint(); +} + +void +KDatePicker::setFontSize(int s) +{ + QWidget *buttons[]= { + // yearBackward, + // monthBackward, + selectMonth, + selectYear, + // monthForward, + // yearForward + }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + int count; + QFont font; + QRect r; + // ----- + fontsize=s; + for(count=0; count<NoOfButtons; ++count) + { + font=buttons[count]->font(); + font.setPointSize(s); + buttons[count]->setFont(font); + } + QFontMetrics metrics(selectMonth->fontMetrics()); + + for (int i = 1; ; ++i) + { + QString str = KGlobal::locale()->calendar()->monthName(i, + KGlobal::locale()->calendar()->year(table->getDate()), false); + if (str.isNull()) break; + r=metrics.boundingRect(str); + maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width())); + maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height())); + } + + QSize metricBound = style().sizeFromContents(QStyle::CT_ToolButton, + selectMonth, + maxMonthRect); + selectMonth->setMinimumSize(metricBound); + + table->setFontSize(s); +} + +void +KDatePicker::setCloseButton( bool enable ) +{ + if ( enable == (d->closeButton != 0L) ) + return; + + if ( enable ) { + d->closeButton = new QToolButton( d->tb ); + d->navigationLayout->addWidget(d->closeButton); + QToolTip::add(d->closeButton, i18n("Close")); + d->closeButton->setPixmap( SmallIcon("remove") ); + connect( d->closeButton, SIGNAL( clicked() ), + topLevelWidget(), SLOT( close() ) ); + } + else { + delete d->closeButton; + d->closeButton = 0L; + } + + updateGeometry(); +} + +bool KDatePicker::hasCloseButton() const +{ + return (d->closeButton != 0L); +} + +void KDatePicker::virtual_hook( int /*id*/, void* /*data*/ ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdatepickernew.h b/microkde/kdatepickernew.h new file mode 100644 index 0000000..9ea909d --- a/dev/null +++ b/microkde/kdatepickernew.h @@ -0,0 +1,253 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KDATEPICKER_H +#define KDATEPICKER_H +#include <qdatetime.h> +#include <qframe.h> +#include <kdemacros.h> + +class QLineEdit; +class QToolButton; +class KDateValidator; +class KDateTable; + +/** + * Provides a widget for calendar date input. + * + * Different from the + * previous versions, it now emits two types of signals, either + * dateSelected() or dateEntered() (see documentation for both + * signals). + * + * A line edit has been added in the newer versions to allow the user + * to select a date directly by entering numbers like 19990101 + * or 990101. + * + * \image html kdatepicker.png "KDE Date Widget" + * + * @version $Id$ + * @author Tim Gilman, Mirko Boehm + * + * @short A date selection widget. + **/ +class KDatePicker: public QFrame +{ + Q_OBJECT + Q_PROPERTY( QDate date READ date WRITE setDate) + Q_PROPERTY( bool closeButton READ hasCloseButton WRITE setCloseButton ) + Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize ) + +public: + /** The usual constructor. The given date will be displayed + * initially. + **/ + KDatePicker(QWidget *parent=0, + QDate=QDate::currentDate(), + const char *name=0); + + /** The usual constructor. The given date will be displayed + * initially. + * @since 3.1 + **/ + KDatePicker(QWidget *parent, + QDate, + const char *name, + WFlags f); // ### KDE 4.0: Merge + + /** + * Standard qt widget constructor. The initial date will be the + * current date. + * @since 3.1 + */ + KDatePicker( QWidget *parent, const char *name ); + + /** + * The destructor. + **/ + virtual ~KDatePicker(); + + /** The size hint for date pickers. The size hint recommends the + * minimum size of the widget so that all elements may be placed + * without clipping. This sometimes looks ugly, so when using the + * size hint, try adding 28 to each of the reported numbers of + * pixels. + **/ + QSize sizeHint() const; + + /** + * Sets the date. + * + * @returns @p false and does not change anything + * if the date given is invalid. + **/ + bool setDate(const QDate&); + + /** + * Returns the selected date. + * @deprecated + **/ + const QDate& getDate() const KDE_DEPRECATED; + + /** + * @returns the selected date. + */ + const QDate &date() const; + + /** + * Enables or disables the widget. + **/ + void setEnabled(bool); + + /** + * @returns the KDateTable widget child of this KDatePicker + * widget. + * @since 3.2 + */ + KDateTable *dateTable() const { return table; }; + + /** + * Sets the font size of the widgets elements. + **/ + void setFontSize(int); + /** + * Returns the font size of the widget elements. + */ + int fontSize() const + { return fontsize; } + + /** + * By calling this method with @p enable = true, KDatePicker will show + * a little close-button in the upper button-row. Clicking the + * close-button will cause the KDatePicker's topLevelWidget()'s close() + * method being called. This is mostly useful for toplevel datepickers + * without a window manager decoration. + * @see hasCloseButton + * @since 3.1 + */ + void setCloseButton( bool enable ); + + /** + * @returns true if a KDatePicker shows a close-button. + * @see setCloseButton + * @since 3.1 + */ + bool hasCloseButton() const; + +protected: + /// to catch move keyEvents when QLineEdit has keyFocus + virtual bool eventFilter(QObject *o, QEvent *e ); + /// the resize event + virtual void resizeEvent(QResizeEvent*); + /// the year forward button + QToolButton *yearForward; + /// the year backward button + QToolButton *yearBackward; + /// the month forward button + QToolButton *monthForward; + /// the month backward button + QToolButton *monthBackward; + /// the button for selecting the month directly + QToolButton *selectMonth; + /// the button for selecting the year directly + QToolButton *selectYear; + /// the line edit to enter the date directly + QLineEdit *line; + /// the validator for the line edit: + KDateValidator *val; + /// the date table + KDateTable *table; + /// the size calculated during resize events + // QSize sizehint; + /// the widest month string in pixels: + QSize maxMonthRect; +protected slots: + void dateChangedSlot(QDate); + void tableClickedSlot(); + void monthForwardClicked(); + void monthBackwardClicked(); + void yearForwardClicked(); + void yearBackwardClicked(); + /** + * @since 3.1 + * @deprecated in 3.2 + */ + void selectWeekClicked() KDE_DEPRECATED; + /** + * @since 3.1 + */ + void selectMonthClicked(); + /** + * @since 3.1 + */ + void selectYearClicked(); + /** + * @since 3.1 + */ + void lineEnterPressed(); + /** + * @since 3.2 + */ + void todayButtonClicked(); + /** + * @since 3.2 + */ + void weekSelected(int); + +signals: + // ### KDE 4.0 Make all QDate parameters const references + + /** This signal is emitted each time the selected date is changed. + * Usually, this does not mean that the date has been entered, + * since the date also changes, for example, when another month is + * selected. + * @see dateSelected + */ + void dateChanged(QDate); + /** This signal is emitted each time a day has been selected by + * clicking on the table (hitting a day in the current month). It + * has the same meaning as dateSelected() in older versions of + * KDatePicker. + */ + void dateSelected(QDate); + /** This signal is emitted when enter is pressed and a VALID date + * has been entered before into the line edit. Connect to both + * dateEntered() and dateSelected() to receive all events where the + * user really enters a date. + */ + void dateEntered(QDate); + /** This signal is emitted when the day has been selected by + * clicking on it in the table. + */ + void tableClicked(); + +private: + /// the font size for the widget + int fontsize; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void init( const QDate &dt ); + void fillWeeksCombo(const QDate &date); + class KDatePickerPrivate; + KDatePickerPrivate *d; +}; + +#endif // KDATEPICKER_H diff --git a/microkde/kdatetbl.cpp b/microkde/kdatetbl.cpp new file mode 100644 index 0000000..0a2d1f5 --- a/dev/null +++ b/microkde/kdatetbl.cpp @@ -0,0 +1,735 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/////////////////// KDateTable widget class ////////////////////// +// +// Copyright (C) 1997 Tim D. Gilman +// (C) 1998-2001 Mirko Boehm +// Written using Qt (http://www.troll.no) for the +// KDE project (http://www.kde.org) +// +// This is a support class for the KDatePicker class. It just +// draws the calender table without titles, but could theoretically +// be used as a standalone. +// +// When a date is selected by the user, it emits a signal: +// dateSelected(QDate) + +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kapplication.h> +#include <klocale.h> +#include <kdebug.h> +#include <knotifyclient.h> +#include "kdatetbl.h" +#include <qdatetime.h> +#include <qstring.h> +#include <qpen.h> +#include <qpainter.h> +#include <qdialog.h> +#include <assert.h> +#include <qapplication.h> + +KDateValidator::KDateValidator(QWidget* parent, const char* name) + : QValidator(parent, name) +{ +} + +QValidator::State +KDateValidator::validate(QString& text, int&) const +{ + QDate temp; + // ----- everything is tested in date(): + return date(text, temp); +} + +QValidator::State +KDateValidator::date(const QString& text, QDate& d) const +{ + QDate tmp = KGlobal::locale()->readDate(text); + if (!tmp.isNull()) + { + d = tmp; + return Acceptable; + } else + return Valid; +} + +void +KDateValidator::fixup( QString& ) const +{ + +} + +KDateTable::KDateTable(QWidget *parent, QDate date_, const char* name, WFlags f) + : QGridView(parent, name, f) +{ + setFontSize(10); + if(!date_.isValid()) + { + date_=QDate::currentDate(); + } + setFocusPolicy( QWidget::StrongFocus ); + setNumRows(7); // 6 weeks max + headline + setNumCols(7); // 7 days a week + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + viewport()->setBackgroundColor(QColor(220,245,255)); +#if 0 + viewport()->setEraseColor(lightGray); +#endif + setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth +} + +void +KDateTable::paintCell(QPainter *painter, int row, int col) +{ + QRect rect; + QString text; + QPen pen; + int w=cellWidth(); + int h=cellHeight(); + int pos; + QBrush brushBlue(blue); + QBrush brushLightblue(QColor(220,245,255)); + QFont font=KGlobalSettings::generalFont(); + // ----- + font.setPointSize(fontsize); + if(row==0) + { // we are drawing the headline + font.setBold(true); + painter->setFont(font); + bool normalday = true; + QString daystr; + if (KGlobal::locale()->weekStartsMonday()) + { + daystr = KGlobal::locale()->weekDayName(col+1, true); + if (col == 5 || col == 6) + normalday = false; + } else { + daystr = KGlobal::locale()->weekDayName(col==0? 7 : col, true); + if (col == 0 || col == 6) + normalday = false; + } + if (!normalday) + { + painter->setPen(QColor(220,245,255)); + painter->setBrush(brushLightblue); + painter->drawRect(0, 0, w, h); + painter->setPen(blue); + } else { + painter->setPen(blue); + painter->setBrush(brushBlue); + painter->drawRect(0, 0, w, h); + painter->setPen(white); + } + painter->drawText(0, 0, w, h-1, AlignCenter, + daystr, -1, &rect); + painter->setPen(black); + painter->moveTo(0, h-1); + painter->lineTo(w-1, h-1); + // ----- draw the weekday: + } else { + painter->setFont(font); + pos=7*(row-1)+col; + if (KGlobal::locale()->weekStartsMonday()) + pos++; + if(pos<firstday || (firstday+numdays<=pos)) + { // we are either + // ° painting a day of the previous month or + // ° painting a day of the following month + if(pos<firstday) + { // previous month + text.setNum(numDaysPrevMonth+pos-firstday+1); + } else { // following month + text.setNum(pos-firstday-numdays+1); + } + painter->setPen(gray); + } else { // paint a day of the current month + text.setNum(pos-firstday+1); + painter->setPen(black); + } + + pen=painter->pen(); + if(firstday+date.day()-1==pos) + { + if(hasFocus()) + { // draw the currently selected date + painter->setPen(red); + painter->setBrush(darkRed); + pen=white; + } else { + painter->setPen(darkGray); + painter->setBrush(darkGray); + pen=white; + } + } else { + painter->setBrush(QColor(220,245,255)); + painter->setPen(QColor(220,245,255)); + } + painter->drawRect(0, 0, w, h); + painter->setPen(pen); + painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect); + } + if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width()); + if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height()); +} + +void +KDateTable::keyPressEvent( QKeyEvent *e ) +{ + /* + // not working properly + if ( e->key() == Qt::Key_Prior ) { + if ( date.month() == 1 ) { + KNotifyClient::beep(); + return; + } + int day = date.day(); + if ( day > 27 ) + while ( !QDate::isValid( date.year(), date.month()-1, day ) ) + day--; + setDate(QDate(date.year(), date.month()-1, day)); + return; + } + if ( e->key() == Qt::Key_Next ) { + if ( date.month() == 12 ) { + KNotifyClient::beep(); + return; + } + int day = date.day(); + if ( day > 27 ) + while ( !QDate::isValid( date.year(), date.month()+1, day ) ) + day--; + setDate(QDate(date.year(), date.month()+1, day)); + return; + } + */ + int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0; + + int temp=firstday+date.day()-dayoff; + int pos = temp; + bool irgnore = true; + if ( e->state() != Qt::ControlButton ) { + if ( e->key() == Qt::Key_Up ) { + pos -= 7; + irgnore = false; + } + if ( e->key() == Qt::Key_Down ) { + pos += 7; + irgnore = false; + } + if ( e->key() == Qt::Key_Left ) { + pos--; + irgnore = false; + } + if ( e->key() == Qt::Key_Right ) { + pos++; + irgnore = false; + } + } + if ( irgnore ) + e->ignore(); + + if(pos+dayoff<=firstday) + { // this day is in the previous month + KNotifyClient::beep(); + return; + } + if(firstday+numdays<pos+dayoff) + { // this date is in the next month + KNotifyClient::beep(i18n( "Month not long enough" )); + return; + } + + if ( pos == temp ) + return; + + setDate(QDate(date.year(), date.month(), pos-firstday+dayoff)); + updateCell(temp/7+1, temp%7); // Update the previously selected cell + updateCell(pos/7+1, pos%7); // Update the selected cell + assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid()); + + +} + +void +KDateTable::viewportResizeEvent(QResizeEvent * e) +{ + QGridView::viewportResizeEvent(e); + + setCellWidth(viewport()->width()/7); + setCellHeight(viewport()->height()/7); +} + +void +KDateTable::setFontSize(int size) +{ + int count; + QRect rect; + // ----- store rectangles: + fontsize=size; + QFont font = KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + font.setBold( true ); + QFontMetrics metrics(font); + + // ----- find largest day name: + maxCell.setWidth(0); + maxCell.setHeight(0); + for(count=0; count<7; ++count) + { + rect=metrics.boundingRect(KGlobal::locale()->weekDayName(count+1, true)); + maxCell.setWidth(QMAX(maxCell.width(), rect.width())); + maxCell.setHeight(QMAX(maxCell.height(), rect.height())); + } + // ----- compare with a real wide number and add some space: + rect=metrics.boundingRect(QString::fromLatin1("88")); + maxCell.setWidth(QMAX(maxCell.width()+2, rect.width())); + maxCell.setHeight(QMAX(maxCell.height()+4, rect.height())); + if ( maxCell.width() * 1000 / maxCell.height() > 1900 ) + maxCell.setHeight(maxCell.width() * 1000 / 1900 ); +} + +void +KDateTable::contentsMousePressEvent(QMouseEvent *e) +{ + if(e->type()!=QEvent::MouseButtonPress) + { // the KDatePicker only reacts on mouse press events: + return; + } + if(!isEnabled()) + { + KNotifyClient::beep(); + return; + } + + int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0; + // ----- + int row, col, pos, temp; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + if(row<0 || col<0) + { // the user clicked on the frame of the table + return; + } + pos=7*(row-1)+col+1; + if(pos+dayoff<=firstday) + { // this day is in the previous month + KNotifyClient::beep(); + return; + } + if(firstday+numdays<pos+dayoff) + { // this date is in the next month + KNotifyClient::beep(); + return; + } + temp=firstday+date.day()-dayoff-1; + setDate(QDate(date.year(), date.month(), pos-firstday+dayoff)); + updateCell(temp/7+1, temp%7); // Update the previously selected cell + updateCell(row, col); // Update the selected cell + // assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid()); + emit(tableClicked()); +} + +bool +KDateTable::setDate(const QDate& date_) +{ + bool changed=false; + QDate temp; + // ----- + if(!date_.isValid()) + { + kdDebug() << "KDateTable::setDate: refusing to set invalid date." << endl; + return false; + } + if(date!=date_) + { + date=date_; + changed=true; + } + temp.setYMD(date.year(), date.month(), 1); + firstday=temp.dayOfWeek(); + if(firstday==1) firstday=8; + numdays=date.daysInMonth(); + if(date.month()==1) + { // set to december of previous year + temp.setYMD(date.year()-1, 12, 1); + } else { // set to previous month + temp.setYMD(date.year(), date.month()-1, 1); + } + numDaysPrevMonth=temp.daysInMonth(); + if(changed) + { + repaintContents(false); + } + emit(dateChanged(date)); + return true; +} + +const QDate& +KDateTable::getDate() const +{ + return date; +} + +void KDateTable::focusInEvent( QFocusEvent *e ) +{ + repaintContents(false); + QGridView::focusInEvent( e ); +} + +void KDateTable::focusOutEvent( QFocusEvent *e ) +{ + repaintContents(false); + QGridView::focusOutEvent( e ); +} + +QSize +KDateTable::sizeHint() const +{ + if(maxCell.height()>0 && maxCell.width()>0) + { + return QSize((maxCell.width()+2)*numCols()+2*frameWidth(), + (maxCell.height()+4)*numRows()+2*frameWidth()); + } else { + return QSize(-1, -1); + } +} + +KDateInternalMonthPicker::KDateInternalMonthPicker +(int fontsize, QWidget* parent, const char* name) + : QGridView(parent, name), + result(0) // invalid +{ + QRect rect; + QFont font; + // ----- + activeCol = -1; + activeRow = -1; + font=KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + setFont(font); + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + setFrameStyle(QFrame::NoFrame); + setNumRows(4); + setNumCols(3); + // enable to find drawing failures: + // setTableFlags(Tbl_clipCellPainting); +#if 0 + viewport()->setEraseColor(lightGray); // for consistency with the datepicker +#endif + // ----- find the preferred size + // (this is slow, possibly, but unfortunatly it is needed here): + QFontMetrics metrics(font); + for(int i=1; i <= 12; ++i) + { + rect=metrics.boundingRect(KGlobal::locale()->monthName(i, false)); + if(max.width()<rect.width()) max.setWidth(rect.width()); + if(max.height()<rect.height()) max.setHeight(rect.height()); + } + +} + +QSize +KDateInternalMonthPicker::sizeHint() const +{ + return QSize((max.width()+6)*numCols()+2*frameWidth(), + (max.height()+6)*numRows()+2*frameWidth()); +} + +int +KDateInternalMonthPicker::getResult() const +{ + return result; +} + +void +KDateInternalMonthPicker::setupPainter(QPainter *p) +{ + p->setPen(black); +} + +void +KDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*) +{ + setCellWidth(width()/3); + setCellHeight(height()/4); +} + +void +KDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col) +{ + int index; + QString text; + // ----- find the number of the cell: + index=3*row+col+1; + text=KGlobal::locale()->monthName(index, false); + painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text); + if ( activeCol == col && activeRow == row ) + painter->drawRect( 0, 0, cellWidth(), cellHeight() ); +} + +void +KDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e) +{ + if(!isEnabled() || e->button() != LeftButton) + { + KNotifyClient::beep(); + return; + } + // ----- + int row, col; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + + if(row<0 || col<0) + { // the user clicked on the frame of the table + activeCol = -1; + activeRow = -1; + } else { + activeCol = col; + activeRow = row; + updateCell( row, col /*, false */ ); + } +} + +void +KDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e) +{ + if (e->state() & LeftButton) + { + int row, col; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + int tmpRow = -1, tmpCol = -1; + if(row<0 || col<0) + { // the user clicked on the frame of the table + if ( activeCol > -1 ) + { + tmpRow = activeRow; + tmpCol = activeCol; + } + activeCol = -1; + activeRow = -1; + } else { + bool differentCell = (activeRow != row || activeCol != col); + if ( activeCol > -1 && differentCell) + { + tmpRow = activeRow; + tmpCol = activeCol; + } + if ( differentCell) + { + activeRow = row; + activeCol = col; + updateCell( row, col /*, false */ ); // mark the new active cell + } + } + if ( tmpRow > -1 ) // repaint the former active cell + updateCell( tmpRow, tmpCol /*, true */ ); + } +} + +void +KDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e) +{ + if(!isEnabled()) + { + return; + } + // ----- + int row, col, pos; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + if(row<0 || col<0) + { // the user clicked on the frame of the table + emit(closeMe(0)); + } + pos=3*row+col+1; + result=pos; + emit(closeMe(1)); +} + + + +KDateInternalYearSelector::KDateInternalYearSelector +(int fontsize, QWidget* parent, const char* name) + : QLineEdit(parent, name), + val(new QIntValidator(this)), + result(0) +{ + QFont font; + // ----- + font=KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + setFont(font); +#if 0 + setFrameStyle(QFrame::NoFrame); +#endif + // we have to respect the limits of QDate here, I fear: + val->setRange(0, 8000); + setValidator(val); + connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot())); +} + +void +KDateInternalYearSelector::yearEnteredSlot() +{ + bool ok; + int year; + QDate date; + // ----- check if this is a valid year: + year=text().toInt(&ok); + if(!ok) + { + KNotifyClient::beep(); + return; + } + date.setYMD(year, 1, 1); + if(!date.isValid()) + { + KNotifyClient::beep(); + return; + } + result=year; + emit(closeMe(1)); +} + +int +KDateInternalYearSelector::getYear() +{ + return result; +} + +void +KDateInternalYearSelector::setYear(int year) +{ + QString temp; + // ----- + temp.setNum(year); + setText(temp); +} + +KPopupFrame::KPopupFrame(QWidget* parent, const char* name) + : QFrame(parent, name, WType_Popup), + result(0), // rejected + main(0) +{ + setFrameStyle(QFrame::Box|QFrame::Raised); + setMidLineWidth(2); +} + +void +KPopupFrame::keyPressEvent(QKeyEvent* e) +{ + if(e->key()==Key_Escape) + { + result=0; // rejected + qApp->exit_loop(); + } +} + +void +KPopupFrame::close(int r) +{ + result=r; + qApp->exit_loop(); +} + +void +KPopupFrame::setMainWidget(QWidget* m) +{ + main=m; + if(main!=0) + { + resize(main->width()+2*frameWidth(), main->height()+2*frameWidth()); + } +} + +void +KPopupFrame::resizeEvent(QResizeEvent*) +{ + if(main!=0) + { + main->setGeometry(frameWidth(), frameWidth(), + width()-2*frameWidth(), height()-2*frameWidth()); + } +} + +void +KPopupFrame::popup(const QPoint &pos) +{ + // Make sure the whole popup is visible. + QRect d = QApplication::desktop()->frameGeometry(); + int x = pos.x(); + int y = pos.y(); + int w = width(); + int h = height(); + if (x+w > d.x()+d.width()) + x = d.width() - w; + if (y+h > d.y()+d.height()) + y = d.height() - h; + if (x < d.x()) + x = 0; + if (y < d.y()) + y = 0; + + // Pop the thingy up. + move(x, y); + show(); +} + +int +KPopupFrame::exec(QPoint pos) +{ + popup(pos); + repaint(); + qApp->enter_loop(); + hide(); + return result; +} + +int +KPopupFrame::exec(int x, int y) +{ + return exec(QPoint(x, y)); +} + +void KPopupFrame::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDateTable::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//#include "kdatetbl.moc" diff --git a/microkde/kdatetbl.h b/microkde/kdatetbl.h new file mode 100644 index 0000000..df7b7ef --- a/dev/null +++ b/microkde/kdatetbl.h @@ -0,0 +1,308 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KDATETBL_H +#define KDATETBL_H + +#include <qvalidator.h> +#include <qgridview.h> +#include <qlineedit.h> +#include <qdatetime.h> + +/** +* A table containing month names. It is used to pick a month directly. +* @internal +* @version $Id$ +* @author Tim Gilman, Mirko Boehm +*/ +class KDateInternalMonthPicker : public QGridView +{ + Q_OBJECT +protected: + /** + * Store the month that has been clicked [1..12]. + */ + int result; + /** + * the cell under mouse cursor when LBM is pressed + */ + short int activeCol; + short int activeRow; + /** + * Contains the largest rectangle needed by the month names. + */ + QRect max; +signals: + /** + * This is send from the mouse click event handler. + */ + void closeMe(int); +public: + /** + * The constructor. + */ + KDateInternalMonthPicker(int fontsize, QWidget* parent, const char* name=0); + /** + * The size hint. + */ + QSize sizeHint() const; + /** + * Return the result. 0 means no selection (reject()), 1..12 are the + * months. + */ + int getResult() const; +protected: + /** + * Set up the painter. + */ + void setupPainter(QPainter *p); + /** + * The resize event. + */ + void viewportResizeEvent(QResizeEvent*); + /** + * Paint a cell. This simply draws the month names in it. + */ + virtual void paintCell(QPainter* painter, int row, int col); + /** + * Catch mouse click and move events to paint a rectangle around the item. + */ + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + /** + * Emit monthSelected(int) when a cell has been released. + */ + void contentsMouseReleaseEvent(QMouseEvent *e); + +private: + class KDateInternalMonthPrivate; + KDateInternalMonthPrivate *d; +}; + +/** Year selection widget. +* @internal +* @version $Id$ +* @author Tim Gilman, Mirko Boehm +*/ +class KDateInternalYearSelector : public QLineEdit +{ + Q_OBJECT +protected: + QIntValidator *val; + int result; +public slots: + void yearEnteredSlot(); +signals: + void closeMe(int); +public: + KDateInternalYearSelector(int fontsize, + QWidget* parent=0, + const char* name=0); + int getYear(); + void setYear(int year); + +private: + class KDateInternalYearPrivate; + KDateInternalYearPrivate *d; +}; + +/** + * Frame with popup menu behaviour. + * @author Tim Gilman, Mirko Boehm + * @version $Id$ + */ +class KPopupFrame : public QFrame +{ + Q_OBJECT +protected: + /** + * The result. It is returned from exec() when the popup window closes. + */ + int result; + /** + * Catch key press events. + */ + void keyPressEvent(QKeyEvent* e); + /** + * The only subwidget that uses the whole dialog window. + */ + QWidget *main; +public slots: + /** + * Close the popup window. This is called from the main widget, usually. + * @p r is the result returned from exec(). + */ + void close(int r); +public: + /** + * The contructor. Creates a dialog without buttons. + */ + KPopupFrame(QWidget* parent=0, const char* name=0); + /** + * Set the main widget. You cannot set the main widget from the constructor, + * since it must be a child of the frame itselfes. + * Be careful: the size is set to the main widgets size. It is up to you to + * set the main widgets correct size before setting it as the main + * widget. + */ + void setMainWidget(QWidget* m); + /** + * The resize event. Simply resizes the main widget to the whole + * widgets client size. + */ + void resizeEvent(QResizeEvent*); + /** + * Open the popup window at position pos. + */ + void popup(const QPoint &pos); + /** + * Execute the popup window. + */ + int exec(QPoint p); + /** + * Dito. + */ + int exec(int x, int y); + +private: + + virtual bool close(bool alsoDelete) { return QFrame::close(alsoDelete); } +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KPopupFramePrivate; + KPopupFramePrivate *d; +}; + +/** +* Validates user-entered dates. +*/ +class KDateValidator : public QValidator +{ +public: + KDateValidator(QWidget* parent=0, const char* name=0); + virtual State validate(QString&, int&) const; + virtual void fixup ( QString & input ) const; + State date(const QString&, QDate&) const; +}; + +/** + * Date selection table. + * This is a support class for the KDatePicker class. It just + * draws the calender table without titles, but could theoretically + * be used as a standalone. + * + * When a date is selected by the user, it emits a signal: + * dateSelected(QDate) + * + * @internal + * @version $Id$ + * @author Tim Gilman, Mirko Boehm + */ +class KDateTable : public QGridView +{ + Q_OBJECT +public: + /** + * The constructor. + */ + KDateTable(QWidget *parent=0, + QDate date=QDate::currentDate(), + const char* name=0, WFlags f=0); + /** + * Returns a recommended size for the widget. + * To save some time, the size of the largest used cell content is + * calculated in each paintCell() call, since all calculations have + * to be done there anyway. The size is stored in maxCell. The + * sizeHint() simply returns a multiple of maxCell. + */ + virtual QSize sizeHint() const; + /** + * Set the font size of the date table. + */ + void setFontSize(int size); + /** + * Select and display this date. + */ + bool setDate(const QDate&); + const QDate& getDate() const; + + +protected: + /** + * Paint a cell. + */ + virtual void paintCell(QPainter*, int, int); + /** + * Handle the resize events. + */ + virtual void viewportResizeEvent(QResizeEvent *); + /** + * React on mouse clicks that select a date. + */ + virtual void contentsMousePressEvent(QMouseEvent *); + virtual void keyPressEvent( QKeyEvent *e ); + virtual void focusInEvent( QFocusEvent *e ); + virtual void focusOutEvent( QFocusEvent *e ); + /** + * The font size of the displayed text. + */ + int fontsize; + /** + * The currently selected date. + */ + QDate date; + /** + * The day of the first day in the month [1..7]. + */ + int firstday; + /** + * The number of days in the current month. + */ + int numdays; + /** + * The number of days in the previous month. + */ + int numDaysPrevMonth; + /** + * unused + */ + bool unused_hasSelection; + /** + * Save the size of the largest used cell content. + */ + QRect maxCell; +signals: + /** + * The selected date changed. + */ + void dateChanged(QDate); + /** + * A date has been selected by clicking on the table. + */ + void tableClicked(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDateTablePrivate; + KDateTablePrivate *d; +}; + +#endif // KDATETBL_H diff --git a/microkde/kdebug.h b/microkde/kdebug.h new file mode 100644 index 0000000..bb9cfe3 --- a/dev/null +++ b/microkde/kdebug.h @@ -0,0 +1,92 @@ +#ifndef MINIKDE_KDEBUG_H +#define MINIKDE_KDEBUG_H + +#include <stdio.h> + +#include <qstring.h> + + + +class kdbgstream; +typedef kdbgstream & (*KDBGFUNC)(kdbgstream &); // manipulator function + +class kdbgstream { + public: + kdbgstream(unsigned int _area, unsigned int _level, bool _print = true) : + area(_area), level(_level), print( _print ) { print = false; } + /* kdbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print = false) : + output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print) { print = false; }*/ + ~kdbgstream() + { + // if (!output.isEmpty()) { + // fprintf(stderr,"ASSERT: debug output not ended with \\n\n"); + //*this << "\n"; + //} + } + kdbgstream &operator<<(bool) { + + return *this; + } + kdbgstream &operator<<(short) { + + return *this; + } + kdbgstream &operator<<(unsigned short) { + + return *this; + } + kdbgstream &operator<<(char) { + + return *this; + } + kdbgstream &operator<<(unsigned char) { + + return *this; + } + + kdbgstream &operator<<(int) { + + return *this; + } + kdbgstream &operator<<(unsigned int) { + + return *this; + } + kdbgstream &operator<<(long) { + return *this; + } + kdbgstream &operator<<(unsigned long) { + return *this; + } + kdbgstream &operator<<(const QString&) { + return *this; + } + kdbgstream &operator<<(const char*) { + return *this; + } + kdbgstream &operator<<(const QCString&) { + return *this; + } + kdbgstream& operator<<(KDBGFUNC f) { + return (*f)(*this); + } + kdbgstream& operator<<(double) { + if (!print) return *this; + return *this; + } + void flush() { + return; + } + private: + QString output; + unsigned int area, level; + bool print; +}; + +inline kdbgstream &endl( kdbgstream &s) { s << "\n"; return s; } + +inline kdbgstream kdDebug(int area = 0) { return kdbgstream(area, 0); } +inline kdbgstream kdWarning(int area = 0) { return kdbgstream(area, 0); } +inline kdbgstream kdError(int area = 0) { return kdbgstream(area, 0); } + +#endif diff --git a/microkde/kdecore/kcatalogue.cpp b/microkde/kdecore/kcatalogue.cpp new file mode 100644 index 0000000..97ac326 --- a/dev/null +++ b/microkde/kdecore/kcatalogue.cpp @@ -0,0 +1,131 @@ +/* This file is part of the KDE libraries + Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//US #include <config.h> + +#include <qfile.h> + +#include <kdebug.h> + +#include "kcatalogue.h" + +char *k_nl_find_msg(struct kde_loaded_l10nfile *domain_file, + const char *msgid); +void k_nl_unload_domain (struct loaded_domain *domain); + +#ifndef KDE_USE_FINAL // with --enable-final, we're getting this from libintl.cpp +struct kde_loaded_l10nfile +{ + const char *filename; + int decided; + + const void *data; + + kde_loaded_l10nfile() : filename(0), decided(0), data(0) {} +}; +#endif + +class KCataloguePrivate +{ +public: + QString name; + + kde_loaded_l10nfile domain; +}; + +KCatalogue::KCatalogue(const QString & name) + : d( new KCataloguePrivate ) +{ + d->name = name; +} + +KCatalogue::KCatalogue(const KCatalogue & rhs) + : d( new KCataloguePrivate ) +{ + *this = rhs; +} + +KCatalogue & KCatalogue::operator=(const KCatalogue & rhs) +{ + d->name = rhs.d->name; + setFileName( rhs.fileName() ); + + return *this; +} + +KCatalogue::~KCatalogue() +{ + doUnload(); + + delete d; +} + +QString KCatalogue::name() const +{ + return d->name; +} + +void KCatalogue::setFileName( const QString & fileName ) +{ + // nothing to do if the file name is already the same + if ( this->fileName() == fileName ) return; + + doUnload(); + + QCString newFileName = QFile::encodeName( fileName ); + + if ( !fileName.isEmpty() ) + { + // set file name + char *filename = new char[ newFileName.length() + 1 ]; + ::qstrcpy( filename, newFileName ); + d->domain.filename = filename; + } +} + +QString KCatalogue::fileName() const +{ + return QFile::decodeName( d->domain.filename ); +} + +const char * KCatalogue::translate(const char * msgid) const +{ + qDebug("KCatalogue::translate has to be fixed %s",msgid ); +//US return ::k_nl_find_msg( &d->domain, msgid ); + return msgid; + +} + +void KCatalogue::doUnload() +{ + // use gettext's unloader + if ( d->domain.data ) + { +//US ::k_nl_unload_domain( (struct loaded_domain *)d->domain.data ); + qDebug("KCatalogue::doUnload has to be fixed" ); + + } + d->domain.data = 0; + + // free name + delete [] const_cast<char *>(d->domain.filename); + d->domain.filename = 0; + + d->domain.decided = 0; +} diff --git a/microkde/kdecore/kcatalogue.h b/microkde/kdecore/kcatalogue.h new file mode 100644 index 0000000..e229cc8 --- a/dev/null +++ b/microkde/kdecore/kcatalogue.h @@ -0,0 +1,104 @@ +/* This file is part of the KDE libraries + Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCATALOGUE_H +#define KCATALOGUE_H + +#include <qstring.h> + +struct kde_loaded_l10nfile; + +class KCataloguePrivate; + +/** + * This class abstracts a gettext message catalogue. It will take care of + * opening the file and reading the catalogue. + * + * @see KLocale + */ +//REVISED: hausmann +class KCatalogue +{ +public: + /** + * Constructor. + * + * @param name The name of the catalogue + */ + explicit KCatalogue(const QString & name = QString::null); + + /** + * Copy constructor. + */ + KCatalogue(const KCatalogue & rhs); + + /** + * Assignment operator. + */ + KCatalogue & operator = ( const KCatalogue & rhs); + + /** + * Destructor. + */ + virtual ~KCatalogue(); + + /** + * Returns the name of the catalogue. + * + * @return The name of the catalogue + */ + QString name() const; + + /** + * Changes the current file name. + * + * @param fileName The new file name + */ + + void setFileName( const QString & fileName ); + + /** + * Retrieves a translation of the specified message id. + * + * Do not pass 0 or "" strings as message ids. + * + * @param msgid The message id + * + * @return The translated message, in utf8 encoding, or 0 if not found + */ + const char * translate( const char * msgid ) const; + +private: + /** + * @internal Retrieves the current file name. + * + * @return The current file name, if any. + */ + QString fileName() const; + + /** + * @internal Unloads the current file. + */ + void doUnload(); + +private: + KCataloguePrivate * d; +}; + +#endif diff --git a/microkde/kdecore/kconfigbase.h b/microkde/kdecore/kconfigbase.h new file mode 100644 index 0000000..7e56d11 --- a/dev/null +++ b/microkde/kdecore/kconfigbase.h @@ -0,0 +1,102 @@ +/* + This file is part of the KDE libraries + Copyright (c) 1999 Preston Brown <pbrown@kde.org> + Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org> + Copyright (c) 2001 Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ + +#ifndef _KCONFIGBASE_H +#define _KCONFIGBASE_H + +#include "kconfig.h" + +/** + * Helper class to facilitate working with @ref KConfig / @ref KSimpleConfig + * groups. + * + * Careful programmers always set the group of a + * @ref KConfig @ref KSimpleConfig object to the group they want to read from + * and set it back to the old one of afterwards. This is usually + * written as: + * <pre> + * + * QString oldgroup config->group(); + * config->setGroup( "TheGroupThatIWant" ); + * ... + * config->writeEntry( "Blah", "Blubb" ); + * + * config->setGroup( oldgroup ); + * </pre> + * + * In order to facilitate this task, you can use + * KConfigGroupSaver. Simply construct such an object ON THE STACK + * when you want to switch to a new group. Then, when the object goes + * out of scope, the group will automatically be restored. If you + * want to use several different groups within a function or method, + * you can still use KConfigGroupSaver: Simply enclose all work with + * one group (including the creation of the KConfigGroupSaver object) + * in one block. + * + * @author Matthias Kalle Dalheimer <kalle@kde.org> + * @version $Id$ + * @see KConfigBase, KConfig, KSimpleConfig + * @short Helper class for easier use of KConfig/KSimpleConfig groups + */ +//US I converted the class in a way that it can be used with KConfig objects of microkde + +class KConfigGroupSaver +{ +public: + /** + * Constructor. You pass a pointer to the KConfigBase-derived + * object you want to work with and a string indicating the _new_ + * group. + * + * @param config The KConfigBase-derived object this + * KConfigGroupSaver works on. + * @param group The new group that the config object should switch to. + */ + KConfigGroupSaver( KConfig* config, QString group ) + /* KDE 4 : make the second parameter const QString & */ + : _config(config), _oldgroup(config->group()) + { _config->setGroup( group ); } + + KConfigGroupSaver( KConfig* config, const char *group ) + : _config(config), _oldgroup(config->group()) + { _config->setGroup( group ); } + + KConfigGroupSaver( KConfig* config, const QCString &group ) + : _config(config), _oldgroup(config->group()) + { _config->setGroup( group ); } + + ~KConfigGroupSaver() { _config->setGroup( _oldgroup ); } + + KConfig* config() { return _config; }; + +private: + KConfig* _config; + QString _oldgroup; + + KConfigGroupSaver(const KConfigGroupSaver&); + KConfigGroupSaver& operator=(const KConfigGroupSaver&); + +}; + +#endif diff --git a/microkde/kdecore/klibloader.cpp b/microkde/kdecore/klibloader.cpp new file mode 100644 index 0000000..1410308 --- a/dev/null +++ b/microkde/kdecore/klibloader.cpp @@ -0,0 +1,626 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Torben Weis <weis@kde.org> + Copyright (C) 2000 Michael Matz <matz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//US #include <config.h> +#include <qclipboard.h> +#include <qfile.h> +#include <qtimer.h> +#include <qobjectdict.h> +#include <qwidgetlist.h> +#include <qwidget.h> + +#include "kapplication.h" +#include "klibloader.h" +#include "kstandarddirs.h" +#include "kdebug.h" +#include "klocale.h" + +//US #include "ltdl.h" + +//US do everything through qlibrary +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#include <qtopia/qlibrary.h> +#endif + +/*US +#ifdef Q_WS_X11 +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#endif +*/ +template class QAsciiDict<KLibrary>; + +#include <stdlib.h> //getenv + +/*US +#if HAVE_DLFCN_H +# include <dlfcn.h> +#endif + +#ifdef RTLD_GLOBAL +# define LT_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_GLOBAL DL_GLOBAL +# endif +#endif +#ifndef LT_GLOBAL +# define LT_GLOBAL 0 +#endif +*/ + +/*US +extern "C" { +extern int lt_dlopen_flag; +} +*/ + +KLibFactory::KLibFactory( QObject* parent, const char* name ) + : QObject( parent, name ) +{ +} + +KLibFactory::~KLibFactory() +{ +// kdDebug(150) << "Deleting KLibFactory " << this << endl; +} + +QObject* KLibFactory::create( QObject* parent, const char* name, const char* classname, const QStringList &args ) +{ + QObject* obj = createObject( parent, name, classname, args ); + if ( obj ) + emit objectCreated( obj ); + return obj; +} + + +QObject* KLibFactory::createObject( QObject*, const char*, const char*, const QStringList &) +{ + return 0; +} + + +// ----------------------------------------------- + +//US KLibrary::KLibrary( const QString& libname, const QString& filename, void * handle ) +KLibrary::KLibrary( const QString& libname, const QString& filename, QLibrary* handle ) +{ + /* Make sure, we have a KLibLoader */ + (void) KLibLoader::self(); + m_libname = libname; + m_filename = filename; + m_handle = handle; + m_factory = 0; + m_timer = 0; +} + +KLibrary::~KLibrary() +{ +// kdDebug(150) << "Deleting KLibrary " << this << " " << m_libname << endl; + if ( m_timer && m_timer->isActive() ) + m_timer->stop(); + + // If any object is remaining, delete + if ( m_objs.count() > 0 ) + { + QPtrListIterator<QObject> it( m_objs ); + for ( ; it.current() ; ++it ) + { + kdDebug(150) << "Factory still has object " << it.current() << " " << it.current()->name () << " Library = " << m_libname << endl; + disconnect( it.current(), SIGNAL( destroyed() ), + this, SLOT( slotObjectDestroyed() ) ); + } + m_objs.setAutoDelete(true); + m_objs.clear(); + } + + if ( m_factory ) { +// kdDebug(150) << " ... deleting the factory " << m_factory << endl; + delete m_factory; + } +} + +QString KLibrary::name() const +{ + return m_libname; +} + +QString KLibrary::fileName() const +{ + return m_filename; +} + +KLibFactory* KLibrary::factory() +{ + if ( m_factory ) + return m_factory; + + QCString symname; + symname.sprintf("init_%s", name().latin1() ); + + void* sym = symbol( symname ); + if ( !sym ) + { + kdWarning(150) << "KLibrary: The library " << name() << " does not offer an init_" << name() << " function" << endl; + return 0; + } + + typedef KLibFactory* (*t_func)(); + t_func func = (t_func)sym; + m_factory = func(); + + if( !m_factory ) + { + kdWarning(150) << "KLibrary: The library " << name() << " does not offer a KDE compatible factory" << endl; + return 0; + } + + connect( m_factory, SIGNAL( objectCreated( QObject * ) ), + this, SLOT( slotObjectCreated( QObject * ) ) ); + + return m_factory; +} + +void* KLibrary::symbol( const char* symname ) const +{ +//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); + void* sym = m_handle->resolve( symname ); + if ( !sym ) + { +//US kdWarning(150) << "KLibrary: " << lt_dlerror() << endl; + kdWarning(150) << "KLibrary: " << m_libname << ", symbol:" << symname << " not found " << endl; + return 0; + } + + return sym; +} + +bool KLibrary::hasSymbol( const char* symname ) const +{ +//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); + void* sym = m_handle->resolve( symname ); + return (sym != 0L ); +} + +void KLibrary::unload() const +{ + if (KLibLoader::s_self) + KLibLoader::s_self->unloadLibrary(QFile::encodeName(name())); +} + +void KLibrary::slotObjectCreated( QObject *obj ) +{ + if ( !obj ) + return; + + if ( m_timer && m_timer->isActive() ) + m_timer->stop(); + + if ( m_objs.containsRef( obj ) ) + return; // we know this object already + + connect( obj, SIGNAL( destroyed() ), + this, SLOT( slotObjectDestroyed() ) ); + + m_objs.append( obj ); +} + +void KLibrary::slotObjectDestroyed() +{ + m_objs.removeRef( sender() ); + + if ( m_objs.count() == 0 ) + { +// kdDebug(150) << "KLibrary: shutdown timer for " << name() << " started!" +// << endl; + + if ( !m_timer ) + { + m_timer = new QTimer( this, "klibrary_shutdown_timer" ); + connect( m_timer, SIGNAL( timeout() ), + this, SLOT( slotTimeout() ) ); + } + + // as long as it's not stable make the timeout short, for debugging + // pleasure (matz) + //m_timer->start( 1000*60, true ); + m_timer->start( 1000*10, true ); + } +} + +void KLibrary::slotTimeout() +{ + if ( m_objs.count() != 0 ) + return; + + /* Don't go through KLibLoader::unloadLibrary(), because that uses the + ref counter, but this timeout means to unconditionally close this library + The destroyed() signal will take care to remove us from all lists. + */ + delete this; +} + +// ------------------------------------------------- + +/* This helper class is needed, because KLibraries can go away without + being unloaded. So we need some info about KLibraries even after its + death. */ +class KLibWrapPrivate +{ +public: +//US KLibWrapPrivate(KLibrary *l, lt_dlhandle h); + KLibWrapPrivate(KLibrary *l, QLibrary* h); + + KLibrary *lib; + enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; + int ref_count; +//US lt_dlhandle handle; + QLibrary *handle; + QString name; + QString filename; +}; + +//US KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, lt_dlhandle h) +KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, QLibrary* h) + : lib(l), ref_count(1), handle(h), name(l->name()), filename(l->fileName()) +{ + unload_mode = UNKNOWN; +/*US + if (lt_dlsym(handle, "__kde_do_not_unload") != 0) { +// kdDebug(150) << "Will not unload " << name << endl; + unload_mode = DONT_UNLOAD; + } else if (lt_dlsym(handle, "__kde_do_unload") != 0) { + unload_mode = UNLOAD; + } +*/ +//US use instead: + if (h->resolve("__kde_do_not_unload") != 0) { +// kdDebug(150) << "Will not unload " << name << endl; + unload_mode = DONT_UNLOAD; + } else if (h->resolve("__kde_do_unload") != 0) { + unload_mode = UNLOAD; + } +} + +class KLibLoaderPrivate +{ +public: + QPtrList<KLibWrapPrivate> loaded_stack; + QPtrList<KLibWrapPrivate> pending_close; + enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; + + QString errorMessage; +}; + +KLibLoader* KLibLoader::s_self = 0; + +KLibLoader* KLibLoader::self() +{ + if ( !s_self ) + s_self = new KLibLoader; + return s_self; +} + +void KLibLoader::cleanUp() +{ + if ( !s_self ) + return; + + delete s_self; + s_self = 0; +} + +KLibLoader::KLibLoader( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + s_self = this; + d = new KLibLoaderPrivate; +//US lt_dlinit(); + d->unload_mode = KLibLoaderPrivate::UNKNOWN; + if (getenv("KDE_NOUNLOAD") != 0) + d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD; + else if (getenv("KDE_DOUNLOAD") != 0) + d->unload_mode = KLibLoaderPrivate::UNLOAD; + d->loaded_stack.setAutoDelete( true ); +} + +KLibLoader::~KLibLoader() +{ +// kdDebug(150) << "Deleting KLibLoader " << this << " " << name() << endl; + + QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); + for (; it.current(); ++it ) + { + kdDebug(150) << "The KLibLoader contains the library " << it.current()->name + << " (" << it.current()->lib << ")" << endl; + d->pending_close.append(it.current()); + } + + close_pending(0); + + delete d; +} + +//static +QString KLibLoader::findLibrary( const char * name/*US , const KInstance * instance*/ ) +{ + QCString libname( name ); + + // only append ".la" if there is no extension + // this allows to load non-libtool libraries as well + // (mhk, 20000228) + int pos = libname.findRev('/'); + if (pos < 0) + pos = 0; + if (libname.find('.', pos) < 0) + libname += ".la"; + + // only look up the file if it is not an absolute filename + // (mhk, 20000228) + QString libfile; + if (libname[0] == '/') + libfile = libname; + else + { +//US libfile = instance->dirs()->findResource( "module", libname ); + libfile = KGlobal::dirs()->findResource( "module", libname ); + if ( libfile.isEmpty() ) + { +//US libfile = instance->dirs()->findResource( "lib", libname ); + libfile = KGlobal::dirs()->findResource( "lib", libname ); +#ifndef NDEBUG + if ( !libfile.isEmpty() && libname.left(3) == "lib" ) // don't warn for kdeinit modules + kdDebug(150) << "library " << libname << " not found under 'module' but under 'lib'" << endl; +#endif + } + if ( libfile.isEmpty() ) + { +#ifndef NDEBUG + kdDebug(150) << "library=" << libname << ": No file names " << libname.data() << " found in paths." << endl; +#endif + self()->d->errorMessage = i18n("Library files for \"%1\" not found in paths").arg(libname); + } + else + self()->d->errorMessage = QString::null; + } + return libfile; +} + + +KLibrary* KLibLoader::globalLibrary( const char *name ) +{ +KLibrary *tmp; +/*US +int olt_dlopen_flag = lt_dlopen_flag; + + lt_dlopen_flag |= LT_GLOBAL; + kdDebug(150) << "Loading the next library global with flag " + << lt_dlopen_flag + << "." << endl; +*/ + tmp = library(name); +/*US + lt_dlopen_flag = olt_dlopen_flag; +*/ +return tmp; +} + + +KLibrary* KLibLoader::library( const char *name ) +{ + if (!name) + return 0; + + KLibWrapPrivate* wrap = m_libs[name]; + if (wrap) { + /* Nothing to do to load the library. */ + wrap->ref_count++; + return wrap->lib; + } + + /* Test if this library was loaded at some time, but got + unloaded meanwhile, whithout being dlclose()'ed. */ + QPtrListIterator<KLibWrapPrivate> it(d->loaded_stack); + for (; it.current(); ++it) { + if (it.current()->name == name) + wrap = it.current(); + } + + if (wrap) { + d->pending_close.removeRef(wrap); + if (!wrap->lib) { + /* This lib only was in loaded_stack, but not in m_libs. */ + wrap->lib = new KLibrary( name, wrap->filename, wrap->handle ); + } + wrap->ref_count++; + } else { + QString libfile = findLibrary( name ); + if ( libfile.isEmpty() ) + return 0; + + const QString & qpeDir = QPEApplication::qpeDir(); + libfile = qpeDir + libfile; +//US QLibrary *lib = new QLibrary( qpeDir + "/plugins/korganizer/libopiekabc.so", QLibrary::Immediately ); + QLibrary *qlib = new QLibrary( libfile.latin1(), QLibrary::Immediately ); + +//US lt_dlhandle handle = lt_dlopen( libfile.latin1() ); +//US if ( !handle ) + if ( !qlib ) + { +//US const char* errmsg = lt_dlerror(); + char* errmsg; + sprintf(errmsg, "KLibLoader::library could not load library: %s", libfile.latin1()); + qDebug(errmsg); + + if(errmsg) + d->errorMessage = QString::fromLatin1(errmsg); + else + d->errorMessage = QString::null; + kdWarning(150) << "library=" << name << ": file=" << libfile << ": " << d->errorMessage << endl; + return 0; + } + else + d->errorMessage = QString::null; + + KLibrary *lib = new KLibrary( name, libfile, qlib ); + wrap = new KLibWrapPrivate(lib, qlib); + d->loaded_stack.prepend(wrap); + } + m_libs.insert( name, wrap ); + + connect( wrap->lib, SIGNAL( destroyed() ), + this, SLOT( slotLibraryDestroyed() ) ); + + return wrap->lib; +} + +QString KLibLoader::lastErrorMessage() const +{ + return d->errorMessage; +} + +void KLibLoader::unloadLibrary( const char *libname ) +{ + KLibWrapPrivate *wrap = m_libs[ libname ]; + if (!wrap) + return; + if (--wrap->ref_count) + return; + +// kdDebug(150) << "closing library " << libname << endl; + + m_libs.remove( libname ); + + disconnect( wrap->lib, SIGNAL( destroyed() ), + this, SLOT( slotLibraryDestroyed() ) ); + close_pending( wrap ); +} + +KLibFactory* KLibLoader::factory( const char* name ) +{ + KLibrary* lib = library( name ); + if ( !lib ) + return 0; + + return lib->factory(); +} + +void KLibLoader::slotLibraryDestroyed() +{ + const KLibrary *lib = static_cast<const KLibrary *>( sender() ); + + QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); + for (; it.current(); ++it ) + if ( it.current()->lib == lib ) + { + KLibWrapPrivate *wrap = it.current(); + wrap->lib = 0; /* the KLibrary object is already away */ + m_libs.remove( it.currentKey() ); + close_pending( wrap ); + return; + } +} + +void KLibLoader::close_pending(KLibWrapPrivate *wrap) +{ + if (wrap && !d->pending_close.containsRef( wrap )) + d->pending_close.append( wrap ); + + /* First delete all KLibrary objects in pending_close, but _don't_ unload + the DSO behind it. */ + QPtrListIterator<KLibWrapPrivate> it(d->pending_close); + for (; it.current(); ++it) { + wrap = it.current(); + if (wrap->lib) { + disconnect( wrap->lib, SIGNAL( destroyed() ), + this, SLOT( slotLibraryDestroyed() ) ); + delete wrap->lib; + wrap->lib = 0; + } + } + + if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) return; + + bool deleted_one = false; + while ((wrap = d->loaded_stack.first())) { + /* Let's first see, if we want to try to unload this lib. + If the env. var KDE_DOUNLOAD is set, we try to unload every lib. + If not, we look at the lib itself, and unload it only, if it exports + the symbol __kde_do_unload. */ + if (d->unload_mode != KLibLoaderPrivate::UNLOAD + && wrap->unload_mode != KLibWrapPrivate::UNLOAD) + break; + + /* Now ensure, that the libs are only unloaded in the reverse direction + they were loaded. */ + if (!d->pending_close.containsRef( wrap )) { + if (!deleted_one) + /* Only diagnose, if we really haven't deleted anything. */ +// kdDebug(150) << "try to dlclose " << wrap->name << ": not yet" << endl; + break; + } + +// kdDebug(150) << "try to dlclose " << wrap->name << ": yes, done." << endl; + +#ifndef Q_WS_QWS + if ( !deleted_one ) { + /* Only do the hack once in this loop. + WABA: *HACK* + We need to make sure to clear the clipboard before unloading a DSO + because the DSO could have defined an object derived from QMimeSource + and placed that on the clipboard. */ + /*kapp->clipboard()->clear();*/ + + /* Well.. let's do something more subtle... convert the clipboard context + to text. That should be safe as it only uses objects defined by Qt. */ + + QWidgetList *widgetlist = QApplication::topLevelWidgets(); + QWidget *co = widgetlist->first(); + while (co) { + if (qstrcmp(co->name(), "internal clipboard owner") == 0) { + if (XGetSelectionOwner(co->x11Display(), XA_PRIMARY) == co->winId()) + kapp->clipboard()->setText(kapp->clipboard()->text()); + + break; + } + co = widgetlist->next(); + } + delete widgetlist; + } +#else + // FIXME(E): Implement in Qt Embedded +#endif + + deleted_one = true; +//US lt_dlclose(wrap->handle); + wrap->handle->unload(); + + d->pending_close.removeRef(wrap); + /* loaded_stack is AutoDelete, so wrap is freed */ + d->loaded_stack.remove(); + } +} + +void KLibLoader::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KLibFactory::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klibloader.moc" diff --git a/microkde/kdecore/klibloader.h b/microkde/kdecore/klibloader.h new file mode 100644 index 0000000..ed57109 --- a/dev/null +++ b/microkde/kdecore/klibloader.h @@ -0,0 +1,405 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Torben Weis <weis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLIBLOADER_H +#define KLIBLOADER_H + +#include <qobject.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qasciidict.h> +#include <qptrlist.h> +#include <kglobal.h> + +#include <stdlib.h> // For backwards compatibility + +class KInstance; +class QTimer; +class KLibrary; +class KLibFactory; +class KLibFactoryPrivate; +class KLibLoaderPrivate; +class KLibraryPrivate; + +class QLibrary; + +#define K_EXPORT_COMPONENT_FACTORY( libname, factory ) \ + extern "C" { void *init_##libname() { return new factory; } } + +/** + * @short Represents a dynamically loaded library. + * + * KLibrary allows you to look up symbols of the shared library. + * Use @ref KLibLoader to create a new instance of KLibrary. + * + * @see KLibLoader + * @author Torben Weis <weis@kde.org> + */ +class KLibrary : public QObject +{ + friend class KLibLoader; + friend class QAsciiDict<KLibrary>; + + Q_OBJECT +public: + /** + * @internal + * Don't create KLibrary objects on your own. Instead use @ref KLibLoader. + */ +//US KLibrary( const QString& libname, const QString& filename, void * handle ); + KLibrary( const QString& libname, const QString& filename, QLibrary* handle ); + + /** + * Returns the name of the library. + * @return The name of the library like "libkspread". + */ + QString name() const; + + /** + * Returns the file name of the library. + * @return The filename of the library, for example "/opt/kde2&/lib/libkspread.la" + */ + QString fileName() const; + + /** + * Returns the factory of the library. + * @return The factory of the library if there is any, otherwise 0 + */ + KLibFactory* factory(); + + /** + * Looks up a symbol from the library. This is a very low level + * function that you usually don't want to use. Usually you should + * check using @ref hasSymbol() whether the symbol actually exists, + * otherwise a warning will be printed. + * @param name the name of the symbol to look up + * @return the address of the symbol, or 0 if it does not exist + * @see #hasSymbol + */ + void* symbol( const char* name ) const; + + /** + * Looks up a symbol from the library. This is a very low level + * function that you usually don't want to use. + * Unlike @ref symbol(), this method doesn't warn if the symbol doesn't exist, + * so if the symbol might or might not exist, better use hasSymbol() before symbol(). + * @param name the name of the symbol to check + * @return true if the symbol exists + * @since 3.1 + */ + bool hasSymbol( const char* name ) const; + + /** + * Unloads the library. + * This typically results in the deletion of this object. You should + * not reference its pointer after calling this function. + */ + void unload() const; + +private slots: + void slotObjectCreated( QObject *obj ); + void slotObjectDestroyed(); + void slotTimeout(); + +private: + /** + * @internal + * Don't destruct KLibrary objects yourself. Instead use @ref unload() instead. + */ + ~KLibrary(); + + QString m_libname; + QString m_filename; + KLibFactory* m_factory; +//US void * m_handle; + QLibrary* m_handle; + QPtrList<QObject> m_objs; + QTimer *m_timer; + KLibraryPrivate *d; +}; + +class KLibWrapPrivate; + +/** + * The KLibLoader allows you to load libraries dynamically at runtime. + * Dependent libraries are loaded automatically. + * + * KLibLoader follows the singleton pattern. You can not create multiple + * instances. Use @ref self() to get a pointer to the loader. + * + * @see KLibrary + * @author Torben Weis <weis@kde.org> + */ +class KLibLoader : public QObject +{ + friend class KLibrary; + + Q_OBJECT +public: + /** + * You should NEVER destruct an instance of KLibLoader + * until you know what you are doing. This will release + * the loaded libraries. + */ + ~KLibLoader(); + + /** + * Loads and initializes a library. Loading a library multiple times is + * handled gracefully. + * + * This is a convenience function that returns the factory immediately + * @param libname This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + * @return the @ref KLibFactory, or 0 if the library does not exist or it does + * not have a factory + * @see #library + */ + KLibFactory* factory( const char* libname ); + + /** + * Loads and initializes a library. Loading a library multiple times is + * handled gracefully. + * + * @param libname This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + * @return @ref KLibrary is invalid (0) when the library couldn't be dlopened. in such + * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage() + * + * @see #factory + */ + virtual KLibrary* library( const char* libname ); + + /** + * Loads and initializes a library. Loading a library multiple times is + * handled gracefully. The library is loaded such that the symbols are + * globally accessible so libraries with dependencies can be loaded + * sequentially. + * + * @param name This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + * @return KLibrariy is invalid (0) when the library couldn't be dlopened. in such + * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage() + * + * @see #factory + */ + KLibrary* globalLibrary( const char *name ); + + /* + * Returns an error message that can be useful to debug the problem. + * Returns QString::null if the last call to @ref #library() was successful. + * You can call this function more than once. The error message is only + * reset by a new call to library(). + * @return the last error message, or QString::null if there was no error + */ + QString lastErrorMessage() const; + + /** + * Unloads the library with the given name. + * @param libname This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + */ + virtual void unloadLibrary( const char *libname ); + + /** + * Returns a pointer to the factory. Use this function to get an instance + * of KLibLoader. + * @return a pointer to the loader. If no loader exists until now + * then one is created. + */ + static KLibLoader* self(); + + /** + * @internal + * Internal Method, called by the KApplication destructor. + * Do not call it. + * This is what makes it possible to rely on ~KLibFactory + * being called in all cases, whether the library is unloaded + * while the application is running or when exiting. + */ + static void cleanUp(); + + /** + * Helper method which looks for a library in the standard paths + * ("module" and "lib" resources). + * Made public for code that doesn't use KLibLoader itself, but still + * wants to open modules. + * @param name of the library. If it is not a path, the function searches in + * the "module" and "lib" resources. If there is no extension, + * ".la" will be appended. + * @param instance a KInstance used to get the standard paths + */ + static QString findLibrary( const char * name/*US , const KInstance * instance = KGlobal::instance()*/ ); + +protected: + KLibLoader( QObject* parent = 0, const char* name = 0 ); + +private slots: + void slotLibraryDestroyed(); +private: + void close_pending( KLibWrapPrivate * ); + QAsciiDict<KLibWrapPrivate> m_libs; + + static KLibLoader* s_self; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KLibLoaderPrivate *d; +}; + +/** + * If you develop a library that is to be loaded dynamically at runtime, then + * you should return a pointer to your factory. The K_EXPORT_COMPONENT_FACTORY + * macro is provided for this purpose: + * <pre> + * K_EXPORT_COMPONENT_FACTORY( libkspread, KSpreadFactory ) + * </pre> + * + * The first macro argument is the name of your library, the second specifies the name + * of your factory. + * + * In the constructor of your factory you should create an instance of @ref KInstance + * like this: + * <pre> + * s_global = new KInstance( "kspread" ); + * </pre> + * This @ref KInstance is comparable to @ref KGlobal used by normal applications. + * It allows you to find resource files (images, XML, sound etc.) belonging + * to the library. + * + * If you want to load a library, use @ref KLibLoader. You can query @ref KLibLoader + * directly for a pointer to the libraries factory by using the @ref KLibLoader::factory() + * function. + * + * The KLibFactory is used to create the components, the library has to offer. + * The factory of KSpread for example will create instances of KSpreadDoc, + * while the Konqueror factory will create KonqView widgets. + * All objects created by the factory must be derived from @ref QObject, since @ref QObject + * offers type safe casting. + * + * KLibFactory is an abstract class. Reimplement the @ref + * createObject() method to give it functionality. + * + * @author Torben Weis <weis@kde.org> + */ +class KLibFactory : public QObject +{ + Q_OBJECT +public: + /** + * Create a new factory. + * @param parent the parent of the QObject, 0 for no parent + * @param name the name of the QObject, 0 for no name + */ + KLibFactory( QObject* parent = 0, const char* name = 0 ); + virtual ~KLibFactory(); + + /** + * Creates a new object. The returned object has to be derived from + * the requested classname. + * + * It is valid behavior to create different kinds of objects + * depending on the requested @p classname. For example a koffice + * library may usually return a pointer to KoDocument. But + * if asked for a "QWidget", it could create a wrapper widget, + * that encapsulates the Koffice specific features. + * + * create() automatically emits a signal @ref objectCreated to tell + * the library about its newly created object. This is very + * important for reference counting, and allows unloading the + * library automatically once all its objects have been destroyed. + * + * @param parent the parent of the QObject, 0 for no parent + * @param name the name of the QObject, 0 for no name + * @param classname the name of the class + * @param args a list of arguments + */ + + QObject* create( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() ); + +signals: + /** + * Emitted in #create + * @param obj the new object + */ + void objectCreated( QObject *obj ); + + +protected: + + /** + * Creates a new object. The returned object has to be derived from + * the requested classname. + * + * It is valid behavior to create different kinds of objects + * depending on the requested @p classname. For example a koffice + * library may usually return a pointer to KoDocument. But + * if asked for a "QWidget", it could create a wrapper widget, + * that encapsulates the Koffice specific features. + * + * This function is called by #create() + * @param parent the parent of the QObject, 0 for no parent + * @param name the name of the QObject, 0 for no name + * @param classname the name of the class + * @param args a list of arguments + */ + virtual QObject* createObject( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() ) = 0; + + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KLibFactoryPrivate *d; +}; + +#endif diff --git a/microkde/kdecore/klocale.cpp b/microkde/kdecore/klocale.cpp new file mode 100644 index 0000000..d77e251 --- a/dev/null +++ b/microkde/kdecore/klocale.cpp @@ -0,0 +1,881 @@ +#include <qregexp.h> +#include <qapplication.h> + +#include "kdebug.h" +#include "kcalendarsystemgregorian.h" + +#include "klocale.h" + + +QDict<QString> *mLocaleDict = 0; +void setLocaleDict( QDict<QString> * dict ) +{ + mLocaleDict = dict; + +} +QString i18n(const char *text) +{ + if ( ! mLocaleDict ) + return QString( text ); + else { + QString* ret = mLocaleDict->find(QString(text)) ; + if ( ret == 0 ) { + return QString( text ); + } + else { + if ( (*ret).isEmpty() ) + return QString( text ); + else + return (*ret); + } + } + +} + +QString i18n(const char *,const char *text) +{ + return i18n( text ); +} + +QString i18n(const char *text1, const char *textn, int num) +{ + if ( num == 1 ) return i18n( text1 ); + else { + QString text = i18n( textn ); + int pos = text.find( "%n" ); + if ( pos >= 0 ) text.replace( pos, 2, QString::number( num ) ); + return text; + } +} + +inline void put_it_in( QChar *buffer, uint& index, const QString &s ) +{ + for ( uint l = 0; l < s.length(); l++ ) + buffer[index++] = s.at( l ); +} + +inline void put_it_in( QChar *buffer, uint& index, int number ) +{ + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; +} + +static int readInt(const QString &str, uint &pos) +{ + if (!str.at(pos).isDigit()) return -1; + int result = 0; + for (; str.length() > pos && str.at(pos).isDigit(); pos++) + { + result *= 10; + result += str.at(pos).digitValue(); + } + + return result; +} + +KLocale::KLocale() : mCalendarSystem( 0 ) +{ + + m_decimalSymbol = "."; + m_positiveSign = ""; + m_negativeSign = "-"; + m_thousandsSeparator = ","; + + + + + mWeekStartsMonday = true; + mHourF24Format = true; + mIntDateFormat = 0; + mLanguage = 0; + mDateFormat = "%a %Y %b %d"; + mDateFormatShort = "%Y-%m-%d"; + mTimeZoneList << i18n ("-11:00 US/Samoa") + << i18n ("-10:00 US/Hawaii") + << i18n ("-09:00 US/Alaska") + << i18n ("-08:00 US/Pacific") + << i18n ("-07:00 US/Mountain") + << i18n ("-06:00 US/Central") + << i18n ("-05:00 US/Eastern") + << i18n ("-04:00 Brazil/West") + << i18n ("-03:00 Brazil/East") + << i18n ("-02:00 Brazil/DeNoronha") + << i18n ("-01:00 Atlantic/Azores") + << i18n (" 00:00 Europe/London(UTC)") + << i18n ("+01:00 Europe/Oslo(CET)") + << i18n ("+02:00 Europe/Helsinki") + << i18n ("+03:00 Europe/Moscow") + << i18n ("+04:00 Indian/Mauritius") + << i18n ("+05:00 Indian/Maldives") + << i18n ("+06:00 Indian/Chagos") + << i18n ("+07:00 Asia/Bangkok") + << i18n ("+08:00 Asia/Hongkong") + << i18n ("+09:00 Asia/Tokyo") + << i18n ("+10:00 Asia/Vladivostok") + << i18n ("+11:00 Asia/Magadan") + << i18n ("+12:00 Asia/Kamchatka") + // << i18n (" xx:xx User defined offset") + << i18n (" Local Time"); + mSouthDaylight = false; + mTimeZoneOffset = 0; + daylightEnabled = false; +} + +void KLocale::setDateFormat( QString s ) +{ + mDateFormat = s; +} + +void KLocale::setDateFormatShort( QString s ) +{ + mDateFormatShort = s; +} + +void KLocale::setHore24Format ( bool b ) +{ + mHourF24Format = b; +} +void KLocale::setWeekStartMonday( bool b ) +{ + mWeekStartsMonday = b; +} +int KLocale::getIntDateFormat( ) +{ + return mIntDateFormat ; + +} +void KLocale::setIntDateFormat( int i ) +{ + mIntDateFormat = i; +} +void KLocale::setLanguage( int i ) +{ + mLanguage = i; +} +QString KLocale::translate( const char *index ) const +{ + return i18n( index ); +} + +QString KLocale::translate( const char *, const char *fallback) const +{ + return i18n( fallback ); +} + +QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const +{ + const QString rst = timeFormat(); + + // only "pm/am" here can grow, the rest shrinks, but + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 30]; + + uint index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); format_index++ ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'H': + put_it_in( buffer, index, pTime.hour() ); + break; + case 'I': + put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 ); + break; + case 'M': + put_it_in( buffer, index, pTime.minute() ); + break; + case 'S': + if (includeSecs) + put_it_in( buffer, index, pTime.second() ); + else + { + // we remove the seperator sign before the seconds and + // assume that works everywhere + --index; + break; + } + break; + case 'k': + number = pTime.hour(); + case 'l': + // to share the code + if ( rst.at( format_index ).unicode() == 'l' ) + number = (pTime.hour() + 11) % 12 + 1; + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'p': + { + QString s; + if ( pTime.hour() >= 12 ) + put_it_in( buffer, index, i18n("pm") ); + else + put_it_in( buffer, index, i18n("am") ); + break; + } + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const +{ + const QString rst = shortFormat?dateFormatShort():dateFormat(); + + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 50]; + + unsigned int index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); ++format_index ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'Y': + put_it_in( buffer, index, pDate.year() / 100 ); + case 'y': + put_it_in( buffer, index, pDate.year() % 100 ); + break; + case 'n': + number = pDate.month(); + case 'e': + // to share the code + if ( rst.at( format_index ).unicode() == 'e' ) + number = pDate.day(); + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'm': + put_it_in( buffer, index, pDate.month() ); + break; + case 'b': + put_it_in( buffer, index, monthName(pDate.month(), true) ); + break; + case 'B': + put_it_in( buffer, index, monthName(pDate.month(), false) ); + break; + case 'd': + put_it_in( buffer, index, pDate.day() ); + break; + case 'a': + put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), true) ); + break; + case 'A': + put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), false) ); + break; + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSeconds) const +{ + return QString( "%1 %2") + .arg( formatDate( pDateTime.date(), shortFormat ) ) + .arg( formatTime( pDateTime.time(), includeSeconds ) ); +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime) const +{ + return formatDateTime(pDateTime, true); +} + +QDate KLocale::readDate(const QString &intstr, bool* ok) const +{ + QDate date; + date = readDate(intstr, true, ok); + if (date.isValid()) return date; + return readDate(intstr, false, ok); +} + +QDate KLocale::readDate(const QString &intstr, bool shortFormat, bool* ok) const +{ + QString fmt = (shortFormat ? dateFormatShort() : dateFormat()).simplifyWhiteSpace(); + return readDate( intstr, fmt, ok ); +} + +QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const +{ + //kdDebug(173) << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl; + QString str = intstr.simplifyWhiteSpace().lower(); + int day = -1, month = -1; + // allow the year to be omitted if not in the format + int year = QDate::currentDate().year(); + uint strpos = 0; + uint fmtpos = 0; + + while (fmt.length() > fmtpos || str.length() > strpos) + { + if ( !(fmt.length() > fmtpos && str.length() > strpos) ) + goto error; + + QChar c = fmt.at(fmtpos++); + + if (c != '%') { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = fmt.at(fmtpos++); + switch (c) + { + case 'a': + case 'A': + // this will just be ignored + { // Cristian Tache: porting to Win: Block added because of "j" redefinition + for (int j = 1; j < 8; j++) { + QString s = weekDayName(j, c == 'a').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + strpos += len; + } + break; + } + case 'b': + case 'B': + { // Cristian Tache: porting to Win: Block added because of "j" redefinition + for (int j = 1; j < 13; j++) { + QString s = monthName(j, c == 'b').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) { + month = j; + strpos += len; + } + } + break; + } + case 'd': + case 'e': + day = readInt(str, strpos); + if (day < 1 || day > 31) + goto error; + + break; + + case 'n': + case 'm': + month = readInt(str, strpos); + if (month < 1 || month > 12) + goto error; + + break; + + case 'Y': + case 'y': + year = readInt(str, strpos); + if (year < 0) + goto error; + // Qt treats a year in the range 0-100 as 1900-1999. + // It is nicer for the user if we treat 0-68 as 2000-2068 + if (year < 69) + year += 2000; + else if (c == 'y') + year += 1900; + + break; + } + } + //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl; + if ( year != -1 && month != -1 && day != -1 ) + { + if (ok) *ok = true; + return QDate(year, month, day); + } + error: + if (ok) *ok = false; + return QDate(); // invalid date +} + +QTime KLocale::readTime(const QString &intstr, bool *ok) const +{ + QTime _time; + _time = readTime(intstr, true, ok); + if (_time.isValid()) return _time; + return readTime(intstr, false, ok); +} + +QTime KLocale::readTime(const QString &intstr, bool seconds, bool *ok) const +{ + QString str = intstr.simplifyWhiteSpace().lower(); + QString Format = timeFormat().simplifyWhiteSpace(); + if (!seconds) + Format.replace(QRegExp(QString::fromLatin1(".%S")), QString::null); + + int hour = -1, minute = -1, second = seconds ? -1 : 0; // don't require seconds + bool g_12h = false; + bool pm = false; + uint strpos = 0; + uint Formatpos = 0; + + while (Format.length() > Formatpos || str.length() > strpos) + { + if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error; + + QChar c = Format.at(Formatpos++); + + if (c != '%') + { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = Format.at(Formatpos++); + switch (c) + { + case 'p': + { + QString s; + s = i18n("pm").lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + { + pm = true; + strpos += len; + } + else + { + s = i18n("am").lower(); + len = s.length(); + if (str.mid(strpos, len) == s) { + pm = false; + strpos += len; + } + else + goto error; + } + } + break; + + case 'k': + case 'H': + g_12h = false; + hour = readInt(str, strpos); + if (hour < 0 || hour > 23) + goto error; + + break; + + case 'l': + case 'I': + g_12h = true; + hour = readInt(str, strpos); + if (hour < 1 || hour > 12) + goto error; + + break; + + case 'M': + minute = readInt(str, strpos); + if (minute < 0 || minute > 59) + goto error; + + break; + + case 'S': + second = readInt(str, strpos); + if (second < 0 || second > 59) + goto error; + + break; + } + } + if (g_12h) + { + hour %= 12; + if (pm) hour += 12; + } + + if (ok) *ok = true; + return QTime(hour, minute, second); + + error: + if (ok) *ok = false; + return QTime(-1, -1, -1); // return invalid date if it didn't work + // This will be removed in the near future, since it gives a warning on stderr. + // The presence of the bool* (since KDE-3.0) removes the need for an invalid QTime. +} + +bool KLocale::use12Clock() const +{ + return !mHourF24Format ;; +} + +bool KLocale::weekStartsMonday() const +{ + return mWeekStartsMonday; +} + +int KLocale::weekStartDay() const +{ + if ( mWeekStartsMonday ) + return 1; + return 7; +} + +QString KLocale::weekDayName(int i,bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return i18n("Monday", "Mon"); + case 2: return i18n("Tuesday", "Tue"); + case 3: return i18n("Wednesday", "Wed"); + case 4: return i18n("Thursday", "Thu"); + case 5: return i18n("Friday", "Fri"); + case 6: return i18n("Saturday", "Sat"); + case 7: return i18n("Sunday", "Sun"); + } + else + switch ( i ) + { + case 1: return i18n("Monday"); + case 2: return i18n("Tuesday"); + case 3: return i18n("Wednesday"); + case 4: return i18n("Thursday"); + case 5: return i18n("Friday"); + case 6: return i18n("Saturday"); + case 7: return i18n("Sunday"); + } + + return QString::null; +} + +QString KLocale::monthName(int i,bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return i18n("January", "Jan"); + case 2: return i18n("February", "Feb"); + case 3: return i18n("March", "Mar"); + case 4: return i18n("April", "Apr"); + case 5: return i18n("May short", "May"); + case 6: return i18n("June", "Jun"); + case 7: return i18n("July", "Jul"); + case 8: return i18n("August", "Aug"); + case 9: return i18n("September", "Sep"); + case 10: return i18n("October", "Oct"); + case 11: return i18n("November", "Nov"); + case 12: return i18n("December", "Dec"); + } + else + switch (i) + { + case 1: return i18n("January"); + case 2: return i18n("February"); + case 3: return i18n("March"); + case 4: return i18n("April"); + case 5: return i18n("May long", "May"); + case 6: return i18n("June"); + case 7: return i18n("July"); + case 8: return i18n("August"); + case 9: return i18n("September"); + case 10: return i18n("October"); + case 11: return i18n("November"); + case 12: return i18n("December"); + } + + return QString::null; +} + +QString KLocale::country() const +{ + return QString::null; +} + +QString KLocale::dateFormat() const +{ + if ( QApplication::desktop()->width() < 480 ) { + if ( mIntDateFormat == 0 ) + return "%a %d %b %Y"; + else if ( mIntDateFormat == 1 ) + return "%a %b %d %Y"; + else if ( mIntDateFormat == 2 ) + return "%a %Y %b %d"; + } else { + + if ( mIntDateFormat == 0 ) + return "%A %d %B %Y"; + else if ( mIntDateFormat == 1 ) + return "%A %B %d %Y"; + else if ( mIntDateFormat == 2 ) + return "%A %Y %B %d"; + } + return mDateFormat ; +} + +QString KLocale::dateFormatShort() const +{ + + if ( mIntDateFormat == 0 ) + return "%d.%m.%Y"; + else if ( mIntDateFormat == 1 ) + return "%m.%d.%Y"; + else if ( mIntDateFormat == 2 ) + return "%Y-%m-%d"; + return mDateFormatShort ; + +} + + +QString KLocale::timeFormat() const +{ + if ( mHourF24Format) + return "%H:%M:%S"; + return "%I:%M:%S%p"; +} + +void KLocale::insertCatalogue ( const QString & ) +{ +} + +KCalendarSystem *KLocale::calendar() +{ + if ( !mCalendarSystem ) { + mCalendarSystem = new KCalendarSystemGregorian; + } + + return mCalendarSystem; +} + +int KLocale::timezoneOffset( QString timeZone ) +{ + int ret = 1001; + int index = mTimeZoneList.findIndex( timeZone ); + if ( index < 24 ) + ret = ( index-11 ) * 60 ; + return ret; +} + +QStringList KLocale::timeZoneList() const +{ + return mTimeZoneList; +} +void KLocale::setTimezone( const QString &timeZone ) +{ + mTimeZoneOffset = timezoneOffset( timeZone ); +} + +void KLocale::setDaylightSaving( bool b, int start , int end ) +{ + daylightEnabled = b; + daylightStart = start; + daylightEnd = end; + mSouthDaylight = (end < start); + // qDebug("klocale daylight %d %d %d ", b, start , end ); +} + +int KLocale::localTimeOffset( const QDateTime &dt ) +{ + bool addDaylight = false; + if ( daylightEnabled ) { + int d_end, d_start; + int dayofyear = dt.date().dayOfYear(); + int year = dt.date().year(); + int add = 0; + if ( QDate::leapYear(year) ) + add = 1; + QDate date ( year,1,1 ); + if ( daylightEnd > 59 ) + d_end = daylightEnd +add; + else + d_end = daylightEnd; + if ( daylightStart > 59 ) + d_start = daylightStart +add; + else + d_start = daylightStart; + QDate s_date = date.addDays( d_start -1 ); + QDate e_date = date.addDays( d_end -1 ); + int dof = s_date.dayOfWeek(); + if ( dof < 7 ) + s_date = s_date.addDays( -dof ); + dof = e_date.dayOfWeek(); + if ( dof < 7 ) + e_date = e_date.addDays( -dof ); + QTime startTime ( 3,0,0 ); + QDateTime startDt( s_date, startTime ); + QDateTime endDt( e_date, startTime ); + //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( )); + if ( mSouthDaylight ) { + if ( ! ( endDt < dt && dt < startDt) ) + addDaylight = true; + } else { + if ( startDt < dt && dt < endDt ) + addDaylight = true; + + + } + } + int addMin = 0; + if ( addDaylight ) + addMin = 60; + return mTimeZoneOffset + addMin; +} +// ****************************************************************** +// added LR +QString KLocale::formatNumber(double num, int precision) const +{ + bool neg = num < 0; + if (precision == -1) precision = 2; + QString res = QString::number(neg?-num:num, 'f', precision); + int pos = res.find('.'); + if (pos == -1) pos = res.length(); + else res.replace(pos, 1, decimalSymbol()); + + while (0 < (pos -= 3)) + res.insert(pos, thousandsSeparator()); // thousand sep + + // How can we know where we should put the sign? + res.prepend(neg?negativeSign():positiveSign()); + + return res; +} +QString KLocale::formatNumber(const QString &numStr) const +{ + return formatNumber(numStr.toDouble()); +} +double KLocale::readNumber(const QString &_str, bool * ok) const +{ + QString str = _str.stripWhiteSpace(); + bool neg = str.find(negativeSign()) == 0; + if (neg) + str.remove( 0, negativeSign().length() ); + + /* will hold the scientific notation portion of the number. + Example, with 2.34E+23, exponentialPart == "E+23" + */ + QString exponentialPart; + int EPos; + + EPos = str.find('E', 0, false); + + if (EPos != -1) + { + exponentialPart = str.mid(EPos); + str = str.left(EPos); + } + + int pos = str.find(decimalSymbol()); + QString major; + QString minor; + if ( pos == -1 ) + major = str; + else + { + major = str.left(pos); + minor = str.mid(pos + decimalSymbol().length()); + } + + // Remove thousand separators + int thlen = thousandsSeparator().length(); + int lastpos = 0; + while ( ( pos = major.find( thousandsSeparator() ) ) > 0 ) + { + // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N + int fromEnd = major.length() - pos; + if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error + || pos - lastpos > 3 // More than 3 digits between two separators -> error + || pos == 0 // Can't start with a separator + || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators + { + if (ok) *ok = false; + return 0.0; + } + + lastpos = pos; + major.remove( pos, thlen ); + } + if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator + { + if (ok) *ok = false; + return 0.0; + } + + QString tot; + if (neg) tot = '-'; + + tot += major + '.' + minor + exponentialPart; + + return tot.toDouble(ok); +} +QString KLocale::decimalSymbol() const +{ + + return m_decimalSymbol; +} + +QString KLocale::thousandsSeparator() const +{ + + return m_thousandsSeparator; +} +QString KLocale::positiveSign() const +{ + return m_positiveSign; +} + +QString KLocale::negativeSign() const +{ + return m_negativeSign; +} diff --git a/microkde/kdecore/klocale.h b/microkde/kdecore/klocale.h new file mode 100644 index 0000000..7470cd2 --- a/dev/null +++ b/microkde/kdecore/klocale.h @@ -0,0 +1,110 @@ +#ifndef MINIKDE_KLOCALE_H +#define MINIKDE_KLOCALE_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qdatetime.h> +#include <qdict.h> + +#ifndef I18N_NOOP +#define I18N_NOOP(x) (x) +#endif + +class KCalendarSystem; +void setLocaleDict( QDict<QString> * dict ); +QString i18n(const char *text); +QString i18n(const char *hint, const char *text); +QString i18n(const char *text1, const char *textn, int num); + +// Qt3's uic generates i18n( "msg", "comment" ) calls which conflict +// with our i18n method. we use uic -tr tr2i18n to redirect +// to the right i18n() function +inline QString tr2i18n(const char* message, const char* =0) { + return i18n( message); +} + +class KLocale +{ + public: + KLocale(); + + QString formatNumber(double num, int precision = -1) const; + QString formatNumber(const QString &numStr) const; + double readNumber(const QString &numStr, bool * ok = 0) const; + + QString decimalSymbol() const; + QString thousandsSeparator() const; + QString positiveSign() const; + QString negativeSign() const; + + + QString translate( const char *index ) const; + QString translate( const char *index, const char *fallback) const; + + QString formatDate(const QDate &pDate, bool shortFormat = false) const; + QString formatTime(const QTime &pTime, bool includeSecs = false) const; + QString formatDateTime(const QDateTime &pDateTime) const; + QString formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSecs = false) const; + + QDate readDate(const QString &str, bool* ok = 0) const; + QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const; + QTime readTime(const QString &str, bool* ok = 0) const; + + bool use12Clock() const; + bool weekStartsMonday() const; + int weekStartDay() const; + + QString weekDayName(int,bool=false) const; + QString monthName(int,bool=false) const; + + QString country() const; + + QString dateFormat() const; + QString dateFormatShort() const; + QString timeFormat() const; + + void insertCatalogue ( const QString & ); + + KCalendarSystem *calendar(); + void setHore24Format ( bool ); + void setWeekStartMonday( bool ); + void setIntDateFormat( int ); + int getIntDateFormat( ); + void setLanguage( int ); + void setDateFormat( QString ); + void setDateFormatShort( QString ); + + QString m_decimalSymbol; + QString m_thousandsSeparator; + QString m_currencySymbol; + QString m_monetaryDecimalSymbol; + QString m_monetaryThousandsSeparator; + QString m_positiveSign; + QString m_negativeSign; + + int timezoneOffset( QString ); + QStringList timeZoneList() const; + void setDaylightSaving( bool, int , int ); + int localTimeOffset(const QDateTime &); + void setTimezone( const QString &timeZone ); + private: + QTime readTime(const QString &str, bool seconds, bool *ok) const; + QDate readDate(const QString &str, bool shortFormat, bool *ok) const; + KCalendarSystem *mCalendarSystem; + bool mWeekStartsMonday; + bool mHourF24Format; + int mIntDateFormat; + int mLanguage; + QString mDateFormat; + QString mDateFormatShort; + QStringList mTimeZoneList; + bool daylightEnabled; + int mDaylightTZoffset; + int mNondaylightTZoffset; + bool mSouthDaylight; + int daylightStart, daylightEnd, mTimeZoneOffset; +}; + +#endif diff --git a/microkde/kdecore/klocale_new.cpp b/microkde/kdecore/klocale_new.cpp new file mode 100644 index 0000000..223b6c4 --- a/dev/null +++ b/microkde/kdecore/klocale_new.cpp @@ -0,0 +1,2441 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE libraries + Copyright (c) 1997,2001 Stephan Kulow <coolo@kde.org> + Copyright (c) 1999 Preston Brown <pbrown@kde.org> + Copyright (c) 1999-2002 Hans Petter Bieker <bieker@kde.org> + Copyright (c) 2002 Lukas Tinkl <lukas@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//US#include <config.h> + +#include <stdlib.h> // getenv +#include <assert.h> + +#include <qtextcodec.h> +#include <qfile.h> +#include <qdict.h> +#include <qprinter.h> +#include <qdatetime.h> +#include <qfileinfo.h> +#include <qregexp.h> + +#include "kcatalogue.h" +#include "kglobal.h" +#include "kstandarddirs.h" +#include "ksimpleconfig.h" +//US #include "kinstance.h" +#include "kconfig.h" +#include "kconfigbase.h" +#include "kdebug.h" +#include "kcalendarsystem.h" + +//US we use no factory. Simply use the gregorian calendar +//US #include "kcalendarsystemfactory.h" +#include "kcalendarsystemgregorian.h" + +#include "klocale.h" + +static const char * const SYSTEM_MESSAGES = "kdelibs"; + +static const char *maincatalogue = 0; + +QDict<char> *mLocaleDict = 0; + +void setLocaleDict( QDict<char> * dict ) +{ + mLocaleDict = dict; + +} + +class KLocalePrivate +{ +public: + int weekStartDay; + int plural_form; + bool nounDeclension; + bool dateMonthNamePossessive; + QStringList languageList; + QValueList<KCatalogue> catalogues; + QString encoding; + QTextCodec * codecForEncoding; + KConfig * config; + bool formatInited; + int /*QPrinter::PageSize*/ pageSize; + KLocale::MeasureSystem measureSystem; + QStringList langTwoAlpha; + KConfig *languages; + + QString calendarType; + KCalendarSystem * calendar; + QString first_language; + bool utf8FileEncoding; +}; + +static KLocale *this_klocale = 0; + +KLocale::KLocale( const QString & catalogue, KConfig * config ) +{ + d = new KLocalePrivate; + d->config = config; + d->languages = 0; + d->calendar = 0; + + initCatalogue(catalogue); + initEncoding(0); + initFileNameEncoding(0); + + KConfig *cfg = d->config; + this_klocale = this; +//US if (!cfg) cfg = KGlobal::instance()->config(); + if (!cfg) cfg = KGlobal::config(); + this_klocale = 0; +//US Q_ASSERT( cfg ); + ASSERT( cfg ); + + if (m_language.isEmpty()) + initLanguage(cfg, config == 0); + + +/*US +//US mDateFormat = "%a %Y %b %d"; +//US mDateFormatShort = "%Y-%m-%d"; + mTimeZoneList << i18n ("-11:00 US/Samoa") + << i18n ("-10:00 US/Hawaii") + << i18n ("-09:00 US/Alaska") + << i18n ("-08:00 US/Pacific") + << i18n ("-07:00 US/Mountain") + << i18n ("-06:00 US/Central") + << i18n ("-05:00 US/Eastern") + << i18n ("-04:00 Brazil/West") + << i18n ("-03:00 Brazil/East") + << i18n ("-02:00 Brazil/DeNoronha") + << i18n ("-01:00 Atlantic/Azores") + << i18n (" 00:00 Europe/London(UTC)") + << i18n ("+01:00 Europe/Oslo(CET)") + << i18n ("+02:00 Europe/Helsinki") + << i18n ("+03:00 Europe/Moscow") + << i18n ("+04:00 Indian/Mauritius") + << i18n ("+05:00 Indian/Maldives") + << i18n ("+06:00 Indian/Chagos") + << i18n ("+07:00 Asia/Bangkok") + << i18n ("+08:00 Asia/Hongkong") + << i18n ("+09:00 Asia/Tokyo") + << i18n ("+10:00 Asia/Vladivostok") + << i18n ("+11:00 Asia/Magadan") + << i18n ("+12:00 Asia/Kamchatka") + // << i18n (" xx:xx User defined offset") + << i18n (" Local Time"); +*/ + mTimeZoneList << "-11:00 US/Samoa" + << "-10:00 US/Hawaii" + << "-09:00 US/Alaska" + << "-08:00 US/Pacific" + << "-07:00 US/Mountain" + << "-06:00 US/Central" + << "-05:00 US/Eastern" + << "-04:00 Brazil/West" + << "-03:00 Brazil/East" + << "-02:00 Brazil/DeNoronha" + << "-01:00 Atlantic/Azores" + << " 00:00 Europe/London(UTC)" + << "+01:00 Europe/Oslo(CET)" + << "+02:00 Europe/Helsinki" + << "+03:00 Europe/Moscow" + << "+04:00 Indian/Mauritius" + << "+05:00 Indian/Maldives" + << "+06:00 Indian/Chagos" + << "+07:00 Asia/Bangkok" + << "+08:00 Asia/Hongkong" + << "+09:00 Asia/Tokyo" + << "+10:00 Asia/Vladivostok" + << "+11:00 Asia/Magadan" + << "+12:00 Asia/Kamchatka" + // << " xx:xx User defined offset" + << " Local Time"; + + mSouthDaylight = false; + mTimeZoneOffset = 0; + daylightEnabled = false; + + mWeekStartsMonday = true; + mHourF24Format = true; + mIntDateFormat = 0; + mLanguage = 0; + +} + + +QString KLocale::_initLanguage(KConfigBase *config) +{ + if (this_klocale) + { + // ### HPB Why this cast?? + this_klocale->initLanguage((KConfig *) config, true); + return this_klocale->language(); + } + return QString::null; +} + +void KLocale::initCatalogue(const QString & catalogue) +{ + // Use the first non-null string. + QString mainCatalogue = catalogue; + if (maincatalogue) + mainCatalogue = QString::fromLatin1(maincatalogue); + + if (mainCatalogue.isEmpty()) { + kdDebug(173) << "KLocale instance created called without valid " + << "catalogue! Give an argument or call setMainCatalogue " + << "before init" << endl; + } + else + d->catalogues.append( KCatalogue(mainCatalogue ) ); + + // always include kdelibs.mo + d->catalogues.append( KCatalogue( SYSTEM_MESSAGES ) ); +} + +void KLocale::initLanguage(KConfig * config, bool useEnv) +{ + KConfigGroupSaver saver(config, "Locale"); + + m_country = config->readEntry( "Country" ); + if ( m_country.isEmpty() ) + m_country = defaultCountry(); + + // Reset the list and add the new languages + QStringList languageList; + if ( useEnv ) + languageList += QStringList::split + (':', QFile::decodeName( ::getenv("KDE_LANG") )); + +//US languageList += config->readListEntry("Language", ':'); + languageList += config->readListEntry("Language"); + + // same order as setlocale use + if ( useEnv ) + { + // HPB: Only run splitLocale on the environment variables.. + QStringList langs; + + langs << QFile::decodeName( ::getenv("LC_ALL") ); + langs << QFile::decodeName( ::getenv("LC_MESSAGES") ); + langs << QFile::decodeName( ::getenv("LANG") ); + langs << QFile::decodeName( ::getenv("LC_CTYPE") ); + + for ( QStringList::Iterator it = langs.begin(); + it != langs.end(); + ++it ) + { + QString ln, ct, chrset; + splitLocale(*it, ln, ct, chrset); + + if (!ct.isEmpty()) { + langs.insert(it, ln + '_' + ct); + if (!chrset.isEmpty()) + langs.insert(it, ln + '_' + ct + '.' + chrset); + } + + langs.insert(it, ln); + } + + languageList += langs; + } + + // now we have a language list -- let's use the first OK language + setLanguage( languageList ); +} + +void KLocale::doBindInit() +{ + return; // LR + for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin(); + it != d->catalogues.end(); + ++it ) + initCatalogue( *it ); + + if ( useDefaultLanguage() ) + d->plural_form = -1; + else + { + QString pf = translate_priv + ( I18N_NOOP("_: Dear translator, please do not translate this string " + "in any form, but pick the _right_ value out of " + "NoPlural/TwoForms/French... If not sure what to do mail " + "thd@kde.org and coolo@kde.org, they will tell you. " + "Better leave that out if unsure, the programs will " + "crash!!\nDefinition of PluralForm - to be set by the " + "translator of kdelibs.po"), 0); + if ( pf.isEmpty() ) { + kdWarning(173) << "found no definition of PluralForm for " << m_language << endl; + d->plural_form = -1; + } else if ( pf == "NoPlural" ) + d->plural_form = 0; + else if ( pf == "TwoForms" ) + d->plural_form = 1; + else if ( pf == "French" ) + d->plural_form = 2; + else if ( pf == "OneTwoRest" || pf == "Gaeilge" ) // Gaelige is the old name + d->plural_form = 3; + else if ( pf == "Russian" ) + d->plural_form = 4; + else if ( pf == "Polish" ) + d->plural_form = 5; + else if ( pf == "Slovenian" ) + d->plural_form = 6; + else if ( pf == "Lithuanian" ) + d->plural_form = 7; + else if ( pf == "Czech" ) + d->plural_form = 8; + else if ( pf == "Slovak" ) + d->plural_form = 9; + else if ( pf == "Maltese" ) + d->plural_form = 10; + else if ( pf == "Arabic" ) + d->plural_form = 11; + else if ( pf == "Balcan" ) + d->plural_form = 12; + else { + kdWarning(173) << "Definition of PluralForm is none of " + << "NoPlural/" + << "TwoForms/" + << "French/" + << "OneTwoRest/" + << "Russian/" + << "Polish/" + << "Slovenian/" + << "Lithuanian/" + << "Czech/" + << "Slovak/" + << "Arabic/" + << "Balcan/" + << "Maltese: " << pf << endl; + exit(1); + } + } + + d->formatInited = false; +} + +void KLocale::doFormatInit() const +{ + if ( d->formatInited ) return; + + KLocale * that = const_cast<KLocale *>(this); + that->initFormat(); + + d->formatInited = true; +} + +void KLocale::initFormat() +{ + KConfig *config = d->config; +//US if (!config) config = KGlobal::instance()->config(); + if (!config) config = KGlobal::config(); + ASSERT( config ); + + kdDebug(173) << "KLocale::initFormat" << endl; + + // make sure the config files are read using the correct locale + // ### Why not add a KConfigBase::setLocale( const KLocale * )? + // ### Then we could remove this hack +//US +//US KLocale *lsave = KGlobal::_locale; +//US KGlobal::_locale = this; + KLocale *lsave = KGlobal::locale(); + KGlobal::setLocale(this); + + KConfigGroupSaver saver(config, "Locale"); + + + +//US in kabc/adress.cpp we have a similar setup. Check there in case of problems + KSimpleConfig entry(locateLocal("locale", + QString::fromLatin1("l10n/%1/entry.desktop") + .arg(m_country)) ); + + entry.setGroup("KCM Locale"); + + // Numeric +#define readConfigEntry(key, default, save) \ + save = entry.readEntry(key, QString::fromLatin1(default)); \ + save = config->readEntry(key, save); + +#define readConfigNumEntry(key, default, save, type) \ + save = (type)entry.readNumEntry(key, default); \ + save = (type)config->readNumEntry(key, save); + +#define readConfigBoolEntry(key, default, save) \ + save = entry.readBoolEntry(key, default); \ + save = config->readBoolEntry(key, save); + + readConfigEntry("DecimalSymbol", ".", m_decimalSymbol); + readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator); + m_thousandsSeparator.replace( QString::fromLatin1("$0"), QString::null ); + //kdDebug(173) << "m_thousandsSeparator=" << m_thousandsSeparator << endl; + + readConfigEntry("PositiveSign", "", m_positiveSign); + readConfigEntry("NegativeSign", "-", m_negativeSign); + + // Monetary + readConfigEntry("CurrencySymbol", "$", m_currencySymbol); + readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol); + readConfigEntry("MonetaryThousandsSeparator", ",", + m_monetaryThousandsSeparator); + m_monetaryThousandsSeparator.replace(QString::fromLatin1("$0"), QString::null); + + readConfigNumEntry("FracDigits", 2, m_fracDigits, int); + readConfigBoolEntry("PositivePrefixCurrencySymbol", true, + m_positivePrefixCurrencySymbol); + readConfigBoolEntry("NegativePrefixCurrencySymbol", true, + m_negativePrefixCurrencySymbol); + readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney, + m_positiveMonetarySignPosition, SignPosition); + readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround, + m_negativeMonetarySignPosition, SignPosition); + + //Grammatical + readConfigBoolEntry("NounDeclension", false, d->nounDeclension); + + // Date and time + readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat); + readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat); + readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort); + readConfigBoolEntry("DateMonthNamePossessive", false, + d->dateMonthNamePossessive); + readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int); + + // other +//US readConfigNumEntry("PageSize", (int)QPrinter::A4, d->pageSize, int); + readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem, + MeasureSystem); + readConfigEntry("CalendarSystem", "gregorian", d->calendarType); + delete d->calendar; + d->calendar = 0; // ### HPB Is this the correct place? + + // end of hack +//US KGlobal::_locale = lsave; + KGlobal::setLocale(lsave); +} + +bool KLocale::setCountry(const QString & country) +{ + // Check if the file exists too?? + if ( country.isEmpty() ) + return false; + + m_country = country; + + d->formatInited = false; + + return true; +} + +QString KLocale::catalogueFileName(const QString & language, + const KCatalogue & catalogue) +{ + QString path = QString::fromLatin1("%1/LC_MESSAGES/%2.mo") + .arg( language ) + .arg( catalogue.name() ); + + return locate( "locale", path ); +} + +bool KLocale::isLanguageInstalled(const QString & language) const +{ + // Do not allow empty languages + if ( language.isEmpty() ) return false; + + bool bRes = true; + if ( language != defaultLanguage() ) + for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin(); + it != d->catalogues.end() && bRes; + ++it ) + { + bRes = !catalogueFileName( language, *it ).isNull(); + if ( !bRes ) + kdDebug(173) << "message catalogue not found: " + << (*it).name() << endl; + } + + return bRes; +} + +bool KLocale::setLanguage(const QString & language) +{ + bool bRes = true; + + if (d->first_language.isNull() || language != d->first_language) + bRes = isLanguageInstalled( language ); + + if ( bRes ) + { + m_language = language; + + // remember our first time - it will be our true love + if (d->first_language.isNull()) + d->first_language = language; + + doBindInit(); + } + + return bRes; +} + +bool KLocale::setLanguage(const QStringList & languages) +{ + QStringList languageList(languages); + + // Remove duplicate entries in reverse so that we + // can keep user's language preference order intact. (DA) + for( QStringList::Iterator it = languageList.fromLast(); + it != languageList.begin(); + --it ) + if ( languageList.contains(*it) > 1 || (*it).isEmpty() ) + it = languageList.remove( it ); + + bool bRes = false; + for ( QStringList::ConstIterator it = languageList.begin(); + it != languageList.end(); + ++it ) + if ( bRes = setLanguage( *it ) ) + break; + + if ( !bRes ) + setLanguage(defaultLanguage()); + + d->languageList = languageList; + d->langTwoAlpha.clear(); // Flush cache + + return bRes; +} + +void KLocale::splitLocale(const QString & aStr, + QString & language, + QString & country, + QString & chrset) +{ + QString str = aStr; + + // just in case, there is another language appended + int f = str.find(':'); + if (f >= 0) + str.truncate(f); + + country = QString::null; + chrset = QString::null; + language = QString::null; + + f = str.find('.'); + if (f >= 0) + { + chrset = str.mid(f + 1); + str.truncate(f); + } + + f = str.find('_'); + if (f >= 0) + { + country = str.mid(f + 1); + str.truncate(f); + } + + language = str; +} + +QString KLocale::language() const +{ + return m_language; +} + +QString KLocale::country() const +{ + return m_country; +} + +QString KLocale::monthName(int i, bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return translate("January", "Jan"); + case 2: return translate("February", "Feb"); + case 3: return translate("March", "Mar"); + case 4: return translate("April", "Apr"); + case 5: return translate("May short", "May"); + case 6: return translate("June", "Jun"); + case 7: return translate("July", "Jul"); + case 8: return translate("August", "Aug"); + case 9: return translate("September", "Sep"); + case 10: return translate("October", "Oct"); + case 11: return translate("November", "Nov"); + case 12: return translate("December", "Dec"); + } + else + switch (i) + { + case 1: return translate("January"); + case 2: return translate("February"); + case 3: return translate("March"); + case 4: return translate("April"); + case 5: return translate("May long", "May"); + case 6: return translate("June"); + case 7: return translate("July"); + case 8: return translate("August"); + case 9: return translate("September"); + case 10: return translate("October"); + case 11: return translate("November"); + case 12: return translate("December"); + } + + return QString::null; +} + +QString KLocale::monthNamePossessive(int i, bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return translate("of January", "of Jan"); + case 2: return translate("of February", "of Feb"); + case 3: return translate("of March", "of Mar"); + case 4: return translate("of April", "of Apr"); + case 5: return translate("of May short", "of May"); + case 6: return translate("of June", "of Jun"); + case 7: return translate("of July", "of Jul"); + case 8: return translate("of August", "of Aug"); + case 9: return translate("of September", "of Sep"); + case 10: return translate("of October", "of Oct"); + case 11: return translate("of November", "of Nov"); + case 12: return translate("of December", "of Dec"); + } + else + switch (i) + { + case 1: return translate("of January"); + case 2: return translate("of February"); + case 3: return translate("of March"); + case 4: return translate("of April"); + case 5: return translate("of May long", "of May"); + case 6: return translate("of June"); + case 7: return translate("of July"); + case 8: return translate("of August"); + case 9: return translate("of September"); + case 10: return translate("of October"); + case 11: return translate("of November"); + case 12: return translate("of December"); + } + + return QString::null; +} + +QString KLocale::weekDayName (int i, bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return translate("Monday", "Mon"); + case 2: return translate("Tuesday", "Tue"); + case 3: return translate("Wednesday", "Wed"); + case 4: return translate("Thursday", "Thu"); + case 5: return translate("Friday", "Fri"); + case 6: return translate("Saturday", "Sat"); + case 7: return translate("Sunday", "Sun"); + } + else + switch ( i ) + { + case 1: return translate("Monday"); + case 2: return translate("Tuesday"); + case 3: return translate("Wednesday"); + case 4: return translate("Thursday"); + case 5: return translate("Friday"); + case 6: return translate("Saturday"); + case 7: return translate("Sunday"); + } + + return QString::null; +} + +void KLocale::insertCatalogue( const QString & catalogue ) +{ + KCatalogue cat( catalogue ); + + initCatalogue( cat ); + + d->catalogues.append( cat ); +} + +void KLocale::removeCatalogue(const QString &catalogue) +{ + for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin(); + it != d->catalogues.end(); ) + if ((*it).name() == catalogue) { + it = d->catalogues.remove(it); + return; + } else + ++it; +} + +void KLocale::setActiveCatalogue(const QString &catalogue) +{ + for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin(); + it != d->catalogues.end(); ++it) + if ((*it).name() == catalogue) { + KCatalogue save = *it; + d->catalogues.remove(it); + d->catalogues.prepend(save); + return; + } +} + +KLocale::~KLocale() +{ + delete d->languages; + delete d; +} + +QString KLocale::translate_priv(const char *msgid, + const char *fallback, + const char **translated) const +{ + if (!msgid || !msgid[0]) + { + kdWarning() << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + if ( useDefaultLanguage() ) + return QString::fromUtf8( fallback ); + + for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin(); + it != d->catalogues.end(); + ++it ) + { + // kdDebug(173) << "translate " << msgid << " " << (*it).name() << " " << (!KGlobal::activeInstance() ? QCString("no instance") : KGlobal::activeInstance()->instanceName()) << endl; + const char * text = (*it).translate( msgid ); + + if ( text ) + { + // we found it + if (translated) + *translated = text; + return QString::fromUtf8( text ); + } + } + + // Always use UTF-8 if the string was not found + return QString::fromUtf8( fallback ); +} + +QString KLocale::translate(const char* msgid) const +{ + return translate_priv(msgid, msgid); +} + +QString KLocale::translate( const char *index, const char *fallback) const +{ + if (!index || !index[0] || !fallback || !fallback[0]) + { + kdDebug(173) << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + if ( useDefaultLanguage() ) + return QString::fromUtf8( fallback ); + + char *newstring = new char[strlen(index) + strlen(fallback) + 5]; + sprintf(newstring, "_: %s\n%s", index, fallback); + // as copying QString is very fast, it looks slower as it is ;/ + QString r = translate_priv(newstring, fallback); + delete [] newstring; + + return r; +} + +static QString put_n_in(const QString &orig, unsigned long n) +{ + QString ret = orig; + int index = ret.find("%n"); + if (index == -1) + return ret; + ret.replace(index, 2, QString::number(n)); + return ret; +} + +#define EXPECT_LENGTH(x) \ + if (forms.count() != x) { \ + kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \ + return QString( "BROKEN TRANSLATION %1" ).arg( singular ); } + +QString KLocale::translate( const char *singular, const char *plural, + unsigned long n ) const +{ + if (!singular || !singular[0] || !plural || !plural[0]) + { + kdWarning() << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + char *newstring = new char[strlen(singular) + strlen(plural) + 6]; + sprintf(newstring, "_n: %s\n%s", singular, plural); + // as copying QString is very fast, it looks slower as it is ;/ + QString r = translate_priv(newstring, 0); + delete [] newstring; + + if ( r.isEmpty() || useDefaultLanguage() || d->plural_form == -1) { + if ( n == 1 ) { + return put_n_in( QString::fromUtf8( singular ), n ); + } else { + QString tmp = QString::fromUtf8( plural ); +#ifndef NDEBUG + if (tmp.find("%n") == -1) { + kdWarning() << "the message for i18n should contain a '%n'! " << plural << endl; + } +#endif + return put_n_in( tmp, n ); + } + } + + QStringList forms = QStringList::split( "\n", r, false ); + switch ( d->plural_form ) { + case 0: // NoPlural + EXPECT_LENGTH( 1 ); + return put_n_in( forms[0], n); + case 1: // TwoForms + EXPECT_LENGTH( 2 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else + return put_n_in( forms[1], n); + case 2: // French + EXPECT_LENGTH( 2 ); + if ( n == 1 || n == 0 ) + return put_n_in( forms[0], n); + else + return put_n_in( forms[1], n); + case 3: // Gaeilge + EXPECT_LENGTH( 3 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else if ( n == 2 ) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 4: // Russian, corrected by mok + EXPECT_LENGTH( 3 ); + if ( n%10 == 1 && n%100 != 11) + return put_n_in( forms[0], n); // odin fail + else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20)) + return put_n_in( forms[1], n); // dva faila + else + return put_n_in( forms[2], n); // desyat' failov + case 5: // Polish + EXPECT_LENGTH( 3 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) ) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 6: // Slovenian + EXPECT_LENGTH( 4 ); + if ( n%100 == 1 ) + return put_n_in( forms[1], n); // ena datoteka + else if ( n%100 == 2 ) + return put_n_in( forms[2], n); // dve datoteki + else if ( n%100 == 3 || n%100 == 4 ) + return put_n_in( forms[3], n); // tri datoteke + else + return put_n_in( forms[0], n); // sto datotek + case 7: // Lithuanian + EXPECT_LENGTH( 3 ); + if ( n%10 == 0 || (n%100>=11 && n%100<=19) ) + return put_n_in( forms[2], n); + else if ( n%10 == 1 ) + return put_n_in( forms[0], n); + else + return put_n_in( forms[1], n); + case 8: // Czech + EXPECT_LENGTH( 3 ); + if ( n%100 == 1 ) + return put_n_in( forms[0], n); + else if (( n%100 >= 2 ) && ( n%100 <= 4 )) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 9: // Slovak + EXPECT_LENGTH( 3 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else if (( n >= 2 ) && ( n <= 4 )) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 10: // Maltese + EXPECT_LENGTH( 4 ); + if ( n == 1 ) + return put_n_in( forms[0], n ); + else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) ) + return put_n_in( forms[1], n ); + else if ( n%100 > 10 && n%100 < 20 ) + return put_n_in( forms[2], n ); + else + return put_n_in( forms[3], n ); + case 11: // Arabic + EXPECT_LENGTH( 4 ); + if (n == 1) + return put_n_in(forms[0], n); + else if (n == 2) + return put_n_in(forms[1], n); + else if ( n < 11) + return put_n_in(forms[2], n); + else + return put_n_in(forms[3], n); + case 12: // Balcan + EXPECT_LENGTH( 3 ); + if (n != 11 && n % 10 == 1) + return put_n_in(forms[0], n); + else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4) + return put_n_in(forms[1], n); + else + return put_n_in(forms[2], n); + } + kdError() << "The function should have been returned in another way\n"; + + return QString::null; +} + +QString KLocale::translateQt( const char *context, const char *source, + const char *message) const +{ + if (!source || !source[0]) { + kdWarning() << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + if ( useDefaultLanguage() ) { + return QString::null; + } + + char *newstring = 0; + const char *translation = 0; + QString r; + + if ( message && message[0]) { + char *newstring = new char[strlen(source) + strlen(message) + 5]; + sprintf(newstring, "_: %s\n%s", source, message); + const char *translation = 0; + // as copying QString is very fast, it looks slower as it is ;/ + r = translate_priv(newstring, source, &translation); + delete [] newstring; + if (translation) + return r; + } + + if ( context && context[0] && message && message[0]) { + newstring = new char[strlen(context) + strlen(message) + 5]; + sprintf(newstring, "_: %s\n%s", context, message); + // as copying QString is very fast, it looks slower as it is ;/ + r = translate_priv(newstring, source, &translation); + delete [] newstring; + if (translation) + return r; + } + + r = translate_priv(source, source, &translation); + if (translation) + return r; + return QString::null; +} + +bool KLocale::nounDeclension() const +{ + doFormatInit(); + return d->nounDeclension; +} + +bool KLocale::dateMonthNamePossessive() const +{ + doFormatInit(); + return d->dateMonthNamePossessive; +} + +int KLocale::weekStartDay() const +{ + doFormatInit(); + return d->weekStartDay; +} + +bool KLocale::weekStartsMonday() const //deprecated +{ + doFormatInit(); + return (d->weekStartDay==1); +} + +QString KLocale::decimalSymbol() const +{ + doFormatInit(); + return m_decimalSymbol; +} + +QString KLocale::thousandsSeparator() const +{ + doFormatInit(); + return m_thousandsSeparator; +} + +QString KLocale::currencySymbol() const +{ + doFormatInit(); + return m_currencySymbol; +} + +QString KLocale::monetaryDecimalSymbol() const +{ + doFormatInit(); + return m_monetaryDecimalSymbol; +} + +QString KLocale::monetaryThousandsSeparator() const +{ + doFormatInit(); + return m_monetaryThousandsSeparator; +} + +QString KLocale::positiveSign() const +{ + doFormatInit(); + return m_positiveSign; +} + +QString KLocale::negativeSign() const +{ + doFormatInit(); + return m_negativeSign; +} + +int KLocale::fracDigits() const +{ + doFormatInit(); + return m_fracDigits; +} + +bool KLocale::positivePrefixCurrencySymbol() const +{ + doFormatInit(); + return m_positivePrefixCurrencySymbol; +} + +bool KLocale::negativePrefixCurrencySymbol() const +{ + doFormatInit(); + return m_negativePrefixCurrencySymbol; +} + +KLocale::SignPosition KLocale::positiveMonetarySignPosition() const +{ + doFormatInit(); + return m_positiveMonetarySignPosition; +} + +KLocale::SignPosition KLocale::negativeMonetarySignPosition() const +{ + doFormatInit(); + return m_negativeMonetarySignPosition; +} + +static inline void put_it_in( QChar *buffer, uint& index, const QString &s ) +{ + for ( uint l = 0; l < s.length(); l++ ) + buffer[index++] = s.at( l ); +} + +static inline void put_it_in( QChar *buffer, uint& index, int number ) +{ + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; +} + +QString KLocale::formatMoney(double num, + const QString & symbol, + int precision) const +{ + // some defaults + QString currency = symbol.isNull() + ? currencySymbol() + : symbol; + if (precision < 0) precision = fracDigits(); + + // the number itself + bool neg = num < 0; + QString res = QString::number(neg?-num:num, 'f', precision); + int pos = res.find('.'); + if (pos == -1) pos = res.length(); + else res.replace(pos, 1, monetaryDecimalSymbol()); + + while (0 < (pos -= 3)) + res.insert(pos, monetaryThousandsSeparator()); // thousend sep + + // set some variables we need later + int signpos = neg + ? negativeMonetarySignPosition() + : positiveMonetarySignPosition(); + QString sign = neg + ? negativeSign() + : positiveSign(); + + switch (signpos) + { + case ParensAround: + res.prepend('('); + res.append (')'); + break; + case BeforeQuantityMoney: + res.prepend(sign); + break; + case AfterQuantityMoney: + res.append(sign); + break; + case BeforeMoney: + currency.prepend(sign); + break; + case AfterMoney: + currency.append(sign); + break; + } + + if (neg?negativePrefixCurrencySymbol(): + positivePrefixCurrencySymbol()) + { + res.prepend(' '); + res.prepend(currency); + } else { + res.append (' '); + res.append (currency); + } + + return res; +} + +QString KLocale::formatMoney(const QString &numStr) const +{ + return formatMoney(numStr.toDouble()); +} + +QString KLocale::formatNumber(double num, int precision) const +{ + bool neg = num < 0; + if (precision == -1) precision = 2; + QString res = QString::number(neg?-num:num, 'f', precision); + int pos = res.find('.'); + if (pos == -1) pos = res.length(); + else res.replace(pos, 1, decimalSymbol()); + + while (0 < (pos -= 3)) + res.insert(pos, thousandsSeparator()); // thousand sep + + // How can we know where we should put the sign? + res.prepend(neg?negativeSign():positiveSign()); + + return res; +} + +QString KLocale::formatLong(long num) const +{ + return formatNumber((double)num, 0); +} + +QString KLocale::formatNumber(const QString &numStr) const +{ + return formatNumber(numStr.toDouble()); +} + +QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const +{ + const QString rst = shortFormat?dateFormatShort():dateFormat(); + + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 50]; + + unsigned int index = 0; + bool escape = false; + int number = 0; + + int year = calendar()->year(pDate); + int month = calendar()->month(pDate); + int day = calendar()->day(pDate); + + for ( uint format_index = 0; format_index < rst.length(); ++format_index ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'Y': + put_it_in( buffer, index, year / 100 ); + case 'y': + put_it_in( buffer, index, year % 100 ); + break; + case 'n': + number = month; + case 'e': + // to share the code + if ( rst.at( format_index ).unicode() == 'e' ) + number = day; + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'm': + put_it_in( buffer, index, month ); + break; + case 'b': + if (d->nounDeclension && d->dateMonthNamePossessive) +//US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, true) ); + put_it_in( buffer, index, calendar()->monthNamePossessive(month, true) ); + else +//US put_it_in( buffer, index, calendar()->monthName(month, year, true) ); + put_it_in( buffer, index, calendar()->monthName(month, true) ); + break; + case 'B': + if (d->nounDeclension && d->dateMonthNamePossessive) +//US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, false) ); + put_it_in( buffer, index, calendar()->monthNamePossessive(month, false) ); + else +//US put_it_in( buffer, index, calendar()->monthName(month, year, false) ); + put_it_in( buffer, index, calendar()->monthName(month, false) ); + break; + case 'd': + put_it_in( buffer, index, day ); + break; + case 'a': + put_it_in( buffer, index, calendar()->weekDayName(pDate, true) ); + break; + case 'A': + put_it_in( buffer, index, calendar()->weekDayName(pDate, false) ); + break; + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +void KLocale::setMainCatalogue(const char *catalogue) +{ + maincatalogue = catalogue; +} + +double KLocale::readNumber(const QString &_str, bool * ok) const +{ + QString str = _str.stripWhiteSpace(); + bool neg = str.find(negativeSign()) == 0; + if (neg) + str.remove( 0, negativeSign().length() ); + + /* will hold the scientific notation portion of the number. + Example, with 2.34E+23, exponentialPart == "E+23" + */ + QString exponentialPart; + int EPos; + + EPos = str.find('E', 0, false); + + if (EPos != -1) + { + exponentialPart = str.mid(EPos); + str = str.left(EPos); + } + + int pos = str.find(decimalSymbol()); + QString major; + QString minor; + if ( pos == -1 ) + major = str; + else + { + major = str.left(pos); + minor = str.mid(pos + decimalSymbol().length()); + } + + // Remove thousand separators + int thlen = thousandsSeparator().length(); + int lastpos = 0; + while ( ( pos = major.find( thousandsSeparator() ) ) > 0 ) + { + // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N + int fromEnd = major.length() - pos; + if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error + || pos - lastpos > 3 // More than 3 digits between two separators -> error + || pos == 0 // Can't start with a separator + || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators + { + if (ok) *ok = false; + return 0.0; + } + + lastpos = pos; + major.remove( pos, thlen ); + } + if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator + { + if (ok) *ok = false; + return 0.0; + } + + QString tot; + if (neg) tot = '-'; + + tot += major + '.' + minor + exponentialPart; + + return tot.toDouble(ok); +} + +double KLocale::readMoney(const QString &_str, bool * ok) const +{ + QString str = _str.stripWhiteSpace(); + bool neg = false; + bool currencyFound = false; + // First try removing currency symbol from either end + int pos = str.find(currencySymbol()); + if ( pos == 0 || pos == (int) str.length()-1 ) + { + str.remove(pos,currencySymbol().length()); + str = str.stripWhiteSpace(); + currencyFound = true; + } + if (str.isEmpty()) + { + if (ok) *ok = false; + return 0; + } + // Then try removing negative sign from either end + // (with a special case for parenthesis) + if (negativeMonetarySignPosition() == ParensAround) + { + if (str.at(0) == '(' && str.at(str.length()-1) == ')') + { + neg = true; + str.remove(str.length()-1,1); + str.remove(0,1); + } + } + else + { + int i1 = str.find(negativeSign()); + if ( i1 == 0 || i1 == (int) str.length()-1 ) + { + neg = true; + str.remove(i1,negativeSign().length()); + } + } + if (neg) str = str.stripWhiteSpace(); + + // Finally try again for the currency symbol, if we didn't find + // it already (because of the negative sign being in the way). + if ( !currencyFound ) + { + pos = str.find(currencySymbol()); + if ( pos == 0 || pos == (int) str.length()-1 ) + { + str.remove(pos,currencySymbol().length()); + str = str.stripWhiteSpace(); + } + } + + // And parse the rest as a number + pos = str.find(monetaryDecimalSymbol()); + QString major; + QString minior; + if (pos == -1) + major = str; + else + { + major = str.left(pos); + minior = str.mid(pos + monetaryDecimalSymbol().length()); + } + + // Remove thousand separators + int thlen = monetaryThousandsSeparator().length(); + int lastpos = 0; + while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 ) + { + // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N + int fromEnd = major.length() - pos; + if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error + || pos - lastpos > 3 // More than 3 digits between two separators -> error + || pos == 0 // Can't start with a separator + || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators + { + if (ok) *ok = false; + return 0.0; + } + lastpos = pos; + major.remove( pos, thlen ); + } + if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator + { + if (ok) *ok = false; + return 0.0; + } + + QString tot; + if (neg) tot = '-'; + tot += major + '.' + minior; + return tot.toDouble(ok); +} + +/** + * helper function to read integers + * @param str + * @param pos the position to start at. It will be updated when we parse it. + * @return the integer read in the string, or -1 if no string + */ +static int readInt(const QString &str, uint &pos) +{ + if (!str.at(pos).isDigit()) return -1; + int result = 0; + for (; str.length() > pos && str.at(pos).isDigit(); pos++) + { + result *= 10; + result += str.at(pos).digitValue(); + } + + return result; +} + +QDate KLocale::readDate(const QString &intstr, bool* ok) const +{ + QDate date; + date = readDate(intstr, ShortFormat, ok); + if (date.isValid()) return date; + return readDate(intstr, NormalFormat, ok); +} + +QDate KLocale::readDate(const QString &intstr, ReadDateFlags flags, bool* ok) const +{ + QString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace(); + return readDate( intstr, fmt, ok ); +} + +QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const +{ + //kdDebug() << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl; + QString str = intstr.simplifyWhiteSpace().lower(); + int day = -1, month = -1; + // allow the year to be omitted if not in the format + int year = calendar()->year(QDate::currentDate()); + uint strpos = 0; + uint fmtpos = 0; + + bool error = false; + + while (fmt.length() > fmtpos && str.length() > strpos && !error) + { + + QChar c = fmt.at(fmtpos++); + + if (c != '%') { + if (c.isSpace() && str.at(strpos).isSpace()) + strpos++; + else if (c != str.at(strpos++)) + error = true; + } + else + { + int j; + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = fmt.at(fmtpos++); + switch (c) + { + case 'a': + case 'A': + + error = true; + j = 1; + while (error && (j < 8)) { + QString s = weekDayName(j, c == 'a').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + { + strpos += len; + error = false; + } + j++; + } + break; + case 'b': + case 'B': + + error = true; + if (d->nounDeclension && d->dateMonthNamePossessive) { + j = 1; + while (error && (j < 13)) { +//US QString s = calendar()->monthNamePossessive(j, year, c == 'b').lower(); + QString s = calendar()->monthNamePossessive(j, c == 'b').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) { + month = j; + strpos += len; + error = false; + } + j++; + } + } + j = 1; + while (error && (j < 13)) { +//US QString s = calendar()->monthName(j, year, c == 'b').lower(); + QString s = calendar()->monthName(j, c == 'b').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) { + month = j; + strpos += len; + error = false; + } + j++; + } + break; + case 'd': + case 'e': + day = readInt(str, strpos); + error = (day < 1 || day > 31); + break; + + case 'n': + case 'm': + month = readInt(str, strpos); + error = (month < 1 || month > 12); + break; + + case 'Y': + case 'y': + year = readInt(str, strpos); + error = (year < 0); + // Qt treats a year in the range 0-100 as 1900-1999. + // It is nicer for the user if we treat 0-68 as 2000-2068 + if (c == 'y' && year < 69) + // eg. gregorian += 2000 + year += (calendar()->year(QDate::currentDate()) / 100) * 100; + else if (c == 'y' && year < 100) + // eg. gregorian += 1900 + year += (calendar()->year(QDate::currentDate()) / 100) * 100 - 100; + break; + } + } + } + + /* for a match, we should reach the end of both strings, not just one of + them */ + if ( fmt.length() > fmtpos || str.length() > strpos ) + { + error = true; + } + + //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl; + if ( year != -1 && month != -1 && day != -1 && !error) + { + if (ok) *ok = true; + + QDate result; + calendar()->setYMD(result, year, month, day); + + return result; + } + else + { + if (ok) *ok = false; + return QDate(); // invalid date + } +} + +QTime KLocale::readTime(const QString &intstr, bool *ok) const +{ + QTime _time; + _time = readTime(intstr, WithSeconds, ok); + if (_time.isValid()) return _time; + return readTime(intstr, WithoutSeconds, ok); +} + +QTime KLocale::readTime(const QString &intstr, ReadTimeFlags flags, bool *ok) const +{ + QString str = intstr.simplifyWhiteSpace().lower(); + QString Format = timeFormat().simplifyWhiteSpace(); + if (flags & WithoutSeconds) + { +//US remove not available in my QT version +//US Format.remove(QRegExp(".%S")); + Format.replace(QRegExp(".%S"), ""); + } + + int hour = -1, minute = -1; + int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0; // don't require seconds + bool g_12h = false; + bool pm = false; + uint strpos = 0; + uint Formatpos = 0; + + while (Format.length() > Formatpos || str.length() > strpos) + { + if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error; + + QChar c = Format.at(Formatpos++); + + if (c != '%') + { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = Format.at(Formatpos++); + switch (c) + { + case 'p': + { + QString s; + s = translate("pm").lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + { + pm = true; + strpos += len; + } + else + { + s = translate("am").lower(); + len = s.length(); + if (str.mid(strpos, len) == s) { + pm = false; + strpos += len; + } + else + goto error; + } + } + break; + + case 'k': + case 'H': + g_12h = false; + hour = readInt(str, strpos); + if (hour < 0 || hour > 23) + goto error; + + break; + + case 'l': + case 'I': + g_12h = true; + hour = readInt(str, strpos); + if (hour < 1 || hour > 12) + goto error; + + break; + + case 'M': + minute = readInt(str, strpos); + if (minute < 0 || minute > 59) + goto error; + + break; + + case 'S': + second = readInt(str, strpos); + if (second < 0 || second > 59) + goto error; + + break; + } + } + if (g_12h) { + hour %= 12; + if (pm) hour += 12; + } + + if (ok) *ok = true; + return QTime(hour, minute, second); + + error: + if (ok) *ok = false; + return QTime(-1, -1, -1); // return invalid date if it didn't work +} + +QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const +{ + const QString rst = timeFormat(); + + // only "pm/am" here can grow, the rest shrinks, but + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 30]; + + uint index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); format_index++ ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'H': + put_it_in( buffer, index, pTime.hour() ); + break; + case 'I': + put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 ); + break; + case 'M': + put_it_in( buffer, index, pTime.minute() ); + break; + case 'S': + if (includeSecs) + put_it_in( buffer, index, pTime.second() ); + else if ( index > 0 ) + { + // we remove the seperator sign before the seconds and + // assume that works everywhere + --index; + break; + } + break; + case 'k': + number = pTime.hour(); + case 'l': + // to share the code + if ( rst.at( format_index ).unicode() == 'l' ) + number = (pTime.hour() + 11) % 12 + 1; + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'p': + { + QString s; + if ( pTime.hour() >= 12 ) + put_it_in( buffer, index, translate("pm") ); + else + put_it_in( buffer, index, translate("am") ); + break; + } + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +bool KLocale::use12Clock() const +{ + if ((timeFormat().contains(QString::fromLatin1("%I")) > 0) || + (timeFormat().contains(QString::fromLatin1("%l")) > 0)) + return true; + else + return false; +} + +QString KLocale::languages() const +{ + return d->languageList.join( QString::fromLatin1(":") ); +} + +QStringList KLocale::languageList() const +{ + return d->languageList; +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSeconds) const +{ + return translate("concatenation of dates and time", "%1 %2") + .arg( formatDate( pDateTime.date(), shortFormat ) ) + .arg( formatTime( pDateTime.time(), includeSeconds ) ); +} + +QString i18n(const char* text) +{ + /* + register KLocale *instance = KGlobal::locale(); + if (instance) + return instance->translate(text); + */ + return QString::fromUtf8(text); +} + +QString i18n(const char* index, const char *text) +{ + /* + register KLocale *instance = KGlobal::locale(); + if (instance) + return instance->translate(index, text); + */ + return QString::fromUtf8(text); +} + +QString i18n(const char* singular, const char* plural, unsigned long n) +{ + return (QString::fromUtf8(plural)); // hack! remove this line! + register KLocale *instance = KGlobal::locale(); + if (instance) + return instance->translate(singular, plural, n); + if (n == 1) + return put_n_in(QString::fromUtf8(singular), n); + else + return put_n_in(QString::fromUtf8(plural), n); +} + +void KLocale::initInstance() +{ + if (KGlobal::locale()) + return; + +/*US lets change the whole way how to create a KLocale + KInstance *app = KGlobal::instance(); + if (app) { + KGlobal::_locale = new KLocale(QString::fromLatin1(app->instanceName())); + + // only do this for the global instance + QTextCodec::setCodecForLocale(KGlobal::_locale->codecForEncoding()); + } + else + kdDebug(173) << "no app name available using KLocale - nothing to do\n"; +*/ +//US new implementation + QString appname = KGlobal::getAppName(); + if (appname) { + KLocale *l = new KLocale(appname); + KGlobal::setLocale(l); + + // only do this for the global instance +//US +//US QTextCodec::setCodecForLocale(KGlobal::locale())->codecForEncoding()); +//US qt_set_locale_codec( KGlobal::locale()->codecForEncoding() ); + qDebug("KLocale::initInstance we have to do here something !!!"); + } + else + kdDebug(173) << "no app name available using KLocale - nothing to do\n"; + +} + +QString KLocale::langLookup(const QString &fname, const char *rtype) +{ + QStringList search; + + // assemble the local search paths +//US we have only one resourcedir. So use it !! +/*US original + const QStringList localDoc = KGlobal::dirs()->resourceDirs(rtype); + // look up the different languages + for (int id=localDoc.count()-1; id >= 0; --id) + { + QStringList langs = KGlobal::locale()->languageList(); + langs.append( "en" ); + langs.remove( defaultLanguage() ); + QStringList::ConstIterator lang; + for (lang = langs.begin(); lang != langs.end(); ++lang) + search.append(QString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname)); + } +*/ +//US new code +//US What is here correct??? const QString localDoc = KGlobal::dirs()->findResourceDir(rtype); + const QString localDoc = rtype; + // look up the different languages + QStringList langs = KGlobal::locale()->languageList(); + langs.append( "en" ); + langs.remove( defaultLanguage() ); + QStringList::ConstIterator lang; + for (lang = langs.begin(); lang != langs.end(); ++lang) + search.append(QString("%1%2/%3").arg(localDoc).arg(*lang).arg(fname)); + + // try to locate the file + QStringList::Iterator it; + for (it = search.begin(); it != search.end(); ++it) + { + kdDebug(173) << "Looking for help in: " << *it << endl; + + QFileInfo info(*it); + if (info.exists() && info.isFile() && info.isReadable()) + return *it; + } + + return QString::null; +} + +bool KLocale::useDefaultLanguage() const +{ + return language() == defaultLanguage(); +} + +void KLocale::initEncoding(KConfig *) +{ + const int mibDefault = 4; // ISO 8859-1 + + // This all made more sense when we still had the EncodingEnum config key. + setEncoding( QTextCodec::codecForLocale()->mibEnum() ); + + if ( !d->codecForEncoding ) + { + kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl; + setEncoding(mibDefault); + } + + ASSERT( d->codecForEncoding ); +} + +void KLocale::initFileNameEncoding(KConfig *) +{ + // If the following environment variable is set, assume all filenames + // are in UTF-8 regardless of the current C locale. + d->utf8FileEncoding = getenv("KDE_UTF8_FILENAMES") != 0; + if (d->utf8FileEncoding) + { + QFile::setEncodingFunction(KLocale::encodeFileNameUTF8); + QFile::setDecodingFunction(KLocale::decodeFileNameUTF8); + } + // Otherwise, stay with QFile's default filename encoding functions + // which, on Unix platforms, use the locale's codec. +} + +QCString KLocale::encodeFileNameUTF8( const QString & fileName ) +{ + return fileName.utf8(); +} + +QString KLocale::decodeFileNameUTF8( const QCString & localFileName ) +{ + return QString::fromUtf8(localFileName); +} + +void KLocale::initCatalogue( KCatalogue & catalogue ) +{ + catalogue.setFileName( catalogueFileName( language(), catalogue ) ); +} + +void KLocale::setDateFormat(const QString & format) +{ + doFormatInit(); + m_dateFormat = format.stripWhiteSpace(); +} + +void KLocale::setDateFormatShort(const QString & format) +{ + doFormatInit(); + m_dateFormatShort = format.stripWhiteSpace(); +} + +void KLocale::setDateMonthNamePossessive(bool possessive) +{ + doFormatInit(); + d->dateMonthNamePossessive = possessive; +} + +void KLocale::setTimeFormat(const QString & format) +{ + doFormatInit(); + m_timeFormat = format.stripWhiteSpace(); +} + +void KLocale::setWeekStartsMonday(bool start) //deprecated +{ + doFormatInit(); + if (start) + d->weekStartDay = 1; + else + d->weekStartDay = 7; +} + +void KLocale::setWeekStartDay(int day) +{ + doFormatInit(); + if (day>7 || day<1) + d->weekStartDay = 1; //Monday is default + else + d->weekStartDay = day; +} + +QString KLocale::dateFormat() const +{ + doFormatInit(); + return m_dateFormat; +} + +QString KLocale::dateFormatShort() const +{ + doFormatInit(); + return m_dateFormatShort; +} + +QString KLocale::timeFormat() const +{ + doFormatInit(); + return m_timeFormat; +} + +void KLocale::setDecimalSymbol(const QString & symbol) +{ + doFormatInit(); + m_decimalSymbol = symbol.stripWhiteSpace(); +} + +void KLocale::setThousandsSeparator(const QString & separator) +{ + doFormatInit(); + // allow spaces here + m_thousandsSeparator = separator; +} + +void KLocale::setPositiveSign(const QString & sign) +{ + doFormatInit(); + m_positiveSign = sign.stripWhiteSpace(); +} + +void KLocale::setNegativeSign(const QString & sign) +{ + doFormatInit(); + m_negativeSign = sign.stripWhiteSpace(); +} + +void KLocale::setPositiveMonetarySignPosition(SignPosition signpos) +{ + doFormatInit(); + m_positiveMonetarySignPosition = signpos; +} + +void KLocale::setNegativeMonetarySignPosition(SignPosition signpos) +{ + doFormatInit(); + m_negativeMonetarySignPosition = signpos; +} + +void KLocale::setPositivePrefixCurrencySymbol(bool prefix) +{ + doFormatInit(); + m_positivePrefixCurrencySymbol = prefix; +} + +void KLocale::setNegativePrefixCurrencySymbol(bool prefix) +{ + doFormatInit(); + m_negativePrefixCurrencySymbol = prefix; +} + +void KLocale::setFracDigits(int digits) +{ + doFormatInit(); + m_fracDigits = digits; +} + +void KLocale::setMonetaryThousandsSeparator(const QString & separator) +{ + doFormatInit(); + // allow spaces here + m_monetaryThousandsSeparator = separator; +} + +void KLocale::setMonetaryDecimalSymbol(const QString & symbol) +{ + doFormatInit(); + m_monetaryDecimalSymbol = symbol.stripWhiteSpace(); +} + +void KLocale::setCurrencySymbol(const QString & symbol) +{ + doFormatInit(); + m_currencySymbol = symbol.stripWhiteSpace(); +} + +int KLocale::pageSize() const +{ + doFormatInit(); + return d->pageSize; +} + +void KLocale::setPageSize(int pageSize) +{ + // #### check if it's in range?? + doFormatInit(); + d->pageSize = pageSize; +} + +KLocale::MeasureSystem KLocale::measureSystem() const +{ + doFormatInit(); + return d->measureSystem; +} + +void KLocale::setMeasureSystem(MeasureSystem value) +{ + doFormatInit(); + d->measureSystem = value; +} + +QString KLocale::defaultLanguage() +{ + return QString::fromLatin1("en_US"); +} + +QString KLocale::defaultCountry() +{ + return QString::fromLatin1("C"); +} + +const char * KLocale::encoding() const +{ + return codecForEncoding()->name(); +} + +int KLocale::encodingMib() const +{ + return codecForEncoding()->mibEnum(); +} + +int KLocale::fileEncodingMib() const +{ + if (d->utf8FileEncoding) + return 106; + return codecForEncoding()->mibEnum(); +} + +QTextCodec * KLocale::codecForEncoding() const +{ + return d->codecForEncoding; +} + +bool KLocale::setEncoding(int mibEnum) +{ + QTextCodec * codec = QTextCodec::codecForMib(mibEnum); + if (codec) + d->codecForEncoding = codec; + + return codec != 0; +} + +QStringList KLocale::languagesTwoAlpha() const +{ + if (d->langTwoAlpha.count()) + return d->langTwoAlpha; + + const QStringList &origList = languageList(); + + QStringList result; + +//US KConfig config(QString::fromLatin1("language.codes"), true, false); + KConfig config(locateLocal("config", QString::fromLatin1("language.codes"))); + config.setGroup("TwoLetterCodes"); + + for ( QStringList::ConstIterator it = origList.begin(); + it != origList.end(); + ++it ) + { + QString lang = *it; + QStringList langLst; + +/*US I changed the following code, because hasKey is not available. +!!! check if my version is correct + if (config.hasKey( lang )) + langLst = config.readListEntry( lang ); + else + { + int i = lang.find('_'); + if (i >= 0) + lang.truncate(i); + langLst << lang; + } +*/ + langLst = config.readListEntry( lang ); + if (langLst.isEmpty()) + { + int i = lang.find('_'); + if (i >= 0) + lang.truncate(i); + langLst << lang; + } + + + for ( QStringList::ConstIterator langIt = langLst.begin(); + langIt != langLst.end(); + ++langIt ) + { + if ( !(*langIt).isEmpty() && !result.contains( *langIt ) ) + result += *langIt; + } + } + d->langTwoAlpha = result; + return result; +} + +QStringList KLocale::allLanguagesTwoAlpha() const +{ + if (!d->languages) +//US d->languages = new KConfig("all_languages", true, false, "locale"); + d->languages = new KConfig(locateLocal( "locale", "all_languages")); + +//US return d->languages->groupList(); + qDebug("KLocale::allLanguagesTwoAlpha has to be fixed."); + return *(new QStringList()); + +} + +QString KLocale::twoAlphaToLanguageName(const QString &code) const +{ + if (!d->languages) +//US d->languages = new KConfig("all_languages", true, false, "locale"); + d->languages = new KConfig(locateLocal( "locale", "all_languages")); + + d->languages->setGroup(code.lower()); + return d->languages->readEntry("Name"); +} + +QStringList KLocale::allCountriesTwoAlpha() const +{ + QStringList countries; + + qDebug("KLocale::allCountriesTwoAlpha has to be fixed."); +//US QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop"); + QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop", true, true); + + for(QStringList::ConstIterator it = paths.begin(); + it != paths.end(); ++it) + { + QString code = (*it).mid((*it).length()-16, 2); + if (code != "/C") + countries.append(code); + } + return countries; +} + +QString KLocale::twoAlphaToCountryName(const QString &code) const +{ +//US KConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale"); + KConfig cfg(locateLocal("locale", "l10n/"+code.lower()+"/entry.desktop")); + cfg.setGroup("KCM Locale"); + return cfg.readEntry("Name"); +} + +void KLocale::setCalendar(const QString & calType) +{ + doFormatInit(); + + d->calendarType = calType; + + delete d->calendar; + d->calendar = 0; +} + +QString KLocale::calendarType() const +{ + doFormatInit(); + + return d->calendarType; +} + +const KCalendarSystem * KLocale::calendar() const +{ + doFormatInit(); + + // Check if it's the correct calendar?!? +//US we are always using the gregorian calendar +//US if ( !d->calendar ) +//US d->calendar = KCalendarSystemFactory::create( d->calendarType, this ); + if ( !d->calendar ) + d->calendar = new KCalendarSystemGregorian; + + return d->calendar; +} + +KLocale::KLocale(const KLocale & rhs) +{ + d = new KLocalePrivate; + + *this = rhs; +} + +KLocale & KLocale::operator=(const KLocale & rhs) +{ + // Numbers and money + m_decimalSymbol = rhs.m_decimalSymbol; + m_thousandsSeparator = rhs.m_thousandsSeparator; + m_currencySymbol = rhs.m_currencySymbol; + m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol; + m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator; + m_positiveSign = rhs.m_positiveSign; + m_negativeSign = rhs.m_negativeSign; + m_fracDigits = rhs.m_fracDigits; + m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol; + m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol; + m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition; + m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition; + + // Date and time + m_timeFormat = rhs.m_timeFormat; + m_dateFormat = rhs.m_dateFormat; + m_dateFormatShort = rhs.m_dateFormatShort; + + m_language = rhs.m_language; + m_country = rhs.m_country; + + // the assignment operator works here + *d = *rhs.d; + d->languages = 0; // Don't copy languages + d->calendar = 0; // Don't copy the calendar + + return *this; +} + +bool KLocale::setCharset(const QString & ) { return true; } +QString KLocale::charset() const { return QString::fromLatin1("UTF-8"); } + + +int KLocale::timezoneOffset( QString timeZone ) +{ + int ret = 1001; + int index = mTimeZoneList.findIndex( timeZone ); + if ( index < 24 ) + ret = ( index-11 ) * 60 ; + return ret; +} + +QStringList KLocale::timeZoneList() const +{ + return mTimeZoneList; +} +void KLocale::setTimezone( const QString &timeZone ) +{ + mTimeZoneOffset = timezoneOffset( timeZone ); +} + +void KLocale::setDaylightSaving( bool b, int start , int end ) +{ + daylightEnabled = b; + daylightStart = start; + daylightEnd = end; + mSouthDaylight = (end < start); + // qDebug("klocale daylight %d %d %d ", b, start , end ); +} + +int KLocale::localTimeOffset( const QDateTime &dt ) +{ + bool addDaylight = false; + if ( daylightEnabled ) { + int d_end, d_start; + int dayofyear = dt.date().dayOfYear(); + int year = dt.date().year(); + int add = 0; + if ( QDate::leapYear(year) ) + add = 1; + QDate date ( year,1,1 ); + if ( daylightEnd > 59 ) + d_end = daylightEnd +add; + else + d_end = daylightEnd; + if ( daylightStart > 59 ) + d_start = daylightStart +add; + else + d_start = daylightStart; + QDate s_date = date.addDays( d_start -1 ); + QDate e_date = date.addDays( d_end -1 ); + int dof = s_date.dayOfWeek(); + if ( dof < 7 ) + s_date = s_date.addDays( -dof ); + dof = e_date.dayOfWeek(); + if ( dof < 7 ) + e_date = e_date.addDays( -dof ); + QTime startTime ( 3,0,0 ); + QDateTime startDt( s_date, startTime ); + QDateTime endDt( e_date, startTime ); + //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( )); + if ( mSouthDaylight ) { + if ( ! ( endDt < dt && dt < startDt) ) + addDaylight = true; + } else { + if ( startDt < dt && dt < endDt ) + addDaylight = true; + + + } + } + int addMin = 0; + if ( addDaylight ) + addMin = 60; + return mTimeZoneOffset + addMin; +} + +void KLocale::setHore24Format ( bool b ) +{ + mHourF24Format = b; +} +void KLocale::setWeekStartMonday( bool b ) +{ + mWeekStartsMonday = b; +} +void KLocale::setIntDateFormat( int i ) +{ + mIntDateFormat = i; +} +void KLocale::setLanguage( int i ) +{ + mLanguage = i; +} + + + diff --git a/microkde/kdecore/klocale_new.h b/microkde/kdecore/klocale_new.h new file mode 100644 index 0000000..777c0bd --- a/dev/null +++ b/microkde/kdecore/klocale_new.h @@ -0,0 +1,1224 @@ +#ifndef MINIKDE_KLOCALE_H +#define MINIKDE_KLOCALE_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qdict.h> + +class QStringList; +class QTextCodec; +class QDate; +class QTime; +class QDateTime; + +class KGlobal; +class KConfig; +class KConfigBase; +class KLocalePrivate; +class KCatalogue; +class KCalendarSystem; + +#ifndef I18N_NOOP +#define I18N_NOOP(x) (x) +#endif + +void setLocaleDict( QDict<char> * dict ); + +/** + * i18n is the function that does everything you need to translate + * a string. You just wrap around every user visible string a i18n + * call to get a QString with the string in the user's preferred + * language. + * + * The argument must be an UTF-8 encoded string (If you only use + * characters that are in US-ASCII, you're on the safe side. But + * for e.g. german umlauts or french accents should be recoded to + * UTF-8) + **/ +QString i18n(const char *text); + +/** + * If the string is too ambiguous to be translated well to a non-english + * language, use this form of i18n to separate lookup string and english + * text. + * @see translate + **/ +QString i18n(const char *index, const char *text); + +/** + * If you want to handle plural forms, use this form of i18n. + * The plural has to contain a %n where n fits into. + * @see translate + **/ +QString i18n(const char *singular, const char *plural, unsigned long n); + +/** + * Qt3's uic generates i18n( "msg", "comment" ) calls which conflict + * with our i18n method. We use uic -tr tr2i18n to redirect + * to the right i18n() function +**/ +inline QString tr2i18n(const char* message, const char* =0) { + return i18n(message); +} + +/** + * + * KLocale provides support for country specific stuff like + * the national language. + * + * KLocale supports translating, as well as specifying the format + * for numbers, currency, time, and date. + * + * @author Stephan Kulow <coolo@kde.org>, Preston Brown <pbrown@kde.org>, + * Hans Petter Bieker <bieker@kde.org>, Lukas Tinkl <lukas.tinkl@suse.cz> + * @short class for supporting locale settings and national language + */ +class KLocale +{ + friend class KGlobal; // for initInstance() +public: + /** + * Constructs a KLocale with the given catalogue name. + * The constructor looks for an entry Locale/Language in the + * configuration file. + * If no config file is specified, it will also look for languages + * using the environment variables (KDE_LANG, LC_MESSAGES, LC_ALL, LANG), + * as well as the global configuration fie. If we were not able to use + * non of the specified languages, the default language (en_US) will be + * used. + * + * If you specify a configuration file, it has to be valid until + * the KLocale object is destroyed. + * + * @param catalogue The name of the main language file + * @param config The configuration file to use. + */ + KLocale( const QString& catalogue, KConfig *config = 0 ); + + /** + * Copy constructor. + */ + KLocale( const KLocale & rhs ); + + /** + * Assignment operator. + */ + KLocale& operator= ( const KLocale & rhs ); + + /** + * Destructor. + */ + ~KLocale(); + + /** + * Translates the string into the corresponding string in + * the national language, if available. If not, returns + * the string itself. + * There is a KDE wide message file that contains the most + * often used phrases, so we can avoid duplicating the + * translation of these phrases. If a phrase is not found + * in the catalogue given to the constructor, it will search + * in the system catalog. This makes it possible to override + * some phrases for your needs. + * + * The argument must be an UTF-8 encoded string (If you only use + * characters that are in US-ASCII you're on the safe side. But + * for e.g. german umlauts or french accents should be recoded to + * UTF-8) + * + * @param index The lookup text and default text, if not found. + */ + QString translate( const char *index ) const; + + /** + * Translates the string into the corresponding string in the + * national language, if available. + * + * The real contents of the string is in the argument fallback, + * but the meaning of it is coded into the argument index. + * In some cases you'll need this function, when english is + * too ambiguous to express it. + * + * Most of the times the translators will tell you if it can't + * be translated as it, but think of cases as "New", where the + * translations differs depending on what is New. + * Or simple cases as "Open", that can be used to express something + * is open or it can be used to express that you want something to + * open... There are tons of such examples. + * + * If translate("Open") is not enough to translate it well, use + * translate("To Open", "Open") or translate("Is Open", "Open"). + * The english user will see "Open" in both cases, but the translated + * version may vary. Of course you can also use i18n() + * + * @param index The lookup text + * @param fallback the default text, if not found + * @return translation + */ + QString translate( const char *index, const char *fallback) const; + + /** + * Used to get the correct, translated singular or plural of a + * word. + * @param singular the singular form of the word, for example "file". + * @param plural the plural form of the word. Must contain a "%n" that will + * be replaced by the number @n, for example "%n files" + * @param n the number + * @return the correct singular or plural for the selected language, + * depending on n + */ + QString translate( const char *singular, const char *plural, + unsigned long n) const; + + /** + * Changes the current encoding. + * + * @param mibEnum The mib of the preferred codec + * + * @return True on success. + */ + bool setEncoding(int mibEnum); + + /** + * Changes the current language. The current language will be left + * unchanged if failed. It will force a reload of the country specific + * configuration as well. + * + * @param language The language code. + * + * @return True on success. + */ + bool setLanguage(const QString & language); + + /** + * Changes the list of prefed languages for the locale. The first valid + * language in the list will be used, or the default (en_US) language + * will be used if non of the specified languages were available. + * + * @param languages The list of language codes. + * + * @return True if one of the specified languages were used. + */ + bool setLanguage(const QStringList & languages); + + /** + * Changes the current country. The current country will be left + * unchanged if failed. It will force a reload of the country specific + * configuration. + * + * @param country The ISO 3166 country code. + * + * @return True on success. + */ + bool setCountry(const QString & country); + + /** + * Various positions for where to place the positive or negative + * sign when they are related to a monetary value. + */ + enum SignPosition { ParensAround = 0, BeforeQuantityMoney = 1, + AfterQuantityMoney = 2, + BeforeMoney = 3, AfterMoney = 4 }; + + /** + * Returns what a decimal point should look like ("." or "," etc.) + * according to the current locale or user settings. + * + * @return The decimal symbol used by locale. + */ + QString decimalSymbol() const; + + /** + * Returns what the thousands separator should look + * like ("," or "." etc.) + * according to the current locale or user settings. + * + * @return The thousands separator used by locale. + */ + QString thousandsSeparator() const; + + /** + * Returns what the symbol denoting currency in the current locale + * as as defined by user settings should look like. + * + * @return The default currency symbol used by locale. + */ + QString currencySymbol() const; + + /** + * Returns what a decimal point should look like ("." or "," etc.) + * for monetary values, according to the current locale or user + * settings. + * + * @return The monetary decimal symbol used by locale. + */ + QString monetaryDecimalSymbol() const; + + /** + * Returns what a thousands separator for monetary values should + * look like ("," or " " etc.) according to the current locale or + * user settings. + * + * @return The monetary thousands separator used by locale. + */ + QString monetaryThousandsSeparator() const; + + /** + * Returns what a positive sign should look like ("+", " ", etc.) + * according to the current locale or user settings. + * + * @return The positive sign used by locale. + */ + QString positiveSign() const; + + /** + * Returns what a negative sign should look like ("-", etc.) + * according to the current locale or user settings. + * + * @return The negative sign used by locale. + */ + QString negativeSign() const; + + /** + * The number of fractional digits to include in numeric/monetary + * values (usually 2). + * + * @return Default number of fractional digits used by locale. + */ + int fracDigits() const; + + /** + * If and only if the currency symbol precedes a positive value, + * this will be true. + * + * @return Where to print the currency symbol for positive numbers. + */ + bool positivePrefixCurrencySymbol() const; + + /** + * If and only if the currency symbol precedes a negative value, + * this will be true. + * + * @return True if the currency symbol precedes negative numbers. + */ + bool negativePrefixCurrencySymbol() const; + + /** + * Returns the position of a positive sign in relation to a + * monetary value. + * + * @return Where/how to print the positive sign. + * @see SignPosition + */ + SignPosition positiveMonetarySignPosition() const; + + /** + * Denotes where to place a negative sign in relation to a + * monetary value. + * + * @return Where/how to print the negative sign. + * @see SignPosition + */ + SignPosition negativeMonetarySignPosition() const; + + /** + * Given a double, converts that to a numeric string containing + * the localized monetary equivalent. + * + * e.g. given 123456, return "$ 123,456.00". + * + * @param num The number we want to format + * @param currency The currency symbol you want. + * @param digits Number of fractional digits, or -1 for the default + * value + * + * @return The number of money as a localized string + * @see fracDigits() + */ + QString formatMoney(double num, + const QString & currency = QString::null, + int digits = -1) const; + + /** + * Given a double, converts that to a numeric string containing + * the localized numeric equivalent. + * + * e.g. given 123456.78F, return "123,456.78" (for some European country). + * If precision isn't specified, 2 is used. + * + * @param num The number to convert + * @param precision Number of fractional digits used. + * + * @return The number as a localized string + */ + QString formatNumber(double num, int precision = -1) const; + + /** + * Given an integer, converts that to a numeric string containing + * the localized numeric equivalent. + * + * e.g. given 123456L, return "123,456" (for some European country). + * + * @param num The number to convert + * + * @return The number as a localized string + * @since 3.2 + */ + QString formatLong(long num) const; + + /** + * Use this to determine whether nouns are declined in + * locale's language. This property should remain + * read-only (no setter function) + * + * @return If nouns are declined + * @since 3.1 + */ + bool nounDeclension() const; + + /** + * Returns a string formatted to the current locale's conventions + * regarding dates. + * + * @param pDate The date to be formated. + * @param shortFormat True for non text dates. + * + * @return The date as a string + */ + QString formatDate(const QDate &pDate, bool shortFormat = false) const; + + /** + * Use this to determine whether in dates a possessive form of month + * name is preferred ("of January" rather than "January") + * + * @return If possessive form should be used + * @since 3.1 + */ + bool dateMonthNamePossessive() const; + + /** + * Returns a string formatted to the current locale's conventions + * regarding times. + * + * @param pTime The time to be formated. + * @param includeSecs if true, seconds are included in the output, + * otherwise only hours and minutes are formatted. + * + * @return The time as a string + */ + QString formatTime(const QTime &pTime, bool includeSecs = false) const; + + /** + * Use this to determine if the user wants a 12 hour clock. + * + * @return If the user wants 12h clock + */ + bool use12Clock() const; + + /** + * @deprecated + * + * Please use the @ref weekStartDay method instead. + * + * Use this to determine if the user wants the week to start on Monday. + * + * @return true if the week starts on Monday + */ + bool weekStartsMonday() const; //### remove for KDE 4.0 + + /** + * Use this to determine which day is the first day of the week. + * + * @return an integer (Monday=1..Sunday=7) + * @since 3.1 + */ + int weekStartDay() const; + + /** + * @deprecated + * + * Returns a string containing the name of the month name used in the Gregorian calendar. + * + * @param i the month number of the year starting at 1/January. + * @param shortName we will return the short version of the string. + * + * @return The name of the month + */ + QString monthName(int i, bool shortName = false) const; + + /** + * @deprecated + * + * Returns a string containing the possessive form of the month name used in the Gregorian calendar. + * ("of January", "of February", etc.) + * It's needed in long format dates in some languages. + * + * @param i the month number of the year starting at 1/January. + * @param shortName we will return the short version of the string. + * + * @return The possessive form of the name of the month + * @since 3.1 + */ + QString monthNamePossessive(int i, bool shortName = false) const; + + /** + * @deprecated + * + * Returns a string containing the name of the week day used in the Gregorian calendar. + * + * @param i the day number of the week starting at 1/Monday. + * @param shortName we will return the short version of the string. + * + * @return The name of the day + */ + QString weekDayName(int i, bool shortName = false) const; + + /** + * Returns a pointer to the calendar system object. + * + * @return the current calendar system instance + * @since 3.2 + */ + const KCalendarSystem * calendar() const; + + /** + * Returns the name of the calendar system that is currently being + * used by the system. + * + * @return the name of the calendar system + * @since 3.2 + */ + QString calendarType() const; + + /** + * Changes the current calendar system to the calendar specified. + * Currently is "gregorian" and "hijri" supported. If the calendar + * system specified is not found, gregorian will be used. + * + * @param calendarType the name of the calendar type + * @since 3.2 + */ + void setCalendar(const QString & calendarType); + + /** + * Returns a string formated to the current locale's conventions + * regarding both date and time. + * + * @param pDateTime The date and time to be formated. + * @param shortFormat using the short date format. + * @param includeSecs using the short date format. + * + * @return The date and time as a string + */ + QString formatDateTime(const QDateTime &pDateTime, + bool shortFormat = true, + bool includeSecs = false) const; + + /** + * Converts a localized monetary string to a double. + * + * @param numStr the string we want to convert. + * @param ok the boolean that is set to false if it's not a number. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a double + */ + double readMoney(const QString &numStr, bool * ok = 0) const; + + /** + * Converts a localized numeric string to a double. + * + * @param numStr the string we want to convert. + * @param ok the boolean that is set to false if it's not a number. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a double + */ + double readNumber(const QString &numStr, bool * ok = 0) const; + + /** + * Converts a localized date string to a QDate. + * The bool pointed by ok will be invalid if the date entered was not valid. + * + * @param str the string we want to convert. + * @param ok the boolean that is set to false if it's not a valid date. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QDate + */ + QDate readDate(const QString &str, bool* ok = 0) const; + + /** + * Converts a localized date string to a QDate, using the specified format. + * You will usually not want to use this method. + */ + QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const; + + enum ReadDateFlags { + NormalFormat = 1, + ShortFormat = 2 + }; + + /** + * Converts a localized date string to a QDate. + * This method is stricter than readDate(str,&ok): it will either accept + * a date in full format or a date in short format, depending on @p flags. + * + * @param str the string we want to convert. + * @param flags whether the date string is to be in full format or in short format. + * @param ok the boolean that is set to false if it's not a valid date. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QDate + * @since 3.2 + */ + QDate readDate(const QString &str, ReadDateFlags flags, bool *ok = 0) const; + + /** + * Converts a localized time string to a QTime. + * This method will try to parse it with seconds, then without seconds. + * The bool pointed by ok will be false if the time entered was not valid. + * + * @param str the string we want to convert. + * @param ok the boolean that is set to false if it's not a valid time. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QTime + */ + QTime readTime(const QString &str, bool* ok = 0) const; + + enum ReadTimeFlags { + WithSeconds = 0, // default (no flag set) + WithoutSeconds = 1 + }; // (maybe use this enum as a bitfield, if adding independent features?) + /** + * Converts a localized time string to a QTime. + * This method is stricter than readTime(str,&ok): it will either accept + * a time with seconds or a time without seconds. + * Use this method when the format is known by the application. + * + * @param str the string we want to convert. + * @param flags whether the time string is expected to contain seconds or not. + * @param ok the boolean that is set to false if it's not a valid time. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QTime + * @since 3.2 + */ + QTime readTime(const QString &str, ReadTimeFlags flags, bool *ok = 0) const; + + /** + * Returns the language used by this object. The domain AND the + * library translation must be available in this language. + * @ref defaultLanguage() is returned by default, if no other available. + * + * @return The currently used language. + */ + QString language() const; + + /** + * Returns the country code of the country where the user lives. + * @ref defaultCountry() is returned by default, if no other available. + * + * @return The country code for the user. + */ + QString country() const; + + /** + * Returns the preferred languages as ISO 639-1 codes. This means + * that information about country is removed. If the internal language + * code might be represented by more than one 639-1 code, they will all be + * listed (but only once). + * + * If the selected languages are "nn, nb, pt_BR", you will get: + * "nn, no, nb, pt". + * + * @return List of language codes + * + * @see languageList + */ + QStringList languagesTwoAlpha() const; + + /** + * Returns the languages selected by user. The codes returned here is the + * internal language codes. + * + * @return List of language codes + * + * @see languagesTwoAlpha + */ + QStringList languageList() const; + + /** + * Returns the user's preferred encoding. + * + * @return The name of the preferred encoding + * + * @see codecForEncoding + * @see encodingMib + */ + const char * encoding() const; + + /** + * Returns the user's preferred encoding. + * + * @return The Mib of the preferred encoding + * + * @see encoding + * @see codecForEncoding + */ + int encodingMib() const; + /** + * Returns the user's preferred encoding. Should never be NULL. + * + * @return The codec for the preferred encoding + * + * @see encoding + * @see encodingMib + */ + QTextCodec * codecForEncoding() const; + + /** + * Returns the file encoding. + * + * @return The Mib of the file encoding + * + * @see QFile::encodeName + * @see QFile::decodeName + */ + int fileEncodingMib() const; + + /** + * Changes the current date format. + * + * The format of the date is a string which contains variables that will + * be replaced: + * @li %Y with the century (e.g. "19" for "1984") + * @li %y with the lower 2 digits of the year (e.g. "84" for "1984") + * @li %n with the month (January="1", December="12") + * @li %m with the month with two digits (January="01", December="12") + * @li %e with the day of the month (e.g. "1" on the first of march) + * @li %d with the day of the month with two digits(e.g. "01" on the first of march) + * @li %b with the short form of the month (e.g. "Jan" for January) + * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday) + * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday) + * Everything else in the format string will be taken as is. + * For example, March 20th 1989 with the format "%y:%m:%d" results + * in "89:03:20". + * + * @param format The new date format + */ + void setDateFormat(const QString & format); + /** + * Changes the current short date format. + * + * The format of the date is a string which contains variables that will + * be replaced: + * @li %Y with the century (e.g. "19" for "1984") + * @li %y with the lower 2 digits of the year (e.g. "84" for "1984") + * @li %n with the month (January="1", December="12") + * @li %m with the month with two digits (January="01", December="12") + * @li %e with the day of the month (e.g. "1" on the first of march) + * @li %d with the day of the month with two digits(e.g. "01" on the first of march) + * @li %b with the short form of the month (e.g. "Jan" for January) + * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday) + * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday) + * Everything else in the format string will be taken as is. + * For example, March 20th 1989 with the format "%y:%m:%d" results + * in "89:03:20". + * + * @param format The new short date format + */ + void setDateFormatShort(const QString & format); + /** + * Changes the form of month name used in dates. + * + * @param possessive True if possessive forms should be used + * @since 3.1 + */ + void setDateMonthNamePossessive(bool possessive); + /** + * Changes the current time format. + * + * The format of the time is string a which contains variables that will + * be replaced: + * @li %H with the hour in 24h format and 2 digits (e.g. 5pm is "17", 5am is "05") + * @li %k with the hour in 24h format and one digits (e.g. 5pm is "17", 5am is "5") + * @li %I with the hour in 12h format and 2 digits (e.g. 5pm is "05", 5am is "05") + * @li %l with the hour in 12h format and one digits (e.g. 5pm is "5", 5am is "5") + * @li %M with the minute with 2 digits (e.g. the minute of 07:02:09 is "02") + * @li %S with the seconds with 2 digits (e.g. the minute of 07:02:09 is "09") + * @li %p with pm or am (e.g. 17.00 is "pm", 05.00 is "am") + * Everything else in the format string will be taken as is. + * For example, 5.23pm with the format "%H:%M" results + * in "17:23". + * + * @param format The new time format + */ + void setTimeFormat(const QString & format); + + /** + * @deprecated + * + * Please use @ref setWeekStartDay instead. + * + * Changes how KLocale defines the first day in week. + * + * @param start True if Monday is the first day in the week + */ + void setWeekStartsMonday(bool start); //### remove for KDE 4.0 + + /** + * Changes how KLocale defines the first day in week. + * + * @param day first day of the week (Monday=1..Sunday=7) as integer + * @since 3.1 + */ + void setWeekStartDay(int day); + /** + * Returns the currently selected date format. + * + * @return Current date format. + * @see setDateFormat() + */ + QString dateFormat() const; + /** + * Returns the currently selected short date format. + * + * @return Current short date format. + * @see setDateFormatShort() + */ + QString dateFormatShort() const; + /** + * Returns the currently selected time format. + * + * @return Current time format. + * @see setTimeFormat() + */ + QString timeFormat() const; + + /** + * Changes the symbol used to identify the decimal pointer. + * + * @param symbol The new decimal symbol. + */ + void setDecimalSymbol(const QString & symbol); + /** + * Changes the separator used to group digits when formating numbers. + * + * @param separator The new thousands separator. + */ + void setThousandsSeparator(const QString & separator); + /** + * Changes the sign used to identify a positive number. Normally this is + * left blank. + * + * @param sign Sign used for positive numbers. + */ + void setPositiveSign(const QString & sign); + /** + * Changes the sign used to identify a negative number. + * + * @param sign Sign used for negative numbers. + */ + void setNegativeSign(const QString & sign); + /** + * Changes the sign position used for positive monetary values. + * + * @param signpos The new sign position + */ + void setPositiveMonetarySignPosition(SignPosition signpos); + /** + * Changes the sign position used for negative monetary values. + * + * @param signpos The new sign position + */ + void setNegativeMonetarySignPosition(SignPosition signpos); + /** + * Changes the position where the currency symbol should be printed for + * positive monetary values. + * + * @param prefix True if the currency symbol should be prefixed instead of + * postfixed + */ + void setPositivePrefixCurrencySymbol(bool prefix); + /** + * Changes the position where the currency symbol should be printed for + * negative monetary values. + * + * @param prefix True if the currency symbol should be prefixed instead of + * postfixed + */ + void setNegativePrefixCurrencySymbol(bool prefix); + /** + * Changes the number of digits used when formating numbers. + * + * @param digits The default number of digits to use. + */ + void setFracDigits(int digits); + /** + * Changes the separator used to group digits when formating monetary values. + * + * @param separator The new thousands separator. + */ + void setMonetaryThousandsSeparator(const QString & separator); + /** + * Changes the symbol used to identify the decimal pointer for monetary + * values. + * + * @param symbol The new decimal symbol. + */ + void setMonetaryDecimalSymbol(const QString & symbol); + /** + * Changes the current currency symbol. + * + * @param symbol The new currency symbol + */ + void setCurrencySymbol(const QString & symbol); + + /** + * Returns the preferred page size for printing. + * + * @return The preferred page size, cast it to QPrinter::PageSize + */ + int pageSize() const; + + /** + * Changes the preferred page size when printing. + * + * @param paperFormat the new preferred page size in the format QPrinter::PageSize + */ + void setPageSize(int paperFormat); + + /** + * The Metric system will give you information in mm, while the + * Imperial system will give you information in inches. + */ + enum MeasureSystem { Metric, Imperial }; + + /** + * Returns which measuring system we use. + * + * @return The preferred measuring system + */ + MeasureSystem measureSystem() const; + + /** + * Changes the preferred measuring system. + * + * @return value The preferred measuring system + */ + void setMeasureSystem(MeasureSystem value); + + /** + * Adds another catalogue to search for translation lookup. + * This function is useful for extern libraries and/or code, + * that provides its own messages. + * + * If the catalogue does not exist for the chosen language, + * it will be ignored and en_US will be used. + * + * @param catalogue The catalogue to add. + */ + void insertCatalogue(const QString& catalogue); + + /** + * Removes a catalog for translation lookup. + * @param catalogue The catalogue to remove. + * @see insertCatalogue() + */ + void removeCatalogue(const QString &catalogue); + + /** + * Sets the active catalog for translation lookup. + * @param catalogue The catalogue to activate. + */ + void setActiveCatalogue(const QString &catalogue); + + /** + * Translates a message as a QTranslator is supposed to. + * The parameters are similar to i18n(), but the result + * value has other semantics (it can be QString::null) + * @since 3.1 + **/ + QString translateQt(const char *context, + const char *sourceText, + const char *message) const; + + /** + * Returns list of all known ISO 639-1 codes. + * @return a list of all language codes + * @since 3.1 + */ + QStringList allLanguagesTwoAlpha() const; + + /** + * Convert a ISO 639-1 code to a human readable form. + * @param code the language ISO 639-1 code + * @return the human readable form + * @since 3.1 + */ + QString twoAlphaToLanguageName(const QString &code) const; + + /** + * Returns list of all known country codes. + * @return a list of all country codes + * @since 3.1 + */ + QStringList allCountriesTwoAlpha() const; + + /** + * Convert a country code to a human readable form. + * @param code the country code + * @return the human readable form of the country name + * @since 3.1 + */ + QString twoAlphaToCountryName(const QString &code) const; + + + + int timezoneOffset( QString ); + QStringList timeZoneList() const; + void setDaylightSaving( bool, int , int ); + int localTimeOffset(const QDateTime &); + void setTimezone( const QString &timeZone ); + + void setHore24Format ( bool ); + void setWeekStartMonday( bool ); + void setIntDateFormat( int ); + void setLanguage( int ); + + + + /** + * Returns the parts of the parameter str understood as language setting + * the format is language_COUNTRY.charset + * + * @param str The string to split. + * @param language This will be set to the language part of the string. + * @param country This will be set to the country part of the string. + * @param charset This will be set to the charset part of the string. + */ + static void splitLocale(const QString & str, + QString & language, + QString & country, + QString & charset); + + /** + * Use this to as main catalogue for *all* KLocales, if not the appname + * will be used. This function is best to be the very first instruction + * in your program's main function as it only has an effect before the + * first KLocale object is created (and this is in common KDE applications + * quite early). + * + * @param catalogue Catalogue to override all other main catalogues. + */ + static void setMainCatalogue(const char *catalogue); + + /** + * Finds localized resource in resourceDir( rtype ) + \<lang> + fname. + * + * @param fname relative path to find + * @param rtype resource type to use + */ + static QString langLookup(const QString &fname, const char *rtype = "html"); + + /** + * Returns the name of the internal language. + * + * @return Name of the default language + */ + static QString defaultLanguage(); + + /** + * Returns the name of the default country. + * + * @return Name of the default country + */ + static QString defaultCountry(); + + + /** + * @internal Called from KConfigBackend to initialize language. + */ + static QString _initLanguage(KConfigBase *config); + +#ifdef KDE_NO_COMPAT +private: +#endif + /** + * @deprecated + * use formatMoney(double) + */ + QString formatMoney(const QString &numStr) const; + + /** + * @deprecated + * use formatNumber(double) + */ + QString formatNumber(const QString &numStr) const; + + /** + * @deprecated + * Use languageList() + * + * @return String containing language codes separated by colons + */ + QString languages() const; + + /** + * @deprecated + * @return True + */ + bool setCharset(const QString & charset); + + /** + * @deprecated + * @see encoding + */ + QString charset() const; + +protected: + /** + * @internal Creates a KLocale object for KGlobal and inits the locale + * pointer. + */ + static void initInstance(); + +private: + /** + * @internal Inits the localization part of the instance with the config + * object. + * + * @param config The configuration object used for init. + */ + void initFormat(KConfig *config); + + /** + * @internal Inits the language part of the instance with the given config + * object. It should be valid and contain the global entries. + * + * @param config The configuration object used for init + * @param useEnv True if we should use environment variables + */ + void initLanguage(KConfig * config, bool useEnv); + + /** + * @internal Figures out which encoding the user prefers. + * + * @param config The configuration object used for init + */ + void initEncoding(KConfig * config); + + /** + * @internal Figures out which catalogues to use. + * + * @param catalogue The name of the main catalogue + */ + void initCatalogue(const QString & catalogue); + + /** + * @internal Figures out which encoding the user prefers for filenames + * and sets up the appropriate QFile encoding and decoding functions. + */ + void initFileNameEncoding(KConfig *config); + + /** + * @internal A QFile filename encoding function (QFile::encodeFn). + */ + static QCString encodeFileNameUTF8( const QString & fileName ); + + /** + * @internal QFile filename decoding function (QFile::decodeFn). + */ + static QString decodeFileNameUTF8( const QCString & localFileName ); + + /** + * @internal Changes the file name of the catalogue to the correct + * one. + */ + void initCatalogue( KCatalogue & catalogue ); + + /** + * @internal Reads the language and format configuration form disk. + */ + void doBindInit(); + + /** + * @internal Ensures that the format configuration is read. + */ + void doFormatInit() const; + + /** + * @internal Reads the format configuration from disk. + */ + void initFormat(); + + /** + * @internal function used by the two translate versions + */ + QString translate_priv(const char *index, + const char *text, + const char ** original = 0) const; + + /** + * @internal function used to determine if we are using the en_US translation + */ + bool useDefaultLanguage() const; + + /** + * @internal Checks if the specified language is installed + */ + bool isLanguageInstalled(const QString & language) const; + + /** + * @internal Retrieves the file name of the catalogue, or QString::null + * if not found. + */ + static QString catalogueFileName(const QString & language, + const KCatalogue & catalogue); + + +private: + // Numbers and money + QString m_decimalSymbol; + QString m_thousandsSeparator; + QString m_currencySymbol; + QString m_monetaryDecimalSymbol; + QString m_monetaryThousandsSeparator; + QString m_positiveSign; + QString m_negativeSign; + int m_fracDigits; + SignPosition m_positiveMonetarySignPosition; + SignPosition m_negativeMonetarySignPosition; + + // Date and time + QString m_timeFormat; + QString m_dateFormat; + QString m_dateFormatShort; + + QString m_language; + QString m_country; + + QStringList mTimeZoneList; + bool daylightEnabled; + int mDaylightTZoffset; + int mNondaylightTZoffset; + bool mSouthDaylight; + int daylightStart, daylightEnd, mTimeZoneOffset; + bool mWeekStartsMonday; + bool mHourF24Format; + int mIntDateFormat; + int mLanguage; + + + + + bool m_weekStartsMonday; //### remove for KDE 4.0 + bool m_positivePrefixCurrencySymbol; + bool m_negativePrefixCurrencySymbol; + + KLocalePrivate *d; +}; + +#endif diff --git a/microkde/kdecore/kmdcodec.cpp b/microkde/kdecore/kmdcodec.cpp new file mode 100644 index 0000000..bc03569 --- a/dev/null +++ b/microkde/kdecore/kmdcodec.cpp @@ -0,0 +1,1127 @@ +/* + Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) + version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. + RSA Data Security, Inc. Created 1991. All rights reserved. + + The KMD5 class is based on a C++ implementation of + "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by + Mordechai T. Abzug, Copyright (c) 1995. This implementation + passes the test-suite as defined in RFC 1321. + + The encoding and decoding utilities in KCodecs with the exception of + quoted-printable are based on the java implementation in HTTPClient + package by Ronald Tschal� Copyright (C) 1996-1999. + + The quoted-printable codec as described in RFC 2045, section 6.7. is by + Rik Hemsley (C) 2001. +*/ + +//US #include <config.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <kdebug.h> +#include "kmdcodec.h" + +#define KMD5_S11 7 +#define KMD5_S12 12 +#define KMD5_S13 17 +#define KMD5_S14 22 +#define KMD5_S21 5 +#define KMD5_S22 9 +#define KMD5_S23 14 +#define KMD5_S24 20 +#define KMD5_S31 4 +#define KMD5_S32 11 +#define KMD5_S33 16 +#define KMD5_S34 23 +#define KMD5_S41 6 +#define KMD5_S42 10 +#define KMD5_S43 15 +#define KMD5_S44 21 + +const char KCodecs::Base64EncMap[64] = +{ + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, + 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F +}; + +const char KCodecs::Base64DecMap[128] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const char KCodecs::UUEncMap[64] = +{ + 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F +}; + +const char KCodecs::UUDecMap[128] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const char KCodecs::hexChars[16] = +{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +const unsigned int KCodecs::maxQPLineLength = 70; + + +/******************************** KCodecs ********************************/ +// strchr(3) for broken systems. +static int rikFindChar(register const char * _s, const char c) +{ + register const char * s = _s; + + while (true) + { + if ((0 == *s) || (c == *s)) break; ++s; + if ((0 == *s) || (c == *s)) break; ++s; + if ((0 == *s) || (c == *s)) break; ++s; + if ((0 == *s) || (c == *s)) break; ++s; + } + + return s - _s; +} + +QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF) +{ + QByteArray out; + quotedPrintableEncode (in, out, useCRLF); + return QCString (out.data(), out.size()+1); +} + +QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF) +{ + if (str.isEmpty()) + return ""; + + QByteArray in (str.length()); + memcpy (in.data(), str.data(), str.length()); + return quotedPrintableEncode(in, useCRLF); +} + +void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF) +{ + out.resize (0); + if (in.isEmpty()) + return; + + char *cursor; + const char *data; + unsigned int lineLength; + unsigned int pos; + + const unsigned int length = in.size(); + const unsigned int end = length - 1; + + + // Reasonable guess for output size when we're encoding + // mostly-ASCII data. It doesn't really matter, because + // the underlying allocation routines are quite efficient, + // but it's nice to have 0 allocations in many cases. + out.resize ((length*12)/10); + cursor = out.data(); + data = in.data(); + lineLength = 0; + pos = 0; + + for (unsigned int i = 0; i < length; i++) + { + unsigned char c (data[i]); + + // check if we have to enlarge the output buffer, use + // a safety margin of 16 byte + pos = cursor-out.data(); + if (out.size()-pos < 16) { + out.resize(out.size()+4096); + cursor = out.data()+pos; + } + + // Plain ASCII chars just go straight out. + + if ((c >= 33) && (c <= 126) && ('=' != c)) + { + *cursor++ = c; + ++lineLength; + } + + // Spaces need some thought. We have to encode them at eol (or eof). + + else if (' ' == c) + { + if + ( + (i >= length) + || + ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2])) + || + (!useCRLF && ('\n' == data[i + 1])))) + ) + { + *cursor++ = '='; + *cursor++ = '2'; + *cursor++ = '0'; + + lineLength += 3; + } + else + { + *cursor++ = ' '; + ++lineLength; + } + } + // If we find a line break, just let it through. + else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) || + (!useCRLF && ('\n' == c))) + { + lineLength = 0; + + if (useCRLF) { + *cursor++ = '\r'; + *cursor++ = '\n'; + ++i; + } else { + *cursor++ = '\n'; + } + } + + // Anything else is converted to =XX. + + else + { + *cursor++ = '='; + *cursor++ = hexChars[c / 16]; + *cursor++ = hexChars[c % 16]; + + lineLength += 3; + } + + // If we're approaching the maximum line length, do a soft line break. + + if ((lineLength > maxQPLineLength) && (i < end)) + { + if (useCRLF) { + *cursor++ = '='; + *cursor++ = '\r'; + *cursor++ = '\n'; + } else { + *cursor++ = '='; + *cursor++ = '\n'; + } + + lineLength = 0; + } + } + + out.truncate(cursor - out.data()); +} + +QCString KCodecs::quotedPrintableDecode(const QByteArray & in) +{ + QByteArray out; + quotedPrintableDecode (in, out); + return QCString (out.data(), out.size()+1); +} + +QCString KCodecs::quotedPrintableDecode(const QCString & str) +{ + if (str.isEmpty()) + return ""; + + QByteArray in (str.length()); + memcpy (in.data(), str.data(), str.length()); + return quotedPrintableDecode (in); +} + +void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out) +{ + // clear out the output buffer + out.resize (0); + if (in.isEmpty()) + return; + + char *cursor; + const char *data; + const unsigned int length = in.size(); + + data = in.data(); + out.resize (length); + cursor = out.data(); + + for (unsigned int i = 0; i < length; i++) + { + char c(in.at(i)); + + if ('=' == c) + { + if (i < length - 2) + { + char c1 = in.at(i + 1); + char c2 = in.at(i + 2); + + if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) + { + // Soft line break. No output. + if ('\r' == c1) + i += 2; // CRLF line breaks + else + i += 1; + } + else + { + // =XX encoded byte. + + int hexChar0 = rikFindChar(hexChars, c1); + int hexChar1 = rikFindChar(hexChars, c2); + + if (hexChar0 < 16 && hexChar1 < 16) + { + *cursor++ = char((hexChar0 * 16) | hexChar1); + i += 2; + } + } + } + } + else + { + *cursor++ = c; + } + } + + out.truncate(cursor - out.data()); +} + +QCString KCodecs::base64Encode( const QCString& str, bool insertLFs ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in (str.length()); + memcpy( in.data(), str.data(), str.length() ); + return base64Encode( in, insertLFs ); +} + +QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs ) +{ + QByteArray out; + base64Encode( in, out, insertLFs ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::base64Encode( const QByteArray& in, QByteArray& out, + bool insertLFs ) +{ + // clear out the output buffer + out.resize (0); + if ( in.isEmpty() ) + return; + + unsigned int sidx = 0; + unsigned int didx = 0; + const char* data = in.data(); + const unsigned int len = in.size(); + + unsigned int out_len = ((len+2)/3)*4; + + // Deal with the 76 characters or less per + // line limit specified in RFC 2045 on a + // pre request basis. + insertLFs = (insertLFs && out_len > 76); + if ( insertLFs ) + out_len += ((out_len-1)/76); + + int count = 0; + out.resize( out_len ); + + // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion + if ( len > 1 ) + { + while (sidx < len-2) + { + if ( insertLFs ) + { + if ( count && (count%76) == 0 ) + out.at(didx++) = '\n'; + count += 4; + } + out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = Base64EncMap[(data[sidx+2] >> 6) & 003 | + (data[sidx+1] << 2) & 077]; + out.at(didx++) = Base64EncMap[data[sidx+2] & 077]; + sidx += 3; + } + } + + if (sidx < len) + { + if ( insertLFs && (count > 0) && (count%76) == 0 ) + out.at(didx++) = '\n'; + + out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077]; + if (sidx < len-1) + { + out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = Base64EncMap[(data[sidx+1] << 2) & 077]; + } + else + { + out.at(didx++) = Base64EncMap[(data[sidx] << 4) & 077]; + } + } + + // Add padding + while (didx < out.size()) + { + out.at(didx) = '='; + didx++; + } +} + +QCString KCodecs::base64Decode( const QCString& str ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in( str.length() ); + memcpy( in.data(), str.data(), str.length() ); + return base64Decode( in ); +} + +QCString KCodecs::base64Decode( const QByteArray& in ) +{ + QByteArray out; + base64Decode( in, out ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::base64Decode( const QByteArray& in, QByteArray& out ) +{ + out.resize(0); + if ( in.isEmpty() ) + return; + + unsigned int count = 0; + unsigned int len = in.size(), tail = len; + const char* data = in.data(); + + // Deal with possible *nix "BEGIN" marker!! + while ( count < len && (data[count] == '\n' || data[count] == '\r' || + data[count] == '\t' || data[count] == ' ') ) + count++; + + if ( QString(data+count).left(5).lower() == "begin" ) + { + count += 5; + while ( count < len && data[count] != '\n' && data[count] != '\r' ) + count++; + + while ( count < len && (data[count] == '\n' || data[count] == '\r') ) + count ++; + + data += count; + tail = (len -= count); + } + + // Find the tail end of the actual encoded data even if + // there is/are trailing CR and/or LF. + while ( data[tail-1] == '=' || data[tail-1] == '\n' || + data[tail-1] == '\r' ) + if ( data[--tail] != '=' ) len = tail; + + unsigned int outIdx = 0; + out.resize( (count=len) ); + for (unsigned int idx = 0; idx < count; idx++) + { + // Adhere to RFC 2045 and ignore characters + // that are not part of the encoding table. + unsigned char ch = data[idx]; + if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || + (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') + { + out.at(outIdx++) = Base64DecMap[ch]; + } + else + { + len--; + tail--; + } + } + + // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl; + + // 4-byte to 3-byte conversion + len = (tail>(len/4)) ? tail-(len/4) : 0; + unsigned int sidx = 0, didx = 0; + if ( len > 1 ) + { + while (didx < len-2) + { + out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003)); + out.at(didx+1) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017)); + out.at(didx+2) = (((out.at(sidx+2) << 6) & 255) | (out.at(sidx+3) & 077)); + sidx += 4; + didx += 3; + } + } + + if (didx < len) + out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003)); + + if (++didx < len ) + out.at(didx) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017)); + + // Resize the output buffer + if ( len == 0 || len < out.size() ) + out.resize(len); +} + +QCString KCodecs::uuencode( const QCString& str ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in; + in.resize( str.length() ); + memcpy( in.data(), str.data(), str.length() ); + return uuencode( in ); +} + +QCString KCodecs::uuencode( const QByteArray& in ) +{ + QByteArray out; + uuencode( in, out ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::uuencode( const QByteArray& in, QByteArray& out ) +{ + out.resize( 0 ); + if( in.isEmpty() ) + return; + + unsigned int sidx = 0; + unsigned int didx = 0; + unsigned int line_len = 45; + + const char nl[] = "\n"; + const char* data = in.data(); + const unsigned int nl_len = strlen(nl); + const unsigned int len = in.size(); + + out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) ); + // split into lines, adding line-length and line terminator + while (sidx+line_len < len) + { + // line length + out.at(didx++) = UUEncMap[line_len]; + + // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion + for (unsigned int end = sidx+line_len; sidx < end; sidx += 3) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 | + (data[sidx+1] << 2) & 077]; + out.at(didx++) = UUEncMap[data[sidx+2] & 077]; + } + + // line terminator + //for (unsigned int idx=0; idx < nl_len; idx++) + //out.at(didx++) = nl[idx]; + memcpy(out.data()+didx, nl, nl_len); + didx += nl_len; + } + + // line length + out.at(didx++) = UUEncMap[len-sidx]; + // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion + while (sidx+2 < len) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 | + (data[sidx+1] << 2) & 077]; + out.at(didx++) = UUEncMap[data[sidx+2] & 077]; + sidx += 3; + } + + if (sidx < len-1) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] << 2) & 077]; + out.at(didx++) = UUEncMap[0]; + } + else if (sidx < len) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[0]; + out.at(didx++) = UUEncMap[0]; + } + + // line terminator + memcpy(out.data()+didx, nl, nl_len); + didx += nl_len; + + // sanity check + if ( didx != out.size() ) + out.resize( 0 ); +} + +QCString KCodecs::uudecode( const QCString& str ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in; + in.resize( str.length() ); + memcpy( in.data(), str.data(), str.length() ); + return uudecode( in ); +} + +QCString KCodecs::uudecode( const QByteArray& in ) +{ + QByteArray out; + uudecode( in, out ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::uudecode( const QByteArray& in, QByteArray& out ) +{ + out.resize( 0 ); + if( in.isEmpty() ) + return; + + unsigned int sidx = 0; + unsigned int didx = 0; + unsigned int len = in.size(); + unsigned int line_len, end; + const char* data = in.data(); + + // Deal with *nix "BEGIN"/"END" separators!! + unsigned int count = 0; + while ( count < len && (data[count] == '\n' || data[count] == '\r' || + data[count] == '\t' || data[count] == ' ') ) + count ++; + + bool hasLF = false; + if ( QString( data+count).left(5).lower() == "begin" ) + { + count += 5; + while ( count < len && data[count] != '\n' && data[count] != '\r' ) + count ++; + + while ( count < len && (data[count] == '\n' || data[count] == '\r') ) + count ++; + + data += count; + len -= count; + hasLF = true; + } + + out.resize( len/4*3 ); + while ( sidx < len ) + { + // get line length (in number of encoded octets) + line_len = UUDecMap[ (unsigned char) data[sidx++]]; + // ascii printable to 0-63 and 4-byte to 3-byte conversion + end = didx+line_len; + char A, B, C, D; + if (end > 2) { + while (didx < end-2) + { + A = UUDecMap[(unsigned char) data[sidx]]; + B = UUDecMap[(unsigned char) data[sidx+1]]; + C = UUDecMap[(unsigned char) data[sidx+2]]; + D = UUDecMap[(unsigned char) data[sidx+3]]; + out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) ); + out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) ); + out.at(didx++) = ( ((C << 6) & 255) | (D & 077) ); + sidx += 4; + } + } + + if (didx < end) + { + A = UUDecMap[(unsigned char) data[sidx]]; + B = UUDecMap[(unsigned char) data[sidx+1]]; + out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) ); + } + + if (didx < end) + { + B = UUDecMap[(unsigned char) data[sidx+1]]; + C = UUDecMap[(unsigned char) data[sidx+2]]; + out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) ); + } + + // skip padding + while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r') + sidx++; + + // skip end of line + while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r')) + sidx++; + + // skip the "END" separator when present. + if ( hasLF && QString( data+sidx).left(3).lower() == "end" ) + break; + } + + if ( didx < out.size() ) + out.resize( didx ); +} + +/******************************** KMD5 ********************************/ +KMD5::KMD5() +{ + init(); +} + +KMD5::KMD5(const char *in, int len) +{ + init(); + update(in, len); +} + +KMD5::KMD5(const QByteArray& in) +{ + init(); + update( in ); +} + +KMD5::KMD5(const QCString& in) +{ + init(); + update( in ); +} + +void KMD5::update(const QByteArray& in) +{ + update(in.data(), int(in.size())); +} + +void KMD5::update(const QCString& in) +{ + update(in.data(), int(in.length())); +} + +void KMD5::update(const unsigned char* in, int len) +{ + if (len < 0) + len = qstrlen(reinterpret_cast<const char*>(in)); + + if (!len) + return; + + if (m_finalized) { + kdWarning() << "KMD5::update called after state was finalized!" << endl; + return; + } + + Q_UINT32 in_index; + Q_UINT32 buffer_index; + Q_UINT32 buffer_space; + Q_UINT32 in_length = static_cast<Q_UINT32>( len ); + + buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F); + + if ( (m_count[0] += (in_length << 3))<(in_length << 3) ) + m_count[1]++; + + m_count[1] += (in_length >> 29); + buffer_space = 64 - buffer_index; + + if (in_length >= buffer_space) + { + memcpy (m_buffer + buffer_index, in, buffer_space); + transform (m_buffer); + + for (in_index = buffer_space; in_index + 63 < in_length; + in_index += 64) + transform (reinterpret_cast<const unsigned char*>(in+in_index)); + + buffer_index = 0; + } + else + in_index=0; + + memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index); +} + +bool KMD5::update(QIODevice& file) +{ + char buffer[1024]; + int len; + + while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) + update(buffer, len); + + return file.atEnd(); +} + +void KMD5::finalize () +{ + if (m_finalized) return; + + Q_UINT8 bits[8]; + Q_UINT32 index, padLen; + static unsigned char PADDING[64]= + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + encode (bits, m_count, 8); + //memcpy( bits, m_count, 8 ); + + // Pad out to 56 mod 64. + index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update (reinterpret_cast<const char*>(PADDING), padLen); + + // Append length (before padding) + update (reinterpret_cast<const char*>(bits), 8); + + // Store state in digest + encode (m_digest, m_state, 16); + //memcpy( m_digest, m_state, 16 ); + + // Fill sensitive information with zero's + memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); + + m_finalized = true; +} + + +bool KMD5::verify( const KMD5::Digest& digest) +{ + finalize(); + return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); +} + +bool KMD5::verify( const QCString& hexdigest) +{ + finalize(); + return (0 == strcmp(hexDigest().data(), hexdigest)); +} + +const KMD5::Digest& KMD5::rawDigest() +{ + finalize(); + return m_digest; +} + +void KMD5::rawDigest( KMD5::Digest& bin ) +{ + finalize(); + memcpy( bin, m_digest, 16 ); +} + + +QCString KMD5::hexDigest() +{ + QCString s(33); + + finalize(); + sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], + m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], + m_digest[12], m_digest[13], m_digest[14], m_digest[15]); + + return s; +} + +void KMD5::hexDigest(QCString& s) +{ + finalize(); + s.resize(33); + sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], + m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], + m_digest[12], m_digest[13], m_digest[14], m_digest[15]); +} + +QCString KMD5::base64Digest() +{ + QByteArray ba(16); + + finalize(); + memcpy(ba.data(), m_digest, 16); + return KCodecs::base64Encode(ba); +} + + +void KMD5::init() +{ + d = 0; + reset(); +} + +void KMD5::reset() +{ + m_finalized = false; + + m_count[0] = 0; + m_count[1] = 0; + + m_state[0] = 0x67452301; + m_state[1] = 0xefcdab89; + m_state[2] = 0x98badcfe; + m_state[3] = 0x10325476; + + memset ( m_buffer, 0, sizeof(*m_buffer)); + memset ( m_digest, 0, sizeof(*m_digest)); +} + +void KMD5::transform( const unsigned char block[64] ) +{ + + Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; + + decode (x, block, 64); + //memcpy( x, block, 64 ); + +//US Q_ASSERT(!m_finalized); // not just a user error, since the method is private + ASSERT(!m_finalized); // not just a user error, since the method is private + + /* Round 1 */ + FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */ + + m_state[0] += a; + m_state[1] += b; + m_state[2] += c; + m_state[3] += d; + + memset ( static_cast<void *>(x), 0, sizeof(x) ); +} + +inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n) +{ + return (x << n) | (x >> (32-n)) ; +} + +inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return (x & y) | (~x & z); +} + +inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return (x & z) | (y & ~z); +} + +inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return x ^ y ^ z; +} + +inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return y ^ (x | ~z); +} + +void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) +{ + a += F(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac) +{ + a += G(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) +{ + a += H(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) +{ + a += I(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + + +void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len ) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(output, in, len); + +#else + Q_UINT32 i, j; + for (i = 0, j = 0; j < len; i++, j += 4) + { + output[j] = static_cast<Q_UINT8>((in[i] & 0xff)); + output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff)); + output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff)); + output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff)); + } +#endif +} + +// Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a +// multiple of 4. +void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(output, in, len); + +#else + Q_UINT32 i, j; + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = static_cast<Q_UINT32>(in[j]) | + (static_cast<Q_UINT32>(in[j+1]) << 8) | + (static_cast<Q_UINT32>(in[j+2]) << 16) | + (static_cast<Q_UINT32>(in[j+3]) << 24); +#endif +} diff --git a/microkde/kdecore/kmdcodec.h b/microkde/kdecore/kmdcodec.h new file mode 100644 index 0000000..2c4d611 --- a/dev/null +++ b/microkde/kdecore/kmdcodec.h @@ -0,0 +1,572 @@ +/* + Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) + version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. + RSA Data Security, Inc. Created 1991. All rights reserved. + + The KMD5 class is based on a C++ implementation of + "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by + Mordechai T. Abzug, Copyright (c) 1995. This implementation + passes the test-suite as defined in RFC 1321. + + The encoding and decoding utilities in KCodecs with the exception of + quoted-printable are based on the java implementation in HTTPClient + package by Ronald Tschalär Copyright (C) 1996-1999. + + The quoted-printable codec as described in RFC 2045, section 6.7. is by + Rik Hemsley (C) 2001. +*/ + +#ifndef _KMDBASE_H +#define _KMDBASE_H + +#define KBase64 KCodecs + +#include <qglobal.h> +#include <qstring.h> +#include <qiodevice.h> + +/** + * A wrapper class for the most commonly used encoding and + * decoding algorithms. Currently there is support for encoding + * and decoding input using base64, uu and the quoted-printable + * specifications. + * + * @sect Usage: + * + * <PRE> + * QCString input = "Aladdin:open sesame"; + * QCString result = KCodecs::base64Encode(input); + * cout << "Result: " << result.data() << endl; + * + * Output should be + * Result: QWxhZGRpbjpvcGVuIHNlc2FtZQ== + * </PRE> + * + * The above example makes use of the convenience functions + * (ones that accept/return null-terminated strings) to encode/decode + * a string. If what you need is to encode or decode binary data, then + * it is highly recommended that you use the functions that take an input + * and output QByteArray as arguments. These functions are specifically + * tailored for encoding and decoding binary data. + * + * @short A collection of commonly used encoding and decoding algorithms. + * @author Dawit Alemayehu <adawit@kde.org> + * @author Rik Hemsley <rik@kde.org> + */ +class KCodecs +{ +public: + + /** + * Encodes the given data using the quoted-printable algorithm. + * + * @param in data to be encoded. + * @param useCRLF if true the input data is expected to have + * CRLF line breaks and the output will have CRLF line + * breaks, too. + * @return quoted-printable encoded data. + */ + static QCString quotedPrintableEncode(const QByteArray & in, + bool useCRLF = true); + + /** + * @overload + * + * Same as above except it accepts a null terminated + * string instead an array. + * + * @param str data to be encoded. + * @param useCRLF if true the input data is expected to have + * CRLF line breaks and the output will have CRLF line + * breaks, too. + * @return quoted-printable encoded data. + */ + static QCString quotedPrintableEncode(const QCString & str, + bool useCRLF = true); + + /** + * Encodes the given data using the quoted-printable algorithm. + * + * Use this function if you want the result of the encoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for encoding binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in data to be encoded. + * @param out decoded data. + * @param useCRLF if true the input data is expected to have + * CRLF line breaks and the output will have CRLF line + * breaks, too. + * @return quoted-printable encoded data. + */ + static void quotedPrintableEncode(const QByteArray & in, QByteArray& out, + bool useCRLF); + + /** + * Decodes a quoted-printable encoded string. + * + * Accepts data with CRLF or standard unix line breaks. + * + * @param in the data to be decoded. + * @return decoded data. + */ + static QCString quotedPrintableDecode(const QByteArray & in); + + /** + * @overload + * + * Same as above except it accepts a null terminated + * string instead an array. + * + * @param str the data to be decoded. + * @return decoded data. + */ + static QCString quotedPrintableDecode(const QCString & str); + + /** + * Decodes a quoted-printable encoded data. + * + * Accepts data with CRLF or standard unix line breaks. + * Use this function if you want the result of the decoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for decoding an encoded + * binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in data to be encoded. + * @param out decoded data. + * + * @return quoted-printable encoded data. + */ + static void quotedPrintableDecode(const QByteArray & in, QByteArray& out); + + + /** + * Encodes the given data using the uuencode algorithm. + * + * The output is split into lines starting with the number of + * encoded octets in the line and ending with a newline. No + * line is longer than 45 octets (60 characters), excluding the + * line terminator. + * + * @param in the data to be uuencoded + * @return a uuencoded data. + */ + static QCString uuencode( const QByteArray& in ); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the string to be uuencoded. + * @return the encoded string. + */ + static QCString uuencode( const QCString& str ); + + /** + * Encodes the given data using the uuencode algorithm. + * + * Use this function if you want the result of the encoding + * to be placed in another array and cut down the number of + * copy operation that have to be performed in the process. + * This is the preffered method for encoding binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the data to be uuencoded. + * @param out the container for the uudecoded data. + */ + static void uuencode( const QByteArray& in, QByteArray& out ); + + /** + * Decodes the given data using the uuencode algorithm. + * + * Any 'begin' and 'end' lines like those generated by + * the utilities in unix and unix-like OS will be + * automatically ignored. + * + * @param in the data uuencoded data to be decoded. + * @return a decoded string. + */ + static QCString uudecode( const QByteArray& in ); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the string to be decoded. + * @return a uudecoded string. + */ + static QCString uudecode( const QCString& str ); + + /** + * Decodes the given data using the uudecode algorithm. + * + * Use this function if you want the result of the decoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is the preferred method for decoding binary data. + * + * Any 'begin' and 'end' lines like those generated by + * the utilities in unix and unix-like OS will be + * automatically ignored. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the uuencoded-data to be decoded. + * @param out the container for the uudecoded data. + */ + static void uudecode( const QByteArray& in, QByteArray& out ); + + + /** + * Encodes the given data using the base64 algorithm. + * + * The boolean argument determines if the encoded data is + * going to be restricted to 76 characters or less per line + * as specified by RFC 2045. If @p insertLFs is true, then + * there will be 76 characters or less per line. + * + * @param in the data to be encoded. + * @param insertLFs limit the number of characters per line. + * + * @return a base64 encoded string. + */ + static QCString base64Encode( const QByteArray& in, bool insertLFs = false); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the string to be encoded. + * @param insertLFs limit the number of characters per line. + * @return the decoded string. + */ + static QCString base64Encode( const QCString& str, bool insertLFs = false ); + + /** + * Encodes the given data using the base64 algorithm. + * + * Use this function if you want the result of the encoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for encoding binary data. + * + * The boolean argument determines if the encoded data is going + * to be restricted to 76 characters or less per line as specified + * by RFC 2045. If @p insertLFs is true, then there will be 76 + * characters or less per line. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the data to be encoded using base64. + * @param out the container for the encoded data. + * @param insertLFs limit the number of characters per line. + */ + static void base64Encode( const QByteArray& in, QByteArray& out, + bool insertLFs = false ); + + /** + * Decodes the given data that was encoded using the + * base64 algorithm. + * + * @param in the base64-encoded data to be decoded. + * @return the decoded data. + */ + static QCString base64Decode( const QByteArray& in ); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the base64-encoded string. + * @return the decoded string. + */ + static QCString base64Decode( const QCString& str ); + + /** + * Decodes the given data that was encoded with the base64 + * algorithm. + * + * Use this function if you want the result of the decoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for decoding an encoded + * binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the encoded data to be decoded. + * @param out the container for the decoded data. + */ + static void base64Decode( const QByteArray& in, QByteArray& out ); + + +private: + KCodecs(); + +private: + static const char UUEncMap[64]; + static const char UUDecMap[128]; + static const char Base64EncMap[64]; + static const char Base64DecMap[128]; + static const char hexChars[16]; + static const unsigned int maxQPLineLength; +}; + +class KMD5Private; +/** + * Provides an easy to use C++ implementation of RSA's + * MD5 algorithm. + * + * The default constructor is designed to provide much the same + * functionality as the most commonly used C-implementation, while + * the other three constructors are meant to further simplify the + * process of obtaining a digest by calculating the result in a + * single step. + * + * KMD5 is state-based, that means you can add new contents with + * update() as long as you didn't request the digest value yet. + * After the digest value was requested, the object is "finalized" + * and you have to call reset() to be able to do another calculation + * with it. The reason for this behaviour is that upon requesting + * the message digest KMD5 has to pad the received contents up to a + * 64 byte boundary to calculate its value. After this operation it + * is not possible to resume consuming data. + * + * @sect Usage: + * + * A common usage of this class: + * + * <PRE> + * const char* test1; + * KMD5::Digest rawResult; + * + * test1 = "This is a simple test."; + * KMD5 context (test1); + * cout << "Hex Digest output: " << context.hexDigest().data() << endl; + * </PRE> + * + * To cut down on the unnecessary overhead of creating multiple KMD5 + * objects, you can simply invoke @ref reset() to reuse the same object + * in making another calculation: + * + * <PRE> + * context.reset (); + * context.update ("TWO"); + * context.update ("THREE"); + * cout << "Hex Digest output: " << context.hexDigest().data() << endl; + * </PRE> + * + * @short An adapted C++ implementation of RSA Data Securities MD5 algorithm. + * @author Dirk Mueller <mueller@kde.org>, Dawit Alemayehu <adawit@kde.org> + */ + +class KMD5 +{ +public: + + typedef unsigned char Digest[16]; + + KMD5(); + + /** + * Constructor that updates the digest for the given string. + * + * @param in C string or binary data + * @param len if negative, calculates the length by using + * strlen on the first parameter, otherwise + * it trusts the given length (does not stop on NUL byte). + */ + KMD5(const char* in, int len = -1); + + /** + * @overload + * + * Same as above except it accepts a QByteArray as its argument. + */ + KMD5(const QByteArray& a ); + + /** + * @overload + * + * Same as above except it accepts a QByteArray as its argument. + */ + KMD5(const QCString& a ); + + /** + * Updates the message to be digested. Be sure to add all data + * before you read the digest. After reading the digest, you + * can <b>not</b> add more data! + * + * @param in message to be added to digest + * @param len the length of the given message. + */ + void update(const char* in, int len = -1) { update(reinterpret_cast<const unsigned char*>(in), len); } + + /** + * @overload + */ + void update(const unsigned char* in, int len = -1); + + /** + * @overload + * + * @param in message to be added to the digest (QByteArray). + */ + void update(const QByteArray& in ); + + /** + * @overload + * + * @param in message to be added to the digest (QByteArray). + */ + void update(const QCString& in ); + + /** + * @overload + * + * reads the data from an I/O device, i.e. from a file (QFile). + * + * NOTE that the file must be open for reading. + * + * @param file a pointer to FILE as returned by calls like f{d,re}open + * + * @returns false if an error occured during reading. + */ + bool update(QIODevice& file); + + /** + * Calling this function will reset the calculated message digest. + * Use this method to perform another message digest calculation + * without recreating the KMD5 object. + */ + void reset(); + + /** + * @return the raw representation of the digest + */ + const Digest& rawDigest (); + + /** + * Fills the given array with the binary representation of the + * message digest. + * + * Use this method if you do not want to worry about making + * copy of the digest once you obtain it. + * + * @param bin an array of 16 characters ( char[16] ) + */ + void rawDigest( KMD5::Digest& bin ); + + /** + * Returns the value of the calculated message digest in + * a hexadecimal representation. + */ + QCString hexDigest (); + + /** + * @overload + */ + void hexDigest(QCString&); + + /** + * Returns the value of the calculated message digest in + * a base64-encoded representation. + */ + QCString base64Digest (); + + /** + * returns true if the calculated digest for the given + * message matches the given one. + */ + bool verify( const KMD5::Digest& digest); + + /** + * @overload + */ + bool verify(const QCString&); + +protected: + /** + * Performs the real update work. Note + * that length is implied to be 64. + */ + void transform( const unsigned char buffer[64] ); + + /** + * finalizes the digest + */ + void finalize(); + +private: + KMD5(const KMD5& u); + KMD5& operator=(const KMD5& md); + + void init(); + void encode( unsigned char* output, Q_UINT32 *in, Q_UINT32 len ); + void decode( Q_UINT32 *output, const unsigned char* in, Q_UINT32 len ); + + Q_UINT32 rotate_left( Q_UINT32 x, Q_UINT32 n ); + Q_UINT32 F( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + Q_UINT32 G( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + Q_UINT32 H( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + Q_UINT32 I( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + void FF( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + void GG( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + void HH( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + void II( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + +private: + Q_UINT32 m_state[4]; + Q_UINT32 m_count[2]; + Q_UINT8 m_buffer[64]; + Digest m_digest; + bool m_finalized; + + KMD5Private* d; +}; +#endif diff --git a/microkde/kdecore/ksharedptr.h b/microkde/kdecore/ksharedptr.h new file mode 100644 index 0000000..545058a --- a/dev/null +++ b/microkde/kdecore/ksharedptr.h @@ -0,0 +1,171 @@ +/* This file is part of the KDE libraries + Copyright (c) 1999 Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSharedPTR_H +#define KSharedPTR_H + +/** + * Reference counting for shared objects. If you derive your object + * from this class, then you may use it in conjunction with + * @ref KSharedPtr to control the lifetime of your object. + * + * Specifically, all classes that derive from KShared have an internal + * counter keeping track of how many other objects have a reference to + * their object. If used with @ref KSharedPtr, then your object will + * not be deleted until all references to the object have been + * released. + * + * You should probably not ever use any of the methods in this class + * directly -- let the @ref KSharedPtr take care of that. Just derive + * your class from KShared and forget about it. + * + * @author Waldo Bastian <bastian@kde.org> + * @version $Id$ + */ +class KShared { +public: + /** + * Standard constructor. This will initialize the reference count + * on this object to 0. + */ + KShared() : count(0) { } + + /** + * Copy constructor. This will @em not actually copy the objects + * but it will initialize the reference count on this object to 0. + */ + KShared( const KShared & ) : count(0) { } + + /** + * Overloaded assignment operator. + */ + KShared &operator=(const KShared & ) { return *this; } + + /** + * Increases the reference count by one. + */ + void _KShared_ref() const { count++; } + + /** + * Releases a reference (decreases the reference count by one). If + * the count goes to 0, this object will delete itself. + */ + void _KShared_unref() const { if (!--count) delete this; } + + /** + * Return the current number of references held. + * + * @return Number of references + */ + int _KShared_count() const { return count; } + +protected: + virtual ~KShared() { } +private: + mutable int count; +}; + +/** + * Can be used to control the lifetime of an object that has derived + * @ref KShared. As long a someone holds a KSharedPtr on some @ref KShared + * object it won't become deleted but is deleted once its reference + * count is 0. This struct emulates C++ pointers perfectly. So just + * use it like a simple C++ pointer. + * + * KShared and KSharedPtr are preferred over QShared / QSharedPtr + * since they are more safe. + * + * @author Waldo Bastian <bastian@kde.org> + * @version $Id$ + */ +template< class T > +struct KSharedPtr +{ +public: +/** + * Creates a null pointer. + */ + KSharedPtr() + : ptr(0) { } + /** + * Creates a new pointer. + * @param the pointer + */ + KSharedPtr( T* t ) + : ptr(t) { if ( ptr ) ptr->_KShared_ref(); } + + /** + * Copies a pointer. + * @param the pointer to copy + */ + KSharedPtr( const KSharedPtr& p ) + : ptr(p.ptr) { if ( ptr ) ptr->_KShared_ref(); } + + /** + * Unreferences the object that this pointer points to. If it was + * the last reference, the object will be deleted. + */ + ~KSharedPtr() { if ( ptr ) ptr->_KShared_unref(); } + + KSharedPtr<T>& operator= ( const KSharedPtr<T>& p ) { + if ( ptr == p.ptr ) return *this; + if ( ptr ) ptr->_KShared_unref(); + ptr = p.ptr; + if ( ptr ) ptr->_KShared_ref(); + return *this; + } + KSharedPtr<T>& operator= ( T* p ) { + if ( ptr == p ) return *this; + if ( ptr ) ptr->_KShared_unref(); + ptr = p; + if ( ptr ) ptr->_KShared_ref(); + return *this; + } + bool operator== ( const KSharedPtr<T>& p ) const { return ( ptr == p.ptr ); } + bool operator!= ( const KSharedPtr<T>& p ) const { return ( ptr != p.ptr ); } + bool operator== ( const T* p ) const { return ( ptr == p ); } + bool operator!= ( const T* p ) const { return ( ptr != p ); } + bool operator!() const { return ( ptr == 0 ); } + operator T*() const { return ptr; } + + /** + * Returns the pointer. + * @return the pointer + */ + T* data() { return ptr; } + + /** + * Returns the pointer. + * @return the pointer + */ + const T* data() const { return ptr; } + + const T& operator*() const { return *ptr; } + T& operator*() { return *ptr; } + const T* operator->() const { return ptr; } + T* operator->() { return ptr; } + + /** + * Returns the number of references. + * @return the number of references + */ + int count() const { return ptr->_KShared_count(); } // for debugging purposes +private: + T* ptr; +}; + +#endif diff --git a/microkde/kdecore/kshell.cpp b/microkde/kdecore/kshell.cpp new file mode 100644 index 0000000..efc007a --- a/dev/null +++ b/microkde/kdecore/kshell.cpp @@ -0,0 +1,386 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kshell.h> + +#include <qfile.h> +#include <qdir.h> + +#include <stdlib.h> +#ifndef _WIN32_ +#include <pwd.h> +#endif +//US #include <sys/types.h> + +/*US +static int fromHex( QChar c ) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return -1; +} + +inline static bool isQuoteMeta( uint c ) +{ +#if 0 // it's not worth it, especially after seeing gcc's asm output ... + static const uchar iqm[] = { + 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 + }; // \'"$ + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +#else + return c == '\\' || c == '\'' || c == '"' || c == '$'; +#endif +} + +inline static bool isMeta( uint c ) +{ + static const uchar iqm[] = { + 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38 + }; // \'"$`<>|;&(){}*?# + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +} + +QStringList KShell::splitArgs( const QString &args, int flags, int *err ) +{ + QStringList ret; + bool firstword = flags & AbortOnMeta; + + for (uint pos = 0; ; ) { + QChar c; + do { + if (pos >= args.length()) + goto okret; + c = args.unicode()[pos++]; + } while (c.isSpace()); + QString cret; + if ((flags & TildeExpand) && c == '~') { + uint opos = pos; + for (; ; pos++) { + if (pos >= args.length()) + break; + c = args.unicode()[pos]; + if (c == '/' || c.isSpace()) + break; + if (isQuoteMeta( c )) { + pos = opos; + c = '~'; + goto notilde; + } + if ((flags & AbortOnMeta) && isMeta( c )) + goto metaerr; + } + QString ccret = homeDir( QConstString( args.unicode() + opos, pos - opos ).string() ); + if (ccret.isEmpty()) { + pos = opos; + c = '~'; + goto notilde; + } + if (pos >= args.length()) { + ret += ccret; + goto okret; + } + pos++; + if (c.isSpace()) { + ret += ccret; + firstword = false; + continue; + } + cret = ccret; + } + // before the notilde label, as a tilde does not match anyway + if (firstword) { + if (c == '_' || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { + uint pos2 = pos; + QChar cc; + do + cc = args[pos2++]; + while (cc == '_' || (cc >= 'A' && cc <= 'Z') || + (cc >= 'a' && cc <= 'z') || (cc >= '0' && cc <= '9')); + if (cc == '=') + goto metaerr; + } + } + notilde: + do { + if (c == '\'') { + uint spos = pos; + do { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + } while (c != '\''); + cret += QConstString( args.unicode() + spos, pos - spos - 1 ).string(); + } else if (c == '"') { + for (;;) { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (c == '"') + break; + if (c == '\\') { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (c != '"' && c != '\\' && + !((flags & AbortOnMeta) && (c == '$' || c == '`'))) + cret += '\\'; + } else if ((flags & AbortOnMeta) && (c == '$' || c == '`')) + goto metaerr; + cret += c; + } + } else if (c == '$' && args[pos] == '\'') { + pos++; + for (;;) { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (c == '\'') + break; + if (c == '\\') { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + switch (c) { + case 'a': cret += '\a'; break; + case 'b': cret += '\b'; break; + case 'e': cret += '\033'; break; + case 'f': cret += '\f'; break; + case 'n': cret += '\n'; break; + case 'r': cret += '\r'; break; + case 't': cret += '\t'; break; + case '\\': cret += '\\'; break; + case '\'': cret += '\''; break; + case 'c': cret += args[pos++] & 31; break; + case 'x': + { + int hv = fromHex( args[pos] ); + if (hv < 0) { + cret += "\\x"; + } else { + int hhv = fromHex( args[++pos] ); + if (hhv > 0) { + hv = hv * 16 + hhv; + pos++; + } + cret += QChar( hv ); + } + break; + } + default: + if (c >= '0' && c <= '7') { + int hv = c - '0'; + for (int i = 0; i < 2; i++) { + c = args[pos]; + if (c < '0' || c > '7') + break; + hv = hv * 8 + (c - '0'); + pos++; + } + cret += QChar( hv ); + } else { + cret += '\\'; + cret += c; + } + break; + } + } else + cret += c; + } + } else { + if (c == '\\') { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (!c.isSpace() && + !((flags & AbortOnMeta) ? isMeta( c ) : isQuoteMeta( c ))) + cret += '\\'; + } else if ((flags & AbortOnMeta) && isMeta( c )) + goto metaerr; + cret += c; + } + if (pos >= args.length()) + break; + c = args.unicode()[pos++]; + } while (!c.isSpace()); + ret += cret; + firstword = false; + } + + okret: + if (err) + *err = NoError; + return ret; + + quoteerr: + if (err) + *err = BadQuoting; + return QStringList(); + + metaerr: + if (err) + *err = FoundMeta; + return QStringList(); +} + +inline static bool isSpecial( uint c ) +{ + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0xdd, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38 + }; // 0-32 \'"$`<>|;&(){}*?# + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +} + +QString KShell::joinArgs( const QStringList &args ) +{ + QChar q( '\'' ); + QString ret; + for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) { + if (!ret.isEmpty()) + ret += ' '; + if (!(*it).length()) + ret.append( q ).append( q ); + else { + for (uint i = 0; i < (*it).length(); i++) + if (isSpecial((*it).unicode()[i])) { + QString tmp(*it); + tmp.replace( q, "'\\''" ); + ret += q; + tmp += q; + ret += tmp; + goto ex; + } + ret += *it; + ex: ; + } + } + return ret; +} + +QString KShell::joinArgs( const char * const *args, int nargs ) +{ + if (!args) + return QString::null; // well, QString::empty, in fact. qt sucks ;) + QChar q( '\'' ); + QString ret; + for (const char * const *argp = args; nargs && *argp; argp++, nargs--) { + if (!ret.isEmpty()) + ret += ' '; + if (!**argp) + ret.append( q ).append( q ); + else { + QString tmp( QFile::decodeName( *argp ) ); + for (uint i = 0; i < tmp.length(); i++) + if (isSpecial(tmp.unicode()[i])) { + tmp.replace( q, "'\\''" ); + ret += q; + tmp += q; + ret += tmp; + goto ex; + } + ret += tmp; + ex: ; + } + } + return ret; +} + +QString KShell::joinArgsDQ( const QStringList &args ) +{ + QChar q( '\'' ), sp( ' ' ), bs( '\\' ); + QString ret; + for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) { + if (!ret.isEmpty()) + ret += sp; + if (!(*it).length()) + ret.append( q ).append( q ); + else { + for (uint i = 0; i < (*it).length(); i++) + if (isSpecial((*it).unicode()[i])) { + ret.append( '$' ).append( q ); + for (uint pos = 0; pos < (*it).length(); pos++) { + int c = (*it).unicode()[pos]; + if (c < 32) { + ret += bs; + switch (c) { + case '\a': ret += 'a'; break; + case '\b': ret += 'b'; break; + case '\033': ret += 'e'; break; + case '\f': ret += 'f'; break; + case '\n': ret += 'n'; break; + case '\r': ret += 'r'; break; + case '\t': ret += 't'; break; + case '\034': ret += 'c'; ret += '|'; break; + default: ret += 'c'; ret += c + '@'; break; + } + } else { + if (c == '\'' || c == '\\') + ret += bs; + ret += c; + } + } + ret.append( q ); + goto ex; + } + ret += *it; + ex: ; + } + } + return ret; +} +*/ + +QString KShell::tildeExpand( const QString &fname ) +{ + if (fname[0] == '~') { + int pos = fname.find( '/' ); + if (pos < 0) + return homeDir( QConstString( (QChar*)(fname.unicode() + 1), fname.length() - 1 ).string() ); + QString ret = homeDir( QConstString( (QChar*)(fname.unicode() + 1), pos - 1 ).string() ); + if (!ret.isNull()) + ret += QConstString( (QChar*)(fname.unicode() + pos), fname.length() - pos ).string(); + return ret; + } + return fname; +} + +QString KShell::homeDir( const QString &user ) +{ +#ifdef _WIN32_ + return QDir::homeDirPath(); +#else + if (user.isEmpty()) + return QFile::decodeName( getenv( "HOME" ) ); + struct passwd *pw = getpwnam( QFile::encodeName( user ).data() ); + if (!pw) + return QString::null; + return QFile::decodeName( pw->pw_dir ); +#endif +} diff --git a/microkde/kdecore/kshell.h b/microkde/kdecore/kshell.h new file mode 100644 index 0000000..35d8217 --- a/dev/null +++ b/microkde/kdecore/kshell.h @@ -0,0 +1,143 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _KSHELL_H +#define _KSHELL_H + +#include <qstring.h> +#include <qstringlist.h> + +/** + * Provides some basic POSIX shell and bash functionality. + * @see KStringHandler + */ +namespace KShell { + + /** + * Flags for @ref splitArgs(). + */ + enum Options { + NoOptions = 0, + + /** + * Perform tilde expansion. + */ + TildeExpand = 1, + + /** + * Bail out if a non-quoting and not quoted shell meta character is encoutered. + * Meta characters are the command separators @p semicolon and @p ampersand, + * the redirection symbols @p less-than, @p greater-than and the @p pipe @p symbol, + * the grouping symbols opening and closing @p parens and @p braces, the command + * substitution symbol @p backquote, the generic substitution symbol @p dollar + * (if not followed by an apostrophe), the wildcards @p asterisk and + * @p question @p mark, and the comment symbol @p hash @p mark. Additionally, + * a variable assignment in the first word is recognized. + */ + AbortOnMeta = 2 + }; + + /** + * Status codes from @ref splitArgs() + */ + enum Errors { + /** + * Success. + */ + NoError = 0, + + /** + * Indicates a parsing error, like an unterminated quoted string. + */ + BadQuoting, + + /** + * The AbortOnMeta flag was set and a shell meta character + * was encoutered. + */ + FoundMeta + }; + + /** + * Splits @p cmd according to POSIX shell word splitting and quoting rules. + * Can optionally perform tilde expansion and/or abort if it finds shell + * meta characters it cannot process. + * + * @param cmd the command to split + * @param flags operation flags, see @ref Options + * @param err if not NULL, a status code will be stored at the pointer + * target, see @ref Errors + * @return a list of unquoted words or an empty list if an error occured + */ + QStringList splitArgs( const QString &cmd, int flags = 0, int *err = 0 ); + + /** + * Quotes and joins @p args together according to POSIX shell rules. + * + * @param args a list of strings to quote and join + * @return a command suitable for shell execution + */ + QString joinArgs( const QStringList &args ); + + /** + * Same as above, but $'' is used instead of '' for the quoting. + * The output is suitable for @ref splitArgs(), bash, zsh and possibly + * other bourne-compatible shells, but not for plain sh. The advantage + * is, that control characters (ASCII less than 32) are escaped into + * human-readable strings. + * + * @param args a list of strings to quote and join + * @return a command suitable for shell execution + */ + QString joinArgsDQ( const QStringList &args ); + + /** + * Quotes and joins @p argv together according to POSIX shell rules. + * + * @param argv an array of c strings to quote and join. + * The strings are expected to be in local-8-bit encoding. + * @param argc maximal number of strings in @p argv. if not supplied, + * @p argv must be null-terminated. + * @return a command suitable for shell execution + */ + QString joinArgs( const char * const *argv, int argc = -1 ); + + /** + * Performs tilde expansion on @p path. Interprets "~/path" and + * "~user/path". + * + * @param path the path to tilde-expand + * @return the expanded path + */ + QString tildeExpand( const QString &path ); + + /** + * Obtain a @p user's home directory. + * + * @param user The name of the user whose home dir should be obtained. + * An empty string denotes the current user. + * @return The user's home directory. + */ + QString homeDir( const QString &user ); + +} + + +#endif /* _KSHELL_H */ diff --git a/microkde/kdecore/kshortcut.h b/microkde/kdecore/kshortcut.h new file mode 100644 index 0000000..4813734 --- a/dev/null +++ b/microkde/kdecore/kshortcut.h @@ -0,0 +1,846 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __KSHORTCUT_H +#define __KSHORTCUT_H +/*US +#include <qkeysequence.h> +#include <qstring.h> + +class QKeyEvent; +class KKeyNative; +*/ +/** +* A KKey object represents a single key with possible modifiers +* (Shift, Ctrl, Alt, Win). It can represent both keys which are +* understood by Qt as well as those which are additionally supported +* by the underlying system (e.g. X11). +* @see KKeyNative +* @see KKeySequence +* @see KShortcut +*/ +/*US +class KKey +{ + public: +*/ + /** + * The number of flags. + * @see ModFlag + */ +/*US + enum { MOD_FLAG_COUNT = 4 }; + enum { QtWIN = (Qt::ALT << 1) }; +*/ + /** + * Flags to represent the modifiers. You can combine modifiers + * by ORing them. + */ +/*US + enum ModFlag { + SHIFT = 0x01, + CTRL = 0x02, + ALT = 0x04, + WIN = 0x08 + }; +*/ + /** + * Creates a new null KKey. + * @see clear() + * @see isNull() + * @see null() + */ +//US KKey(); + + /** + * Creates a new key for the given Qt key code. + * @param keyQt the qt keycode + * @see Qt::Key + */ +//US KKey( int keyQt ); + + /** + * Creates a new key from the first key code of the given key sequence. + * @param keySeq the key sequence that contains the key + */ +//US KKey( const QKeySequence& keySeq ); + + /** + * Extracts the key from the given key event. + * @param keyEvent the key event to get the key from + */ +//US KKey( const QKeyEvent* keyEvent ); + + /** + * Copy constructor. + */ +//US KKey( const KKey& key ); + + /** + * Creates a new key from the given description. The form of the description + * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or + * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and + * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive. + * @param key the description of the key + * @see KKeyServer::Sym::init() + */ +//US KKey( const QString& key ); + /** + * @internal + */ +//US KKey( uint key, uint mod ); +//US ~KKey(); + + // Initialization methods + /** + * Clears the key. The key is null after calling this function. + * @see isNull() + */ +//US void clear(); + + /** + * Initializes the key with the given Qt key code. + * @param keyQt the qt keycode + * @return true if successful, false otherwise + * @see Qt::Key + */ +//US bool init( int keyQt ); + + /** + * Initializes the key with the first key code of the given key sequence. + * @param keySeq the key sequence that contains the key + * @return true if successful, false otherwise + */ +//US bool init( const QKeySequence& keySeq ); + + /** + * Initializes the key by extracting the code from the given key event. + * @param keyEvent the key event to get the key from + * @return true if successful, false otherwise + */ +//US bool init( const QKeyEvent* keyEvent ); + + /** + * Copies the given key. + * @param key the key to copy + * @return true if successful, false otherwise + */ +//US bool init( const KKey& key ); + + /** + * Initializes the key with the given description. The form of the description + * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or + * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and + * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive. + * @param key the description of the key + * @return true if successful, false otherwise + * @see KKeyServer::Sym::init() + */ +//US bool init( const QString& ); + + /** + * @internal + */ +//US bool init( uint key, uint mod ); + + /** + * Copies the key. + */ +//US KKey& operator =( const KKey& key ) +//US { init( key ); return *this; } + + // Query methods. + /** + * Returns true if the key is null (after @ref clear() or empty + * constructor). + * @return true if the key is null + * @see clear() + * @see null() + */ +//US bool isNull() const; + + /** + * @internal + */ +//US bool isValidQt() const; + + /** + * @internal + */ +//US bool isValidNative() const; + + /** + * @internal + */ +//US uint sym() const; + /** + * @internal + */ +//US uint modFlags() const; + + // Comparison Methods + /** + * Compares this key with the given KKey object. Returns a negative + * number if the given KKey is larger, 0 if they are equal and + * a positive number this KKey is larger. The returned value + * is the difference between the symbol or, if the symbols + * are equal, the difference between the encoded modifiers. + * @param key the key to compare with this key + * @return a negative number if the given KKey is larger, 0 if + * they are equal and a positive number this KKey is larger + */ +//US int compare( const KKey& key ) const; + + /** + * Compares the symbol and modifiers of both keys. + * @see compare() + */ +//US bool operator == ( const KKey& key ) const +//US { return compare( key ) == 0; } + /** + * Compares the symbol and modifiers of both keys. + * @see compare() + */ +//US bool operator != ( const KKey& key ) const +//US { return compare( key ) != 0; } + /** + * Compares the symbol and modifiers of both keys. + * @see compare() + */ +//US bool operator < ( const KKey& key ) const +//US { return compare( key ) < 0; } + + // Conversion methods. + /** + * Returns the qt key code. + * @return the qt key code or 0 if there is no key set. + * @see Qt::Key + */ +//US int keyCodeQt() const; + + /** + * Returns a human-readable representation of the key in the form + * "modifier+key". + * @return the string representation of the key + */ +//US QString toString() const; + + /** + * @internal + */ +//US QString toStringInternal() const; + + // Operation methods + /** + * @internal + */ +//US void simplify(); + + /** + * Returns a null key. + * @return the null key + * @see isNull() + * @see clear() + */ +//US static KKey& null(); + + /** + * Returns a user-readable representation of the given modifiers. + * @param f the modifiers to convert + * @return the string representation of the modifiers + */ +//US static QString modFlagLabel( ModFlag f ); + +//US private: + /* + * Under X11, m_key will hold an X11 key symbol. + * For Qt/Embedded, it will hold the Qt key code. + */ + /** + * Returns the native key symbol value key. Under X11, this is the X + * keycode. Under Qt/Embedded, this is the Qt keycode. + * @see /usr/include/X11/keysymdef.h + * @see qnamespace.h + */ +//US uint m_sym; + /** + * m_mod holds the + */ +//US uint m_mod; + +//US private: +//US friend class KKeyNative; +//US}; + +/** +* A KKeySequence object holds a sequence of up to 4 keys. +* Ex: Ctrl+X,I +* @see KKey +* @see KShortcut +*/ + +//USclass KKeySequence +//US{ +//US public: + /// Defines the maximum length of the key sequence +//US enum { MAX_KEYS = 4 }; + + /** + * Create a new null key sequence. + * @see isNull() + * @see null() + * @see clear() + */ +//US KKeySequence(); + + /** + * Copies the given qt key sequence. + * @param keySeq the qt key sequence to copy + */ +//US KKeySequence( const QKeySequence& keySeq ); + + /** + * Create a new key sequence that only contains the given key. + * @param key the key to add + */ +//US KKeySequence( const KKey& key ); + + /** + * Create a new key sequence that only contains the given key. + * @param key the key to add + */ +//US KKeySequence( const KKeyNative& key ); + + /** + * Copies the given key sequence. + * @param keySeq the key sequence to copy + */ +//US KKeySequence( const KKeySequence& keySeq ); + + /** + * Creates a new key sequence that contains the given key sequence. + * The description consists of comma-separated keys as + * required by @ref KKey::KKey(const QString&). + * @param keySeq the description of the key + * @see KKeyServer::Sym::init() + * @see KKey::KKey(const QString&) + */ +//US KKeySequence( const QString& keySeq ); + +//US ~KKeySequence(); + + /** + * Clears the key sequence. The key sequence is null after calling this + * function. + * @see isNull() + */ +//US void clear(); + + /** + * Copies the given qt key sequence over this key sequence. + * @param keySeq the qt key sequence to copy + * @return true if successful, false otherwise + */ +//US bool init( const QKeySequence& keySeq ); + + /** + * Initializes the key sequence to only contain the given key. + * @param key the key to set + * @return true if successful, false otherwise + */ +//US bool init( const KKey& key ); + + /** + * Initializes the key sequence to only contain the given key. + * @param key the key to set + * @return true if successful, false otherwise + */ +//US bool init( const KKeyNative& key ); + + /** + * Copies the given key sequence over this key sequence. + * @param keySeq the key sequence to copy + * @return true if successful, false otherwise + */ +//US bool init( const KKeySequence& keySeq ); + + /** + * Initializes this key sequence to contain the given key sequence. + * The description consists of comma-separated keys as + * required by @ref KKey::KKey(const QString&). + * @param key the description of the key + * @return true if successful, false otherwise + * @see KKeyServer::Sym::init() + * @see KKey::KKey(const QString&) + */ +//US bool init( const QString& key ); + + /** + * Copy the given key sequence into this sequence. + */ +//US KKeySequence& operator =( const KKeySequence& seq ) +//US { init( seq ); return *this; } + + /** + * Returns the number of key strokes of this sequence. + * @return the number of key strokes + * @see MAX_KEYS + */ +//US uint count() const; + + /** + * Return the @p i'th key of this sequence, or a null key if there + * are less then i keys. + * @param i the key to retrieve + * @return the @p i'th key, or @ref KKey::null() if there are less + * than i keys + * @see MAX_KEYS + */ +//US const KKey& key( uint i ) const; + + /** + * @internal + */ +//US bool isTriggerOnRelease() const; + + /** + * Sets the @p i'th key of the sequence. You can not introduce gaps + * in a sequence, so you must use an @p i <= @ref count(). Also note that + * the maximum length of a key sequence is @ref MAX_KEYS. + * @param i the position of the new key (<= @ref count(), <= @ref MAX_KEYS) + * @param key the key to set + * @return true if successful, false otherwise + */ +//US bool setKey( uint i, const KKey& key ); + + /** + * @internal + */ +//US void setTriggerOnRelease( bool ); + + /** + * Returns true if the key sequence is null (after @ref clear() or empty + * constructor). + * @return true if the key sequence is null + * @see clear() + * @see null() + */ +//US bool isNull() const; + + /** + * Returns true if this key sequence begins with the given sequence. + * @param keySeq the key sequence to search + * @return true if this key sequence begins with the given sequence + */ +//US bool startsWith( const KKeySequence& keySeq ) const; + + /** + * Compares this object with the given key sequence. Returns a negative + * number if the given KKeySequence is larger, 0 if they are equal and + * a positive number this KKeySequence is larger. Key sequences are + * compared by comparing the individual keys, starting from the beginning + * until an unequal key has been found. If a sequence contains more + * keys, it is considered larger. + * @param keySeq the key sequence to compare to + * @return a negative number if the given KKeySequence is larger, 0 if + * they are equal and a positive number this KKeySequence is larger + * @see KKey::sequence + */ +//US int compare( const KKeySequence& keySeq ) const; + + /** + * Compares the keys of both sequences. + * @see compare() + */ +//US bool operator == ( const KKeySequence& seq ) const +//US { return compare( seq ) == 0; } + + /** + * Compares the keys of both sequences. + * @see compare() + */ +//US bool operator != ( const KKeySequence& seq ) const +//US { return compare( seq ) != 0; } + + /** + * Compares the keys of both sequences. + * @see compare() + */ +//US bool operator < ( const KKeySequence& seq ) const +//US { return compare( seq ) < 0; } + // TODO: consider adding Qt::SequenceMatch matches(...) methods for QKeySequence equivalence + + /** + * Converts this key sequence to a QKeySequence. + * @return the QKeySequence + */ +//US QKeySequence qt() const; + + /** + * Returns the qt key code of the first key. + * @return the qt key code of the first key + * @see Qt::Key + * @see KKey::keyCodeQt() + */ +//US int keyCodeQt() const; + + /** + * Returns the key sequence as a number of key presses as + * returned by @ref KKey::toString(), seperated by commas. + * @return the string represenation of this key sequence + * @see KKey::toString() + */ +//US QString toString() const; + + /** + * @internal + */ +//US QString toStringInternal() const; + + /** + * Returns a null key sequence. + * @return the null key sequence + * @see isNull() + * @see clear() + */ +//US static KKeySequence& null(); + +//US protected: +//US uchar m_nKeys; +//US uchar m_bTriggerOnRelease; + // BCI: m_rgvar should be renamed to m_rgkey for KDE 4.0 +//US KKey m_rgvar[MAX_KEYS]; + +//US private: +//US class KKeySequencePrivate* d; +//US friend class KKeyNative; +//US}; + +/** +* The KShortcut class is used to represent a keyboard shortcut to an action. +* A shortcut is normally a single key with modifiers, such as Ctrl+V. +* A KShortcut object may also contain an alternate key which will also +* activate the action it's associated to, as long as no other actions have +* defined that key as their primary key. Ex: Ctrl+V;Shift+Insert. +*/ + +class KShortcut +{ + public: + /** + * The maximum number of key sequences that can be contained in + * a KShortcut. + */ + enum { MAX_SEQUENCES = 2 }; + + /** + * Creates a new null shortcut. + * @see null() + * @see isNull() + * @see clear() + */ + KShortcut() {} + + /** + * Creates a new shortcut with the given Qt key code + * as the only key sequence. + * @param keyQt the qt keycode + * @see Qt::Key + */ + KShortcut( int keyQt ) {} + + /** + * Creates a new shortcut that contains only the given qt key + * sequence. + * @param keySeq the qt key sequence to add + */ +//US KShortcut( const QKeySequence& keySeq ) {} + + /** + * Creates a new shortcut that contains only the given key + * in its only sequence. + * @param key the key to add + */ +//US KShortcut( const KKey& key ); + + /** + * Creates a new shortcut that contains only the given key + * sequence. + * @param keySeq the key sequence to add + */ +//US KShortcut( const KKeySequence& keySeq ); + + /** + * Copies the given shortcut. + * @param shortcut the shortcut to add + */ +//US KShortcut( const KShortcut& shortcut ); + + /** + * Creates a new key sequence that contains the given key sequence. + * The description consists of semicolon-separated keys as + * used in @ref KKeySequence::KKeySequence(const QString&). + * @param shortcut the description of the key + * @see KKeySequence::KKeySequence(const QString&) + */ + KShortcut( const char* shortcut ) {} + + /** + * Creates a new key sequence that contains the given key sequence. + * The description consists of semicolon-separated keys as + * used in @ref KKeySequence::KKeySequence(const QString&). + * @param shortcut the description of the key + * @see KKeySequence::KKeySequence(const QString&) + */ + KShortcut( const QString& shortcut ) {} + ~KShortcut() {} + + /** + * Clears the shortcut. The shortcut is null after calling this + * function. + * @see isNull() + */ +//US void clear(); + + /** + * Initializes the shortcut with the given Qt key code + * as the only key sequence. + * @param keyQt the qt keycode + * @see Qt::Key + */ +//US bool init( int keyQt ); + + /** + * Initializes the shortcut with the given qt key sequence. + * @param keySeq the qt key sequence to add + */ +//US bool init( const QKeySequence& keySeq ); + + /** + * Initializes the shortcut with the given key as its only sequence. + * @param key the key to add + */ +//US bool init( const KKey& key ); + + /** + * Initializes the shortcut with the given qt key sequence. + * @param keySeq the qt key sequence to add + */ +//US bool init( const KKeySequence& keySeq ); + + /** + * Copies the given shortcut. + * @param shortcut the shortcut to add + */ +//US bool init( const KShortcut& shortcut ); + + /** + * Initializes the key sequence with the given key sequence. + * The description consists of semicolon-separated keys as + * used in @ref KKeySequence::KKeySequence(const QString&). + * @param shortcut the description of the key + * @see KKeySequence::KKeySequence(const QString&) + */ +//US bool init( const QString& shortcut ); + + /** + * Copies the given shortcut over this shortcut. + */ +//US KShortcut& operator =( const KShortcut& cut ) +//US { init( cut ); return *this; } + + /** + * Returns the number of sequences that are in this + * shortcut. + * @return the number of sequences + * @ref MAX_SEQUENCES + */ +//US uint count() const; + + /** + * Returns the @p i'th key sequence of this shortcut. + * @param i the number of the key sequence to retrieve + * @return the @p i'th sequence or @ref KKeySequence::null() if + * there are less than @p i key sequences + * @ref MAX_SEQUENCES + */ +//US const KKeySequence& seq( uint i ) const; + + /** + * Returns the key code of the first key sequence, or + * null if there is no first key sequence. + * @return the key code of the first sequence's first key + * @see Qt::Key + * @see KKeySequence::keyCodeQt() + */ +//US int keyCodeQt() const; + + /** + * Returns true if the shortcut is null (after @ref clear() or empty + * constructor). + * @return true if the shortcut is null + * @see clear() + * @see null() + */ + bool isNull() const { return true; } + + /** + * Compares this object with the given shortcut. Returns a negative + * number if the given shortcut is larger, 0 if they are equal and + * a positive number this shortcut is larger. Shortcuts are + * compared by comparing the individual key sequences, starting from the + * beginning until an unequal key sequences has been found. If a shortcut + * contains more key sequences, it is considered larger. + * @param shortcut the shortcut to compare to + * @return a negative number if the given KShortcut is larger, 0 if + * they are equal and a positive number this KShortcut is larger + * @see KKey::compare() + * @see KKeyShortcut::compare() + */ +//US int compare( const KShortcut& shortcut ) const; + + /** + * Compares the sequences of both shortcuts. + * @see compare() + */ +//US bool operator == ( const KShortcut& cut ) const +//US { return compare( cut ) == 0; } + + /** + * Compares the sequences of both shortcuts. + * @see compare() + */ +//US bool operator != ( const KShortcut& cut ) const +//US { return compare( cut ) != 0; } + + /** + * Compares the sequences of both shortcuts. + * @see compare() + */ +//US bool operator < ( const KShortcut& cut ) const +//US { return compare( cut ) < 0; } + + /** + * Checks whether this shortcut contains a sequence that starts + * with the given key. + * @param key the key to check + * @return true if a key sequence starts with the key + */ +//US bool contains( const KKey& key ) const; + + /** + * Checks whether this shortcut contains a sequence that starts + * with the given key. + * @param key the key to check + * @return true if a key sequence starts with the key + */ +//US bool contains( const KKeyNative& key ) const; + + /** + * Checks whether this shortcut contains the given sequence. + * @param keySeq the key sequence to check + * @return true if the shortcut has the given key sequence + */ +//US bool contains( const KKeySequence& keySeq ) const; + + /** + * Sets the @p i'th key sequence of the shortcut. You can not introduce + * gaps in the list of sequences, so you must use an @i <= @ref count(). + * Also note that the maximum number of key sequences is @ref MAX_SEQUENCES. + * @param i the position of the new key sequence(<= @ref count(), + * <= @ref MAX_SEQUENCES) + * @param keySeq the key sequence to set + * @return true if successful, false otherwise + */ +//US bool setSeq( uint i, const KKeySequence& keySeq ); + + /** + * Appends the given key sequence. + * @param keySeq the key sequence to add + * @return true if successful, false otherwise + * @see setSeq() + * @see MAX_SEQUENCES + */ +//US bool append( const KKeySequence& keySeq ); + + /** + * Appends the given key + * @param spec the key to add + * @return true if successful, false otherwise + * @see setSeq() + * @see MAX_SEQUENCES + * @since 3.2 + */ +//US bool append( const KKey& spec ); + + /** + * Appends the sequences from the given shortcut. + * @param cut the shortcut to append + * @return true if successful, false otherwise + * @see MAX_SEQUENCES + * @since 3.2 + */ +//US bool append( const KShortcut& cut ); + + /** + * Converts this shortcut to a key sequence. The first key sequence + * will be taken. + */ +//US operator QKeySequence () const; + + /** + * Returns a description of the shortcut as semicolon-separated + * ket sequences, as returned by @ref KKeySequence::toString(). + * @return the string represenation of this shortcut + * @see KKey::toString() + * @see KKeySequence::toString() + */ +//US QString toString() const; + + /** + * @internal + */ + QString toStringInternal( const KShortcut* pcutDefault = 0 ) const + { + return "EMPTY IMPL."; + } + + /** + * Returns a null shortcut. + * @return the null shortcut + * @see isNull() + * @see clear() + */ +//US static KShortcut& null(); + +//US protected: +//US uint m_nSeqs; +//US KKeySequence m_rgseq[MAX_SEQUENCES]; + +//US private: +//US class KShortcutPrivate* d; +//US friend class KKeyNative; + +//US#ifndef KDE_NO_COMPAT +//US public: +//US operator int () const { return keyCodeQt(); } +//US#endif +}; + +#endif // __KSHORTCUT_H diff --git a/microkde/kdecore/kstandarddirs.cpp b/microkde/kdecore/kstandarddirs.cpp new file mode 100644 index 0000000..5abe05c --- a/dev/null +++ b/microkde/kdecore/kstandarddirs.cpp @@ -0,0 +1,1620 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org> + Copyright (C) 1999 Stephan Kulow <coolo@kde.org> + Copyright (C) 1999 Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org> + * Version: $Id$ + * Generated: Thu Mar 5 16:05:28 EST 1998 + */ + +//US #include "config.h" + +#include <stdlib.h> +#include <assert.h> +//US#include <errno.h> +//US #ifdef HAVE_SYS_STAT_H +//US #include <sys/stat.h> +//US #endif +//US#include <sys/types.h> +//US#include <dirent.h> +//US#include <pwd.h> + +#include <qregexp.h> +#include <qasciidict.h> +#include <qdict.h> +#include <qdir.h> +#include <qfileinfo.h> +#include <qstring.h> +#include <qstringlist.h> + +#include "kstandarddirs.h" +#include "kconfig.h" +#include "kdebug.h" +//US #include "kinstance.h" +#include "kshell.h" +//US#include <sys/param.h> +//US#include <unistd.h> + +//US +QString KStandardDirs::mAppDir = QString::null; + + +template class QDict<QStringList>; + +#if 0 +#include <qtextedit.h> +void ddd( QString op ) +{ + static QTextEdit * dot = 0; + if ( ! dot ) + dot = new QTextEdit(); + + dot->show(); + + dot->append( op ); + +} +#endif +class KStandardDirs::KStandardDirsPrivate +{ +public: + KStandardDirsPrivate() + : restrictionsActive(false), + dataRestrictionActive(false) + { } + + bool restrictionsActive; + bool dataRestrictionActive; + QAsciiDict<bool> restrictions; + QStringList xdgdata_prefixes; + QStringList xdgconf_prefixes; +}; + +static const char* const types[] = {"html", "icon", "apps", "sound", + "data", "locale", "services", "mime", + "servicetypes", "config", "exe", + "wallpaper", "lib", "pixmap", "templates", + "module", "qtplugins", + "xdgdata-apps", "xdgdata-dirs", "xdgconf-menu", 0 }; + +static int tokenize( QStringList& token, const QString& str, + const QString& delim ); + +KStandardDirs::KStandardDirs( ) : addedCustoms(false) +{ + d = new KStandardDirsPrivate; + dircache.setAutoDelete(true); + relatives.setAutoDelete(true); + absolutes.setAutoDelete(true); + savelocations.setAutoDelete(true); + addKDEDefaults(); +} + +KStandardDirs::~KStandardDirs() +{ + delete d; +} + +bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const +{ + if (!d || !d->restrictionsActive) + return false; + + if (d->restrictions[type]) + return true; + + if (strcmp(type, "data")==0) + { + applyDataRestrictions(relPath); + if (d->dataRestrictionActive) + { + d->dataRestrictionActive = false; + return true; + } + } + return false; +} + +void KStandardDirs::applyDataRestrictions(const QString &relPath) const +{ + QString key; + int i = relPath.find('/'); + if (i != -1) + key = "data_"+relPath.left(i); + else + key = "data_"+relPath; + + if (d && d->restrictions[key.latin1()]) + d->dataRestrictionActive = true; +} + + +QStringList KStandardDirs::allTypes() const +{ + QStringList list; + for (int i = 0; types[i] != 0; ++i) + list.append(QString::fromLatin1(types[i])); + return list; +} + +void KStandardDirs::addPrefix( const QString& _dir ) +{ + if (_dir.isNull()) + return; + + QString dir = _dir; + if (dir.at(dir.length() - 1) != '/') + dir += '/'; + + if (!prefixes.contains(dir)) { + prefixes.append(dir); + dircache.clear(); + } +} + +void KStandardDirs::addXdgConfigPrefix( const QString& _dir ) +{ + if (_dir.isNull()) + return; + + QString dir = _dir; + if (dir.at(dir.length() - 1) != '/') + dir += '/'; + + if (!d->xdgconf_prefixes.contains(dir)) { + d->xdgconf_prefixes.append(dir); + dircache.clear(); + } +} + +void KStandardDirs::addXdgDataPrefix( const QString& _dir ) +{ + if (_dir.isNull()) + return; + + QString dir = _dir; + if (dir.at(dir.length() - 1) != '/') + dir += '/'; + + if (!d->xdgdata_prefixes.contains(dir)) { + d->xdgdata_prefixes.append(dir); + dircache.clear(); + } +} + + +QString KStandardDirs::kfsstnd_prefixes() +{ + return prefixes.join(":"); +} + +bool KStandardDirs::addResourceType( const char *type, + const QString& relativename ) +{ + if (relativename.isNull()) + return false; + + QStringList *rels = relatives.find(type); + if (!rels) { + rels = new QStringList(); + relatives.insert(type, rels); + } + QString copy = relativename; + if (copy.at(copy.length() - 1) != '/') + copy += '/'; + if (!rels->contains(copy)) { + rels->prepend(copy); + dircache.remove(type); // clean the cache + return true; + } + return false; +} + +bool KStandardDirs::addResourceDir( const char *type, + const QString& absdir) +{ + QStringList *paths = absolutes.find(type); + if (!paths) { + paths = new QStringList(); + absolutes.insert(type, paths); + } + QString copy = absdir; + if (copy.at(copy.length() - 1) != '/') + copy += '/'; + + if (!paths->contains(copy)) { + paths->append(copy); + dircache.remove(type); // clean the cache + return true; + } + return false; +} + +QString KStandardDirs::findResource( const char *type, + const QString& filename ) const +{ + if (filename.at(0) == '/') + return filename; // absolute dirs are absolute dirs, right? :-/ + +#if 0 +kdDebug() << "Find resource: " << type << endl; +for (QStringList::ConstIterator pit = prefixes.begin(); + pit != prefixes.end(); + pit++) +{ + kdDebug() << "Prefix: " << *pit << endl; +} +#endif + + QString dir = findResourceDir(type, filename); + if (dir.isNull()) + return dir; + else return dir + filename; +} +/*US +static Q_UINT32 updateHash(const QString &file, Q_UINT32 hash) +{ + QCString cFile = QFile::encodeName(file); +//US struct stat buff; +//US if ((access(cFile, R_OK) == 0) && +//US (stat( cFile, &buff ) == 0) && +//US (S_ISREG( buff.st_mode ))) + QFileInfo pathfnInfo(cFile); + if (( pathfnInfo.isReadable() == true ) && + ( pathfnInfo.isFile()) ) + { +//US hash = hash + (Q_UINT32) buff.st_ctime; + hash = hash + (Q_UINT32) pathfnInfo.lastModified(); + } + return hash; +} +*/ +/*US +Q_UINT32 KStandardDirs::calcResourceHash( const char *type, + const QString& filename, bool deep) const +{ + Q_UINT32 hash = 0; + + if (filename.at(0) == '/') + { + // absolute dirs are absolute dirs, right? :-/ + return updateHash(filename, hash); + } + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(filename); + QStringList candidates = resourceDirs(type); + QString fullPath; + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + { + hash = updateHash(*it + filename, hash); + if (!deep && hash) + return hash; + } + return hash; +} +*/ + +QStringList KStandardDirs::findDirs( const char *type, + const QString& reldir ) const +{ + QStringList list; + + checkConfig(); + + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(reldir); + QStringList candidates = resourceDirs(type); + QDir testdir; + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) { + testdir.setPath(*it + reldir); + if (testdir.exists()) + list.append(testdir.absPath() + '/'); + } + + return list; +} + +QString KStandardDirs::findResourceDir( const char *type, + const QString& filename) const +{ +#ifndef NDEBUG + if (filename.isEmpty()) { + kdWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!" << endl; + return QString::null; + } +#endif + + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(filename); + QStringList candidates = resourceDirs(type); + QString fullPath; + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + if (exists(*it + filename)) + return *it; + +#ifndef NDEBUG + if(false && type != "locale") + kdDebug() << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\"." << endl; +#endif + + return QString::null; +} + +bool KStandardDirs::exists(const QString &fullPath) +{ +//US struct stat buff; + QFileInfo fullPathInfo(QFile::encodeName(fullPath)); + +//US if (access(QFile::encodeName(fullPath), R_OK) == 0 && fullPathInfo.isReadable()) + if (fullPathInfo.isReadable()) + { + if (fullPath.at(fullPath.length() - 1) != '/') { +//US if (S_ISREG( buff.st_mode )) + if (fullPathInfo.isFile()) + return true; + } + else { +//US if (S_ISDIR( buff.st_mode )) + if (fullPathInfo.isDir()) + return true; + } + } + return false; +} + +static void lookupDirectory(const QString& path, const QString &relPart, + const QRegExp ®exp, + QStringList& list, + QStringList& relList, + bool recursive, bool uniq) +{ + QString pattern = regexp.pattern(); + if (recursive || pattern.contains('?') || pattern.contains('*')) + { + // We look for a set of files. +//US DIR *dp = opendir( QFile::encodeName(path)); + QDir dp(QFile::encodeName(path)); + if (!dp.exists()) + return; + static int iii = 0; + ++iii; + if ( iii == 5 ) + abort(); + assert(path.at(path.length() - 1) == '/'); + +//US struct dirent *ep; +//US struct stat buff; + + QString _dot("."); + QString _dotdot(".."); + +//US while( ( ep = readdir( dp ) ) != 0L ) + QStringList direntries = dp.entryList(); + QStringList::Iterator it = direntries.begin(); + + while ( it != list.end() ) // for each file... + { + +//US QString fn( QFile::decodeName(ep->d_name)); + QString fn = (*it); // dp.entryList already decodes + it++; + if ( fn.isNull() ) + break; + + if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1).latin1() == '~' ) + continue; + +/*US + if (!recursive && !regexp.exactMatch(fn)) + continue; // No match +*/ +//US this should do the same: + int pos = regexp.match(fn); + if (!recursive && !pos == 0) + continue; // No match + + QString pathfn = path + fn; +/*US + if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) { + kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl; + continue; // Couldn't stat (e.g. no read permissions) + } + + if ( recursive ) + { + if ( S_ISDIR( buff.st_mode )) { + lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq); + } +*/ +//US replacement: + QFileInfo pathfnInfo(QFile::encodeName(pathfn)); + if ( pathfnInfo.isReadable() == false ) + { +//US kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl; + continue; // Couldn't stat (e.g. no read permissions) + } + + if ( recursive ) + { + if ( pathfnInfo.isDir()) { + lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq); + } + + +/*US + if (!regexp.exactMatch(fn)) + continue; // No match +*/ +//US this should do the same: + pos = regexp.match(fn); + if (!pos == 0) + continue; // No match + } + +//US if ( S_ISREG( buff.st_mode)) + if ( pathfnInfo.isFile()) + { + if (!uniq || !relList.contains(relPart + fn)) + { + list.append( pathfn ); + relList.append( relPart + fn ); + } + } + } +//US closedir( dp ); + } + else + { + // We look for a single file. + QString fn = pattern; + QString pathfn = path + fn; +//US struct stat buff; + QFileInfo pathfnInfo(QFile::encodeName(pathfn)); + + +//US if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) + if ( pathfnInfo.isReadable() == false ) + return; // File not found + +//US if ( S_ISREG( buff.st_mode)) + if ( pathfnInfo.isFile()) + { + if (!uniq || !relList.contains(relPart + fn)) + { + list.append( pathfn ); + relList.append( relPart + fn ); + } + } + } +} + +static void lookupPrefix(const QString& prefix, const QString& relpath, + const QString& relPart, + const QRegExp ®exp, + QStringList& list, + QStringList& relList, + bool recursive, bool uniq) +{ + if (relpath.isNull()) { + lookupDirectory(prefix, relPart, regexp, list, + relList, recursive, uniq); + return; + } + QString path; + QString rest; + + if (relpath.length()) + { + int slash = relpath.find('/'); + if (slash < 0) + rest = relpath.left(relpath.length() - 1); + else { + path = relpath.left(slash); + rest = relpath.mid(slash + 1); + } + } + assert(prefix.at(prefix.length() - 1) == '/'); + +//US struct stat buff; + + if (path.contains('*') || path.contains('?')) { + QRegExp pathExp(path, true, true); +//US DIR *dp = opendir( QFile::encodeName(prefix) ); + QDir dp(QFile::encodeName(prefix)); + +//US if (!dp) + if (!dp.exists()) + { + return; + } + +//US struct dirent *ep; + + QString _dot("."); + QString _dotdot(".."); + +//US while( ( ep = readdir( dp ) ) != 0L ) + QStringList direntries = dp.entryList(); + QStringList::Iterator it = direntries.begin(); + + while ( it != list.end() ) // for each file... + { +//US QString fn( QFile::decodeName(ep->d_name)); + QString fn = (*it); // dp.entryList() already encodes the strings + it++; + + if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1) == '~') + continue; + +#ifdef DESKTOP_VERSION + + if (pathExp.search(fn) == -1) + continue; // No match + +#else +//US this should do the same: + if (pathExp.find(fn, 0) == -1) + continue; // No match +#endif + QString rfn = relPart+fn; + fn = prefix + fn; +//US if ( stat( QFile::encodeName(fn), &buff ) != 0 ) + QFileInfo fnInfo(QFile::encodeName(fn)); + if ( fnInfo.isReadable() == false ) + { +//US kdDebug() << "Error statting " << fn << " : " << perror << endl; + continue; // Couldn't stat (e.g. no permissions) + } +//US if ( S_ISDIR( buff.st_mode )) + if ( fnInfo.isDir() ) + + lookupPrefix(fn + '/', rest, rfn + '/', regexp, list, relList, recursive, uniq); + } + +//US closedir( dp ); + } else { + // Don't stat, if the dir doesn't exist we will find out + // when we try to open it. + lookupPrefix(prefix + path + '/', rest, + relPart + path + '/', regexp, list, + relList, recursive, uniq); + } +} + +QStringList +KStandardDirs::findAllResources( const char *type, + const QString& filter, + bool recursive, + bool uniq, + QStringList &relList) const +{ + QStringList list; + if (filter.at(0) == '/') // absolute paths we return + { + list.append( filter); + return list; + } + + QString filterPath; + QString filterFile; + + if (filter.length()) + { + int slash = filter.findRev('/'); + if (slash < 0) + filterFile = filter; + else { + filterPath = filter.left(slash + 1); + filterFile = filter.mid(slash + 1); + } + } + checkConfig(); + + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(filter); + QStringList candidates = resourceDirs(type); + if (filterFile.isEmpty()) + filterFile = "*"; + + QRegExp regExp(filterFile, true, true); + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + { + lookupPrefix(*it, filterPath, "", regExp, list, + relList, recursive, uniq); + } + return list; +} + +QStringList +KStandardDirs::findAllResources( const char *type, + const QString& filter, + bool recursive, + bool uniq) const +{ + QStringList relList; + return findAllResources(type, filter, recursive, uniq, relList); +} + +QString +KStandardDirs::realPath(const QString &dirname) +{ +#ifdef _WIN32_ + return dirname; +#else +//US char realpath_buffer[MAXPATHLEN + 1]; +//US memset(realpath_buffer, 0, MAXPATHLEN + 1); + char realpath_buffer[250 + 1]; + memset(realpath_buffer, 0, 250 + 1); + + /* If the path contains symlinks, get the real name */ + if (realpath( QFile::encodeName(dirname).data(), realpath_buffer) != 0) { + // succes, use result from realpath + int len = strlen(realpath_buffer); + realpath_buffer[len] = '/'; + realpath_buffer[len+1] = 0; + return QFile::decodeName(realpath_buffer); + } + + return dirname; +#endif +} +/*US +void KStandardDirs::createSpecialResource(const char *type) +{ + char hostname[256]; + hostname[0] = 0; + gethostname(hostname, 255); + QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname); + char link[1024]; + link[1023] = 0; + int result = readlink(QFile::encodeName(dir).data(), link, 1023); + if ((result == -1) && (errno == ENOENT)) + { + QString srv = findExe(QString::fromLatin1("lnusertemp"), KDEDIR+QString::fromLatin1("/bin")); + if (srv.isEmpty()) + srv = findExe(QString::fromLatin1("lnusertemp")); + if (!srv.isEmpty()) + { + system(QFile::encodeName(srv)+" "+type); + result = readlink(QFile::encodeName(dir).data(), link, 1023); + } + } + if (result > 0) + { + link[result] = 0; + if (link[0] == '/') + dir = QFile::decodeName(link); + else + dir = QDir::cleanDirPath(dir+QFile::decodeName(link)); + } + addResourceDir(type, dir+'/'); +} +*/ + +QStringList KStandardDirs::resourceDirs(const char *type) const +{ + QStringList *candidates = dircache.find(type); + + if (!candidates) { // filling cache +/*US + if (strcmp(type, "socket") == 0) + const_cast<KStandardDirs *>(this)->createSpecialResource(type); + else if (strcmp(type, "tmp") == 0) + const_cast<KStandardDirs *>(this)->createSpecialResource(type); + else if (strcmp(type, "cache") == 0) + const_cast<KStandardDirs *>(this)->createSpecialResource(type); +*/ + QDir testdir; + + candidates = new QStringList(); + QStringList *dirs; + + bool restrictionActive = false; + if (d && d->restrictionsActive) + { + if (d->dataRestrictionActive) + restrictionActive = true; + else if (d->restrictions["all"]) + restrictionActive = true; + else if (d->restrictions[type]) + restrictionActive = true; + d->dataRestrictionActive = false; // Reset + } + + dirs = relatives.find(type); + if (dirs) + { + bool local = true; + const QStringList *prefixList = 0; + if (strncmp(type, "xdgdata-", 8) == 0) + prefixList = &(d->xdgdata_prefixes); + else if (strncmp(type, "xdgconf-", 8) == 0) + prefixList = &(d->xdgconf_prefixes); + else + prefixList = &prefixes; + + for (QStringList::ConstIterator pit = prefixList->begin(); + pit != prefixList->end(); + pit++) + { + for (QStringList::ConstIterator it = dirs->begin(); + it != dirs->end(); ++it) { + QString path = realPath(*pit + *it); + testdir.setPath(path); + if (local && restrictionActive) + continue; + if ((local || testdir.exists()) && !candidates->contains(path)) + candidates->append(path); + } + local = false; + } + } + dirs = absolutes.find(type); + if (dirs) + for (QStringList::ConstIterator it = dirs->begin(); + it != dirs->end(); ++it) + { + testdir.setPath(*it); + if (testdir.exists()) + { + QString filename = realPath(*it); + if (!candidates->contains(filename)) + candidates->append(filename); + } + } + dircache.insert(type, candidates); + } + +#if 0 + kdDebug() << "found dirs for resource " << type << ":" << endl; + for (QStringList::ConstIterator pit = candidates->begin(); + pit != candidates->end(); + pit++) + { + fprintf(stderr, "%s\n", (*pit).latin1()); + } +#endif + + + return *candidates; +} + +/*US +QString KStandardDirs::findExe( const QString& appname, + const QString& pstr, bool ignore) +{ + QFileInfo info; + + // absolute path ? + if (appname.startsWith(QString::fromLatin1("/"))) + { + info.setFile( appname ); + if( info.exists() && ( ignore || info.isExecutable() ) + && info.isFile() ) { + return appname; + } + return QString::null; + } + +//US QString p = QString("%1/%2").arg(__KDE_BINDIR).arg(appname); + QString p = QString("%1/%2").arg(appname).arg(appname); + qDebug("KStandardDirs::findExe this is probably wrong"); + + info.setFile( p ); + if( info.exists() && ( ignore || info.isExecutable() ) + && ( info.isFile() || info.isSymLink() ) ) { + return p; + } + + QStringList tokens; + p = pstr; + + if( p.isNull() ) { + p = getenv( "PATH" ); + } + + tokenize( tokens, p, ":\b" ); + + // split path using : or \b as delimiters + for( unsigned i = 0; i < tokens.count(); i++ ) { + p = tokens[ i ]; + + if ( p[ 0 ] == '~' ) + { + int len = p.find( '/' ); + if ( len == -1 ) + len = p.length(); + if ( len == 1 ) + p.replace( 0, 1, QDir::homeDirPath() ); + else + { + QString user = p.mid( 1, len - 1 ); + struct passwd *dir = getpwnam( user.local8Bit().data() ); + if ( dir && strlen( dir->pw_dir ) ) + p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) ); + } + } + + p += "/"; + p += appname; + + // Check for executable in this tokenized path + info.setFile( p ); + + if( info.exists() && ( ignore || info.isExecutable() ) + && ( info.isFile() || info.isSymLink() ) ) { + return p; + } + } + + // If we reach here, the executable wasn't found. + // So return empty string. + + return QString::null; +} + +int KStandardDirs::findAllExe( QStringList& list, const QString& appname, + const QString& pstr, bool ignore ) +{ + QString p = pstr; + QFileInfo info; + QStringList tokens; + + if( p.isNull() ) { + p = getenv( "PATH" ); + } + + list.clear(); + tokenize( tokens, p, ":\b" ); + + for ( unsigned i = 0; i < tokens.count(); i++ ) { + p = tokens[ i ]; + p += "/"; + p += appname; + + info.setFile( p ); + + if( info.exists() && (ignore || info.isExecutable()) + && info.isFile() ) { + list.append( p ); + } + + } + + return list.count(); +} +*/ + +static int tokenize( QStringList& tokens, const QString& str, + const QString& delim ) +{ + int len = str.length(); + QString token = ""; + + for( int index = 0; index < len; index++) + { + if ( delim.find( str[ index ] ) >= 0 ) + { + tokens.append( token ); + token = ""; + } + else + { + token += str[ index ]; + } + } + if ( token.length() > 0 ) + { + tokens.append( token ); + } + + return tokens.count(); +} + +QString KStandardDirs::kde_default(const char *type) { + if (!strcmp(type, "data")) + return "apps/"; + if (!strcmp(type, "html")) + return "share/doc/HTML/"; + if (!strcmp(type, "icon")) + return "share/icons/"; + if (!strcmp(type, "config")) + return "config/"; + if (!strcmp(type, "pixmap")) + return "share/pixmaps/"; + if (!strcmp(type, "apps")) + return "share/applnk/"; + if (!strcmp(type, "sound")) + return "share/sounds/"; + if (!strcmp(type, "locale")) + return "share/locale/"; + if (!strcmp(type, "services")) + return "share/services/"; + if (!strcmp(type, "servicetypes")) + return "share/servicetypes/"; + if (!strcmp(type, "mime")) + return "share/mimelnk/"; + if (!strcmp(type, "cgi")) + return "cgi-bin/"; + if (!strcmp(type, "wallpaper")) + return "share/wallpapers/"; + if (!strcmp(type, "templates")) + return "share/templates/"; + if (!strcmp(type, "exe")) + return "bin/"; + if (!strcmp(type, "lib")) + return "lib/"; + if (!strcmp(type, "module")) + return "lib/kde3/"; + if (!strcmp(type, "qtplugins")) + return "lib/kde3/plugins"; + if (!strcmp(type, "xdgdata-apps")) + return "applications/"; + if (!strcmp(type, "xdgdata-dirs")) + return "desktop-directories/"; + if (!strcmp(type, "xdgconf-menu")) + return "menus/"; + qFatal("unknown resource type %s", type); + return QString::null; +} + +QString KStandardDirs::saveLocation(const char *type, + const QString& suffix, + bool create) const +{ + //qDebug("KStandardDirs::saveLocation called %s %s", type,suffix.latin1() ); + //return ""; + checkConfig(); + + QString *pPath = savelocations.find(type); + if (!pPath) + { + QStringList *dirs = relatives.find(type); + if (!dirs && ( + (strcmp(type, "socket") == 0) || + (strcmp(type, "tmp") == 0) || + (strcmp(type, "cache") == 0) )) + { + (void) resourceDirs(type); // Generate socket|tmp|cache resource. + dirs = relatives.find(type); // Search again. + } + if (dirs) + { + // Check for existance of typed directory + suffix + if (strncmp(type, "xdgdata-", 8) == 0) + pPath = new QString(realPath(localxdgdatadir() + dirs->last())); + else if (strncmp(type, "xdgconf-", 8) == 0) + pPath = new QString(realPath(localxdgconfdir() + dirs->last())); + else + pPath = new QString(realPath(localkdedir() + dirs->last())); + } + else { + dirs = absolutes.find(type); + if (!dirs) + qFatal("KStandardDirs: The resource type %s is not registered", type); + pPath = new QString(realPath(dirs->last())); + } + + savelocations.insert(type, pPath); + } + + QString fullPath = *pPath + suffix; +//US struct stat st; +//US if (stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) + QFileInfo fullPathInfo(QFile::encodeName(fullPath)); + if (fullPathInfo.isReadable() || !fullPathInfo.isDir()) + + + { + if(!create) { +#ifndef NDEBUG + qDebug("save location %s doesn't exist", fullPath.latin1()); +#endif + return fullPath; + } + if(!makeDir(fullPath, 0700)) { + qWarning("failed to create %s", fullPath.latin1()); + return fullPath; + } + dircache.remove(type); + } + return fullPath; +} + +QString KStandardDirs::relativeLocation(const char *type, const QString &absPath) +{ + QString fullPath = absPath; + int i = absPath.findRev('/'); + if (i != -1) + { + fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1); // Normalize + } + + QStringList candidates = resourceDirs(type); + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + if (fullPath.startsWith(*it)) + { + return fullPath.mid((*it).length()); + } + + return absPath; +} + + +bool KStandardDirs::makeDir(const QString& dir2, int mode) +{ + QString dir = QDir::convertSeparators( dir2 ); +#if 0 + //LR + + // we want an absolute path + if (dir.at(0) != '/') + return false; + + QString target = dir; + uint len = target.length(); + + // append trailing slash if missing + if (dir.at(len - 1) != '/') + target += '/'; + + QString base(""); + uint i = 1; + + while( i < len ) + { +//US struct stat st; + int pos = target.find('/', i); + base += target.mid(i - 1, pos - i + 1); + QCString baseEncoded = QFile::encodeName(base); + // bail out if we encountered a problem +//US if (stat(baseEncoded, &st) != 0) + QFileInfo baseEncodedInfo(baseEncoded); + if (!baseEncodedInfo.exists()) + { + // Directory does not exist.... + // Or maybe a dangling symlink ? +//US if (lstat(baseEncoded, &st) == 0) + if (baseEncodedInfo.isSymLink()) { +//US (void)unlink(baseEncoded); // try removing + QFile(baseEncoded).remove(); + } + +//US if ( mkdir(baseEncoded, (mode_t) mode) != 0) + QDir dirObj; + if ( dirObj.mkdir(baseEncoded) != true ) + { +//US perror("trying to create local folder"); + return false; // Couldn't create it :-( + } + } + i = pos + 1; + } + return true; +#endif + + // ******************************************** + // new code for WIN32 + QDir dirObj; + + + // we want an absolute path +#ifndef _WIN32_ + if (dir.at(0) != '/') + return false; +#endif + + QString target = dir; + uint len = target.length(); +#ifndef _WIN32_ + // append trailing slash if missing + if (dir.at(len - 1) != '/') + target += '/'; +#endif + + QString base(""); + uint i = 1; + + while( i < len ) + { +//US struct stat st; +#ifndef _WIN32_ + int pos = target.find('/', i); +#else + int pos = target.find('\\', i); +#endif + if ( pos < 0 ) + return true; + base += target.mid(i - 1, pos - i + 1); + //QMessageBox::information( 0,"cap111", base, 1 ); +/*US + QCString baseEncoded = QFile::encodeName(base); + // bail out if we encountered a problem + if (stat(baseEncoded, &st) != 0) + { + // Directory does not exist.... + // Or maybe a dangling symlink ? + if (lstat(baseEncoded, &st) == 0) + (void)unlink(baseEncoded); // try removing + + + if ( mkdir(baseEncoded, (mode_t) mode) != 0) { + perror("trying to create local folder"); + return false; // Couldn't create it :-( + } + } +*/ + + if (dirObj.exists(base) == false) + { + //qDebug("KStandardDirs::makeDir try to create : %s" , base.latin1()); + if (dirObj.mkdir(base) != true) + { + qDebug("KStandardDirs::makeDir could not create: %s" , base.latin1()); + return false; + } + } + + i = pos + 1; + } + return true; + +} + +static QString readEnvPath(const char *env) +{ +#ifdef _WIN32_ + return ""; +#else + QCString c_path = getenv(env); + if (c_path.isEmpty()) + return QString::null; + return QFile::decodeName(c_path); +#endif +} + +void KStandardDirs::addKDEDefaults() +{ + //qDebug("ERROR: KStandardDirs::addKDEDefaults() called "); + //return; + QStringList kdedirList; + + // begin KDEDIRS + QString kdedirs = readEnvPath("MICROKDEDIRS"); + if (!kdedirs.isEmpty()) + { + tokenize(kdedirList, kdedirs, ":"); + } + else + { + QString kdedir = readEnvPath("MICROKDEDIR"); + if (!kdedir.isEmpty()) + { + kdedir = KShell::tildeExpand(kdedir); + kdedirList.append(kdedir); + } + } +//US kdedirList.append(KDEDIR); + +#ifdef __KDE_EXECPREFIX + QString execPrefix(__KDE_EXECPREFIX); + if (execPrefix!="NONE") + kdedirList.append(execPrefix); +#endif + + QString localKdeDir; + +//US if (getuid()) + if (true) + { + localKdeDir = readEnvPath("MICROKDEHOME"); + if (!localKdeDir.isEmpty()) + { + if (localKdeDir.at(localKdeDir.length()-1) != '/') + localKdeDir += '/'; + } + else + { + localKdeDir = QDir::homeDirPath() + "/kdepim/"; + } + } + else + { + // We treat root different to prevent root messing up the + // file permissions in the users home directory. + localKdeDir = readEnvPath("MICROKDEROOTHOME"); + if (!localKdeDir.isEmpty()) + { + if (localKdeDir.at(localKdeDir.length()-1) != '/') + localKdeDir += '/'; + } + else + { +//US struct passwd *pw = getpwuid(0); +//US localKdeDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.microkde/"; + qDebug("KStandardDirs::addKDEDefaults: 1 has to be fixed"); + } + + } + +//US localKdeDir = appDir(); + +//US +// qDebug("KStandardDirs::addKDEDefaults: localKdeDir=%s", localKdeDir.latin1()); + if (localKdeDir != "-/") + { + localKdeDir = KShell::tildeExpand(localKdeDir); + addPrefix(localKdeDir); + } + + for (QStringList::ConstIterator it = kdedirList.begin(); + it != kdedirList.end(); it++) + { + QString dir = KShell::tildeExpand(*it); + addPrefix(dir); + } + // end KDEDIRS + + // begin XDG_CONFIG_XXX + QStringList xdgdirList; + QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS"); + if (!xdgdirs.isEmpty()) + { + tokenize(xdgdirList, xdgdirs, ":"); + } + else + { + xdgdirList.clear(); + xdgdirList.append("/etc/xdg"); + } + + QString localXdgDir = readEnvPath("XDG_CONFIG_HOME"); + if (!localXdgDir.isEmpty()) + { + if (localXdgDir.at(localXdgDir.length()-1) != '/') + localXdgDir += '/'; + } + else + { +//US if (getuid()) + if (true) + { + localXdgDir = QDir::homeDirPath() + "/.config/"; + } + else + { +//US struct passwd *pw = getpwuid(0); +//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.config/"; + qDebug("KStandardDirs::addKDEDefaults: 2 has to be fixed"); + } + } + + localXdgDir = KShell::tildeExpand(localXdgDir); + addXdgConfigPrefix(localXdgDir); + + for (QStringList::ConstIterator it = xdgdirList.begin(); + it != xdgdirList.end(); it++) + { + QString dir = KShell::tildeExpand(*it); + addXdgConfigPrefix(dir); + } + // end XDG_CONFIG_XXX + + // begin XDG_DATA_XXX + xdgdirs = readEnvPath("XDG_DATA_DIRS"); + if (!xdgdirs.isEmpty()) + { + tokenize(xdgdirList, xdgdirs, ":"); + } + else + { + xdgdirList.clear(); + for (QStringList::ConstIterator it = kdedirList.begin(); + it != kdedirList.end(); it++) + { + QString dir = *it; + if (dir.at(dir.length()-1) != '/') + dir += '/'; + xdgdirList.append(dir+"share/"); + } + + xdgdirList.append("/usr/local/share/"); + xdgdirList.append("/usr/share/"); + } + + localXdgDir = readEnvPath("XDG_DATA_HOME"); + if (!localXdgDir.isEmpty()) + { + if (localXdgDir.at(localXdgDir.length()-1) != '/') + localXdgDir += '/'; + } + else + { +//US if (getuid()) + if (true) + { + localXdgDir = QDir::homeDirPath() + "/.local/share/"; + } + else + { +//US struct passwd *pw = getpwuid(0); +//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.local/share/"; + qDebug("KStandardDirs::addKDEDefaults: 3 has to be fixed"); + } + } + + localXdgDir = KShell::tildeExpand(localXdgDir); + addXdgDataPrefix(localXdgDir); + + for (QStringList::ConstIterator it = xdgdirList.begin(); + it != xdgdirList.end(); it++) + { + QString dir = KShell::tildeExpand(*it); + + addXdgDataPrefix(dir); + } + // end XDG_DATA_XXX + + + uint index = 0; + while (types[index] != 0) { + addResourceType(types[index], kde_default(types[index])); + index++; + } + + addResourceDir("home", QDir::homeDirPath()); +} + +void KStandardDirs::checkConfig() const +{ +/*US + if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config) + const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config); +*/ + if (!addedCustoms && KGlobal::config()) + const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::config()); +} + +bool KStandardDirs::addCustomized(KConfig *config) +{ + if (addedCustoms) // there are already customized entries + return false; // we just quite and hope they are the right ones + + // save the numbers of config directories. If this changes, + // we will return true to give KConfig a chance to reparse + uint configdirs = resourceDirs("config").count(); + + // reading the prefixes in + QString oldGroup = config->group(); + config->setGroup("Directories"); + + QStringList list; + QStringList::ConstIterator it; + list = config->readListEntry("prefixes"); + for (it = list.begin(); it != list.end(); it++) + addPrefix(*it); + + // iterating over all entries in the group Directories + // to find entries that start with dir_$type +/*US + QMap<QString, QString> entries = config->entryMap("Directories"); + + QMap<QString, QString>::ConstIterator it2; + for (it2 = entries.begin(); it2 != entries.end(); it2++) + { + QString key = it2.key(); + if (key.left(4) == "dir_") { + // generate directory list, there may be more than 1. + QStringList dirs = QStringList::split(',', *it2); + QStringList::Iterator sIt(dirs.begin()); + QString resType = key.mid(4, key.length()); + for (; sIt != dirs.end(); ++sIt) { + addResourceDir(resType.latin1(), *sIt); + } + } + } + + // Process KIOSK restrictions. + config->setGroup("KDE Resource Restrictions"); + entries = config->entryMap("KDE Resource Restrictions"); + for (it2 = entries.begin(); it2 != entries.end(); it2++) + { + QString key = it2.key(); + if (!config->readBoolEntry(key, true)) + { + d->restrictionsActive = true; + d->restrictions.insert(key.latin1(), &d->restrictionsActive); // Anything will do + dircache.remove(key.latin1()); + } + } +*/ + // save it for future calls - that will return + addedCustoms = true; + config->setGroup(oldGroup); + + // return true if the number of config dirs changed + return (resourceDirs("config").count() != configdirs); +} + +QString KStandardDirs::localkdedir() const +{ + // Return the prefix to use for saving + return prefixes.first(); +} + +QString KStandardDirs::localxdgdatadir() const +{ + // Return the prefix to use for saving + return d->xdgdata_prefixes.first(); +} + +QString KStandardDirs::localxdgconfdir() const +{ + // Return the prefix to use for saving + return d->xdgconf_prefixes.first(); +} + +void KStandardDirs::setAppDir( const QString &appDir ) +{ + mAppDir = appDir; + + if ( mAppDir.right( 1 ) != "/" ) + mAppDir += "/"; +} + +QString KStandardDirs::appDir() +{ + return mAppDir; +} + +// just to make code more readable without macros +QString locate( const char *type, + const QString& filename/*US , const KInstance* inst*/ ) +{ +//US return inst->dirs()->findResource(type, filename); + return KGlobal::dirs()->findResource(type, filename); +} + +QString locateLocal( const char *type, + const QString& filename/*US , const KInstance* inst*/ ) +{ + + QString path = locateLocal(type, filename, true /*US, inst*/); + + +/* + static int ccc = 0; + ++ccc; + if ( ccc > 13 ) + abort(); +*/ + qDebug("locatelocal: %s" , path.latin1()); + return path; + +/*US why do we put all files into one directory. It is quit complicated. +why not staying with the original directorystructure ? + + + QString escapedFilename = filename; + escapedFilename.replace( QRegExp( "/" ), "_" ); + + QString path = KStandardDirs::appDir() + type + "_" + escapedFilename; + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; +*/ +//US so my proposal is this: + +// QString escapedFilename = filename; +// escapedFilename.replace( QRegExp( "/" ), "_" ); + +#if 0 +#ifdef _WIN32_ + QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename); +#else + QString path = KStandardDirs::appDir() + type + "/" + filename; +#endif + + //US Create the containing dir if needed + QFileInfo fi ( path ); + + // QString dir=pathurl.directory(); + // QMessageBox::information( 0,"path", path, 1 ); + +#ifdef _WIN32_ + KStandardDirs::makeDir(path); +#else + KStandardDirs::makeDir(fi.dirPath( true )); +#endif + + qDebug("locate22: %s" , path.latin1()); + return path; + +#endif + +} + +QString locateLocal( const char *type, + const QString& filename, bool createDir/*US , const KInstance* inst*/ ) +{ + // try to find slashes. If there are some, we have to + // create the subdir first + int slash = filename.findRev('/')+1; + if (!slash) // only one filename +//US return inst->dirs()->saveLocation(type, QString::null, createDir) + filename; + return KGlobal::dirs()->saveLocation(type, QString::null, createDir) + filename; + + // split path from filename + QString dir = filename.left(slash); + QString file = filename.mid(slash); +//US return inst->dirs()->saveLocation(type, dir, createDir) + file; + return KGlobal::dirs()->saveLocation(type, dir, createDir) + file; + + // *************************************************************** +#if 0 + +/*US why do we put all files into one directory. It is quit complicated. +why not staying with the original directorystructure ? + + + QString escapedFilename = filename; + escapedFilename.replace( QRegExp( "/" ), "_" ); + + QString path = KStandardDirs::appDir() + type + "_" + escapedFilename; + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; +*/ +//US so my proposal is this: + +// QString escapedFilename = filename; +// escapedFilename.replace( QRegExp( "/" ), "_" ); + +#ifdef _WIN32_ + QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename); +#else + QString path = KStandardDirs::appDir() + type + "/" + filename; +#endif + + //US Create the containing dir if needed + KURL pathurl; + pathurl.setPath(path); + QString dir=pathurl.directory(); + // QMessageBox::information( 0,"path", path, 1 ); +#ifdef _WIN32_ + KStandardDirs::makeDir(path); +#else + KStandardDirs::makeDir(dir); +#endif + + return path; +#endif +} diff --git a/microkde/kdecore/kstandarddirs.h b/microkde/kdecore/kstandarddirs.h new file mode 100644 index 0000000..c4e1108 --- a/dev/null +++ b/microkde/kdecore/kstandarddirs.h @@ -0,0 +1,681 @@ +/* + This file is part of the KDE libraries + Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org> + Stephan Kulow <coolo@kde.org> + Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef SSK_KSTDDIRS_H +#define SSK_KSTDDIRS_H + +#include <qstring.h> +#include <qdict.h> +#include <qstringlist.h> +#include <kglobal.h> + +class KConfig; +class KStandardDirsPrivate; + + +/** + * @short Site-independent access to standard KDE directories. + * @author Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org> + * @version $Id$ + * + * This is one of the most central classes in kdelibs as + * it provides a basic service: It knows where the files + * reside on the user's hard disk. And it's meant to be the + * only one that knows -- to make the real location as + * transparent as possible to both the user and the applications. + * + * To this end it insulates the application from all information + * and applications always refer to a file with a resource type + * (e.g. icon) and a filename (e.g. khexdit.xpm). In an ideal world + * the application would make no assumption where this file is and + * leave it up to @ref KStandardDirs::findResource("apps", "Home.desktop") + * to apply this knowledge to return /opt/kde/share/applnk/Home.desktop + * or ::locate("data", "kgame/background.jpg") to return + * /opt/kde/share/apps/kgame/background.jpg + * + * The main idea behind KStandardDirs is that there are several + * toplevel prefixes below which the files lie. One of these prefixes is + * the one where the user installed kdelibs, one is where the + * application was installed, and one is $HOME/.kde, but there + * may be even more. Under these prefixes there are several well + * defined suffixes where specific resource types are to be found. + * For example, for the resource type "html" the suffixes could be + * share/doc/HTML and share/doc/kde/HTML. + * So the search algorithm basicly appends to each prefix each registered + * suffix and tries to locate the file there. + * To make the thing even more complex, it's also possible to register + * absolute paths that KStandardDirs looks up after not finding anything + * in the former steps. They can be useful if the user wants to provide + * specific directories that aren't in his $HOME/.kde directory for, + * for example, icons. + * + * @sect Standard resources that kdelibs allocates are: + * + * @li apps - Applications menu (.desktop files). + * @li cache - Cached information (e.g. favicons, web-pages) + * @li cgi - CGIs to run from kdehelp. + * @li config - Configuration files. + * @li data - Where applications store data. + * @li exe - Executables in $prefix/bin. @ref findExe() for a function that takes $PATH into account. + * @li html - HTML documentation. + * @li icon - Icons, see @ref KIconLoader. + * @li lib - Libraries. + * @li locale - Translation files for @ref KLocale. + * @li mime - Mime types. + * @li module - Module (dynamically loaded library). + * @li qtplugins - Qt plugins (dynamically loaded objects for Qt) + * @li services - Services. + * @li servicetypes - Service types. + * @li scripts - Application scripting additions. + * @li sound - Application sounds. + * @li templates - Templates + * @li wallpaper - Wallpapers. + * @li tmp - Temporary files (specfic for both current host and current user) + * @li socket - UNIX Sockets (specific for both current host and current user) + * + * A type that is added by the class @ref KApplication if you use it, is + * appdata. This one makes the use of the type data a bit easier as it + * appends the name of the application. + * So while you had to ::locate("data", "appname/filename") so you can + * also write ::locate("appdata", "filename") if your KApplication instance + * is called "appname" (as set via KApplication's constructor or KAboutData, if + * you use the global KStandardDirs object @ref KGlobal::dirs()). + * Please note though that you cannot use the "appdata" + * type if you intend to use it in an applet for Kicker because 'appname' would + * be "Kicker" instead of the applet's name. Therefore, for applets, you've got + * to work around this by using ::locate("data", "appletname/filename"). + * + * @sect KStandardDirs supports the following environment variables: + * + * @li KDEDIRS: This may set an additional number of directory prefixes to + * search for resources. The directories should be seperated + * by ':'. The directories are searched in the order they are + * specified. + * @li KDEDIR: Used for backwards compatibility. As KDEDIRS but only a single + * directory may be specified. If KDEDIRS is set KDEDIR is + * ignored. + * @li KDEHOME: The directory where changes are saved to. This directory is + * used to search for resources first. If KDEHOME is not + * specified it defaults to "$HOME/.kde" + * @li KDEROOTHOME: Like KDEHOME, but used for the root user. + * If KDEROOTHOME is not set it defaults to the .kde directory in the + * home directory of root, usually "/root/.kde". + * Note that the setting of $HOME is ignored in this case. + * + * @see KGlobalSettings + */ +class KStandardDirs +{ +public: + /** + * KStandardDirs' constructor. It just initializes the caches. + **/ + KStandardDirs( ); + + /** + * KStandardDirs' destructor. + */ + virtual ~KStandardDirs(); + + /** + * Adds another search dir to front of the @p fsstnd list. + * + * @li When compiling kdelibs, the prefix is added to this. + * @li KDEDIRS or KDEDIR is taking into account + * @li Additional dirs may be loaded from kdeglobals. + * + * @param dir The directory to append relative paths to. + */ + void addPrefix( const QString& dir ); + + /** + * Adds another search dir to front of the XDG_CONFIG_XXX list + * of prefixes. + * This prefix is only used for resources that start with "xdgconf-" + * + * @param dir The directory to append relative paths to. + */ + void addXdgConfigPrefix( const QString& dir ); + + /** + * Adds another search dir to front of the XDG_DATA_XXX list + * of prefixes. + * This prefix is only used for resources that start with "xdgdata-" + * + * @param dir The directory to append relative paths to. + */ + void addXdgDataPrefix( const QString& dir ); + + /** + * Adds suffixes for types. + * + * You may add as many as you need, but it is advised that there + * is exactly one to make writing definite. + * All basic types (@ref kde_default) are added by @ref addKDEDefaults(), + * but for those you can add more relative paths as well. + * + * The later a suffix is added, the higher its priority. Note, that the + * suffix should end with / but doesn't have to start with one (as prefixes + * should end with one). So adding a suffix for app_pics would look + * like KGlobal::dirs()->addResourceType("app_pics", "share/app/pics"); + * + * @param type Specifies a short descriptive string to access + * files of this type. + * @param relativename Specifies a directory relative to the root + * of the KFSSTND. + * @return true if successful, false otherwise. + */ + bool addResourceType( const char *type, + const QString& relativename ); + + /** + * Adds absolute path at the end of the search path for + * particular types (for example in case of icons where + * the user specifies extra paths). + * + * You shouldn't need this + * function in 99% of all cases besides adding user-given + * paths. + * + * @param type Specifies a short descriptive string to access files + * of this type. + * @param absdir Points to directory where to look for this specific + * type. Non-existant directories may be saved but pruned. + * @return true if successful, false otherwise. + */ + bool addResourceDir( const char *type, + const QString& absdir); + + /** + * Tries to find a resource in the following order: + * @li All PREFIX/\<relativename> paths (most recent first). + * @li All absolute paths (most recent first). + * + * The filename should be a filename relative to the base dir + * for resources. So is a way to get the path to libkdecore.la + * to findResource("lib", "libkdecore.la"). KStandardDirs will + * then look into the subdir lib of all elements of all prefixes + * ($KDEDIRS) for a file libkdecore.la and return the path to + * the first one it finds (e.g. /opt/kde/lib/libkdecore.la) + * + * @param type The type of the wanted resource + * @param filename A relative filename of the resource. + * + * @return A full path to the filename specified in the second + * argument, or QString::null if not found. + */ + QString findResource( const char *type, + const QString& filename ) const; + + /** + * Checks whether a resource is restricted as part of the KIOSK + * framework. When a resource is restricted it means that user- + * specific files in the resource are ignored. + * + * E.g. by restricting the "wallpaper" resource, only system-wide + * installed wallpapers will be found by this class. Wallpapers + * installed under the $KDEHOME directory will be ignored. + * + * @param type The type of the resource to check + * @param relPath A relative path in the resource. + * + * @return True if the resource is restricted. + * @since 3.1 + */ + bool isRestrictedResource( const char *type, + const QString& relPath=QString::null ) const; + + /** + * Returns a number that identifies this version of the resource. + * When a change is made to the resource this number will change. + * + * @param type The type of the wanted resource + * @param filename A relative filename of the resource. + * @param deep If true, all resources are taken into account + * otherwise only the one returned by findResource(). + * + * @return A number identifying the current version of the + * resource. + */ +/*US + Q_UINT32 calcResourceHash( const char *type, + const QString& filename, bool deep) const; +*/ + /** + * Tries to find all directories whose names consist of the + * specified type and a relative path. So would + * findDirs("apps", "Settings") return + * @li /opt/kde/share/applnk/Settings/ + * @li /home/joe/.kde/share/applnk/Settings/ + * + * Note that it appends / to the end of the directories, + * so you can use this right away as directory names. + * + * @param type The type of the base directory. + * @param reldir Relative directory. + * + * @return A list of matching directories, or an empty + * list if the resource specified is not found. + */ + QStringList findDirs( const char *type, + const QString& reldir ) const; + + /** + * Tries to find the directory the file is in. + * It works the same as @ref findResource(), but it doesn't + * return the filename but the name of the directory. + * + * This way the application can access a couple of files + * that have been installed into the same directory without + * having to look for each file. + * + * findResourceDir("lib", "libkdecore.la") would return the + * path of the subdir libkdecore.la is found first in + * (e.g. /opt/kde/lib/) + * + * @param type The type of the wanted resource + * @param filename A relative filename of the resource. + * @return The directory where the file specified in the second + * argument is located, or QString::null if the type + * of resource specified is unknown or the resource + * cannot be found. + */ + QString findResourceDir( const char *type, + const QString& filename) const; + + + /** + * Tries to find all resources with the specified type. + * + * The function will look into all specified directories + * and return all filenames in these directories. + * + * @param type The type of resource to locate directories for. + * @param filter Only accept filenames that fit to filter. The filter + * may consist of an optional directory and a @ref QRegExp + * wildcard expression. E.g. "images\*.jpg". Use QString::null + * if you do not want a filter. + * @param recursive Specifies if the function should decend + * into subdirectories. + * @param uniq If specified, only return items which have + * unique suffixes - suppressing duplicated filenames. + * + * @return A list of directories matching the resource specified, + * or an empty list if the resource type is unknown. + */ + QStringList findAllResources( const char *type, + const QString& filter = QString::null, + bool recursive = false, + bool uniq = false) const; + + /** + * Tries to find all resources with the specified type. + * + * The function will look into all specified directories + * and return all filenames (full and relative paths) in + * these directories. + * + * @param type The type of resource to locate directories for. + * @param filter Only accept filenames that fit to filter. The filter + * may consist of an optional directory and a @ref QRegExp + * wildcard expression. E.g. "images\*.jpg". Use QString::null + * if you do not want a filter. + * @param recursive Specifies if the function should decend + * into subdirectories. + * @param uniq If specified, only return items which have + * unique suffixes. + * @param list Of relative paths for the given type. + * @param relPaths The list to store the relative paths into + * These can be used later to ::locate() the file + * + * @return A list of directories matching the resource specified, + * or an empty list if the resource type is unknown. + */ + QStringList findAllResources( const char *type, + const QString& filter, + bool recursive, + bool uniq, + QStringList &relPaths) const; + + /** + * Finds the executable in the system path. + * + * A valid executable must + * be a file and have its executable bit set. + * + * @param appname The name of the executable file for which to search. + * @param pathstr The path which will be searched. If this is + * null (default), the $PATH environment variable will + * be searched. + * @param ignoreExecBit If true, an existing file will be returned + * even if its executable bit is not set. + * + * @return The path of the executable. If it was not found, + * it will return QString::null. + * @see findAllExe() + */ +/*US + static QString findExe( const QString& appname, + const QString& pathstr=QString::null, + bool ignoreExecBit=false ); +*/ + + /** + * Finds all occurences of an executable in the system path. + * + * @param list Will be filled with the pathnames of all the + * executables found. Will be empty if the executable + * was not found. + * @param appname The name of the executable for which to + * search. + * @param pathstr The path list which will be searched. If this + * is 0 (default), the $PATH environment variable will + * be searched. + * @param ignoreExecBit If true, an existing file will be returned + * even if its executable bit is not set. + * + * @return The number of executables found, 0 if none were found. + * + * @see findExe() + */ + static int findAllExe( QStringList& list, const QString& appname, + const QString& pathstr=QString::null, + bool ignoreExecBit=false ); + + /** + * This function adds the defaults that are used by the current + * KDE version. + * + * It's a series of @ref addResourceTypes() + * and @ref addPrefix() calls. + * You normally wouldn't call this function because it's called + * for you from @ref KGlobal. + */ + void addKDEDefaults(); + + /** + * Reads customized entries out of the given config object and add + * them via @ref addResourceDirs(). + * + * @param config The object the entries are read from. This should + * contain global config files + * @return true if new config paths have been added + * from @p config. + **/ + bool addCustomized(KConfig *config); + + /** + * This function is used internally by almost all other function as + * it serves and fills the directories cache. + * + * @param type The type of resource + * @return The list of possible directories for the specified @p type. + * The function updates the cache if possible. If the resource + * type specified is unknown, it will return an empty list. + * Note, that the directories are assured to exist beside the save + * location, which may not exist, but is returned anyway. + */ + QStringList resourceDirs(const char *type) const; + + /** + * This function will return a list of all the types that KStandardDirs + * supports. + * + * @return All types that KDE supports + */ + QStringList allTypes() const; + + /** + * Finds a location to save files into for the given type + * in the user's home directory. + * + * @param type The type of location to return. + * @param suffix A subdirectory name. + * Makes it easier for you to create subdirectories. + * You can't pass filenames here, you _have_ to pass + * directory names only and add possible filename in + * that directory yourself. A directory name always has a + * trailing slash ('/'). + * @param create If set, saveLocation() will create the directories + * needed (including those given by @p suffix). + * + * @return A path where resources of the specified type should be + * saved, or QString::null if the resource type is unknown. + */ + QString saveLocation(const char *type, + const QString& suffix = QString::null, + bool create = true) const; + + /** + * Converts an absolute path to a path relative to a certain + * resource. + * + * If "abs = ::locate(resource, rel)" + * then "rel = relativeLocation(resource, abs)" and vice versa. + * + * @param type The type of resource. + * + * @param absPath An absolute path to make relative. + * + * @return A relative path relative to resource @p type that + * will find @p absPath. If no such relative path exists, absPath + * will be returned unchanged. + */ + QString relativeLocation(const char *type, const QString &absPath); + + /** + * Recursively creates still-missing directories in the given path. + * + * The resulting permissions will depend on the current umask setting. + * permission = mode & ~umask. + * + * @param dir Absolute path of the directory to be made. + * @param mode Directory permissions. + * @return true if successful, false otherwise + */ + static bool makeDir(const QString& dir, int mode = 0755); + + /** + * This returns a default relative path for the standard KDE + * resource types. Below is a list of them so you get an idea + * of what this is all about. + * + * @li data - share/apps + * @li html - share/doc/HTML + * @li icon - share/icon + * @li config - share/config + * @li pixmap - share/pixmaps + * @li apps - share/applnk + * @li sound - share/sounds + * @li locale - share/locale + * @li services - share/services + * @li servicetypes - share/servicetypes + * @li mime - share/mimelnk + * @li wallpaper - share/wallpapers + * @li templates - share/templates + * @li exe - bin + * @li lib - lib + * + * @returns Static default for the specified resource. You + * should probably be using locate() or locateLocal() + * instead. + * @see locate() + * @see locateLocal() + */ + static QString kde_default(const char *type); + + /** + * @internal (for use by sycoca only) + */ + QString kfsstnd_prefixes(); + + /** + * Returns the toplevel directory in which KStandardDirs + * will store things. Most likely $HOME/.kde + * Don't use this function if you can use locateLocal + * @return the toplevel directory + */ + QString localkdedir() const; + + /** + * @return $XDG_DATA_HOME + * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html + */ + QString localxdgdatadir() const; + + /** + * @return $XDG_CONFIG_HOME + * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html + */ + QString localxdgconfdir() const; + + /** + * Checks for existence and accessability. + * Faster than creating a QFileInfo first. + * @param fullPath the path to check + * @return true if the directory exists + */ + static bool exists(const QString &fullPath); + + /** + * Expands all symbolic links and resolves references to + * '/./', '/../' and extra '/' characters in @p dirname + * and returns the canonicalized absolute pathname. + * The resulting path will have no symbolic link, '/./' + * or '/../' components. + * @since 3.1 + */ + static QString realPath(const QString &dirname); + + static void setAppDir( const QString & ); + static QString appDir(); + + private: + + QStringList prefixes; + + // Directory dictionaries + QDict<QStringList> absolutes; + QDict<QStringList> relatives; + + mutable QDict<QStringList> dircache; + mutable QDict<QString> savelocations; + + // Disallow assignment and copy-construction + KStandardDirs( const KStandardDirs& ); + KStandardDirs& operator= ( const KStandardDirs& ); + + bool addedCustoms; + + class KStandardDirsPrivate; + KStandardDirsPrivate *d; +//US + static QString mAppDir; + + void checkConfig() const; + void applyDataRestrictions(const QString &) const; +//US void createSpecialResource(const char*); +}; + +/** + * \addtogroup locates Locate Functions + * @{ + * On The Usage Of 'locate' and 'locateLocal' + * + * Typical KDE applications use resource files in one out of + * three ways: + * + * 1) A resource file is read but is never written. A system + * default is supplied but the user can override this + * default in his local .kde directory: + * + * \code + * // Code example + * myFile = locate("appdata", "groups.lst"); + * myData = myReadGroups(myFile); // myFile may be null + * \endcode + * + * 2) A resource file is read and written. If the user has no + * local version of the file the system default is used. + * The resource file is always written to the users local + * .kde directory. + * + * \code + * // Code example + * myFile = locate("appdata", "groups.lst") + * myData = myReadGroups(myFile); + * ... + * doSomething(myData); + * ... + * myFile = locateLocal("appdata", "groups.lst"); + * myWriteGroups(myFile, myData); + * \endcode + * + * 3) A resource file is read and written. No system default + * is used if the user has no local version of the file. + * The resource file is always written to the users local + * .kde directory. + * + * \code + * // Code example + * myFile = locateLocal("appdata", "groups.lst"); + * myData = myReadGroups(myFile); + * ... + * doSomething(myData); + * ... + * myFile = locateLocal("appdata", "groups.lst"); + * myWriteGroups(myFile, myData); + * \endcode + **/ + +/*! + * \relates KStandardDirs + * This function is just for convenience. It simply calls + *instance->dirs()->\link KStandardDirs::findResource() findResource\endlink(type, filename). + **/ +QString locate( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance()*/ ); + +/*! + * \relates KStandardDirs + * This function is much like locate. However it returns a + * filename suitable for writing to. No check is made if the + * specified filename actually exists. Missing directories + * are created. If filename is only a directory, without a + * specific file, filename must have a trailing slash. + * + **/ +QString locateLocal( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance() */ ); + +/*! + * \relates KStandardDirs + * This function is much like locate. No check is made if the + * specified filename actually exists. Missing directories + * are created if @p createDir is true. If filename is only + * a directory, without a specific file, + * filename must have a trailing slash. + * + **/ +QString locateLocal( const char *type, const QString& filename, bool createDir /*US , const KInstance* instance = KGlobal::instance() */); + +/*! @} */ + +#endif // SSK_KSTDDIRS_H diff --git a/microkde/kdecore/kstringhandler.cpp b/microkde/kdecore/kstringhandler.cpp new file mode 100644 index 0000000..b737e97 --- a/dev/null +++ b/microkde/kdecore/kstringhandler.cpp @@ -0,0 +1,650 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Ian Zepp (icszepp@islc.net) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* AIX needs strings.h for str*casecmp(), and our config.h loads it on AIX + So we don't need to include strings.h explicitly */ + +//US #include "config.h" + +#include "kstringhandler.h" +/*US +QString KStringHandler::word( const QString &text , uint pos ) +{ + QStringList list = QStringList::split( " ", text , true ); + + if ( pos < list.count() ) + return list[ pos ]; + + return ""; +} + +QString KStringHandler::word( const QString &text , const char *range ) +{ + // Format in: START:END + // Note index starts a 0 (zero) + // + // 0: first word to end + // 1:3 second to fourth words + QStringList list = QStringList::split( " ", text , true ); + QString tmp = ""; + QString r = range; + + if ( text.isEmpty() ) + return tmp; + + // do stuff here + QRegExp reg; + + int at = 0; + int pos = 0; + int cnt = 0; + + if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 ) + { + at = r.find(":"); + pos = atoi( r.left(at).ascii() ); + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp(":+[0-9]+")) != -1 ) + { + at = r.find(":"); + pos = 0; + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp("[0-9]+:+")) != -1 ) + { + at = r.find(":"); + pos = atoi( r.left(at).ascii() ); + cnt = list.count(); // zero index + } + else if ( r.find(QRegExp("[0-9]+")) != -1 ) + { + pos = atoi( r.ascii() ); + cnt = pos; + } + else + { + return tmp; // not found/implemented + } + + // + // Extract words + // + int wordsToExtract = cnt-pos+1; + QStringList::Iterator it = list.at( pos); + + while ( (it != list.end()) && (wordsToExtract-- > 0)) + { + tmp += *it; + tmp += " "; + it++; + } + + return tmp.stripWhiteSpace(); +} + +// +// Insertion and removal routines +// +QString KStringHandler::insword( const QString &text , const QString &word , uint pos ) +{ + if ( text.isEmpty() ) + return word; + + if ( word.isEmpty() ) + return text; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + if ( pos >= list.count() ) + list.append( word ); + else + list.insert( list.at(pos) , word ); + + // Rejoin + return list.join( " " ); +} + +QString KStringHandler::setword( const QString &text , const QString &word , uint pos ) +{ + if ( text.isEmpty() ) + return word; + + if ( word.isEmpty() ) + return text; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + if ( pos >= list.count() ) + list.append( word ); + else + { + list.insert( list.remove( list.at(pos) ) , word ); + } + + // Rejoin + return list.join( " " ); +} + +QString KStringHandler::remrange( const QString &text , const char *range ) +{ + // Format in: START:END + // Note index starts a 0 (zero) + // + // 0: first word to end + // 1:3 second to fourth words + QStringList list = QStringList::split( " ", text , true ); + QString tmp = ""; + QString r = range; + + if ( text.isEmpty() ) + return tmp; + + // do stuff here + QRegExp reg; + + int at = 0; + int pos = 0; + int cnt = 0; + + if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 ) + { + at = r.find(':'); + pos = atoi( r.left(at).ascii() ); + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp(":+[0-9]+")) != -1 ) + { + at = r.find(':'); + pos = 0; + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp("[0-9]+:+")) != -1 ) + { + at = r.find(':'); + pos = atoi( r.left(at).ascii() ); + cnt = list.count(); // zero index + } + else if ( r.find(QRegExp("[0-9]+")) != -1 ) + { + pos = atoi( r.ascii() ); + cnt = pos; + } + else + { + return text; // not found/implemented + } + + // + // Remove that range of words + // + int wordsToDelete = cnt-pos+1; + QStringList::Iterator it = list.at( pos); + + while ( (it != list.end()) && (wordsToDelete-- > 0)) + it = list.remove( it ); + + return list.join( " " ); +} + +QString KStringHandler::remword( const QString &text , uint pos ) +{ + QString tmp = ""; + + if ( text.isEmpty() ) + return tmp; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + if ( pos < list.count() ) + list.remove( list.at( pos ) ); + + // Rejoin + return list.join( " " ); +} + +QString KStringHandler::remword( const QString &text , const QString &word ) +{ + QString tmp = ""; + + if ( text.isEmpty() ) + return tmp; + + if ( word.isEmpty() ) + return text; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + QStringList::Iterator it = list.find(word); + + if (it != list.end()) + list.remove( it ); + + // Rejoin + return list.join( " " ); +} + +// +// Capitalization routines +// +QString KStringHandler::capwords( const QString &text ) +{ + QString tmp = ""; + + if ( text.isEmpty() ) + return tmp; + + QStringList list = QStringList::split( " ", text, true ); + + return capwords( QStringList::split( " ", text, true )).join( " " ); +} + +QStringList KStringHandler::capwords( const QStringList &list ) +{ + QStringList tmp; + QString word; + + if ( list.count() == 0 ) + return tmp; + + for ( QStringList::ConstIterator it= list.begin(); + it != list.end(); + it++) + { + word = *it; + word = word.left(1).upper() + word.remove(0,1); + + tmp.append( word ); // blank list to start with + } + + return tmp; +} + +// +// Reverse routines +// +QString KStringHandler::reverse( const QString &text ) +{ + QString tmp; + + if ( text.isEmpty() ) + return tmp; + + QStringList list; + list = QStringList::split( " ", text, true ); + list = reverse( list ); + + return list.join( " " ); +} + +QStringList KStringHandler::reverse( const QStringList &list ) +{ + QStringList tmp; + + if ( list.count() == 0 ) + return tmp; + + for ( QStringList::ConstIterator it= list.begin(); + it != list.end(); + it++) + tmp.prepend( *it ); + + return tmp; +} + +// +// Left, Right, Center justification +// +QString KStringHandler::ljust( const QString &text , uint width ) +{ + QString tmp = text; + tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces + + if ( tmp.length() >= width ) + return tmp; + + for ( uint pos = tmp.length() ; pos < width ; pos++ ) + tmp.append(" "); + + return tmp; +} + +QString KStringHandler::rjust( const QString &text , uint width ) +{ + QString tmp = text; + tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces + + if ( tmp.length() >= width ) + return tmp; + + for ( uint pos = tmp.length() ; pos < width ; pos++ ) + tmp.prepend(" "); + + return tmp; +} + +QString KStringHandler::center( const QString &text , uint width ) +{ + // Center is slightly different, in that it will add + // spaces to the RIGHT side (left-justified) before + // it adds a space to the LEFT side. + + QString tmp = text; + tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces + + if ( tmp.length() >= width ) + return tmp; + + bool left = false; // start at right side. + + for ( uint pos = tmp.length() ; pos < width ; pos++ ) + { + if ( left ) + tmp.prepend(" "); + else + tmp.append(" "); + + // Reverse bool + left = !left; + } + + return tmp; +} + +QString KStringHandler::lsqueeze( const QString & str, uint maxlen ) +{ + if (str.length() > maxlen) { + int part = maxlen-3; + return QString("..." + str.right(part)); + } + else return str; +} + +QString KStringHandler::csqueeze( const QString & str, uint maxlen ) +{ + if (str.length() > maxlen && maxlen > 3) { + int part = (maxlen-3)/2; + return QString(str.left(part) + "..." + str.right(part)); + } + else return str; +} + +QString KStringHandler::rsqueeze( const QString & str, uint maxlen ) +{ + if (str.length() > maxlen) { + int part = maxlen-3; + return QString(str.left(part) + "..."); + } + else return str; +} + +QString KStringHandler::lEmSqueeze(const QString &name, const QFontMetrics& fontMetrics, uint maxlen) +{ + return lPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); +} + +static inline int emSqueezeLimit(int delta, int min, int max) +{ + if (delta < min) return min; + if (delta > max) return max; + return delta; +} + +QString KStringHandler::lPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels) +{ + uint nameWidth = fontMetrics.width(name); + + if (maxPixels < nameWidth) + { + QString tmp = name; + const uint em = fontMetrics.maxWidth(); + maxPixels -= fontMetrics.width("..."); + + while (maxPixels < nameWidth && !tmp.isEmpty()) + { + int delta = (nameWidth - maxPixels) / em; + delta = emSqueezeLimit(delta, 1, delta); // no max + + tmp.remove(0, delta); + nameWidth = fontMetrics.width(tmp); + } + + return ("..." + tmp); + } + + return name; +} + +QString KStringHandler::cEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen) +{ + return cPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); +} + +QString KStringHandler::cPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels) +{ + uint nameWidth = fontMetrics.width(name); + + if (maxPixels < nameWidth) + { + QString tmp = name; + const uint em = fontMetrics.maxWidth(); + maxPixels -= fontMetrics.width("..."); + + while (maxPixels < nameWidth && !tmp.isEmpty()) + { + int length = tmp.length(); + int delta = (nameWidth - maxPixels) / em; + delta = emSqueezeLimit(delta, 1, length) ; + + tmp.remove((length / 2) - (delta / 2), delta); + nameWidth = fontMetrics.width(tmp); + } + + return tmp.insert((tmp.length() + 1) / 2, "..."); + } + + return name; +} + +QString KStringHandler::rEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen) +{ + return rPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); +} + +QString KStringHandler::rPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels) +{ + uint nameWidth = fontMetrics.width(name); + + if (maxPixels < nameWidth) + { + QString tmp = name; + const uint em = fontMetrics.maxWidth(); + maxPixels -= fontMetrics.width("..."); + + while (maxPixels < nameWidth && !tmp.isEmpty()) + { + int length = tmp.length(); + int delta = (nameWidth - maxPixels) / em; + delta = emSqueezeLimit(delta, 1, length) ; + + tmp.remove(length - delta, delta); + nameWidth = fontMetrics.width(tmp); + } + + return (tmp + "..."); + } + + return name; +} + +///// File name patterns (like *.txt) + +bool KStringHandler::matchFileName( const QString& filename, const QString& pattern ) +{ + int len = filename.length(); + int pattern_len = pattern.length(); + + if (!pattern_len) + return false; + + // Patterns like "Makefile*" + if ( pattern[ pattern_len - 1 ] == '*' && len + 1 >= pattern_len ) { + const QChar *c1 = pattern.unicode(); + const QChar *c2 = filename.unicode(); + int cnt = 1; + while ( cnt < pattern_len && *c1++ == *c2++ ) + ++cnt; + return cnt == pattern_len; + } + + // Patterns like "*~", "*.extension" + if ( pattern[ 0 ] == '*' && len + 1 >= pattern_len ) + { + const QChar *c1 = pattern.unicode() + pattern_len - 1; + const QChar *c2 = filename.unicode() + len - 1; + int cnt = 1; + while ( cnt < pattern_len && *c1-- == *c2-- ) + ++cnt; + return cnt == pattern_len; + } + + // Patterns like "Makefile" + return ( filename == pattern ); +} + + QStringList +KStringHandler::perlSplit(const QString & sep, const QString & s, uint max) +{ + bool ignoreMax = 0 == max; + + QStringList l; + + int searchStart = 0; + + int tokenStart = s.find(sep, searchStart); + + while (-1 != tokenStart && (ignoreMax || l.count() < max - 1)) + { + if (!s.mid(searchStart, tokenStart - searchStart).isEmpty()) + l << s.mid(searchStart, tokenStart - searchStart); + + searchStart = tokenStart + sep.length(); + tokenStart = s.find(sep, searchStart); + } + + if (!s.mid(searchStart, s.length() - searchStart).isEmpty()) + l << s.mid(searchStart, s.length() - searchStart); + + return l; +} + + QStringList +KStringHandler::perlSplit(const QChar & sep, const QString & s, uint max) +{ + bool ignoreMax = 0 == max; + + QStringList l; + + int searchStart = 0; + + int tokenStart = s.find(sep, searchStart); + + while (-1 != tokenStart && (ignoreMax || l.count() < max - 1)) + { + if (!s.mid(searchStart, tokenStart - searchStart).isEmpty()) + l << s.mid(searchStart, tokenStart - searchStart); + + searchStart = tokenStart + 1; + tokenStart = s.find(sep, searchStart); + } + + if (!s.mid(searchStart, s.length() - searchStart).isEmpty()) + l << s.mid(searchStart, s.length() - searchStart); + + return l; +} + + QStringList +KStringHandler::perlSplit(const QRegExp & sep, const QString & s, uint max) +{ + bool ignoreMax = 0 == max; + + QStringList l; + + int searchStart = 0; + int tokenStart = sep.search(s, searchStart); + int len = sep.matchedLength(); + + while (-1 != tokenStart && (ignoreMax || l.count() < max - 1)) + { + if (!s.mid(searchStart, tokenStart - searchStart).isEmpty()) + l << s.mid(searchStart, tokenStart - searchStart); + + searchStart = tokenStart + len; + tokenStart = sep.search(s, searchStart); + len = sep.matchedLength(); + } + + if (!s.mid(searchStart, s.length() - searchStart).isEmpty()) + l << s.mid(searchStart, s.length() - searchStart); + + return l; +} +US end */ + +/*US + QString +KStringHandler::tagURLs( const QString& text ) +{ + QRegExp urlEx("(www\\.(?!\\.)|(f|ht)tp(|s)://)[\\d\\w\\./,:_~\\?=&;#@\\-\\+\\%]+[\\d\\w/]"); + + QString richText( text ); + int urlPos = 0, urlLen; + while ((urlPos = urlEx.search(richText, urlPos)) >= 0) + { + urlLen = urlEx.matchedLength(); + QString href = richText.mid( urlPos, urlLen ); + // Qt doesn't support (?<=pattern) so we do it here + if((urlPos > 0) && richText[urlPos-1].isLetterOrNumber()){ + urlPos++; + continue; + } + // Don't use QString::arg since %01, %20, etc could be in the string + QString anchor = "<a href=\"" + href + "\">" + href + "</a>"; + richText.replace( urlPos, urlLen, anchor ); + + + urlPos += anchor.length(); + } + return richText; +} +*/ +QString KStringHandler::obscure( const QString &str ) +{ + QString result; + for ( uint i = 0; i < str.length(); ++i ) + result += ( str.at( i ).unicode() < 0x20 ) ? str.at( i ) : + QChar( 0x1001F - str.at( i ).unicode() ); + + return result; +} diff --git a/microkde/kdecore/kstringhandler.h b/microkde/kdecore/kstringhandler.h new file mode 100644 index 0000000..d07b1e2 --- a/dev/null +++ b/microkde/kdecore/kstringhandler.h @@ -0,0 +1,417 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Ian Zepp (icszepp@islc.net) + Copyright (C) 2000 Rik Hemsley (rikkus) <rik@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSTRINGHANDLER_H +#define KSTRINGHANDLER_H + +#include <stdlib.h> // for atoi() +#include <qstring.h> +#include <qstringlist.h> +#include <qregexp.h> // for the word ranges +#include <qfontmetrics.h> + +/** + * This class contains utility functions for handling strings. + * + * This class is @em not a substitute for the @ref QString class. What + * I tried to do with this class is provide an easy way to + * cut/slice/splice words inside sentences in whatever order desired. + * While the main focus of this class are words (ie characters + * separated by spaces/tabs), the two core functions here (@ref split() + * and @ref join() ) will function given any char to use as a separator. + * This will make it easy to redefine what a 'word' means in the + * future if needed. + * + * I freely stole some of the function names from python. I also think + * some of these were influenced by mIRC (yes, believe it if you will, I + * used to write a LOT of scripts in mIRC). + * + * The ranges are a fairly powerful way of getting/stripping words from + * a string. These ranges function, for the large part, as they would in + * python. See the @ref word(const QString&, int) and @ref remword(const QString&, int) functions for more detail. + * + * This class contains no data members of it own. All strings are cut + * on the fly and returned as new qstrings/qstringlists. + * + * Quick example on how to use: + * + * <pre> + * KStringHandler kstr; + * QString line = "This is a test of the strings"; + * + * cout << "1> " << kstr.word( line , "4:" ) << "\n"; + * cout << "2> " << kstr.remrange( line , "2:5" ) << "\n"; + * cout << "2> " << kstr.reverse( line ) << "\n"; + * cout << "2> " << kstr.center( kstr.word( line , 4 ) , 15 ) << "\n"; + * </pre> + * + * and so forth. + * + * @short Class for manipulating words and sentences in strings + * @author Ian Zepp <icszepp@islc.net> + */ +class KStringHandler +{ +public: + /** Returns the nth word in the string if found + * Returns a EMPTY (not null) string otherwise. + * Note that the FIRST index is 0. + * @param text the string to search for the words + * @param pos the position of the word to search + * @return the word, or an empty string if not found + */ +//US static QString word( const QString &text , uint pos ); + + /** Returns a range of words from that string. + * Ie: + * @li "0" returns the very first word + * @li "0:" returns the first to the last word + * @li "0:3" returns the first to fourth words + * @li ":3" returns everything up to the fourth word + * + * If you grok python, you're set. + * @param text the string to search for the words + * @param range the words to return (see description) + * @return the words, or an empty string if not found + */ +//US static QString word( const QString &text , const char *range ); + + /** Inserts a word into the string, and returns + * a new string with the word included. the first + * index is zero (0). If there are not @p pos words in the original + * string, the new word will be appended to the end. + * @param text the original text + * @param word the word to insert + * @param pos the position (in words) for the new word + * @return the resulting string + */ +//US static QString insword( const QString &text , const QString &word , uint pos ); + + /** Replaces a word in the string, and returns + * a new string with the word included. the first + * index is zero (0). If there are not @p pos words in the original + * string, the new word will be appended to the end. + * @param text the original text + * @param word the word to insert + * @param pos the position (in words) for the new word + * @return the resulting string + */ +//US static QString setword( const QString &text , const QString &word , uint pos ); + + /** Removes a word or ranges of words from the string, + * and returns a new string. The ranges definitions + * follow the definitions for the word() function. + * + * @li "0" removes the very first word + * @li "0:" removes the first the the last word + * @li "0:3" removes the first to fourth words + * @li ":3" removes everything up to the fourth word + * @param text the original text + * @param range the words to remove (see description) + * @return the resulting string + */ +//US static QString remrange( const QString &text , const char *range ); + + + /** Removes a word at the given index, and returns a + * new string. The first index is zero (0). + * @param text the original text + * @param pos the position (in words) of thw word to delete + * @return the resulting string + */ +//US static QString remword( const QString &text , uint pos ); + + /** Removes a matching word from the string, and returns + * a new string. Note that only ONE match is removed. + * @param text the original text + * @param word the word to remove + * @return the resulting string + */ +//US static QString remword( const QString &text , const QString &word ); + + /** Capitalizes each word in the string + * "hello there" becomes "Hello There" (string) + * @param text the text to capitalize + * @return the resulting string + */ +//US static QString capwords( const QString &text ); + + /** Capitalizes each word in the list + * [hello, there] becomes [Hello, There] (list) + * @param list the list to capitalize + * @return the resulting list + */ +//US static QStringList capwords( const QStringList &list ); + + /** Reverses the order of the words in a string + * "hello there" becomes "there hello" (string) + * @param text the text to reverse + * @return the resulting string + */ +//US static QString reverse( const QString &text ); + + /** Reverses the order of the words in a list + * [hello, there] becomes [there, hello] (list) + * @param list the list to reverse + * @return the resulting list + */ +//US static QStringList reverse( const QStringList &list ); + + /** Left-justifies a string and returns a string at least 'width' characters + * wide. + * If the string is longer than the @p width, the original + * string is returned. It is never truncated. + * @param text the text to justify + * @param width the desired width of the new string + * @return the resulting string + */ +//US static QString ljust( const QString &text , uint width ); + + /** Right-justifies a string and returns a string at least 'width' characters + * wide. + * If the string is longer than the @p width, the original + * string is returned. It is never truncated. + * @param text the text to justify + * @param width the desired width of the new string + * @return the resulting string + */ +//US static QString rjust( const QString &text , uint width ); + + /** Centers a string and returns a string at least 'width' characters + * wide. + * If the string is longer than the @p width, the original + * string is returned. It is never truncated. + * @param text the text to justify + * @param width the desired width of the new string + * @return the resulting string + */ +//US static QString center( const QString &text , uint width ); + + /** Substitute characters at the beginning of a string by "...". + * @param str is the string to modify + * @param maxlen is the maximum length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + */ +//US static QString lsqueeze( const QString & str, uint maxlen = 40 ); + + /** Substitute characters at the beginning of a string by "...". Similar to + * method above, except that it truncates based on pixel width rather than + * the number of characters + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxlen is the maximum length in ems the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString lEmSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxlen = 30 ); + + /** Substitute characters at the beginning of a string by "...". Similar to + * method above, except that maxlen is the width in pixels to truncate to + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxPixels is the maximum pixel length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString lPixelSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxPixels ); + + /** Substitute characters at the middle of a string by "...". + * @param str is the string to modify + * @param maxlen is the maximum length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + */ +//US static QString csqueeze( const QString & str, uint maxlen = 40 ); + + /** Substitute characters in the middle of a string by "...". Similar to + * method above, except that it truncates based on pixel width rather than + * the number of characters + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxlen is the maximum length in ems the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString cEmSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxlen = 30 ); + + /** Substitute characters in the middle of a string by "...". Similar to + * method above, except that maxlen is the width in pixels to truncate to + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxPixels is the maximum pixel length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString cPixelSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxPixels ); + + /** Substitute characters at the end of a string by "...". + * @param str is the string to modify + * @param maxlen is the maximum length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + */ + static QString rsqueeze( const QString & str, uint maxlen = 40 ); + + /** Substitute characters at the end of a string by "...". Similar to + * method above, except that it truncates based on pixel width rather than + * the number of characters + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxlen is the maximum length in ems the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString rEmSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxlen = 30 ); + + /** Substitute characters at the end of a string by "...". Similar to + * method above, except that maxlen is the width in pixels to truncate to + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxPixels is the maximum pixel length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString rPixelSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxPixels ); + + /** + * Match a filename. + * @param filename is the real decoded filename (or dirname + * without trailing '/'). + * @param pattern is a pattern like *.txt, *.tar.gz, Makefile.*, etc. + * Patterns with two asterisks like "*.*pk" are not supported. + * @return true if the given filename matches the given pattern + */ +//US static bool matchFileName( const QString& filename, const QString& pattern ); + + /** + * Split a QString into a QStringList in a similar fashion to the static + * QStringList function in Qt, except you can specify a maximum number + * of tokens. If max is specified (!= 0) then only that number of tokens + * will be extracted. The final token will be the remainder of the string. + * + * Example: + * <pre> + * perlSplit("__", "some__string__for__you__here", 4) + * QStringList contains: "some", "string", "for", "you__here" + * </pre> + * + * @param sep is the string to use to delimit s. + * @param s is the input string + * @param max is the maximum number of extractions to perform, or 0. + * @return A QStringList containing tokens extracted from s. + */ +//US static QStringList perlSplit +//US (const QString & sep, const QString & s, uint max = 0); + + /** + * Split a QString into a QStringList in a similar fashion to the static + * QStringList function in Qt, except you can specify a maximum number + * of tokens. If max is specified (!= 0) then only that number of tokens + * will be extracted. The final token will be the remainder of the string. + * + * Example: + * <pre> + * perlSplit(' ', "kparts reaches the parts other parts can't", 3) + * QStringList contains: "kparts", "reaches", "the parts other parts can't" + * </pre> + * + * @param sep is the character to use to delimit s. + * @param s is the input string + * @param max is the maximum number of extractions to perform, or 0. + * @return A QStringList containing tokens extracted from s. + */ +//US static QStringList perlSplit +//US (const QChar & sep, const QString & s, uint max = 0); + + /** + * Split a QString into a QStringList in a similar fashion to the static + * QStringList function in Qt, except you can specify a maximum number + * of tokens. If max is specified (!= 0) then only that number of tokens + * will be extracted. The final token will be the remainder of the string. + * + * Example: + * <pre> + * perlSplit(QRegExp("[! ]", "Split me up ! I'm bored ! OK ?", 3) + * QStringList contains: "Split", "me", "up ! I'm bored, OK ?" + * </pre> + * + * @param sep is the regular expression to use to delimit s. + * @param s is the input string + * @param max is the maximum number of extractions to perform, or 0. + * @return A QStringList containing tokens extracted from s. + */ +//US static QStringList perlSplit +//US (const QRegExp & sep, const QString & s, uint max = 0); + + /** + * This method auto-detects URLs in strings, and adds HTML markup to them + * so that richtext or HTML-enabled widgets (such as KActiveLabel) + * will display the URL correctly. + * @param text the string which may contain URLs + * @return the resulting text + * @since 3.1 + */ +//US static QString tagURLs( const QString& text ); + + /** + Obscure string by using a simple symmetric encryption. Applying the + function to a string obscured by this function will result in the original + string. + + The function can be used to obscure passwords stored to configuration + files. Note that this won't give you any more security than preventing + that the password is directly copied and pasted. + + @param str string to be obscured + @return obscured string + @since 3.2 + */ + static QString obscure( const QString &str ); + +#ifdef KDE_NO_COMPAT +private: +#endif + /** + * @deprecated Use @see matchFileName () instead. + */ +/*US static bool matchFilename( const QString& filename, const QString& pattern ) + { + return matchFileName (filename, pattern); + }; +*/ +}; +#endif diff --git a/microkde/kdemacros.h b/microkde/kdemacros.h new file mode 100644 index 0000000..698a15a --- a/dev/null +++ b/microkde/kdemacros.h @@ -0,0 +1,105 @@ +/* This file is part of the KDE libraries + Copyright (c) 2002-2003 KDE Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _KDE_MACROS_H_ +#define _KDE_MACROS_H_ + +/** + * The KDE_NO_EXPORT macro marks the symbol of the given variable + * to be hidden. A hidden symbol is stripped during the linking step, + * so it can't be used from outside the resulting library, which is similiar + * to static. However, static limits the visibility to the current + * compilation unit. hidden symbols can still be used in multiple compilation + * units. + * + * \code + * int KDE_NO_EXPORT foo; + * int KDE_EXPORT bar; + * \end + */ + +#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 > 2) +#define KDE_NO_EXPORT __attribute__ ((visibility("hidden"))) +#define KDE_EXPORT __attribute__ ((visibility("visible"))) +#else +#define KDE_NO_EXPORT +#define KDE_EXPORT +#endif + +/** + * The KDE_PACKED can be used to hint the compiler that a particular + * structure or class should not contain unnecessary paddings. + */ + +#ifdef __GNUC__ +#define KDE_PACKED __attribute__((__packed__)) +#else +#define KDE_PACKED +#endif + +/** + * The KDE_DEPRECATED macro can be used to trigger compile-time warnings + * with gcc >= 3.2 when deprecated functions are used. + * + * For non-inline functions, the macro gets inserted at the very end of the + * function declaration, right before the semicolon: + * + * \code + * DeprecatedConstructor() KDE_DEPRECATED; + * void deprecatedFunctionA() KDE_DEPRECATED; + * int deprecatedFunctionB() const KDE_DEPRECATED; + * \endcode + * + * Functions which are implemented inline are handled differently: for them, + * the KDE_DEPRECATED macro is inserted at the front, right before the return + * type, but after "static" or "virtual": + * + * \code + * KDE_DEPRECATED void deprecatedInlineFunctionA() { .. } + * virtual KDE_DEPRECATED int deprecatedInlineFunctionB() { .. } + * static KDE_DEPRECATED bool deprecatedInlineFunctionC() { .. } + * \end + * + * You can also mark whole structs or classes as deprecated, by inserting the + * KDE_DEPRECATED macro after the struct/class keyword, but before the + * name of the struct/class: + * + * \code + * class KDE_DEPRECATED DeprecatedClass { }; + * struct KDE_DEPRECATED DeprecatedStruct { }; + * \endcode + * + * \note + * It does not make much sense to use the KDE_DEPRECATED keyword for a Qt signal + * or a slot; this is because signals and slots always get referenced by the + * code generated by moc. + * + * \par + * Also note that it is not possible to use KDE_DEPRECATED for classes which + * use the k_dcop keyword (to indicate a DCOP interface declaration); this is + * because the dcopidl program would choke on the unexpected declaration + * syntax. + */ +#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2) +# define KDE_DEPRECATED __attribute__ ((deprecated)) +#else +# define KDE_DEPRECATED +#endif + +#endif // _KDE_MACROS_H_ diff --git a/microkde/kdeui/kaction.cpp b/microkde/kdeui/kaction.cpp new file mode 100644 index 0000000..77d36a5 --- a/dev/null +++ b/microkde/kdeui/kaction.cpp @@ -0,0 +1,1215 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + (C) 2002 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kaction.h" + +#include <assert.h> + +#include <qtooltip.h> +//US#include <qwhatsthis.h> +//US#include <kaccel.h> +//US#include <kaccelbase.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kguiitem.h> +//US#include <kmainwindow.h> +//US#include <kmenubar.h> +//US#include <kpopupmenu.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> + +//US added this includefiles +#include <qmenubar.h> +#include <qtoolbar.h> +#include <qpopupmenu.h> +#include <qiconset.h> + +/** +* How it works. +* KActionCollection is an organizing container for KActions. +* KActionCollection keeps track of the information necessary to handle +* configuration and shortcuts. +* +* Focus Widget pointer: +* This is the widget which is the focus for action shortcuts. +* It is set either by passing a QWidget* to the KActionCollection constructor +* or by calling setWidget() if the widget wasn't known when the object was +* initially constructed (as in KXMLGUIClient and KParts::PartBase) +* +* Shortcuts: +* An action's shortcut will not not be connected unless a focus widget has +* been specified in KActionCollection. +* +* XML Filename: +* This is used to save user-modified settings back to the *ui.rc file. +* It is set by KXMLGUIFactory. +*/ + +int KAction::getToolButtonID() +{ + static int toolbutton_no = -2; + return toolbutton_no--; +} + +//--------------------------------------------------------------------- +// KAction::KActionPrivate +//--------------------------------------------------------------------- + +class KAction::KActionPrivate : public KGuiItem +{ +public: + KActionPrivate() : KGuiItem() + { + m_kaccel = 0; + m_configurable = true; + } + + KAccel *m_kaccel; + QValueList<KAccel*> m_kaccelList; + + QString m_groupText; + QString m_group; + + KShortcut m_cut; + KShortcut m_cutDefault; + + bool m_configurable; + + struct Container + { + Container() { m_container = 0; m_representative = 0; m_id = 0; } + Container( const Container& s ) { m_container = s.m_container; + m_id = s.m_id; m_representative = s.m_representative; } + QWidget* m_container; + int m_id; + QWidget* m_representative; + }; + + QValueList<Container> m_containers; +}; + +//--------------------------------------------------------------------- +// KAction +//--------------------------------------------------------------------- +KAction::KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); +} + +KAction::KAction( const QString& text, const QString& sIconName, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconName( sIconName ); +} + +KAction::KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconSet( pix ); +} +KAction::KAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( item.text(), cut, receiver, slot ); + if( item.hasIconSet() ) + setIcon( item.iconName() ); + setToolTip( item.toolTip() ); + setWhatsThis( item.whatsThis() ); +} + +// KDE 4: remove +KAction::KAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, 0, 0 ); +} +KAction::KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); +} +KAction::KAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, 0, 0 ); + setIconSet( pix ); +} + +KAction::KAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, 0, 0 ); + d->setIconName( pix ); +} + +KAction::KAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + setIconSet( pix ); +} + +KAction::KAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconName(pix); +} + +KAction::KAction( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + + initPrivate( QString::null, KShortcut(), 0, 0 ); +} +// KDE 4: remove end + +KAction::~KAction() +{ + kdDebug(129) << "KAction::~KAction( this = \"" << name() << "\" )" << endl; // -- ellis +#ifndef KDE_NO_COMPAT + if (d->m_kaccel) + unplugAccel(); +#endif + + // If actionCollection hasn't already been destructed, + if ( m_parentCollection ) { + m_parentCollection->take( this ); + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) +//US d->m_kaccelList[i]->remove( name() ); + qDebug("KAction::KAction~ ...1 has top be fixed"); + } + + // Do not call unplugAll from here, as tempting as it sounds. + // KAction is designed around the idea that you need to plug + // _and_ to unplug it "manually". Unplugging leads to an important + // slowdown when e.g. closing the window, in which case we simply + // want to destroy everything asap, not to remove actions one by one + // from the GUI. + + delete d; d = 0; +} + +void KAction::initPrivate( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot ) +{ + d = new KActionPrivate; + + d->m_cutDefault = cut; + +//US m_parentCollection = dynamic_cast<KActionCollection *>( parent() ); + m_parentCollection = (KActionCollection *)( parent() ); + kdDebug(129) << "KAction::initPrivate(): this = " << this << " name = \"" << name() << "\" cut = " << cut.toStringInternal() << " m_parentCollection = " << m_parentCollection << endl; + if ( m_parentCollection ) + m_parentCollection->insert( this ); + + if ( receiver && slot ) + connect( this, SIGNAL( activated() ), receiver, slot ); + + if( !cut.isNull() && qstrcmp( name(), "unnamed" ) == 0 ) + kdWarning(129) << "KAction::initPrivate(): trying to assign a shortcut (" << cut.toStringInternal() << ") to an unnamed action." << endl; + d->setText( text ); + initShortcut( cut ); + +} + +bool KAction::isPlugged() const +{ + return (containerCount() > 0) || d->m_kaccel; +} + +bool KAction::isPlugged( const QWidget *container ) const +{ + return findContainer( container ) > -1; +} + +bool KAction::isPlugged( const QWidget *container, int id ) const +{ + int i = findContainer( container ); + return ( i > -1 && itemId( i ) == id ); +} + +bool KAction::isPlugged( const QWidget *container, const QWidget *_representative ) const +{ + int i = findContainer( container ); + return ( i > -1 && representative( i ) == _representative ); +} + + +/* +Three actionCollection conditions: + 1) Scope is known on creation and KAccel object is created (e.g. KMainWindow) + 2) Scope is unknown and no KAccel object is available (e.g. KXMLGUIClient) + a) addClient() will be called on object + b) we just want to add the actions to another KXMLGUIClient object + +The question is how to do we incorporate #2b into the XMLGUI framework? + + +We have a KCommandHistory object with undo and redo actions in a passed actionCollection +We have a KoDoc object which holds a KCommandHistory object and the actionCollection +We have two KoView objects which both point to the same KoDoc object +Undo and Redo should be available in both KoView objects, and + calling the undo->setEnabled() should affect both KoViews + +When addClient is called, it needs to be able to find the undo and redo actions +When it calls plug() on them, they need to be inserted into the KAccel object of the appropriate KoView + +In this case, the actionCollection belongs to KoDoc and we need to let it know that its shortcuts +have the same scope as the KoView actionCollection + +KXMLGUIClient::addSubActionCollection + +Document: + create document actions + +View + create view actions + add document actionCollection as sub-collection + +A parentCollection is created +Scenario 1: parentCollection has a focus widget set (e.g. via KMainWindow) + A KAccel object is created in the parentCollection + A KAction is created with parent=parentCollection + The shortcut is inserted into this actionCollection + Scenario 1a: xml isn't used + done + Scenario 1b: KXMLGUIBuilder::addClient() called + setWidget is called -- ignore + shortcuts are set +Scenario 2: parentCollection has no focus widget (e.g., KParts) + A KAction is created with parent=parentCollection + Scenario 2a: xml isn't used + no shortcuts + Scenario 2b: KXMLGUIBuilder::addClient() called + setWidget is called + shortcuts are inserted into current KAccel + shortcuts are set in all other KAccels, if the action is present in the other KAccels +*/ + +/* +shortcut may be set: + - on construction + - on plug + - on reading XML + - on plugAccel (deprecated) + +On Construction: [via initShortcut()] + insert into KAccel of m_parentCollection, + if kaccel() && isAutoConnectShortcuts() exists + +On Plug: [via plug() -> plugShortcut()] + insert into KAccel of m_parentCollection, if exists and not already inserted into + +On Read XML: [via setShortcut()] + set in all current KAccels + insert into KAccel of m_parentCollection, if exists and not already inserted into +*/ + +KAccel* KAction::kaccelCurrent() +{ + if( m_parentCollection && m_parentCollection->builderKAccel() ) + return m_parentCollection->builderKAccel(); + else if( m_parentCollection && m_parentCollection->kaccel() ) + return m_parentCollection->kaccel(); + else + return 0L; +} + +// Only to be called from initPrivate() +bool KAction::initShortcut( const KShortcut& cut ) +{ + d->m_cut = cut; + + // Only insert action into KAccel if it has a valid name, + if( qstrcmp( name(), "unnamed" ) != 0 && + m_parentCollection && + m_parentCollection->isAutoConnectShortcuts() && + m_parentCollection->kaccel() ) + { + insertKAccel( m_parentCollection->kaccel() ); + return true; + } + return false; + } + +// Only to be called from plug() +void KAction::plugShortcut() +{ + KAccel* kaccel = kaccelCurrent(); + + //kdDebug(129) << "KAction::plugShortcut(): this = " << this << " kaccel() = " << (m_parentCollection ? m_parentCollection->kaccel() : 0) << endl; + if( kaccel && qstrcmp( name(), "unnamed" ) != 0 ) { + // Check if already plugged into current KAccel object + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + if( d->m_kaccelList[i] == kaccel ) + return; + } + + insertKAccel( kaccel ); + } +} + +bool KAction::setShortcut( const KShortcut& cut ) +{ + qDebug("KAction::setShortcut~ ...1 has top be fixed"); +/*US + bool bChanged = (d->m_cut != cut); + d->m_cut = cut; + + KAccel* kaccel = kaccelCurrent(); + bool bInsertRequired = true; + // Apply new shortcut to all existing KAccel objects + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + // Check whether shortcut has already been plugged into + // the current kaccel object. + if( d->m_kaccelList[i] == kaccel ) + bInsertRequired = false; + if( bChanged ) + updateKAccelShortcut( d->m_kaccelList[i] ); + } + + // Only insert action into KAccel if it has a valid name, + if( kaccel && bInsertRequired && qstrcmp( name(), "unnamed" ) ) + insertKAccel( kaccel ); + + if( bChanged ) { + // KDE 4: remove + if ( d->m_kaccel ) + d->m_kaccel->setShortcut( name(), cut ); + // KDE 4: remove end + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateShortcut( i ); + } +*/ + + return true; +} + +bool KAction::updateKAccelShortcut( KAccel* kaccel ) +{ + qDebug("KAction::updateKAccelShortcut~ ...1 has top be fixed"); + // Check if action is permitted +/*US + if (kapp && !kapp->authorizeKAction(name())) + return false; + + bool b = true; + + if ( !kaccel->actions().actionPtr( name() ) ) { + if(!d->m_cut.isNull() ) { + kdDebug(129) << "Inserting " << name() << ", " << d->text() << ", " << d->plainText() << endl; + b = kaccel->insert( name(), d->plainText(), QString::null, + d->m_cut, + this, SLOT(slotActivated()), + isShortcutConfigurable(), isEnabled() ); + } + } + else + b = kaccel->setShortcut( name(), d->m_cut ); + + return b; +*/ + return true; +} + +void KAction::insertKAccel( KAccel* kaccel ) +{ + qDebug("KAction::updateKAccelShortcut~ ...1 has top be fixed"); +/*US + //kdDebug(129) << "KAction::insertKAccel( " << kaccel << " ): this = " << this << endl; + if ( !kaccel->actions().actionPtr( name() ) ) { + if( updateKAccelShortcut( kaccel ) ) { + d->m_kaccelList.append( kaccel ); + connect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + } + } + else + kdWarning(129) << "KAction::insertKAccel( kaccel = " << kaccel << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis +*/ +} + +void KAction::removeKAccel( KAccel* kaccel ) +{ + qDebug("KAction::removeKAccel~ ...1 has top be fixed"); +/*US + //kdDebug(129) << "KAction::removeKAccel( " << i << " ): this = " << this << endl; + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + if( d->m_kaccelList[i] == kaccel ) { + kaccel->remove( name() ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + disconnect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + break; + } + } +*/ +} + +// KDE 4: remove +void KAction::setAccel( int keyQt ) +{ + setShortcut( KShortcut(keyQt) ); +} +// KDE 4: remove end + +void KAction::updateShortcut( int i ) +{ + int id = itemId( i ); + + QWidget* w = container( i ); + if ( w->inherits( "QPopupMenu" ) ) { + QPopupMenu* menu = static_cast<QPopupMenu*>(w); + updateShortcut( menu, id ); + } + else if ( w->inherits( "QMenuBar" ) ) +//US static_cast<QMenuBar*>(w)->setAccel( d->m_cut.keyCodeQt(), id ); +//US (QMenuBar*)(w)->setAccel( d->m_cut.keyCodeQt(), id ); + qDebug("KAction::updateShortcut( int i ) ...1 has top be fixed"); + +} + +void KAction::updateShortcut( QPopupMenu* menu, int id ) +{ +/*US + //kdDebug(129) << "KAction::updateShortcut(): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl; + // If the action has a KAccel object, + // show the string representation of its shortcut. + if ( d->m_kaccel || d->m_kaccelList.count() ) { + QString s = menu->text( id ); + int i = s.find( '\t' ); + if ( i >= 0 ) + s.replace( i+1, s.length()-i, d->m_cut.seq(0).toString() ); + else + s += "\t" + d->m_cut.seq(0).toString(); + + menu->changeItem( id, s ); + } + // Otherwise insert the shortcut itself into the popup menu. + else { + // This is a fall-hack in case the KAction is missing a proper parent collection. + // It should be removed eventually. --ellis + menu->setAccel( d->m_cut.keyCodeQt(), id ); + kdWarning(129) << "KAction::updateShortcut(): name = \"" << name() << "\", cut = " << d->m_cut.toStringInternal() << "; No KAccel, probably missing a parent collection." << endl; + } +*/ + qDebug("KAction::updateShortcut( QPopupMenu* menu, int id ) ...1 has top be fixed"); + +} + +const KShortcut& KAction::shortcut() const +{ + return d->m_cut; +} + +const KShortcut& KAction::shortcutDefault() const +{ + return d->m_cutDefault; +} + +QString KAction::shortcutText() const +{ + return d->m_cut.toStringInternal(); +} + +void KAction::setShortcutText( const QString& s ) +{ + setShortcut( KShortcut(s) ); +} + +int KAction::accel() const +{ + qDebug("KAction::accel() ...1 has top be fixed"); +//US return d->m_cut.keyCodeQt(); + return 0; +} + +void KAction::setGroup( const QString& grp ) +{ + d->m_group = grp; + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateGroup( i ); +} + +void KAction::updateGroup( int ) +{ + // DO SOMETHING +} + +QString KAction::group() const +{ + return d->m_group; +} + +bool KAction::isEnabled() const +{ + return d->isEnabled(); +} + +bool KAction::isShortcutConfigurable() const +{ + return d->m_configurable; +} + +void KAction::setToolTip( const QString& tt ) +{ + qDebug("KAction::setToolTip ...1 has top be fixed"); + d->setToolTip( tt ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateToolTip( i ); +} + +void KAction::updateToolTip( int i ) +{ + qDebug("KAction::updateToolTip ...1 has top be fixed"); + QWidget *w = container( i ); + + if ( w->inherits( "KToolBar" ) ) + QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() ); + else if ( w->inherits( "QToolBar" ) ) + QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() ); +} + +QString KAction::toolTip() const +{ + return d->toolTip(); +} + +int KAction::plug( QWidget *w, int index ) +{ + //kdDebug(129) << "KAction::plug( " << w << ", " << index << " )" << endl; + if (w == 0) { + kdWarning(129) << "KAction::plug called with 0 argument\n"; + return -1; + } + +#ifndef NDEBUG + KAccel* kaccel = kaccelCurrent(); + // If there is a shortcut, but no KAccel available + if( !d->m_cut.isNull() && kaccel == 0 ) { + kdWarning(129) << "KAction::plug(): has no KAccel object; this = " << this << " name = " << name() << " parentCollection = " << m_parentCollection << endl; // ellis +//US kdDebug(129) << kdBacktrace() << endl; + } +#endif + + // Check if action is permitted +//US if (kapp && !kapp->authorizeKAction(name())) +//US return -1; + + plugShortcut(); + + if ( w->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( w ); + int id; + // Don't insert shortcut into menu if it's already in a KAccel object. + //qDebug("KAction::plug warning: real shortcuts not available yet. "); +//US int keyQt = (d->m_kaccelList.count() || d->m_kaccel) ? 0 : d->m_cut.keyCodeQt(); + int keyQt = 0; + + if ( d->hasIcon() ) + { +/*US + KInstance *instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + id = menu->insertItem( d->iconSet( KIcon::Small, 0/*US , instance */), d->text(), this,//dsweet + SLOT( slotActivated() ), keyQt, + -1, index ); + } + else + id = menu->insertItem( d->text(), this, + SLOT( slotActivated() ), //dsweet + keyQt, -1, index ); + + // If the shortcut is already in a KAccel object, then + // we need to set the menu item's shortcut text. +/*US if ( d->m_kaccelList.count() || d->m_kaccel ) + updateShortcut( menu, id ); +*/ + // call setItemEnabled only if the item really should be disabled, + // because that method is slow and the item is per default enabled + if ( !d->isEnabled() ) + menu->setItemEnabled( id, false ); + + if ( !d->whatsThis().isEmpty() ) + menu->setWhatsThis( id, whatsThisWithIcon() ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( menu, this ); + + return d->m_containers.count() - 1; + } + else if ( w->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( w ); + + int id_ = getToolButtonID(); +/*US + KInstance *instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + if ( icon().isEmpty() && !iconSet().pixmap().isNull() ) // old code using QIconSet directly + { + bar->insertButton( iconSet().pixmap(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index ); + } + else + { + QString icon = d->iconName(); + if ( icon.isEmpty() ) + icon = "unknown"; + bar->insertButton( icon, id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index/*US, instance*/ ); + } + bar->getButton( id_ )->setName( QCString("toolbutton_")+name() ); + +//US if ( !d->whatsThis().isEmpty() ) +//US QWhatsThis::add( bar->getButton(id_), whatsThisWithIcon() ); + if ( !d->toolTip().isEmpty() ) + QToolTip::add( bar->getButton(id_), d->toolTip() ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( bar, this ); + + return containerCount() - 1; + + } + + return -1; +} + +void KAction::unplug( QWidget *w ) +{ + int i = findContainer( w ); + if ( i == -1 ) + return; + int id = itemId( i ); + + if ( w->inherits( "QPopupMenu" ) ) + { + QPopupMenu *menu = static_cast<QPopupMenu *>( w ); + menu->removeItem( id ); + } + else if ( w->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( w ); + bar->removeItemDelayed( id ); + } + else if ( w->inherits( "QMenuBar" ) ) + { + QMenuBar *bar = static_cast<QMenuBar *>( w ); + bar->removeItem( id ); + } + + removeContainer( i ); + + if ( m_parentCollection ) + m_parentCollection->disconnectHighlight( w, this ); +} + +void KAction::plugAccel(KAccel *kacc, bool configurable) +{ + qDebug("KAction::plugAccel ...1 has top be fixed"); +/*US + kdWarning(129) << "KAction::plugAccel(): call to deprecated action." << endl; + kdDebug(129) << kdBacktrace() << endl; + //kdDebug(129) << "KAction::plugAccel( kacc = " << kacc << " ): name \"" << name() << "\"" << endl; + if ( d->m_kaccel ) + unplugAccel(); + + // If the parent collection's accel ptr isn't set yet + //if ( m_parentCollection && !m_parentCollection->accel() ) + // m_parentCollection->setAccel( kacc ); + + // We can only plug this action into the given KAccel object + // if it does not already contain an action with the same name. + if ( !kacc->actions().actionPtr(name()) ) + { + d->m_kaccel = kacc; + d->m_kaccel->insert(name(), d->plainText(), QString::null, + KShortcut(d->m_cut), + this, SLOT(slotActivated()), + configurable, isEnabled()); + connect(d->m_kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed())); + //connect(d->m_kaccel, SIGNAL(keycodeChanged()), this, SLOT(slotKeycodeChanged())); + } + else + kdWarning(129) << "KAction::plugAccel( kacc = " << kacc << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis +*/ +} + +void KAction::unplugAccel() +{ + qDebug("KAction::unplugAccel ...1 has top be fixed"); +/*US + //kdDebug(129) << "KAction::unplugAccel() " << this << " " << name() << endl; + if ( d->m_kaccel ) + { + d->m_kaccel->remove(name()); + d->m_kaccel = 0; + } +*/ +} + +void KAction::plugMainWindowAccel( QWidget *w ) +{ + qDebug("KAction::plugMainWindowAccel ...1 has top be fixed"); +/*US + // Note: topLevelWidget() stops too early, we can't use it. + QWidget * tl = w; + QWidget * n; + while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store + tl = n; + + KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + if (mw) + plugAccel( mw->accel() ); + else + kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl; +*/ +} + +void KAction::setEnabled(bool enable) +{ + //kdDebug(129) << "KAction::setEnabled( " << enable << " ): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl; + if ( enable == d->isEnabled() ) + return; + + // KDE 4: remove +//US if (d->m_kaccel) +//US d->m_kaccel->setEnabled(name(), enable); + // KDE 4: remove end + +//US for ( uint i = 0; i < d->m_kaccelList.count(); i++ ) +//US d->m_kaccelList[i]->setEnabled( name(), enable ); + + d->setEnabled( enable ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateEnabled( i ); + + emit enabled( d->isEnabled() ); +} + +void KAction::updateEnabled( int i ) +{ + QWidget *w = container( i ); + + if ( w->inherits("QPopupMenu") ) + static_cast<QPopupMenu*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( w->inherits("QMenuBar") ) + static_cast<QMenuBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( w->inherits( "KToolBar" ) ) + { + static_cast<KToolBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + } +} + +void KAction::setShortcutConfigurable( bool b ) +{ + d->m_configurable = b; +} + +void KAction::setText( const QString& text ) +{ +/*US + // KDE 4: remove + if (d->m_kaccel) { + KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name()); + if (pAction) + pAction->setLabel( text ); + } + // KDE 4: remove end + + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + KAccelAction* pAction = d->m_kaccelList[i]->actions().actionPtr(name()); + if (pAction) + pAction->setLabel( text ); + } +*/ + d->setText( text ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateText( i ); + +} + +void KAction::updateText( int i ) +{ + QWidget *w = container( i ); + + if ( w->inherits( "QPopupMenu" ) ) { + int id = itemId( i ); + static_cast<QPopupMenu*>(w)->changeItem( id, d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), id ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( i ), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + { + qDebug("KAction::updateText ...3 has top be fixed"); + QWidget *button = static_cast<KToolBar *>(w)->getWidget( itemId( i ) ); + if ( button->inherits( "KToolBarButton" ) ) + static_cast<KToolBarButton *>(button)->setText( d->plainText() ); + + } +} + +QString KAction::text() const +{ + return d->text(); +} + +QString KAction::plainText() const +{ + return d->plainText( ); +} + +void KAction::setIcon( const QString &icon ) +{ + d->setIconName( icon ); + + // now handle any toolbars + int len = containerCount(); + for ( int i = 0; i < len; ++i ) + updateIcon( i ); +} + +void KAction::updateIcon( int id ) +{ + QWidget* w = container( id ); + + if ( w->inherits( "QPopupMenu" ) ) { + int itemId_ = itemId( id ); + static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet( KIcon::Small ), d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), itemId_ ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet( KIcon::Small ), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + static_cast<KToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() ); + else if ( w->inherits( "QToolBar" ) ) + { + qDebug("KAction::updateIcon has top be fixed"); +//US static_cast<QToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() ); + } +} + +QString KAction::icon() const +{ + return d->iconName( ); +} + +void KAction::setIconSet( const QIconSet &iconset ) +{ + d->setIconSet( iconset ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateIconSet( i ); +} + + +void KAction::updateIconSet( int id ) +{ + QWidget *w = container( id ); + + if ( w->inherits( "QPopupMenu" ) ) + { + int itemId_ = itemId( id ); + static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet(), d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), itemId_ ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet(), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + { + if ( icon().isEmpty() && d->hasIconSet() ) // only if there is no named icon ( scales better ) + static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet() ); + else + static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet( KIcon::Small ) ); + } +} + +QIconSet KAction::iconSet( KIcon::Group group, int size ) const +{ + return d->iconSet( group, size ); +} + +bool KAction::hasIcon() const +{ + return d->hasIcon(); +} + + +void KAction::setWhatsThis( const QString& text ) +{ + d->setWhatsThis( text ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateWhatsThis( i ); +} + +void KAction::updateWhatsThis( int i ) +{ + qDebug("KAction::updateWhatsThis ...1 has top be fixed"); + QPopupMenu* pm = popupMenu( i ); + if ( pm ) + { + pm->setWhatsThis( itemId( i ), d->whatsThis() ); + return; + } + + KToolBar *tb = toolBar( i ); + if ( tb ) + { + QWidget *w = tb->getButton( itemId( i ) ); +//US QWhatsThis::remove( w ); +//US QWhatsThis::add( w, d->whatsThis() ); + return; + } +} + +QString KAction::whatsThis() const +{ + return d->whatsThis(); +} + +QString KAction::whatsThisWithIcon() const +{ + QString text = whatsThis(); + if (!d->iconName().isEmpty()) + return QString::fromLatin1("<img source=\"small|%1\"> %2").arg(d->iconName() ).arg(text); + return text; +} + +QWidget* KAction::container( int index ) const +{ + assert( index < containerCount() ); + return d->m_containers[ index ].m_container; +} + +KToolBar* KAction::toolBar( int index ) const +{ +//US return dynamic_cast<KToolBar *>( d->m_containers[ index ].m_container ); + return (KToolBar *)( d->m_containers[ index ].m_container ); +} + +QPopupMenu* KAction::popupMenu( int index ) const +{ +//US return dynamic_cast<QPopupMenu *>( d->m_containers[ index ].m_container ); + return (QPopupMenu *)( d->m_containers[ index ].m_container ); +} + +QWidget* KAction::representative( int index ) const +{ + return d->m_containers[ index ].m_representative; +} + +int KAction::itemId( int index ) const +{ + return d->m_containers[ index ].m_id; +} + +int KAction::containerCount() const +{ + return d->m_containers.count(); +} + +uint KAction::kaccelCount() const +{ + return d->m_kaccelList.count(); +} + +void KAction::addContainer( QWidget* c, int id ) +{ + KActionPrivate::Container p; + p.m_container = c; + p.m_id = id; + d->m_containers.append( p ); +} + +void KAction::addContainer( QWidget* c, QWidget* w ) +{ + KActionPrivate::Container p; + p.m_container = c; + p.m_representative = w; + d->m_containers.append( p ); +} + +void KAction::activate() +{ + slotActivated(); +} + +void KAction::slotActivated() +{ + emit activated(); +} + +void KAction::slotDestroyed() +{ + kdDebug(129) << "KAction::slotDestroyed(): this = " << this << ", name = \"" << name() << "\", sender = " << sender() << endl; + const QObject* o = sender(); + +/* + + + // KDE 4: remove + if ( o == d->m_kaccel ) + { + d->m_kaccel = 0; + return; + } + // KDE 4: remove end + + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) + { + if ( o == d->m_kaccelList[i] ) + { + disconnect( d->m_kaccelList[i], SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + return; + } + } +*/ + int i; + do + { + i = findContainer( static_cast<const QWidget*>( o ) ); + if ( i != -1 ) + removeContainer( i ); + } while ( i != -1 ); + +} + +int KAction::findContainer( const QWidget* widget ) const +{ + int pos = 0; + QValueList<KActionPrivate::Container>::ConstIterator it = d->m_containers.begin(); + while( it != d->m_containers.end() ) + { + if ( (*it).m_representative == widget || (*it).m_container == widget ) + return pos; + ++it; + ++pos; + } + + return -1; +} + +void KAction::removeContainer( int index ) +{ + int i = 0; + QValueList<KActionPrivate::Container>::Iterator it = d->m_containers.begin(); + while( it != d->m_containers.end() ) + { + if ( i == index ) + { + d->m_containers.remove( it ); + return; + } + ++it; + ++i; + } +} + +// FIXME: Remove this (ellis) +void KAction::slotKeycodeChanged() +{ + qDebug("KAction::slotKeycodeChanged() ...44 has top be fixed"); +/*US + kdDebug(129) << "KAction::slotKeycodeChanged()" << endl; // -- ellis + KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name()); + if( pAction ) + setShortcut(pAction->shortcut()); +*/ +} + +KActionCollection *KAction::parentCollection() const +{ + return m_parentCollection; +} + +void KAction::unplugAll() +{ + while ( containerCount() != 0 ) + unplug( container( 0 ) ); +} + +void KAction::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/* vim: et sw=2 ts=2 + */ + +//US #include "kaction.moc" diff --git a/microkde/kdeui/kaction.h b/microkde/kdeui/kaction.h new file mode 100644 index 0000000..13e2e1e --- a/dev/null +++ b/microkde/kdeui/kaction.h @@ -0,0 +1,624 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kaction_h__ +#define __kaction_h__ + + +//US #include <qkeysequence.h> +#include <qobject.h> +#include <qvaluelist.h> +#include <qguardedptr.h> +#include <kguiitem.h> +#include <kshortcut.h> +#include <kstdaction.h> +//US#include <kicontheme.h> + +//US added the following files +#include <kiconloader.h> + +class QMenuBar; +class QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +class QIconSet; +class QString; +class KToolBar; + +class KAccel; +//USclass KAccelActions; +//USclass KConfig; +//USclass KConfigBase; +//USclass KURL; +//USclass KInstance; +//USclass KToolBar; +class KActionCollection; +//USclass KPopupMenu; +class KMainWindow; + +/** + * The KAction class (and derived and super classes) provides a way to + * easily encapsulate a "real" user-selected action or event in your + * program. + * + * For instance, a user may want to @p paste the contents of + * the clipboard or @p scroll @p down a document or @p quit the + * application. These are all @p actions -- events that the + * user causes to happen. The KAction class allows the developer to + * deal with these actions in an easy and intuitive manner. + * + * Specifically, the KAction class encapsulated the various attributes + * to an event/action. For instance, an action might have an icon + * that goes along with it (a clipboard for a "paste" action or + * scissors for a "cut" action). The action might have some text to + * describe the action. It will certainly have a method or function + * that actually @p executes the action! All these attributes + * are contained within the KAction object. + * + * The advantage of dealing with Actions is that you can manipulate + * the Action without regard to the GUI representation of it. For + * instance, in the "normal" way of dealing with actions like "cut", + * you would manually insert a item for Cut into a menu and a button + * into a toolbar. If you want to disable the cut action for a moment + * (maybe nothing is selected), you woud have to hunt down the pointer + * to the menu item and the toolbar button and disable both + * individually. Setting the menu item and toolbar item up uses very + * similar code - but has to be done twice! + * + * With the Action concept, you simply "plug" the Action into whatever + * GUI element you want. The KAction class will then take care of + * correctly defining the menu item (with icons, accelerators, text, + * etc) or toolbar button.. or whatever. From then on, if you + * manipulate the Action at all, the effect will propogate through all + * GUI representations of it. Back to the "cut" example: if you want + * to disable the Cut Action, you would simply do + * 'cutAction->setEnabled(false)' and the menuitem and button would + * instantly be disabled! + * + * This is the biggest advantage to the Action concept -- there is a + * one-to-one relationship between the "real" action and @p all + * GUI representations of it. + * + * KAction emits the activated() signal if the user activated the + * corresponding GUI element ( menu item, toolbar button, etc. ) + * + * If you are in the situation of wanting to map the activated() + * signal of multiple action objects to one slot, with a special + * argument bound to each action, then you might consider using + * @ref QSignalMapper . A tiny example: + * + * <PRE> + * QSignalMapper *desktopNumberMapper = new QSignalMapper( this ); + * connect( desktopNumberMapper, SIGNAL( mapped( int ) ), + * this, SLOT( moveWindowToDesktop( int ) ) ); + * + * for ( uint i = 0; i < numberOfDesktops; ++i ) { + * KAction *desktopAction = new KAction( i18n( "Move Window to Desktop %i" ).arg( i ), ... ); + * connect( desktopAction, SIGNAL( activated() ), desktopNumberMapper, SLOT( map() ) ); + * desktopNumberMapper->setMapping( desktopAction, i ); + * } + * </PRE> + * + * @sect General Usage: + * + * The steps to using actions are roughly as follows + * + * @li Decide which attributes you want to associate with a given + * action (icons, text, keyboard shortcut, etc) + * @li Create the action using KAction (or derived or super class). + * @li "Plug" the Action into whatever GUI element you want. Typically, + * this will be a menu or toolbar. + * + * @sect Detailed Example: + * + * Here is an example of enabling a "New [document]" action + * <PRE> + * KAction *newAct = new KAction(i18n("&New"), "filenew", + * KStdAccel::shortcut(KStdAccel::New), + * this, SLOT(fileNew()), + * actionCollection(), "new"); + * </PRE> + * This line creates our action. It says that wherever this action is + * displayed, it will use "&New" as the text, the standard icon, and + * the standard shortcut. It further says that whenever this action + * is invoked, it will use the fileNew() slot to execute it. + * + * <PRE> + * QPopupMenu *file = new QPopupMenu; + * newAct->plug(file); + * </PRE> + * That just inserted the action into the File menu. The point is, it's not + * important in which menu it is: all manipulation of the item is + * done through the newAct object. + * + * <PRE> + * newAct->plug(toolBar()); + * </PRE> + * And this inserted the Action into the main toolbar as a button. + * + * That's it! + * + * If you want to disable that action sometime later, you can do so + * with + * <PRE> + * newAct->setEnabled(false) + * </PRE> + * and both the menuitem in File and the toolbar button will instantly + * be disabled. + * + * Do not delete a KAction object without unplugging it from all its + * containers. The simplest way to do that is to use the unplugAll() + * as in the following example: + * <PRE> + * newAct->unplugAll(); + * delete newAct; + * </PRE> + * Normally you will not need to do this as KActionCollection manages + * everything for you. + * + * Note: if you are using a "standard" action like "new", "paste", + * "quit", or any other action described in the KDE UI Standards, + * please use the methods in the @ref KStdAction class rather than + * defining your own. + * + * @sect Usage Within the XML Framework: + * + * If you are using KAction within the context of the XML menu and + * toolbar building framework, then there are a few tiny changes. The + * first is that you must insert your new action into an action + * collection. The action collection (a @ref KActionCollection) is, + * logically enough, a central collection of all of the actions + * defined in your application. The XML UI framework code in KXMLGUI + * classes needs access to this collection in order to build up the + * GUI (it's how the builder code knows which actions are valid and + * which aren't). + * + * Also, if you use the XML builder framework, then you do not ever + * have to plug your actions into containers manually. The framework + * does that for you. + * + * @see KStdAction + * @short Class to encapsulate user-driven action or event + */ +class KAction : public QObject +{ + friend class KActionCollection; + Q_OBJECT + Q_PROPERTY( int containerCount READ containerCount ) + Q_PROPERTY( QString plainText READ plainText ) + Q_PROPERTY( QString text READ text WRITE setText ) + Q_PROPERTY( QString shortcut READ shortcutText WRITE setShortcutText ) + Q_PROPERTY( bool enabled READ isEnabled WRITE setEnabled ) + Q_PROPERTY( QString group READ group WRITE setGroup ) + Q_PROPERTY( QString whatsThis READ whatsThis WRITE setWhatsThis ) + Q_PROPERTY( QString toolTip READ toolTip WRITE setToolTip ) + Q_PROPERTY( QString icon READ icon WRITE setIcon ) +public: + /** + * Constructs an action with text, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. + * + * If you do not want or have a keyboard shortcut, + * set the @p cut param to 0. + * + * This is the most common KAction used when you do not have a + * corresponding icon (note that it won't appear in the current version + * of the "Edit ToolBar" dialog, because an action needs an icon to be + * plugged in a toolbar...). + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard shortcut. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + /** + * Constructs an action with text, icon, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. + * + * If you do not want or have a keyboard shortcut, set the + * @p cut param to 0. + * + * This is the other common KAction used. Use it when you + * @p do have a corresponding icon. + * + * @param text The text that will be displayed. + * @param pix The icon to display. + * @param cut The corresponding keyboard shortcut. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + /** + * Constructs an action with text, icon, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. The icon is loaded on demand later based on where it + * is plugged in. + * + * If you do not want or have a keyboard shortcut, set the + * @p cut param to 0. + * + * This is the other common KAction used. Use it when you + * @p do have a corresponding icon. + * + * @param text The text that will be displayed. + * @param pix The icon to display. + * @param cut The corresponding keyboard shortcut (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + /** + * The same as the above constructor, but with a KGuiItem providing + * the text and icon. + * + * @param item The KGuiItem with the label and (optional) icon. + */ + KAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + /** + * @obsolete + */ + KAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + /** + * @obsolete + */ + KAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Standard destructor + */ + virtual ~KAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will + * typically be a menu or a toolbar. From this point on, you will + * never need to directly manipulate the item in the menu or + * toolbar. You do all enabling/disabling/manipulation directly + * with your KAction object. + * + * @param w The GUI element to display this action + */ + virtual int plug( QWidget *w, int index = -1 ); + + /** + * @deprecated. Shouldn't be used. No substitute available. + * + * "Plug" or insert this action into a given KAccel. + * + * @param accel The KAccel collection which holds this accel + * @param configurable If the shortcut is configurable via + * the KAccel configuration dialog (this is somehow deprecated since + * there is now a KAction key configuration dialog). + */ + virtual void plugAccel(KAccel *accel, bool configurable = true); + + /** + * "Unplug" or remove this action from a given widget. + * + * This will typically be a menu or a toolbar. This is rarely + * used in "normal" application. Typically, it would be used if + * your application has several views or modes, each with a + * completely different menu structure. If you simply want to + * disable an action for a given period, use @ref setEnabled() + * instead. + * + * @param w Remove the action from this GUI element. + */ + virtual void unplug( QWidget *w ); + + /** + * @deprecated. Complement method to plugAccel(). + * Disconnect this action from the KAccel. + */ + virtual void unplugAccel(); + + /** + * returns whether the action is plugged into any container widget or not. + * @since 3.1 + */ + virtual bool isPlugged() const; + + /** + * returns whether the action is plugged into the given container + */ + bool isPlugged( const QWidget *container ) const; + + /** + * returns whether the action is plugged into the given container with the given, container specific, id (often + * menu or toolbar id ) . + */ + virtual bool isPlugged( const QWidget *container, int id ) const; + + /** + * returns whether the action is plugged into the given container with the given, container specific, representative + * container widget item. + */ + virtual bool isPlugged( const QWidget *container, const QWidget *_representative ) const; + + QWidget* container( int index ) const; + int itemId( int index ) const; + QWidget* representative( int index ) const; + int containerCount() const; + /// @since 3.1 + uint kaccelCount() const; + + virtual bool hasIcon() const; +#ifndef KDE_NO_COMPAT + bool hasIconSet() const { return hasIcon(); } +#endif + virtual QString plainText() const; + + /** + * Get the text associated with this action. + */ + virtual QString text() const; + + /** + * Get the keyboard shortcut associated with this action. + */ + virtual const KShortcut& shortcut() const; + /** + * Get the default shortcut for this action. + */ + virtual const KShortcut& shortcutDefault() const; + + // These two methods are for Q_PROPERTY + QString shortcutText() const; + void setShortcutText( const QString& ); + + /** + * Returns true if this action is enabled. + */ + virtual bool isEnabled() const; + + /** + * Returns true if this action's shortcut is configurable. + */ + virtual bool isShortcutConfigurable() const; + + virtual QString group() const; + + /** + * Get the What's this text for the action. + */ + virtual QString whatsThis() const; + + /** + * Get the tooltip text for the action. + */ + virtual QString toolTip() const; + + /** + * Get the QIconSet from which the icons used to display this action will + * be chosen. + */ + virtual QIconSet iconSet( KIcon::Group group, int size=0 ) const; + +#ifndef KDE_NO_COMPAT + QIconSet iconSet() const + { + return iconSet( KIcon::Small ); + } +#endif + + virtual QString icon() const; + + KActionCollection *parentCollection() const; + + /** + * @internal + * Generate a toolbar button id. Made public for reimplementations. + */ + static int getToolButtonID(); + + + void unplugAll(); + +public slots: + /** + * Sets the text associated with this action. The text is used for menu + * and toolbar labels etc. + */ + virtual void setText(const QString &text); + + /** + * Sets the keyboard shortcut associated with this action. + */ + virtual bool setShortcut( const KShortcut& ); + + virtual void setGroup( const QString& ); + + /** + * Sets the What's this text for the action. This text will be displayed when + * a widget that has been created by plugging this action into a container + * is clicked on in What's this mode. + * + * The What's this text can include QML markup as well as raw text. + */ + virtual void setWhatsThis( const QString& text ); + + /** + * Sets the tooltip text for the action. + * This will be used as a tooltip for a toolbar button, as a + * statusbar help-text for a menu item, and it also appears + * in the toolbar editor, to describe the action. + */ + virtual void setToolTip( const QString& ); + + /** + * Sets the QIconSet from which the icons used to display this action will + * be chosen. + */ + virtual void setIconSet( const QIconSet &iconSet ); + + virtual void setIcon( const QString& icon ); + + /** + * Enables or disables this action. All uses of this action (eg. in menus + * or toolbars) will be updated to reflect the state of the action. + */ + virtual void setEnabled(bool enable); + + /** + * Indicate whether the user may configure the action's shortcut. + */ + virtual void setShortcutConfigurable( bool ); + + /** + * Emulate user's interaction programmatically, by activating the action. + * The implementation simply emits activated(). + */ + virtual void activate(); + +protected slots: + virtual void slotDestroyed(); + virtual void slotKeycodeChanged(); + virtual void slotActivated(); + +protected: + KToolBar* toolBar( int index ) const; + QPopupMenu* popupMenu( int index ) const; + void removeContainer( int index ); + int findContainer( const QWidget* widget ) const; + void plugMainWindowAccel( QWidget *w ); + + void addContainer( QWidget* parent, int id ); + void addContainer( QWidget* parent, QWidget* representative ); + + virtual void updateShortcut( int i ); + virtual void updateShortcut( QPopupMenu* menu, int id ); + virtual void updateGroup( int id ); + virtual void updateText(int i ); + virtual void updateEnabled(int i); + virtual void updateIconSet(int i); + virtual void updateIcon( int i); + virtual void updateToolTip( int id ); + virtual void updateWhatsThis( int i ); + + KActionCollection *m_parentCollection; + QString whatsThisWithIcon() const; + +signals: + void activated(); + void enabled( bool ); + +private: + void initPrivate( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot ); + KAccel* kaccelCurrent(); + bool initShortcut( const KShortcut& ); + void plugShortcut(); + bool updateKAccelShortcut( KAccel* kaccel ); + void insertKAccel( KAccel* ); + /** @internal To be used exclusively by KActionCollection::removeWidget(). */ + void removeKAccel( KAccel* ); + +#ifndef KDE_NO_COMPAT +public: + /** + * @deprecated. Use shortcut(). + * Get the keyboard accelerator associated with this action. + */ + int accel() const; + + QString statusText() const + { return toolTip(); } + + /** + * @deprecated. Use setShortcut(). + * Sets the keyboard accelerator associated with this action. + */ + void setAccel( int key ); + + /** + * @deprecated. Use setToolTip instead (they do the same thing now). + */ + void setStatusText( const QString &text ) + { setToolTip( text ); } + + /** + * @deprecated. for backwards compatibility. + */ + int menuId( int i ) { return itemId( i ); } +#endif // !KDE_NO_COMPAT + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionPrivate; + KActionPrivate *d; +}; + +#include <kactioncollection.h> +#include <kactionclasses.h> + +#endif diff --git a/microkde/kdeui/kactionclasses.cpp b/microkde/kdeui/kactionclasses.cpp new file mode 100644 index 0000000..82e6c8b --- a/dev/null +++ b/microkde/kdeui/kactionclasses.cpp @@ -0,0 +1,2058 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + (C) 2002 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kactionclasses.h" + +#include <assert.h> + +#include <qfontdatabase.h> +#include <qobjectlist.h> +//US#include <qwhatsthis.h> +#include <qtimer.h> + +//US#include <kaccel.h> +//US#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +//US#include <kfontcombo.h> +//US#include <kmainwindow.h> +//US#include <kmenubar.h> +//US#include <kpopupmenu.h> +#include <kcombobox.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> +#include <kurl.h> + +//US added the following includefiles +#include <kconfigbase.h> +#include <qwidget.h> +#include <qpopupmenu.h> +#include <qmenubar.h> +#include <qmainwindow.h> +#include <qtoolbar.h> +#include <qcombobox.h> +#include <qmainwindow.h> + + +static QFontDatabase *fontDataBase = 0; + +static void cleanupFontDatabase() +{ + delete fontDataBase; + fontDataBase = 0; +} + +static void get_fonts( QStringList &lst ) +{ + if ( !fontDataBase ) { + fontDataBase = new QFontDatabase(); + qAddPostRoutine( cleanupFontDatabase ); + } + lst.clear(); + QStringList families = fontDataBase->families(); + for ( QStringList::Iterator it = families.begin(); it != families.end(); ++it ) + { + QString family = *it; + if ( family. contains('-') ) // remove foundry + family = family.right( family.length() - family.find('-' ) - 1); + if ( !lst.contains( family ) ) + lst.append( family ); + } + lst.sort(); +} + +static QValueList<int> get_standard_font_sizes() +{ + if ( !fontDataBase ) { + fontDataBase = new QFontDatabase(); + qAddPostRoutine( cleanupFontDatabase ); + } + return fontDataBase->standardSizes(); +} + +class KToggleAction::KToggleActionPrivate +{ +public: + KToggleActionPrivate() + { + m_checked = false; + } + + bool m_checked; + QString m_exclusiveGroup; +}; + +KToggleAction::KToggleAction( const QString& text, const KShortcut& cut, + QObject* parent, + const char* name ) + : KAction( text, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::~KToggleAction() +{ + delete d; +} + +int KToggleAction::plug( QWidget* widget, int index ) +{ + if ( !widget->inherits("QPopupMenu") && !widget->inherits("KToolBar") ) + { + kdWarning() << "Can not plug KToggleAction in " << widget->className() << endl; + return -1; + } + +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + + int _index = KAction::plug( widget, index ); + if ( _index == -1 ) + return _index; + + if ( widget->inherits("QPopupMenu") ) + { + int id = itemId( _index ); + + static_cast<QPopupMenu*>(widget)->setItemChecked( id, d->m_checked ); + } else if ( widget->inherits( "KToolBar" ) ) { + + KToolBar *bar = static_cast<KToolBar *>( widget ); + + bar->setToggle( itemId( _index ), true ); + bar->setButton( itemId( _index ), isChecked() ); + } + + return _index; +} + +void KToggleAction::setChecked( bool c ) +{ + if ( c == d->m_checked ) + return; + //kdDebug(129) << "KToggleAction::setChecked(" << c << ") " << this << " " << name() << endl; + + d->m_checked = c; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateChecked( i ); + + if ( c && parent() && !exclusiveGroup().isEmpty() ) { + const QObjectList *list = parent()->children(); + if ( list ) { + QObjectListIt it( *list ); + for( ; it.current(); ++it ) { + if ( it.current()->inherits( "KToggleAction" ) && it.current() != this && + static_cast<KToggleAction*>(it.current())->exclusiveGroup() == exclusiveGroup() ) { + KToggleAction *a = static_cast<KToggleAction*>(it.current()); + if( a->isChecked() ) { + a->setChecked( false ); + emit a->toggled( false ); + } + } + } + } + } +} + +void KToggleAction::updateChecked( int id ) +{ + QWidget *w = container( id ); + + if ( w->inherits( "QPopupMenu" ) ) + static_cast<QPopupMenu*>(w)->setItemChecked( itemId( id ), d->m_checked ); + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->setItemChecked( itemId( id ), d->m_checked ); + else if ( w->inherits( "KToolBar" ) ) + { + QWidget* r = static_cast<KToolBar*>( w )->getButton( itemId( id ) ); + if ( r && r->inherits( "KToolBarButton" ) ) + static_cast<KToolBar*>( w )->setButton( itemId( id ), d->m_checked ); + } +} + +void KToggleAction::slotActivated() +{ + setChecked( !isChecked() ); + emit activated(); + emit toggled( isChecked() ); +} + +bool KToggleAction::isChecked() const +{ + return d->m_checked; +} + +void KToggleAction::setExclusiveGroup( const QString& name ) +{ + d->m_exclusiveGroup = name; +} + +QString KToggleAction::exclusiveGroup() const +{ + return d->m_exclusiveGroup; +} + + +KRadioAction::KRadioAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( QObject* parent, const char* name ) +: KToggleAction( parent, name ) +{ +} + +void KRadioAction::slotActivated() +{ + if ( isChecked() ) + { + const QObject *senderObj = sender(); + + if ( !senderObj || !senderObj->inherits( "KToolBarButton" ) ) + return; + + qDebug("KRadioAction::slotActivated has to be fixed"); + const_cast<KToolBarButton *>( static_cast<const KToolBarButton *>( senderObj ) )->on( true ); + + return; + } + + KToggleAction::slotActivated(); +} + +class KSelectAction::KSelectActionPrivate +{ +public: + KSelectActionPrivate() + { + m_edit = false; + m_menuAccelsEnabled = true; + m_menu = 0; + m_current = -1; + m_comboWidth = -1; + } + bool m_edit; + bool m_menuAccelsEnabled; + QPopupMenu *m_menu; + int m_current; + int m_comboWidth; + QStringList m_list; + + QString makeMenuText( const QString &_text ) + { + if ( m_menuAccelsEnabled ) + return _text; + QString text = _text; + uint i = 0; + while ( i < text.length() ) { + if ( text.at( i ) == '&' ) { + text.insert( i, '&' ); + i += 2; + } + else + ++i; + } + return text; + } +}; + +KSelectAction::KSelectAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::~KSelectAction() +{ + assert(d); + delete d->m_menu; + delete d; d = 0; +} + +void KSelectAction::setCurrentItem( int id ) +{ + if ( id >= (int)d->m_list.count() ) { + ASSERT(id < (int)d->m_list.count()); + return; + } + + if ( d->m_menu ) + { + if ( d->m_current >= 0 ) + d->m_menu->setItemChecked( d->m_current, false ); + if ( id >= 0 ) + { + //US qDebug("KSelectAction::setCurrentItem %i", id); + d->m_menu->setItemChecked( id, true ); + } + } + + d->m_current = id; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateCurrentItem( i ); + + // emit KAction::activated(); + // emit activated( currentItem() ); + // emit activated( currentText() ); +} + +void KSelectAction::setComboWidth( int width ) +{ + if ( width < 0 ) + return; + + d->m_comboWidth=width; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateComboWidth( i ); + +} +QPopupMenu* KSelectAction::popupMenu() const +{ + kdDebug(129) << "KSelectAction::popupMenu()" << endl; // remove -- ellis + if ( !d->m_menu ) + { +//US d->m_menu = new KPopupMenu(0L, "KSelectAction::popupMenu()"); + d->m_menu = new QPopupMenu(0L, "QSelectAction::popupMenu()"); + setupMenu(); + if ( d->m_current >= 0 ) + d->m_menu->setItemChecked( d->m_current, true ); + } + + return d->m_menu; +} + +void KSelectAction::setupMenu() const +{ + if ( !d->m_menu ) + return; + d->m_menu->clear(); + + QStringList::ConstIterator it = d->m_list.begin(); + for( uint id = 0; it != d->m_list.end(); ++it, ++id ) { + QString text = *it; + if ( !text.isEmpty() ) + d->m_menu->insertItem( d->makeMenuText( text ), this, SLOT( slotActivated( int ) ), 0, id ); + else + d->m_menu->insertSeparator(); + } +} + +void KSelectAction::changeItem( int index, const QString& text ) +{ + if ( index < 0 || index >= (int)d->m_list.count() ) + { + kdWarning() << "KSelectAction::changeItem Index out of scope" << endl; + return; + } + + d->m_list[ index ] = text; + + if ( d->m_menu ) + d->m_menu->changeItem( index, d->makeMenuText( text ) ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + changeItem( i, index, text ); +} + +void KSelectAction::changeItem( int id, int index, const QString& text) +{ + if ( index < 0 ) + return; + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) + { + QWidget* r = (static_cast<KToolBar*>( w ))->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) + { + QComboBox *b = static_cast<QComboBox*>( r ); + b->changeItem(text, index ); + } + } + +} + +void KSelectAction::setItems( const QStringList &lst ) +{ + kdDebug(129) << "KAction::setItems()" << endl; // remove -- ellis + d->m_list = lst; + d->m_current = -1; + + setupMenu(); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateItems( i ); + + // Disable if empty and not editable + setEnabled ( lst.count() > 0 || d->m_edit ); +} + +QStringList KSelectAction::items() const +{ + return d->m_list; +} + +QString KSelectAction::currentText() const +{ + if ( currentItem() < 0 ) + return QString::null; + + return d->m_list[ currentItem() ]; +} + +int KSelectAction::currentItem() const +{ + return d->m_current; +} + +void KSelectAction::updateCurrentItem( int id ) +{ + if ( d->m_current < 0 ) + return; + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *b = static_cast<QComboBox*>( r ); + b->setCurrentItem( d->m_current ); + } + } +} + +int KSelectAction::comboWidth() const +{ + return d->m_comboWidth; +} + +void KSelectAction::updateComboWidth( int id ) +{ + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *cb = static_cast<QComboBox*>( r ); + cb->setMinimumWidth( d->m_comboWidth ); + cb->setMaximumWidth( d->m_comboWidth ); + } + } +} + +void KSelectAction::updateItems( int id ) +{ + kdDebug(129) << "KAction::updateItems( " << id << ", lst )" << endl; // remove -- ellis + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *cb = static_cast<QComboBox*>( r ); + cb->clear(); + QStringList lst = comboItems(); + QStringList::ConstIterator it = lst.begin(); + for( ; it != lst.end(); ++it ) + cb->insertItem( *it ); + // Ok, this currently doesn't work due to a bug in QComboBox + // (the sizehint is cached for ever and never recalculated) + // Bug reported (against Qt 2.3.1). + cb->setMinimumWidth( cb->sizeHint().width() ); + } + } + +} + +int KSelectAction::plug( QWidget *widget, int index ) +{ +//US if (kapp && !kapp->authorizeKAction(name())) +//US return -1; + + kdDebug(129) << "KAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis + if ( widget->inherits("QPopupMenu") ) + { + // Create the PopupMenu and store it in m_menu + (void)popupMenu(); + + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + int id; + + if ( hasIconSet() ) + id = menu->insertItem( iconSet(), text(), d->m_menu, -1, index ); + else + id = menu->insertItem( text(), d->m_menu, -1, index ); + + if ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + QString wth = whatsThis(); + if ( !wth.isEmpty() ) + menu->setWhatsThis( id, wth ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits("KToolBar") ) + { + + KToolBar* bar = static_cast<KToolBar*>( widget ); + int id_ = KAction::getToolButtonID(); + bar->insertCombo( comboItems(), id_, isEditable(), + SIGNAL( activated( const QString & ) ), this, + SLOT( slotActivated( const QString & ) ), isEnabled(), + toolTip(), -1, index ); + + KComboBox *cb = bar->getCombo( id_ ); + if ( cb ) + { + cb->setMaximumHeight( 34 ); + if (!isEditable()) cb->setFocusPolicy(QWidget::NoFocus); + cb->setMinimumWidth( cb->sizeHint().width() ); + if ( d->m_comboWidth > 0 ) + { + cb->setMinimumWidth( d->m_comboWidth ); + cb->setMaximumWidth( d->m_comboWidth ); + } + cb->setInsertionPolicy( QComboBox::NoInsertion ); +//US QWhatsThis::add( cb, whatsThis() ); + } + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + updateCurrentItem( containerCount() - 1 ); + + return containerCount() - 1; + + } + kdWarning() << "Can not plug KAction in " << widget->className() << endl; + return -1; +} + +QStringList KSelectAction::comboItems() const +{ + //qDebug("KSelectAction::comboItems has to be fixed"); + if( d->m_menuAccelsEnabled ) + { + QStringList lst; + QStringList::ConstIterator it = d->m_list.begin(); + for( ; it != d->m_list.end(); ++it ) + { + QString item = *it; + int i = item.find( '&' ); + if ( i > -1 ) + item = item.remove( i, 1 ); + lst.append( item ); + } + return lst; + } + else + { + return d->m_list; + } +} + +void KSelectAction::clear() +{ + if ( d->m_menu ) + d->m_menu->clear(); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateClear( i ); +} + +void KSelectAction::updateClear( int id ) +{ + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *b = static_cast<QComboBox*>( r ); + b->clear(); + } + } +} + +void KSelectAction::slotActivated( int id ) +{ + if ( d->m_current == id ) + return; + + setCurrentItem( id ); + // Delay this. Especially useful when the slot connected to activated() will re-create + // the menu, e.g. in the recent files action. This prevents a crash. + + QTimer::singleShot( 0, this, SLOT( slotActivated() ) ); +} + +void KSelectAction::slotActivated( const QString &text ) +{ + if ( isEditable() ) + { + QStringList lst = items(); + if(lst.contains(text)==0) + { + lst.append( text ); + setItems( lst ); + } + } + + int i = items().findIndex( text ); + if ( i > -1 ) + setCurrentItem( i ); + else + setCurrentItem( comboItems().findIndex( text ) ); + // Delay this. Especially useful when the slot connected to activated() will re-create + // the menu, e.g. in the recent files action. This prevents a crash. + + QTimer::singleShot( 0, this, SLOT( slotActivated() ) ); +} + +void KSelectAction::slotActivated() +{ + KAction::slotActivated(); + kdDebug(129) << "KSelectAction::slotActivated currentItem=" << currentItem() << " currentText=" << currentText() << endl; + emit activated( currentItem() ); + emit activated( currentText() ); +} + +void KSelectAction::setEditable( bool edit ) +{ + d->m_edit = edit; +} + +bool KSelectAction::isEditable() const +{ + return d->m_edit; +} + +void KSelectAction::setRemoveAmpersandsInCombo( bool b ) +{ + setMenuAccelsEnabled( b ); +} + +bool KSelectAction::removeAmpersandsInCombo() const +{ + return menuAccelsEnabled( ); +} + +void KSelectAction::setMenuAccelsEnabled( bool b ) +{ + d->m_menuAccelsEnabled = b; +} + +bool KSelectAction::menuAccelsEnabled() const +{ + return d->m_menuAccelsEnabled; +} + +class KListAction::KListActionPrivate +{ +public: + KListActionPrivate() + { + m_current = 0; + } + int m_current; +}; + +KListAction::KListAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( const QString& text, const QString& pix, + const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::~KListAction() +{ + delete d; d = 0; +} + +void KListAction::setCurrentItem( int index ) +{ + KSelectAction::setCurrentItem( index ); + d->m_current = index; + + // emit KAction::activated(); + // emit activated( currentItem() ); + // emit activated( currentText() ); +} + +QString KListAction::currentText() const +{ + if ( currentItem() < 0 ) + return QString::null; + + return items()[ currentItem() ]; +} + +int KListAction::currentItem() const +{ + return d->m_current; +} + +class KRecentFilesAction::KRecentFilesActionPrivate +{ +public: + KRecentFilesActionPrivate() + { + m_maxItems = 0; + } + uint m_maxItems; +}; + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( QObject* parent, const char* name, + uint maxItems ) + : KListAction( parent, name ) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +void KRecentFilesAction::init() +{ + connect( this, SIGNAL( activated( const QString& ) ), + this, SLOT( itemSelected( const QString& ) ) ); + + setMenuAccelsEnabled( false ); +} + +KRecentFilesAction::~KRecentFilesAction() +{ + delete d; d = 0; +} + +uint KRecentFilesAction::maxItems() const +{ + return d->m_maxItems; +} + +void KRecentFilesAction::setMaxItems( uint maxItems ) +{ + QStringList lst = items(); + uint oldCount = lst.count(); + + // set new maxItems + d->m_maxItems = maxItems; + + // remove all items that are too much + while( lst.count() > maxItems ) + { + // remove last item + lst.remove( lst.last() ); + } + + // set new list if changed + if( lst.count() != oldCount ) + setItems( lst ); +} + +void KRecentFilesAction::addURL( const KURL& url ) +{ + QString file = url.prettyURL(); + QStringList lst = items(); + + // remove file if already in list + lst.remove( file ); + + // remove las item if already maxitems in list + if( lst.count() == d->m_maxItems ) + { + // remove last item + lst.remove( lst.last() ); + } + + // add file to list + lst.prepend( file ); + setItems( lst ); +} + +void KRecentFilesAction::removeURL( const KURL& url ) +{ + QStringList lst = items(); + QString file = url.prettyURL(); + + // remove url + if( lst.count() > 0 ) + { + lst.remove( file ); + setItems( lst ); + } +} + +void KRecentFilesAction::clearURLList() +{ + clear(); +} + +void KRecentFilesAction::loadEntries( KConfig* config, QString groupname) +{ + QString key; + QString value; + QString oldGroup; + QStringList lst; + + oldGroup = config->group(); + + if (groupname.isEmpty()) + groupname = "RecentFiles"; + config->setGroup( groupname ); + + // read file list + for( unsigned int i = 1 ; i <= d->m_maxItems ; i++ ) + { + key = QString( "File%1" ).arg( i ); + value = config->readEntry( key, QString::null ); + + if (!value.isNull()) + lst.append( value ); + } + + // set file + setItems( lst ); + + config->setGroup( oldGroup ); +} + +void KRecentFilesAction::saveEntries( KConfig* config, QString groupname ) +{ + QString key; + QString value; + QStringList lst = items(); + + if (groupname.isEmpty()) + groupname = "RecentFiles"; + + config->deleteGroup( groupname); + + KConfigGroupSaver( config, groupname ); + + // write file list + for( unsigned int i = 1 ; i <= lst.count() ; i++ ) + { + key = QString( "File%1" ).arg( i ); + value = lst[ i - 1 ]; + config->writeEntry( key, value ); + } +} + +void KRecentFilesAction::itemSelected( const QString& text ) +{ + emit urlSelected( KURL( text ) ); +} + +class KFontAction::KFontActionPrivate +{ +public: + KFontActionPrivate() + { + } + QStringList m_fonts; +}; + +KFontAction::KFontAction( const QString& text, + const KShortcut& cut, QObject* parent, + const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + + +KFontAction::KFontAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::~KFontAction() +{ + delete d; + d = 0; +} + +/* + * Maintenance note: Keep in sync with KFontCombo::setCurrentFont() + */ +void KFontAction::setFont( const QString &family ) +{ + QString lowerName = family.lower(); + int i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower() == lowerName) + { + setCurrentItem(i); + return; + } + } + i = lowerName.find(" ["); + if (i>-1) + { + lowerName = lowerName.left(i); + i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower() == lowerName) + { + setCurrentItem(i); + return; + } + } + } + + lowerName += " ["; + i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower().startsWith(lowerName)) + { + setCurrentItem(i); + return; + } + } + kdDebug(129) << "Font not found " << family.lower() << endl; +} + +int KFontAction::plug( QWidget *w, int index ) +{ + qDebug("KFontAction::plug ha to be fixed"); +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; + if ( w->inherits("KToolBar") ) + { + KToolBar* bar = static_cast<KToolBar*>( w ); + int id_ = KAction::getToolButtonID(); + KFontCombo *cb = new KFontCombo( items(), bar ); + connect( cb, SIGNAL( activated( const QString & ) ), + SLOT( slotActivated( const QString & ) ) ); + cb->setEnabled( isEnabled() ); + bar->insertWidget( id_, comboWidth(), cb, index ); + cb->setMinimumWidth( cb->sizeHint().width() ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + updateCurrentItem( containerCount() - 1 ); + + return containerCount() - 1; + } + else return KSelectAction::plug( w, index ); +*/ + return 3; +} + +class KFontSizeAction::KFontSizeActionPrivate +{ +public: + KFontSizeActionPrivate() + { + } +}; + +KFontSizeAction::KFontSizeAction( const QString& text, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + init(); +} + +KFontSizeAction::~KFontSizeAction() +{ + delete d; + d = 0; +} + +void KFontSizeAction::init() +{ + d = new KFontSizeActionPrivate; + + setEditable( true ); + QValueList<int> sizes = get_standard_font_sizes(); + QStringList lst; + for ( QValueList<int>::Iterator it = sizes.begin(); it != sizes.end(); ++it ) + lst.append( QString::number( *it ) ); + + setItems( lst ); +} + +void KFontSizeAction::setFontSize( int size ) +{ + if ( size == fontSize() ) { + setCurrentItem( items().findIndex( QString::number( size ) ) ); + return; + } + + if ( size < 1 ) { + kdWarning() << "KFontSizeAction: Size " << size << " is out of range" << endl; + return; + } + + int index = items().findIndex( QString::number( size ) ); + if ( index == -1 ) { + // Insert at the correct position in the list (to keep sorting) + QValueList<int> lst; + // Convert to list of ints + QStringList itemsList = items(); + for (QStringList::Iterator it = itemsList.begin() ; it != itemsList.end() ; ++it) + lst.append( (*it).toInt() ); + // New size + lst.append( size ); + // Sort the list +qDebug("KFontSizeAction::setFontSize heapsort not found."); +//US has to be fixed +//US qHeapSort( lst ); + // Convert back to string list + QStringList strLst; + for (QValueList<int>::Iterator it = lst.begin() ; it != lst.end() ; ++it) + strLst.append( QString::number(*it) ); + KSelectAction::setItems( strLst ); + // Find new current item + index = lst.findIndex( size ); + setCurrentItem( index ); + } + else + setCurrentItem( index ); + + + //emit KAction::activated(); + //emit activated( index ); + //emit activated( QString::number( size ) ); + //emit fontSizeChanged( size ); +} + +int KFontSizeAction::fontSize() const +{ + return currentText().toInt(); +} + +void KFontSizeAction::slotActivated( int index ) +{ + KSelectAction::slotActivated( index ); + + emit fontSizeChanged( items()[ index ].toInt() ); +} + +void KFontSizeAction::slotActivated( const QString& size ) +{ + setFontSize( size.toInt() ); // insert sorted first + KSelectAction::slotActivated( size ); + emit fontSizeChanged( size.toInt() ); +} + +class KActionMenu::KActionMenuPrivate +{ +public: + KActionMenuPrivate() + { +//US m_popup = new KPopupMenu(0L,"KActionMenu::KActionMenuPrivate"); + m_popup = new QPopupMenu(0L,"KActionMenu::KActionMenuPrivate"); + m_delayed = true; + m_stickyMenu = true; + } + ~KActionMenuPrivate() + { + delete m_popup; m_popup = 0; + } + +//US KPopupMenu *m_popup; + QPopupMenu *m_popup; + bool m_delayed; + bool m_stickyMenu; +}; + +KActionMenu::KActionMenu( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, QObject* parent, + const char* name ) + : KAction( text, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, const QIconSet& icon, + QObject* parent, const char* name ) + : KAction( text, icon, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, const QString& icon, + QObject* parent, const char* name ) + : KAction( text, icon, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::~KActionMenu() +{ + unplugAll(); + kdDebug(129) << "KActionMenu::~KActionMenu()" << endl; // ellis + delete d; d = 0; +} + +void KActionMenu::popup( const QPoint& global ) +{ + popupMenu()->popup( global ); +} + + +//US KPopupMenu* KActionMenu::popupMenu() const +QPopupMenu* KActionMenu::popupMenu() const +{ + return d->m_popup; +} + +void KActionMenu::insert( KAction* cmd, int index ) +{ + if ( cmd ) + cmd->plug( d->m_popup, index ); +} + +void KActionMenu::remove( KAction* cmd ) +{ + if ( cmd ) + cmd->unplug( d->m_popup ); +} + +bool KActionMenu::delayed() const { + return d->m_delayed; +} + +void KActionMenu::setDelayed(bool _delayed) { + d->m_delayed = _delayed; +} + +bool KActionMenu::stickyMenu() const { + return d->m_stickyMenu; +} + +void KActionMenu::setStickyMenu(bool sticky) { + d->m_stickyMenu = sticky; +} + +int KActionMenu::plug( QWidget* widget, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + kdDebug(129) << "KAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis + if ( widget->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + int id; + if ( hasIconSet() ) + id = menu->insertItem( iconSet(), text(), d->m_popup, -1, index ); + else + id = menu->insertItem( text(), d->m_popup, -1, index ); + + if ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( menu, this ); + + return containerCount() - 1; + } + else if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( widget ); + + int id_ = KAction::getToolButtonID(); + + if ( icon().isEmpty() && !iconSet().isNull() ) + bar->insertButton( iconSet().pixmap(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index ); + else + { + /*US + KInstance *instance; + + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + bar->insertButton( icon(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index/*US, instance */); + } + + addContainer( bar, id_ ); +/*US + if (!whatsThis().isEmpty()) + QWhatsThis::add( bar->getButton(id_), whatsThis() ); +*/ + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if (delayed()) { + bar->setDelayedPopup( id_, popupMenu(), stickyMenu() ); + } else { + bar->getButton(id_)->setPopup(popupMenu(), stickyMenu() ); + } + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( bar, this ); + + return containerCount() - 1; + } + else if ( widget->inherits( "QMenuBar" ) ) + { + QMenuBar *bar = static_cast<QMenuBar *>( widget ); + + int id; + + id = bar->insertItem( text(), popupMenu(), -1, index ); + + if ( !isEnabled() ) + bar->setItemEnabled( id, false ); + + addContainer( bar, id ); + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + + return -1; +} + +//////// + +KToolBarPopupAction::KToolBarPopupAction( const QString& text, + const QString& icon, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, icon, cut, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + +KToolBarPopupAction::KToolBarPopupAction( const QString& text, + const QString& icon, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, icon, cut, receiver, slot, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + +KToolBarPopupAction::KToolBarPopupAction( const KGuiItem& item, + const KShortcut& cut, + const QObject* receiver, + const char* slot, KActionCollection* parent, + const char* name ) + : KAction( item, cut, receiver, slot, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + + +KToolBarPopupAction::~KToolBarPopupAction() +{ + if ( m_popup ) + delete m_popup; +} + +bool KToolBarPopupAction::delayed() const { + return m_delayed; +} + +void KToolBarPopupAction::setDelayed(bool delayed) { + m_delayed = delayed; +} + +bool KToolBarPopupAction::stickyMenu() const { + return m_stickyMenu; +} + +void KToolBarPopupAction::setStickyMenu(bool sticky) { + m_stickyMenu = sticky; +} + +int KToolBarPopupAction::plug( QWidget *widget, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + // This is very related to KActionMenu::plug. + // In fact this class could be an interesting base class for KActionMenu + if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *bar = (KToolBar *)widget; + + int id_ = KAction::getToolButtonID(); +/*US + KInstance * instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + bar->insertButton( icon(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index/*US, instance*/ ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if (delayed()) { + bar->setDelayedPopup( id_, popupMenu(), stickyMenu() ); + } else { + bar->getButton(id_)->setPopup(popupMenu(), stickyMenu()); + } +/*US + if ( !whatsThis().isEmpty() ) + QWhatsThis::add( bar->getButton( id_ ), whatsThisWithIcon() ); +*/ + return containerCount() - 1; + } + + + return KAction::plug( widget, index ); +} + +//US KPopupMenu *KToolBarPopupAction::popupMenu() const +QPopupMenu *KToolBarPopupAction::popupMenu() const +{ + if ( !m_popup ) { + KToolBarPopupAction *that = const_cast<KToolBarPopupAction*>(this); +//US that->m_popup = new KPopupMenu; + that->m_popup = new QPopupMenu; + } + return m_popup; +} + +//////// + +KToggleToolBarAction::KToggleToolBarAction( const char* toolBarName, + const QString& text, KActionCollection* parent, const char* name ) + : KToggleAction( text, KShortcut(), parent, name ) + , m_toolBarName( toolBarName ) + , m_toolBar( 0L ) +{ +} + +KToggleToolBarAction::KToggleToolBarAction( KToolBar *toolBar, const QString &text, + KActionCollection *parent, const char *name ) + : KToggleAction( text, KShortcut(), parent, name ) + , m_toolBarName( 0 ) + , m_toolBar( toolBar ) +{ +} + +KToggleToolBarAction::~KToggleToolBarAction() +{ +} + +int KToggleToolBarAction::plug( QWidget* w, int index ) +{ + qDebug("KToggleToolBarAction::plug has to be fixed"); +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; + + if ( !m_toolBar ) { + // Note: topLevelWidget() stops too early, we can't use it. + QWidget * tl = w; + QWidget * n; + while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store + tl = n; + +//US KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + QMainWindow * mw = 0; + if ( tl->inherits("QMainWindow") ) + mw = (QMainWindow *)(tl); // try to see if it's a kmainwindow + + if ( mw ) + m_toolBar = mw->toolBar( m_toolBarName ); + } + + if( m_toolBar ) { + setChecked( m_toolBar->isVisible() ); + connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(setChecked(bool)) ); + // Also emit toggled when the toolbar's visibility changes (see comment in header) + connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SIGNAL(toggled(bool)) ); + } else { + setEnabled( false ); + } +*/ + return KToggleAction::plug( w, index ); +} + +void KToggleToolBarAction::setChecked( bool c ) +{ + if( m_toolBar && c != m_toolBar->isVisible() ) { + if( c ) { + m_toolBar->show(); + } else { + m_toolBar->hide(); + } + qDebug("KToggleToolBarAction::setChecked has to be fixed"); +/*US + QMainWindow* mw = m_toolBar->mainWindow(); + if ( mw && mw->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>( mw )->setSettingsDirty(); +*/ + } + KToggleAction::setChecked( c ); + +} + +//////// + +KWidgetAction::KWidgetAction( QWidget* widget, + const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) + , m_widget( widget ) + , m_autoSized( false ) +{ +} + +KWidgetAction::~KWidgetAction() +{ +} + +void KWidgetAction::setAutoSized( bool autoSized ) +{ + if( m_autoSized == autoSized ) + return; + + m_autoSized = autoSized; + + if( !m_widget || !isPlugged() ) + return; + + KToolBar* toolBar = (KToolBar*)m_widget->parent(); + int i = findContainer( toolBar ); + if ( i == -1 ) + return; + int id = itemId( i ); + + toolBar->setItemAutoSized( id, m_autoSized ); + +} + +int KWidgetAction::plug( QWidget* w, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + if ( !w->inherits( "KToolBar" ) ) { + kdError() << "KWidgetAction::plug: KWidgetAction must be plugged into KToolBar." << endl; + return -1; + } + if ( !m_widget ) { + kdError() << "KWidgetAction::plug: Widget was deleted or null!" << endl; + return -1; + } + + KToolBar* toolBar = static_cast<KToolBar*>( w ); + + int id = KAction::getToolButtonID(); + + m_widget->reparent( toolBar, QPoint() ); + toolBar->insertWidget( id, 0, m_widget, index ); + toolBar->setItemAutoSized( id, m_autoSized ); + +//US QWhatsThis::add( m_widget, whatsThis() ); + addContainer( toolBar, id ); + + connect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) ); + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; +} + +void KWidgetAction::unplug( QWidget *w ) +{ + if( !m_widget || !isPlugged() ) + return; + + KToolBar* toolBar = (KToolBar*)m_widget->parent(); + if ( toolBar == w ) + { + disconnect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) ); + m_widget->reparent( 0L, QPoint(), false ); // false = showit + } + KAction::unplug( w ); +} + +void KWidgetAction::slotToolbarDestroyed() +{ + //Q_ASSERT( m_widget ); // When exiting the app the widget could be destroyed before the toolbar. + + ASSERT( isPlugged() ); + if( !m_widget || !isPlugged() ) + return; + + // Don't let a toolbar being destroyed, delete my widget. + m_widget->reparent( 0L, QPoint(), false /*showIt*/ ); +} + +//////// + +KActionSeparator::KActionSeparator( QObject *parent, const char *name ) + : KAction( parent, name ) +{ +} + +KActionSeparator::~KActionSeparator() +{ +} + +int KActionSeparator::plug( QWidget *widget, int index ) +{ + if ( widget->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + + int id = menu->insertSeparator( index ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits( "QMenuBar" ) ) + { + QMenuBar *menuBar = static_cast<QMenuBar *>( widget ); + + int id = menuBar->insertSeparator( index ); + + addContainer( menuBar, id ); + + connect( menuBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *toolBar = static_cast<KToolBar *>( widget ); + + int id = toolBar->insertSeparator( index ); +// toolBar->addSeparator(); + + addContainer( toolBar, id ); + + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + + return -1; +} + +void KToggleAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KRadioAction::virtual_hook( int id, void* data ) +{ KToggleAction::virtual_hook( id, data ); } + +void KSelectAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KListAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KRecentFilesAction::virtual_hook( int id, void* data ) +{ KListAction::virtual_hook( id, data ); } + +void KFontAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KFontSizeAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KActionMenu::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KToolBarPopupAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KToggleToolBarAction::virtual_hook( int id, void* data ) +{ KToggleAction::virtual_hook( id, data ); } + +void KWidgetAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KActionSeparator::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +/* vim: et sw=2 ts=2 + */ + +/*US +#include "kactionclasses.moc" +*/ diff --git a/microkde/kdeui/kactionclasses.h b/microkde/kdeui/kactionclasses.h new file mode 100644 index 0000000..f6e7a0f --- a/dev/null +++ b/microkde/kdeui/kactionclasses.h @@ -0,0 +1,1223 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kactionclasses_h__ +#define __kactionclasses_h__ + +#include <kaction.h> + +//US#include <qkeysequence.h> +//US#include <qobject.h> +//US#include <qvaluelist.h> +//US#include <qguardedptr.h> +//US#include <kguiitem.h> +#include <kshortcut.h> +//US#include <kstdaction.h> +//US#include <kicontheme.h> + +class QMenuBar; +class QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +//USclass QIconSet; +//USclass QString; +//USclass KToolBar; + +//USclass KAccel; +//USclass KAccelActions; +class KConfig; +//USclass KConfigBase; +class KURL; +//USclass KInstance; + + +//US class KToolBar needs to be replaced +class KToolBar; +class KActionCollection; + +//US class KPopupMenu needs to be replaced +//US class KPopupMenu; +//USclass KMainWindow; + +/** + * Checkbox like action. + * + * This action provides two states: checked or not. + * + * @short Checkbox like action. + */ +class KToggleAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool checked READ isChecked WRITE setChecked ) + Q_PROPERTY( QString exclusiveGroup READ exclusiveGroup WRITE setExclusiveGroup ) +public: + + /** + * Constructs a toggle action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KToggleAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will typically be a menu or a toolbar. From this point + * on, you will never need to directly manipulate the item in the + * menu or toolbar. You do all enabling/disabling/manipulation + * directly with your KToggleAction object. + * + * @param widget The GUI element to display this action. + * @param index The index of the item. + */ + virtual int plug( QWidget* widget, int index = -1 ); + + /** + * Returns the actual state of the action. + */ + bool isChecked() const; + + /** + * @return which "exclusive group" this action is part of. + * @see setExclusiveGroup + */ + QString exclusiveGroup() const; + + /** + * Defines which "exclusive group" this action is part of. + * In a given exclusive group, only one toggle action can be checked + * at a any moment. Checking an action unchecks the other actions + * of the group. + */ + virtual void setExclusiveGroup( const QString& name ); + +public slots: + /** + * Sets the state of the action. + */ + virtual void setChecked( bool ); + +protected slots: + virtual void slotActivated(); + +protected: + virtual void updateChecked( int id ); + +signals: + void toggled( bool ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToggleActionPrivate; + KToggleActionPrivate *d; +}; + +/** + * An action that operates like a radio button. At any given time + * only a single action from the group will be active. + */ +class KRadioAction : public KToggleAction +{ + Q_OBJECT +public: + /** + * Constructs a radio action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( QObject* parent = 0, const char* name = 0 ); + +protected: + virtual void slotActivated(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KRadioActionPrivate; + KRadioActionPrivate *d; +}; + +/** + * Action for selecting one of several items. + * + * This action shows up a submenu with a list of items. + * One of them can be checked. If the user clicks on an item + * this item will automatically be checked, + * the formerly checked item becomes unchecked. + * There can be only one item checked at a time. + * + * @short Action for selecting one of several items + */ +class KSelectAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( int currentItem READ currentItem WRITE setCurrentItem ) + Q_PROPERTY( QStringList items READ items WRITE setItems ) + Q_PROPERTY( bool editable READ isEditable WRITE setEditable ) + Q_PROPERTY( int comboWidth READ comboWidth WRITE setComboWidth ) + Q_PROPERTY( QString currentText READ currentText ) + Q_PROPERTY( bool menuAccelsEnabled READ menuAccelsEnabled WRITE setMenuAccelsEnabled ) +public: + + /** + * Constructs a select action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KSelectAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will typically be a menu or a toolbar. + * From this point on, you will never need to directly + * manipulate the item in the menu or toolbar. + * You do all enabling/disabling/manipulation directly with your KSelectAction object. + * + * @param widget The GUI element to display this action. + * @param index The index of the item. + */ + virtual int plug( QWidget* widget, int index = -1 ); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * @return true if the combo editable. + */ + virtual bool isEditable() const; + + /** + * @return the items that can be selected with this action. + * Use setItems to set them. + */ + virtual QStringList items() const; + + virtual void changeItem( int index, const QString& text ); + + virtual QString currentText() const; + + virtual int currentItem() const; + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This returns the maximum width set by setComboWidth + */ + virtual int comboWidth() const; + + QPopupMenu* popupMenu() const; + + /** + * Deprecated. See @ref setMenuAccelsEnabled . + * @since 3.1 + */ + void setRemoveAmpersandsInCombo( bool b ); + /// @since 3.1 + bool removeAmpersandsInCombo() const; + + /** + * Sets whether any occurence of the ampersand character ( & ) in items + * should be interpreted as keyboard accelerator for items displayed in a + * menu or not. + * @since 3.1 + */ + void setMenuAccelsEnabled( bool b ); + /// @since 3.1 + bool menuAccelsEnabled() const; + +public slots: + /** + * Sets the currently checked item. + * + * @param index Index of the item (remember the first item is zero). + */ + virtual void setCurrentItem( int index ); + + /** + * Sets the items to be displayed in this action + * You need to call this. + */ + virtual void setItems( const QStringList &lst ); + + /** + * Clears up all the items in this action + */ + virtual void clear(); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This makes the combo editable or read-only. + */ + virtual void setEditable( bool ); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This gives a _maximum_ size to the combobox. + * The minimum size is automatically given by the contents (the items). + */ + virtual void setComboWidth( int width ); + +protected: + virtual void changeItem( int id, int index, const QString& text ); + + /** + * Depending on the menuAccelsEnabled property this method will return the + * actions items in a way for inclusion in a combobox with the ampersand + * character removed from all items or not. + * @since 3.1 + */ + QStringList comboItems() const; + +protected slots: + virtual void slotActivated( int id ); + virtual void slotActivated( const QString &text ); + virtual void slotActivated(); + +signals: + void activated( int index ); + void activated( const QString& text ); + +protected: + virtual void updateCurrentItem( int id ); + + virtual void updateComboWidth( int id ); + + virtual void updateItems( int id ); + + virtual void updateClear( int id ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void setupMenu() const; + class KSelectActionPrivate; + KSelectActionPrivate *d; + +}; + +/// Remove this class in KDE-4.0. It doesn't add _anything_ to KSelectAction +/** + * @deprecated Use KSelectAction instead. + */ +class KListAction : public KSelectAction +{ + Q_OBJECT +public: + /** + * Constructs a list action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KListAction(); + + + virtual QString currentText() const; + virtual int currentItem() const; + + +public slots: + /** + * Sets the currently checked item. + * + * @param index Index of the item (remember the first item is zero). + */ + virtual void setCurrentItem( int index ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListActionPrivate; + KListActionPrivate *d; +}; + +/** + * This class is an action to handle a recent files submenu. + * The best way to create the action is to use KStdAction::openRecent. + * Then you simply need to call @ref loadEntries on startup, @ref saveEntries + * on shutdown, @ref addURL when your application loads/saves a file. + * + * @author Michael Koch + * @short Recent files action + */ +class KRecentFilesAction : public KListAction // TODO public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( uint maxItems READ maxItems WRITE setMaxItems ) +public: + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( QObject* parent = 0, const char* name = 0, + uint maxItems = 10 ); + + /** + * Destructor. + */ + virtual ~KRecentFilesAction(); + + /** + * Returns the maximum of items in the recent files list. + */ + uint maxItems() const; + +public slots: + /** + * Sets the maximum of items in the recent files list. + * The default for this value is 10 set in the constructor. + * + * If this value is lesser than the number of items currently + * in the recent files list the last items are deleted until + * the number of items are equal to the new maximum. + */ + void setMaxItems( uint maxItems ); + + /** + * Loads the recent files entries from a given KConfig object. + * You can provide the name of the group used to load the entries. + * If the groupname is empty, entries are load from a group called 'RecentFiles' + * + * This method does not effect the active group of KConfig. + */ + void loadEntries( KConfig* config, QString groupname=QString::null ); + + /** + * Saves the current recent files entries to a given KConfig object. + * You can provide the name of the group used to load the entries. + * If the groupname is empty, entries are saved to a group called 'RecentFiles' + * + * This method does not effect the active group of KConfig. + */ + void saveEntries( KConfig* config, QString groupname=QString::null ); + +public slots: + /** + * Add URL to recent files list. + * + * @param url The URL of the file + */ + void addURL( const KURL& url ); + + /** + * Remove an URL from the recent files list. + * + * @param url The URL of the file + */ + void removeURL( const KURL& url ); + + /** + * Removes all entries from the recent files list. + */ + void clearURLList(); + +signals: + + /** + * This signal gets emited when the user selects an URL. + * + * @param url The URL thats the user selected. + */ + void urlSelected( const KURL& url ); + +protected slots: + /** + * + */ + void itemSelected( const QString& string ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void init(); + + class KRecentFilesActionPrivate; + KRecentFilesActionPrivate *d; +}; + +class KFontAction : public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( QString font READ font WRITE setFont ) +public: + KFontAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + KFontAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + KFontAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + KFontAction( QObject* parent = 0, const char* name = 0 ); + ~KFontAction(); + + QString font() const { + return currentText(); + } + + int plug( QWidget*, int index = -1 ); + +public slots: + void setFont( const QString &family ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KFontActionPrivate; + KFontActionPrivate *d; +}; + +class KFontSizeAction : public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize ) +public: + KFontSizeAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + KFontSizeAction( const QString& text, const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0 ); + KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + KFontSizeAction( QObject* parent = 0, const char* name = 0 ); + + virtual ~KFontSizeAction(); + + virtual int fontSize() const; + +public slots: + virtual void setFontSize( int size ); + +protected slots: + virtual void slotActivated( int ); + virtual void slotActivated( const QString& ); + virtual void slotActivated() { KAction::slotActivated(); } + +signals: + void fontSizeChanged( int ); + +private: + void init(); + + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KFontSizeActionPrivate; + KFontSizeActionPrivate *d; +}; + + +/** + * A KActionMenu is an action that holds a sub-menu of other actions. + * insert() and remove() allow to insert and remove actions into this action-menu. + * Plugged in a popupmenu, it will create a submenu. + * Plugged in a toolbar, it will create a button with a popup menu. + * + * This is the action used by the XMLGUI since it holds other actions. + * If you want a submenu for selecting one tool among many (without icons), see KSelectAction. + * See also setDelayed about the main action. + */ +class KActionMenu : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool delayed READ delayed WRITE setDelayed ) + Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu ) + +public: + KActionMenu( const QString& text, QObject* parent = 0, + const char* name = 0 ); + KActionMenu( const QString& text, const QIconSet& icon, + QObject* parent = 0, const char* name = 0 ); + KActionMenu( const QString& text, const QString& icon, + QObject* parent = 0, const char* name = 0 ); + KActionMenu( QObject* parent = 0, const char* name = 0 ); + virtual ~KActionMenu(); + + virtual void insert( KAction*, int index = -1 ); + virtual void remove( KAction* ); + +//US KPopupMenu* popupMenu() const; + QPopupMenu* popupMenu() const; + void popup( const QPoint& global ); + + /** + * Returns true if this action creates a delayed popup menu + * when plugged in a KToolbar. + */ + bool delayed() const; + /** + * If set to true, this action will create a delayed popup menu + * when plugged in a KToolbar. Otherwise it creates a normal popup. + * Default: delayed + * + * Remember that if the "main" action (the toolbar button itself) + * cannot be clicked, then you should call setDelayed(false). + * + * On the opposite, if the main action can be clicked, it can only happen + * in a toolbar: in a menu, the parent of a submenu can't be activated. + * To get a "normal" menu item when plugged a menu (and no submenu) + * use KToolBarPopupAction. + */ + void setDelayed(bool _delayed); + + /** + * Returns true if this action creates a sticky popup menu. + * See @ref setStickyMenu. + */ + bool stickyMenu() const; + /** + * If set to true, this action will create a sticky popup menu + * when plugged in a KToolbar. + * "Sticky", means it's visible until a selection is made or the mouse is + * clicked elsewhere. This feature allows you to make a selection without + * having to press and hold down the mouse while making a selection. + * Default: sticky. + */ + void setStickyMenu(bool sticky); + + virtual int plug( QWidget* widget, int index = -1 ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionMenuPrivate; + KActionMenuPrivate *d; +}; + +/** + * This action is a normal action everywhere, except in a toolbar + * where it also has a popupmenu (optionnally delayed). This action is designed + * for history actions (back/forward, undo/redo) and for any other action + * that has more detail in a toolbar than in a menu (e.g. tool chooser + * with "Other" leading to a dialog...). + */ +class KToolBarPopupAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool delayed READ delayed WRITE setDelayed ) + Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu ) + +public: + //Not all constructors - because we need an icon, since this action only makes + // sense when being plugged at least in a toolbar. + /** + * Create a KToolBarPopupAction, with a text, an icon, an optionnal accelerator, + * parent and name. + * + * @param text The text that will be displayed. + * @param icon The icon to display. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * Create a KToolBarPopupAction, with a text, an icon, an accelerator, + * a slot connected to the action, parent and name. + * + * If you do not want or have a keyboard accelerator, set the + * @p cut param to 0. + * + * @param text The text that will be displayed. + * @param icon The icon to display. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's owner. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent = 0, const char* name = 0 ); + + /** + * Create a KToolBarPopupAction, with a KGuiItem, an accelerator, + * a slot connected to the action, parent and name. The text and the + * icon are taken from the KGuiItem. + * + * If you do not want or have a keyboard accelerator, set the + * @p cut param to 0. + * + * @param item The text and icon that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's owner. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + + KToolBarPopupAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + virtual ~KToolBarPopupAction(); + + virtual int plug( QWidget *widget, int index = -1 ); + + /** + * The popup menu that is shown when clicking (some time) on the toolbar + * button. You may want to plug items into it on creation, or connect to + * aboutToShow for a more dynamic menu. + */ +//US KPopupMenu *popupMenu() const; + QPopupMenu *popupMenu() const; + + /** + * Returns true if this action creates a delayed popup menu + * when plugged in a KToolbar. + */ + bool delayed() const; + /** + * If set to true, this action will create a delayed popup menu + * when plugged in a KToolbar. Otherwise it creates a normal popup. + * Default: delayed. + */ + void setDelayed(bool delayed); + /** + * Returns true if this action creates a sticky popup menu. + * See @ref setStickyMenu. + */ + bool stickyMenu() const; + /** + * If set to true, this action will create a sticky popup menu + * when plugged in a KToolbar. + * "Sticky", means it's visible until a selection is made or the mouse is + * clicked elsewhere. This feature allows you to make a selection without + * having to press and hold down the mouse while making a selection. + * Only available if delayed() is true. + * Default: sticky. + */ + void setStickyMenu(bool sticky); + +private: +//US KPopupMenu *m_popup; + QPopupMenu *m_popup; + bool m_delayed:1; + bool m_stickyMenu:1; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToolBarPopupActionPrivate; + KToolBarPopupActionPrivate *d; +}; + +/** + * An action that takes care of everything associated with + * showing or hiding a toolbar by a menu action. It will + * show or hide the toolbar with the given name when + * activated, and check or uncheck itself if the toolbar + * is manually shown or hidden. + * + * If you need to perfom some additional action when the + * toolbar is shown or hidden, connect to the toggled(bool) + * signal. It will be emitted after the toolbar's + * visibility has changed, whenever it changes. + * @since 3.1 + */ +class KToggleToolBarAction : public KToggleAction +{ + Q_OBJECT +public: + /** + * Create a KToggleToolbarAction that manages the toolbar + * named toolBarName. This can be either the name of a + * toolbar in an xml ui file, or a toolbar programmatically + * created with that name. + */ + KToggleToolBarAction( const char* toolBarName, const QString& text, + KActionCollection* parent, const char* name ); + KToggleToolBarAction( KToolBar *toolBar, const QString &text, + KActionCollection *parent, const char *name ); + virtual ~KToggleToolBarAction(); + + virtual int plug( QWidget*, int index = -1 ); + + KToolBar *toolBar() { + return m_toolBar; + } + +public slots: + virtual void setChecked( bool ); + +private: + QCString m_toolBarName; + QGuardedPtr<KToolBar> m_toolBar; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToggleToolBarActionPrivate; + KToggleToolBarActionPrivate *d; +}; + +/** + * An action that automatically embeds a widget into a + * toolbar. + */ +class KWidgetAction : public KAction +{ + Q_OBJECT +public: + /** + * Create an action that will embed widget into a toolbar + * when plugged. This action may only be plugged into + * a toolbar. + */ + KWidgetAction( QWidget* widget, const QString& text, + const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + virtual ~KWidgetAction(); + + /** + * Returns the widget associated with this action. + */ + QWidget* widget() { return m_widget; } + + void setAutoSized( bool ); + + /** + * Plug the action. The widget passed to the constructor + * will be reparented to w, which must inherit KToolBar. + */ + virtual int plug( QWidget* w, int index = -1 ); + /** + * Unplug the action. Ensures that the action is not + * destroyed. It will be hidden and reparented to 0L instead. + */ + virtual void unplug( QWidget *w ); +protected slots: + void slotToolbarDestroyed(); +private: + QGuardedPtr<QWidget> m_widget; + bool m_autoSized; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KWidgetActionPrivate; + KWidgetActionPrivate *d; +}; + +class KActionSeparator : public KAction +{ + Q_OBJECT +public: + KActionSeparator( QObject* parent = 0, const char* name = 0 ); + virtual ~KActionSeparator(); + + virtual int plug( QWidget*, int index = -1 ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionSeparatorPrivate; + KActionSeparatorPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kactioncollection.cpp b/microkde/kdeui/kactioncollection.cpp new file mode 100644 index 0000000..b819e76 --- a/dev/null +++ b/microkde/kdeui/kactioncollection.cpp @@ -0,0 +1,839 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + (C) 2002 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kactioncollection.h" +//US#include "kactionshortcutlist.h" + +#include <qptrdict.h> +//US#include <qvariant.h> + +//US#include <kaccel.h> +//US#include <kaccelbase.h> +//US#include <kapplication.h> +#include <kdebug.h> +//US#include <kxmlguifactory.h> + +//US I included the following files +#include <qasciidict.h> +#include <qptrlist.h> +#include "kaction.h" +#include <kglobal.h> +#include <qobject.h> +#include <qwidget.h> + +class KActionCollection::KActionCollectionPrivate +{ +public: + KActionCollectionPrivate() + { +//US m_instance = 0; + //m_bOneKAccelOnly = false; + //m_iWidgetCurrent = 0; + m_bAutoConnectShortcuts = true; + m_widget = 0; + m_kaccel = m_builderKAccel = 0; + m_dctHighlightContainers.setAutoDelete( true ); + m_highlight = false; + m_currentHighlightAction = 0; + m_statusCleared = true; + } + +//US KInstance *m_instance; +//US QString m_sXMLFile; + bool m_bAutoConnectShortcuts; + //bool m_bOneKAccelOnly; + //int m_iWidgetCurrent; + //QValueList<QWidget*> m_widgetList; + //QValueList<KAccel*> m_kaccelList; + QValueList<KActionCollection*> m_docList; + QWidget *m_widget; + KAccel *m_kaccel; + KAccel *m_builderKAccel; + + QAsciiDict<KAction> m_actionDict; + QPtrDict< QPtrList<KAction> > m_dctHighlightContainers; + bool m_highlight; + KAction *m_currentHighlightAction; + bool m_statusCleared; +}; + +KActionCollection::KActionCollection( QWidget *parent, const char *name /*US, + KInstance *instance */) + : QObject( (QObject*)parent, name ) +{ + kdDebug(129) << "KActionCollection::KActionCollection( " << parent << ", " << name << " ): this = " << this << endl; // ellis + d = new KActionCollectionPrivate; + if( parent ) + setWidget( parent ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + + +KActionCollection::KActionCollection( QWidget *watch, QObject* parent, const char *name /*US, + KInstance *instance */) + : QObject( parent, name ) +{ + kdDebug(129) << "KActionCollection::KActionCollection( " << watch << ", " << parent << ", " << name << " ): this = " << this << endl; //ellis + d = new KActionCollectionPrivate; + if( watch ) + setWidget( watch ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + +// KDE 4: remove +KActionCollection::KActionCollection( QObject *parent, const char *name /*US, + KInstance *instance */) + : QObject( parent, name ) +{ + kdWarning(129) << "KActionCollection::KActionCollection( QObject *parent, const char *name, KInstance *instance )" << endl; //ellis +//US kdBacktrace not available +//US kdDebug(129) << kdBacktrace() << endl; + d = new KActionCollectionPrivate; +//US QWidget* w = dynamic_cast<QWidget*>( parent ); + QWidget* w = (QWidget*)( parent ); + if( w ) + setWidget( w ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + +KActionCollection::KActionCollection( const KActionCollection © ) + : QObject() +{ + kdWarning(129) << "KActionCollection::KActionCollection( const KActionCollection & ): function is severely deprecated." << endl; + d = new KActionCollectionPrivate; + *this = copy; +} +// KDE 4: remove end + +KActionCollection::~KActionCollection() +{ + kdDebug(129) << "KActionCollection::~KActionCollection(): this = " << this << endl; + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + if ( pAction->m_parentCollection == this ) + pAction->m_parentCollection = 0L; + } + +//US delete d->m_kaccel; +//US delete d->m_builderKAccel; + delete d; d = 0; +} + +void KActionCollection::setWidget( QWidget* w ) +{ + //if ( d->m_actionDict.count() > 0 ) { + // kdError(129) << "KActionCollection::setWidget(): must be called before any actions are added to collection!" << endl; + // kdDebug(129) << kdBacktrace() << endl; + //} + //else + if ( !d->m_widget ) { + d->m_widget = w; + qDebug("KActionCollection::setWidget: warning: KAccel is never used in microkde"); +//US d->m_kaccel = new KAccel( w, this, "KActionCollection-KAccel" ); + } + else if ( d->m_widget != w ) + kdWarning(129) << "KActionCollection::setWidget(): tried to change widget from " << d->m_widget << " to " << w << endl; +} + +void KActionCollection::setAutoConnectShortcuts( bool b ) +{ + d->m_bAutoConnectShortcuts = b; +} + +bool KActionCollection::isAutoConnectShortcuts() +{ + return d->m_bAutoConnectShortcuts; +} + +bool KActionCollection::addDocCollection( KActionCollection* pDoc ) +{ + d->m_docList.append( pDoc ); + return true; +} + +void KActionCollection::beginXMLPlug( QWidget *widget ) +{ + qDebug("KActionCollection::beginXMLPlug has to be fixed"); +/*US + kdDebug(129) << "KActionCollection::beginXMLPlug( buildWidget = " << widget << " ): this = " << this << " d->m_builderKAccel = " << d->m_builderKAccel << endl; + + if( widget && !d->m_builderKAccel ) { + d->m_builderKAccel = new KAccel( widget, this, "KActionCollection-BuilderKAccel" ); + } +*/ +} + +void KActionCollection::endXMLPlug() +{ + kdDebug(129) << "KActionCollection::endXMLPlug(): this = " << this << endl; + //s_kaccelXML = 0; +} + +void KActionCollection::prepareXMLUnplug() +{ + qDebug("KActionCollection::prepareXMLUnplug has to be fixed"); +/*US + kdDebug(129) << "KActionCollection::prepareXMLUnplug(): this = " << this << endl; + unplugShortcuts( d->m_kaccel ); + + if( d->m_builderKAccel ) { + unplugShortcuts( d->m_builderKAccel ); + delete d->m_builderKAccel; + d->m_builderKAccel = 0; + } +*/ +} + +void KActionCollection::unplugShortcuts( KAccel* kaccel ) +{ + qDebug("KActionCollection::unplugShortcuts has to be fixed"); +/*US + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + pAction->removeKAccel( kaccel ); + } + + for( uint i = 0; i < d->m_docList.count(); i++ ) + d->m_docList[i]->unplugShortcuts( kaccel ); +*/ + +} + +/*void KActionCollection::addWidget( QWidget* w ) +{ + if( !d->m_bOneKAccelOnly ) { + kdDebug(129) << "KActionCollection::addWidget( " << w << " ): this = " << this << endl; + for( uint i = 0; i < d->m_widgetList.count(); i++ ) { + if( d->m_widgetList[i] == w ) { + d->m_iWidgetCurrent = i; + return; + } + } + d->m_iWidgetCurrent = d->m_widgetList.count(); + d->m_widgetList.append( w ); + d->m_kaccelList.append( new KAccel( w, this, "KActionCollection-KAccel" ) ); + } +} + +void KActionCollection::removeWidget( QWidget* w ) +{ + if( !d->m_bOneKAccelOnly ) { + kdDebug(129) << "KActionCollection::removeWidget( " << w << " ): this = " << this << endl; + for( uint i = 0; i < d->m_widgetList.count(); i++ ) { + if( d->m_widgetList[i] == w ) { + // Remove KAccel object from children. + KAccel* pKAccel = d->m_kaccelList[i]; + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + if ( pAction->m_parentCollection == this ) { + pAction->removeKAccel( pKAccel ); + } + } + delete pKAccel; + + d->m_widgetList.remove( d->m_widgetList.at( i ) ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + + if( d->m_iWidgetCurrent == (int)i ) + d->m_iWidgetCurrent = -1; + else if( d->m_iWidgetCurrent > (int)i ) + d->m_iWidgetCurrent--; + return; + } + } + kdWarning(129) << "KActionCollection::removeWidget( " << w << " ): widget not in list." << endl; + } +} + +bool KActionCollection::ownsKAccel() const +{ + return d->m_bOneKAccelOnly; +} + +uint KActionCollection::widgetCount() const +{ + return d->m_widgetList.count(); +} + +const KAccel* KActionCollection::widgetKAccel( uint i ) const +{ + return d->m_kaccelList[i]; +}*/ + +//US we are using no accelerators so far. So just setup an empty implementation. +KAccel* KActionCollection::kaccel() +{ + //if( d->m_kaccelList.count() > 0 ) + // return d->m_kaccelList[d->m_iWidgetCurrent]; + //else + // return 0; +//US return d->m_kaccel; + return 0; +} + +//US we are using no accelerators so far. So just setup an empty implementation. +const KAccel* KActionCollection::kaccel() const +{ + //if( d->m_kaccelList.count() > 0 ) + // return d->m_kaccelList[d->m_iWidgetCurrent]; + //else + // return 0; + //USreturn d->m_kaccel; + return 0; +} + +/*void KActionCollection::findMainWindow( QWidget *w ) +{ + // Note: topLevelWidget() stops too early, we can't use it. + QWidget * tl = w; + while ( tl->parentWidget() ) // lookup parent and store + tl = tl->parentWidget(); + + KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + if (mw) + d->m_mainwindow = mw; + else + kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl; +}*/ + +void KActionCollection::_insert( KAction* action ) +{ + char unnamed_name[100]; + const char *name = action->name(); + if( qstrcmp( name, "unnamed" ) == 0 ) + { + sprintf(unnamed_name, "unnamed-%p", (void *)action); + name = unnamed_name; + } + KAction *a = d->m_actionDict[ name ]; + if ( a == action ) + return; + + d->m_actionDict.insert( name, action ); + + emit inserted( action ); +} + +void KActionCollection::_remove( KAction* action ) +{ + delete _take( action ); +} + +KAction* KActionCollection::_take( KAction* action ) +{ + char unnamed_name[100]; + const char *name = action->name(); + if( qstrcmp( name, "unnamed" ) == 0 ) + { + sprintf(unnamed_name, "unnamed-%p", (void *) action); + name = unnamed_name; + } + + KAction *a = d->m_actionDict.take( name ); + if ( !a || a != action ) + return 0; + + emit removed( action ); + return a; +} + +void KActionCollection::_clear() +{ + QAsciiDictIterator<KAction> it( d->m_actionDict ); + while ( it.current() ) + _remove( it.current() ); +} + +void KActionCollection::insert( KAction* action ) { _insert( action ); } +void KActionCollection::remove( KAction* action ) { _remove( action ); } +KAction* KActionCollection::take( KAction* action ) { return _take( action ); } +void KActionCollection::clear() { _clear(); } +KAccel* KActionCollection::accel() { return kaccel(); } +const KAccel* KActionCollection::accel() const { return kaccel(); } +KAccel* KActionCollection::builderKAccel() const { return d->m_builderKAccel; } + +KAction* KActionCollection::action( const char* name, const char* classname ) const +{ + KAction* pAction = 0; + + if ( !classname && name ) + pAction = d->m_actionDict[ name ]; + + else { + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + { + if ( ( !name || strcmp( it.current()->name(), name ) == 0 ) && + ( !classname || strcmp( it.current()->className(), classname ) == 0 ) ) { + pAction = it.current(); + break; + } + } + } + + if( !pAction ) { + for( uint i = 0; i < d->m_docList.count() && !pAction; i++ ) + pAction = d->m_docList[i]->action( name, classname ); + } + + return pAction; +} + +KAction* KActionCollection::action( int index ) const +{ + QAsciiDictIterator<KAction> it( d->m_actionDict ); + it += index; + return it.current(); +// return d->m_actions.at( index ); +} +/*US +bool KActionCollection::readShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) +{ + return KActionShortcutList(this).readSettings( sConfigGroup, pConfig ); +} + +bool KActionCollection::writeShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) const +{ + return KActionShortcutList((KActionCollection*)this).writeSettings( sConfigGroup, pConfig ); +} +*/ +uint KActionCollection::count() const +{ + return d->m_actionDict.count(); +} + +QStringList KActionCollection::groups() const +{ + QStringList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + if ( !it.current()->group().isEmpty() && !lst.contains( it.current()->group() ) ) + lst.append( it.current()->group() ); + + return lst; +} + +KActionPtrList KActionCollection::actions( const QString& group ) const +{ + KActionPtrList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + if ( it.current()->group() == group ) + lst.append( it.current() ); + else if ( it.current()->group().isEmpty() && group.isEmpty() ) + lst.append( it.current() ); + + return lst; +} + +KActionPtrList KActionCollection::actions() const +{ + KActionPtrList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + lst.append( it.current() ); + + return lst; +} + +/*US we have no instance object. Use KGlobal instead +void KActionCollection::setInstance( KInstance *instance ) +{ + if ( instance ) + d->m_instance = instance; +qDebug("KActionCollection::setInstance has to be fixed"); + else + d->m_instance = KGlobal::instance(); +} + +KInstance *KActionCollection::instance() const +{ + return d->m_instance; +} +*/ + +/*US we have no XML facility in microkde +void KActionCollection::setXMLFile( const QString& sXMLFile ) +{ + d->m_sXMLFile = sXMLFile; +} + +const QString& KActionCollection::xmlFile() const +{ + return d->m_sXMLFile; +} +*/ + +void KActionCollection::setHighlightingEnabled( bool enable ) +{ + d->m_highlight = enable; +} + +bool KActionCollection::highlightingEnabled() const +{ + return d->m_highlight; +} + +void KActionCollection::connectHighlight( QWidget *container, KAction *action ) +{ + if ( !d->m_highlight ) + return; + + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ]; + + if ( !actionList ) + { + actionList = new QPtrList<KAction>; + + if ( container->inherits( "QPopupMenu" ) ) + { + connect( container, SIGNAL( highlighted( int ) ), + this, SLOT( slotMenuItemHighlighted( int ) ) ); + connect( container, SIGNAL( aboutToHide() ), + this, SLOT( slotMenuAboutToHide() ) ); + } +//US else if ( container->inherits( "KToolBar" ) ) + else if ( container->inherits( "QToolBar" ) ) + { + connect( container, SIGNAL( highlighted( int, bool ) ), + this, SLOT( slotToolBarButtonHighlighted( int, bool ) ) ); + } + + connect( container, SIGNAL( destroyed() ), + this, SLOT( slotDestroyed() ) ); + + d->m_dctHighlightContainers.insert( container, actionList ); + } + + actionList->append( action ); +} + +void KActionCollection::disconnectHighlight( QWidget *container, KAction *action ) +{ + if ( !d->m_highlight ) + return; + + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ]; + + if ( !actionList ) + return; + + actionList->removeRef( action ); + + if ( actionList->count() == 0 ) + d->m_dctHighlightContainers.remove( container ); +} + +void KActionCollection::slotMenuItemHighlighted( int id ) +{ + if ( !d->m_highlight ) + return; + + if ( d->m_currentHighlightAction ) + emit actionHighlighted( d->m_currentHighlightAction, false ); + + QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) ); + + d->m_currentHighlightAction = findAction( container, id ); + + if ( !d->m_currentHighlightAction ) + { + if ( !d->m_statusCleared ) + emit clearStatusText(); + d->m_statusCleared = true; + return; + } + + d->m_statusCleared = false; + emit actionHighlighted( d->m_currentHighlightAction ); + emit actionHighlighted( d->m_currentHighlightAction, true ); + emit actionStatusText( d->m_currentHighlightAction->toolTip() ); +} + +void KActionCollection::slotMenuAboutToHide() +{ + if ( d->m_currentHighlightAction ) + emit actionHighlighted( d->m_currentHighlightAction, false ); + d->m_currentHighlightAction = 0; + + if ( !d->m_statusCleared ) + emit clearStatusText(); + d->m_statusCleared = true; +} + +void KActionCollection::slotToolBarButtonHighlighted( int id, bool highlight ) +{ + if ( !d->m_highlight ) + return; + + QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) ); + + KAction *action = findAction( container, id ); + + if ( !action ) + { + d->m_currentHighlightAction = 0; + // use tooltip groups for toolbar status text stuff instead (Simon) +// emit clearStatusText(); + return; + } + + emit actionHighlighted( action, highlight ); + + if ( highlight ) + d->m_currentHighlightAction = action; + else + { + d->m_currentHighlightAction = 0; +// emit clearStatusText(); + } +} + +void KActionCollection::slotDestroyed() +{ + d->m_dctHighlightContainers.remove( reinterpret_cast<void *>( const_cast<QObject *>(sender()) ) ); +} + +KAction *KActionCollection::findAction( QWidget *container, int id ) +{ + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ reinterpret_cast<void *>( container ) ]; + + if ( !actionList ) + return 0; + + QPtrListIterator<KAction> it( *actionList ); + for (; it.current(); ++it ) + if ( it.current()->isPlugged( container, id ) ) + return it.current(); + + return 0; +} + +// KDE 4: remove +KActionCollection KActionCollection::operator+(const KActionCollection &c ) const +{ + kdWarning(129) << "KActionCollection::operator+(): function is severely deprecated." << endl; + KActionCollection ret( *this ); + + QValueList<KAction *> actions = c.actions(); + QValueList<KAction *>::ConstIterator it = actions.begin(); + QValueList<KAction *>::ConstIterator end = actions.end(); + for (; it != end; ++it ) + ret.insert( *it ); + + return ret; +} + +KActionCollection &KActionCollection::operator=( const KActionCollection © ) +{ + kdWarning(129) << "KActionCollection::operator=(): function is severely deprecated." << endl; + //d->m_bOneKAccelOnly = copy.d->m_bOneKAccelOnly; + //d->m_iWidgetCurrent = copy.d->m_iWidgetCurrent; + //d->m_widgetList = copy.d->m_widgetList; + //d->m_kaccelList = copy.d->m_kaccelList; + d->m_widget = copy.d->m_widget; + d->m_kaccel = copy.d->m_kaccel; + d->m_actionDict = copy.d->m_actionDict; +//US setInstance( copy.instance() ); + return *this; +} + +KActionCollection &KActionCollection::operator+=( const KActionCollection &c ) +{ + kdWarning(129) << "KActionCollection::operator+=(): function is severely deprecated." << endl; + QAsciiDictIterator<KAction> it(c.d->m_actionDict); + for ( ; it.current(); ++it ) + insert( it.current() ); + + return *this; +} +// KDE 4: remove end + +//--------------------------------------------------------------------- +// KActionShortcutList +//--------------------------------------------------------------------- +/*US +KActionShortcutList::KActionShortcutList( KActionCollection* pColl ) +: m_actions( *pColl ) + { } +KActionShortcutList::~KActionShortcutList() + { } +uint KActionShortcutList::count() const + { return m_actions.count(); } +QString KActionShortcutList::name( uint i ) const + { return m_actions.action(i)->name(); } +QString KActionShortcutList::label( uint i ) const + { return m_actions.action(i)->text(); } +QString KActionShortcutList::whatsThis( uint i ) const + { return m_actions.action(i)->whatsThis(); } +const KShortcut& KActionShortcutList::shortcut( uint i ) const + { return m_actions.action(i)->shortcut(); } +const KShortcut& KActionShortcutList::shortcutDefault( uint i ) const + { return m_actions.action(i)->shortcutDefault(); } +bool KActionShortcutList::isConfigurable( uint i ) const + { return m_actions.action(i)->isShortcutConfigurable(); } +bool KActionShortcutList::setShortcut( uint i, const KShortcut& cut ) + { return m_actions.action(i)->setShortcut( cut ); } +const KInstance* KActionShortcutList::instance() const + { return m_actions.instance(); } +QVariant KActionShortcutList::getOther( Other, uint ) const + { return QVariant(); } +bool KActionShortcutList::setOther( Other, uint, QVariant ) + { return false; } + +bool KActionShortcutList::save() const +{ + kdDebug(129) << "KActionShortcutList::save(): xmlFile = " << m_actions.xmlFile() << endl; + + if( m_actions.xmlFile().isEmpty() ) + return writeSettings(); + + QString tagActionProp = QString::fromLatin1("ActionProperties"); + QString tagAction = QString::fromLatin1("Action"); + QString attrName = QString::fromLatin1("name"); + QString attrShortcut = QString::fromLatin1("shortcut"); + QString attrAccel = QString::fromLatin1("accel"); // Depricated attribute + + // Read XML file + QString sXml( KXMLGUIFactory::readConfigFile( m_actions.xmlFile(), false, instance() ) ); + QDomDocument doc; + doc.setContent( sXml ); + + // Process XML data + + // first, lets see if we have existing properties + QDomElement elem; + QDomElement it = doc.documentElement(); + // KXMLGUIFactory::removeDOMComments( it ); <-- What was this for? --ellis + it = it.firstChild().toElement(); + for( ; !it.isNull(); it = it.nextSibling().toElement() ) { + if( it.tagName() == tagActionProp ) { + elem = it; + break; + } + } + + // if there was none, create one + if( elem.isNull() ) { + elem = doc.createElement( tagActionProp ); + doc.documentElement().appendChild( elem ); + } + + // now, iterate through our actions + uint nSize = count(); + for( uint i = 0; i < nSize; i++ ) { + const QString& sName = name(i); + + bool bSameAsDefault = (shortcut(i) == shortcutDefault(i)); + //kdDebug(129) << "name = " << sName << " shortcut = " << shortcut(i).toStringInternal() << " def = " << shortcutDefault(i).toStringInternal() << endl; + + // now see if this element already exists + QDomElement act_elem; + for( it = elem.firstChild().toElement(); !it.isNull(); it = it.nextSibling().toElement() ) { + if( it.attribute( attrName ) == sName ) { + act_elem = it; + break; + } + } + + // nope, create a new one + if( act_elem.isNull() ) { + if( bSameAsDefault ) + continue; + //kdDebug(129) << "\tnode doesn't exist." << endl; + act_elem = doc.createElement( tagAction ); + act_elem.setAttribute( attrName, sName ); + } + + act_elem.removeAttribute( attrAccel ); + if( bSameAsDefault ) { + act_elem.removeAttribute( attrShortcut ); + //kdDebug(129) << "act_elem.attributes().count() = " << act_elem.attributes().count() << endl; + if( act_elem.attributes().count() == 1 ) + elem.removeChild( act_elem ); + } else { + act_elem.setAttribute( attrShortcut, shortcut(i).toStringInternal() ); + elem.appendChild( act_elem ); + } + } + + // Write back to XML file + return KXMLGUIFactory::saveConfigFile( doc, m_actions.xmlFile(), instance() ); +} + +//--------------------------------------------------------------------- +// KActionPtrShortcutList +//--------------------------------------------------------------------- + +KActionPtrShortcutList::KActionPtrShortcutList( KActionPtrList& list ) +: m_actions( list ) + { } +KActionPtrShortcutList::~KActionPtrShortcutList() + { } +uint KActionPtrShortcutList::count() const + { return m_actions.count(); } +QString KActionPtrShortcutList::name( uint i ) const + { return m_actions[i]->name(); } +QString KActionPtrShortcutList::label( uint i ) const + { return m_actions[i]->text(); } +QString KActionPtrShortcutList::whatsThis( uint i ) const + { return m_actions[i]->whatsThis(); } +const KShortcut& KActionPtrShortcutList::shortcut( uint i ) const + { return m_actions[i]->shortcut(); } +const KShortcut& KActionPtrShortcutList::shortcutDefault( uint i ) const + { return m_actions[i]->shortcutDefault(); } +bool KActionPtrShortcutList::isConfigurable( uint i ) const + { return m_actions[i]->isShortcutConfigurable(); } +bool KActionPtrShortcutList::setShortcut( uint i, const KShortcut& cut ) + { return m_actions[i]->setShortcut( cut ); } +QVariant KActionPtrShortcutList::getOther( Other, uint ) const + { return QVariant(); } +bool KActionPtrShortcutList::setOther( Other, uint, QVariant ) + { return false; } +bool KActionPtrShortcutList::save() const + { return false; } + +void KActionShortcutList::virtual_hook( int id, void* data ) +{ KShortcutList::virtual_hook( id, data ); } + +void KActionPtrShortcutList::virtual_hook( int id, void* data ) +{ KShortcutList::virtual_hook( id, data ); } +*/ + +void KActionCollection::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/* vim: et sw=2 ts=2 + */ + +/*US +#include "kactioncollection.moc" +*/ diff --git a/microkde/kdeui/kactioncollection.h b/microkde/kdeui/kactioncollection.h new file mode 100644 index 0000000..b9466d0 --- a/dev/null +++ b/microkde/kdeui/kactioncollection.h @@ -0,0 +1,329 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kactioncollection_h__ +#define __kactioncollection_h__ + +#include <kaction.h> + +//US #include <qkeysequence.h> +#include <qobject.h> +//US#include <qvaluelist.h> +//US#include <qguardedptr.h> +//US #include <kguiitem.h> +//US#include <kshortcut.h> +//US#include <kstdaction.h> +//US#include <kicontheme.h> + +//USclass QMenuBar; +//USclass QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +//USclass QIconSet; +//USclass QString; +//USclass KToolBar; + +//USclass KAccel; +//USclass KAccelActions; +//USclass KConfig; +//USclass KConfigBase; +//USclass KURL; +//USclass KInstance; +//USclass KToolBar; +//USclass KActionCollection; +//USclass KPopupMenu; +//USclass KMainWindow; + +//US added inclidefiles +class QWidget; + + +typedef QValueList<KAction *> KActionPtrList; + +/** + * A managed set of KAction objects. + */ +class KActionCollection : public QObject +{ + friend class KAction; + friend class KXMLGUIClient; + + Q_OBJECT +public: + KActionCollection( QWidget *parent, const char *name = 0/*US , KInstance *instance = 0 */); + /** + * Use this constructor if you want the collection's actions to restrict + * their accelerator keys to @p watch rather than the @p parent. If + * you don't require shortcuts, you can pass a null to the @p watch parameter. + */ + KActionCollection( QWidget *watch, QObject* parent, const char *name = 0/*US, KInstance *instance = 0 */); + KActionCollection( const KActionCollection © ); + virtual ~KActionCollection(); + + /** + * This sets the widget to which the keyboard shortcuts should be attached. + * You only need to call this if a null pointer was passed in the constructor. + */ + virtual void setWidget( QWidget *widget ); + + /** + * This indicates whether new actions which are created in this collection + * should have their keyboard shortcuts automatically connected on + * construction. Set to 'false' if you will be loading XML-based settings. + * This is automatically done by KParts. The default is 'true'. + * @see isAutoConnectShortcuts() + */ + void setAutoConnectShortcuts( bool ); + + /** + * This indicates whether new actions which are created in this collection + * have their keyboard shortcuts automatically connected on + * construction. + * @see setAutoConnectShortcuts() + */ + bool isAutoConnectShortcuts(); + + /** + * This sets the default shortcut scope for new actions created in this + * collection. The default is ScopeUnspecified. Ideally the default + * would have been ScopeWidget, but that would cause some backwards + * compatibility problems. + */ + //void setDefaultScope( KAction::Scope ); + + /** + * Doc/View model. This lets you add the action collection of a document + * to a view's action collection. + */ + bool addDocCollection( KActionCollection* pDoc ); + + /** Returns the number of widgets which this collection is associated with. */ + //uint widgetCount() const; + + /** + * Returns true if the collection has its own KAccel object. This will be + * the case if it was constructed with a valid widget ptr or if setWidget() + * was called. + */ + //bool ownsKAccel() const; + + /** @deprecated Deprecated because of ambiguous name. Use kaccel() */ + virtual KAccel* accel(); + /** @deprecated Deprecated because of ambiguous name. Use kaccel() */ + virtual const KAccel* accel() const; + + /** Returns the KAccel object of the most recently set widget. */ + KAccel* kaccel(); + /** Returns the KAccel object of the most recently set widget. Const version for convenience. */ + const KAccel* kaccel() const; + + /** @internal, for KAction::kaccelCurrent() */ + KAccel* builderKAccel() const; + /** Returns the KAccel object associated with widget #. */ + //KAccel* widgetKAccel( uint i ); + //const KAccel* widgetKAccel( uint i ) const; + + /** Returns the number of actions in the collection */ + virtual uint count() const; + bool isEmpty() const { return count() == 0; } + /** + * Return the KAction* at position "index" in the action collection. + * @see count() + */ + virtual KAction* action( int index ) const; + /** + * Find an action (optionally, of a given subclass of KAction) in the action collection. + * @param name Name of the KAction. + * @param classname Name of the KAction subclass. + * @return A pointer to the first KAction in the collection which matches the parameters or + * null if nothing matches. + */ + virtual KAction* action( const char* name, const char* classname = 0 ) const; + + /** Returns a list of all the groups of all the KActions in this action collection. + * @see KAction::group() + * @see KAction::setGroup() + */ + virtual QStringList groups() const; + /** + * Returns the list of actions in a particular managed by this action collection. + * @param group The name of the group. + */ + virtual KActionPtrList actions( const QString& group ) const; + /** Returns the list of actions managed by this action collection. */ + virtual KActionPtrList actions() const; + + /** + * Used for reading shortcut configuration from a non-XML rc file. + */ +//US bool readShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 ); + /** + * Used for writing shortcut configuration to a non-XML rc file. + */ +//US bool writeShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 ) const; + +//US void setInstance( KInstance *instance ); + /** The instance with which this class is associated. */ +//US KInstance *instance() const; + + /** + * Use this to tell the KActionCollection what rc file its configuration + * is stored in. + */ + void setXMLFile( const QString& ); + /** The rc file in which the current configuration is stored. */ + const QString& xmlFile() const; + + /** + * Enable highlighting notification for specific KActions. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see actionHighlighted() + * @see highlightingEnabled() + */ + void setHighlightingEnabled( bool enable ); + /** + * Return whether highlighting notifications are enabled. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see actionHighlighted() + */ + bool highlightingEnabled() const; + + /** + * Call this function if you want to receive a signal whenever a KAction is highlighted in a menu or a toolbar. + * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar) + * @param action The action you are interested in + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + * @see actionHighlighted() + */ + void connectHighlight( QWidget *container, KAction *action ); + /** + * Disconnect highlight notifications for a particular pair of contianer and action. + * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar) + * @param action The action you are interested in + * @see connectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + * @see actionHighlighted() + */ + void disconnectHighlight( QWidget *container, KAction *action ); + +signals: + void inserted( KAction* ); + void removed( KAction* ); + + /** Emitted when "action" is highlighted. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + */ + void actionHighlighted( KAction *action ); + /** Emitted when "action" is highlighed or loses highlighting. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + */ + void actionHighlighted( KAction *action, bool highlight ); + + void actionStatusText( const QString &text ); + void clearStatusText(); + +private: + /** + * @internal Only to be called by KXMLGUIFactory::addClient(). + * When actions are being connected, KAction needs to know what + * widget it should connect widget-scope actions to, and what + * main window it should connect + */ + void beginXMLPlug( QWidget *widget ); + void endXMLPlug(); + /** @internal. Only to be called by KXMLGUIFactory::removeClient() */ + void prepareXMLUnplug(); + void unplugShortcuts( KAccel* kaccel ); + + void _clear(); + void _insert( KAction* ); + void _remove( KAction* ); + KAction* _take( KAction* ); + +private slots: + void slotMenuItemHighlighted( int id ); + void slotToolBarButtonHighlighted( int id, bool highlight ); + void slotMenuAboutToHide(); + void slotDestroyed(); + +private: + KAction *findAction( QWidget *container, int id ); + +#ifndef KDE_NO_COMPAT +public: + KActionCollection( QObject *parent, const char *name = 0 /*US, KInstance *instance = 0 */); + + void insert( KAction* ); + + /** + * @deprecated Removes an action from the collection and deletes it. + * @param action The KAction to remove. + */ + void remove( KAction* action ); + + /** + * @deprecated Removes an action from the collection. + * @return NULL if not found else returns action. + * @param action the KAction to remove. + */ + KAction* take( KAction* action ); + + KActionCollection operator+ ( const KActionCollection& ) const; + KActionCollection& operator= ( const KActionCollection& ); + KActionCollection& operator+= ( const KActionCollection& ); + +public slots: + /** + * Clears the entire actionCollection, deleting all actions. + * @see #remove + */ + void clear(); +#endif // !KDE_NO_COMPAT +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionCollectionPrivate; + KActionCollectionPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kbuttonbox.cpp b/microkde/kdeui/kbuttonbox.cpp new file mode 100644 index 0000000..16206e8 --- a/dev/null +++ b/microkde/kdeui/kbuttonbox.cpp @@ -0,0 +1,300 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * KButtonBox class + * + * A container widget for buttons. Uses Qt layout control to place the + * buttons, can handle both vertical and horizontal button placement. +* + * HISTORY + * + * 03/08/2000 Mario Weilguni <mweilguni@kde.org> + * Removed all those long outdated Motif stuff + * Improved and clarified some if conditions (easier to understand) + * + * 11/13/98 Reginald Stadlbauer <reggie@kde.org> + * Now in Qt 1.4x motif default buttons have no extra width/height anymore. + * So the KButtonBox doesn't add this width/height to default buttons anymore + * which makes the buttons look better. + * + * 01/17/98 Mario Weilguni <mweilguni@sime.com> + * Fixed a bug in sizeHint() + * Improved the handling of Motif default buttons + * + * 01/09/98 Mario Weilguni <mweilguni@sime.com> + * The last button was to far right away from the right/bottom border. + * Fixed this. Removed old code. Buttons get now a minimum width. + * Programmer may now override minimum width and height of a button. + * + */ + +//US #include "kbuttonbox.moc" + +#include <kbuttonbox.h> +#include <qpushbutton.h> +#include <qptrlist.h> +#include <assert.h> + +#define minButtonWidth 50 + +class KButtonBox::Item { +public: + QPushButton *button; + bool noexpand; + unsigned short stretch; + unsigned short actual_size; +}; + +template class QPtrList<KButtonBox::Item>; + +class KButtonBoxPrivate { +public: + unsigned short border; + unsigned short autoborder; + unsigned short orientation; + bool activated; + QPtrList<KButtonBox::Item> buttons; +}; + +KButtonBox::KButtonBox(QWidget *parent, Orientation _orientation, + int border, int autoborder) + : QWidget(parent) +{ + data = new KButtonBoxPrivate; + assert(data != 0); + + data->orientation = _orientation; + data->border = border; + data->autoborder = autoborder < 0 ? border : autoborder; + data->buttons.setAutoDelete(TRUE); +} + +KButtonBox::~KButtonBox() { + delete data; +} + +QPushButton *KButtonBox::addButton(const QString& text, bool noexpand) { + Item *item = new Item; + + item->button = new QPushButton(text, this); + item->noexpand = noexpand; + data->buttons.append(item); + item->button->adjustSize(); + + return item->button; +} + + QPushButton * +KButtonBox::addButton( + const QString & text, + QObject * receiver, + const char * slot, + bool noexpand +) +{ + QPushButton * pb = addButton(text, noexpand); + + if ((0 != receiver) && (0 != slot)) + QObject::connect(pb, SIGNAL(clicked()), receiver, slot); + + return pb; +} + + +void KButtonBox::addStretch(int scale) { + if(scale > 0) { + Item *item = new Item; + item->button = 0; + item->noexpand = FALSE; + item->stretch = scale; + data->buttons.append(item); + } +} + +void KButtonBox::layout() { + // resize all buttons + QSize bs = bestButtonSize(); + + for(unsigned int i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + QPushButton *b = item->button; + if(b != 0) { + if(item->noexpand) + b->setFixedSize(buttonSizeHint(b)); + else + b->setFixedSize(bs); + } + } + + setMinimumSize(sizeHint()); +} + +void KButtonBox::placeButtons() { + unsigned int i; + + if(data->orientation == Horizontal) { + // calculate free size and stretches + int fs = width() - 2 * data->border; + int stretch = 0; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + fs -= item->button->width(); + + // Last button? + if(i != data->buttons.count() - 1) + fs -= data->autoborder; + } else + stretch +=item->stretch; + } + + // distribute buttons + int x_pos = data->border; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + QPushButton *b = item->button; + b->move(x_pos, (height() - b->height()) / 2); + + x_pos += b->width() + data->autoborder; + } else + x_pos += (int)((((double)fs) * item->stretch) / stretch); + } + } else { // VERTICAL + // calcualte free size and stretches + int fs = height() - 2 * data->border; + int stretch = 0; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) + fs -= item->button->height() + data->autoborder; + else + stretch +=item->stretch; + } + + // distribute buttons + int y_pos = data->border; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + QPushButton *b = item->button; + b->move((width() - b->width()) / 2, y_pos); + + y_pos += b->height() + data->autoborder; + } else + y_pos += (int)((((double)fs) * item->stretch) / stretch); + } + } +} + +void KButtonBox::resizeEvent(QResizeEvent *) { + placeButtons(); +} + +QSize KButtonBox::bestButtonSize() const { + QSize s(0, 0); + unsigned int i; + + // calculate optimal size + for(i = 0; i < data->buttons.count(); i++) { + KButtonBox *that = (KButtonBox*)this; // to remove the const ;( + Item *item = that->data->buttons.at(i); + QPushButton *b = item->button; + + if(b != 0 && !item->noexpand) { + QSize bs = buttonSizeHint(b); + + if(bs.width() > s.width()) + s.setWidth(bs.width()); + if(bs.height() > s.height()) + s.setHeight(bs.height()); + } + } + + return s; +} + +QSize KButtonBox::sizeHint() const { + unsigned int i, dw; + + if(data->buttons.count() == 0) + return QSize(0, 0); + else { + dw = 2 * data->border; + + QSize bs = bestButtonSize(); + for(i = 0; i < data->buttons.count(); i++) { + KButtonBox *that = (KButtonBox*)this; + Item *item = that->data->buttons.at(i); + QPushButton *b = item->button; + if(b != 0) { + QSize s; + if(item->noexpand) + s = that->buttonSizeHint(b); + else + s = bs; + + if(data->orientation == Horizontal) + dw += s.width(); + else + dw += s.height(); + + if( i != data->buttons.count() - 1 ) + dw += data->autoborder; + } + } + + if(data->orientation == Horizontal) + return QSize(dw, bs.height() + 2 * data->border); + else + return QSize(bs.width() + 2 * data->border, dw); + } +} + +QSizePolicy KButtonBox::sizePolicy() const +{ + return data->orientation == Horizontal? + QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) : + QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ); +} + +/* + * Returns the best size for a button. If a button is less than + * minButtonWidth pixels wide, return minButtonWidth pixels + * as minimum width + */ +QSize KButtonBox::buttonSizeHint(QPushButton *b) const { + QSize s = b->sizeHint(); + QSize ms = b->minimumSize(); + if(s.width() < minButtonWidth) + s.setWidth(minButtonWidth); + + // allows the programmer to override the settings + if(ms.width() > s.width()) + s.setWidth(ms.width()); + if(ms.height() > s.height()) + s.setHeight(ms.height()); + + return s; +} + +void KButtonBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdeui/kbuttonbox.h b/microkde/kdeui/kbuttonbox.h new file mode 100644 index 0000000..1104366 --- a/dev/null +++ b/microkde/kdeui/kbuttonbox.h @@ -0,0 +1,139 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __KBUTTONBOX__H__ +#define __KBUTTONBOX__H__ + +#include <qwidget.h> +class QPushButton; + +class KButtonBoxPrivate; +/** + * Container widget for buttons. + * + * This class uses Qt layout control to place the buttons; can handle + * both vertical and horizontal button placement. The default border + * is now @p 0 (making it easier to deal with layouts). The space + * between buttons is now more Motif compliant. + * + * @author Mario Weilguni <mweilguni@sime.com> + * @version $Id$ + **/ + +class KButtonBox : public QWidget +{ + Q_OBJECT + +public: + /** + * Create an empty container for buttons. + * + * If @p _orientation is @p Vertical, the buttons inserted with + * @ref addButton() are laid out from top to bottom, otherwise they + * are laid out from left to right. + */ + KButtonBox(QWidget *parent, Orientation _orientation = Horizontal, + int border = 0, int _autoborder = 6); + + /** + * Free private data field + */ + ~KButtonBox(); + + /** + * @return The minimum size needed to fit all buttons. + * + * This size is + * calculated by the width/height of all buttons plus border/autoborder. + */ + virtual QSize sizeHint() const; + /** + * @reimplemented + */ + virtual QSizePolicy sizePolicy() const; + /** + * @reimplemented + */ + virtual void resizeEvent(QResizeEvent *); + + /** + * Add a new @ref QPushButton. + * + * @param noexpand If @p noexpand is @p false, the width + * of the button is adjusted to fit the other buttons (the maximum + * of all buttons is taken). If @p noexpand is @p true, the width of this + * button will be set to the minimum width needed for the given text). + * + * @return A pointer to the new button. + */ + QPushButton *addButton(const QString& text, bool noexpand = FALSE); + + /** + * Add a new @ref QPushButton. + * + * @param receiver An object to connect to. + * @param slot A Qt slot to connect the 'clicked()' signal to. + * @param noexpand If @p noexpand is @p false, the width + * of the button is adjusted to fit the other buttons (the maximum + * of all buttons is taken). If @p noexpand @p true, the width of this + * button will be set to the minimum width needed for the given text). + * + * @return A pointer to the new button. + */ + QPushButton *addButton(const QString& text, QObject * receiver, const char * slot, bool noexpand = FALSE); + + /** + * Add a stretch to the buttonbox. + * + * Can be used to separate buttons. That is, if you add the + * buttons OK and Cancel, add a stretch, and then add the button Help, + * the buttons OK and Cancel will be left-aligned (or top-aligned + * for vertical) whereas Help will be right-aligned (or + * bottom-aligned for vertical). + * + * @see QBoxLayout + */ + void addStretch(int scale = 1); + + /** + * This function must be called @em once after all buttons have been + * inserted. + * + * It will start layout control. + */ + void layout(); + +public: // as PrivateData needs Item, it has to be exported + class Item; +protected: + /** + * @return the best size for a button. Checks all buttons and takes + * the maximum width/height. + */ + QSize bestButtonSize() const; + void placeButtons(); + QSize buttonSizeHint(QPushButton *) const; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KButtonBoxPrivate *data; +}; + +#endif diff --git a/microkde/kdeui/kcmodule.cpp b/microkde/kdeui/kcmodule.cpp new file mode 100644 index 0000000..915cd0f --- a/dev/null +++ b/microkde/kdeui/kcmodule.cpp @@ -0,0 +1,106 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2001 Michael Goffioul <goffioul@imec.be> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include "kcmodule.h" +//US#include <kinstance.h> +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +class KCModulePrivate +{ +public: +//US KInstance *_instance; + QString _rootOnlyMsg; + bool _useRootOnlyMsg; + bool _hasOwnInstance; +}; + +KCModule::KCModule(QWidget *parent, const char *name, const QStringList &) + : QWidget(parent, name), _btn(Help|Default|Apply) +{ + kdDebug() << "KCModule " << name << endl; + d = new KCModulePrivate; + d->_useRootOnlyMsg = true; +/*US + d->_instance = new KInstance(name); + if (name && strlen(name)) { + d->_instance = new KInstance(name); + KGlobal::locale()->insertCatalogue(name); + } else + d->_instance = new KInstance("kcmunnamed"); +*/ + d->_hasOwnInstance = true; +//US KGlobal::setActiveInstance(this->instance()); +} + +/*US +KCModule::KCModule(KInstance *instance, QWidget *parent, const QStringList & ) + : QWidget(parent, instance ? instance->instanceName().data() : 0), _btn(Help|Default|Apply) +{ + kdDebug() << "KCModule instance " << (instance ? instance->instanceName().data() : "none") << endl; + d = new KCModulePrivate; + d->_useRootOnlyMsg = true; + d->_instance = instance; + KGlobal::locale()->insertCatalogue(instance->instanceName()); + d->_hasOwnInstance = false; + KGlobal::setActiveInstance(this->instance()); +} +*/ +KCModule::~KCModule() +{ +/*US + if (d->_hasOwnInstance) + delete d->_instance; +*/ + delete d; +} + +void KCModule::setRootOnlyMsg(const QString& msg) +{ + d->_rootOnlyMsg = msg; +} + +QString KCModule::rootOnlyMsg() const +{ + return d->_rootOnlyMsg; +} + +void KCModule::setUseRootOnlyMsg(bool on) +{ + d->_useRootOnlyMsg = on; +} + +bool KCModule::useRootOnlyMsg() const +{ + return d->_useRootOnlyMsg; +} +/*US +KInstance *KCModule::instance() const +{ + return d->_instance; +} +*/ +void KCModule::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "kcmodule.moc" diff --git a/microkde/kdeui/kcmodule.h b/microkde/kdeui/kcmodule.h new file mode 100644 index 0000000..90a87c9 --- a/dev/null +++ b/microkde/kdeui/kcmodule.h @@ -0,0 +1,266 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +#ifndef __KCMODULE_H__ +#define __KCMODULE_H__ + +#include <qwidget.h> +#include <qstringlist.h> +//USclass KAboutData; +class KCModulePrivate; +//US class KInstance; + +/** + * The base class for control center modules. + * + * Starting from KDE 2.0, control center modules are realized as shared + * libraries that are loaded into the control center at runtime. + * + * The module in principle is a simple widget displaying the + * item to be changed. The module has a very small interface. + * + * All the necessary glue logic and the GUI bells and whistles + * are provided by the control center and must not concern + * the module author. + * + * To write a config module, you have to create a library + * that contains at one factory function like this: + * + * <pre> + * #include <kgenericfactory.h> + * + * typedef KGenericFactory<YourKCModule, QWidget> YourKCModuleFactory; + * K_EXPORT_COMPONENT_FACTORY( yourLibName, YourKCModuleFactory("name_of_the_po_file") ); + * </pre> + * + * The parameter "name_of_the_po_file" has to correspond with the messages target + * that you created in your Makefile.am. + * + * See kdebase/kcontrol/HOWTO for more detailed documentation. + * + * @author Matthias Hoelzer-Kluepfel <hoelzer@kde.org> + */ + +class KCModule : public QWidget +{ + Q_OBJECT + +public: + + /** + * An enumeration type for the buttons used by this module. + * You should only use Help, Default and Apply. The rest is obsolete. + * + * @see KCModule::buttons @see KCModule::setButtons + */ + enum Button {Help=1, Default=2, Apply=16, + Reset=4, /* obsolete, do not use! */ + Cancel=8, /* obsolete, do not use! */ + Ok=32, /* obsolete, do not use! */ + SysDefault=64 /* obsolete, do not use! */ }; + + /* + * Base class for all KControlModules. + * Make sure you have a QStringList argument in your + * implementation. + */ + KCModule(QWidget *parent=0, const char *name=0, const QStringList &args=QStringList() ); + +//US KCModule(KInstance *instance, QWidget *parent=0, const QStringList &args=QStringList() ); + + /* + * Destroys the module. + */ + ~KCModule(); + + /** + * Load the configuration data into the module. + * + * The load method sets the user interface elements of the + * module to reflect the current settings stored in the + * configuration files. + * + * This method is invoked whenever the module should read its configuration + * (most of the times from a config file) and update the user interface. + * This happens when the user clicks the "Reset" button in the control + * center, to undo all of his changes and restore the currently valid + * settings. NOTE that this is not called after the modules is loaded, + * so you probably want to call this method in the constructor. + */ + virtual void load() {}; + + /** + * Save the configuration data. + * + * The save method stores the config information as shown + * in the user interface in the config files. + * + * If necessary, this method also updates the running system, + * e.g. by restarting applications. + * + * save is called when the user clicks "Apply" or "Ok". + */ + virtual void save() {}; + + /** + * Sets the configuration to sensible default values. + * + * This method is called when the user clicks the "Default" + * button. It should set the display to useful values. + */ + virtual void defaults() {}; + + /** + * Set the configuration to system default values. + * + * This method is called when the user clicks the "System-Default" + * button. It should set the display to the system default values. + * + * NOTE: The default behaviour is to call defaults(). + */ + virtual void sysdefaults() { defaults(); }; + + /** + * Return a quick-help text. + * + * This method is called when the module is docked. + * The quick-help text should contain a short description of the module and + * links to the module's help files. You can use QML formating tags in the text. + * + * NOTE: Please make sure the quick help text gets translated (use i18n()). + */ + virtual QString quickHelp() const { return QString::null; }; + + /** + * Returns a the KAboutData for this module + * This is generally only called for the KBugReport. + * Override and have it return a pointer to a constant + */ +//US virtual const KAboutData *aboutData() const { return 0; } + + /** + * Indicate which buttons will be used. + * + * The return value is a value or'ed together from + * the Button enumeration type. + * + * @see KCModule::setButtons + */ + int buttons() const { return _btn; }; + + /** + * Get the RootOnly message for this module. + * + * When the module must be run as root, or acts differently + * for root and a normal user, it is sometimes useful to + * customize the message that appears at the top of the module + * when used as a normal user. This function returns this + * customized message. If none has been set, a default message + * will be used. + * + * @see KCModule::setRootOnlyMsg + */ + QString rootOnlyMsg() const; + + /** + * Tell if KControl should show a RootOnly message when run as + * a normal user. + * + * In some cases, the module don't want a RootOnly message to + * appear (for example if it has already one). This function + * tells KControl if a RootOnly message should be shown + * + * @see KCModule::setUseRootOnlyMsg + */ + bool useRootOnlyMsg() const; + + +//US KInstance *instance() const; + +signals: + + /** + * Indicate that the state of the modules contents has changed. + * + * This signal is emitted whenever the state of the configuration + * shown in the module changes. It allows the control center to + * keep track of unsaved changes. + * + */ + void changed(bool state); + + /** + * Indicate that the module's quickhelp has changed. + * + * Emit this signal whenever the module's quickhelp changes. + * Modules implemented as tabbed dialogs might want to implement + * per-tab quickhelp for example. + * + */ + void quickHelpChanged(); + +protected: + + /** + * Sets the buttons to display. + * + * Help: shows a "Help" button. + * Default: shows a "Use Defaults" button + * Apply: in kcontrol this will show an "Apply" and "Reset" button + * in kcmshell this will show an "Ok", "Apply" and "Cancel" button + * + * If Apply is not specified, kcmshell will show a "Close" button. + * + * @see KCModule::buttons + */ + void setButtons(int btn) { _btn = btn; }; + + /** + * Sets the RootOnly message. + * + * This message will be shown at the top of the module of the + * corresponding desktop file contains the line X-KDE-RootOnly=true. + * If no message is set, a default one will be used. + * + * @see KCModule::rootOnlyMessage + */ + void setRootOnlyMsg(const QString& msg); + + /** + * Change wether or not the RootOnly message should be shown. + * + * Following the value of @p on, the RootOnly message will be + * shown or not. + * + * @see KCModule::useRootOnlyMsg + */ + void setUseRootOnlyMsg(bool on); + +private: + + int _btn; +protected: + virtual void virtual_hook( int id, void* data ); +private: + KCModulePrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kguiitem.cpp b/microkde/kdeui/kguiitem.cpp new file mode 100644 index 0000000..828c5e6 --- a/dev/null +++ b/microkde/kdeui/kguiitem.cpp @@ -0,0 +1,205 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 Holger Freyther (freyher@yahoo.com) + based on ideas from Martijn and Simon + many thanks to Simon + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qregexp.h> +#include <qstring.h> +#include <qiconset.h> +#include <qpixmap.h> + +#include <assert.h> +//US #include <kiconloader.h> +#include <kdebug.h> + +#include "kguiitem.h" + +class KGuiItem::KGuiItemPrivate +{ +public: + KGuiItemPrivate() + { + m_enabled = true; + m_hasIcon = false; + } + + KGuiItemPrivate( const KGuiItemPrivate &rhs ) + { + (*this ) = rhs; + } + + KGuiItemPrivate &operator=( const KGuiItemPrivate &rhs ) + { + m_text = rhs.m_text; + m_iconSet = rhs.m_iconSet; + m_iconName = rhs.m_iconName; + m_toolTip = rhs.m_toolTip; + m_whatsThis = rhs.m_whatsThis; + m_statusText = rhs.m_statusText; + m_enabled = rhs.m_enabled; + m_hasIcon = rhs.m_hasIcon; + + return *this; + } + + QString m_text; + QString m_toolTip; + QString m_whatsThis; + QString m_statusText; + QString m_iconName; + QIconSet m_iconSet; + bool m_hasIcon : 1; + bool m_enabled : 1; +}; + + +KGuiItem::KGuiItem() { + d = new KGuiItemPrivate; +} + +KGuiItem::KGuiItem( const QString &text, const QString &iconName, + const QString &toolTip, const QString &whatsThis ) +{ + d = new KGuiItemPrivate; + d->m_text = text; + d->m_toolTip = toolTip; + d->m_whatsThis = whatsThis; + setIconName( iconName ); +} + +KGuiItem::KGuiItem( const QString &text, const QIconSet &iconSet, + const QString &toolTip, const QString &whatsThis ) +{ + d = new KGuiItemPrivate; + d->m_text = text; + d->m_toolTip = toolTip; + d->m_whatsThis = whatsThis; + setIconSet( iconSet ); +} + +KGuiItem::KGuiItem( const KGuiItem &rhs ) + : d( 0 ) +{ + (*this) = rhs; +} + +KGuiItem &KGuiItem::operator=( const KGuiItem &rhs ) { + if ( d == rhs.d ) + return *this; + + assert( rhs.d ); + + delete d; + d = new KGuiItemPrivate( *rhs.d ); + + return *this; +} + +KGuiItem::~KGuiItem() { + delete d; +} + +QString KGuiItem::text() const { + return d->m_text; +} +QString KGuiItem::plainText() const { + QString stripped( d->m_text ); + stripped.replace( QRegExp( "&(?!&)" ), QString::null ); + + return stripped; +} + +QIconSet KGuiItem::iconSet( KIcon::Group group, int size /*US, KInstance* instance */ ) const +{ + if( d->m_hasIcon ) + { + if( !d->m_iconName.isEmpty()) + { +// some caching here would(?) come handy +//US return instance->iconLoader()->loadIconSet( d->m_iconName, group, size ); + return KGlobal::iconLoader()->loadIconSet( d->m_iconName); +// here is a little problem that with delayed icon loading +// we can't check if the icon really exists ... so what ... +// if( set.isNull() ) +// { +// d->m_hasIcon = false; +// return QIconSet(); +// } +// return set; + } + else + { + return d->m_iconSet; + } + } + else + return QIconSet(); +} + +QString KGuiItem::iconName() const +{ + return d->m_iconName; +} + +QString KGuiItem::toolTip() const { + return d->m_toolTip; +} +QString KGuiItem::whatsThis() const { + return d->m_whatsThis; +} + +bool KGuiItem::isEnabled() const +{ + return d->m_enabled; +} + +bool KGuiItem::hasIcon() const +{ + return d->m_hasIcon; +} + +void KGuiItem::setText( const QString &text ) { + d->m_text=text; +} + +void KGuiItem::setIconSet( const QIconSet &iconset ) +{ + d->m_iconSet = iconset; + d->m_iconName = QString::null; + d->m_hasIcon = !iconset.isNull(); +} + +void KGuiItem::setIconName( const QString &iconName ) +{ + d->m_iconName = iconName; + d->m_iconSet = QIconSet(); + d->m_hasIcon = !iconName.isEmpty(); +} + +void KGuiItem::setToolTip( const QString &toolTip) { + d->m_toolTip = toolTip; +} +void KGuiItem::setWhatsThis( const QString &whatsThis ) { + d->m_whatsThis = whatsThis; +} +void KGuiItem::setEnabled( bool enabled ){ + d->m_enabled = enabled; +} + +/* vim: et sw=4 + */ diff --git a/microkde/kdeui/kguiitem.h b/microkde/kdeui/kguiitem.h new file mode 100644 index 0000000..0079bb4 --- a/dev/null +++ b/microkde/kdeui/kguiitem.h @@ -0,0 +1,87 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 Holger Freyther (freyher@yahoo.com) + based on ideas from Martijn and Simon + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Many thanks to Simon tronical Hausmann +*/ + +#ifndef __kguiitem_h__ +#define __kguiitem_h__ + +#include <qstring.h> +#include <qiconset.h> +#include <qpixmap.h> +#include <qvaluelist.h> +//US#include <kicontheme.h> +#include <kglobal.h> + +//US added the following files +#include <kiconloader.h> + +class KGuiItem +{ +public: + KGuiItem(); + + KGuiItem( const QString &text, + const QString &iconName = QString::null, + const QString &toolTip = QString::null, + const QString &whatsThis = QString::null ); + + KGuiItem( const QString &text, const QIconSet &iconSet, + const QString &toolTip = QString::null, + const QString &whatsThis = QString::null ); + + KGuiItem( const KGuiItem &rhs ); + KGuiItem &operator=( const KGuiItem &rhs ); + + ~KGuiItem(); + + QString text() const; + QString plainText() const; + QIconSet iconSet( KIcon::Group, int size = 0/*US , KInstance* instance = KGlobal::instance()*/) const; + +#ifndef KDE_NO_COMPAT + QIconSet iconSet() const { return iconSet( KIcon::Small); } +#endif + + QString iconName() const; + QString toolTip() const; + QString whatsThis() const; + bool isEnabled() const; + bool hasIcon() const; +#ifndef KDE_NO_COMPAT + bool hasIconSet() const { return hasIcon(); } +#endif + + void setText( const QString &text ); + void setIconSet( const QIconSet &iconset ); + void setIconName( const QString &iconName ); + void setToolTip( const QString &tooltip ); + void setWhatsThis( const QString &whatsThis ); + void setEnabled( bool enable ); + +private: + class KGuiItemPrivate; + KGuiItemPrivate *d; +}; + +/* vim: et sw=4 + */ + +#endif + diff --git a/microkde/kdeui/kjanuswidget.cpp b/microkde/kdeui/kjanuswidget.cpp new file mode 100644 index 0000000..7d25854 --- a/dev/null +++ b/microkde/kdeui/kjanuswidget.cpp @@ -0,0 +1,1176 @@ +/* This file is part of the KDE Libraries + * Copyright (C) 1999-2000 Espen Sand (espensa@online.no) + * Copyright (C) 2003 Ravikiran Rajagopal (ravi@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <qpixmap.h> +#include <qbitmap.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qwidgetstack.h> +#include <qtabwidget.h> +#include <qlistview.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qgrid.h> +#include <qpainter.h> +#include <qobjectlist.h> + +/*US +#include <qbitmap.h> +#include <qgrid.h> +#include <qhbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qpixmap.h> +#include <qsplitter.h> +#include <qtabwidget.h> +#include <qvbox.h> +#include <qwidgetstack.h> +#include <qpainter.h> +#include <qstyle.h> + +#include <kapplication.h> +#include <klocale.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kseparator.h> +#include <kdebug.h> +#include "kjanuswidget.h" +#include <klistview.h> + +*/ + +#include <kseparator.h> +#include <kdialog.h> // Access to some static members +#include <kdebug.h> +#include <klistview.h> + +#include "kjanuswidget.h" + +class KJanusWidget::IconListItem : public QListBoxItem +{ + public: + IconListItem( QListBox *listbox, const QPixmap &pixmap, + const QString &text ); + virtual int height( const QListBox *lb ) const; + virtual int width( const QListBox *lb ) const; + int expandMinimumWidth( int width ); + + protected: + const QPixmap &defaultPixmap(); + void paint( QPainter *painter ); + + private: + QPixmap mPixmap; + int mMinimumWidth; +}; + +class KJanusWidget::KJanusWidgetPrivate +{ +public: + KJanusWidgetPrivate() : mNextPageIndex(0) { } + + int mNextPageIndex; // The next page index. + + // Dictionary for multipage modes. + QMap<int,QWidget*> mIntToPage; + // Reverse dictionary. Used because showPage() may be performance critical. + QMap<QWidget*,int> mPageToInt; + // Dictionary of title string associated with page. + QMap<int, QString> mIntToTitle; +}; + +template class QPtrList<QListViewItem>; + + +KJanusWidget::KJanusWidget( QWidget *parent, const char *name, int face ) + : QWidget( parent, name ), + mValid(false), mPageList(0), + mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0), + mShowIconsInTreeList(false), d(0) +{ + QVBoxLayout *topLayout = new QVBoxLayout( this ); + if( mFace == TreeList || mFace == IconList ) + { + d = new KJanusWidgetPrivate; + + QFrame *page = 0; + if( mFace == TreeList ) + { + //US + qDebug("KJanusWidget::KJanusWidget TreeList not implemented yet"); +/*US + QSplitter *splitter = new QSplitter( this ); + topLayout->addWidget( splitter, 10 ); + mTreeListResizeMode = QSplitter::KeepSize; + + mTreeList = new KListView( splitter ); + mTreeList->addColumn( QString::null ); + mTreeList->header()->hide(); + mTreeList->setRootIsDecorated(true); + mTreeList->setSorting( -1 ); + connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) ); + connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *))); + + // + // Page area. Title at top with a separator below and a pagestack using + // all available space at bottom. + // + QFrame *p = new QFrame( splitter ); + + QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 ); + hbox->addSpacing( KDialog::marginHint() ); + + page = new QFrame( p ); + hbox->addWidget( page, 10 ); +*/ + } + else + { + QHBoxLayout *hbox = new QHBoxLayout( topLayout ); + mIconList = new IconListBox( this ); + + QFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + + mIconList->verticalScrollBar()->installEventFilter( this ); + hbox->addWidget( mIconList ); + connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage())); + hbox->addSpacing( KDialog::marginHint() ); + page = new QFrame( this ); + hbox->addWidget( page, 10 ); + } + + // + // Rest of page area. Title at top with a separator below and a + // pagestack using all available space at bottom. + // + + QVBoxLayout *vbox = new QVBoxLayout( page, 0, KDialog::spacingHint() ); + + mTitleLabel = new QLabel( QString::fromLatin1("Empty page"), page, "KJanusWidgetTitleLabel" ); + vbox->addWidget( mTitleLabel ); + + QFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + + mTitleSep = new KSeparator( page ); + mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain ); + vbox->addWidget( mTitleSep ); + + mPageStack = new QWidgetStack( page ); + connect(mPageStack, SIGNAL(aboutToShow(QWidget *)), + SIGNAL(aboutToShowPage(QWidget *))); + vbox->addWidget( mPageStack, 10 ); + } + else if( mFace == Tabbed ) + { + d = new KJanusWidgetPrivate; + + mTabControl = new QTabWidget( this ); + mTabControl->setMargin (KDialog::marginHint()); + topLayout->addWidget( mTabControl, 10 ); + } + else if( mFace == Swallow ) + { + mSwallowPage = new QWidget( this ); + topLayout->addWidget( mSwallowPage, 10 ); + } + else + { + mFace = Plain; + mPlainPage = new QFrame( this ); + topLayout->addWidget( mPlainPage, 10 ); + } +/*US + if ( kapp ) + connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged())); +*/ + mValid = true; + setSwallowedWidget(0); // Set default size if 'mFace' is Swallow. +} + + +KJanusWidget::~KJanusWidget() +{ + +/*US the destroyed signal caused a segmentation fault while closing the dialog and destructing + all pages. Why not just remove all pages in the destructor?? +*/ +// LR we have all subwidgets with parent-child relation +// LR we do not need to delete here anything by the private class +/* + if( mFace == Tabbed ) + { + QMap<QWidget*,int>::Iterator it; + for (it = d->mPageToInt.begin(); it != d->mPageToInt.end(); ++it) { + QObject*page = (QObject*)it.key(); + pageGone(page); + } + } + else + qDebug("KJanusWidget::~KJanusWidget so far "); +*/ +//US end + + delete d; + + +} + + +bool KJanusWidget::isValid() const +{ + return( mValid ); +} + + +QFrame *KJanusWidget::plainPage() +{ + return( mPlainPage ); +} + + +int KJanusWidget::face() const +{ + return( mFace ); +} + +QWidget *KJanusWidget::FindParent() +{ + if( mFace == Tabbed ) { + return mTabControl; + } + else { + return this; + } +} + +QFrame *KJanusWidget::addPage( const QStringList &items, const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QFrame *page = new QFrame( FindParent(), "page" ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +void KJanusWidget::pageGone( QObject *obj ) +{ +// QObject* obj = (QObject*)sender(); + removePage( static_cast<QWidget*>( obj ) ); +} + +void KJanusWidget::slotReopen( QListViewItem * item ) +{ + if( item ) + item->setOpen( true ); +} + +QFrame *KJanusWidget::addPage( const QString &itemName, const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addPage(items, header, pixmap); +} + + + +QVBox *KJanusWidget::addVBoxPage( const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + qDebug("addPage: Invalid object "); + + return( 0 ); + } + + QVBox *page = new QVBox(FindParent() , "vbox_page" ); + page->setSpacing( KDialog::spacingHintSmall() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +QVBox *KJanusWidget::addVBoxPage( const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addVBoxPage(items, header, pixmap); +} + +QHBox *KJanusWidget::addHBoxPage( const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QHBox *page = new QHBox(FindParent(), "hbox_page"); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +QHBox *KJanusWidget::addHBoxPage( const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addHBoxPage(items, header, pixmap); +} + +QGrid *KJanusWidget::addGridPage( int n, QGrid::Direction dir, + const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QGrid *page = new QGrid( n, dir, FindParent(), "page" ); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + + +QGrid *KJanusWidget::addGridPage( int n, QGrid::Direction dir, + const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addGridPage(n, dir, items, header, pixmap); +} + +void KJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page) +{ + bool isTop = true; + QListViewItem *curTop = 0, *child, *last, *newChild; + unsigned int index = 1; + QStringList curPath; + + for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) { + QString name = (*it); + bool isPath = ( index != items.count() ); + + // Find the first child. + if (isTop) { + child = mTreeList->firstChild(); + } + else { + child = curTop->firstChild(); + } + + // Now search for a child with the current Name, and if it we doesn't + // find it, then remember the location of the last child. + for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling()); + + if (last == 0 && child == 0) { + // This node didn't have any children at all, lets just insert the + // new child. + if (isTop) + newChild = new QListViewItem(mTreeList, name); + else + newChild = new QListViewItem(curTop, name); + + } + else if (child != 0) { + // we found the given name in this child. + if (!isPath) { + kdDebug() << "The element inserted was already in the TreeList box!" << endl; + return; + } + else { + // Ok we found the folder + newChild = child; + } + } + else { + // the node had some children, but we didn't find the given name + if (isTop) + newChild = new QListViewItem(mTreeList, last, name); + else + newChild = new QListViewItem(curTop, last, name); + } + + // Now make the element expandable if it is a path component, and make + // ready for next loop + if (isPath) { + newChild->setExpandable(true); + curTop = newChild; + isTop = false; + curPath << name; + + QString key = curPath.join("_/_"); + if (mFolderIconMap.contains(key)) { + QPixmap p = mFolderIconMap[key]; + newChild->setPixmap(0,p); + } + } + else { + if (mShowIconsInTreeList) { + newChild->setPixmap(0, pixmap); + } + mTreeListToPageStack.insert(newChild, page); + } + } +} + +void KJanusWidget::addPageWidget( QFrame *page, const QStringList &items, + const QString &header,const QPixmap &pixmap ) +{ +/*US the following signal causes a segmentation fault while closing the dialog. + Why not just remove all pages in the destructor?? +*/ +//US connect(page, SIGNAL(destroyed(QObject*)), this, SLOT(pageGone(QObject*))); +// we have the SIGNAL(destroyed(QObject*) only in Qt3 +#ifdef DESKTOP_VERSION + // connect(page, SIGNAL(destroyed(QObject*)), this, SLOT(pageGone(QObject*))); +#endif + if( mFace == Tabbed ) + { + mTabControl->addTab (page, items.last()); + d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page); + d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex; + d->mNextPageIndex++; + } + else if( mFace == TreeList || mFace == IconList ) + { + d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page); + d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex; + mPageStack->addWidget( page, 0 ); + + if (items.count() == 0) { + kdDebug() << "Invalid QStringList, with zero items" << endl; + return; + } + + if( mFace == TreeList ) + { + InsertTreeListItem(items, pixmap, page); + } + else // mFace == IconList + { + QString itemName = items.last(); + IconListItem *item = new IconListItem( mIconList, pixmap, itemName ); + mIconListToPageStack.insert(item, page); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + + if (mIconList->isVisible()) + mIconList->updateWidth(); + } + + // + // Make sure the title label is sufficiently wide + // + QString lastName = items.last(); + const QString &title = (!header.isNull() ? header : lastName); + QRect r = mTitleLabel->fontMetrics().boundingRect( title ); + if( mTitleLabel->minimumWidth() < r.width() ) + { + mTitleLabel->setMinimumWidth( r.width() ); + } + d->mIntToTitle[d->mNextPageIndex] = title; + if( d->mIntToTitle.count() == 1 ) + { + showPage(0); + } + d->mNextPageIndex++; + } + else + { + kdDebug() << "KJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" << endl; + } + +} + +void KJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap) +{ + QString key = path.join("_/_"); + mFolderIconMap.insert(key,pixmap); +} + + + +bool KJanusWidget::setSwallowedWidget( QWidget *widget ) +{ + if( mFace != Swallow || mValid == false ) + { + return( false ); + } + + // + // Remove current layout and make a new. + // + if( mSwallowPage->layout() != 0 ) + { + delete mSwallowPage->layout(); + } + QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 ); + + // + // Hide old children + // + QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please + for( uint i=0; i < l->count(); i++ ) + { + QObject *o = l->at(i); + if( o->isWidgetType() ) + { + ((QWidget*)o)->hide(); + } + } + + // + // Add new child or make default size + // + if( widget == 0 ) + { + gbox->addRowSpacing(0,100); + gbox->addColSpacing(0,100); + mSwallowPage->setMinimumSize(100,100); + } + else + { + if( widget->parent() != mSwallowPage ) + { + widget->reparent( mSwallowPage, 0, QPoint(0,0) ); + } + gbox->addWidget(widget, 0, 0 ); + gbox->activate(); + mSwallowPage->setMinimumSize( widget->minimumSize() ); + } + + return( true ); +} + +bool KJanusWidget::slotShowPage() +{ + if( mValid == false ) + { + return( false ); + } + + if( mFace == TreeList ) + { + QListViewItem *node = mTreeList->selectedItem(); + if( node == 0 ) { return( false ); } + + QWidget *stackItem = mTreeListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + else if( mFace == IconList ) + { + QListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( node == 0 ) { return( false ); } + QWidget *stackItem = mIconListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + + return( false ); +} + + +bool KJanusWidget::showPage( int index ) +{ + if( d == 0 || mValid == false ) + { + return( false ); + } + else + { + return showPage(d->mIntToPage[index]); + } +} + + +bool KJanusWidget::showPage( QWidget *w ) +{ + if( w == 0 || mValid == false ) + { + return( false ); + } + + if( mFace == TreeList || mFace == IconList ) + { + mPageStack->raiseWidget( w ); + mActivePageWidget = w; + + int index = d->mPageToInt[w]; + mTitleLabel->setText( d->mIntToTitle[index] ); + if( mFace == TreeList ) + { + QMap<QListViewItem *, QWidget *>::Iterator it; + for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){ + QListViewItem *key = it.key(); + QWidget *val = it.data(); + if (val == w) { + mTreeList->setSelected(key, true ); + break; + } + } + } + else + { + QMap<QListBoxItem *, QWidget *>::Iterator it; + for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){ + QListBoxItem *key = it.key(); + QWidget *val = it.data(); + if (val == w) { + mIconList->setSelected( key, true ); + break; + } + } + } + } + else if( mFace == Tabbed ) + { + mTabControl->showPage(w); + mActivePageWidget = w; + } + else + { + return( false ); + } + + return( true ); +} + + +int KJanusWidget::activePageIndex() const +{ + if( mFace == TreeList) { + QListViewItem *node = mTreeList->selectedItem(); + if( node == 0 ) { return -1; } + QWidget *stackItem = mTreeListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if (mFace == IconList) { + QListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( node == 0 ) { return( false ); } + QWidget *stackItem = mIconListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if( mFace == Tabbed ) { + QWidget *widget = mTabControl->currentPage(); + return( widget == 0 ? -1 : d->mPageToInt[widget] ); + } + else { + return( -1 ); + } +} + + +int KJanusWidget::pageIndex( QWidget *widget ) const +{ + if( widget == 0 ) + { + return( -1 ); + } + else if( mFace == TreeList || mFace == IconList ) + { + return( d->mPageToInt[widget] ); + } + else if( mFace == Tabbed ) + { + // + // The user gets the real page widget with addVBoxPage(), addHBoxPage() + // and addGridPage() but not with addPage() which returns a child of + // the toplevel page. addPage() returns a QFrame so I check for that. + // + if( widget->isA("QFrame") ) + { + return( d->mPageToInt[widget->parentWidget()] ); + } + else + { + return( d->mPageToInt[widget] ); + } + } + else + { + return( -1 ); + } +} +/*US not yet implemented +void KJanusWidget::slotFontChanged() +{ + if( mTitleLabel != 0 ) + { + mTitleLabel->setFont( KGlobalSettings::generalFont() ); + QFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + } + + if( mFace == IconList ) + { + QFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + } +} +*/ + +// makes the treelist behave like the list of kcontrol +void KJanusWidget::slotItemClicked(QListViewItem *it) +{ + if(it && (it->childCount()>0)) + it->setOpen(!it->isOpen()); +} + +void KJanusWidget::setFocus() +{ + if( mValid == false ) { return; } + if( mFace == TreeList ) + { + mTreeList->setFocus(); + } + if( mFace == IconList ) + { + mIconList->setFocus(); + } + else if( mFace == Tabbed ) + { + mTabControl->setFocus(); + } + else if( mFace == Swallow ) + { + mSwallowPage->setFocus(); + } + else if( mFace == Plain ) + { + mPlainPage->setFocus(); + } +} + + +QSize KJanusWidget::minimumSizeHint() const +{ + if( mFace == TreeList || mFace == IconList ) + { + QSize s1( KDialog::spacingHint(), KDialog::spacingHint()*2 ); + QSize s2(0,0); + QSize s3(0,0); + QSize s4( mPageStack->sizeHint() ); + + if( mFace == TreeList ) + { +/*US + s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth ); + s2 = mTreeList->minimumSize(); +*/ + } + else + { + mIconList->updateMinimumHeight(); + mIconList->updateWidth(); + s2 = mIconList->minimumSize(); + } + + if( mTitleLabel->isVisible() == true ) + { + s3 += mTitleLabel->sizeHint(); + s3.rheight() += mTitleSep->minimumSize().height(); + } + + // + // Select the tallest item. It has only effect in IconList mode + // + int h1 = s1.rheight() + s3.rheight() + s4.height(); + int h2 = QMAX( h1, s2.rheight() ); + + return( QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ) ); + } + else if( mFace == Tabbed ) + { + return( mTabControl->sizeHint() ); + } + else if( mFace == Swallow ) + { + return( mSwallowPage->minimumSize() ); + } + else if( mFace == Plain ) + { + return( mPlainPage->sizeHint() ); + } + else + { + return( QSize( 100, 100 ) ); // Should never happen though. + } + +} + + +QSize KJanusWidget::sizeHint() const +{ + return( minimumSizeHint() ); +} + + +void KJanusWidget::setTreeListAutoResize( bool state ) +{ + if( mFace == TreeList ) + { +/*US + mTreeListResizeMode = state == false ? + QSplitter::KeepSize : QSplitter::Stretch; + QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget()); + splitter->setResizeMode( mTreeList, mTreeListResizeMode ); +*/ + } +} + + +void KJanusWidget::setIconListAllVisible( bool state ) +{ + if( mFace == IconList ) + { + mIconList->setShowAll( state ); + } +} + +void KJanusWidget::setShowIconsInTreeList( bool state ) +{ + mShowIconsInTreeList = state; +} + +void KJanusWidget::setRootIsDecorated( bool state ) +{ + if( mFace == TreeList ) { + mTreeList->setRootIsDecorated(state); + } +} + +void KJanusWidget::unfoldTreeList( bool persist ) +{ + if( mFace == TreeList ) + { + if( persist ) + connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) ); + else + disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) ); + + for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() ) + item->setOpen( true ); + } +} + +void KJanusWidget::showEvent( QShowEvent * ) +{ + if( mFace == TreeList ) + { +/*US + QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget()); + splitter->setResizeMode( mTreeList, mTreeListResizeMode ); +*/ + } +} + + +// +// 2000-13-02 Espen Sand +// It should be obvious that this eventfilter must only be +// be installed on the vertical scrollbar of the mIconList. +// +bool KJanusWidget::eventFilter( QObject *o, QEvent *e ) +{ + if( e->type() == QEvent::Show ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item != 0 ) + { + int lw = item->width( mIconList ); + int sw = mIconList->verticalScrollBar()->sizeHint().width(); + mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 ); + } + } + else if( e->type() == QEvent::Hide ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item != 0 ) + { + int lw = item->width( mIconList ); + mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 ); + } + } + return QWidget::eventFilter( o, e ); +} + + + +// +// Code for the icon list box +// + + +KJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name, + WFlags f ) + :KListBox( parent, name, f ), mShowAll(false), mHeightValid(false), + mWidthValid(false) +{ +} + + +void KJanusWidget::IconListBox::updateMinimumHeight() +{ + if( mShowAll == true && mHeightValid == false ) + { + int h = frameWidth()*2; + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + h += i->height( this ); + } + setMinimumHeight( h ); + mHeightValid = true; + } +} + + +void KJanusWidget::IconListBox::updateWidth() +{ + if( mWidthValid == false ) + { + int maxWidth = 10; + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + int w = ((IconListItem *)i)->width(this); + maxWidth = QMAX( w, maxWidth ); + } + + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + ((IconListItem *)i)->expandMinimumWidth( maxWidth ); + } + + if( verticalScrollBar()->isVisible() ) + { + maxWidth += verticalScrollBar()->sizeHint().width(); + } + + setFixedWidth( maxWidth + frameWidth()*2 ); + mWidthValid = true; + } +} + + +void KJanusWidget::IconListBox::invalidateHeight() +{ + mHeightValid = false; +} + + +void KJanusWidget::IconListBox::invalidateWidth() +{ + mWidthValid = false; +} + + +void KJanusWidget::IconListBox::setShowAll( bool showAll ) +{ + mShowAll = showAll; + mHeightValid = false; +} + + + +KJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap, + const QString &text ) + : QListBoxItem( listbox ) +{ + mPixmap = pixmap; + if( mPixmap.isNull() == true ) + { + mPixmap = defaultPixmap(); + } + setText( text ); + mMinimumWidth = 0; +} + + +int KJanusWidget::IconListItem::expandMinimumWidth( int width ) +{ + mMinimumWidth = QMAX( mMinimumWidth, width ); + return( mMinimumWidth ); +} + + +const QPixmap &KJanusWidget::IconListItem::defaultPixmap() +{ + static QPixmap *pix=0; + if( pix == 0 ) + { + pix = new QPixmap( 32, 32 ); + QPainter p( pix ); + p.eraseRect( 0, 0, pix->width(), pix->height() ); + p.setPen( Qt::red ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + QBitmap mask( pix->width(), pix->height(), true); + mask.fill( Qt::black ); + p.begin( &mask ); + p.setPen( Qt::white ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + pix->setMask( mask ); + } + return( *pix ); +} + + +void KJanusWidget::IconListItem::paint( QPainter *painter ) +{ + QFontMetrics fm = painter->fontMetrics(); + //int wt = fm.boundingRect(text()).width(); + int wp = mPixmap.width(); + int ht = fm.lineSpacing(); + int hp = mPixmap.height(); + + painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap ); + if( text().isEmpty() == false ) + { + painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() ); + } +} + +int KJanusWidget::IconListItem::height( const QListBox *lb ) const +{ + if( text().isEmpty() == true ) + { + return( mPixmap.height() ); + } + else + { + return( mPixmap.height() + lb->fontMetrics().lineSpacing()+10 ); + } +} + + +int KJanusWidget::IconListItem::width( const QListBox *lb ) const +{ + int wt = lb->fontMetrics().boundingRect(text()).width()+10; + int wp = mPixmap.width() + 10; + int w = QMAX( wt, wp ); + return( QMAX( w, mMinimumWidth ) ); +} + + +void KJanusWidget::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +// TODO: In TreeList, if the last child of a node is removed, and there is no corrsponding widget for that node, allow the caller to +// delete the node. +void KJanusWidget::removePage( QWidget *page ) +{ +//US qDebug("KJanusWidget::removePage 1 %lu , %lu, %lu", d, page, &(d->mPageToInt)); + if (!d || !(d->mPageToInt.contains(page))) + { + return; + } + + int index = d->mPageToInt[page]; + + if ( mFace == TreeList ) + { + QMap<QListViewItem*, QWidget *>::Iterator i; + for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mTreeListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else if ( mFace == IconList ) + { + QMap<QListBoxItem*, QWidget *>::Iterator i; + for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mIconListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else // Tabbed + { + mTabControl->removePage(page); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + } +} + +QString KJanusWidget::pageTitle(int index) const +{ + if (!d || !d->mIntToTitle.contains(index)) + return QString::null; + else + return d->mIntToTitle[index]; +} + +QWidget *KJanusWidget::pageWidget(int index) const +{ + if (!d || !d->mIntToPage.contains(index)) + return 0; + else + return d->mIntToPage[index]; +} + +//US #include "kjanuswidget.moc" diff --git a/microkde/kdeui/kjanuswidget.h b/microkde/kdeui/kjanuswidget.h new file mode 100644 index 0000000..6d3f23d --- a/dev/null +++ b/microkde/kdeui/kjanuswidget.h @@ -0,0 +1,565 @@ +/* This file is part of the KDE Libraries + * Copyright (C) 1999-2000 Espen Sand (espen@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _KJANUS_WIDGET_H_ +#define _KJANUS_WIDGET_H_ + +#include <qptrlist.h> +#include <qwidget.h> +#include <qmap.h> +#include <qgrid.h> +#include <klistbox.h> + +/*US +#include <qptrlist.h> +#include <qpixmap.h> +#include <qsplitter.h> + +#include <qstringlist.h> +#include <qmap.h> + +*/ + +class KSeparator; +class KListView; +class QWidgetStack; +class QLabel; +class QTabWidget; +class QListViewItem; +class QVBox; +class QHBox; + +/** + * Provides a number of ready to use layouts (faces). It is used + * as an internal widget in @ref KDialogBase, but can also used as a + * widget of its own. + * + * It provides TreeList, IconList, Tabbed, Plain and Swallow layouts. + * + * The TreeList face provides a list in the left area and pages in the + * right. The area are separated by a movable splitter. The style is somewhat + * similar to the layout in the Control Center. A page is raised by + * selecting the corresponding tree list item. + * + * The IconList face provides an icon list in the left area and pages in the + * right. For each entry the Icon is on top with the text below. The style + * is somewhat similar to the layout of the Eudora configuation dialog box. + * A page is raised by selecting the corresponding icon list item. The + * preferred icon size is 32x32 pixels. + * + * The Tabbed face is a common tabbed widget. The procedure for creating a + * page is similar for creating a TreeList. This has the advantage that if + * your widget contain too many pages it is trivial to convert it into a + * TreeList. Just change the face in the KJanusWidget constructor to + * KJanusWidget::TreeList and you have a tree list layout instead. + * + * The Plain face provides an empty widget (QFrame) where you can place your + * widgets. The KJanusWidget makes no assumptions regarding the contents so + * you are free to add whatever you want. + * + * The Swallow face is provided in order to simplify the usage of existing + * widgets and to allow changing the visible widget. You specify the widget + * to be displayed by @ref #setSwallowedWidget(). Your widget will be + * reparented inside the widget. You can specify a Null (0) widget. A empty + * space is then displayed. + * + * For all modes it is important that you specify the @ref QWidget::minimumSize() + * on the page, plain widget or the swallowed widget. If you use a QLayout + * on the page, plain widget or the swallowed widget this will be taken care + * of automatically. The size is used when the KJanusWidget determines its + * own minimum size. You get the minimum size by using the + * @ref #minimumSizeHint() or @ref #sizeHint() methods. + * + * Pages that have been added in TreeList, IconList or Tabbed mode can be + * removed by simply deleting the page. However, it would be preferable to use + * the QObject::deleteLater() function on the page as the main event loop + * may have optimized UI update events of the page by scheduling them for later. + * + * @short Easy to use widget with many layouts + * @author Espen Sand (espen@kde.org) + */ +class KJanusWidget : public QWidget +{ + Q_OBJECT + + private: + class IconListBox : public KListBox + { + public: + IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 ); + void updateMinimumHeight(); + void updateWidth(); + void invalidateHeight(); + void invalidateWidth(); + void setShowAll( bool showAll ); + + private: + bool mShowAll; + bool mHeightValid; + bool mWidthValid; + }; + + public: + enum Face + { + TreeList = 0, + Tabbed, + Plain, + Swallow, + IconList + }; + + public: + + /** + * Constructor where you specify the face. + * + * @param parent Parent of the widget. + * @param name Widget name. + * @param int face The kind of dialog, Use TreeList, Tabbed, Plain or + * Swallow. + */ + KJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain ); + + /** + * Destructor. + */ + ~KJanusWidget(); + + /** + * Raises the page which was added by @ref addPage(). + * + * @param index The index of the page you want to raise. + */ + virtual bool showPage( int index ); + + /** + * Returns the index of the page that are currently displayed. + * + * @return The index or -1 if the face is not Tabbed, TreeList or + * IconList. + */ + virtual int activePageIndex() const; + + /** + * Use this to verify + * that no memory allocation failed. + * + * @return true if the widget was properly created. + */ + virtual bool isValid() const; + + /** + * Returns the face type. + * + * @return The face type. + */ + virtual int face() const; + + /** + * Returns the minimum size that must be made available for the widget + * so that UIs can be displayed properly + * + * @return The minimum size. + */ + virtual QSize minimumSizeHint() const; + + /** + * Returns the recommended size for the widget in order to be displayed + * properly. + * + * @return The recommended size. + */ + virtual QSize sizeHint() const; + + /** + * Returns the empty widget that is available in Plain mode. + * + * @return The widget or 0 if the face in not Plain. + */ + virtual QFrame *plainPage(); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. In most cases you must create a layout + * manager and associate it with this widget as well. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ + virtual QFrame *addPage(const QString &item,const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QVBox + * so it contains a QVBoxLayout layout that lines up the child widgets + * are vertically. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. */ + virtual QVBox *addVBoxPage( const QString &item, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addVBoxPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QVBox *addVBoxPage( const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QHBox + * so it contains a QHBoxLayout layout that lines up the child widgets + * are horizontally. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ + virtual QHBox *addHBoxPage( const QString &itemName, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addHBoxPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QHBox *addHBoxPage( const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in either TreeList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QGrid + * so it contains a QGridLayout layout that places up the child widgets + * in a grid. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal + * or the number of rows if 'dir' is QGrid::Vertical. + * @param dir Can be QGrid::Horizontal or QGrid::Vertical. + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ +//US changed Orientation into Direction for compatibility + virtual QGrid *addGridPage( int n, QGrid::Direction dir, + const QString &itemName, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addGridPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ +//US changed Orientation into Direction for compatibility + virtual QGrid *addGridPage( int n, QGrid::Direction dir, + const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * @short Removes a page created with @ref addPage, @ref addVBoxPage, + * @ref addHBoxPage or @ref addGridPage. If the page has already + * been deleted or has already been removed, nothing happens. The widget + * itself is not deleted. + * + * @param page The widget returned by @ref addPage , @ref addVBoxPage , + * @ref addHBoxPage or @ref addGridPage . + */ + void removePage( QWidget *page ); + + + /** + * Returns the index of a page created with @ref addPage , + * @ref addVBoxPage , @ref addHBoxPage or @ref addGridPage . + * You can can compare this index with the value returned from + * @ref activePageIndex if you need to do some page specific actions + * in your code. + * + * The returned index will never change so you can safely use this + * function once and save the value. + * + * @param widget The widget returned by @ref addPage , @ref addVBoxPage , + * @ref addHBoxPage or @ref addGridPage . + * + * @return The index or -1 if the face is not Tabbed, TreeList or + * IconList + */ + virtual int pageIndex( QWidget *widget ) const; + + /** + * Defines the widget to be swallowed. + * + * This method can be used several + * times. Only the latest defined widget will be shown. + * + * @param widget The widget to be swallowed. If 0, then an empty rectangle + * is displayed. + */ + virtual bool setSwallowedWidget( QWidget *widget ); + + /** + * This function has only effect in TreeList mode. + * + * Defines how the tree list is resized when the widget is resized + * horizontally. By default the tree list keeps its width when the + * widget becomes wider. + * + * @param state The resize mode. If false (default) the TreeList keeps + * its current width when the widget becomes wider. + */ + virtual void setTreeListAutoResize( bool state ); + + /** + * This function has only effect in TreeList mode. + * + * This tells the widgets whether the icons given in the @ref addPage, + * @ref addVBoxPage, @ref addHBoxPage, or @ref addGridPage methods should + * be shown in the TreeList. + * + * Note: This method must be called before calling any of the methods + * which add icons to the page. + * + * @param state If true the icons are shown. + **/ + virtual void setShowIconsInTreeList(bool state); + + /** + * This function has only effect in TreeList mode. + * + * This tells the widgets whether the root should be decorated. + * For details see @ref QListView::setRootIsDecorated + * + * @param state Root will be decorated if true. + **/ + virtual void setRootIsDecorated( bool state ); + + /** + * This function has only effect in TreeList mode. + * + * This tells the TreeList to unfold the whole tree so that all entries + * are visible. + * + * If the list is empty when you call this method newly created entries + * will not automatically be opened. If the @p persist flag is set opened + * entries cannot be closed again, though. + * + * @param persist If true the tree always stays unfolded. + * @since 3.2 + */ + /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual + + /** + * This function has only effect in IconList mode. + * + * Defines how the icon list widget is displayed. By default it is + * the widgets in the pages that decide the minimum height + * of the toplevel widget. A vertical scrollbar can be used in + * the icon list area. + * + * @param state The visibility mode. If true, the minimum height is + * adjusted so that every icon in the list is visible at the + * same time. The vertical scrollbar will never be visible. + */ + virtual void setIconListAllVisible( bool state ); + + /** + * Sets the icon used in TreeList Mode for the given path. + * @param path The path for which this icon should be shown. + * @param pixmap The icon used. + **/ + virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap); + /** + * Returns the title string associated with a page index in TreeList or IconList mode. + * @param index The index of the page or null if there is no such page. + * @see @ref #pageIndex() + * @since 3.2 + */ + /*virtual*/ QString pageTitle(int index) const; + /** + * Returns the page widget associated with a page index or null if there is + * no such page. + * @param index The index of the page. + * @see @ref #pageIndex() + * @since 3.2 + */ + /*virtual*/ QWidget *pageWidget(int index) const; + + signals: + void aboutToShowPage(QWidget *page); + + public slots: + /** + * Give the keyboard input focus to the widget. + */ + virtual void setFocus(); + + protected: + /** + * Reimplemented to handle the splitter width when the the face + * is TreeList + */ + virtual void showEvent( QShowEvent * ); + + /** + * This function is used internally when in IconList mode. If you + * reimplement this class a make your own event filter, make sure to + * call this function from your filter. + * + * @param o Object that has received an event. + * @param e The event. + */ + virtual bool eventFilter( QObject *o, QEvent *e ); + + private slots: + bool slotShowPage(); +//US not yet implemented void slotFontChanged(); + void slotItemClicked(QListViewItem *it); + void pageGone( QObject *obj); // signal from the added page's "destroyed" signal + void slotReopen(QListViewItem *item); + + protected: + bool showPage( QWidget *w ); + void addPageWidget( QFrame *page, const QStringList &items, + const QString &header, const QPixmap &pixmap ); + void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page); + QWidget *FindParent(); + + private: + bool mValid; + + // Obsolete members. Remove in KDE 4. + QPtrList<QWidget> *mPageList; + QStringList *mTitleList; + + int mFace; + KListView *mTreeList; + IconListBox *mIconList; + QWidgetStack *mPageStack; + QLabel *mTitleLabel; + QTabWidget *mTabControl; + QFrame *mPlainPage; + QWidget *mSwallowPage; + QWidget *mActivePageWidget; + KSeparator *mTitleSep; +//US QSplitter::ResizeMode mTreeListResizeMode; + bool mShowIconsInTreeList; + QMap<QListViewItem *, QWidget *> mTreeListToPageStack; + QMap<QListBoxItem *, QWidget *> mIconListToPageStack; + QMap<QString, QPixmap> mFolderIconMap; + QMap<QString, QStringList> mChildrenNames; + QMap<QString, QWidget *> mChildPages; + + public: + class IconListItem; + protected: + virtual void virtual_hook( int id, void* data ); + private: + class KJanusWidgetPrivate; + KJanusWidgetPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/klistbox.cpp b/microkde/kdeui/klistbox.cpp new file mode 100644 index 0000000..c65b892 --- a/dev/null +++ b/microkde/kdeui/klistbox.cpp @@ -0,0 +1,314 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#include <qtimer.h> + +#include <kglobalsettings.h> +//US#include <kcursor.h> +#include <kapplication.h> +//US#include <kipc.h> +#include <kdebug.h> + +#include "klistbox.h" + +#ifdef Q_WS_X11 +#include <X11/Xlib.h> +#endif +#ifdef _WIN32_ +#define Q_WS_QWS +#endif +KListBox::KListBox( QWidget *parent, const char *name, WFlags f ) + : QListBox( parent, name, f ) +{ + connect( this, SIGNAL( onViewport() ), + this, SLOT( slotOnViewport() ) ); + connect( this, SIGNAL( onItem( QListBoxItem * ) ), + this, SLOT( slotOnItem( QListBoxItem * ) ) ); + + connect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); +/*US + + slotSettingsChanged(KApplication::SETTINGS_MOUSE); + if (kapp) + { + connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) ); + kapp->addKipcEventMask( KIPC::SettingsChanged ); + } +*/ + m_pCurrentItem = 0L; +//US set single to true + m_bUseSingle = true; + m_pAutoSelect = new QTimer( this ); + connect( m_pAutoSelect, SIGNAL( timeout() ), + this, SLOT( slotAutoSelect() ) ); +} + +void KListBox::slotOnItem( QListBoxItem *item ) +{ +/*US + if ( item && m_bChangeCursorOverItem && m_bUseSingle ) + viewport()->setCursor( KCursor().handCursor() ); +*/ + if ( item && (m_autoSelectDelay > -1) && m_bUseSingle ) { + m_pAutoSelect->start( m_autoSelectDelay, true ); + m_pCurrentItem = item; + } +} + +void KListBox::slotOnViewport() +{ +/*US + if ( m_bChangeCursorOverItem ) + viewport()->unsetCursor(); +*/ + m_pAutoSelect->stop(); + m_pCurrentItem = 0L; +} + + +/*US +void KListBox::slotSettingsChanged(int category) +{ + if (category != KApplication::SETTINGS_MOUSE) + return; + + m_bUseSingle = KGlobalSettings::singleClick(); + m_bUseSingle = true; + + disconnect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); +// disconnect( this, SIGNAL( doubleClicked( QListBoxItem *, +// const QPoint & ) ), +// this, SLOT( slotExecute( QListBoxItem *, +// const QPoint & ) ) ); + + if( m_bUseSingle ) + { + connect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); + } + else + { +// connect( this, SIGNAL( doubleClicked( QListBoxItem *, +// const QPoint & ) ), +// this, SLOT( slotExecute( QListBoxItem *, +// const QPoint & ) ) ); + } + + m_bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); + m_autoSelectDelay = KGlobalSettings::autoSelectDelay(); + + if( !m_bUseSingle || !m_bChangeCursorOverItem ) + viewport()->unsetCursor(); + +} +*/ +void KListBox::slotAutoSelect() +{ + // check that the item still exists + if( index( m_pCurrentItem ) == -1 ) + return; + + //Give this widget the keyboard focus. + if( !hasFocus() ) + setFocus(); + +#ifdef Q_WS_X11 //FIXME + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); +#endif + + QListBoxItem* previousItem = item( currentItem() ); + setCurrentItem( m_pCurrentItem ); + + if( m_pCurrentItem ) { +#ifndef Q_WS_QWS //FIXME + //Shift pressed? + if( (keybstate & ShiftMask) ) { +#endif + bool block = signalsBlocked(); + blockSignals( true ); + +#ifndef Q_WS_QWS //FIXME + //No Ctrl? Then clear before! + if( !(keybstate & ControlMask) ) + clearSelection(); +#endif + +//US in my QT version it is called isSelected() So what is right? +//US bool select = !m_pCurrentItem->isSelected(); + bool select = !m_pCurrentItem->selected(); + bool update = viewport()->isUpdatesEnabled(); + viewport()->setUpdatesEnabled( false ); + + bool down = index( previousItem ) < index( m_pCurrentItem ); + QListBoxItem* it = down ? previousItem : m_pCurrentItem; + for (;it ; it = it->next() ) { + if ( down && it == m_pCurrentItem ) { + setSelected( m_pCurrentItem, select ); + break; + } + if ( !down && it == previousItem ) { + setSelected( previousItem, select ); + break; + } + setSelected( it, select ); + } + + blockSignals( block ); + viewport()->setUpdatesEnabled( update ); + triggerUpdate( false ); + + emit selectionChanged(); + + if( selectionMode() == QListBox::Single ) + emit selectionChanged( m_pCurrentItem ); + } +#ifndef Q_WS_QWS //FIXME + else if( (keybstate & ControlMask) ) + setSelected( m_pCurrentItem, !m_pCurrentItem->isSelected() ); +#endif + else { + bool block = signalsBlocked(); + blockSignals( true ); + +//US in my QT version it is called isSelected() So what is right? +//US if( !m_pCurrentItem->isSelected() ) + if( !m_pCurrentItem->selected() ) + clearSelection(); + + blockSignals( block ); + + setSelected( m_pCurrentItem, true ); + } +#ifndef Q_WS_QWS //FIXME + } + else + kdDebug() << "Thats not supposed to happen!!!!" << endl; +#endif +} + +void KListBox::emitExecute( QListBoxItem *item, const QPoint &pos ) +{ +#ifdef Q_WS_X11 //FIXME + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); +#endif + + m_pAutoSelect->stop(); + +#ifndef Q_WS_QWS //FIXME + //Dont emit executed if in SC mode and Shift or Ctrl are pressed + if( !( m_bUseSingle && ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) { +#endif + emit executed( item ); + emit executed( item, pos ); +#ifndef Q_WS_QWS //FIXME + } +#endif +} + +// +// 2000-16-01 Espen Sand +// This widget is used in dialogs. It should ignore +// F1 (and combinations) and Escape since these are used +// to start help or close the dialog. This functionality +// should be done in QListView but it is not (at least now) +// +void KListBox::keyPressEvent(QKeyEvent *e) +{ + if( e->key() == Key_Escape ) + { + e->ignore(); + } + else if( e->key() == Key_F1 ) + { + e->ignore(); + } + else + { + QListBox::keyPressEvent(e); + } +} + +void KListBox::focusOutEvent( QFocusEvent *fe ) +{ + m_pAutoSelect->stop(); + + QListBox::focusOutEvent( fe ); +} + +void KListBox::leaveEvent( QEvent *e ) +{ + m_pAutoSelect->stop(); + + QListBox::leaveEvent( e ); +} + +void KListBox::contentsMousePressEvent( QMouseEvent *e ) +{ + if( (selectionMode() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) { + bool block = signalsBlocked(); + blockSignals( true ); + + clearSelection(); + + blockSignals( block ); + } + + QListBox::contentsMousePressEvent( e ); +} + +void KListBox::contentsMouseDoubleClickEvent ( QMouseEvent * e ) +{ + QListBox::contentsMouseDoubleClickEvent( e ); + + QListBoxItem* item = itemAt( e->pos() ); + + if( item ) { + emit doubleClicked( item, e->globalPos() ); + + if( (e->button() == LeftButton) && !m_bUseSingle ) + emitExecute( item, e->globalPos() ); + } +} + +void KListBox::slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos ) +{ + if( (btn == LeftButton) && item ) + emitExecute( item, pos ); +} + +void KListBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klistbox.moc" diff --git a/microkde/kdeui/klistbox.h b/microkde/kdeui/klistbox.h new file mode 100644 index 0000000..8023780 --- a/dev/null +++ b/microkde/kdeui/klistbox.h @@ -0,0 +1,141 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLISTBOX_H +#define KLISTBOX_H + +#include <qlistbox.h> + +/** + * Extends the functionality of @ref QListBox to honor the system + * wide settings for Single Click/Double Click mode, Auto Selection and + * Change Cursor over Link. + * + * There is a new signal @ref executed(). It gets connected to either + * @ref QListBox::clicked() or @ref QListBox::doubleClicked() + * depending on the KDE wide Single Click/Double Click settings. It is + * strongly recomended that you use this signal instead of the above + * mentioned. This way you don't need to care about the current + * settings. If you want to get informed when the user selects + * something connect to the @ref QListBox::selectionChanged() signal. + * + * @short A variant of @ref QListBox that honors KDE's system-wide settings. + **/ +class KListBox : public QListBox +{ + Q_OBJECT + +public: + KListBox( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + +signals: + + /** + * Emitted whenever the user executes an listbox item. + * + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listbox item. + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + */ + void executed( QListBoxItem *item ); + + /** + * Emitted whenever the user executes an listbox item. + * + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listbox item. + * @param pos is the position where the user has clicked + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + */ + void executed( QListBoxItem *item, const QPoint &pos ); + + /** + * This signal gets emitted whenever the user double clicks into the + * listbox. + * + * @param item The pointer to the clicked listbox item. + * @param pos The position where the user has clicked. + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + * + * This signal is more or less here for the sake of completeness. + * You should normally not need to use this. In most cases it's better + * to use @ref executed() instead. + */ + void doubleClicked( QListBoxItem *item, const QPoint &pos ); + +protected slots: + void slotOnItem( QListBoxItem *item ); + void slotOnViewport(); + +//US void slotSettingsChanged(int); + + /** + * Auto selection happend. + */ + void slotAutoSelect(); + +protected: + void emitExecute( QListBoxItem *item, const QPoint &pos ); + + /** + * @reimplemented + */ + virtual void keyPressEvent(QKeyEvent *e); + /** + * @reimplemented + */ + virtual void focusOutEvent( QFocusEvent *fe ); + /** + * @reimplemented + */ + virtual void leaveEvent( QEvent *e ); + /** + * @reimplemented + */ + virtual void contentsMousePressEvent( QMouseEvent *e ); + /** + * @reimplemented + */ + virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); + + bool m_bUseSingle; +//US bool m_bChangeCursorOverItem; + + QListBoxItem* m_pCurrentItem; + + QTimer* m_pAutoSelect; + int m_autoSelectDelay; + +private slots: + void slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListBoxPrivate; + KListBoxPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/klistview.cpp b/microkde/kdeui/klistview.cpp new file mode 100644 index 0000000..b53a88a --- a/dev/null +++ b/microkde/kdeui/klistview.cpp @@ -0,0 +1,2191 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2000 Charles Samuels <charles@kde.org> + Copyright (C) 2000 Peter Putzer + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdragobject.h> +#include <qtimer.h> +#include <qheader.h> +#include <qcursor.h> +#include <qtooltip.h> +#include <qstyle.h> +#include <qpainter.h> + +#include <kglobalsettings.h> +#include <kconfig.h> +#include <kconfigbase.h> +//US #include <kcursor.h> +#include <kapplication.h> +//US #include <kipc.h> +#include <kdebug.h> +#ifdef _WIN32_ +#define Q_WS_QWS +#endif +#ifndef _WIN32_ +#define private public +#include <qlistview.h> +#undef private +#endif +#include "klistview.h" +//US #include "klistviewlineedit.h" +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + +// /*US +class KListView::Tooltip : public QToolTip +{ +public: + Tooltip (KListView* parent, QToolTipGroup* group = 0L); + virtual ~Tooltip () {} + +protected: + // */ + /** + * Reimplemented from QToolTip for internal reasons. + */ + // /*US + virtual void maybeTip (const QPoint&); + +private: + KListView* mParent; +}; + +KListView::Tooltip::Tooltip (KListView* parent, QToolTipGroup* group) + : QToolTip (parent, group), + mParent (parent) +{ +} + +void KListView::Tooltip::maybeTip (const QPoint&) +{ + // FIXME +} +// */ + +class KListView::KListViewPrivate +{ +public: + KListViewPrivate (KListView* listview) + : pCurrentItem (0L), + autoSelectDelay(1), +//US dragDelay (KGlobalSettings::dndEventDelay()), + + dragDelay (10), +//US editor (new KListViewLineEdit (listview)), + cursorInExecuteArea(false), + bUseSingle(false), + bChangeCursorOverItem(false), + itemsMovable (true), + selectedBySimpleMove(false), + selectedUsingMouse(false), + showContextMenusOnPress(true), + itemsRenameable (false), + validDrag (false), + dragEnabled (false), + autoOpen (true), + dropVisualizer (true), + dropHighlighter (false), + createChildren (true), + pressedOnSelected (false), + wasShiftEvent (false), + fullWidth (false), + sortAscending(true), + tabRename(true), + sortColumn(0), + selectionDirection(0), + tooltipColumn (0), + selectionMode (Single), +//US contextMenuKey (KGlobalSettings::contextMenuKey()), +//US showContextMenusOnPress (KGlobalSettings::showContextMenusOnPress()), + mDropVisualizerWidth (4) + { + renameable += 0; +//US connect(editor, SIGNAL(done(QListViewItem*,int)), listview, SLOT(doneEditing(QListViewItem*,int))); + } + + ~KListViewPrivate () + { +//US delete editor; + } + + QListViewItem* pCurrentItem; + + QTimer autoSelect; + int autoSelectDelay; + + QTimer dragExpand; + QListViewItem* dragOverItem; + QPoint dragOverPoint; + + QPoint startDragPos; + int dragDelay; + +//US KListViewLineEdit *editor; + QValueList<int> renameable; + + bool cursorInExecuteArea:1; + bool bUseSingle:1; + bool bChangeCursorOverItem:1; + bool itemsMovable:1; + bool selectedBySimpleMove : 1; + bool selectedUsingMouse:1; + bool itemsRenameable:1; + bool validDrag:1; + bool dragEnabled:1; + bool autoOpen:1; + bool dropVisualizer:1; + bool dropHighlighter:1; + bool createChildren:1; + bool pressedOnSelected:1; + bool wasShiftEvent:1; + bool fullWidth:1; + bool sortAscending:1; + bool tabRename:1; + + int sortColumn; + + //+1 means downwards (y increases, -1 means upwards, 0 means not selected), aleXXX + int selectionDirection; + int tooltipColumn; + + SelectionModeExt selectionMode; + int contextMenuKey; + bool showContextMenusOnPress; + + QRect mOldDropVisualizer; + int mDropVisualizerWidth; + QRect mOldDropHighlighter; + QListViewItem *afterItemDrop; + QListViewItem *parentItemDrop; + + QColor alternateBackground; +}; + +/*US +KListViewLineEdit::KListViewLineEdit(KListView *parent) + : KLineEdit(parent->viewport()), item(0), col(0), p(parent) +{ + setFrame( false ); + hide(); + connect( parent, SIGNAL( selectionChanged() ), SLOT( slotSelectionChanged() )); +} + +KListViewLineEdit::~KListViewLineEdit() +{ +} + +void KListViewLineEdit::load(QListViewItem *i, int c) +{ + item=i; + col=c; + + QRect rect(p->itemRect(i)); + setText(item->text(c)); + + int fieldX = rect.x() - 1; + int fieldW = p->columnWidth(col) + 2; + + int pos = p->header()->mapToIndex(col); + for ( int index = 0; index < pos; index++ ) + fieldX += p->columnWidth( p->header()->mapToSection( index )); + + if ( col == 0 ) { + int d = i->depth() + (p->rootIsDecorated() ? 1 : 0); + d *= p->treeStepSize(); + fieldX += d; + fieldW -= d; + } + + if ( i->pixmap( col ) ) {// add width of pixmap + int d = i->pixmap( col )->width(); + fieldX += d; + fieldW -= d; + } + + setGeometry(fieldX, rect.y() - 1, fieldW, rect.height() + 2); + show(); + setFocus(); +} +*/ +/* Helper functions to for + * tabOrderedRename functionality. + */ + +static int nextCol (KListView *pl, QListViewItem *pi, int start, int dir) +{ + if (pi) + { + // Find the next renameable column in the current row + for (; ((dir == +1) ? (start < pl->columns()) : (start >= 0)); start += dir) + if (pl->isRenameable(start)) + return start; + } + + return -1; +} + +static QListViewItem *prevItem (QListViewItem *pi) +{ + QListViewItem *pa = pi->itemAbove(); + + /* Does what the QListViewItem::previousSibling() + * of my dreams would do. + */ + if (pa && pa->parent() == pi->parent()) + return pa; + + return NULL; +} + +static QListViewItem *lastQChild (QListViewItem *pi) +{ + if (pi) + { + /* Since there's no QListViewItem::lastChild(). + * This finds the last sibling for the given + * item. + */ + for (QListViewItem *pt = pi->nextSibling(); pt; pt = pt->nextSibling()) + pi = pt; + } + + return pi; +} +/*US +void KListViewLineEdit::selectNextCell (QListViewItem *pitem, int column, bool forward) +{ + const int ncols = p->columns(); + const int dir = forward ? +1 : -1; + const int restart = forward ? 0 : (ncols - 1); + QListViewItem *top = (pitem && pitem->parent()) + ? pitem->parent()->firstChild() + : p->firstChild(); + QListViewItem *pi = pitem; + + terminate(); // Save current changes + + do + { +*/ + /* Check the rest of the current row for an editable column, + * if that fails, check the entire next/previous row. The + * last case goes back to the first item in the current branch + * or the last item in the current branch depending on the + * direction. + */ +/*US + if ((column = nextCol(p, pi, column + dir, dir)) != -1 || + (column = nextCol(p, (pi = (forward ? pi->nextSibling() : prevItem(pi))), restart, dir)) != -1 || + (column = nextCol(p, (pi = (forward ? top : lastQChild(pitem))), restart, dir)) != -1) + { + if (pi) + { + p->setCurrentItem(pi); // Calls terminate + p->rename(pi, column); +*/ + /* Some listviews may override rename() to + * prevent certain items from being renamed, + * if this is done, [m_]item will be NULL + * after the rename() call... try again. + */ +/*US + if (!item) + continue; + + break; + } + } + } + while (pi && !item); +} +*/ + +/*US +#ifdef KeyPress +#undef KeyPress +#endif + +bool KListViewLineEdit::event (QEvent *pe) +{ + if (pe->type() == QEvent::KeyPress) + { + QKeyEvent *k = (QKeyEvent *) pe; + + if ((k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab) && + p->tabOrderedRenaming() && p->itemsRenameable() && + !(k->state() & ControlButton || k->state() & AltButton)) + { + selectNextCell(item, col, + (k->key() == Key_Tab && !(k->state() & ShiftButton))); + return true; + } + } + + return KLineEdit::event(pe); +} + +void KListViewLineEdit::keyPressEvent(QKeyEvent *e) +{ + if(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter ) + terminate(true); + else if(e->key() == Qt::Key_Escape) + terminate(false); + else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Up) + { + terminate(true); + KLineEdit::keyPressEvent(e); + } + else + KLineEdit::keyPressEvent(e); +} + +void KListViewLineEdit::terminate() +{ + terminate(true); +} + +void KListViewLineEdit::terminate(bool commit) +{ + if ( item ) + { + //kdDebug() << "KListViewLineEdit::terminate " << commit << endl; + if (commit) + item->setText(col, text()); + int c=col; + QListViewItem *i=item; + col=0; + item=0; + hide(); // will call focusOutEvent, that's why we set item=0 before + emit done(i,c); + } +} + +void KListViewLineEdit::focusOutEvent(QFocusEvent *ev) +{ + QFocusEvent * focusEv = static_cast<QFocusEvent*>(ev); + // Don't let a RMB close the editor + if (focusEv->reason() != QFocusEvent::Popup && focusEv->reason() != QFocusEvent::ActiveWindow) + terminate(true); +} + +void KListViewLineEdit::paintEvent( QPaintEvent *e ) +{ + KLineEdit::paintEvent( e ); + + if ( !frame() ) { + QPainter p( this ); + p.setClipRegion( e->region() ); + p.drawRect( rect() ); + } +} + +// selection changed -> terminate. As our "item" can be already deleted, +// we can't call terminate(false), because that would emit done() with +// a dangling pointer to "item". +void KListViewLineEdit::slotSelectionChanged() +{ + item = 0; + col = 0; + hide(); +} +*/ + +KListView::KListView( QWidget *parent, const char *name ) + : QListView( parent, name ), + d (new KListViewPrivate (this)) +{ +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold ); +#endif +//US setDragAutoScroll(true); + + connect( this, SIGNAL( onViewport() ), + this, SLOT( slotOnViewport() ) ); + connect( this, SIGNAL( onItem( QListViewItem * ) ), + this, SLOT( slotOnItem( QListViewItem * ) ) ); + + connect (this, SIGNAL(contentsMoving(int,int)), + this, SLOT(cleanDropVisualizer())); + connect (this, SIGNAL(contentsMoving(int,int)), + this, SLOT(cleanItemHighlighter())); + +/*US + slotSettingsChanged(KApplication::SETTINGS_MOUSE); + + if (kapp) + { + connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) ); + kapp->addKipcEventMask( KIPC::SettingsChanged ); + } +*/ + slotSettingsChanged(1); //US do this to initialize the connections + + + connect(&d->autoSelect, SIGNAL( timeout() ), + this, SLOT( slotAutoSelect() ) ); + connect(&d->dragExpand, SIGNAL( timeout() ), + this, SLOT( slotDragExpand() ) ); + + // context menu handling + if (d->showContextMenusOnPress) + { + connect (this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + else + { + connect (this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + + connect (this, SIGNAL (menuShortCutPressed (KListView*, QListViewItem*)), + this, SLOT (emitContextMenu (KListView*, QListViewItem*))); + + + //qDebug("KListView::KListView make alternate color configurable"); +//US d->alternateBackground = KGlobalSettings::alternateBackgroundColor(); + d->alternateBackground = QColor(240, 240, 240); +} + + + +KListView::~KListView() +{ + delete d; +} + +bool KListView::isExecuteArea( const QPoint& point ) +{ + if ( itemAt( point ) ) + return isExecuteArea( point.x() ); + + return false; +} + +bool KListView::isExecuteArea( int x ) +{ + if( allColumnsShowFocus() ) + return true; + else { + int offset = 0; + int width = columnWidth( 0 ); + int pos = header()->mapToIndex( 0 ); + + for ( int index = 0; index < pos; index++ ) + offset += columnWidth( header()->mapToSection( index ) ); + + x += contentsX(); // in case of a horizontal scrollbar + return ( x > offset && x < ( offset + width ) ); + } +} + +void KListView::slotOnItem( QListViewItem *item ) +{ + QPoint vp = viewport()->mapFromGlobal( QCursor::pos() ); + if ( item && isExecuteArea( vp.x() ) && (d->autoSelectDelay > -1) && d->bUseSingle ) { + d->autoSelect.start( d->autoSelectDelay, true ); + d->pCurrentItem = item; + } +} + +void KListView::slotOnViewport() +{ + if ( d->bChangeCursorOverItem ) + viewport()->unsetCursor(); + + d->autoSelect.stop(); + d->pCurrentItem = 0L; +} + +void KListView::slotSettingsChanged(int category) +{ +qDebug("KListView::slotSettingsChanged has to be verified"); +/*US + + switch (category) + { + case KApplication::SETTINGS_MOUSE: + d->dragDelay = KGlobalSettings::dndEventDelay(); + d->bUseSingle = KGlobalSettings::singleClick(); + + disconnect(this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked (int, QListViewItem*, const QPoint &, int))); + + if( d->bUseSingle ) + connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int))); + + d->bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); + d->autoSelectDelay = KGlobalSettings::autoSelectDelay(); + + if( !d->bUseSingle || !d->bChangeCursorOverItem ) + viewport()->unsetCursor(); + + break; + + case KApplication::SETTINGS_POPUPMENU: + d->contextMenuKey = KGlobalSettings::contextMenuKey (); + d->showContextMenusOnPress = KGlobalSettings::showContextMenusOnPress (); + + if (d->showContextMenusOnPress) + { + disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + + connect(this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + else + { + disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + + connect(this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + break; + + default: + break; + } +*/ + + if( d->bUseSingle ) + connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int))); + +} + +void KListView::slotAutoSelect() +{ + // check that the item still exists + if( itemIndex( d->pCurrentItem ) == -1 ) + return; + + if (!isActiveWindow()) + { + d->autoSelect.stop(); + return; + } + + //Give this widget the keyboard focus. + if( !hasFocus() ) + setFocus(); + + QListViewItem* previousItem = currentItem(); + setCurrentItem( d->pCurrentItem ); + +#if 0 +#ifndef Q_WS_QWS + // FIXME(E): Implement for Qt Embedded + if( d->pCurrentItem ) { + //Shift pressed? + if( (keybstate & ShiftMask) ) { + bool block = signalsBlocked(); + blockSignals( true ); + + //No Ctrl? Then clear before! + if( !(keybstate & ControlMask) ) + clearSelection(); + + bool select = !d->pCurrentItem->isSelected(); + bool update = viewport()->isUpdatesEnabled(); + viewport()->setUpdatesEnabled( false ); + + bool down = previousItem->itemPos() < d->pCurrentItem->itemPos(); + QListViewItemIterator lit( down ? previousItem : d->pCurrentItem ); + for ( ; lit.current(); ++lit ) { + if ( down && lit.current() == d->pCurrentItem ) { + d->pCurrentItem->setSelected( select ); + break; + } + if ( !down && lit.current() == previousItem ) { + previousItem->setSelected( select ); + break; + } + lit.current()->setSelected( select ); + } + + blockSignals( block ); + viewport()->setUpdatesEnabled( update ); + triggerUpdate(); + + emit selectionChanged(); + + if( selectionMode() == QListView::Single ) + emit selectionChanged( d->pCurrentItem ); + } + else if( (keybstate & ControlMask) ) + setSelected( d->pCurrentItem, !d->pCurrentItem->isSelected() ); + else { + bool block = signalsBlocked(); + blockSignals( true ); + + if( !d->pCurrentItem->isSelected() ) + clearSelection(); + + blockSignals( block ); + + setSelected( d->pCurrentItem, true ); + } + } + else + kdDebug() << "KListView::slotAutoSelect: Thats not supposed to happen!!!!" << endl; +#endif +#endif +} + +void KListView::slotHeaderChanged() +{ + if (d->fullWidth && columns()) + { + int w = 0; + for (int i = 0; i < columns() - 1; ++i) w += columnWidth(i); + setColumnWidth( columns() - 1, viewport()->width() - w - 1 ); + } +} + +void KListView::emitExecute( QListViewItem *item, const QPoint &pos, int c ) +{ + if( isExecuteArea( viewport()->mapFromGlobal(pos) ) ) { + + // Double click mode ? + if ( !d->bUseSingle ) + { + emit executed( item ); + emit executed( item, pos, c ); + } + else + { +#if 0 +#ifndef Q_WS_QWS + // FIXME(E): Implement for Qt Embedded + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); + + d->autoSelect.stop(); + + //Dont emit executed if in SC mode and Shift or Ctrl are pressed + if( !( ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) { + emit executed( item ); + emit executed( item, pos, c ); + } +#endif +#endif + } + } +} + +void KListView::focusInEvent( QFocusEvent *fe ) +{ + // kdDebug()<<"KListView::focusInEvent()"<<endl; + QListView::focusInEvent( fe ); + if ((d->selectedBySimpleMove) + && (d->selectionMode == FileManager) + && (fe->reason()!=QFocusEvent::Popup) + && (fe->reason()!=QFocusEvent::ActiveWindow) + && (currentItem()!=0)) + { + currentItem()->setSelected(true); + currentItem()->repaint(); + emit selectionChanged(); + }; +} + +void KListView::focusOutEvent( QFocusEvent *fe ) +{ + cleanDropVisualizer(); + cleanItemHighlighter(); + + d->autoSelect.stop(); + + if ((d->selectedBySimpleMove) + && (d->selectionMode == FileManager) + && (fe->reason()!=QFocusEvent::Popup) + && (fe->reason()!=QFocusEvent::ActiveWindow) + && (currentItem()!=0) +/*US && (!d->editor->isVisible()) */ + ) + { + currentItem()->setSelected(false); + currentItem()->repaint(); + emit selectionChanged(); + }; + + QListView::focusOutEvent( fe ); +} + +void KListView::leaveEvent( QEvent *e ) +{ + d->autoSelect.stop(); + + QListView::leaveEvent( e ); +} + +bool KListView::event( QEvent *e ) +{ + if (e->type() == QEvent::ApplicationPaletteChange) { +qDebug("KListView::event make alternate color configurable"); +//US d->alternateBackground=KGlobalSettings::alternateBackgroundColor(); + d->alternateBackground = QColor(240, 240, 240); + } + + return QListView::event(e); +} + +void KListView::contentsMousePressEvent( QMouseEvent *e ) +{ + if( (selectionModeExt() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) + { + bool block = signalsBlocked(); + blockSignals( true ); + + clearSelection(); + + blockSignals( block ); + } + else if ((selectionModeExt()==FileManager) && (d->selectedBySimpleMove)) + { + d->selectedBySimpleMove=false; + d->selectedUsingMouse=true; + if (currentItem()!=0) + { + currentItem()->setSelected(false); + currentItem()->repaint(); +// emit selectionChanged(); + }; + }; + + QPoint p( contentsToViewport( e->pos() ) ); + QListViewItem *at = itemAt (p); + + // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) + bool rootDecoClicked = at + && ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + + treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) + && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); + + if (e->button() == LeftButton && !rootDecoClicked) + { + //Start a drag + d->startDragPos = e->pos(); + + if (at) + { + d->validDrag = true; + d->pressedOnSelected = at->isSelected(); + } + } + + QListView::contentsMousePressEvent( e ); +} + +void KListView::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if (!dragEnabled() || d->startDragPos.isNull() || !d->validDrag) { + QListView::contentsMouseMoveEvent (e); + return; + } + + QPoint vp = contentsToViewport(e->pos()); + QListViewItem *item = itemAt( vp ); + + //do we process cursor changes at all? + if ( item && d->bChangeCursorOverItem && d->bUseSingle ) + { + //Cursor moved on a new item or in/out the execute area + if( (item != d->pCurrentItem) || + (isExecuteArea(vp) != d->cursorInExecuteArea) ) + { + d->cursorInExecuteArea = isExecuteArea(vp); +qDebug("KListView::contentsMouseMoveEvent drag&drop not supported yet"); +/*US + if( d->cursorInExecuteArea ) //cursor moved in execute area + viewport()->setCursor( KCursor::handCursor() ); + else //cursor moved out of execute area + viewport()->unsetCursor(); +*/ + } + } + + bool dragOn = dragEnabled(); + QPoint newPos = e->pos(); + if (dragOn && d->validDrag && + (newPos.x() > d->startDragPos.x()+d->dragDelay || + newPos.x() < d->startDragPos.x()-d->dragDelay || + newPos.y() > d->startDragPos.y()+d->dragDelay || + newPos.y() < d->startDragPos.y()-d->dragDelay)) + //(d->startDragPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) + { + QListView::contentsMouseReleaseEvent( 0 ); + startDrag(); + d->startDragPos = QPoint(); + d->validDrag = false; + } +} + +void KListView::contentsMouseReleaseEvent( QMouseEvent *e ) +{ + if (e->button() == LeftButton) + { + // If the row was already selected, maybe we want to start an in-place editing + if ( d->pressedOnSelected && itemsRenameable() ) + { + QPoint p( contentsToViewport( e->pos() ) ); + QListViewItem *at = itemAt (p); + if ( at ) + { + // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) + bool rootDecoClicked = + ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + + treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) + && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); + + if (!rootDecoClicked) + { + int col = header()->mapToLogical( header()->cellAt( p.x() ) ); + if ( d->renameable.contains(col) ) + rename(at, col); + } + } + } + + d->pressedOnSelected = false; + d->validDrag = false; + d->startDragPos = QPoint(); + } + QListView::contentsMouseReleaseEvent( e ); +} + +void KListView::contentsMouseDoubleClickEvent ( QMouseEvent *e ) +{ + // We don't want to call the parent method because it does setOpen, + // whereas we don't do it in single click mode... (David) + //QListView::contentsMouseDoubleClickEvent( e ); + + QPoint vp = contentsToViewport(e->pos()); + QListViewItem *item = itemAt( vp ); + emit QListView::doubleClicked( item ); // we do it now + + int col = item ? header()->mapToLogical( header()->cellAt( vp.x() ) ) : -1; + + if( item ) { + emit doubleClicked( item, e->globalPos(), col ); + + if( (e->button() == LeftButton) && !d->bUseSingle ) + emitExecute( item, e->globalPos(), col ); + } +} + +void KListView::slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ) +{ + if( (btn == LeftButton) && item ) + emitExecute(item, pos, c); +} + +void KListView::contentsDropEvent(QDropEvent* e) +{ +qDebug("KListView::contentsDropEvent drag&drop not supported yet"); +/*US + cleanDropVisualizer(); + cleanItemHighlighter(); + d->dragExpand.stop(); + + if (acceptDrag (e)) + { + e->acceptAction(); + QListViewItem *afterme; + QListViewItem *parent; + findDrop(e->pos(), parent, afterme); + + if (e->source() == viewport() && itemsMovable()) + movableDropEvent(parent, afterme); + else + { + + emit dropped(e, afterme); + emit dropped(this, e, afterme); + emit dropped(e, parent, afterme); + emit dropped(this, e, parent, afterme); + + } + } +*/ + +} + +void KListView::movableDropEvent (QListViewItem* parent, QListViewItem* afterme) +{ + QPtrList<QListViewItem> items, afterFirsts, afterNows; + QListViewItem *current=currentItem(); + bool hasMoved=false; + for (QListViewItem *i = firstChild(), *iNext=0; i != 0; i = iNext) + { + iNext=i->itemBelow(); + if (!i->isSelected()) + continue; + + // don't drop an item after itself, or else + // it moves to the top of the list + if (i==afterme) + continue; + + i->setSelected(false); + + QListViewItem *afterFirst = i->itemAbove(); + + if (!hasMoved) + { + emit aboutToMove(); + hasMoved=true; + } + + moveItem(i, parent, afterme); + + // ###### This should include the new parent !!! -> KDE 3.0 + // If you need this right now, have a look at keditbookmarks. + emit moved(i, afterFirst, afterme); + + items.append (i); + afterFirsts.append (afterFirst); + afterNows.append (afterme); + + afterme = i; + } + clearSelection(); + for (QListViewItem *i=items.first(); i != 0; i=items.next() ) + i->setSelected(true); + if (current) + setCurrentItem(current); + + emit moved(items,afterFirsts,afterNows); + + if (firstChild()) + emit moved(); +} + +void KListView::contentsDragMoveEvent(QDragMoveEvent *event) +{ +qDebug("KListView::contentsDropEvent drag&drop not supported yet"); +/*US + if (acceptDrag(event)) + { + event->acceptAction(); + //Clean up the view + + findDrop(event->pos(), d->parentItemDrop, d->afterItemDrop); + QPoint vp = contentsToViewport( event->pos() ); + QListViewItem *item = isExecuteArea( vp ) ? itemAt( vp ) : 0L; + + if ( item != d->dragOverItem ) + { + d->dragExpand.stop(); + d->dragOverItem = item; + d->dragOverPoint = vp; + if ( d->dragOverItem && d->dragOverItem->isExpandable() && !d->dragOverItem->isOpen() ) + d->dragExpand.start( QApplication::startDragTime(), true ); + } + if (dropVisualizer()) + { + QRect tmpRect = drawDropVisualizer(0, d->parentItemDrop, d->afterItemDrop); + if (tmpRect != d->mOldDropVisualizer) + { + cleanDropVisualizer(); + d->mOldDropVisualizer=tmpRect; + viewport()->repaint(tmpRect); + } + } + if (dropHighlighter()) + { + QRect tmpRect = drawItemHighlighter(0, d->afterItemDrop); + if (tmpRect != d->mOldDropHighlighter) + { + cleanItemHighlighter(); + d->mOldDropHighlighter=tmpRect; + viewport()->repaint(tmpRect); + } + } + } + else + event->ignore(); +*/ +} + +void KListView::slotDragExpand() +{ + if ( itemAt( d->dragOverPoint ) == d->dragOverItem ) + d->dragOverItem->setOpen( true ); +} + +void KListView::contentsDragLeaveEvent (QDragLeaveEvent*) +{ + d->dragExpand.stop(); + cleanDropVisualizer(); + cleanItemHighlighter(); +} + +void KListView::cleanDropVisualizer() +{ + if (d->mOldDropVisualizer.isValid()) + { + QRect rect=d->mOldDropVisualizer; + d->mOldDropVisualizer = QRect(); + viewport()->repaint(rect, true); + } +} + +int KListView::depthToPixels( int depth ) +{ + return treeStepSize() * ( depth + (rootIsDecorated() ? 1 : 0) ) + itemMargin(); +} + +void KListView::findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after) +{ + QPoint p (contentsToViewport(pos)); + + // Get the position to put it in + QListViewItem *atpos = itemAt(p); + + QListViewItem *above; + if (!atpos) // put it at the end + above = lastItem(); + else + { + // Get the closest item before us ('atpos' or the one above, if any) + if (p.y() - itemRect(atpos).topLeft().y() < (atpos->height()/2)) + above = atpos->itemAbove(); + else + above = atpos; + } + + if (above) + { + // Now, we know we want to go after "above". But as a child or as a sibling ? + // We have to ask the "above" item if it accepts children. + if (above->isExpandable()) + { + // The mouse is sufficiently on the right ? - doesn't matter if 'above' has visible children + if (p.x() >= depthToPixels( above->depth() + 1 ) || + (above->isOpen() && above->childCount() > 0) ) + { + parent = above; + after = 0L; + return; + } + } + + // Ok, there's one more level of complexity. We may want to become a new + // sibling, but of an upper-level group, rather than the "above" item + QListViewItem * betterAbove = above->parent(); + QListViewItem * last = above; + while ( betterAbove ) + { + // We are allowed to become a sibling of "betterAbove" only if we are + // after its last child + if ( last->nextSibling() == 0 ) + { + if (p.x() < depthToPixels ( betterAbove->depth() + 1 )) + above = betterAbove; // store this one, but don't stop yet, there may be a better one + else + break; // not enough on the left, so stop + last = betterAbove; + betterAbove = betterAbove->parent(); // up one level + } else + break; // we're among the child of betterAbove, not after the last one + } + } + // set as sibling + after = above; + parent = after ? after->parent() : 0L ; +} + +QListViewItem* KListView::lastChild () const +{ + QListViewItem* lastchild = firstChild(); + + if (lastchild) + for (; lastchild->nextSibling(); lastchild = lastchild->nextSibling()); + + return lastchild; +} + +QListViewItem *KListView::lastItem() const +{ + QListViewItem* last = lastChild(); + + for (QListViewItemIterator it (last); it.current(); ++it) + last = it.current(); + + return last; +} + +KLineEdit *KListView::renameLineEdit() const +{ +//US return d->editor; +qDebug("KListView::renameLineEdit returns 0. Might crash"); +return 0; +} + +void KListView::startDrag() +{ +qDebug("KListView::startDrag drag&drop not supported yet."); +/*US + QDragObject *drag = dragObject(); + + if (!drag) + return; + + if (drag->drag() && drag->target() != viewport()) + emit moved(); +*/ +} + +QDragObject *KListView::dragObject() +{ + if (!currentItem()) + return 0; + + return new QStoredDrag("application/x-qlistviewitem", viewport()); +} + +void KListView::setItemsMovable(bool b) +{ + d->itemsMovable=b; +} + +bool KListView::itemsMovable() const +{ + return d->itemsMovable; +} + +void KListView::setItemsRenameable(bool b) +{ + d->itemsRenameable=b; +} + +bool KListView::itemsRenameable() const +{ + return d->itemsRenameable; +} + + +void KListView::setDragEnabled(bool b) +{ + d->dragEnabled=b; +} + +bool KListView::dragEnabled() const +{ + return d->dragEnabled; +} + +void KListView::setAutoOpen(bool b) +{ + d->autoOpen=b; +} + +bool KListView::autoOpen() const +{ + return d->autoOpen; +} + +bool KListView::dropVisualizer() const +{ + return d->dropVisualizer; +} + +void KListView::setDropVisualizer(bool b) +{ + d->dropVisualizer=b; +} + +QPtrList<QListViewItem> KListView::selectedItems() const +{ + QPtrList<QListViewItem> list; + for (QListViewItem *i=firstChild(); i!=0; i=i->itemBelow()) + if (i->isSelected()) list.append(i); + return list; +} + + +void KListView::moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after) +{ + // sanity check - don't move a item into it's own child structure + QListViewItem *i = parent; + while(i) + { + if(i == item) + return; + i = i->parent(); + } + + // Basically reimplementing the QListViewItem(QListViewItem*, QListViewItem*) constructor + // in here, without ever deleting the item. + if (item->parent()) + item->parent()->takeItem(item); + else + takeItem(item); + + if (parent) + parent->insertItem(item); + else + insertItem(item); + + if (after) + ;//item->moveToJustAfter(after); +} + +void KListView::contentsDragEnterEvent(QDragEnterEvent *event) +{ +qDebug("KListView::contentsDragEnterEvent drag&drop not supported yet."); +/*US + if (acceptDrag (event)) + event->accept(); +*/ +} + +void KListView::setDropVisualizerWidth (int w) +{ + d->mDropVisualizerWidth = w > 0 ? w : 1; +} + +QRect KListView::drawDropVisualizer(QPainter *p, QListViewItem *parent, + QListViewItem *after) +{ + QRect insertmarker; + + if (!after && !parent) + insertmarker = QRect (0, 0, viewport()->width(), d->mDropVisualizerWidth/2); + else + { + int level = 0; + if (after) + { + QListViewItem* it = 0L; + if (after->isOpen()) + { + // Look for the last child (recursively) + it = after->firstChild(); + if (it) + while (it->nextSibling() || it->firstChild()) + if ( it->nextSibling() ) + it = it->nextSibling(); + else + it = it->firstChild(); + } + + insertmarker = itemRect (it ? it : after); + level = after->depth(); + } + else if (parent) + { + insertmarker = itemRect (parent); + level = parent->depth() + 1; + } + insertmarker.setLeft( treeStepSize() * ( level + (rootIsDecorated() ? 1 : 0) ) + itemMargin() ); + insertmarker.setRight (viewport()->width()); + insertmarker.setTop (insertmarker.bottom() - d->mDropVisualizerWidth/2 + 1); + insertmarker.setBottom (insertmarker.bottom() + d->mDropVisualizerWidth/2); + } + + // This is not used anymore, at least by KListView itself (see viewportPaintEvent) + // Remove for KDE 3.0. + if (p) + p->fillRect(insertmarker, Dense4Pattern); + + return insertmarker; +} + +QRect KListView::drawItemHighlighter(QPainter *painter, QListViewItem *item) +{ + QRect r; + + if (item) + { + r = itemRect(item); + r.setLeft(r.left()+(item->depth()+1)*treeStepSize()); + if (painter) { +//US style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(), +//US QStyle::Style_FocusAtBorder, colorGroup().highlight()); + const QColor* pHighl = &(colorGroup().highlight()); + //LR style().drawFocusRect(painter, r, colorGroup(), pHighl, true); + +qDebug("KListView::drawItemHighlighter has to be verified"); + + } + + } + + return r; +} + +void KListView::cleanItemHighlighter () +{ + if (d->mOldDropHighlighter.isValid()) + { + QRect rect=d->mOldDropHighlighter; + d->mOldDropHighlighter = QRect(); + viewport()->repaint(rect, true); + } +} + +void KListView::rename(QListViewItem *item, int c) +{ + if (d->renameable.contains(c)) + { + ensureItemVisible(item); +//US d->editor->load(item,c); +qDebug("KListView::rename has to be verified"); + + } +} + +bool KListView::isRenameable (int col) const +{ + return d->renameable.contains(col); +} + +void KListView::setRenameable (int col, bool yesno) +{ + if (col>=header()->count()) return; + + d->renameable.remove(col); + if (yesno && d->renameable.find(col)==d->renameable.end()) + d->renameable+=col; + else if (!yesno && d->renameable.find(col)!=d->renameable.end()) + d->renameable.remove(col); +} + +void KListView::doneEditing(QListViewItem *item, int row) +{ + emit itemRenamed(item, item->text(row), row); + emit itemRenamed(item); +} + +bool KListView::acceptDrag(QDropEvent* e) const +{ +qDebug("KListView::acceptDrag drag&drop not supported yet"); +//US return acceptDrops() && itemsMovable() && (e->source()==viewport()); +return false; +} + +void KListView::setCreateChildren(bool b) +{ + d->createChildren=b; +} + +bool KListView::createChildren() const +{ + return d->createChildren; +} + + +int KListView::tooltipColumn() const +{ + return d->tooltipColumn; +} + +void KListView::setTooltipColumn(int column) +{ + d->tooltipColumn=column; +} + +void KListView::setDropHighlighter(bool b) +{ + d->dropHighlighter=b; +} + +bool KListView::dropHighlighter() const +{ + return d->dropHighlighter; +} + +bool KListView::showTooltip(QListViewItem *item, const QPoint &, int column) const +{ + return ((tooltip(item, column).length()>0) && (column==tooltipColumn())); +} + +QString KListView::tooltip(QListViewItem *item, int column) const +{ + return item->text(column); +} + +void KListView::setTabOrderedRenaming(bool b) +{ + d->tabRename = b; +} + +bool KListView::tabOrderedRenaming() const +{ + return d->tabRename; +} + +void KListView::keyPressEvent (QKeyEvent* e) +{ + //don't we need a contextMenuModifier too ? (aleXXX) + if (e->key() == d->contextMenuKey) + { + emit menuShortCutPressed (this, currentItem()); + return; + } + if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) + { + emit signalDelete ( ); + return; + } + + if (d->selectionMode != FileManager) + QListView::keyPressEvent (e); + else + fileManagerKeyPressEvent (e); +} + +void KListView::activateAutomaticSelection() +{ + d->selectedBySimpleMove=true; + d->selectedUsingMouse=false; + if (currentItem()!=0) + { + selectAll(false); + currentItem()->setSelected(true); + currentItem()->repaint(); + emit selectionChanged(); + }; +} + +void KListView::deactivateAutomaticSelection() +{ + d->selectedBySimpleMove=false; +} + +bool KListView::automaticSelection() const +{ + return d->selectedBySimpleMove; +} + +void KListView::fileManagerKeyPressEvent (QKeyEvent* e) +{ + //don't care whether it's on the keypad or not + int e_state=(e->state() & ~Keypad); + + int oldSelectionDirection(d->selectionDirection); + + if ((e->key()!=Key_Shift) && (e->key()!=Key_Control) + && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)) + { + if ((e_state==ShiftButton) && (!d->wasShiftEvent) && (!d->selectedBySimpleMove)) + selectAll(FALSE); + d->selectionDirection=0; + d->wasShiftEvent = (e_state == ShiftButton); + }; + + //d->wasShiftEvent = (e_state == ShiftButton); + + + QListViewItem* item = currentItem(); + if (item==0) return; + + QListViewItem* repaintItem1 = item; + QListViewItem* repaintItem2 = 0L; + QListViewItem* visItem = 0L; + + QListViewItem* nextItem = 0L; + int items = 0; + + bool shiftOrCtrl((e_state==ControlButton) || (e_state==ShiftButton)); + int selectedItems(0); + for (QListViewItem *tmpItem=firstChild(); tmpItem!=0; tmpItem=tmpItem->nextSibling()) + if (tmpItem->isSelected()) selectedItems++; + + if (((selectedItems==0) || ((selectedItems==1) && (d->selectedUsingMouse))) + && (e_state==NoButton) + && ((e->key()==Key_Down) + || (e->key()==Key_Up) + || (e->key()==Key_Next) + || (e->key()==Key_Prior) + || (e->key()==Key_Home) + || (e->key()==Key_End))) + { + d->selectedBySimpleMove=true; + d->selectedUsingMouse=false; + } + else if (selectedItems>1) + d->selectedBySimpleMove=false; + + bool emitSelectionChanged(false); + + switch (e->key()) + { + case Key_Escape: + selectAll(FALSE); + emitSelectionChanged=TRUE; + break; + + case Key_Space: + //toggle selection of current item + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + break; + + case Key_Insert: + //toggle selection of current item and move to the next item + if (d->selectedBySimpleMove) + { + d->selectedBySimpleMove=false; + if (!item->isSelected()) item->setSelected(TRUE); + } + else + { + item->setSelected(!item->isSelected()); + }; + + nextItem=item->itemBelow(); + + if (nextItem!=0) + { + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + d->selectionDirection=1; + emitSelectionChanged=TRUE; + break; + + case Key_Down: + nextItem=item->itemBelow(); + //toggle selection of current item and move to the next item + if (shiftOrCtrl) + { + d->selectionDirection=1; + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + else + { + if (oldSelectionDirection!=-1) + { + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + }; + }; + } + else if ((d->selectedBySimpleMove) && (nextItem!=0)) + { + item->setSelected(false); + emitSelectionChanged=TRUE; + }; + + if (nextItem!=0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + break; + + case Key_Up: + nextItem=item->itemAbove(); + d->selectionDirection=-1; + //move to the prev. item and toggle selection of this one + // => No, can't select the last item, with this. For symmetry, let's + // toggle selection and THEN move up, just like we do in down (David) + if (shiftOrCtrl) + { + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + else + { + if (oldSelectionDirection!=1) + { + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + }; + } + } + else if ((d->selectedBySimpleMove) && (nextItem!=0)) + { + item->setSelected(false); + emitSelectionChanged=TRUE; + }; + + if (nextItem!=0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + break; + + case Key_End: + //move to the last item and toggle selection of all items inbetween + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + d->selectedBySimpleMove=false; + + while(nextItem!=0) + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + if (nextItem->itemBelow()==0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + } + nextItem=nextItem->itemBelow(); + } + emitSelectionChanged=TRUE; + break; + + case Key_Home: + // move to the first item and toggle selection of all items inbetween + nextItem = firstChild(); + visItem = nextItem; + repaintItem2 = visItem; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectedBySimpleMove=false; + + while ( nextItem != item ) + { + nextItem->setSelected( !nextItem->isSelected() ); + nextItem = nextItem->itemBelow(); + } + item->setSelected( !item->isSelected() ); + } + setCurrentItem( firstChild() ); + emitSelectionChanged=TRUE; + break; + + case Key_Next: + items=visibleHeight()/item->height(); + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectedBySimpleMove=false; + d->selectionDirection=1; + }; + + for (int i=0; i<items; i++) + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + //the end + if ((i==items-1) || (nextItem->itemBelow()==0)) + + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + ensureItemVisible(nextItem); + setCurrentItem(nextItem); + update(); + if ((shiftOrCtrl) || (d->selectedBySimpleMove)) + { + emit selectionChanged(); + } + return; + } + nextItem=nextItem->itemBelow(); + } + break; + + case Key_Prior: + items=visibleHeight()/item->height(); + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectionDirection=-1; + d->selectedBySimpleMove=false; + }; + + for (int i=0; i<items; i++) + { + if ((nextItem!=item) &&(shiftOrCtrl)) + nextItem->setSelected(!nextItem->isSelected()); + //the end + if ((i==items-1) || (nextItem->itemAbove()==0)) + + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + ensureItemVisible(nextItem); + setCurrentItem(nextItem); + update(); + if ((shiftOrCtrl) || (d->selectedBySimpleMove)) + { + emit selectionChanged(); + } + return; + } + nextItem=nextItem->itemAbove(); + } + break; + + case Key_Minus: + if ( item->isOpen() ) + setOpen( item, FALSE ); + break; + case Key_Plus: + if ( !item->isOpen() && (item->isExpandable() || item->childCount()) ) + setOpen( item, TRUE ); + break; + default: + bool realKey = ((e->key()!=Key_Shift) && (e->key()!=Key_Control) + && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)); + + bool selectCurrentItem = (d->selectedBySimpleMove) && (item->isSelected()); + if (realKey && selectCurrentItem) + item->setSelected(false); + //this is mainly for the "goto filename beginning with pressed char" feature (aleXXX) + QListView::SelectionMode oldSelectionMode = selectionMode(); + setSelectionMode (QListView::Multi); + QListView::keyPressEvent (e); + setSelectionMode (oldSelectionMode); + if (realKey && selectCurrentItem) + { + currentItem()->setSelected(true); + emitSelectionChanged=TRUE; + } + repaintItem2=currentItem(); + if (realKey) + visItem=currentItem(); + break; + } + + if (visItem) + ensureItemVisible(visItem); + + QRect ir; + if (repaintItem1) + ir = ir.unite( itemRect(repaintItem1) ); + if (repaintItem2) + ir = ir.unite( itemRect(repaintItem2) ); + + if ( !ir.isEmpty() ) + { // rectangle to be repainted + if ( ir.x() < 0 ) + ir.moveBy( -ir.x(), 0 ); + viewport()->repaint( ir, FALSE ); + } + /*if (repaintItem1) + repaintItem1->repaint(); + if (repaintItem2) + repaintItem2->repaint();*/ + update(); + if (emitSelectionChanged) + emit selectionChanged(); +} + +void KListView::setSelectionModeExt (SelectionModeExt mode) +{ + d->selectionMode = mode; + + switch (mode) + { + case Single: + case Multi: + case Extended: + case NoSelection: + setSelectionMode (static_cast<QListView::SelectionMode>(static_cast<int>(mode))); + break; + + case FileManager: + setSelectionMode (QListView::Extended); + break; + + default: + kdWarning () << "Warning: illegal selection mode " << int(mode) << " set!" << endl; + break; + } +} + +KListView::SelectionModeExt KListView::selectionModeExt () const +{ + return d->selectionMode; +} + +int KListView::itemIndex( const QListViewItem *item ) const +{ + if ( !item ) + return -1; + + if ( item == firstChild() ) + return 0; + else { + QListViewItemIterator it(firstChild()); + uint j = 0; + for (; it.current() && it.current() != item; ++it, ++j ); + + if( !it.current() ) + return -1; + + return j; + } +} + +QListViewItem* KListView::itemAtIndex(int index) +{ + if (index<0) + return 0; + + int j(0); + for (QListViewItemIterator it=firstChild(); it.current(); it++) + { + if (j==index) + return it.current(); + j++; + }; + return 0; +} + + +void KListView::emitContextMenu (KListView*, QListViewItem* i) +{ + QPoint p; + qDebug("KListView::emitContextMenu "); + + if (i) + p = viewport()->mapToGlobal(itemRect(i).center()); + else + p = mapToGlobal(rect().center()); + + emit contextMenu (this, i, p); +} + +void KListView::emitContextMenu (QListViewItem* i, const QPoint& p, int) +{ + qDebug("KListView::emitContextMenu "); + emit contextMenu (this, i, p); +} + +void KListView::setAcceptDrops (bool val) +{ + QListView::setAcceptDrops (val); + viewport()->setAcceptDrops (val); +} + +int KListView::dropVisualizerWidth () const +{ + return d->mDropVisualizerWidth; +} + + +void KListView::viewportPaintEvent(QPaintEvent *e) +{ + QListView::viewportPaintEvent(e); + + if (d->mOldDropVisualizer.isValid() && e->rect().intersects(d->mOldDropVisualizer)) + { + QPainter painter(viewport()); + + // This is where we actually draw the drop-visualizer + painter.fillRect(d->mOldDropVisualizer, Dense4Pattern); + } + if (d->mOldDropHighlighter.isValid() && e->rect().intersects(d->mOldDropHighlighter)) + { + QPainter painter(viewport()); + +qDebug("KListView::viewportPaintEvent has to be verified"); + + // This is where we actually draw the drop-highlighter +//US style().drawPrimitive(QStyle::PE_FocusRect, &painter, d->mOldDropHighlighter, colorGroup(), +//US QStyle::Style_FocusAtBorder); + +//LR style().drawFocusRect(&painter, d->mOldDropHighlighter, colorGroup(), (const QColor*)0, true); + + + } +} + +void KListView::setFullWidth() +{ + setFullWidth(true); +} + +void KListView::setFullWidth(bool fullWidth) +{ + d->fullWidth = fullWidth; +//US header()->setStretchEnabled(fullWidth, columns()-1); +} + +bool KListView::fullWidth() const +{ + return d->fullWidth; +} + +int KListView::addColumn(const QString& label, int width) +{ + int result = QListView::addColumn(label, width); + if (d->fullWidth) { +//US header()->setStretchEnabled(false, columns()-2); +//US header()->setStretchEnabled(true, columns()-1); + } + return result; +} + +int KListView::addColumn(const QIconSet& iconset, const QString& label, int width) +{ + int result = QListView::addColumn(iconset, label, width); + if (d->fullWidth) { +//US header()->setStretchEnabled(false, columns()-2); +//US header()->setStretchEnabled(true, columns()-1); + } + return result; +} + +void KListView::removeColumn(int index) +{ + QListView::removeColumn(index); +//US if (d->fullWidth && index == columns()) header()->setStretchEnabled(true, columns()-1); +} + +void KListView::viewportResizeEvent(QResizeEvent* e) +{ + QListView::viewportResizeEvent(e); +} + +const QColor &KListView::alternateBackground() const +{ + return d->alternateBackground; +} + +void KListView::setAlternateBackground(const QColor &c) +{ + d->alternateBackground = c; + repaint(); +} + +void KListView::saveLayout(KConfig *config, const QString &group) const +{ + KConfigGroupSaver saver(config, group); + QStringList widths, order; + for (int i = 0; i < columns(); ++i) + { + widths << QString::number(columnWidth(i)); + order << QString::number(header()->mapToIndex(i)); + } + config->writeEntry("ColumnWidths", widths); + config->writeEntry("ColumnOrder", order); + config->writeEntry("SortColumn", d->sortColumn); + config->writeEntry("SortAscending", d->sortAscending); +} + +void KListView::restoreLayout(KConfig *config, const QString &group) +{ + KConfigGroupSaver saver(config, group); + QStringList cols = config->readListEntry("ColumnWidths"); + int i = 0; + for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) + setColumnWidth(i++, (*it).toInt()); + + cols = config->readListEntry("ColumnOrder"); + i = 0; + for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) + header()->moveSection(i++, (*it).toInt()); + +/*US I changed the following code, because hasKey is not available. +!!! check if my version is correct + if (config->hasKey("SortColumn")) + setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); +*/ + QStringList langLst = config->readListEntry( "SortColumn" ); + if (!langLst.isEmpty()) + setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); +} + +void KListView::setSorting(int column, bool ascending) +{ + d->sortColumn = column; + d->sortAscending = ascending; + QListView::setSorting(column, ascending); +} + +int KListView::columnSorted(void) const +{ + return d->sortColumn; +} + +bool KListView::ascendingSort(void) const +{ + return d->sortAscending; +} + +KListViewItem::KListViewItem(QListView *parent) + : QListViewItem(parent) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent) + : QListViewItem(parent) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, QListViewItem *after) + : QListViewItem(parent, after) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after) + : QListViewItem(parent, after) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, QListViewItem *after, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::~KListViewItem() +{ +} + +void KListViewItem::init() +{ + m_known = false; +} + +const QColor &KListViewItem::backgroundColor() +{ + if (isAlternate()) + return static_cast< KListView* >(listView())->alternateBackground(); + return listView()->viewport()->colorGroup().base(); +} + +bool KListViewItem::isAlternate() +{ + KListView *lv = static_cast<KListView *>(listView()); + if (lv && lv->alternateBackground().isValid()) + { + KListViewItem *above = 0; +//US above = dynamic_cast<KListViewItem *>(itemAbove()); + above = (KListViewItem *)(itemAbove()); + m_known = above ? above->m_known : true; + if (m_known) + { + m_odd = above ? !above->m_odd : false; + } + else + { + KListViewItem *item; + bool previous = true; + if (parent()) + { +//US item = dynamic_cast<KListViewItem *>(parent()); + item = (KListViewItem *)(parent()); + if (item) + previous = item->m_odd; +//US item = dynamic_cast<KListViewItem *>(parent()->firstChild()); + item = (KListViewItem *)(parent()->firstChild()); + } + else + { +//US item = dynamic_cast<KListViewItem *>(lv->firstChild()); + item = (KListViewItem *)(lv->firstChild()); + } + + while(item) + { + item->m_odd = previous = !previous; + item->m_known = true; +//US item = dynamic_cast<KListViewItem *>(item->nextSibling()); + item = (KListViewItem *)(item->nextSibling()); + } + } + return m_odd; + } + return false; +} + +void KListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QColorGroup _cg = cg; + const QPixmap *pm = listView()->viewport()->backgroundPixmap(); + if (pm && !pm->isNull()) + { + _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(), *pm)); + QPoint o = p->brushOrigin(); + p->setBrushOrigin( o.x()-listView()->contentsX(), o.y()-listView()->contentsY() ); + } + else if (isAlternate()) { +//US if (listView()->viewport()->backgroundMode()==Qt::FixedColor) + if (listView()->viewport()->backgroundMode()==QWidget::PaletteBackground) + _cg.setColor(QColorGroup::Background, static_cast< KListView* >(listView())->alternateBackground()); + else + _cg.setColor(QColorGroup::Base, static_cast< KListView* >(listView())->alternateBackground()); + } + QListViewItem::paintCell(p, _cg, column, width, alignment); +} + +void KListView::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klistview.moc" +//US #include "klistviewlineedit.moc" + +// vim: ts=2 sw=2 et diff --git a/microkde/kdeui/klistview.h b/microkde/kdeui/klistview.h new file mode 100644 index 0000000..f7d9f85 --- a/dev/null +++ b/microkde/kdeui/klistview.h @@ -0,0 +1,1033 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2000 Charles Samuels <charles@kde.org> + Copyright (C) 2000 Peter Putzer <putzer@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLISTVIEW_H +#define KLISTVIEW_H + +#include <qlistview.h> + +#include <qptrlist.h> + +//US +class QDropEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDragEnterEvent; + +class QDragObject; +class KConfig; +class KLineEdit; +/** + * This Widget extends the functionality of QListView to honor the system + * wide settings for Single Click/Double Click mode, AutoSelection and + * ChangeCursorOverLink (TM). + * + * There is a new signal executed(). It gets connected to either + * @ref QListView::clicked() or @ref QListView::doubleClicked() depending on the KDE + * wide Single Click/Double Click settings. It is strongly recommended that + * you use this signal instead of the above mentioned. This way you dont + * need to care about the current settings. + * If you want to get informed when the user selects something connect to the + * QListView::selectionChanged() signal. + * + * Drag-and-Drop is supported with the signal @ref #dropped(), just @ref #setAcceptDrops(true) + * and connect it to a suitable slot. + * To see where you are dropping, @ref setDropVisualizer(true). + * And also you'll need @ref acceptDrag(QDropEvent*) + * + * KListView is drag-enabled, too: to benefit from that you've got derive from it. + * Reimplement @ref dragObject() and (possibly) @ref startDrag(), + * and @ref setDragEnabled(true). + * + * @version $Id$ + */ +class KListView : public QListView +{ + Q_OBJECT + Q_ENUMS( SelectionModeExt ) + Q_PROPERTY( bool fullWidth READ fullWidth WRITE setFullWidth ) + Q_PROPERTY( bool itemsMovable READ itemsMovable WRITE setItemsMovable ) + Q_PROPERTY( bool itemsRenameable READ itemsRenameable WRITE setItemsRenameable ) + Q_PROPERTY( bool dragEnabled READ dragEnabled WRITE setDragEnabled ) + Q_PROPERTY( bool autoOpen READ autoOpen WRITE setAutoOpen ) + Q_PROPERTY( bool dropVisualizer READ dropVisualizer WRITE setDropVisualizer ) +//US Q_PROPERTY( int tooltipColumn READ tooltipColumn WRITE setTooltipColumn ) + Q_PROPERTY( int dropVisualizerWidth READ dropVisualizerWidth WRITE setDropVisualizerWidth ) + Q_PROPERTY( QColor alternateBackground READ alternateBackground WRITE setAlternateBackground ) + + Q_OVERRIDE( SelectionModeExt selectionMode READ selectionModeExt WRITE setSelectionModeExt ) + +public: + /** + * Possible selection modes. + * + * The first four correspond directly to QListView::SelectionMode, while + * the FileManager selection mode is defined as follows: + * @li home: move to the first + * @li end: move to the last + * @li PgUp/PgDn: move one page up/down + * @li up/down: move one item up/down + * @li insert: toggle selection of current and move to the next + * @li space: toggle selection of the current + * @li CTRL+up: move to the previous item and toggle selection of this one + * @li CTRL+down: toggle selection of the current item and move to the next + * @li CTRL+end: toggle selection from (including) the current + * item to (including) the last item + * @li CTRL+home: toggle selection from (including) the current + * item to the (including) the first item + * @li CTRL+PgDn: toggle selection from (including) the current + * item to (excluding) the item one page down + * @li CTRL+PgUp: toggle selection from (excluding) the current + * item to (including) the item one page up + * + * The combinations work the same with SHIFT instead of CTRL, except + * that if you start selecting something using SHIFT everything selected + * before will be deselected first. + * + * Additionally the current item is always selected automatically when + * navigating using the keyboard, except other items were selected explicitely. + * + * This way e.g. SHIFT+up/PgUp then SHIFT+down/PgDn leaves no item selected + */ + enum SelectionModeExt { + Single = QListView::Single, + Multi = QListView::Multi, + Extended = QListView::Extended, + NoSelection = QListView::NoSelection, + FileManager + }; + void repaintContents( bool erase = true ) + { + QScrollView::repaintContents( contentsX(), contentsY(), + visibleWidth(), visibleHeight(), erase ); + }; + /** + * Constructor. + * + * The parameters @p parent and @p name are handled by + * @ref QListView, as usual. + */ + KListView (QWidget *parent = 0, const char *name = 0); + + /** + * Destructor. + */ + virtual ~KListView(); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void setAcceptDrops (bool); + + /** + * This function determines whether the given coordinates are within the + * execute area. The execute area is the part of a @ref QListViewItem where mouse + * clicks or double clicks respectively generate a @ref #executed() signal. + * Depending on @ref QListView::allColumnsShowFocus() this is either the + * whole item or only the first column. + * @return true if point is inside execute area of an item, false in all + * other cases including the case that it is over the viewport. + */ + virtual bool isExecuteArea( const QPoint& point ); + + /** + * Same thing, but from an x coordinate only. This only checks if x is in + * the first column (if all columns don't show focus), without testing if + * the y coordinate is over an item or not. + */ + bool isExecuteArea( int x ); + + /** + * @return a list containing the currently selected items. + */ + QPtrList<QListViewItem> selectedItems() const; // ### BIC: KDE 4: use an implicitly shared class! (QValueList?) + + /** + * Arbitrarily move @p item to @p parent, positioned immediately after item @p after. + */ + void moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after); + + /** + * @return the last item (not child!) of this listview. + * + * @see lastChild() + */ + QListViewItem *lastItem() const; + + /** + * @return the last child of this listview. + * + * @see lastItem() + */ + QListViewItem* lastChild () const; + + /** + * @return the lineedit used for inline renaming. + * Use that to setup a @ref KCompletion or @ref QValidator for the lineedit + * + * @since 3.2 + */ + KLineEdit* renameLineEdit() const; + + /** + * @returns if it is legal to move items in the list view. True by default. + * + * @see #setDragEnabled() + * @see #setItemsMovable() + */ + bool itemsMovable() const; + + /** + * @return whether inplace-renaming has been enabled. False by default. + * + * @see #setItemsRenameable() + */ + bool itemsRenameable() const; + + /** + * @return whether dragging is enabled. False by default. + * + * @see #setDragEnabled() + */ + bool dragEnabled() const; + + /** + * @return true if AutoOpen is enabled (not implemented currently). + * + * @see #setAutoOpen() + */ + bool autoOpen() const; + + /** + * @return true if @p column is renamable. + * + * @see #setRenameable() + */ + bool isRenameable (int column) const; + + /** + * @return true if drawing of the drop-visualizer has been enabled. True by default. + * + * @see #setDropVisualizer() + */ + bool dropVisualizer() const; + + /** + * @return the column for which tooltips are displayed (or -1 if none set). + * + * @see #setTooltipColumn() + */ + int tooltipColumn() const; + + /** + * For future expansions. + * + * Do not use. + * @deprecated + */ + bool createChildren() const; + + /** + * @return true if drawing of the drop-highlighter has been enabled. False by default. + * + * @see #setDropHighlighter() + */ + bool dropHighlighter() const; + + /** + * The dropVisualizerWidth defaults to 4. + * + * @see #setDropVisualizerWidth() + * @return the current width of the drop-visualizer. + */ + int dropVisualizerWidth () const; + + /** + * @return the "extended" selection mode of this listview. + * + * @see SelectionModeExt + * @see setSelectionModeExt + */ + SelectionModeExt selectionModeExt () const; + + /** + * Returns the index of @p item within the item tree or -1 if + * @p item doesn't exist in this list view. This function takes + * all items into account not only the visible ones. + */ + int itemIndex( const QListViewItem *item ) const; + + /** + * Returns the item of @p index within the item tree or 0 if + * @p index doesn't exist in this list view. This function takes + * all items into account not only the visible ones. + */ + QListViewItem* itemAtIndex(int index); + + /** + * @deprecated + * @see #setFullWidth() + */ + void setFullWidth(); + + /** + * Let the last column fit exactly all the available width. + * + * @see #fullWidth() + */ + void setFullWidth(bool fullWidth); + + /** + * Returns whether the last column is set to fit the available width. + * + * @see #setFullWidth() + */ + bool fullWidth() const; + + /** + * Reimplemented for full width support + * + * @see #removeColumn() + */ + virtual int addColumn(const QString& label, int width = -1); + /** + * Reimplemented for full width support + */ + virtual int addColumn(const QIconSet& iconset, const QString& label, int width = -1); + /** + * Reimplemented for full width support + * + * @see #addColumn() + */ + virtual void removeColumn(int index); + + /** + * sets the alternate background background color. + * This only has an effect if the items are KListViewItems + * + * @param c the color to use for every other item. Set to an invalid + * colour to disable alternate colours. + * + * @see #alternateBackground() + **/ + void setAlternateBackground(const QColor &c); + /** + * @return the alternate background color + * + * @see #setAlternateBackground() + */ + const QColor &alternateBackground() const; + + /** + * Saves the list view's layout (column widtsh, column order, sort column) + * to a KConfig group + * + * @param config the @ref KConfig object to write to + * @param group the config group to use + */ + void saveLayout(KConfig *config, const QString &group) const; + /** + * Reads the list view's layout from a KConfig group as stored with + * @ref #saveLayout + * + * @param config the @ref KConfig object to read from + * @param group the config group to use + */ + void restoreLayout(KConfig *config, const QString &group); + /** + * Reimplemented to remember the current sort column and order. + * @param column is the column to be sorted, or -1 to sort in order of + * insertion + * @param whether to sort ascending (or descending) + */ + virtual void setSorting(int column, bool ascending = true); + + /** + * @return the currently sorted column, or -1 if none is sorted + */ + int columnSorted(void) const; + + /** + * @return whether the current sort is ascending (or descending) + */ + bool ascendingSort(void) const; + +signals: + + /** + * This signal is emitted whenever the user executes an listview item. + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listview item. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + */ + void executed( QListViewItem *item ); + + /** + * This signal is emitted whenever the user executes an listview item. + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listview item. + * @param pos is the position where the user has clicked + * @param c is the column into which the user clicked. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + */ + void executed( QListViewItem *item, const QPoint &pos, int c ); + + /** + * This signal gets emitted whenever the user double clicks into the + * listview. + * @param item is the pointer to the clicked listview item. + * @param pos is the position where the user has clicked, and + * @param c is the column into which the user clicked. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + * + * This signal is more or less here for the sake of completeness. + * You should normally not need to use this. In most cases its better + * to use @ref #executed() instead. + */ + void doubleClicked( QListViewItem *item, const QPoint &pos, int c ); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * @param e is the drop event itself (it has already been accepted) + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items) + * + * @see #acceptDrop() + */ + void dropped (QDropEvent * e, QListViewItem *after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This is an overloaded version of the above (provided to simplify + * processing drops outside of the class). + * + * @param list is the listview + * @param e is the drop event itself (it has already been accepted) + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (KListView* list, QDropEvent* e, QListViewItem* after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This function also provides a parent, in the event that your listview + * is a tree + * @param list is the listview + * @param e is the drop event itself (it has already been accepted) + * @param parent the item that is to be the parent of the new item + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (KListView* list, QDropEvent* e, QListViewItem* parent, QListViewItem* after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This function also provides a parent, in the event that your listview + * is a tree + * @param e is the drop event itself (it has already been accepted) + * @param parent the item that is to be the parent of the new item + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (QDropEvent* e, QListViewItem* parent, QListViewItem* after); + + /** + * This signal is emitted when ever the user moves an item in the list via + * DnD. + * If more than one item is moved at the same time, this signal is only emitted + * once. + */ + void moved(); + + /** + * Connect to this signal if you want to do some preprocessing before + * a move is made, for example, to disable sorting + * + * This is sent only once per each groups of moves. That is, for each + * drop that is a move this will be emitted once, before KListView calls + * @see moveItem() + */ + void aboutToMove(); + + /** + * This signal is emitted when ever the user moves an item in the list via + * DnD. + * If more than one item is moved at the same time, @p afterFirst and + * @p afterNow will reflect what was true before the move. + * This differs from @ref moved(), so be careful. All the items will have been + * moved before @ref moved() is emitted, which is not true in this method. // FIXME + * @param item the item that was moved + * @param afterFirst the item that parameter item was in before the move, in the list + * @param afterNow the item it's currently after. + */ + void moved (QListViewItem *item, QListViewItem *afterFirst, QListViewItem *afterNow); + + + /** + * This signal is emitted after all the items have been moved. It reports info for + * each and every item moved, in order. The first element in @p items associates + * with the first of afterFirst and afterNow. + */ + void moved(QPtrList<QListViewItem> &items, QPtrList<QListViewItem> &afterFirst, QPtrList<QListViewItem> &afterNow); + + /** + * This signal gets emitted when an item is renamed via in-place renaming. + * + * @param item is the renamed item. + * @param str is the new value of column @p col. + * @param col is the renamed column. + */ + void itemRenamed(QListViewItem* item, const QString &str, int col); + + /** + * Same as above, but without the extra information. + */ + void itemRenamed(QListViewItem* item); + void signalDelete(); + + /** + * This signal is emitted when the shortcut key for popup-menus is pressed. + * + * Normally you should not use this, just connect a slot to signal + * @ref contextMenu (KListView*, QListViewItem*, const QPoint&) to correctly + * handle showing context menus regardless of settings. + * + * @param list is this listview. + * @param item is the @ref currentItem() at the time the key was pressed. May be 0L. + */ + void menuShortCutPressed (KListView* list, QListViewItem* item); + + /** + * This signal is emitted whenever a context-menu should be shown for item @p i. + * It automatically adjusts for all settings involved (Menu key, showMenuOnPress/Click). + * + * @param l is this listview. + * @param i is the item for which the menu should be shown. May be 0L. + * @param p is the point at which the menu should be shown. + */ + void contextMenu (KListView* l, QListViewItem* i, const QPoint& p); + +public slots: + /** + * Rename column @p c of @p item. + */ + virtual void rename(QListViewItem *item, int c); + + /** + * By default, if you called setItemsRenameable(true), + * only the first column is renameable. + * Use this function to enable the feature on other columns. + * + * If you want more intelligent (dynamic) selection, + * you'll have to derive from KListView, + * and override @ref rename() and call only call it + * if you want the item to be renamed. + */ + void setRenameable (int column, bool yesno=true); + + /** + * Set whether items in the list view can be moved. + * It is enabled by default. + * + * @see itemsMovable() + */ + virtual void setItemsMovable(bool b); + + /** + * Enables inplace-renaming of items. + * It is disabled by default. + * + * @see itemsRenameable() + * @see setRenameable() + */ + virtual void setItemsRenameable(bool b); + + /** + * Enable/Disable the dragging of items. + * It is disabled by default. + */ + virtual void setDragEnabled(bool b); + + /** + * Enable/Disable AutoOpen (not implemented currently). + */ + virtual void setAutoOpen(bool b); + + /** + * Enable/Disable the drawing of a drop-visualizer + * (a bar that shows where a dropped item would be inserted). + * It is enabled by default, if dragging is enabled + */ + virtual void setDropVisualizer(bool b); + + /** + * Set the width of the (default) drop-visualizer. + * If you don't call this method, the width is set to 4. + */ + void setDropVisualizerWidth (int w); + + /** + * Set which column should be used for automatic tooltips. + * + * @param column is the column for which tooltips will be shown. + * Set -1 to disable this feature. + */ + virtual void setTooltipColumn(int column); + + /** + * Enable/Disable the drawing of a drop-highlighter + * (a rectangle around the item under the mouse cursor). + * It is disabled by default. + */ + virtual void setDropHighlighter(bool b); + + /** + * For future expansions. + * + * Do not use. + * @deprecated + */ + virtual void setCreateChildren(bool b); + + /** + * Set the selection mode. + * + * A different name was chosen to avoid API-clashes with @ref QListView::setSelectionMode(). + */ + void setSelectionModeExt (SelectionModeExt mode); + + /** + * Enable/disable tabbing between editable cells + * @since 3.1 + */ + void setTabOrderedRenaming(bool b); + + /** + * Returns whether tab ordered renaming is enabled + * @since 3.1 + */ + bool tabOrderedRenaming() const; + +protected: + /** + * Determine whether a drop on position @p p would count as + * being above or below the QRect @p rect. + * + * @param rect is the rectangle we examine. + * @param p is the point located in the rectangle, p is assumed to be in + * viewport coordinates. + */ + inline bool below (const QRect& rect, const QPoint& p) + { + return (p.y() > (rect.top() + (rect.bottom() - rect.top())/2)); + } + + /** + * An overloaded version of below(const QRect&, const QPoint&). + * + * It differs from the above only in what arguments it takes. + * + * @param i the item whose rect() is passed to the above function. + * @param p is translated from contents coordinates to viewport coordinates + * before being passed to the above function. + */ + inline bool below (QListViewItem* i, const QPoint& p) + { + return below (itemRect(i), contentsToViewport(p)); + } + + /** + * Reimplemented to reload the alternate background in palette changes. + * @internal + */ + virtual bool event( QEvent * ); + + /** + * Emit signal @ref #executed. + * @internal + */ + void emitExecute( QListViewItem *item, const QPoint &pos, int c ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void focusInEvent(QFocusEvent* fe); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void focusOutEvent( QFocusEvent *fe ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void leaveEvent( QEvent *e ); + + /** + * @return the tooltip for @p column of @p item. + */ + virtual QString tooltip(QListViewItem* item, int column) const; + + /** + * @return whether the tooltip for @p column of @p item shall be shown at point @p pos. + */ + virtual bool showTooltip(QListViewItem *item, const QPoint &pos, int column) const; + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragMoveEvent (QDragMoveEvent *event); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMousePressEvent( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseMoveEvent( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragLeaveEvent (QDragLeaveEvent *event); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseReleaseEvent (QMouseEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDropEvent (QDropEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragEnterEvent (QDragEnterEvent *); + + /** + * @return a dragobject encoding the current selection. + * + * @see setDragEnabled() + */ + virtual QDragObject *dragObject(); + + /** + * @return true if the @p event provides some acceptable + * format. + * A common mistake is to forget the "const" in your reimplementation + */ + virtual bool acceptDrag (QDropEvent* event) const; + + /** + * Paint the drag line. If painter is null, don't try to :) + * + * If after == 0 then the marker should be drawn at the top. + * + * @return the rectangle that you painted to. + */ + virtual QRect drawDropVisualizer (QPainter *p, QListViewItem *parent, QListViewItem *after); + + /** + * Paint the drag rectangle. If painter is null, don't try to :) + * + * + * @return the rectangle that you painted to. + */ + virtual QRect drawItemHighlighter(QPainter *painter, QListViewItem *item); + + /** + * This method calls @ref dragObject() and starts the drag. + * + * Reimplement it to do fancy stuff like setting a pixmap or + * using a non-default DragMode + */ + virtual void startDrag(); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void keyPressEvent (QKeyEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void viewportPaintEvent(QPaintEvent*); + + /** + * In FileManager selection mode: explicitely activate the mode + * in which the current item is automatically selected. + */ + void activateAutomaticSelection(); + /** + * In FileManager selection mode: explicitely deactivate the mode + * in which the current item is automatically selected. + */ + void deactivateAutomaticSelection(); + /** + * In FileManager selection mode: return whether it is currently in the mode + * where the current item is selected automatically. + * Returns false if items were selected explicitely, e.g. using the mouse. + */ + bool automaticSelection() const; + + /** + * Reimplemented for setFullWidth() + */ + virtual void viewportResizeEvent(QResizeEvent* e); + +protected slots: + /** + * Update internal settings whenever the global ones change. + * @internal + */ + void slotSettingsChanged(int); + + void slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ); + void doneEditing(QListViewItem *item, int row); + + /** + * Repaint the rect where I was drawing the drop line. + */ + void cleanDropVisualizer(); + + /** + * Repaint the rect where I was drawing the drop rectangle. + */ + void cleanItemHighlighter(); + + /** + * Emit the @ref contextMenu signal. This slot is for mouse actions. + */ + void emitContextMenu (QListViewItem*, const QPoint&, int); + + /** + * Emit the @ref #contextMenu signal. This slot is for key presses. + */ + void emitContextMenu (KListView*, QListViewItem*); + + /** + * Accessory slot for AutoSelect + * @internal + */ + void slotOnItem( QListViewItem *item ); + + /** + * Accessory slot for AutoSelect/ChangeCursorOverItem + * @internal + */ + void slotOnViewport(); + + /** + * Process AutoSelection. + * @internal + */ + void slotAutoSelect(); + + void slotDragExpand(); + + /** + * Reacts to header changes in full width mode + * @internal + */ + void slotHeaderChanged(); + +protected: + /** + * Handle dropEvent when itemsMovable() is set to true. + */ + virtual void movableDropEvent (QListViewItem* parent, QListViewItem* afterme); + + /** + * Where is the nearest QListViewItem that I'm going to drop? + * + * FIXME KDE 4.0: Make this method const so it can be called from an + * acceptDrag method without ugly casts + */ + virtual void findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after); + + /** + * A special keyPressEvent (for FileManager selection mode). + */ + void fileManagerKeyPressEvent (QKeyEvent*); + + /** + * Convert the depth of an item into its indentation in pixels + */ + int depthToPixels( int depth ); + +private: + class Tooltip; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListViewPrivate; + KListViewPrivate *d; +}; + +/** + * A listview item with support for alternate background colours. It is + * a drop-in replacement for @ref QListViewItem + * + * @short listview item with alternate background colour support + */ +class KListViewItem : public QListViewItem +{ +public: + /** + * constructors. The semantics remain as in @ref QListViewItem. + * Although they accept a @ref QListViewItem as parent, please + * don't mix KListViewItem (or subclasses) with QListViewItem + * (or subclasses). + */ + KListViewItem(QListView *parent); + KListViewItem(QListViewItem *parent); + KListViewItem(QListView *parent, QListViewItem *after); + KListViewItem(QListViewItem *parent, QListViewItem *after); + + KListViewItem(QListView *parent, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListViewItem *parent, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListView *parent, QListViewItem *after, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListViewItem *parent, QListViewItem *after, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + virtual ~KListViewItem(); + + /** + * retuns true if this item is to be drawn with the alternate background + */ + bool isAlternate(); + /** + * returns the background colour for this item + */ + const QColor &backgroundColor(); + + virtual void paintCell(QPainter *p, const QColorGroup &cg, + int column, int width, int alignment); + +private: + void init(); + +private: + uint m_odd : 1; + uint m_known : 1; + uint m_unused : 30; +}; + +#endif + +// vim: ts=2 sw=2 et diff --git a/microkde/kdeui/kmainwindow.cpp b/microkde/kdeui/kmainwindow.cpp new file mode 100644 index 0000000..3a2a4d0 --- a/dev/null +++ b/microkde/kdeui/kmainwindow.cpp @@ -0,0 +1,994 @@ + /* This file is part of the KDE libraries + Copyright + (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997 Stephan Kulow (coolo@kde.org) + (C) 1997-2000 Sven Radej (radej@kde.org) + (C) 1997-2000 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 2002 Joseph Wenninger (jowenn@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ +#include <qobjectlist.h> +#include <qstringlist.h> +#include <qtimer.h> +#include <qmenubar.h> +#include <qstatusbar.h> +#include <qapplication.h> + + +#include "kdebug.h" +#include "kmainwindow.h" +#include "kglobalsettings.h" +#include "kactioncollection.h" + +class KMainWindowPrivate { +public: +//US bool showHelpMenu:1; + + bool autoSaveSettings:1; + bool settingsDirty:1; + bool autoSaveWindowSize:1; + bool care_about_geometry:1; + QString autoSaveGroup; +//US KAccel * kaccel; +//US KMainWindowInterface *m_interface; + KDEPrivate::ToolBarHandler *toolBarHandler; + QTimer* settingsTimer; + KToggleAction *showStatusBarAction; + QRect defaultWindowSize; +}; + +static bool no_query_exit = false; + +KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f ) + : QMainWindow( parent, name, f )/*US, KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )*/ +{ + mQToolBar = 0; + initKMainWindow(name); +} + +void KMainWindow::parseGeometry(bool parsewidth) +{ +//US the following code is not getting used in the embedded version !! So disable it for now +/*US + + assert ( !kapp->geometryArgument().isNull() ); + assert ( d->care_about_geometry ); + +#ifndef Q_WS_QWS + // FIXME: (E) Implement something similar for Qt Embedded (or decide we don't need it) + int x, y; + int w, h; + int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h); + if (parsewidth) { + QSize minSize = minimumSize(); + QSize maxSize = maximumSize(); + if ( (m & WidthValue) == 0 ) + w = width(); + if ( (m & HeightValue) == 0 ) + h = height(); + w = QMIN(w,maxSize.width()); + h = QMIN(h,maxSize.height()); + w = QMAX(w,minSize.width()); + h = QMAX(h,minSize.height()); + resize(w, h); + } else { + if ( parsewidth && (m & XValue) == 0 ) + x = geometry().x(); + if ( parsewidth && (m & YValue) == 0 ) + y = geometry().y(); + if ( (m & XNegative) ) + x = KApplication::desktop()->width() + x - w; + if ( (m & YNegative) ) + y = KApplication::desktop()->height() + y - h; + move(x, y); + } +#endif +*/ +} + +KMainWindow::~KMainWindow() +{ + delete d->settingsTimer; + QMenuBar* mb = internalMenuBar(); + delete mb; +//US delete d->m_interface; + + delete d; +//US memberList->remove( this ); +} + +void KMainWindow::initKMainWindow(const char *name) +{ + setDockMenuEnabled( FALSE ); +//US mHelpMenu = 0; + +//US kapp->setTopWidget( this ); + actionCollection()->setWidget( this ); +//US connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); +//US if( !memberList ) +//US memberList = new QPtrList<KMainWindow>; +/*US + + if ( !ksm ) + ksm = ksmd.setObject(new KMWSessionManaged()); + // set a unique object name. Required by session management. + QCString objname; + QCString s; + int unusedNumber; + if ( !name ) + { // no name given + objname = kapp->instanceName() + "-mainwindow#"; + s = objname + '1'; // start adding number immediately + unusedNumber = 1; + } + else if( name[ strlen( name ) - 1 ] == '#' ) + { // trailing # - always add a number + objname = name; + s = objname + '1'; // start adding number immediately + unusedNumber = 1; + } + else + { + objname = name; + s = objname; + unusedNumber = 0; // add numbers only when needed + } + for(;;) { + QWidgetList* list = kapp->topLevelWidgets(); + QWidgetListIt it( *list ); + bool found = false; + for( QWidget* w = it.current(); + w != NULL; + ++it, w = it.current()) + if( w != this && w->name() == s ) + { + found = true; + break; + } + delete list; + if( !found ) + break; + s.setNum( ++unusedNumber ); + s = objname + s; + } + setName( s ); + memberList->append( this ); +*/ + + d = new KMainWindowPrivate; +//US d->showHelpMenu = true; + d->settingsDirty = false; + d->autoSaveSettings = false; + d->autoSaveWindowSize = true; // for compatibility +//US d->kaccel = actionCollection()->kaccel(); + d->toolBarHandler = 0; + d->settingsTimer = 0; + d->showStatusBarAction = NULL; +/*US + if ((d->care_about_geometry == beeing_first)) { + beeing_first = false; + if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater + d->care_about_geometry = false; + else + parseGeometry(false); + } +*/ + d->care_about_geometry = false; + +//US setCaption( kapp->caption() ); + // attach dcop interface +//US d->m_interface = new KMainWindowInterface(this); + +//US if (!kapp->authorize("movable_toolbars")) +//US setDockWindowsMovable(false); +} + +KAction *KMainWindow::toolBarMenuAction() +{ + if ( !d->toolBarHandler ) + return 0; + + return d->toolBarHandler->toolBarMenuAction(); +} + +bool KMainWindow::canBeRestored( int number ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ +//US if ( !kapp->isRestored() ) +//US return FALSE; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + if ( !config ) + return FALSE; + config->setGroup( QString::fromLatin1("Number") ); + int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 ); + return number >= 1 && number <= n; + +} + +const QString KMainWindow::classNameOfToplevel( int number ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ +//US if ( !kapp->isRestored() ) +//US return QString::null; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + if ( !config ) + return QString::null; + QString s; + s.setNum( number ); + s.prepend( QString::fromLatin1("WindowProperties") ); + config->setGroup( s ); + if ( !config->hasKey( QString::fromLatin1("ClassName") ) ) + return QString::null; + else + return config->readEntry( QString::fromLatin1("ClassName") ); +} + +bool KMainWindow::restore( int number, bool show ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ + if ( !canBeRestored( number ) ) + return FALSE; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + + if ( readPropertiesInternal( config, number ) ){ + if ( show ) + KMainWindow::show(); + return FALSE; + } + return FALSE; + +} + +void KMainWindow::setCaption( const QString &caption ) +{ +//US setPlainCaption( kapp->makeStdCaption(caption) ); + setPlainCaption( caption ); +} + +void KMainWindow::setCaption( const QString &caption, bool modified ) +{ +//US setPlainCaption( kapp->makeStdCaption(caption, true, modified) ); + setPlainCaption( caption + "modified:" ); +} + +void KMainWindow::setPlainCaption( const QString &caption ) +{ + QMainWindow::setCaption( caption ); +#ifndef Q_WS_QWS +//US the following is disabled for the embedded version +//US NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); +//US info.setName( caption.utf8().data() ); +#endif +} + +void KMainWindow::slotStateChanged(const QString &newstate) +{ + stateChanged(newstate, KXMLGUIClient::StateNoReverse); +} + +/* + * Get rid of this for KDE 4.0 + */ +void KMainWindow::slotStateChanged(const QString &newstate, + KXMLGUIClient::ReverseStateChange reverse) +{ + stateChanged(newstate, reverse); +} + +void KMainWindow::closeEvent ( QCloseEvent *e ) +{ + // Save settings if auto-save is enabled, and settings have changed + if (d->settingsDirty && d->autoSaveSettings) + saveAutoSaveSettings(); + + if (queryClose()) { + e->accept(); + + int not_withdrawn = 0; +/*US + QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); + for (it.toFirst(); it.current(); ++it){ + if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) + not_withdrawn++; + } +*/ + if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? +/*US + if ( queryExit() && !kapp->sessionSaving()) { // Yes, Quit app? + // don't call queryExit() twice + disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); + kapp->deref(); // ...and quit aplication. + } else { + // cancel closing, it's stupid to end up with no windows at all.... + e->ignore(); + } +*/ +//US we have no sessionmanagement. Simply close app. + if ( queryExit() ) { // Yes, Quit app? + qDebug("KMainWindow::closeEvent: Exit application ???"); + // don't call queryExit() twice +//US disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); + } + + } + } +} + +bool KMainWindow::queryExit() +{ + return TRUE; +} + +bool KMainWindow::queryClose() +{ + return TRUE; +} + +void KMainWindow::saveGlobalProperties( KConfig* ) +{ +} + +void KMainWindow::readGlobalProperties( KConfig* ) +{ +} + +void KMainWindow::savePropertiesInternal( KConfig *config, int number ) +{ + bool oldASWS = d->autoSaveWindowSize; + d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size + + QString s; + s.setNum(number); + s.prepend(QString::fromLatin1("WindowProperties")); + config->setGroup(s); + + // store objectName, className, Width and Height for later restoring + // (Only useful for session management) + config->writeEntry(QString::fromLatin1("ObjectName"), name()); + config->writeEntry(QString::fromLatin1("ClassName"), className()); + + saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. + + s.setNum(number); + config->setGroup(s); + saveProperties(config); + + d->autoSaveWindowSize = oldASWS; +} + +void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) +{ + if ( enable ) + { + if ( d->toolBarHandler ) + return; + + d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); + +/*US if ( factory() ) + factory()->addClient( d->toolBarHandler ); +*/ + } + else + { + if ( !d->toolBarHandler ) + return; +/*US + if ( factory() ) + factory()->removeClient( d->toolBarHandler ); +*/ + delete d->toolBarHandler; + d->toolBarHandler = 0; + } + +} + +bool KMainWindow::isStandardToolBarMenuEnabled() const +{ + return ( d->toolBarHandler != 0 ); +} + +void KMainWindow::createStandardStatusBarAction(){ + if(!d->showStatusBarAction){ + d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection()); + connect(d->showStatusBarAction, SIGNAL(toggled(bool)), statusBar(), SLOT(setShown(bool))); + if(internalStatusBar()) + d->showStatusBarAction->setChecked(!internalStatusBar()->isHidden()); + } +} + +QToolBar *KMainWindow::tBar( ) +{ + if ( ! mQToolBar ) + mQToolBar = new QToolBar( this ); + return mQToolBar; +} + +KToolBar *KMainWindow::toolBar( const char * name ) +{ + + if (!name) + name = "mainToolBar"; + KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); + if ( tb ) + return tb; + bool honor_mode = (name == "mainToolBar"); + +/*US + if ( builderClient() ) + return new KToolBar(this, name, honor_mode); // XMLGUI constructor + else +*/ + return new KToolBar(this, Top, false, name, honor_mode ); // non-XMLGUI +} + +QPtrListIterator<KToolBar> KMainWindow::toolBarIterator() +{ + toolbarList.clear(); + QPtrList<QToolBar> lst; + for ( int i = (int)QMainWindow::Unmanaged; i <= (int)Minimized; ++i ) { + lst = toolBars( (ToolBarDock)i ); + for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) { + if ( !tb->inherits( "KToolBar" ) ) + continue; + toolbarList.append( (KToolBar*)tb ); + } + } + return QPtrListIterator<KToolBar>( toolbarList ); +} + +void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize ) +{ + d->autoSaveSettings = true; + d->autoSaveGroup = groupName; + d->autoSaveWindowSize = saveWindowSize; + // Get notified when the user moves a toolbar around +//US connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), +//US this, SLOT( setSettingsDirty() ) ); + connect( this, SIGNAL( toolBarPositionChanged(QToolBar *) ), + this, SLOT( setSettingsDirty() ) ); + + + // Get default values +//US int scnum = QApplication::desktop()->screenNumber(parentWidget()); +//US QRect desk = QApplication::desktop()->screenGeometry(scnum); + QRect desk = KGlobalSettings::desktopGeometry(0); + + d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); + // Now read the previously saved settings + applyMainWindowSettings( KGlobal::config(), groupName ); +} + + +void KMainWindow::resetAutoSaveSettings() +{ + d->autoSaveSettings = false; + if ( d->settingsTimer ) + d->settingsTimer->stop(); +} + +bool KMainWindow::autoSaveSettings() const +{ + return d->autoSaveSettings; +} + +QString KMainWindow::autoSaveGroup() const +{ + return d->autoSaveGroup; +} + +void KMainWindow::saveAutoSaveSettings() +{ + ASSERT( d->autoSaveSettings ); + //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; + saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); + KGlobal::config()->sync(); + d->settingsDirty = false; + if ( d->settingsTimer ) + d->settingsTimer->stop(); +} + +void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory ) +{ + // disabling the updates prevents unnecessary redraws + setUpdatesEnabled( false ); + + // just in case we are rebuilding, let's remove our old client +//US guiFactory()->removeClient( this ); + + // make sure to have an empty GUI + QMenuBar* mb = internalMenuBar(); + if ( mb ) + mb->clear(); + + (void)toolBarIterator(); // make sure toolbarList is most-up-to-date + toolbarList.setAutoDelete( true ); + toolbarList.clear(); + toolbarList.setAutoDelete( false ); +/*US + // don't build a help menu unless the user ask for it + if (d->showHelpMenu) { + // we always want a help menu + if (helpMenu2 == 0) + helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true, + actionCollection()); + } + + // we always want to load in our global standards file + setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) ); + + // now, merge in our local xml file. if this is null, then that + // means that we will be only using the global file + if ( !xmlfile.isNull() ) { + setXMLFile( xmlfile, true ); + } else { + QString auto_file(instance()->instanceName() + "ui.rc"); + setXMLFile( auto_file, true ); + } + + // make sure we don't have any state saved already + setXMLGUIBuildDocument( QDomDocument() ); + + // do the actual GUI building + guiFactory()->addClient( this ); + + // try and get back *some* of our memory + if ( _conserveMemory ) + { + // before freeing the memory allocated by the DOM document we also + // free all memory allocated internally in the KXMLGUIFactory for + // the menubar and the toolbars . This however implies that we + // have to take care of deleting those widgets ourselves. For + // destruction this is no problem, but when rebuilding we have + // to take care of that (and we want to rebuild the GUI when + // using stuff like the toolbar editor ). + // In addition we have to take care of not removing containers + // like popupmenus, defined in the XML document. + // this code should probably go into a separate method in KMainWindow. + // there's just one problem: I'm bad in finding names ;-) , so + // I skipped this ;-) + + QDomDocument doc = domDocument(); + + QDomElement e = doc.documentElement().firstChild().toElement(); + for (; !e.isNull(); e = e.nextSibling().toElement() ) { + if ( e.tagName().lower() == "toolbar" ) + factory_->resetContainer( e.attribute( "name" ) ); + else if ( e.tagName().lower() == "menubar" ) + factory_->resetContainer( e.tagName(), true ); + } + + conserveMemory(); + } +*/ + setUpdatesEnabled( true ); + updateGeometry(); +} + +void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup) +{ + kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; +//US QStrList entryList; + QStringList entryList; + QString oldGroup; + + if (!configGroup.isEmpty()) + { + oldGroup = config->group(); + config->setGroup(configGroup); + } + + // Called by session management - or if we want to save the window size anyway + if ( d->autoSaveWindowSize ) + saveWindowSize( config ); + + QStatusBar* sb = internalStatusBar(); + if (sb) { + entryList.clear(); + if ( sb->isHidden() ) + entryList.append("Disabled"); + else + entryList.append("Enabled"); + + if(sb->isHidden()) +//US config->writeEntry(QString::fromLatin1("StatusBar"), entryList, ';'); + config->writeEntry(QString::fromLatin1("StatusBar"), entryList); + else + config->deleteEntry(QString::fromLatin1("StatusBar")); + } + + QMenuBar* mb = internalMenuBar(); + if (mb) { + entryList.clear(); + if ( mb->isHidden() ) + entryList.append("Disabled"); + else + entryList.append("Enabled"); + + // By default we don't hide. + if(mb->isHidden()) +//US config->writeEntry(QString::fromLatin1("MenuBar"), entryList, ';'); + config->writeEntry(QString::fromLatin1("MenuBar"), entryList); + else + config->deleteEntry(QString::fromLatin1("MenuBar")); + } + + int n = 1; // Toolbar counter. toolbars are counted from 1, + KToolBar *toolbar = 0; + QPtrListIterator<KToolBar> it( toolBarIterator() ); + while ( ( toolbar = it.current() ) ) { + ++it; + QString group; + if (!configGroup.isEmpty()) + { + // Give a number to the toolbar, but prefer a name if there is one, + // because there's no real guarantee on the ordering of toolbars + group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); + group.prepend(" Toolbar"); + group.prepend(configGroup); + } + toolbar->saveSettings(config, group); + n++; + } + if (!configGroup.isEmpty()) + config->setGroup(oldGroup); +} + +bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) +{ + if ( number == 1 ) + readGlobalProperties( config ); + + // in order they are in toolbar list + QString s; + s.setNum(number); + s.prepend(QString::fromLatin1("WindowProperties")); + + config->setGroup(s); + + // restore the object name (window role) + if ( config->hasKey(QString::fromLatin1("ObjectName" )) ) + setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here + + applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. + + s.setNum(number); + config->setGroup(s); + readProperties(config); + return true; +} + +void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup) +{ + kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; + QString entry; +//US QStrList entryList; + QStringList entryList; + int i = 0; // Number of entries in list + + if (!configGroup.isEmpty()) + config->setGroup(configGroup); + + restoreWindowSize(config); + + QStatusBar* sb = internalStatusBar(); + if (sb) { + entryList.clear(); +//US i = config->readListEntry (QString::fromLatin1("StatusBar"), entryList, ';'); + entryList = config->readListEntry (QString::fromLatin1("StatusBar")); + entry = entryList.first(); + if (entry == QString::fromLatin1("Disabled")) + sb->hide(); + else + sb->show(); + if(d->showStatusBarAction) + d->showStatusBarAction->setChecked(!sb->isHidden()); + } + + QMenuBar* mb = internalMenuBar(); + if (mb) { + entryList.clear(); +//US i = config->readListEntry (QString::fromLatin1("MenuBar"), entryList, ';'); + entryList = config->readListEntry (QString::fromLatin1("MenuBar")); + entry = entryList.first(); + if (entry==QString::fromLatin1("Disabled")) + { + mb->hide(); + } else + { + mb->show(); + } + } + + int n = 1; // Toolbar counter. toolbars are counted from 1, + KToolBar *toolbar; + QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator + + for ( ; it.current(); ++it) { + toolbar= it.current(); + QString group; + if (!configGroup.isEmpty()) + { + // Give a number to the toolbar, but prefer a name if there is one, + // because there's no real guarantee on the ordering of toolbars + group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); + group.prepend(" Toolbar"); + group.prepend(configGroup); + } + toolbar->applySettings(config, group); + n++; + } + + finalizeGUI( true ); + } + +void KMainWindow::finalizeGUI( bool force ) +{ + //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; + // The whole reason for this is that moveToolBar relies on the indexes + // of the other toolbars, so in theory it should be called only once per + // toolbar, but in increasing order of indexes. + // Since we can't do that immediately, we move them, and _then_ + // we call positionYourself again for each of them, but this time + // the toolbariterator should give them in the proper order. + // Both the XMLGUI and applySettings call this, hence "force" for the latter. + QPtrListIterator<KToolBar> it( toolBarIterator() ); + for ( ; it.current() ; ++ it ) + it.current()->positionYourself( force ); + + d->settingsDirty = false; +} + +void KMainWindow::saveWindowSize( KConfig * config ) const +{ +/*US + int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); +*/ + QRect desk = KGlobalSettings::desktopGeometry(0); + + QRect size( desk.width(), width(), desk.height(), height() ); + if(size != d->defaultWindowSize){ + config->writeEntry(QString::fromLatin1("Width %1").arg(desk.width()), width() ); + config->writeEntry(QString::fromLatin1("Height %1").arg(desk.height()), height() ); + } + else{ + config->deleteEntry(QString::fromLatin1("Width %1").arg(desk.width())); + config->deleteEntry(QString::fromLatin1("Height %1").arg(desk.height())); + } +} + +void KMainWindow::restoreWindowSize( KConfig * config ) +{ + if (d->care_about_geometry) { + parseGeometry(true); + } else { + // restore the size +/*US int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); +*/ + QRect desk = KGlobalSettings::desktopGeometry(0); + + QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ), + config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); + if (size.isEmpty()) { + // try the KDE 2.0 way + size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ), + config->readNumEntry( QString::fromLatin1("Height"), 0 ) ); + if (!size.isEmpty()) { + // make sure the other resolutions don't get old settings + config->writeEntry( QString::fromLatin1("Width"), 0 ); + config->writeEntry( QString::fromLatin1("Height"), 0 ); + } + } + if ( !size.isEmpty() ) + resize( size ); + } +} + +bool KMainWindow::initialGeometrySet() const +{ + return d->care_about_geometry; +} + +void KMainWindow::ignoreInitialGeometry() +{ + d->care_about_geometry = false; +} + +void KMainWindow::setSettingsDirty() +{ + //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; + d->settingsDirty = true; + if ( d->autoSaveSettings ) + { + // Use a timer to save "immediately" user-wise, but not too immediately + // (to compress calls and save only once, in case of multiple changes) + if ( !d->settingsTimer ) + { + d->settingsTimer = new QTimer( this ); + connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) ); + } + d->settingsTimer->start( 500, true ); + } +} + +bool KMainWindow::settingsDirty() const +{ + return d->settingsDirty; +} + +QString KMainWindow::settingsGroup() const +{ + return d->autoSaveGroup; +} + +void KMainWindow::resizeEvent( QResizeEvent * ) +{ + if ( d->autoSaveWindowSize ) + setSettingsDirty(); +} + +bool KMainWindow::hasMenuBar() +{ + return (internalMenuBar()); +} + +//US KMenuBar *KMainWindow::menuBar() +QMenuBar *KMainWindow::menuBar() +{ +//US KMenuBar * mb = internalMenuBar(); + QMenuBar * mb = internalMenuBar(); + if ( !mb ) { +//US mb = new KMenuBar( this ); + mb = new QMenuBar( this ); + // trigger a re-layout and trigger a call to the private + // setMenuBar method. + QMainWindow::menuBar(); + } + return mb; +} + +//US KStatusBar *KMainWindow::statusBar() +QStatusBar *KMainWindow::statusBar() +{ +//US KStatusBar * sb = internalStatusBar(); + QStatusBar * sb = internalStatusBar(); + if ( !sb ) { +//US sb = new KStatusBar( this ); + sb = new QStatusBar( this ); + // trigger a re-layout and trigger a call to the private + // setStatusBar method. + QMainWindow::statusBar(); + } + return sb; +} + +void KMainWindow::shuttingDown() +{ + // Needed for Qt <= 3.0.3 at least to prevent reentrancy + // when queryExit() shows a dialog. Check before removing! + static bool reentrancy_protection = false; + if (!reentrancy_protection) + { + reentrancy_protection = true; + // call the virtual queryExit + queryExit(); + reentrancy_protection = false; + } + +} + +//US KMenuBar *KMainWindow::internalMenuBar() +QMenuBar *KMainWindow::internalMenuBar() +{ +//US QObjectList *l = queryList( "KMenuBar", 0, false, false ); + QObjectList *l = queryList( "QMenuBar", 0, false, false ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + +//US KMenuBar *m = (KMenuBar*)l->first(); + QMenuBar *m = (QMenuBar*)l->first(); + delete l; + return m; +} + +//US KStatusBar *KMainWindow::internalStatusBar() +QStatusBar *KMainWindow::internalStatusBar() +{ +//US QObjectList *l = queryList( "KStatusBar", 0, false, false ); + QObjectList *l = queryList( "QStatusBar", 0, false, false ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + +//US KStatusBar *s = (KStatusBar*)l->first(); + QStatusBar *s = (QStatusBar*)l->first(); + delete l; + return s; +} + +void KMainWindow::childEvent( QChildEvent* e) +{ + QMainWindow::childEvent( e ); +} + +void KMainWindow::paintEvent( QPaintEvent * ) +{ + // do nothing +} + +QSize KMainWindow::sizeForCentralWidgetSize(QSize size) +{ + KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); + if (tb && !tb->isHidden()) { + switch( tb->barPos() ) + { + case KToolBar::Top: + case KToolBar::Bottom: + size += QSize(0, tb->sizeHint().height()); + break; + + case KToolBar::Left: + case KToolBar::Right: + size += QSize(toolBar()->sizeHint().width(), 0); + break; + + case KToolBar::Flat: +//US size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); + size += QSize(0, tb->sizeHint().height()); + break; + + default: + break; + } + } +//US KMenuBar *mb = menuBar(); + QMenuBar *mb = menuBar(); + if (!mb->isHidden()) { + size += QSize(0,mb->heightForWidth(size.width())); +/*US if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) + size += QSize( 0, dockWindowsMovable() ? 1 : 2); +*/ + size += QSize( 0, 2); + } + QStatusBar *sb = internalStatusBar(); + if( sb && !sb->isHidden() ) + size += QSize(0, sb->sizeHint().height()); + + return size; +} + +// why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; +void KMainWindow::finalizeGUI( KXMLGUIClient *client ) +{ /*US KXMLGUIBuilder::finalizeGUI( client );*/ } + +void KMainWindow::virtual_hook( int id, void* data ) +{ /*US KXMLGUIBuilder::virtual_hook( id, data );*/ + KXMLGUIClient::virtual_hook( id, data ); } diff --git a/microkde/kdeui/kmainwindow.h b/microkde/kdeui/kmainwindow.h new file mode 100644 index 0000000..e76e732 --- a/dev/null +++ b/microkde/kdeui/kmainwindow.h @@ -0,0 +1,776 @@ +/* + This file is part of the KDE libraries + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + $Id$ + +*/ + + + +#ifndef KMAINWINDOW_H +#define KMAINWINDOW_H + +/*US +#include "kxmlguifactory.h" +#include "kxmlguiclient.h" +#include "kxmlguibuilder.h" +#include <qmetaobject.h> + +class KPopupMenu; +class KXMLGUIFactory; +class KConfig; +class KHelpMenu; +class KStatusBar; +class QStatusBar; +class KMenuBar; +class KMWSessionManaged; +class KAccel; +class KToolBarMenuAction; +*/ + +class QMenuBar; +class QStatusBar; +class KMainWindowPrivate; +class KAction; + +#include <ktoolbar.h> +#include <ktoolbarhandler.h> +#include <kxmlguiclient.h> +#include <qmainwindow.h> +#include <qptrlist.h> + +class KActionCollection; + +class KMainWindow : public QMainWindow, virtual public KXMLGUIClient +{ + Q_OBJECT + +private: +//US create private defaultconstructor + KMainWindow() {;}; + +public: +public: + /** + * Construct a main window. + * + * @param parent The widget parent. This is usually 0 but it may also be the window + * group leader. In that case, the KMainWindow becomes sort of a + * secondary window. + * + * @param name The object name. For session management and window management to work + * properly, all main windows in the application should have a + * different name. When passing 0 (the default), KMainWindow will create + * a unique name, but it's recommended to explicitly pass a window name that will + * also describe the type of the window. If there can be several windows of the same + * type, append '#' (hash) to the name, and KMainWindow will append numbers to make + * the names unique. For example, for a mail client which has one main window showing + * the mails and folders, and which can also have one or more windows for composing + * mails, the name for the folders window should be e.g. "mainwindow" and + * for the composer windows "composer#". + * + * @param f Specify the widget flags. The default is + * WType_TopLevel and WDestructiveClose. TopLevel indicates that a + * main window is a toplevel window, regardless of whether it has a + * parent or not. DestructiveClose indicates that a main window is + * automatically destroyed when its window is closed. Pass 0 if + * you do not want this behavior. + * + * KMainWindows must be created on the heap with 'new', like: + * <pre> KMainWindow *kmw = new KMainWindow (...</pre> + **/ + KMainWindow( QWidget* parent = 0, const char *name = 0, WFlags f = WType_TopLevel | WDestructiveClose ); + + + /** + * Destructor. + * + * Will also destroy the toolbars, and menubar if + * needed. + */ + virtual ~KMainWindow(); + + /** + * Retrieve the standard help menu. + * + * It contains entires for the + * help system (activated by F1), an optional "What's This?" entry + * (activated by Shift F1), an application specific dialog box, + * and an "About KDE" dialog box. + * + * Example (adding a standard help menu to your application): + * <pre> + * KPopupMenu *help = helpMenu( <myTextString> ); + * menuBar()->insertItem( i18n("&Help"), help ); + * </pre> + * + * @param aboutAppText The string that is used in the application + * specific dialog box. If you leave this string empty the + * information in the global @ref KAboutData of the + * application will be used to make a standard dialog box. + * + * @param showWhatsThis Set this to false if you do not want to include + * the "What's This" menu entry. + * + * @return A standard help menu. + */ +//US KPopupMenu* helpMenu( const QString &aboutAppText = QString::null, +//US bool showWhatsThis = TRUE ); + + /** + * Returns the help menu. Creates a standard help menu if none exists yet. + * + * It contains entries for the + * help system (activated by F1), an optional "What's This?" entry + * (activated by Shift F1), an application specific dialog box, + * and an "About KDE" dialog box. You must create the application + * specific dialog box yourself. When the "About application" + * menu entry is activated, a signal will trigger the + * @ref showAboutApplication slot. See @ref showAboutApplication for more + * information. + * + * Example (adding a help menu to your application): + * <pre> + * menuBar()->insertItem( i18n("&Help"), customHelpMenu() ); + * </pre> + * + * @param showWhatsThis Set this to @p false if you do not want to include + * the "What's This" menu entry. + * + * @return A standard help menu. + */ +//US KPopupMenu* customHelpMenu( bool showWhatsThis = TRUE ); + + /** + * @sect Session Management + * + * Try to restore the toplevel widget as defined by the number (1..X). + * + * If the session did not contain so high a number, the configuration + * is not changed and @p false returned. + * + * That means clients could simply do the following: + * <pre> + * if (kapp->isRestored()){ + * int n = 1; + * while (KMainWindow::canBeRestored(n)){ + * (new childMW)->restore(n); + * n++; + * } + * } else { + * // create default application as usual + * } + * </pre> + * Note that @ref QWidget::show() is called implicitly in restore. + * + * With this you can easily restore all toplevel windows of your + * application. + * + * If your application uses different kinds of toplevel + * windows, then you can use @ref KMainWindow::classNameOfToplevel(n) + * to determine the exact type before calling the childMW + * constructor in the example from above. + * + * If your client has only one kind of toplevel widgets (which + * should be pretty usual) then you should use the RESTORE-macro + * for backwards compatibility with 3.1 and 3.0 branches: + * + * <pre> + * if (kapp->isRestored()) + * RESTORE(childMW) + * else { + * // create default application as usual + * } + * </pre> + * + * The macro expands to the term above but is easier to use and + * less code to write. + * + * For new code or if you have more than one kind of toplevel + * widget (each derived from @ref KMainWindow, of course), you can + * use the templated @ref kRestoreMainWindows global functions: + * + * <pre> + * if (kapp->isRestored()) + * kRestoreMainWindows< childMW1, childMW2, childMW3 >(); + * else { + * // create default application as usual + * } + * </pre> + * + * Currently, these functions are provided for up to three + * template arguments. If you need more, tell us. To help you in + * deciding whether or not you can use @ref kRestoreMainWindows, a + * define KDE_RESTORE_MAIN_WINDOWS_NUM_TEMPLATE_ARGS is provided. + * + * @see restore() + * @see classNameOfToplevel() + * + **/ + static bool canBeRestored( int number ); + + /** + * Returns the @ref className() of the @p number of the toplevel window which + * should be restored. + * + * This is only useful if your application uses + * different kinds of toplevel windows. + */ + static const QString classNameOfToplevel( int number ); + + /** + * Restore the session specified by @p number. + * + * Returns @p false if this + * fails, otherwise returns @p true and shows the window. + * You should call @ref canBeRestored() first. + * If @p show is true (default), this widget will be shown automatically. + */ + bool restore( int number, bool show = TRUE ); + +//US virtual KXMLGUIFactory *guiFactory(); + + /** + * Create a GUI given a local XML file. + * + * If @p xmlfile is NULL, + * then it will try to construct a local XML filename like + * appnameui.rc where 'appname' is your app's name. If that file + * does not exist, then the XML UI code will only use the global + * (standard) XML file for the layout purposes. + * + * Note that when passing true for the conserveMemory argument subsequent + * calls to guiFactory()->addClient/removeClient may not work as expected. + * Also retrieving references to containers like popup menus or toolbars using + * the container method will not work. + * + * @param xmlfile The local xmlfile (relative or absolute) + * @param _conserveMemory Specify whether createGUI() should call + * @ref KXMLGuiClient::conserveMemory() to free all memory + * allocated by the @ref QDomDocument and by the KXMLGUIFactory. + */ + void createGUI( const QString &xmlfile = QString::null, bool _conserveMemory = TRUE ); + + /** + * Enables the build of a standard help menu when calling createGUI(). + * + * The default behavior is to build one, you must call this function + * to disable it + */ + void setHelpMenuEnabled(bool showHelpMenu = true); + + /** + * Return @p true when the help menu is enabled + */ + bool isHelpMenuEnabled(); + + + /** + * Returns true, if there is a menubar + * @since 3.1 + */ + bool hasMenuBar(); + + /** + * Returns a pointer to the menu bar. + * + * If there is no menu bar yet one will be created. + **/ +//US KMenuBar *menuBar(); + QMenuBar *menuBar(); + + /** + * Returns a pointer to the status bar. + * + * If there is no + * status bar yet one will be created. + */ +//US KStatusBar *statusBar(); + QStatusBar *statusBar(); + + /** + * List of members of KMainWindow class. + */ +//US static QPtrList<KMainWindow>* memberList; + + /** + * Returns a pointer to the toolbar with the specified name. + * This refers to toolbars created dynamically from the XML UI + * framework. If the toolbar does not exist one will be created. + * + * @param name The internal name of the toolbar. If no name is + * specified "mainToolBar" is assumed. + * + * @return A pointer to the toolbar + **/ + KToolBar *toolBar( const char *name=0 ); + // method for getting rid of KDE-Crap + QToolBar *tBar( ); + + /** + * @return An iterator over the list of all toolbars for this window. + */ + QPtrListIterator<KToolBar> toolBarIterator(); + + /** + * @return A KAccel instance bound to this mainwindow. Used automatically + * by KAction to make keybindings work in all cases. + */ + KAccel *accel(); + + void setFrameBorderWidth( int ) {} + + /** + * Call this to enable "auto-save" of toolbar/menubar/statusbar settings + * (and optionally window size). + * If the *bars were moved around/shown/hidden when the window is closed, + * saveMainWindowSettings( KGlobal::config(), groupName ) will be called. + * + * @param groupName a name that identifies this "type of window". + * You can have several types of window in the same application. + * + * @param saveWindowSize set it to true to include the window size + * when saving. + * + * Typically, you will call setAutoSaveSettings() in your + * KMainWindow-inherited class constructor, and it will take care + * of restoring and saving automatically. Make sure you call this + * _after all_ your *bars have been created. + */ + void setAutoSaveSettings( const QString & groupName = QString::fromLatin1("MainWindow"), + bool saveWindowSize = true ); + + /** + * Disable the auto-save-settings feature. + * You don't normally need to call this, ever. + */ + void resetAutoSaveSettings(); + + /** + * @return the current autosave setting, i.e. true if setAutoSaveSettings() was called, + * false by default or if resetAutoSaveSettings() was called. + * @since 3.1 + */ + bool autoSaveSettings() const; + + /** + * @return the group used for setting-autosaving. + * Only meaningful if setAutoSaveSettings() was called. + * This can be useful for forcing a save or an apply, e.g. before and after + * using KEditToolbar. + * @since 3.1 + */ + QString autoSaveGroup() const; + + /** + * Read settings for statusbar, menubar and toolbar from their respective + * groups in the config file and apply them. + * + * @param config Config file to read the settings from. + * @param groupName Group name to use. If not specified, the last used + * group name is used. + */ + void applyMainWindowSettings(KConfig *config, const QString &groupName = QString::null); + + /** + * Save settings for statusbar, menubar and toolbar to their respective + * groups in the config file @p config. + * + * @param config Config file to save the settings to. + * @param groupName Group name to use. If not specified, the last used + * group name is used + */ + void saveMainWindowSettings(KConfig *config, const QString &groupName = QString::null); + + /** + * Sets whether KMainWindow should provide a menu that allows showing/hiding + * the available toolbars ( using @ref KToggleToolBarAction ) . In case there + * is only one toolbar configured a simple 'Show <toolbar name here>' menu item + * is shown. + * + * The menu / menu item is implemented using xmlgui. It will be inserted in your + * menu structure in the 'Settings' menu. + * + * If your application uses a non-standard xmlgui resource file then you can + * specify the exact position of the menu / menu item by adding a + * <Merge name="StandardToolBarMenuHandler" /> + * line to the settings menu section of your resource file ( usually appname.rc ). + * + * Note that you should enable this feature before calling createGUI() ( or similar ) . + * You enable/disable it anytime if you pass false to the conserveMemory argument of createGUI. + * @since 3.1 + */ + void setStandardToolBarMenuEnabled( bool enable ); + /// @since 3.1 + bool isStandardToolBarMenuEnabled() const; + + + /** + * Sets whether KMainWindow should provide a menu that allows showing/hiding + * of the statusbar ( using @ref KToggleStatusBarAction ). + * + * The menu / menu item is implemented using xmlgui. It will be inserted + * in your menu structure in the 'Settings' menu. + * + * Note that you should enable this feature before calling createGUI() + * ( or similar ). + * + * If an application maintains the action on its own (i.e. never calls + * this function) a connection needs to be made to let KMainWindow + * know when that status (hidden/shown) of the statusbar has changed. + * For example: + * connect(action, SIGNAL(activated()), + * kmainwindow, SLOT(setSettingsDirty())); + * Otherwise the status (hidden/show) of the statusbar might not be saved + * by KMainWindow. + * @since 3.2 + */ + void createStandardStatusBarAction(); + + + /** + * Returns a pointer to the mainwindows action responsible for the toolbars menu + * @since 3.1 + */ + KAction *toolBarMenuAction(); + + // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; + /// @since 3.1 + virtual void finalizeGUI( KXMLGUIClient *client ); + + /** + * @internal + */ + void finalizeGUI( bool force ); + + /** + * @return true if a -geometry argument was given on the command line, + * and this is the first window created (the one on which this option applies) + */ + bool initialGeometrySet() const; + + /** + * @internal + * Used from Konqueror when reusing the main window. + */ + void ignoreInitialGeometry(); + + /** + * @return the size the mainwindow should have so that the central + * widget will be of @p size. + */ + QSize sizeForCentralWidgetSize(QSize size); + +public slots: + /** + * Makes a KDE compliant caption. + * + * @param caption Your caption. @em Do @em not include the application name + * in this string. It will be added automatically according to the KDE + * standard. + */ + virtual void setCaption( const QString &caption ); + /** + * Makes a KDE compliant caption. + * + * @param caption Your caption. @em Do @em not include the application name + * in this string. It will be added automatically according to the KDE + * standard. + * @param modified Specify whether the document is modified. This displays + * an additional sign in the title bar, usually "**". + */ + virtual void setCaption( const QString &caption, bool modified ); + + /** + * Make a plain caption without any modifications. + * + * @param caption Your caption. This is the string that will be + * displayed in the window title. + */ + virtual void setPlainCaption( const QString &caption ); + + /** + * Open the help page for the application. + * + * The application name is + * used as a key to determine what to display and the system will attempt + * to open <appName>/index.html. + * + * This method is intended for use by a help button in the toolbar or + * components outside the regular help menu. Use @ref helpMenu() when you + * want to provide access to the help system from the help menu. + * + * Example (adding a help button to the first toolbar): + * + * <pre> + * KIconLoader &loader = *KGlobal::iconLoader(); + * QPixmap pixmap = loader.loadIcon( "help" ); + * toolBar(0)->insertButton( pixmap, 0, SIGNAL(clicked()), + * this, SLOT(appHelpActivated()), true, i18n("Help") ); + * </pre> + * + */ +//US void appHelpActivated( void ); + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file + * @since 3.1 + */ + virtual void slotStateChanged(const QString &newstate); + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file, + * can "reverse" the state (disable the actions which should be + * enabled, and vice-versa) if specified. + * @since 3.1 + */ + void slotStateChanged(const QString &newstate, + KXMLGUIClient::ReverseStateChange); // KDE 4.0: remove this + + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file, + * can "reverse" the state (disable the actions which should be + * enabled, and vice-versa) if specified. + */ +// void slotStateChanged(const QString &newstate, +// bool reverse); // KDE 4.0: enable this + + /** + * Tell the main window that it should save its settings when being closed. + * This is part of the auto-save-settings feature. + * For everything related to toolbars this happens automatically, + * but you have to call setSettingsDirty() in the slot that toggles + * the visibility of the statusbar. + */ + void setSettingsDirty(); + +protected: + void paintEvent( QPaintEvent* e ); + void childEvent( QChildEvent* e); + void resizeEvent( QResizeEvent* e); + /** + * Reimplemented to call the queryClose() and queryExit() handlers. + * + * We recommend that you reimplement the handlers rather than @ref closeEvent(). + * If you do it anyway, ensure to call the base implementation to keep + * @ref queryExit() running. + */ + virtual void closeEvent ( QCloseEvent *); + + // KDE4 This seems to be flawed to me. Either the app has only one + // mainwindow, so queryClose() is enough, or if it can have more of them, + // then the windows should take care of themselves, and queryExit() + // would be useful only for the annoying 'really quit' dialog, which + // also doesn't make sense in apps with multiple mainwindows. + // And saving configuration in something called queryExit()? IMHO + // one can e.g. use KApplication::shutDown(), which if nothing else + // has at least better fitting name. + // See also KApplication::sessionSaving(). + // This stuff should get changed somehow, so that it at least doesn't + // mess with session management. + /** + Called before the very last window is closed, either by the + user or indirectly by the session manager. + + It is not recommended to do any user interaction in this + function other than indicating severe errors. Better ask the + user on @ref queryClose() (see below). + + A typical usage of @ref queryExit() is to write configuration data back. + Note that the application may continue to run after @ref queryExit() + (the user may have cancelled a shutdown), so you should not do any cleanups + here. The purpose of @ref queryExit() is purely to prepare the application + (with possible user interaction) so it can safely be closed later (without + user interaction). + + If you need to do serious things on exit (like shutting a + dial-up connection down), connect to the signal + @ref KApplication::shutDown(). + + Default implementation returns @p true. Returning @p false will + cancel the exiting. In the latter case, the last window will + remain visible. If KApplication::sessionSaving() is true, refusing + the exit will also cancel KDE logout. + + @see queryClose() + @see KApplication::sessionSaving() + */ + virtual bool queryExit(); + + /** + Called before the window is closed, either by the user or indirectly by + the session manager. + + The purpose of this function is to prepare the window in a way that it is + safe to close it, i.e. without the user losing some data. + + Default implementation returns true. Returning @p false will cancel + the closing, and, if KApplication::sessionSaving() is true, it will also + cancel KDE logout. + + Reimplement this function to prevent the user from losing data. + Example: + <pre> + + switch ( KMessageBox::warningYesNoCancel( this, + i18n("Save changes to document foo?")) ) { + case KMessageBox::Yes : + // save document here. If saving fails, return FALSE; + return TRUE; + case KMessageBox::No : + return TRUE; + default: // cancel + return FALSE; + + </pre> + + @see queryExit() + @see KApplication::sessionSaving() + + */ + virtual bool queryClose(); + /** + * Save your instance-specific properties. The function is + * invoked when the session manager requests your application + * to save its state. + * + * You @em must @em not change the group of the @p kconfig object, since + * KMainWindow uses one group for each window. Please + * reimplement these function in childclasses. + * + * Note: No user interaction is allowed + * in this function! + * + */ + virtual void saveProperties( KConfig* ) {} + + /** + * Read your instance-specific properties. + */ + virtual void readProperties( KConfig* ) {} + + /** + * Save your application-wide properties. The function is + * invoked when the session manager requests your application + * to save its state. + * + * This function is similar to @ref saveProperties() but is only called for + * the very first main window, regardless how many main window are open. + + * Override it if you need to save other data about your documents on + * session end. sessionConfig is a config to which that data should be + * saved. Normally, you don't need this function. But if you want to save + * data about your documents that are not in opened windows you might need + * it. + * + * Default implementation does nothing. + */ + virtual void saveGlobalProperties( KConfig* sessionConfig ); + + /** + * The counterpart of @ref saveGlobalProperties(). + * + * Read the application-specific properties in again. + */ + virtual void readGlobalProperties( KConfig* sessionConfig ); + void savePropertiesInternal( KConfig*, int ); + bool readPropertiesInternal( KConfig*, int ); + + /** + * For inherited classes + */ + bool settingsDirty() const; + /** + * For inherited classes + */ + QString settingsGroup() const; + /** + * For inherited classes + * Note that the group must be set before calling + */ + void saveWindowSize( KConfig * config ) const; + /** + * For inherited classes + * Note that the group must be set before calling, and that + * a -geometry on the command line has priority. + */ + void restoreWindowSize( KConfig * config ); + + /// parse the geometry from the geometry command line argument + void parseGeometry(bool parsewidth); + +protected slots: + + /** + * This slot does nothing. + * + * It must be reimplemented if you want + * to use a custom About Application dialog box. This slot is + * connected to the About Application entry in the menu returned + * by @ref customHelpMenu. + * + * Example: + * <pre> + * + * void MyMainLevel::setupInterface() + * { + * .. + * menuBar()->insertItem( i18n("&Help"), customHelpMenu() ); + * .. + * } + * + * void MyMainLevel::showAboutApplication() + * { + * <activate your custom dialog> + * } + * </pre> + */ +//US virtual void showAboutApplication(); + +private slots: + /** + * Called when the app is shutting down. + */ + void shuttingDown(); + + void saveAutoSaveSettings(); + +private: + QToolBar * mQToolBar; +//US KMenuBar *internalMenuBar(); + QMenuBar *internalMenuBar(); +//US KStatusBar *internalStatusBar(); + QStatusBar *internalStatusBar(); + + KMainWindowPrivate *d; + void initKMainWindow(const char *name); + + QPtrList<KToolBar> toolbarList; + +protected: + virtual void virtual_hook( int id, void* data ); + +}; + +#endif diff --git a/microkde/kdeui/knuminput.cpp b/microkde/kdeui/knuminput.cpp new file mode 100644 index 0000000..335d6f4 --- a/dev/null +++ b/microkde/kdeui/knuminput.cpp @@ -0,0 +1,1095 @@ +// -*- c-basic-offset: 4 -*- +/* + * knuminput.cpp + * + * Initial implementation: + * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca> + * Rewritten and maintained by: + * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org> + * KDoubleSpinBox: + * Copyright (c) 2002 Marc Mutz <mutz@kde.org> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +//US #include <config.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#include <assert.h> +#include <math.h> +#include <algorithm> + +#include <qlabel.h> +#include <qlineedit.h> +#include <qsize.h> +#include <qslider.h> +#include <qspinbox.h> +#include <qstyle.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "knumvalidator.h" +#include "knuminput.h" + +static inline int calcDiffByTen( int x, int y ) { + // calculate ( x - y ) / 10 without overflowing ints: + return ( x / 10 ) - ( y / 10 ) + ( x % 10 - y % 10 ) / 10; +} + +// ---------------------------------------------------------------------------- + +KNumInput::KNumInput(QWidget* parent, const char* name) + : QWidget(parent, name) +{ + init(); +} + +KNumInput::KNumInput(KNumInput* below, QWidget* parent, const char* name) + : QWidget(parent, name) +{ + init(); + + if(below) { + m_next = below->m_next; + m_prev = below; + below->m_next = this; + if(m_next) + m_next->m_prev = this; + } +} + +void KNumInput::init() +{ + m_prev = m_next = 0; + m_colw1 = m_colw2 = 0; + + m_label = 0; + m_slider = 0; + m_alignment = 0; +} + +KNumInput::~KNumInput() +{ + if(m_prev) + m_prev->m_next = m_next; + + if(m_next) + m_next->m_prev = m_prev; +} + +void KNumInput::setLabel(const QString & label, int a) +{ + if(label.isEmpty()) { + delete m_label; + m_label = 0; + m_alignment = 0; + } + else { + if (m_label) m_label->setText(label); + else m_label = new QLabel(label, this, "KNumInput::QLabel"); + m_label->setAlignment((a & (~(AlignTop|AlignBottom|AlignVCenter))) + | AlignVCenter); + // if no vertical alignment set, use Top alignment + if(!(a & (AlignTop|AlignBottom|AlignVCenter))) + a |= AlignTop; + m_alignment = a; + } + + layout(true); +} + +QString KNumInput::label() const +{ + if (m_label) return m_label->text(); + return QString::null; +} + +void KNumInput::layout(bool deep) +{ + int w1 = m_colw1; + int w2 = m_colw2; + + // label sizeHint + m_sizeLabel = (m_label ? m_label->sizeHint() : QSize(0,0)); + + if(m_label && (m_alignment & AlignVCenter)) + m_colw1 = m_sizeLabel.width() + 4; + else + m_colw1 = 0; + + // slider sizeHint + m_sizeSlider = (m_slider ? m_slider->sizeHint() : QSize(0, 0)); + + doLayout(); + + if(!deep) { + m_colw1 = w1; + m_colw2 = w2; + return; + } + + KNumInput* p = this; + while(p) { + p->doLayout(); + w1 = QMAX(w1, p->m_colw1); + w2 = QMAX(w2, p->m_colw2); + p = p->m_prev; + } + + p = m_next; + while(p) { + p->doLayout(); + w1 = QMAX(w1, p->m_colw1); + w2 = QMAX(w2, p->m_colw2); + p = p->m_next; + } + + p = this; + while(p) { + p->m_colw1 = w1; + p->m_colw2 = w2; + p = p->m_prev; + } + + p = m_next; + while(p) { + p->m_colw1 = w1; + p->m_colw2 = w2; + p = p->m_next; + } + +// kdDebug() << "w1 " << w1 << " w2 " << w2 << endl; +} + +QSizePolicy KNumInput::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ); +} + +QSize KNumInput::sizeHint() const +{ + return minimumSizeHint(); +} + +void KNumInput::setSteps(int minor, int major) +{ + if(m_slider) + m_slider->setSteps( minor, major ); +} + + +// ---------------------------------------------------------------------------- + +KIntSpinBox::KIntSpinBox(QWidget *parent, const char *name) + : QSpinBox(0, 99, 1, parent, name) +{ + editor()->setAlignment(AlignRight); + val_base = 10; + setValue(0); +} + +KIntSpinBox::~KIntSpinBox() +{ +} + +KIntSpinBox::KIntSpinBox(int lower, int upper, int step, int value, int base, + QWidget* parent, const char* name) + : QSpinBox(lower, upper, step, parent, name) +{ + editor()->setAlignment(AlignRight); + val_base = base; + setValue(value); +} + +void KIntSpinBox::setBase(int base) +{ + val_base = base; +} + + +int KIntSpinBox::base() const +{ + return val_base; +} + +QString KIntSpinBox::mapValueToText(int v) +{ + return QString::number(v, val_base); +} + +int KIntSpinBox::mapTextToValue(bool* ok) +{ + return cleanText().toInt(ok, val_base); +} + +void KIntSpinBox::setEditFocus(bool mark) +{ + editor()->setFocus(); + if(mark) + editor()->selectAll(); +} + + +// ---------------------------------------------------------------------------- + +class KIntNumInput::KIntNumInputPrivate { +public: + int referencePoint; + short blockRelative; + KIntNumInputPrivate( int r ) + : referencePoint( r ), + blockRelative( 0 ) {} +}; + + +KIntNumInput::KIntNumInput(KNumInput* below, int val, QWidget* parent, + int _base, const char* name) + : KNumInput(below, parent, name) +{ + init(val, _base); +} + +KIntNumInput::KIntNumInput(QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(0, 10); +} + +KIntNumInput::KIntNumInput(int val, QWidget *parent, int _base, const char *name) + : KNumInput(parent, name) +{ + init(val, _base); + +} + +void KIntNumInput::init(int val, int _base) +{ + d = new KIntNumInputPrivate( val ); + m_spin = new KIntSpinBox(INT_MIN, INT_MAX, 1, val, _base, this, "KIntNumInput::KIntSpinBox"); + m_spin->setValidator(new KIntValidator(this, _base, "KNumInput::KIntValidtr")); + connect(m_spin, SIGNAL(valueChanged(int)), SLOT(spinValueChanged(int))); + connect(this, SIGNAL(valueChanged(int)), + SLOT(slotEmitRelativeValueChanged(int))); + + setFocusProxy(m_spin); + layout(true); +} + +void KIntNumInput::setReferencePoint( int ref ) { + // clip to valid range: + ref = kMin( maxValue(), kMax( minValue(), ref ) ); + d->referencePoint = ref; +} + +int KIntNumInput::referencePoint() const { + return d->referencePoint; +} + +void KIntNumInput::spinValueChanged(int val) +{ + if(m_slider) + m_slider->setValue(val); + + emit valueChanged(val); +} + +void KIntNumInput::slotEmitRelativeValueChanged( int value ) { + if ( d->blockRelative || !d->referencePoint ) return; + emit relativeValueChanged( double( value ) / double( d->referencePoint ) ); +} + +void KIntNumInput::setRange(int lower, int upper, int step, bool slider) +{ + upper = kMax(upper, lower); + lower = kMin(upper, lower); + m_spin->setMinValue(lower); + m_spin->setMaxValue(upper); + m_spin->setLineStep(step); + + step = m_spin->lineStep(); // maybe QRangeControl didn't like out lineStep? + + if(slider) { + if (m_slider) + m_slider->setRange(lower, upper); + else { + m_slider = new QSlider(lower, upper, step, m_spin->value(), + QSlider::Horizontal, this); + m_slider->setTickmarks(QSlider::Below); + connect(m_slider, SIGNAL(valueChanged(int)), + m_spin, SLOT(setValue(int))); + } + + // calculate (upper-lower)/10 without overflowing int's: + int major = calcDiffByTen( upper, lower ); + if ( major==0 ) major = step; // #### workaround Qt bug in 2.1-beta4 + + m_slider->setSteps(step, major); + m_slider->setTickInterval(major); + } + else { + delete m_slider; + m_slider = 0; + } + + // check that reference point is still inside valid range: + setReferencePoint( referencePoint() ); + + layout(true); +} + +void KIntNumInput::setMinValue(int min) +{ + setRange(min, m_spin->maxValue(), m_spin->lineStep(), m_slider); +} + +int KIntNumInput::minValue() const +{ + return m_spin->minValue(); +} + +void KIntNumInput::setMaxValue(int max) +{ + setRange(m_spin->minValue(), max, m_spin->lineStep(), m_slider); +} + +int KIntNumInput::maxValue() const +{ + return m_spin->maxValue(); +} + +void KIntNumInput::setSuffix(const QString &suffix) +{ + m_spin->setSuffix(suffix); + + layout(true); +} + +QString KIntNumInput::suffix() const +{ + return m_spin->suffix(); +} + +void KIntNumInput::setPrefix(const QString &prefix) +{ + m_spin->setPrefix(prefix); + + layout(true); +} + +QString KIntNumInput::prefix() const +{ + return m_spin->prefix(); +} + +void KIntNumInput::setEditFocus(bool mark) +{ + m_spin->setEditFocus(mark); +} + +QSize KIntNumInput::minimumSizeHint() const +{ + constPolish(); + + int w; + int h; + + h = 2 + QMAX(m_sizeSpin.height(), m_sizeSlider.height()); + + // if in extra row, then count it here + if(m_label && (m_alignment & (AlignBottom|AlignTop))) + h += 4 + m_sizeLabel.height(); + else + // label is in the same row as the other widgets + h = QMAX(h, m_sizeLabel.height() + 2); + + w = m_slider ? m_slider->sizeHint().width() + 8 : 0; + w += m_colw1 + m_colw2; + + if(m_alignment & (AlignTop|AlignBottom)) + w = QMAX(w, m_sizeLabel.width() + 4); + + return QSize(w, h); +} + +void KIntNumInput::doLayout() +{ + m_sizeSpin = m_spin->sizeHint(); + m_colw2 = m_sizeSpin.width(); + + if (m_label) + m_label->setBuddy(m_spin); +} + +void KIntNumInput::resizeEvent(QResizeEvent* e) +{ + int w = m_colw1; + int h = 0; + + if(m_label && (m_alignment & AlignTop)) { + m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height()); + h += m_sizeLabel.height() + 4; + } + + if(m_label && (m_alignment & AlignVCenter)) + m_label->setGeometry(0, 0, w, m_sizeSpin.height()); + + m_spin->setGeometry(w, h, m_slider ? m_colw2 : QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height()); + w += m_colw2 + 8; + + if(m_slider) + m_slider->setGeometry(w, h, e->size().width() - w, m_sizeSpin.height()); + + h += m_sizeSpin.height() + 2; + + if(m_label && (m_alignment & AlignBottom)) + m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height()); +} + +KIntNumInput::~KIntNumInput() +{ + delete d; +} + +void KIntNumInput::setValue(int val) +{ + m_spin->setValue(val); + // slider value is changed by spinValueChanged +} + +void KIntNumInput::setRelativeValue( double r ) { + if ( !d->referencePoint ) return; + ++d->blockRelative; + setValue( int( d->referencePoint * r + 0.5 ) ); + --d->blockRelative; +} + +double KIntNumInput::relativeValue() const { + if ( !d->referencePoint ) return 0; + return double( value() ) / double ( d->referencePoint ); +} + +int KIntNumInput::value() const +{ + return m_spin->value(); +} + +void KIntNumInput::setSpecialValueText(const QString& text) +{ + m_spin->setSpecialValueText(text); + layout(true); +} + +QString KIntNumInput::specialValueText() const +{ + return m_spin->specialValueText(); +} + +void KIntNumInput::setLabel(const QString & label, int a) +{ + KNumInput::setLabel(label, a); + + if(m_label) + m_label->setBuddy(m_spin); +} + +// ---------------------------------------------------------------------------- + +class KDoubleNumInput::KDoubleNumInputPrivate { +public: + KDoubleNumInputPrivate( double r ) + : spin( 0 ), + referencePoint( r ), + blockRelative ( 0 ) {} + KDoubleSpinBox * spin; + double referencePoint; + short blockRelative; +}; + +KDoubleNumInput::KDoubleNumInput(QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(0.0, 0.0, 9999.0, 0.01, 2); +} + +KDoubleNumInput::KDoubleNumInput(double lower, double upper, double value, + double step, int precision, QWidget* parent, + const char *name) + : KNumInput(parent, name) +{ + init(value, lower, upper, step, precision); +} + +KDoubleNumInput::KDoubleNumInput(KNumInput *below, + double lower, double upper, double value, + double step, int precision, QWidget* parent, + const char *name) + : KNumInput(below, parent, name) +{ + init(value, lower, upper, step, precision); +} + +KDoubleNumInput::KDoubleNumInput(double value, QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 ); +} + +KDoubleNumInput::KDoubleNumInput(KNumInput* below, double value, QWidget* parent, + const char* name) + : KNumInput(below, parent, name) +{ + init( value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 ); +} + +KDoubleNumInput::~KDoubleNumInput() +{ + delete d; +} + +// ### remove when BIC changes are allowed again: + +bool KDoubleNumInput::eventFilter( QObject * o, QEvent * e ) { + return KNumInput::eventFilter( o, e ); +} + +void KDoubleNumInput::resetEditBox() { + +} + +// ### end stuff to remove when BIC changes are allowed again + + + +void KDoubleNumInput::init(double value, double lower, double upper, + double step, int precision ) +{ + // ### init no longer used members: + edit = 0; + m_range = true; + m_value = 0.0; + m_precision = 2; + // ### end + + d = new KDoubleNumInputPrivate( value ); + + d->spin = new KDoubleSpinBox( lower, upper, step, value, precision, + this, "KDoubleNumInput::d->spin" ); + setFocusProxy(d->spin); + connect( d->spin, SIGNAL(valueChanged(double)), + this, SIGNAL(valueChanged(double)) ); + connect( this, SIGNAL(valueChanged(double)), + this, SLOT(slotEmitRelativeValueChanged(double)) ); + + updateLegacyMembers(); + + layout(true); +} + +void KDoubleNumInput::updateLegacyMembers() { + // ### update legacy members that are either not private or for + // which an inlined getter exists: + m_lower = minValue(); + m_upper = maxValue(); + m_step = d->spin->lineStep(); + m_specialvalue = specialValueText(); +} + + +double KDoubleNumInput::mapSliderToSpin( int val ) const +{ + // map [slidemin,slidemax] to [spinmin,spinmax] + double spinmin = d->spin->minValue(); + double spinmax = d->spin->maxValue(); + double slidemin = m_slider->minValue(); // cast int to double to avoid + double slidemax = m_slider->maxValue(); // overflow in rel denominator + double rel = ( double(val) - slidemin ) / ( slidemax - slidemin ); + return spinmin + rel * ( spinmax - spinmin ); +} + +void KDoubleNumInput::sliderMoved(int val) +{ + d->spin->setValue( mapSliderToSpin( val ) ); +} + +void KDoubleNumInput::slotEmitRelativeValueChanged( double value ) +{ + if ( !d->referencePoint ) return; + emit relativeValueChanged( value / d->referencePoint ); +} + +QSize KDoubleNumInput::minimumSizeHint() const +{ + constPolish(); + + int w; + int h; + + h = 2 + QMAX(m_sizeEdit.height(), m_sizeSlider.height()); + + // if in extra row, then count it here + if(m_label && (m_alignment & (AlignBottom|AlignTop))) + h += 4 + m_sizeLabel.height(); + else + // label is in the same row as the other widgets + h = QMAX(h, m_sizeLabel.height() + 2); + + w = m_slider ? m_slider->sizeHint().width() + 8 : 0; + w += m_colw1 + m_colw2; + + if(m_alignment & (AlignTop|AlignBottom)) + w = QMAX(w, m_sizeLabel.width() + 4); + + return QSize(w, h); +} + +void KDoubleNumInput::resizeEvent(QResizeEvent* e) +{ + int w = m_colw1; + int h = 0; + + if(m_label && (m_alignment & AlignTop)) { + m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height()); + h += m_sizeLabel.height() + 4; + } + + if(m_label && (m_alignment & AlignVCenter)) + m_label->setGeometry(0, 0, w, m_sizeEdit.height()); + + d->spin->setGeometry(w, h, m_slider ? m_colw2 + : e->size().width() - w, m_sizeEdit.height()); + w += m_colw2 + 8; + + if(m_slider) + m_slider->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height()); + + h += m_sizeEdit.height() + 2; + + if(m_label && (m_alignment & AlignBottom)) + m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height()); +} + +void KDoubleNumInput::doLayout() +{ + m_sizeEdit = d->spin->sizeHint(); + m_colw2 = m_sizeEdit.width(); +} + +void KDoubleNumInput::setValue(double val) +{ + d->spin->setValue( val ); +} + +void KDoubleNumInput::setRelativeValue( double r ) +{ + if ( !d->referencePoint ) return; + ++d->blockRelative; + setValue( r * d->referencePoint ); + --d->blockRelative; +} + +void KDoubleNumInput::setReferencePoint( double ref ) +{ + // clip to valid range: + ref = kMin( maxValue(), kMax( minValue(), ref ) ); + d->referencePoint = ref; +} + +void KDoubleNumInput::setRange(double lower, double upper, double step, + bool slider) +{ + if( m_slider ) { + // don't update the slider to avoid an endless recursion + QSpinBox * spin = d->spin; + disconnect(spin, SIGNAL(valueChanged(int)), + m_slider, SLOT(setValue(int)) ); + } + d->spin->setRange( lower, upper, step, d->spin->precision() ); + + if(slider) { + // upcast to base type to get the min/maxValue in int form: + QSpinBox * spin = d->spin; + int slmax = spin->maxValue(); + int slmin = spin->minValue(); + int slvalue = spin->value(); + int slstep = spin->lineStep(); + if (m_slider) { + m_slider->setRange(slmin, slmax); + m_slider->setLineStep(slstep); + m_slider->setValue(slvalue); + } else { + m_slider = new QSlider(slmin, slmax, slstep, slvalue, + QSlider::Horizontal, this); + m_slider->setTickmarks(QSlider::Below); + // feedback line: when one moves, the other moves, too: + connect(m_slider, SIGNAL(valueChanged(int)), + SLOT(sliderMoved(int)) ); + } + connect(spin, SIGNAL(valueChanged(int)), + m_slider, SLOT(setValue(int)) ); + // calculate ( slmax - slmin ) / 10 without overflowing ints: + int major = calcDiffByTen( slmax, slmin ); + if ( !major ) major = slstep; // ### needed? + m_slider->setTickInterval(major); + } else { + delete m_slider; + m_slider = 0; + } + + setReferencePoint( referencePoint() ); + + layout(true); + updateLegacyMembers(); +} + +void KDoubleNumInput::setMinValue(double min) +{ + setRange(min, maxValue(), d->spin->lineStep(), m_slider); +} + +double KDoubleNumInput::minValue() const +{ + return d->spin->minValue(); +} + +void KDoubleNumInput::setMaxValue(double max) +{ + setRange(minValue(), max, d->spin->lineStep(), m_slider); +} + +double KDoubleNumInput::maxValue() const +{ + return d->spin->maxValue(); +} + +double KDoubleNumInput::value() const +{ + return d->spin->value(); +} + +double KDoubleNumInput::relativeValue() const +{ + if ( !d->referencePoint ) return 0; + return value() / d->referencePoint; +} + +double KDoubleNumInput::referencePoint() const +{ + return d->referencePoint; +} + +QString KDoubleNumInput::suffix() const +{ + return d->spin->suffix(); +} + +QString KDoubleNumInput::prefix() const +{ + return d->spin->prefix(); +} + +void KDoubleNumInput::setSuffix(const QString &suffix) +{ + d->spin->setSuffix( suffix ); + + layout(true); +} + +void KDoubleNumInput::setPrefix(const QString &prefix) +{ + d->spin->setPrefix( prefix ); + + layout(true); +} + +void KDoubleNumInput::setPrecision(int precision) +{ + d->spin->setPrecision( precision ); + + layout(true); +} + +int KDoubleNumInput::precision() const +{ + return d->spin->precision(); +} + +void KDoubleNumInput::setSpecialValueText(const QString& text) +{ + d->spin->setSpecialValueText( text ); + + layout(true); + updateLegacyMembers(); +} + +void KDoubleNumInput::setLabel(const QString & label, int a) +{ + KNumInput::setLabel(label, a); + + if(m_label) + m_label->setBuddy(d->spin); + +} + +// ---------------------------------------------------------------------------- + + +// We use a kind of fixed-point arithmetic to represent the range of +// doubles [mLower,mUpper] in steps of 10^(-mPrecision). Thus, the +// following relations hold: +// +// 1. factor = 10^mPrecision +// 2. basicStep = 1/factor = 10^(-mPrecision); +// 3. lowerInt = lower * factor; +// 4. upperInt = upper * factor; +// 5. lower = lowerInt * basicStep; +// 6. upper = upperInt * basicStep; +class KDoubleSpinBox::Private { +public: + Private( int precision=1 ) + : mPrecision( precision ), + mValidator( 0 ) + { + } + + int factor() const { + int f = 1; + for ( int i = 0 ; i < mPrecision ; ++i ) f *= 10; + return f; + } + + double basicStep() const { + return 1.0/double(factor()); + } + + int mapToInt( double value, bool * ok ) const { + assert( ok ); + const double f = factor(); + if ( value > double(INT_MAX) / f ) { + kdWarning() << "KDoubleSpinBox: can't represent value " << value + << "in terms of fixed-point numbers with precision " + << mPrecision << endl; + *ok = false; + return INT_MAX; + } else if ( value < double(INT_MIN) / f ) { + kdWarning() << "KDoubleSpinBox: can't represent value " << value + << "in terms of fixed-point numbers with precision " + << mPrecision << endl; + *ok = false; + return INT_MIN; + } else { + *ok = true; + return int( value * f + ( value < 0 ? -0.5 : 0.5 ) ); + } + } + + double mapToDouble( int value ) const { + return double(value) * basicStep(); + } + + int mPrecision; + KDoubleValidator * mValidator; +}; + +KDoubleSpinBox::KDoubleSpinBox( QWidget * parent, const char * name ) + : QSpinBox( parent, name ) +{ + editor()->setAlignment( Qt::AlignRight ); + d = new Private(); + updateValidator(); +} + +KDoubleSpinBox::KDoubleSpinBox( double lower, double upper, double step, + double value, int precision, + QWidget * parent, const char * name ) + : QSpinBox( parent, name ) +{ + editor()->setAlignment( Qt::AlignRight ); + d = new Private(); + setRange( lower, upper, step, precision ); + setValue( value ); + connect( this, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)) ); +} + +KDoubleSpinBox::~KDoubleSpinBox() { + delete d; d = 0; +} + +bool KDoubleSpinBox::acceptLocalizedNumbers() const { + if ( !d->mValidator ) return true; // we'll set one that does; + // can't do it now, since we're const + return d->mValidator->acceptLocalizedNumbers(); +} + +void KDoubleSpinBox::setAcceptLocalizedNumbers( bool accept ) { + if ( !d->mValidator ) updateValidator(); + d->mValidator->setAcceptLocalizedNumbers( accept ); +} + +void KDoubleSpinBox::setRange( double lower, double upper, double step, + int precision ) { + lower = kMin(upper, lower); + upper = kMax(upper, lower); + setPrecision( precision, true ); // disable bounds checking, since + setMinValue( lower ); // it's done in set{Min,Max}Value + setMaxValue( upper ); // anyway and we want lower, upper + setLineStep( step ); // and step to have the right precision +} + +int KDoubleSpinBox::precision() const { + return d->mPrecision; +} + +void KDoubleSpinBox::setPrecision( int precision ) { + setPrecision( precision, false ); +} + +void KDoubleSpinBox::setPrecision( int precision, bool force ) { + if ( precision < 1 ) return; + if ( !force ) { + int maxPrec = maxPrecision(); + if ( precision > maxPrec ) + precision = maxPrec; + } + d->mPrecision = precision; + updateValidator(); +} + +int KDoubleSpinBox::maxPrecision() const { + // INT_MAX must be > maxAbsValue * 10^precision + // ==> 10^precision < INT_MAX / maxAbsValue + // ==> precision < log10 ( INT_MAX / maxAbsValue ) + // ==> maxPrecision = floor( log10 ( INT_MAX / maxAbsValue ) ); + double maxAbsValue = kMax( fabs(minValue()), fabs(maxValue()) ); + if ( maxAbsValue == 0 ) return 6; // return arbitrary value to avoid dbz... + + return int( floor( log10( double(INT_MAX) / maxAbsValue ) ) ); +} + +double KDoubleSpinBox::value() const { + return d->mapToDouble( base::value() ); +} + +void KDoubleSpinBox::setValue( double value ) { + if ( value == this->value() ) return; + if ( value < minValue() ) + base::setValue( base::minValue() ); + else if ( value > maxValue() ) + base::setValue( base::maxValue() ); + else { + bool ok = false; + base::setValue( d->mapToInt( value, &ok ) ); + assert( ok ); + } +} + +double KDoubleSpinBox::minValue() const { + return d->mapToDouble( base::minValue() ); +} + +void KDoubleSpinBox::setMinValue( double value ) { + bool ok = false; + int min = d->mapToInt( value, &ok ); + if ( !ok ) return; + base::setMinValue( min ); + updateValidator(); +} + + +double KDoubleSpinBox::maxValue() const { + return d->mapToDouble( base::maxValue() ); +} + +void KDoubleSpinBox::setMaxValue( double value ) { + bool ok = false; + int max = d->mapToInt( value, &ok ); + if ( !ok ) return; + base::setMaxValue( max ); + updateValidator(); +} + +double KDoubleSpinBox::lineStep() const { + return d->mapToDouble( base::lineStep() ); +} + +void KDoubleSpinBox::setLineStep( double step ) { + bool ok = false; + if ( step > maxValue() - minValue() ) + base::setLineStep( 1 ); + else + base::setLineStep( kMax( d->mapToInt( step, &ok ), 1 ) ); +} + +QString KDoubleSpinBox::mapValueToText( int value ) { + if ( acceptLocalizedNumbers() ) + return KGlobal::locale() + ->formatNumber( d->mapToDouble( value ), d->mPrecision ); + else + return QString().setNum( d->mapToDouble( value ), 'f', d->mPrecision ); +} + +int KDoubleSpinBox::mapTextToValue( bool * ok ) { + double value; + if ( acceptLocalizedNumbers() ) + value = KGlobal::locale()->readNumber( cleanText(), ok ); + else + value = cleanText().toDouble( ok ); + if ( !*ok ) return 0; + if ( value > maxValue() ) + value = maxValue(); + else if ( value < minValue() ) + value = minValue(); + return d->mapToInt( value, ok ); +} + +void KDoubleSpinBox::setValidator( const QValidator * ) { + // silently discard the new validator. We don't want another one ;-) +} + +void KDoubleSpinBox::slotValueChanged( int value ) { + emit valueChanged( d->mapToDouble( value ) ); +} + +void KDoubleSpinBox::updateValidator() { + if ( !d->mValidator ) { + d->mValidator = new KDoubleValidator( minValue(), maxValue(), precision(), + this, "d->mValidator" ); + base::setValidator( d->mValidator ); + } else + d->mValidator->setRange( minValue(), maxValue(), precision() ); +} + +void KNumInput::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KIntNumInput::virtual_hook( int id, void* data ) +{ KNumInput::virtual_hook( id, data ); } + +void KDoubleNumInput::virtual_hook( int id, void* data ) +{ KNumInput::virtual_hook( id, data ); } + +void KIntSpinBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDoubleSpinBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "knuminput.moc" diff --git a/microkde/kdeui/knuminput.h b/microkde/kdeui/knuminput.h new file mode 100644 index 0000000..123fefa --- a/dev/null +++ b/microkde/kdeui/knuminput.h @@ -0,0 +1,948 @@ +/* + * knuminput.h + * + * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca> + * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org> + * Copyright (c) 2002 Marc Mutz <mutz@kde.org> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef K_NUMINPUT_H +#define K_NUMINPUT_H + +#include <qwidget.h> +#include <qspinbox.h> + +class QLabel; +class QSlider; +class QLineEdit; +class QLayout; +class QValidator; + +class KIntSpinBox; + +/* ------------------------------------------------------------------------ */ + +/** + * You need to inherit from this class if you want to implement K*NumInput + * for a different variable type + * + */ +class KNumInput : public QWidget +{ + Q_OBJECT + Q_PROPERTY( QString label READ label WRITE setLabel ) +public: + /** + * Default constructor + * + */ + KNumInput(QWidget* parent=0, const char* name=0); + + /** + * @param below A pointer to another KNumInput. + * + */ + KNumInput(KNumInput* below, QWidget* parent=0, const char* name=0); + ~KNumInput(); + + /** + * Sets the text and alignment of the main description label. + * + * @param label The text of the label. + * Use QString::null to remove an existing one. + * + * @param a one of @p AlignLeft, @p AlignHCenter, YAlignRight and + * @p AlignTop, @p AlignVCenter, @p AlignBottom. + * default is @p AlignLeft | @p AlignTop. + * + * The vertical alignment flags have special meaning with this + * widget: + * + * @li @p AlignTop The label is placed above the edit/slider + * @li @p AlignVCenter The label is placed left beside the edit + * @li @p AlignBottom The label is placed below the edit/slider + * + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + + /** + * @return the text of the label. + */ + QString label() const; + + /** + * @return if the num input has a slider. + * @since 3.1 + */ + bool showSlider() const { return m_slider; } + + /** + * Sets the spacing of tickmarks for the slider. + * + * @param minor Minor tickmark separation. + * @param major Major tickmark separation. + */ + void setSteps(int minor, int major); + + /** + * Specifies that this widget may stretch horizontally, but is + * fixed vertically (like @ref QSpinBox itself). + */ + QSizePolicy sizePolicy() const; + + /** + * Returns a size which fits the contents of the control. + * + * @return the preferred size necessary to show the control + */ + virtual QSize sizeHint() const; + +protected: + /** + * Call this function whenever you change something in the geometry + * of your KNumInput child. + * + */ + void layout(bool deep); + + /** + * You need to overwrite this method and implement your layout + * calculations there. + * + * See KIntNumInput::doLayout and KDoubleNumInput::doLayout implementation + * for details. + * + */ + virtual void doLayout() = 0; + + KNumInput* m_prev, *m_next; + int m_colw1, m_colw2; + + QLabel* m_label; + QSlider* m_slider; + QSize m_sizeSlider, m_sizeLabel; + + int m_alignment; + +private: + void init(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KNumInputPrivate; + KNumInputPrivate *d; +}; + +/* ------------------------------------------------------------------------ */ + +/** + * KIntNumInput combines a @ref QSpinBox and optionally a @ref QSlider + * with a label to make an easy to use control for setting some integer + * parameter. This is especially nice for configuration dialogs, + * which can have many such combinated controls. + * + * The slider is created only when the user specifies a range + * for the control using the setRange function with the slider + * parameter set to "true". + * + * A special feature of KIntNumInput, designed specifically for + * the situation when there are several KIntNumInputs in a column, + * is that you can specify what portion of the control is taken by the + * QSpinBox (the remaining portion is used by the slider). This makes + * it very simple to have all the sliders in a column be the same size. + * + * It uses @ref KIntValidator validator class. KIntNumInput enforces the + * value to be in the given range, and can display it in any base + * between 2 and 36. + * + * @short An input widget for integer numbers, consisting of a spinbox and a slider. + * @version $Id$ + */ + +class KIntNumInput : public KNumInput +{ + Q_OBJECT + Q_PROPERTY( int value READ value WRITE setValue ) + Q_PROPERTY( int minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue ) + Q_PROPERTY( int referencePoint READ referencePoint WRITE setReferencePoint ) + Q_PROPERTY( QString suffix READ suffix WRITE setSuffix ) + Q_PROPERTY( QString prefix READ prefix WRITE setPrefix ) + Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText ) + +public: + /** + * Constructs an input control for integer values + * with base 10 and initial value 0. + */ + KIntNumInput(QWidget *parent=0, const char *name=0); + /** + * Constructor + * It constructs a QSpinBox that allows the input of integer numbers + * in the range of -INT_MAX to +INT_MAX. To set a descriptive label, + * use setLabel(). To enforce the value being in a range and optionally to + * attach a slider to it, use setRange(). + * + * @param value initial value for the control + * @param base numeric base used for display + * @param parent parent QWidget + * @param name internal name for this widget + */ + KIntNumInput(int value, QWidget* parent=0, int base = 10, const char *name=0); + + /** + * Constructor + * + * the difference to the one above is the "below" parameter. It tells + * this instance that it is visually put below some other KNumInput widget. + * Note that these two KNumInput's need not to have the same parent widget + * or be in the same layout group. + * The effect is that it'll adjust it's layout in correspondence + * with the layout of the other KNumInput's (you can build an arbitary long + * chain). + * + * @param below append KIntNumInput to the KNumInput chain + * @param value initial value for the control + * @param base numeric base used for display + * @param parent parent QWidget + * @param name internal name for this widget + */ + KIntNumInput(KNumInput* below, int value, QWidget* parent=0, int base = 10, const char *name=0); + + /** + * Destructor + * + * + */ + virtual ~KIntNumInput(); + + /** + * @return the current value. + */ + int value() const; + + /** + * @return the curent value in units of the @ref referencePoint. + * @since 3.1 + */ + double relativeValue() const; + + /** + * @return the current reference point + * @since 3.1 + */ + int referencePoint() const; + + /** + * @return the suffix displayed behind the value. + * @see #setSuffix() + */ + QString suffix() const; + /** + * @return the prefix displayed in front of the value. + * @see #setPrefix() + */ + QString prefix() const; + /** + * @return the string displayed for a special value. + * @see #setSpecialValueText() + */ + QString specialValueText() const; + + /** + * @param min minimum value + * @param max maximum value + * @param step step size for the QSlider + */ + void setRange(int min, int max, int step=1, bool slider=true); + /** + * Sets the minimum value. + */ + void setMinValue(int min); + /** + * @return the minimum value. + */ + int minValue() const; + /** + * Sets the maximum value. + */ + void setMaxValue(int max); + /** + * @return the maximum value. + */ + int maxValue() const; + + /** + * Sets the special value text. If set, the SpinBox will display + * this text instead of the numeric value whenever the current + * value is equal to minVal(). Typically this is used for indicating + * that the choice has a special (default) meaning. + */ + void setSpecialValueText(const QString& text); + + /** + * @reimplemented + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + + /** + * This method returns the minimum size necessary to display the + * control. The minimum size is enough to show all the labels + * in the current font (font change may invalidate the return value). + * + * @return the minimum size necessary to show the control + */ + virtual QSize minimumSizeHint() const; + +public slots: + /** + * Sets the value of the control. + */ + void setValue(int); + + /** + * Sets the value in units of the @ref referencePoint + * @since 3.1 + */ + void setRelativeValue(double); + + /** + * Sets the reference point for @ref relativeValue. + * @since 3.1 + */ + void setReferencePoint(int); + + /** + * Sets the suffix to @p suffix. + * Use QString::null to disable this feature. + * Formatting has to be provided (e.g. a space separator between the + * prepended @p value and the suffix's text has to be provided + * as the first character in the suffix). + * + * @see QSpinBox::setSuffix(), #setPrefix() + */ + void setSuffix(const QString &suffix); + + /** + * Sets the prefix to @p prefix. + * Use QString::null to disable this feature. + * Formatting has to be provided (see above). + * + * @see QSpinBox::setPrefix(), #setSuffix() + */ + void setPrefix(const QString &prefix); + + /** + * sets focus to the edit widget and marks all text in if mark == true + * + */ + void setEditFocus( bool mark = true ); + +signals: + /** + * Emitted every time the value changes (by calling @ref setValue() or + * by user interaction). + */ + void valueChanged(int); + + /** + * Emitted whenever @ref #valueChanged is. Contains the change + * relative to the @ref referencePoint. + * @since 3.1 + */ + void relativeValueChanged(double); + +private slots: + void spinValueChanged(int); + void slotEmitRelativeValueChanged(int); + +protected: + /** + * @reimplemented + */ + virtual void doLayout(); + /** + * @reimplemented + */ + void resizeEvent ( QResizeEvent * ); + + KIntSpinBox* m_spin; + QSize m_sizeSpin; + +private: + void init(int value, int _base); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KIntNumInputPrivate; + KIntNumInputPrivate *d; +}; + + +/* ------------------------------------------------------------------------ */ + +class KDoubleLine; + +/** + * KDoubleNumInput combines a @ref QSpinBox and optionally a @ref QSlider + * with a label to make an easy to use control for setting some float + * parameter. This is especially nice for configuration dialogs, + * which can have many such combinated controls. + * + * The slider is created only when the user specifies a range + * for the control using the setRange function with the slider + * parameter set to "true". + * + * A special feature of KDoubleNumInput, designed specifically for + * the situation when there are several instances in a column, + * is that you can specify what portion of the control is taken by the + * QSpinBox (the remaining portion is used by the slider). This makes + * it very simple to have all the sliders in a column be the same size. + * + * It uses the @ref KDoubleValidator validator class. KDoubleNumInput + * enforces the value to be in the given range, but see the class + * documentation of @ref KDoubleSpinBox for the tricky + * interrelationship of precision and values. All of what is said + * there applies here, too. + * + * @see KIntNumInput, KDoubleSpinBox + * @short An input control for real numbers, consisting of a spinbox and a slider. + */ + +class KDoubleNumInput : public KNumInput +{ + Q_OBJECT + Q_PROPERTY( double value READ value WRITE setValue ) + Q_PROPERTY( double minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( double maxValue READ maxValue WRITE setMaxValue ) + Q_PROPERTY( QString suffix READ suffix WRITE setSuffix ) + Q_PROPERTY( QString prefix READ prefix WRITE setPrefix ) + Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText ) + Q_PROPERTY( int precision READ precision WRITE setPrecision ) + +public: + /** + * Constructs an input control for double values + * with initial value 0.00. + */ + KDoubleNumInput(QWidget *parent=0, const char *name=0); + + /** + * @deprecated (value is rounded to a multiple of 1/100) + * Constructor + * + * @param value initial value for the control + * @param parent parent QWidget + * @param name internal name for this widget + */ + KDoubleNumInput(double value, QWidget *parent=0, const char *name=0); + + /** + * Constructor + * + * @param lower lower boundary value + * @param upper upper boundary value + * @param value initial value for the control + * @param step step size to use for up/down arrow clicks + * @param precision number of digits after the decimal point + * @param parent parent QWidget + * @param name internal name for this widget + * @since 3.1 + */ + KDoubleNumInput(double lower, double upper, double value, double step=0.01, + int precision=2, QWidget *parent=0, const char *name=0); + + /** + * destructor + */ + virtual ~KDoubleNumInput(); + + /** + * @deprecated (rounds @p value to a mulitple of 1/100) + * Constructor + * + * puts it below other KNumInput + * + * @param below + * @param value initial value for the control + * @param parent parent QWidget + * @param name internal name for this widget + **/ + KDoubleNumInput(KNumInput* below, double value, QWidget* parent=0, const char* name=0); + + /** + * Constructor + * + * puts it below other KNumInput + * + * @param lower lower boundary value + * @param upper upper boundary value + * @param value initial value for the control + * @param step step size to use for up/down arrow clicks + * @param precision number of digits after the decimal point + * @param parent parent QWidget + * @param name internal name for this widget + * @since 3.1 + */ + KDoubleNumInput(KNumInput* below, + double lower, double upper, double value, double step=0.02, + int precision=2, QWidget *parent=0, const char *name=0); + + /** + * @return the current value. + */ + double value() const; + + /** + * @return the suffix. + * @see #setSuffix() + */ + QString suffix() const; + + /** + * @return the prefix. + * @see #setPrefix() + */ + QString prefix() const; + + /** + * @return the precision. + * @see #setPrecision() + */ + int precision() const; + + /** + * @return the string displayed for a special value. + * @see #setSpecialValueText() + */ + QString specialValueText() const { return m_specialvalue; } + + /** + * @param min minimum value + * @param max maximum value + * @param step step size for the QSlider + */ + void setRange(double min, double max, double step=1, bool slider=true); + /** + * Sets the minimum value. + */ + void setMinValue(double min); + /** + * @return the minimum value. + */ + double minValue() const; + /** + * Sets the maximum value. + */ + void setMaxValue(double max); + /** + * @return the maximum value. + */ + double maxValue() const; + + /** + * Specifies the number of digits to use. + */ + void setPrecision(int precision); + + /** + * @return the reference point for @ref #relativeValue calculation + * @since 3.1 + */ + double referencePoint() const; + + /** + * @return the current value in units of @ref #referencePoint. + * @since 3.1 + */ + double relativeValue() const; + + /** + * Sets the special value text. If set, the spin box will display + * this text instead of the numeric value whenever the current + * value is equal to @ref #minVal(). Typically this is used for indicating + * that the choice has a special (default) meaning. + */ + void setSpecialValueText(const QString& text); + + /** + * @reimplemented + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + /** + * @reimplemented + */ + virtual QSize minimumSizeHint() const; + /** + * @reimplemented + */ + virtual bool eventFilter(QObject*, QEvent*); + +public slots: + /** + * Sets the value of the control. + */ + void setValue(double); + + /** + * Sets the value in units of @ref #referencePoint. + * @since 3.1 + */ + void setRelativeValue(double); + + /** + * Sets the reference Point to @p ref. It @p ref == 0, emitting of + * @ref #relativeValueChanged is blocked and @ref #relativeValue + * just returns 0. + * @since 3.1 + */ + void setReferencePoint(double ref); + + /** + * Sets the suffix to be displayed to @p suffix. Use QString::null to disable + * this feature. Note that the suffix is attached to the value without any + * spacing. So if you prefer to display a space separator, set suffix + * to something like " cm". + * @see #setSuffix() + */ + void setSuffix(const QString &suffix); + + /** + * Sets the prefix to be displayed to @p prefix. Use QString::null to disable + * this feature. Note that the prefix is attached to the value without any + * spacing. + * @see #setPrefix() + */ + void setPrefix(const QString &prefix); + +signals: + /** + * Emitted every time the value changes (by calling @ref setValue() or + * by user interaction). + */ + void valueChanged(double); + /** + * This is an overloaded member function, provided for + * convenience. It essentially behaves like the above function. + * + * Contains the value in units of @ref #referencePoint. + * @since 3.1 + */ + void relativeValueChanged(double); + +private slots: + void sliderMoved(int); + void slotEmitRelativeValueChanged(double); + +protected: + + /** + * @reimplemented + */ + virtual void doLayout(); + /** + * @reimplemented + */ + void resizeEvent ( QResizeEvent * ); + virtual void resetEditBox(); + + // ### no longer used, remove when BIC allowed + KDoubleLine* edit; + + bool m_range; + double m_lower, m_upper, m_step; + // ### end no longer used + + QSize m_sizeEdit; + + friend class KDoubleLine; +private: + void init(double value, double lower, double upper, + double step, int precision); + double mapSliderToSpin(int) const; + void updateLegacyMembers(); + // ### no longer used, remove when BIC allowed: + QString m_specialvalue, m_prefix, m_suffix; + double m_value; + short m_precision; + // ### end remove when BIC allowed + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDoubleNumInputPrivate; + KDoubleNumInputPrivate *d; +}; + + +/* ------------------------------------------------------------------------ */ + +/** + * A @ref QSpinBox with support for arbitrary base numbers + * (e.g. hexadecimal). + * + * The class provides an easy interface to use other + * numeric systems than the decimal. + * + * @short A @ref QSpinBox with support for arbitrary base numbers. + */ +class KIntSpinBox : public QSpinBox +{ + Q_OBJECT + Q_PROPERTY( int base READ base WRITE setBase ) + +public: + + /** + * Constructor. + * + * Constructs a widget with an integer inputline with a little scrollbar + * and a slider, with minimal value 0, maximal value 99, step 1, base 10 + * and initial value 0. + */ + KIntSpinBox( QWidget *parent=0, const char *name=0); + + /** + * Constructor. + * + * Constructs a widget with an integer inputline with a little scrollbar + * and a slider. + * + * @param lower The lowest valid value. + * @param upper The greatest valid value. + * @param step The step size of the scrollbar. + * @param value The actual value. + * @param base The base of the used number system. + * @param parent The parent of the widget. + * @param name The Name of the widget. + */ + KIntSpinBox(int lower, int upper, int step, int value, int base = 10, + QWidget* parent = 0, const char* name = 0); + + /** + * Destructor. + */ + virtual ~KIntSpinBox(); + + /** + * Sets the base in which the numbers in the spin box are represented. + */ + void setBase(int base); + /** + * @return the base in which numbers in the spin box are represented. + */ + int base() const; + /** + * sets focus and optionally marks all text + * + */ + void setEditFocus(bool mark); + +protected: + + /** + * Overloaded the method in QSpinBox + * to make use of the base given in the constructor. + */ + virtual QString mapValueToText(int); + + /** + * Overloaded the method in QSpinBox + * to make use of the base given in the constructor. + */ + virtual int mapTextToValue(bool*); + +private: + int val_base; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KIntSpinBoxPrivate; + KIntSpinBoxPrivate *d; +}; + + +/* --------------------------------------------------------------------------- */ + +/** + This class provides a spin box for fractional numbers. + + @sect Parameters + + There are a number of interdependent parameters whose relation to + each other you need to understand in order to make successful use + of the spin box. + + @li precision: The number of decimals after the decimal point. + @li maxValue/minValue: upper and lower bound of the valid range + @li lineStep: the size of the step that is taken when the user hits + the up or down buttons + + Since we work with fixed-point numbers internally, the maximum + precision is a function of the valid range and vice versa. More + precisely, the following relations hold: + <pre> + max( abs(minValue()), abs(maxValue() ) <= INT_MAX/10^precision + maxPrecision = floor( log10( INT_MAX/max(abs(minValue()),abs(maxValue())) ) ) + </pre> + + Since the value, bounds and step are rounded to the current + precision, you may experience that the order of setting above + parameters matters. E.g. the following are @em not equivalent (try + it!): + + <pre> + // sets precision, + // then min/max value (rounded to precison and clipped to obtainable range if needed) + // then value and lineStep + KDoubleSpinBox * spin = new KDoubleSpinBox( 0, 9.999, 0.001, 4.321, 3, this ); + + // sets minValue to 0; maxValue to 10.00(!); value to 4.32(!) and only then + // increases the precision - too late, since e.g. value has already been rounded... + KDpubleSpinBox * spin = new KDoubleSpinBox( this ); + spin->setMinValue( 0 ); + spin->setMaxValue( 9.999 ); + spin->setValue( 4.321 ); + spin->setPrecision( 3 ); + </pre> + + @short A spin box for fractional numbers. + @author Marc Mutz <mutz@kde.org> + @version $Id$ + @since 3.1 +**/ + +class KDoubleSpinBox : public QSpinBox { + Q_OBJECT + Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers ) + Q_OVERRIDE( double maxValue READ maxValue WRITE setMaxValue ) + Q_OVERRIDE( double minValue READ minValue WRITE setMinValue ) + Q_OVERRIDE( double lineStep READ lineStep WRITE setLineStep ) + Q_OVERRIDE( double value READ value WRITE setValue ) + Q_PROPERTY( int precision READ precision WRITE setPrecision ) + +public: + /** Constructs a @ref KDoubleSpinBox with parent @p parent and + default values for range and value (whatever @ref QRangeControl + uses) and precision (2). */ + KDoubleSpinBox( QWidget * parent=0, const char * name=0 ); + /** Constructs a @ref KDoubleSpinBox with parent @p parent, range + [@p lower,@p upper], @ref lineStep @p step, @ref precision @p + precision and initial value @p value. */ + KDoubleSpinBox( double lower, double upper, double step, double value, + int precision=2, QWidget * parent=0, const char * name=0 ); + + virtual ~KDoubleSpinBox(); + + /** @return whether the spinbox uses localized numbers */ + bool acceptLocalizedNumbers() const; + /** Sets whether to use and accept localized numbers as returned by + @ref KLocale::formatNumber() */ + virtual void setAcceptLocalizedNumbers( bool accept ); + + /** Sets a new range for the spin box values. Note that @p lower, @p + upper and @p step are rounded to @p precision decimal points + first. */ + void setRange( double lower, double upper, double step=0.01, int precision=2 ); + + /** @return the current number of decimal points displayed. */ + int precision() const; + /** Equivalent to @ref setPrecsion( @p precison, @p false ); Needed + since Qt's moc doesn't ignore trailing parameters with default + args when searching for a property setter method. */ + void setPrecision( int precision ); + /** Sets the number of decimal points to use. Note that there is a + tradeoff between the precision used and the available range of + values. See the class docs for more. + @param precision the new number of decimal points to use + + @param force disables checking of bound violations that can + arise if you increase the precision so much that the + minimum and maximum values can't be represented + anymore. Disabling is useful if you don't want to keep + the current min and max values anyway. This is what + e.g. @ref setRange() does. + **/ + virtual void setPrecision( int precision, bool force ); + + /** @return the current value */ + double value() const; + /** @return the current lower bound */ + double minValue() const; + /** Sets the lower bound of the range to @p value, subject to the + contraints that @p value is first rounded to the current + precision and then clipped to the maximum representable + interval. + @see maxValue, minValue, setMaxValue, setRange + */ + void setMinValue( double value ); + /** @return the current upper bound */ + double maxValue() const; + /** Sets the upper bound of the range to @p value, subject to the + contraints that @p value is first rounded to the current + precision and then clipped to the maximum representable + interval. + @see minValue, maxValue, setMinValue, setRange + */ + void setMaxValue( double value ); + + /** @return the current step size */ + double lineStep() const; + /** Sets the step size for clicking the up/down buttons to @p step, + subject to the constraints that @p step is first rounded to the + current precision and then clipped to the meaningful interval + [1, @p maxValue - @p minValue]. */ + void setLineStep( double step ); + + /** Overridden to ignore any setValidator() calls. */ + void setValidator( const QValidator * ); + +signals: + /** Emitted whenever @ref QSpinBox::valueChanged( int ) is emitted. */ + void valueChanged( double value ); + +public slots: + /** Sets the current value to @p value, cubject to the constraints + that @p value is frist rounded to the current precision and then + clipped to the interval [@p minvalue(),@p maxValue()]. */ + virtual void setValue( double value ); + +protected: + virtual QString mapValueToText(int); + virtual int mapTextToValue(bool*); + +protected slots: + void slotValueChanged( int value ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + typedef QSpinBox base; + void updateValidator(); + int maxPrecision() const; + + class Private; + Private * d; +}; + +#endif // K_NUMINPUT_H diff --git a/microkde/kdeui/knumvalidator.cpp b/microkde/kdeui/knumvalidator.cpp new file mode 100644 index 0000000..78a8471 --- a/dev/null +++ b/microkde/kdeui/knumvalidator.cpp @@ -0,0 +1,372 @@ +/********************************************************************** +** +** $Id$ +** +** KIntValidator, KFloatValidator: +** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com> +** KDoubleValidator: +** Copyright (c) 2002 Marc Mutz <mutz@kde.org> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the Free +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** +*****************************************************************************/ + +#include <qwidget.h> +#include <qstring.h> + +#include "knumvalidator.h" +#include <klocale.h> +#include <kglobal.h> +#include <kdebug.h> + +/////////////////////////////////////////////////////////////// +// Implementation of KIntValidator +// + +KIntValidator::KIntValidator ( QWidget * parent, int base, const char * name ) + : QValidator(parent, name) +{ + _base = base; + if (_base < 2) _base = 2; + if (_base > 36) _base = 36; + + _min = _max = 0; +} + +KIntValidator::KIntValidator ( int bottom, int top, QWidget * parent, int base, const char * name ) + : QValidator(parent, name) +{ + _base = base; + if (_base > 36) _base = 36; + + _min = bottom; + _max = top; +} + +KIntValidator::~KIntValidator () +{} + +QValidator::State KIntValidator::validate ( QString &str, int & ) const +{ + bool ok; + int val = 0; + QString newStr; + + newStr = str.stripWhiteSpace(); + if (_base > 10) + newStr = newStr.upper(); + + if (newStr == QString::fromLatin1("-")) // a special case + if ((_min || _max) && _min >= 0) + ok = false; + else + return QValidator::Acceptable; + else if (newStr.length()) + val = newStr.toInt(&ok, _base); + else { + val = 0; + ok = true; + } + + if (! ok) + return QValidator::Invalid; + + if ((! _min && ! _max) || (val >= _min && val <= _max)) + return QValidator::Acceptable; + + if (_max && _min >= 0 && val < 0) + return QValidator::Invalid; + + return QValidator::Valid; +} + +void KIntValidator::fixup ( QString &str ) const +{ + int dummy; + int val; + QValidator::State state; + + state = validate(str, dummy); + + if (state == QValidator::Invalid || state == QValidator::Acceptable) + return; + + if (! _min && ! _max) + return; + + val = str.toInt(0, _base); + + if (val < _min) val = _min; + if (val > _max) val = _max; + + str.setNum(val, _base); +} + +void KIntValidator::setRange ( int bottom, int top ) +{ + _min = bottom; + _max = top; + + if (_max < _min) + _max = _min; +} + +void KIntValidator::setBase ( int base ) +{ + _base = base; + if (_base < 2) _base = 2; +} + +int KIntValidator::bottom () const +{ + return _min; +} + +int KIntValidator::top () const +{ + return _max; +} + +int KIntValidator::base () const +{ + return _base; +} + + +/////////////////////////////////////////////////////////////// +// Implementation of KFloatValidator +// + +class KFloatValidatorPrivate +{ +public: + KFloatValidatorPrivate() + { + } + ~KFloatValidatorPrivate() + { + } + bool acceptLocalizedNumbers; +}; + + +KFloatValidator::KFloatValidator ( QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers=false; + _min = _max = 0; +} + +KFloatValidator::KFloatValidator ( double bottom, double top, QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers=false; + _min = bottom; + _max = top; +} + +KFloatValidator::KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers = localeAware; + _min = bottom; + _max = top; +} + +KFloatValidator::~KFloatValidator () +{ + delete d; +} + +void KFloatValidator::setAcceptLocalizedNumbers(bool _b) +{ + d->acceptLocalizedNumbers=_b; +} + +bool KFloatValidator::acceptLocalizedNumbers() const +{ + return d->acceptLocalizedNumbers; +} + +QValidator::State KFloatValidator::validate ( QString &str, int & ) const +{ + bool ok; + double val = 0; + QString newStr; + newStr = str.stripWhiteSpace(); + + if (newStr == QString::fromLatin1("-")) // a special case + if ((_min || _max) && _min >= 0) + ok = false; + else + return QValidator::Acceptable; + else if (newStr == QString::fromLatin1(".") || (d->acceptLocalizedNumbers && newStr==KGlobal::locale()->decimalSymbol())) // another special case + return QValidator::Acceptable; + else if (newStr.length()) + { + val = newStr.toDouble(&ok); + if(!ok && d->acceptLocalizedNumbers) + val= KGlobal::locale()->readNumber(newStr,&ok); + } + else { + val = 0; + ok = true; + } + + if (! ok) + return QValidator::Invalid; + + if (( !_min && !_max) || (val >= _min && val <= _max)) + return QValidator::Acceptable; + + if (_max && _min >= 0 && val < 0) + return QValidator::Invalid; + + if ( (_min || _max) && (val < _min || val > _max)) + return QValidator::Invalid; + + return QValidator::Valid; +} + +void KFloatValidator::fixup ( QString &str ) const +{ + int dummy; + double val; + QValidator::State state; + + state = validate(str, dummy); + + if (state == QValidator::Invalid || state == QValidator::Acceptable) + return; + + if (! _min && ! _max) + return; + + val = str.toDouble(); + + if (val < _min) val = _min; + if (val > _max) val = _max; + + str.setNum(val); +} + +void KFloatValidator::setRange ( double bottom, double top ) +{ + _min = bottom; + _max = top; + + if (_max < _min) + _max = _min; +} + +double KFloatValidator::bottom () const +{ + return _min; +} + +double KFloatValidator::top () const +{ + return _max; +} + + + + +/////////////////////////////////////////////////////////////// +// Implementation of KDoubleValidator +// + +class KDoubleValidator::Private { +public: + Private( bool accept=true ) : acceptLocalizedNumbers( accept ) {} + + bool acceptLocalizedNumbers; +}; + +KDoubleValidator::KDoubleValidator( QObject * parent, const char * name ) + : QDoubleValidator( (QWidget*)parent, name ), d( 0 ) +{ + d = new Private(); +} + +KDoubleValidator::KDoubleValidator( double bottom, double top, int decimals, + QObject * parent, const char * name ) + : QDoubleValidator( bottom, top, decimals, (QWidget*)parent, name ), d( 0 ) +{ + d = new Private(); +} + +KDoubleValidator::~KDoubleValidator() +{ + delete d; +} + +bool KDoubleValidator::acceptLocalizedNumbers() const { + return d->acceptLocalizedNumbers; +} + +void KDoubleValidator::setAcceptLocalizedNumbers( bool accept ) { + d->acceptLocalizedNumbers = accept; +} + +QValidator::State KDoubleValidator::validate( QString & input, int & p ) const { + QString s = input; + if ( acceptLocalizedNumbers() ) { + KLocale * l = KGlobal::locale(); + // ok, we have to re-format the number to have: + // 1. decimalSymbol == '.' + // 2. negativeSign == '-' + // 3. positiveSign == <empty> + // 4. thousandsSeparator() == <empty> (we don't check that there + // are exactly three decimals between each separator): + QString d = l->decimalSymbol(), + n = l->negativeSign(), + p = l->positiveSign(), + t = l->thousandsSeparator(); + // first, delete p's and t's: + if ( !p.isEmpty() ) + for ( int idx = s.find( p ) ; idx >= 0 ; idx = s.find( p, idx ) ) + s.remove( idx, p.length() ); + + + if ( !t.isEmpty() ) + for ( int idx = s.find( t ) ; idx >= 0 ; idx = s.find( t, idx ) ) + s.remove( idx, t.length() ); + + // then, replace the d's and n's + if ( ( !n.isEmpty() && n.find('.') != -1 ) || + ( !d.isEmpty() && d.find('-') != -1 ) ) { + // make sure we don't replace something twice: + kdWarning() << "KDoubleValidator: decimal symbol contains '-' or " + "negative sign contains '.' -> improve algorithm" << endl; + return Invalid; + } + + if ( !d.isEmpty() && d != "." ) + for ( int idx = s.find( d ) ; idx >= 0 ; idx = s.find( d, idx + 1 ) ) + s.replace( idx, d.length(), "."); + + if ( !n.isEmpty() && n != "-" ) + for ( int idx = s.find( n ) ; idx >= 0 ; idx = s.find( n, idx + 1 ) ) + s.replace( idx, n.length(), "-" ); + } + + return base::validate( s, p ); +} + +//US #include "knumvalidator.moc" diff --git a/microkde/kdeui/knumvalidator.h b/microkde/kdeui/knumvalidator.h new file mode 100644 index 0000000..2f0a937 --- a/dev/null +++ b/microkde/kdeui/knumvalidator.h @@ -0,0 +1,209 @@ +/********************************************************************** +** +** $Id$ +** +** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com> +** Copyright (C) 2002 Marc Mutz <mutz@kde.org> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the Free +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** +*****************************************************************************/ + +#ifndef __KNUMVALIDATOR_H +#define __KNUMVALIDATOR_H + +#include <qvalidator.h> + +class QWidget; +class QString; + +/** + * @ref QValidator for integers. + + This can be used by @ref QLineEdit or subclass to provide validated + text entry. Can be provided with a base value (default is 10), to allow + the proper entry of hexadecimal, octal, or any other base numeric data. + + @author Glen Parker <glenebob@nwlink.com> + @version 0.0.1 +*/ +class KIntValidator : public QValidator { + + public: + /** + Constuctor. Also sets the base value. + */ + KIntValidator ( QWidget * parent, int base = 10, const char * name = 0 ); + /** + * Constructor. Also sets the minimum, maximum, and numeric base values. + */ + KIntValidator ( int bottom, int top, QWidget * parent, int base = 10, const char * name = 0 ); + /** + * Destructs the validator. + */ + virtual ~KIntValidator (); + /** + * Validates the text, and return the result. Does not modify the parameters. + */ + virtual State validate ( QString &, int & ) const; + /** + * Fixes the text if possible, providing a valid string. The parameter may be modified. + */ + virtual void fixup ( QString & ) const; + /** + * Sets the minimum and maximum values allowed. + */ + virtual void setRange ( int bottom, int top ); + /** + * Sets the numeric base value. + */ + virtual void setBase ( int base ); + /** + * Returns the current minimum value allowed. + */ + virtual int bottom () const; + /** + * Returns the current maximum value allowed. + */ + virtual int top () const; + /** + * Returns the current numeric base. + */ + virtual int base () const; + + private: + int _base; + int _min; + int _max; + +}; + +class KFloatValidatorPrivate; + +/** + @obsolete Use @ref KDoubleValidator + + @ref QValidator for floating point entry. + Extends the QValidator class to properly validate double numeric data. + This can be used by @ref QLineEdit or subclass to provide validated + text entry. + + @author Glen Parker <glenebob@nwlink.com> + @version 0.0.1 +*/ +class KFloatValidator : public QValidator { + + public: + /** + * Constructor. + */ + KFloatValidator ( QWidget * parent, const char * name = 0 ); + /** + * Constructor. Also sets the minimum and maximum values. + */ + KFloatValidator ( double bottom, double top, QWidget * parent, const char * name = 0 ); + /** + * Constructor. Sets the validator to be locale aware if @p localeAware is true. + */ + KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name = 0 ); + /** + * Destructs the validator. + */ + virtual ~KFloatValidator (); + /** + * Validates the text, and return the result. Does not modify the parameters. + */ + virtual State validate ( QString &, int & ) const; + /** + * Fixes the text if possible, providing a valid string. The parameter may be modified. + */ + virtual void fixup ( QString & ) const; + /** + * Sets the minimum and maximum value allowed. + */ + virtual void setRange ( double bottom, double top ); + /** + * Returns the current minimum value allowed. + */ + virtual double bottom () const; + /** + * Returns the current maximum value allowed. + */ + virtual double top () const; + /** + * Sets the validator to be locale aware if @p is true. In this case, the + * character KLocale::decimalSymbol() from the global locale is recognized + * as decimal separator. + */ + void setAcceptLocalizedNumbers(bool b); + /** + * Returns true if the validator is locale aware. + * @see setAcceptLocalizedNumbers(). + */ + bool acceptLocalizedNumbers() const; + + private: + double _min; + double _max; + + KFloatValidatorPrivate *d; +}; + +/** + KDoubleValidator extends @ref QDoubleValidator to be + locale-aware. That means that - subject to not being disabled - + @ref KLocale::decimalPoint(), @ref KLocale::thousandsSeparator() + and @ref KLocale::positiveSign() and @ref KLocale::negativeSign() + are respected. + + @short A locale-aware @ref QDoubleValidator + @author Marc Mutz <mutz@kde.org> + @version $Id$ + @see KIntValidator + @since 3.1 +**/ + +class KDoubleValidator : public QDoubleValidator { + Q_OBJECT + Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers ) +public: + /** Constuct a locale-aware KDoubleValidator with default range + (whatever @ref QDoubleValidator uses for that) and parent @p + parent */ + KDoubleValidator( QObject * parent, const char * name=0 ); + /** Constuct a locale-aware KDoubleValidator for range [@p bottom,@p + top] and a precision of @p decimals decimals after the decimal + point. */ + KDoubleValidator( double bottom, double top, int decimals, + QObject * parent, const char * name=0 ); + /** Destructs the validator. + */ + virtual ~KDoubleValidator(); + + /** Overloaded for internal reasons. The API is not affected. */ + virtual QValidator::State validate( QString & input, int & pos ) const; + + /** @return whether localized numbers are accepted (default: true) */ + bool acceptLocalizedNumbers() const; + /** Sets whether to accept localized numbers (default: true) */ + void setAcceptLocalizedNumbers( bool accept ); + +private: + typedef QDoubleValidator base; + class Private; + Private * d; +}; + +#endif diff --git a/microkde/kdeui/kseparator.cpp b/microkde/kdeui/kseparator.cpp new file mode 100644 index 0000000..d028420 --- a/dev/null +++ b/microkde/kdeui/kseparator.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <qstyle.h> + +#include <kdebug.h> +//US #include <kapplication.h> + +//US #include "kseparator.moc" + +#include "kseparator.h" + +KSeparator::KSeparator(QWidget* parent, const char* name, WFlags f) + : QFrame(parent, name, f) +{ + setLineWidth(1); + setMidLineWidth(0); + setOrientation( HLine ); +} + + + +KSeparator::KSeparator(int orientation, QWidget* parent, const char* name, WFlags f) + : QFrame(parent, name, f) +{ + setLineWidth(1); + setMidLineWidth(0); + setOrientation( orientation ); +} + + + +void KSeparator::setOrientation(int orientation) +{ + switch(orientation) + { + case Vertical: + case VLine: + setFrameStyle( QFrame::VLine | QFrame::Sunken ); + setMinimumSize(2, 0); + break; + + default: + kdWarning() << "KSeparator::setOrientation(): invalid orientation, using default orientation HLine" << endl; + + case Horizontal: + case HLine: + setFrameStyle( QFrame::HLine | QFrame::Sunken ); + setMinimumSize(0, 2); + break; + } +} + + + +int KSeparator::orientation() const +{ + if ( frameStyle() & VLine ) + return VLine; + + if ( frameStyle() & HLine ) + return HLine; + + return 0; +} + +void KSeparator::drawFrame(QPainter *p) +{ + QPoint p1, p2; + QRect r = frameRect(); + const QColorGroup & g = colorGroup(); + + if ( frameStyle() & HLine ) { + p1 = QPoint( r.x(), r.height()/2 ); + p2 = QPoint( r.x()+r.width(), p1.y() ); + } + else { + p1 = QPoint( r.x()+r.width()/2, 0 ); + p2 = QPoint( p1.x(), r.height() ); + } + +/*US + QStyleOption opt( lineWidth(), midLineWidth() ); + style().drawPrimitive( QStyle::PE_Separator, p, QRect( p1, p2 ), g, + QStyle::Style_Sunken, opt ); +*/ +//LRstyle().drawSeparator( p, p1.x(), p1.y(), p2.x(), p2.y(), g, true, lineWidth(), midLineWidth()); + +} + + +QSize KSeparator::sizeHint() const +{ + if ( frameStyle() & VLine ) + return QSize(2, 0); + + if ( frameStyle() & HLine ) + return QSize(0, 2); + + return QSize(-1, -1); +} + +void KSeparator::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdeui/kseparator.h b/microkde/kdeui/kseparator.h new file mode 100644 index 0000000..6d2712a --- a/dev/null +++ b/microkde/kdeui/kseparator.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __KSEPARATOR_H__ +#define __KSEPARATOR_H__ + +#include <qframe.h> + +/** + * Standard horizontal or vertical separator. + * + * @author Michael Roth <mroth@wirlweb.de> + * @version $Id$ +*/ +class KSeparator : public QFrame +{ + Q_OBJECT + Q_PROPERTY( int orientation READ orientation WRITE setOrientation ) + public: + /** + * Constructor. + **/ + KSeparator(QWidget* parent=0, const char* name=0, WFlags f=0); + /** + * Constructor. + * + * @param orientation Set the orientation of the separator. + * Possible values are HLine or Horizontal and VLine or Vertical. + **/ + KSeparator(int orientation, QWidget* parent=0, const char* name=0, + WFlags f=0); + + /** + * Returns the orientation of the separator. + * + * Possible values are VLine and HLine. + **/ + int orientation() const; + + /** + * Set the orientation of the separator to @p orient + * + * Possible values are VLine and HLine. + */ + void setOrientation(int orient); + + /** + * The recommended height (width) for a horizontal (vertical) separator. + **/ + virtual QSize sizeHint() const; + +protected: + virtual void drawFrame( QPainter * ); +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KSeparatorPrivate* d; +}; + + +#endif // __KSEPARATOR_H__ diff --git a/microkde/kdeui/ksqueezedtextlabel.cpp b/microkde/kdeui/ksqueezedtextlabel.cpp new file mode 100644 index 0000000..37fa29a --- a/dev/null +++ b/microkde/kdeui/ksqueezedtextlabel.cpp @@ -0,0 +1,107 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "ksqueezedtextlabel.h" +#include <qtooltip.h> + +KSqueezedTextLabel::KSqueezedTextLabel( const QString &text , QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); + fullText = text; + squeezeTextToLabel(); +} + +KSqueezedTextLabel::KSqueezedTextLabel( QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); +} + +void KSqueezedTextLabel::resizeEvent( QResizeEvent * ) { + squeezeTextToLabel(); +} + +QSize KSqueezedTextLabel::minimumSizeHint() const +{ + QSize sh = QLabel::minimumSizeHint(); + sh.setWidth(-1); + return sh; +} + +void KSqueezedTextLabel::setText( const QString &text ) { + fullText = text; + squeezeTextToLabel(); +} + +void KSqueezedTextLabel::squeezeTextToLabel() { + QFontMetrics fm(fontMetrics()); + int labelWidth = size().width(); + int textWidth = fm.width(fullText); + if (textWidth > labelWidth) { + // start with the dots only + QString squeezedText = "..."; + int squeezedWidth = fm.width(squeezedText); + + // estimate how many letters we can add to the dots on both sides + int letters = fullText.length() * (labelWidth - squeezedWidth) / textWidth / 2; + if (labelWidth < squeezedWidth) letters=1; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + + if (squeezedWidth < labelWidth) { + // we estimated too short + // add letters while text < label + do { + letters++; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth < labelWidth); + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + } else if (squeezedWidth > labelWidth) { + // we estimated too long + // remove letters while text > label + do { + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (letters && squeezedWidth > labelWidth); + } + + if (letters < 5) { + // too few letters added -> we give up squeezing + QLabel::setText(fullText); + } else { + QLabel::setText(squeezedText); + } + +//US QToolTip::remove( this ); +//US QToolTip::add( this, fullText ); + + } else { + QLabel::setText(fullText); + +//US QToolTip::remove( this ); +//US QToolTip::hide(); + + }; +} + +void KSqueezedTextLabel::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ksqueezedtextlabel.moc" diff --git a/microkde/kdeui/ksqueezedtextlabel.h b/microkde/kdeui/ksqueezedtextlabel.h new file mode 100644 index 0000000..1634adc --- a/dev/null +++ b/microkde/kdeui/ksqueezedtextlabel.h @@ -0,0 +1,76 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KSQUEEZEDTEXTLABEL_H +#define KSQUEEZEDTEXTLABEL_H + +#include <qlabel.h> + +/** + * A label class that squeezes its text into the label + * + * If the text is too long to fit into the label it is divided into + * remaining left and right parts which are separated by three dots. + * + * Example: + * http://www.kde.org/documentation/index.html could be squeezed to + * http://www.kde...ion/index.html + + * @short A replacement for QLabel that squeezes its text + * @author Ronny Standtke <Ronny.Standtke@gmx.de> + * @version $Id$ + * + */ + +/* + * @ref QLabel + */ +class KSqueezedTextLabel : public QLabel { + Q_OBJECT + +public: + /** + * Default constructor. + */ + KSqueezedTextLabel( QWidget *parent, const char *name = 0 ); + KSqueezedTextLabel( const QString &text, QWidget *parent, const char *name = 0 ); + + virtual QSize minimumSizeHint() const; + +public slots: + void setText( const QString & ); + +protected: + /** + * used when widget is resized + */ + void resizeEvent( QResizeEvent * ); + /** + * does the dirty work + */ + void squeezeTextToLabel(); + QString fullText; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KSqueezedTextLabelPrivate; + KSqueezedTextLabelPrivate *d; +}; + +#endif // KSQUEEZEDTEXTLABEL_H diff --git a/microkde/kdeui/kstdaction.cpp b/microkde/kdeui/kstdaction.cpp new file mode 100644 index 0000000..cfd7b54 --- a/dev/null +++ b/microkde/kdeui/kstdaction.cpp @@ -0,0 +1,362 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kstdaction.h" + +#include <qtoolbutton.h> +#include <qwhatsthis.h> + +//US #include <kaboutdata.h> +#include <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +//US #include <kstdaccel.h> +//US #include <kmainwindow.h> + +namespace KStdAction +{ + +struct KStdActionInfo +{ + StdAction id; +/*US KStdAccel::StdAccel idAccel;*/ + const char* psName; + const char* psLabel; + const char* psWhatsThis; + const char* psIconName; +}; + +const KStdActionInfo g_rgActionInfo[] = +{ + { New, /*USKStdAccel::New,*/ "file_new", I18N_NOOP("&New"), 0, "filenew" }, + { Open, /*USKStdAccel::Open,*/ "file_open", I18N_NOOP("&Open..."), 0, "fileopen" }, + { OpenRecent, /*USKStdAccel::AccelNone,*/ "file_open_recent", I18N_NOOP("Open &Recent"), 0, 0 }, + { Save, /*USKStdAccel::Save,*/ "file_save", I18N_NOOP("&Save"), 0, "filesave" }, + { SaveAs, /*USKStdAccel::AccelNone,*/ "file_save_as", I18N_NOOP("Save &As..."), 0, "filesaveas" }, + { Revert, /*USKStdAccel::AccelNone,*/ "file_revert", I18N_NOOP("Re&vert"), 0, "revert" }, + { Close, /*USKStdAccel::Close,*/ "file_close", I18N_NOOP("&Close"), 0, "fileclose" }, + { Print, /*USKStdAccel::Print,*/ "file_print", I18N_NOOP("&Print..."), 0, "fileprint" }, + { PrintPreview, /*USKStdAccel::AccelNone,*/ "file_print_preview", I18N_NOOP("Print Previe&w..."), 0, "filequickprint" }, + { Mail, /*USKStdAccel::AccelNone,*/ "file_mail", I18N_NOOP("&Mail..."), 0, "mail_send" }, + { Quit, /*USKStdAccel::Quit,*/ "file_quit", I18N_NOOP("&Exit"), 0, "exit" }, + + { Undo, /*USKStdAccel::Undo,*/ "edit_undo", I18N_NOOP("&Undo"), 0, "undo" }, + { Redo, /*USKStdAccel::Redo,*/ "edit_redo", I18N_NOOP("Re&do"), 0, "redo" }, + { Cut, /*USKStdAccel::Cut,*/ "edit_cut", I18N_NOOP("Cu&t"), 0, "editcut" }, + { Copy, /*USKStdAccel::Copy,*/ "edit_copy", I18N_NOOP("&Copy"), 0, "editcopy" }, + { Paste, /*USKStdAccel::Paste,*/ "edit_paste", I18N_NOOP("&Paste"), 0, "editpaste" }, + { SelectAll, /*USKStdAccel::SelectAll,*/ "edit_select_all", I18N_NOOP("Select &All"), 0, 0 }, + { Deselect, /*USKStdAccel::Deselect,*/ "edit_deselect", I18N_NOOP("Dese&lect"), 0, 0 }, + { Find, /*USKStdAccel::Find,*/ "edit_find", I18N_NOOP("&Find..."), 0, "find" }, + { FindNext, /*USKStdAccel::FindNext,*/ "edit_find_next", I18N_NOOP("Find &Next"), 0, "next" }, + // FIXME: rename edit_find_last to edit_find_prev for KDE 4 + { FindPrev, /*USKStdAccel::FindPrev,*/ "edit_find_last", I18N_NOOP("Find Pre&vious"), 0, "previous" }, + { Replace, /*USKStdAccel::Replace,*/ "edit_replace", I18N_NOOP("&Replace..."), 0, 0 }, + + { ActualSize, /*USKStdAccel::AccelNone,*/ "view_actual_size", I18N_NOOP("&Actual Size"), 0, 0 }, + { FitToPage, /*USKStdAccel::AccelNone,*/ "view_fit_to_page", I18N_NOOP("&Fit to Page"), 0, 0 }, + { FitToWidth, /*USKStdAccel::AccelNone,*/ "view_fit_to_width", I18N_NOOP("Fit to Page &Width"), 0, 0 }, + { FitToHeight, /*USKStdAccel::AccelNone,*/ "view_fit_to_height", I18N_NOOP("Fit to Page &Height"), 0, 0 }, + { ZoomIn, /*USKStdAccel::ZoomIn,*/ "view_zoom_in", I18N_NOOP("Zoom &In"), 0, "viewmag+" }, + { ZoomOut, /*USKStdAccel::ZoomOut,*/ "view_zoom_out", I18N_NOOP("Zoom &Out"), 0, "viewmag-" }, + { Zoom, /*USKStdAccel::AccelNone,*/ "view_zoom", I18N_NOOP("&Zoom..."), 0, "viewmag" }, + { Redisplay, /*USKStdAccel::AccelNone,*/ "view_redisplay", I18N_NOOP("&Redisplay"), 0, "reload" }, + + { Up, /*USKStdAccel::Up,*/ "go_up", I18N_NOOP("&Up"), 0, "up" }, + // The following three have special i18n() needs for sLabel + { Back, /*USKStdAccel::Back,*/ "go_back", 0, 0, "back" }, + { Forward, /*USKStdAccel::Forward,*/ "go_forward", 0, 0, "forward" }, + { Home, /*USKStdAccel::Home,*/ "go_home", 0, 0, "gohome" }, + { Prior, /*USKStdAccel::Prior,*/ "go_previous", I18N_NOOP("&Previous Page"), 0, "previous" }, + { Next, /*USKStdAccel::Next,*/ "go_next", I18N_NOOP("&Next Page"), 0, "next" }, + { Goto, /*USKStdAccel::AccelNone,*/ "go_goto", I18N_NOOP("&Go To..."), 0, 0 }, + { GotoPage, /*USKStdAccel::AccelNone,*/ "go_goto_page", I18N_NOOP("&Go to Page..."), 0, "goto" }, + { GotoLine, /*USKStdAccel::GotoLine,*/ "go_goto_line", I18N_NOOP("&Go to Line..."), 0, 0 }, + { FirstPage, /*USKStdAccel::Home,*/ "go_first", I18N_NOOP("&First Page"), 0, "top" }, + { LastPage, /*USKStdAccel::End,*/ "go_last", I18N_NOOP("&Last Page"), 0, "bottom" }, + + { AddBookmark, /*USKStdAccel::AddBookmark,*/ "bookmark_add", I18N_NOOP("&Add Bookmark"), 0, "bookmark_add" }, + { EditBookmarks, /*USKStdAccel::AccelNone,*/ "bookmark_edit", I18N_NOOP("&Edit Bookmarks"), 0, "bookmark" }, + + { Spelling, /*USKStdAccel::AccelNone,*/ "tools_spelling", I18N_NOOP("&Spelling..."), 0, "spellcheck" }, + + { ShowMenubar, /*USKStdAccel::ShowMenubar,*/ "options_show_menubar", I18N_NOOP("Show &Menubar"), 0, "showmenu" }, + { ShowToolbar, /*USKStdAccel::AccelNone,*/ "options_show_toolbar", I18N_NOOP("Show &Toolbar"), 0, 0 }, + { ShowStatusbar, /*USKStdAccel::AccelNone,*/ "options_show_statusbar", I18N_NOOP("Show St&atusbar"), 0, 0 }, + { SaveOptions, /*USKStdAccel::AccelNone,*/ "options_save_options", I18N_NOOP("&Save Settings"), 0, 0 }, + { KeyBindings, /*USKStdAccel::AccelNone,*/ "options_configure_keybinding", I18N_NOOP("Configure S&hortcuts..."), 0,"configure_shortcuts" }, + { Preferences, /*USKStdAccel::AccelNone,*/ "options_configure", I18N_NOOP("&Configure %1..."), 0, "configure" }, + { ConfigureToolbars, /*USKStdAccel::AccelNone,*/ "options_configure_toolbars", I18N_NOOP("Configure Tool&bars..."), 0,"configure_toolbars" }, + { ConfigureNotifications, /*USKStdAccel::AccelNone,*/ "options_configure_notifications", I18N_NOOP("Configure &Notifications..."), 0, "knotify" }, + + { Help, /*USKStdAccel::Help,*/ "help", 0, 0, "help" }, + { HelpContents, /*USKStdAccel::AccelNone,*/ "help_contents", I18N_NOOP("%1 &Handbook"), 0, "contents" }, + { WhatsThis, /*USKStdAccel::WhatsThis,*/ "help_whats_this", I18N_NOOP("What's &This?"), 0, "contexthelp" }, + { TipofDay, /*USKStdAccel::AccelNone,*/ "help_show_tip", I18N_NOOP("Tip of the &Day"), 0, "idea" }, + { ReportBug, /*USKStdAccel::AccelNone,*/ "help_report_bug", I18N_NOOP("&Report Bug..."), 0, 0 }, + { AboutApp, /*USKStdAccel::AccelNone,*/ "help_about_app", I18N_NOOP("&About %1"), 0, 0 }, + { AboutKDE, /*USKStdAccel::AccelNone,*/ "help_about_kde", I18N_NOOP("About &KDE"), 0,"about_kde" }, + { ActionNone, /*USKStdAccel::AccelNone,*/ 0, 0, 0, 0 } +}; + +static const KStdActionInfo* infoPtr( StdAction id ) +{ + for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ ) { + if( g_rgActionInfo[i].id == id ) + return &g_rgActionInfo[i]; + } + return 0; +} + +QStringList stdNames() +{ + QStringList result; + + for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ ) + if (g_rgActionInfo[i].psLabel) + result.append(i18n(g_rgActionInfo[i].psLabel)); + return result; +} + +KAction* create( StdAction id, const char *name, const QObject *recvr, const char *slot, KActionCollection* parent ) +{ + KAction* pAction = 0; + const KStdActionInfo* pInfo = infoPtr( id ); + kdDebug(125) << "KStdAction::create( " << id << "=" << (pInfo ? pInfo->psName : (const char*)0) << ", " << parent << ", " << name << " )" << endl; // ellis + if( pInfo ) { + QString sLabel, iconName = pInfo->psIconName; + switch( id ) { + case Back: sLabel = i18n("go back", "&Back"); +//US if (QApplication::reverseLayout() ) +//US iconName = "forward"; + break; + + case Forward: sLabel = i18n("go forward", "&Forward"); +//US if (QApplication::reverseLayout() ) +//US iconName = "back"; + break; + + case Home: sLabel = i18n("beginning (of line)", "&Home"); break; + case Help: sLabel = i18n("show help", "&Help"); break; +//US case AboutApp: iconName = kapp->miniIconName(); + case Preferences: + case HelpContents: + { +//US const KAboutData *aboutData = KGlobal::instance()->aboutData(); +//US QString appName = (aboutData) ? aboutData->programName() : QString::fromLatin1(qApp->name()); + QString appName = QString::fromLatin1(KGlobal::getAppName()); + sLabel = i18n(pInfo->psLabel).arg(appName); + } + break; + default: sLabel = i18n(pInfo->psLabel); + } + +/*US if (QApplication::reverseLayout()){ + if (id == Prior) iconName = "next"; + if (id == Next ) iconName = "previous"; + } +*/ +//US KShortcut cut = KStdAccel::shortcut(pInfo->idAccel); + KShortcut cut; + switch( id ) { + case OpenRecent: + pAction = new KRecentFilesAction( sLabel, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + break; + case ShowMenubar: + case ShowToolbar: + case ShowStatusbar: + KToggleAction *ret; + ret = new KToggleAction( sLabel, pInfo->psIconName, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + ret->setChecked( true ); + pAction = ret; + break; + default: + pAction = new KAction( sLabel, iconName, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + break; + } + } + return pAction; +} + +const char* name( StdAction id ) +{ + const KStdActionInfo* pInfo = infoPtr( id ); + return (pInfo) ? pInfo->psName : 0; +} + +KAction *openNew( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( New, name, recvr, slot, parent ); } +KAction *open( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Open, name, recvr, slot, parent ); } +KRecentFilesAction *openRecent( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return (KRecentFilesAction*) KStdAction::create( OpenRecent, name, recvr, slot, parent ); } +KAction *save( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Save, name, recvr, slot, parent ); } +KAction *saveAs( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SaveAs, name, recvr, slot, parent ); } +KAction *revert( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Revert, name, recvr, slot, parent ); } +KAction *print( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Print, name, recvr, slot, parent ); } +KAction *printPreview( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( PrintPreview, name, recvr, slot, parent ); } +KAction *close( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Close, name, recvr, slot, parent ); } +KAction *mail( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Mail, name, recvr, slot, parent ); } +KAction *quit( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Quit, name, recvr, slot, parent ); } +KAction *undo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Undo, name, recvr, slot, parent ); } +KAction *redo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Redo, name, recvr, slot, parent ); } +KAction *cut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Cut, name, recvr, slot, parent ); } +KAction *copy( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Copy, name, recvr, slot, parent ); } +KAction *paste( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Paste, name, recvr, slot, parent ); } +KAction *selectAll( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SelectAll, name, recvr, slot, parent ); } +KAction *deselect( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Deselect, name, recvr, slot, parent ); } +KAction *find( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Find, name, recvr, slot, parent ); } +KAction *findNext( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FindNext, name, recvr, slot, parent ); } +KAction *findPrev( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FindPrev, name, recvr, slot, parent ); } +KAction *replace( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Replace, name, recvr, slot, parent ); } +KAction *actualSize( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ActualSize, name, recvr, slot, parent ); } +KAction *fitToPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToPage, name, recvr, slot, parent ); } +KAction *fitToWidth( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToWidth, name, recvr, slot, parent ); } +KAction *fitToHeight( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToHeight, name, recvr, slot, parent ); } +KAction *zoomIn( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ZoomIn, name, recvr, slot, parent ); } +KAction *zoomOut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ZoomOut, name, recvr, slot, parent ); } +KAction *zoom( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Zoom, name, recvr, slot, parent ); } +KAction *redisplay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Redisplay, name, recvr, slot, parent ); } +KAction *up( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Up, name, recvr, slot, parent ); } +KAction *back( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Back, name, recvr, slot, parent ); } +KAction *forward( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Forward, name, recvr, slot, parent ); } +KAction *home( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Home, name, recvr, slot, parent ); } +KAction *prior( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Prior, name, recvr, slot, parent ); } +KAction *next( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Next, name, recvr, slot, parent ); } +KAction *goTo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Goto, name, recvr, slot, parent ); } +KAction *gotoPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( GotoPage, name, recvr, slot, parent ); } +KAction *gotoLine( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( GotoLine, name, recvr, slot, parent ); } +KAction *firstPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FirstPage, name, recvr, slot, parent ); } +KAction *lastPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( LastPage, name, recvr, slot, parent ); } +KAction *addBookmark( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AddBookmark, name, recvr, slot, parent ); } +KAction *editBookmarks( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( EditBookmarks, name, recvr, slot, parent ); } +KAction *spelling( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Spelling, name, recvr, slot, parent ); } + +KToggleAction *showMenubar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show &Menubar"), "showmenu", /*US KStdAccel::shortcut(KStdAccel::ShowMenubar)*/0, recvr, slot, + parent, _name ? _name : name(ShowMenubar)); + ret->setChecked(true); + return ret; +} + +KToggleAction *showToolbar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show &Toolbar"), 0, recvr, slot, parent, + _name ? _name : name(ShowToolbar)); + ret->setChecked(true); + return ret; + +} + +KToggleToolBarAction *showToolbar( const char* toolBarName, KActionCollection* parent, const char *_name ) +{ + KToggleToolBarAction *ret; + ret = new KToggleToolBarAction(toolBarName, i18n("Show &Toolbar"), parent, + _name ? _name : name(ShowToolbar)); + return ret; +} + +KToggleAction *showStatusbar( const QObject *recvr, const char *slot, + KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show St&atusbar"), 0, recvr, slot, parent, + _name ? _name : name(ShowStatusbar)); + ret->setChecked(true); + return ret; +} + +KAction *saveOptions( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SaveOptions, name, recvr, slot, parent ); } +KAction *keyBindings( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( KeyBindings, name, recvr, slot, parent ); } +KAction *preferences( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Preferences, name, recvr, slot, parent ); } +KAction *configureToolbars( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ConfigureToolbars, name, recvr, slot, parent ); } +KAction *configureNotifications( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ConfigureNotifications, name, recvr, slot, parent ); } +KAction *help( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Help, name, recvr, slot, parent ); } +KAction *helpContents( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( HelpContents, name, recvr, slot, parent ); } +KAction *whatsThis( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( WhatsThis, name, recvr, slot, parent ); } +KAction *tipOfDay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( TipofDay, name, recvr, slot, parent ); } +KAction *reportBug( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ReportBug, name, recvr, slot, parent ); } +KAction *aboutApp( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AboutApp, name, recvr, slot, parent ); } +KAction *aboutKDE( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AboutKDE, name, recvr, slot, parent ); } + +} diff --git a/microkde/kdeui/kstdaction.h b/microkde/kdeui/kstdaction.h new file mode 100644 index 0000000..bc712b3 --- a/dev/null +++ b/microkde/kdeui/kstdaction.h @@ -0,0 +1,568 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org> + Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSTDACTION_H +#define KSTDACTION_H + +class QObject; +class KAction; +class KActionCollection; +class KRecentFilesAction; +class KToggleAction; +class KToggleToolBarAction; + +#include <qstringlist.h> + +/** + * Convenience methods to access all standard KDE actions. + * + * These actions should be used instead of hardcoding menubar and + * toolbar items. Using these actions helps your application easily + * conform to the KDE UI Style Guide + * @see http://developer.kde.org/documentation/standards/kde/style/basics/index.html . + * + * All of the documentation for @ref KAction holds for KStdAction + * also. When in doubt on how things work, check the @ref KAction + * documention first. + * + * @sect Simple Example: + * + * In general, using standard actions should be a drop in replacement + * for regular actions. For example, if you previously had: + * + * <PRE> + * KAction *newAct = new KAction(i18n("&New"), QIconSet(BarIcon("filenew")), + * KStdAccel::key(KStdAccel::New), this, + * SLOT(fileNew()), actionCollection()); + * </PRE> + * + * You could drop that and replace it with: + * + * <PRE> + * KAction *newAct = KStdAction::openNew(this, SLOT(fileNew()), + * actionCollection()); + * </PRE> + * + * @sect Non-standard Usages + * + * It is possible to use the standard actions in various + * non-recommended ways. Say, for instance, you wanted to have a + * standard action (with the associated correct text and icon and + * accelerator, etc) but you didn't want it to go in the standard + * place (this is not recommended, by the way). One way to do this is + * to simply not use the XML UI framework and plug it into wherever + * you want. If you do want to use the XML UI framework (good!), then + * it is still possible. + * + * Basically, the XML building code matches names in the XML code with + * the internal names of the actions. You can find out the internal + * names of each of the standard actions by using the @ref stdName + * action like so: @ref KStdAction::stdName(KStdAction::Cut) would return + * 'edit_cut'. The XML building code will match 'edit_cut' to the + * attribute in the global XML file and place your action there. + * + * However, you can change the internal name. In this example, just + * do something like: + * + * <PRE> + * (void)KStdAction::cut(this, SLOT(editCut()), actionCollection(), "my_cut"); + * </PRE> + * + * Now, in your local XML resource file (e.g., yourappui.rc), simply + * put 'my_cut' where you want it to go. + * + * Another non-standard usage concerns getting a pointer to an + * existing action if, say, you want to enable or disable the action. + * You could do it the recommended way and just grab a pointer when + * you instantiate it as in the the 'openNew' example above... or you + * could do it the hard way: + * + * <pre> + * KAction *cut = actionCollection()->action(KStdAction::stdName(KStdAction::Cut)); + * </pre> + * + * Another non-standard usage concerns instantiating the action in the + * first place. Usually, you would use the member functions as + * shown above (e.g., KStdAction::cut(this, SLOT, parent)). You + * may, however, do this using the enums provided. This author can't + * think of a reason why you would want to, but, hey, if you do, + * here's how: + * + * <pre> + * (void)KStdAction::action(KStdAction::New, this, SLOT(fileNew()), actionCollection()); + * (void)KStdAction::action(KStdAction::Cut, this, SLOT(editCut()), actionCollection()); + * </pre> + * + * @author Kurt Granroth <granroth@kde.org> + */ +namespace KStdAction +{ + /** + * The standard menubar and toolbar actions. + */ + enum StdAction { + ActionNone, + + // File Menu + New, Open, OpenRecent, Save, SaveAs, Revert, Close, + Print, PrintPreview, Mail, Quit, + + // Edit Menu + Undo, Redo, Cut, Copy, Paste, SelectAll, Deselect, Find, FindNext, FindPrev, + Replace, + + // View Menu + ActualSize, FitToPage, FitToWidth, FitToHeight, ZoomIn, ZoomOut, + Zoom, Redisplay, + + // Go Menu + Up, Back, Forward, Home, Prior, Next, Goto, GotoPage, GotoLine, + FirstPage, LastPage, + + // Bookmarks Menu + AddBookmark, EditBookmarks, + + // Tools Menu + Spelling, + + // Settings Menu + ShowMenubar, ShowToolbar, ShowStatusbar, SaveOptions, KeyBindings, + Preferences, ConfigureToolbars, + + // Help Menu + Help, HelpContents, WhatsThis, ReportBug, AboutApp, AboutKDE, + TipofDay, ///< @since 3.1 + + // Another settings menu item + ConfigureNotifications + }; + + /** + * Creates an action corresponding to the + * @ref KStdAction::StdAction enum. + */ + KAction* create( StdAction id, const char *name, + const QObject *recvr, const char *slot, + KActionCollection* parent ); + + inline KAction* create( StdAction id, + const QObject *recvr, const char *slot, + KActionCollection* parent ) + { return KStdAction::create( id, 0, recvr, slot, parent ); } + + /** + * @obsolete. Creates an action corresponding to the + * @ref KStdAction::StdAction enum. + */ + inline KAction *action(StdAction act_enum, + const QObject *recvr, const char *slot, + KActionCollection *parent, const char *name = 0L ) + { return KStdAction::create( act_enum, name, recvr, slot, parent ); } + + /** + * This will return the internal name of a given standard action. + */ + const char* name( StdAction id ); + + /// @obsolete. Use #name + inline const char* stdName(StdAction act_enum) { return name( act_enum ); } + + /** + * Returns a list of all standard names. Used by @ref KAccelManager + * to give those heigher weight. + * @since 3.1 + */ + QStringList stdNames(); + + /** + * Create a new document or window. + */ + KAction *openNew(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Open an existing file. + */ + KAction *open(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Open a recently used document. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + */ + KRecentFilesAction *openRecent(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Save the current document. + */ + KAction *save(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Save the current document under a different name. + */ + KAction *saveAs(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Revert the current document to the last saved version + * (essentially will undo all changes). + */ + KAction *revert(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Close the current document. + */ + KAction *close(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Print the current document. + */ + KAction *print(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Show a print preview of the current document. + */ + KAction *printPreview(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Mail this document. + */ + KAction *mail(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Quit the program. + */ + KAction *quit(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Undo the last operation. + */ + KAction *undo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Redo the last operation. + */ + KAction *redo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Cut selected area and store it in the clipboard. + */ + KAction *cut(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Copy the selected area into the clipboard. + */ + KAction *copy(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Paste the contents of clipboard at the current mouse or cursor + * position. + */ + KAction *paste(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Select all elements in the current document. + */ + KAction *selectAll(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Deselect any selected elements in the current document. + */ + KAction *deselect(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Initiate a 'find' request in the current document. + */ + KAction *find(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find the next instance of a stored 'find'. + */ + KAction *findNext(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find a previous instance of a stored 'find'. + */ + KAction *findPrev(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find and replace matches. + */ + KAction *replace(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * View the document at its actual size. + */ + KAction *actualSize(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the size of the current window. + */ + KAction *fitToPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the width of the current window. + */ + KAction *fitToWidth(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the height of the current window. + */ + KAction *fitToHeight(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Zoom in. + */ + KAction *zoomIn(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Zoom out. + */ + KAction *zoomOut(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Popup a zoom dialog. + */ + KAction *zoom(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Redisplay or redraw the document. + */ + KAction *redisplay(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move up (web style menu). + */ + KAction *up(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move back (web style menu). + */ + KAction *back(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move forward (web style menu). + */ + KAction *forward(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to the "Home" position or document. + */ + KAction *home(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Scroll up one page. + */ + KAction *prior(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Scroll down one page. + */ + KAction *next(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to somewhere in general. + */ + KAction *goTo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + + /** + * Go to a specific page (dialog). + */ + KAction *gotoPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to a specific line (dialog). + */ + KAction *gotoLine(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Jump to the first page. + */ + KAction *firstPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Jump to the last page. + */ + KAction *lastPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Add the current page to the bookmarks tree. + */ + KAction *addBookmark(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Edit the application bookmarks. + */ + KAction *editBookmarks(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Pop up the spell checker. + */ + KAction *spelling(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + + /** + * Show/Hide the menubar. + */ + KToggleAction *showMenubar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * @obsolete. toolbar actions are created automatically now in the + * Settings menu. Don't use this anymore. + * See: @ref KMainWindow::createStandardStatusBarAction() + * Show/Hide the primary toolbar. + * @since 3.1 + */ + KToggleAction *showToolbar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + /** + * @obsolete. toolbar actions are created automatically now in the + * Settings menu. Don't use this anymore. + * See: @ref KMainWindow::setStandardToolBarMenuEnabled(bool); + * Show/Hide the primary toolbar. + */ + KToggleToolBarAction *showToolbar(const char* toolBarName, + KActionCollection* parent, const char *name = 0 ); + + /** + * Show/Hide the statusbar. + */ + KToggleAction *showStatusbar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the save options dialog. + */ + KAction *saveOptions(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the configure key bindings dialog. + */ + KAction *keyBindings(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the preferences/options dialog. + */ + KAction *preferences(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * The Customize Toolbar dialog. + */ + KAction *configureToolbars(const QObject *recvr, + const char *slot, + KActionCollection* parent, + const char *name = 0 ); + + /** + * The Configure Notifications dialo + * @since 3.1 + */ + KAction *configureNotifications(const QObject *recvr, + const char *slot, + KActionCollection *parent, + const char *name = 0); + + /** + * Display the help. + */ + KAction *help(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the help contents. + */ + KAction *helpContents(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Trigger the What's This cursor. + */ + KAction *whatsThis(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display "Tip of the Day" + * @since 3.1 + */ + KAction *tipOfDay(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Open up the Report Bug dialog. + */ + KAction *reportBug(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the application's About box. + */ + KAction *aboutApp(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the About KDE dialog. + */ + KAction *aboutKDE(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); +} + +#endif // KSTDACTION_H diff --git a/microkde/kdeui/ktoolbar.cpp b/microkde/kdeui/ktoolbar.cpp new file mode 100644 index 0000000..92cb8d2 --- a/dev/null +++ b/microkde/kdeui/ktoolbar.cpp @@ -0,0 +1,2260 @@ +/* This file is part of the KDE libraries + Copyright + (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 1999 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifdef KDE_USE_FINAL +#undef Always +#include <qdockwindow.h> +#endif + + + +#include "ktoolbar.h" +#include "kmainwindow.h" + +#include <string.h> + +#include <qpainter.h> +#include <qtooltip.h> +#include <qdrawutil.h> +#include <qstring.h> +#include <qrect.h> +#include <qobjectlist.h> +#include <qtimer.h> +#include <qstyle.h> +#include <qapplication.h> + +//US #include <config.h> + +#include "klineedit.h" +#include "kseparator.h" +#include <klocale.h> +#include <kapplication.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kiconloader.h> +#include <kcombobox.h> +//US #include <kpopupmenu.h> +//US #include <kanimwidget.h> +//US #include <kipc.h> +//US #include <kwin.h> +#include <kdebug.h> +#include <qlayout.h> + +#include "ktoolbarbutton.h" + +//US +#include "kconfigbase.h" + +#include <qpopupmenu.h> +#include <qmainwindow.h> + +enum { + CONTEXT_TOP = 0, + CONTEXT_LEFT = 1, + CONTEXT_RIGHT = 2, + CONTEXT_BOTTOM = 3, + CONTEXT_FLOAT = 4, + CONTEXT_FLAT = 5, + CONTEXT_ICONS = 6, + CONTEXT_TEXT = 7, + CONTEXT_TEXTRIGHT = 8, + CONTEXT_TEXTUNDER = 9, + CONTEXT_ICONSIZES = 50 // starting point for the icon size list, put everything else before +}; + +class KToolBarPrivate +{ +public: + KToolBarPrivate() { + m_iconSize = 0; + m_iconText = KToolBar::IconOnly; + m_highlight = true; + m_transparent = true; + m_honorStyle = false; + + m_enableContext = true; + + m_xmlguiClient = 0; + m_configurePlugged = false; + +//US oldPos = Qt::DockUnmanaged; + oldPos = QMainWindow::Unmanaged; + + modified = m_isHorizontal = positioned = FALSE; + + HiddenDefault = false; + IconSizeDefault = 0; + IconTextDefault = "IconOnly"; + IndexDefault = -1; + NewLineDefault = false; + OffsetDefault = -1; + PositionDefault = "Top"; + idleButtons.setAutoDelete(true); + } + + int m_iconSize; + KToolBar::IconText m_iconText; + bool m_highlight : 1; + bool m_transparent : 1; + bool m_honorStyle : 1; + bool m_isHorizontal : 1; + bool m_enableContext : 1; + bool m_configurePlugged : 1; + bool modified : 1; + bool positioned : 1; + + QWidget *m_parent; + + QMainWindow::ToolBarDock oldPos; + + KXMLGUIClient *m_xmlguiClient; + + struct ToolBarInfo + { +//US ToolBarInfo() : index( 0 ), offset( -1 ), newline( FALSE ), dock( Qt::DockTop ) {} + ToolBarInfo() : index( 0 ), offset( -1 ), newline( FALSE ), dock( QMainWindow::Top ) {} +//US ToolBarInfo( Qt::Dock d, int i, bool n, int o ) : index( i ), offset( o ), newline( n ), dock( d ) {} + ToolBarInfo( QMainWindow::ToolBarDock d, int i, bool n, int o ) : index( i ), offset( o ), newline( n ), dock( d ) {} + int index, offset; + bool newline; +//US Qt::Dock dock; + QMainWindow::ToolBarDock dock; + }; + + ToolBarInfo toolBarInfo; + QValueList<int> iconSizes; + QTimer repaintTimer; + + // Default Values. + bool HiddenDefault; + int IconSizeDefault; + QString IconTextDefault; + int IndexDefault; + bool NewLineDefault; + int OffsetDefault; + QString PositionDefault; + + QPtrList<QWidget> idleButtons; +}; + +KToolBarSeparator::KToolBarSeparator(Orientation o , bool l, QToolBar *parent, + const char* name ) + :QFrame( parent, name ), line( l ) +{ + connect( parent, SIGNAL(orientationChanged(Orientation)), + this, SLOT(setOrientation(Orientation)) ); + setOrientation( o ); + setBackgroundMode( parent->backgroundMode() ); + setBackgroundOrigin( ParentOrigin ); +} + +void KToolBarSeparator::setOrientation( Orientation o ) +{ + orient = o; + if ( line ) { + if ( orientation() == Vertical ) + setFrameStyle( HLine + Sunken ); + else + setFrameStyle( VLine + Sunken ); + } else { + setFrameStyle( NoFrame ); + } +} + +void KToolBarSeparator::styleChange( QStyle& ) +{ + setOrientation( orient ); +} + +QSize KToolBarSeparator::sizeHint() const +{ + return orientation() == Vertical ? QSize( 0, 6 ) : QSize( 6, 0 ); +} + +QSizePolicy KToolBarSeparator::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); +} + +KToolBar::KToolBar( QWidget *parent, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parent && parent->inherits( "QMainWindow" ) ? static_cast<QMainWindow*>(parent) : 0, + parent, FALSE, + name ? name : "mainToolBar") +#else + : QPEToolBar( parent && parent->inherits( "QMainWindow" ) ? static_cast<QMainWindow*>(parent) : 0, + QString::fromLatin1( name )) + + +#endif +{ + init( readConfig, honorStyle ); +} + +KToolBar::KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock, bool newLine, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parentWindow, dock, newLine, + name ? name : "mainToolBar") +#else + : QPEToolBar( parentWindow,QString::fromLatin1( name )) + + +#endif + +{ + init( readConfig, honorStyle ); +} + +KToolBar::KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parentWindow, dock, newLine, + name ? name : "mainToolBar") +#else + : QPEToolBar( parentWindow,QString::fromLatin1( name )) + + +#endif + +{ + init( readConfig, honorStyle ); +} + +KToolBar::~KToolBar() +{ + inshutdownprocess = true; + emit toolbarDestroyed(); + delete d; +} + +void KToolBar::init( bool readConfig, bool honorStyle ) +{ + inshutdownprocess = false; + d = new KToolBarPrivate; + setFullSize( TRUE ); + d->m_honorStyle = honorStyle; + context = 0; + layoutTimer = new QTimer( this ); + connect( layoutTimer, SIGNAL( timeout() ), + this, SLOT( rebuildLayout() ) ); + connect( &(d->repaintTimer), SIGNAL( timeout() ), + this, SLOT( slotRepaint() ) ); +/*US + if ( kapp ) { // may be null when started inside designer + connect(kapp, SIGNAL(toolbarAppearanceChanged(int)), this, SLOT(slotAppearanceChanged())); + // request notification of changes in icon style + kapp->addKipcEventMask(KIPC::IconChanged); + connect(kapp, SIGNAL(iconChanged(int)), this, SLOT(slotIconChanged(int))); + } +*/ + // finally, read in our configurable settings + if ( readConfig ) + slotReadConfig(); + + if ( mainWindow() ) + connect( mainWindow(), SIGNAL( toolBarPositionChanged( QToolBar * ) ), + this, SLOT( toolBarPosChanged( QToolBar * ) ) ); + + // Hack to make sure we recalculate our size when we dock. +//US connect( this, SIGNAL(placeChanged(QDockWindow::Place)), SLOT(rebuildLayout()) ); +} + +int KToolBar::insertButton(const QString& icon, int id, bool enabled, + const QString& text, int index/*US, KInstance *_instance*/ ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text/*US, _instance*/ ); + + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QString& icon, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled, const QString& text, int index/*US, KInstance *_instance*/ ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text/*US, _instance*/); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + connect( button, signal, receiver, slot ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QPixmap& pixmap, int id, bool enabled, + const QString& text, int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + doConnections( button ); + return index; +} +#if 0 + bar->insertButton( icon, id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index/*US, instance*/ ); +#endif + +int KToolBar::insertButton(const QPixmap& pixmap, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled, const QString& text, + int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + connect( button, signal, receiver, slot ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QString& icon, int id, QPopupMenu *popup, + bool enabled, const QString &text, int index ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text ); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + button->setPopup( popup ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup, + bool enabled, const QString &text, int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text ); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + button->setPopup( popup ); + doConnections( button ); + return index; +} + + +int KToolBar::insertLined (const QString& text, int id, + const char *signal, + const QObject *receiver, const char *slot, + bool enabled , + const QString& toolTipText, + int size, int index ) +{ + KLineEdit *lined = new KLineEdit ( this, 0 ); + if ( !toolTipText.isEmpty() ) + QToolTip::add( lined, toolTipText ); + if ( size > 0 ) + lined->setMinimumWidth( size ); + insertWidgetInternal( lined, index, id ); + connect( lined, signal, receiver, slot ); + lined->setText(text); + lined->setEnabled( enabled ); + return index; +} + +int KToolBar::insertCombo (const QStringList &list, int id, bool writable, + const char *signal, const QObject *receiver, + const char *slot, bool enabled, + const QString& tooltiptext, + int size, int index, + QComboBox::Policy policy ) +{ +//US KComboBox *combo = new KComboBox ( writable, this ); + KComboBox *combo = new KComboBox ( this ); + combo->setEditable(writable); + + insertWidgetInternal( combo, index, id ); + combo->insertStringList (list); + combo->setInsertionPolicy(policy); + combo->setEnabled( enabled ); + if ( !tooltiptext.isEmpty() ) + QToolTip::add( combo, tooltiptext ); + if ( size > 0 ) + combo->setMinimumWidth( size ); + if (!tooltiptext.isNull()) + QToolTip::add( combo, tooltiptext ); + + if ( signal && receiver && slot ) + connect ( combo, signal, receiver, slot ); + return index; +} + + +int KToolBar::insertCombo (const QString& text, int id, bool writable, + const char *signal, QObject *receiver, + const char *slot, bool enabled, + const QString& tooltiptext, + int size, int index, + QComboBox::Policy policy ) +{ +//US KComboBox *combo = new KComboBox ( writable, this ); + KComboBox *combo = new KComboBox ( this ); + combo->setEditable(writable); + + insertWidgetInternal( combo, index, id ); + combo->insertItem (text); + combo->setInsertionPolicy(policy); + combo->setEnabled( enabled ); + if ( !tooltiptext.isEmpty() ) + QToolTip::add( combo, tooltiptext ); + if ( size > 0 ) + combo->setMinimumWidth( size ); + if (!tooltiptext.isNull()) + QToolTip::add( combo, tooltiptext ); + connect (combo, signal, receiver, slot); + return index; +} + +int KToolBar::insertSeparator(int index, int id) +{ + QWidget *w = new KToolBarSeparator( orientation(), FALSE, this, "tool bar separator" ); + insertWidgetInternal( w, index, id ); + return index; +} + +int KToolBar::insertLineSeparator(int index, int id) +{ + QWidget *w = new KToolBarSeparator( orientation(), TRUE, this, "tool bar separator" ); + insertWidgetInternal( w, index, id ); + return index; +} + + +int KToolBar::insertWidget(int id, int /*width*/, QWidget *widget, int index) +{ + // removeWidgetInternal( widget ); // in case we already have it ? + insertWidgetInternal( widget, index, id ); + return index; +} +/*US +int KToolBar::insertAnimatedWidget(int id, QObject *receiver, const char *slot, + const QString& icons, int index ) +{ + KAnimWidget *anim = new KAnimWidget( icons, d->m_iconSize, this ); + insertWidgetInternal( anim, index, id ); + + if ( receiver ) + connect( anim, SIGNAL(clicked()), receiver, slot); + + return index; +} + +KAnimWidget *KToolBar::animatedWidget( int id ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; + if ( (*it) && (*it)->inherits( "KAnimWidget" ) ) + return (KAnimWidget*)(*it); + QObjectList *l = queryList( "KAnimWidget" ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + + for ( QObject *o = l->first(); o; o = l->next() ) { + if ( o->inherits( "KAnimWidget" ) ) + { + delete l; + return (KAnimWidget*)o; + } + } + + delete l; + return 0; +} +*/ + +void KToolBar::addConnection (int id, const char *signal, + const QObject *receiver, const char *slot) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( (*it) ) + connect( (*it), signal, receiver, slot ); +} + +void KToolBar::setItemEnabled( int id, bool enabled ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( (*it) ) + (*it)->setEnabled( enabled ); +} + + +void KToolBar::setButtonPixmap( int id, const QPixmap& _pixmap ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setPixmap( _pixmap ); +} + + +void KToolBar::setButtonIcon( int id, const QString& _icon ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setIcon( _icon ); +} + +void KToolBar::setButtonIconSet( int id, const QIconSet& iconset ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setIconSet( iconset ); +} + + +void KToolBar::setDelayedPopup (int id , QPopupMenu *_popup, bool toggle ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setDelayedPopup( _popup, toggle ); +} + + +void KToolBar::setAutoRepeat (int id, bool flag) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setAutoRepeat( flag ); +} + + +void KToolBar::setToggle (int id, bool flag ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setToggle( flag ); +} + + +void KToolBar::toggleButton (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->toggle(); +} + + +void KToolBar::setButton (int id, bool flag) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->on( flag ); +} + + +bool KToolBar::isButtonOn (int id) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return false; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + return button ? button->isOn() : false; +} + + +void KToolBar::setLinedText (int id, const QString& text) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QLineEdit * lineEdit = dynamic_cast<QLineEdit *>( *it ); + QLineEdit * lineEdit = (QLineEdit *)( *it ); + if ( lineEdit ) + lineEdit->setText( text ); +} + + +QString KToolBar::getLinedText (int id) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return QString::null; +//US QLineEdit * lineEdit = dynamic_cast<QLineEdit *>( *it ); + QLineEdit * lineEdit = (QLineEdit *)( *it ); + return lineEdit ? lineEdit->text() : QString::null; +} + + +void KToolBar::insertComboItem (int id, const QString& text, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->insertItem( text, index ); +} + +void KToolBar::insertComboList (int id, const QStringList &list, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->insertStringList( list, index ); +} + + +void KToolBar::removeComboItem (int id, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->removeItem( index ); +} + + +void KToolBar::setCurrentComboItem (int id, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->setCurrentItem( index ); +} + + +void KToolBar::changeComboItem (int id, const QString& text, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->changeItem( text, index ); +} + + +void KToolBar::clearCombo (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->clear(); +} + + +QString KToolBar::getComboItem (int id, int index) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return QString::null; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + return comboBox ? comboBox->text( index ) : QString::null; +} + + +KComboBox * KToolBar::getCombo(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KComboBox *>( *it ); + return (KComboBox *)( *it ); +} + + +KLineEdit * KToolBar::getLined (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KLineEdit *>( *it ); + return (KLineEdit *)( *it ); +} + + +KToolBarButton * KToolBar::getButton (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KToolBarButton *>( *it ); + return (KToolBarButton *)( *it ); +} + + +void KToolBar::alignItemRight (int id, bool right ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( rightAligned && !right && (*it) == rightAligned ) + rightAligned = 0; + if ( (*it) && right ) + rightAligned = (*it); +} + + +QWidget *KToolBar::getWidget (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + return ( it == id2widget.end() ) ? 0 : (*it); +} + + +void KToolBar::setItemAutoSized (int id, bool yes ) +{ + QWidget *w = getWidget(id); + if ( w && yes ) + setStretchableWidget( w ); +} + + +void KToolBar::clear () +{ + QToolBar::clear(); + widget2id.clear(); + id2widget.clear(); +} + + +void KToolBar::removeItem(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + { + kdDebug(220) << "KToolBar::removeItem item " << id << " not found" << endl; + return; + } + QWidget * w = (*it); + id2widget.remove( id ); + widget2id.remove( w ); + widgets.removeRef( w ); + delete w; +} + + +void KToolBar::removeItemDelayed(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + { + kdDebug(220) << "KToolBar::removeItem item " << id << " not found" << endl; + return; + } + QWidget * w = (*it); + id2widget.remove( id ); + widget2id.remove( w ); + widgets.removeRef( w ); + + w->blockSignals(true); + d->idleButtons.append(w); + layoutTimer->start( 50, TRUE ); +} + + +void KToolBar::hideItem (int id) +{ + QWidget *w = getWidget(id); + if ( w ) + w->hide(); +} + + +void KToolBar::showItem (int id) +{ + QWidget *w = getWidget(id); + if ( w ) + w->show(); +} + + +int KToolBar::itemIndex (int id) +{ + QWidget *w = getWidget(id); + return w ? widgets.findRef(w) : -1; +} + + +void KToolBar::setFullSize(bool flag ) +{ + setHorizontalStretchable( flag ); + setVerticalStretchable( flag ); +} + + +bool KToolBar::fullSize() const +{ + return isHorizontalStretchable() || isVerticalStretchable(); +} + + +void KToolBar::enableMoving(bool flag ) +{ +//US setMovingEnabled(flag); + this->mainWindow()->setToolBarsMovable(flag); +} + + +void KToolBar::setBarPos (BarPosition bpos) +{ + if ( !mainWindow() ) + return; +//US mainWindow()->moveDockWindow( this, (Dock)bpos ); + mainWindow()->moveToolBar( this, (QMainWindow::ToolBarDock)bpos ); +} + + +KToolBar::BarPosition KToolBar::barPos() +{ + if ( !(QMainWindow*)mainWindow() ) + return KToolBar::Top; +//US Dock dock; + QMainWindow::ToolBarDock dock; + int dm1, dm2; + bool dm3; + ((QMainWindow*)mainWindow())->getLocation( (QToolBar*)this, dock, dm1, dm3, dm2 ); +//US if ( dock == DockUnmanaged ) { + if ( dock == QMainWindow::Unmanaged ) { + return (KToolBar::BarPosition)Top; + } + return (BarPosition)dock; +} + + +bool KToolBar::enable(BarStatus stat) +{ + bool mystat = isVisible(); + + if ( (stat == Toggle && mystat) || stat == Hide ) + hide(); + else + show(); + + return isVisible() == mystat; +} + + +void KToolBar::setMaxHeight ( int h ) +{ + setMaximumHeight( h ); +} + +int KToolBar::maxHeight() +{ + return maximumHeight(); +} + + +void KToolBar::setMaxWidth (int dw) +{ + setMaximumWidth( dw ); +} + + +int KToolBar::maxWidth() +{ + return maximumWidth(); +} + + +void KToolBar::setTitle (const QString& _title) +{ + setLabel( _title ); +} + + +void KToolBar::enableFloating (bool ) +{ +} + + +void KToolBar::setIconText(IconText it) +{ + setIconText( it, true ); +} + + +void KToolBar::setIconText(IconText icontext, bool update) +{ + bool doUpdate=false; + + if (icontext != d->m_iconText) { + d->m_iconText = icontext; + doUpdate=true; + } + + if (update == false) + return; + + if (doUpdate) + emit modechange(); // tell buttons what happened + + // ugly hack to force a QMainWindow::triggerLayout( TRUE ) + if ( mainWindow() ) { + QMainWindow *mw = mainWindow(); + mw->setUpdatesEnabled( FALSE ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setUpdatesEnabled( TRUE ); + } +} + + +KToolBar::IconText KToolBar::iconText() const +{ + return d->m_iconText; +} + + +void KToolBar::setIconSize(int size) +{ + setIconSize( size, true ); +} + +void KToolBar::setIconSize(int size, bool update) +{ + bool doUpdate=false; + + if ( size != d->m_iconSize ) { + d->m_iconSize = size; + doUpdate=true; + } + + if (update == false) + return; + + if (doUpdate) + emit modechange(); // tell buttons what happened + + // ugly hack to force a QMainWindow::triggerLayout( TRUE ) + if ( mainWindow() ) { + QMainWindow *mw = mainWindow(); + mw->setUpdatesEnabled( FALSE ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setUpdatesEnabled( TRUE ); + } +} + + +int KToolBar::iconSize() const +{ +/*US + if ( !d->m_iconSize ) // default value? + { + if (!::qstrcmp(QObject::name(), "mainToolBar")) + return KGlobal::iconLoader()->currentSize(KIcon::MainToolbar); + else + return KGlobal::iconLoader()->currentSize(KIcon::Toolbar); + } + return d->m_iconSize; +*/ + int ret = 18; + if ( QApplication::desktop()->width() > 320 && QApplication::desktop()->width() < 650 ) + ret = 30; + return ret; +} + + +void KToolBar::setEnableContextMenu(bool enable ) +{ + d->m_enableContext = enable; +} + + +bool KToolBar::contextMenuEnabled() const +{ + return d->m_enableContext; +} + + +void KToolBar::setItemNoStyle(int id, bool no_style ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if (button) + button->setNoStyle( no_style ); +} + + +void KToolBar::setFlat (bool flag) +{ + if ( !mainWindow() ) + return; + if ( flag ) +//US mainWindow()->moveDockWindow( this, DockMinimized ); + mainWindow()->moveToolBar( this, QMainWindow::Minimized ); + else +//US mainWindow()->moveDockWindow( this, DockTop ); + mainWindow()->moveToolBar( this, QMainWindow::Top ); + // And remember to save the new look later +/*US + if ( mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + + +int KToolBar::count() const +{ + return id2widget.count(); +} + + +void KToolBar::saveState() +{ +/*US + // first, try to save to the xml file + if ( d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty() ) { + // go down one level to get to the right tags + QDomElement elem = d->m_xmlguiClient->domDocument().documentElement().toElement(); + elem = elem.firstChild().toElement(); + QString barname(!::qstrcmp(name(), "unnamed") ? "mainToolBar" : name()); + QDomElement current; + // now try to find our toolbar + d->modified = false; + for( ; !elem.isNull(); elem = elem.nextSibling().toElement() ) { + current = elem; + + if ( current.tagName().lower() != "toolbar" ) + continue; + + QString curname(current.attribute( "name" )); + + if ( curname == barname ) { + saveState( current ); + break; + } + } + // if we didn't make changes, then just return + if ( !d->modified ) + return; + + // now we load in the (non-merged) local file + QString local_xml(KXMLGUIFactory::readConfigFile(d->m_xmlguiClient->xmlFile(), true, d->m_xmlguiClient->instance())); + QDomDocument local; + local.setContent(local_xml); + + // make sure we don't append if this toolbar already exists locally + bool just_append = true; + elem = local.documentElement().toElement(); + KXMLGUIFactory::removeDOMComments( elem ); + elem = elem.firstChild().toElement(); + for( ; !elem.isNull(); elem = elem.nextSibling().toElement() ) { + if ( elem.tagName().lower() != "toolbar" ) + continue; + + QString curname(elem.attribute( "name" )); + + if ( curname == barname ) { + just_append = false; + local.documentElement().replaceChild( current, elem ); + break; + } + } + + if (just_append) + local.documentElement().appendChild( current ); + + KXMLGUIFactory::saveConfigFile(local, d->m_xmlguiClient->localXMLFile(), d->m_xmlguiClient->instance() ); + + return; + } +*/ + // if that didn't work, we save to the config file + KConfig *config = KGlobal::config(); + saveSettings(config, QString::null); + config->sync(); +} + +QString KToolBar::settingsGroup() +{ + QString configGroup; + if (!::qstrcmp(name(), "unnamed") || !::qstrcmp(name(), "mainToolBar")) + configGroup = "Toolbar style"; + else + configGroup = QString(name()) + " Toolbar style"; + if ( this->mainWindow() ) + { + configGroup.prepend(" "); + configGroup.prepend( this->mainWindow()->name() ); + } + return configGroup; +} + +void KToolBar::saveSettings(KConfig *config, const QString &_configGroup) +{ + QString configGroup = _configGroup; + if (configGroup.isEmpty()) + configGroup = settingsGroup(); + //kdDebug(220) << "KToolBar::saveSettings group=" << _configGroup << " -> " << configGroup << endl; + + QString position, icontext; + int index; + getAttributes( position, icontext, index ); + + //kdDebug(220) << "KToolBar::saveSettings " << name() << " newLine=" << newLine << endl; + + KConfigGroupSaver saver(config, configGroup); + + if ( position != d->PositionDefault ) + config->writeEntry("Position", position); + else + config->deleteEntry("Position"); + + if ( icontext != d->IconTextDefault ) + config->writeEntry("IconText", icontext); + else + config->deleteEntry("IconText"); + + if ( iconSize() != d->IconSizeDefault ) + config->writeEntry("IconSize", iconSize()); + else + config->deleteEntry("IconSize"); + + if ( isHidden() != d->HiddenDefault ) + config->writeEntry("Hidden", isHidden()); + else + config->deleteEntry("Hidden"); + + if ( index != d->IndexDefault ) + config->writeEntry( "Index", index ); + else + config->deleteEntry("Index"); +//US the older version of KDE (used on the Zaurus) has no Offset property +/* if ( offset() != d->OffsetDefault ) + config->writeEntry( "Offset", offset() ); + else +*/ + config->deleteEntry("Offset"); + +//US the older version of KDE (used on the Zaurus) has no NewLine property +/* + if ( newLine() != d->NewLineDefault ) + config->writeEntry( "NewLine", newLine() ); + else +*/ + config->deleteEntry("NewLine"); +} + +void KToolBar::setXMLGUIClient( KXMLGUIClient *client ) +{ + d->m_xmlguiClient = client; +} + +void KToolBar::setText( const QString & txt ) +{ +//US setLabel( txt + " ( " + kapp->caption() + " ) " ); + setLabel( txt + " ( " + KGlobal::getAppName() + " ) " ); +} + + +QString KToolBar::text() const +{ + return label(); +} + + +void KToolBar::doConnections( KToolBarButton *button ) +{ + connect(button, SIGNAL(clicked(int)), this, SIGNAL( clicked( int ) ) ); + connect(button, SIGNAL(doubleClicked(int)), this, SIGNAL( doubleClicked( int ) ) ); + connect(button, SIGNAL(released(int)), this, SIGNAL( released( int ) ) ); + connect(button, SIGNAL(pressed(int)), this, SIGNAL( pressed( int ) ) ); + connect(button, SIGNAL(toggled(int)), this, SIGNAL( toggled( int ) ) ); + connect(button, SIGNAL(highlighted(int, bool)), this, SIGNAL( highlighted( int, bool ) ) ); +} + +void KToolBar::mousePressEvent ( QMouseEvent *m ) +{ + if ( !mainWindow() ) + return; + QMainWindow *mw = mainWindow(); + if ( mw->toolBarsMovable() && d->m_enableContext ) { + if ( m->button() == RightButton ) { + int i = contextMenu()->exec( m->globalPos(), 0 ); + switch ( i ) { + case -1: + return; // popup cancelled + case CONTEXT_LEFT: +//US mw->moveDockWindow( this, DockLeft ); + mw->moveToolBar( this, QMainWindow::Left ); + break; + case CONTEXT_RIGHT: +//US mw->moveDockWindow( this, DockRight ); + mw->moveToolBar( this, QMainWindow::Right ); + break; + case CONTEXT_TOP: +//US mw->moveDockWindow( this, DockTop ); + mw->moveToolBar( this, QMainWindow::Top ); + break; + case CONTEXT_BOTTOM: +//US mw->moveDockWindow( this, DockBottom ); + mw->moveToolBar( this, QMainWindow::Bottom ); + break; + case CONTEXT_FLOAT: + break; + case CONTEXT_FLAT: +//US mw->moveDockWindow( this, DockMinimized ); + mw->moveToolBar( this, QMainWindow::Minimized ); + break; + case CONTEXT_ICONS: + setIconText( IconOnly ); + break; + case CONTEXT_TEXTRIGHT: + setIconText( IconTextRight ); + break; + case CONTEXT_TEXT: + setIconText( TextOnly ); + break; + case CONTEXT_TEXTUNDER: + setIconText( IconTextBottom ); + break; + default: + if ( i >= CONTEXT_ICONSIZES ) + setIconSize( i - CONTEXT_ICONSIZES ); + else + return; // assume this was an action handled elsewhere, no need for setSettingsDirty() + } +/*US + if ( mw->inherits("KMainWindow") ) + static_cast<KMainWindow *>(mw)->setSettingsDirty(); +*/ + } + } +} + + +void KToolBar::rebuildLayout() +{ + + for(QWidget *w=d->idleButtons.first(); w; w=d->idleButtons.next()) + w->blockSignals(false); + d->idleButtons.clear(); + + layoutTimer->stop(); + QApplication::sendPostedEvents( this, QEvent::ChildInserted ); + QBoxLayout *l = boxLayout(); + l->setMargin( 1 ); + // clear the old layout + QLayoutIterator it = l->iterator(); + + while ( it.current() ) { + it.deleteCurrent(); + } + for ( QWidget *w = widgets.first(); w; w = widgets.next() ) { + if ( w == rightAligned ) { + continue; + } + if ( w->inherits( "KToolBarSeparator" ) && + !( (KToolBarSeparator*)w )->showLine() ) { + l->addSpacing( 6 ); + w->hide(); + continue; + } + if ( w->inherits( "QPopupMenu" ) ) + continue; + l->addWidget( w ); + w->show(); + } + if ( rightAligned ) { + l->addStretch(); + l->addWidget( rightAligned ); + rightAligned->show(); + } + + if ( fullSize() ) { + // This code sucks. It makes the last combo in a toolbar VERY big (e.g. zoom combo in kword). + //if ( !stretchableWidget && widgets.last() && + // !widgets.last()->inherits( "QButton" ) && !widgets.last()->inherits( "KAnimWidget" ) ) + // setStretchableWidget( widgets.last() ); + if ( !rightAligned ) + l->addStretch(); + if ( stretchableWidget ) + l->setStretchFactor( stretchableWidget, 10 ); + } + l->invalidate(); + QApplication::postEvent( this, new QEvent( QEvent::LayoutHint ) ); + //#endif //DESKTOP_VERSION +} + +void KToolBar::childEvent( QChildEvent *e ) +{ + + if ( e->child()->isWidgetType() ) { + QWidget * w = (QWidget*)e->child(); + if ( e->type() == QEvent::ChildInserted ) { + if ( !e->child()->inherits( "QPopupMenu" ) && + ::qstrcmp( "qt_dockwidget_internal", e->child()->name() ) != 0 ) { + + // prevent items that have been explicitly inserted by insert*() from + // being inserted again + if ( !widget2id.contains( w ) ) + { + int dummy = -1; + insertWidgetInternal( w, dummy, -1 ); + } + } + } else { + removeWidgetInternal( w ); + } + if ( isVisibleTo( 0 ) ) + { + QBoxLayout *l = boxLayout(); + // QLayout *l = layout(); + + // clear the old layout so that we don't get unnecassery layout + // changes till we have rebuild the thing + QLayoutIterator it = l->iterator(); + while ( it.current() ) { + it.deleteCurrent(); + } + layoutTimer->start( 50, TRUE ); + } + } + QToolBar::childEvent( e ); +} + +void KToolBar::insertWidgetInternal( QWidget *w, int &index, int id ) +{ + // we can't have it in widgets, or something is really wrong + //widgets.removeRef( w ); + + connect( w, SIGNAL( destroyed() ), + this, SLOT( widgetDestroyed() ) ); + if ( index == -1 || index > (int)widgets.count() ) { + widgets.append( w ); + index = (int)widgets.count(); + } + else + widgets.insert( index, w ); + if ( id == -1 ) + id = id2widget.count(); + id2widget.insert( id, w ); + widget2id.insert( w, id ); +} + +void KToolBar::showEvent( QShowEvent *e ) +{ + QToolBar::showEvent( e ); + rebuildLayout(); +} + +void KToolBar::setStretchableWidget( QWidget *w ) +{ + QToolBar::setStretchableWidget( w ); + stretchableWidget = w; +} + +QSizePolicy KToolBar::sizePolicy() const +{ + if ( orientation() == Horizontal ) + return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + else + return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ); +} + +QSize KToolBar::sizeHint() const +{ + return QToolBar::sizeHint(); +#if 0 + QWidget::polish(); + static int iii = 0; + ++iii; + qDebug("++++++++ KToolBar::sizeHint() %d ", iii ); + int margin = static_cast<QWidget*>(ncThis)->layout()->margin(); + switch( barPos() ) + { + case KToolBar::Top: + case KToolBar::Bottom: + for ( QWidget *w = widgets.first(); w; w =widgets.next() ) + { + if ( w->inherits( "KToolBarSeparator" ) && + !( static_cast<KToolBarSeparator*>(w)->showLine() ) ) + { + minSize += QSize(6, 0); + } + else + { + QSize sh = w->sizeHint(); + if (!sh.isValid()) + sh = w->minimumSize(); + minSize = minSize.expandedTo(QSize(0, sh.height())); + minSize += QSize(sh.width()+1, 0); + } + } +/*US + minSize += QSize(QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent ), 0); +*/ + minSize += QSize(margin*2, margin*2); + break; + + case KToolBar::Left: + case KToolBar::Right: + for ( QWidget *w = widgets.first(); w; w = widgets.next() ) + { + if ( w->inherits( "KToolBarSeparator" ) && + !( static_cast<KToolBarSeparator*>(w)->showLine() ) ) + { + minSize += QSize(0, 6); + } + else + { + QSize sh = w->sizeHint(); + if (!sh.isValid()) + sh = w->minimumSize(); + minSize = minSize.expandedTo(QSize(sh.width(), 0)); + minSize += QSize(0, sh.height()+1); + } + } +/*US + minSize += QSize(0, QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); +*/ + minSize += QSize(margin*2, margin*2); + break; + + default: + minSize = QToolBar::sizeHint(); + break; + } + return minSize; +#endif +} + +QSize KToolBar::minimumSize() const +{ + return minimumSizeHint(); +} + +QSize KToolBar::minimumSizeHint() const +{ + return sizeHint(); +} + +bool KToolBar::highlight() const +{ + return d->m_highlight; +} + +void KToolBar::hide() +{ + QToolBar::hide(); +} + +void KToolBar::show() +{ + QToolBar::show(); +} + +void KToolBar::resizeEvent( QResizeEvent *e ) +{ + bool b = isUpdatesEnabled(); + setUpdatesEnabled( FALSE ); + QToolBar::resizeEvent( e ); + if (b) + d->repaintTimer.start( 100, true ); +} + +void KToolBar::slotIconChanged(int group) +{ + if ((group != KIcon::Toolbar) && (group != KIcon::MainToolbar)) + return; + if ((group == KIcon::MainToolbar) != !::qstrcmp(name(), "mainToolBar")) + return; + + emit modechange(); + if (isVisible()) + updateGeometry(); +} + +void KToolBar::slotReadConfig() +{ + //kdDebug(220) << "KToolBar::slotReadConfig" << endl; + // Read appearance settings (hmm, we used to do both here, + // but a well behaved application will call applyMainWindowSettings + // anyway, right ?) + applyAppearanceSettings(KGlobal::config(), QString::null ); +} + +void KToolBar::slotAppearanceChanged() +{ + // Read appearance settings from global file. + applyAppearanceSettings(KGlobal::config(), QString::null, true /* lose local settings */ ); + // And remember to save the new look later +/*US + if ( mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + +//static +bool KToolBar::highlightSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + return KGlobal::config()->readBoolEntry(QString::fromLatin1("Highlighting"),true); +} + +//static +bool KToolBar::transparentSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + return KGlobal::config()->readBoolEntry(QString::fromLatin1("TransparentMoving"),true); +} + +//static +KToolBar::IconText KToolBar::iconTextSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + QString icontext = KGlobal::config()->readEntry(QString::fromLatin1("IconText"),QString::fromLatin1("IconOnly")); + if ( icontext == "IconTextRight" ) + return IconTextRight; + else if ( icontext == "IconTextBottom" ) + return IconTextBottom; + else if ( icontext == "TextOnly" ) + return TextOnly; + else + return IconOnly; +} + +void KToolBar::applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal) +{ + QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup; + //kdDebug(220) << "KToolBar::applyAppearanceSettings: configGroup=" << configGroup << endl; + // We have application-specific settings in the XML file, + // and nothing in the application's config file + // -> don't apply the global defaults, the XML ones are preferred + // See applySettings for a full explanation +/*US :we do not support xml files + if ( d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty() && + !config->hasGroup(configGroup) ) + { + //kdDebug(220) << "skipping global defaults, using XML ones instead" << endl; + return; + } +*/ + if ( !config->hasGroup(configGroup) ) + { + //kdDebug(220) << "skipping global defaults, using XML ones instead" << endl; + return; + } + + + KConfig *gconfig = KGlobal::config(); +/*US + static const QString &attrIconText = KGlobal::staticQString("IconText"); + static const QString &attrHighlight = KGlobal::staticQString("Highlighting"); + static const QString &attrTrans = KGlobal::staticQString("TransparentMoving"); + static const QString &attrSize = KGlobal::staticQString("IconSize"); +*/ + // we actually do this in two steps. + // First, we read in the global styles [Toolbar style] (from the KControl module). + // Then, if the toolbar is NOT 'mainToolBar', we will also try to read in [barname Toolbar style] + bool highlight; + int transparent; + QString icontext; + int iconsize = 0; + + // this is the first iteration + QString grpToolbar(QString::fromLatin1("Toolbar style")); + { // start block for KConfigGroupSaver + KConfigGroupSaver saver(gconfig, grpToolbar); + + // first, get the generic settings +//US highlight = gconfig->readBoolEntry(attrHighlight, true); + highlight = gconfig->readBoolEntry("Highlighting", true); +//US transparent = gconfig->readBoolEntry(attrTrans, true); + transparent = gconfig->readBoolEntry("TransparentMoving", true); + + // we read in the IconText property *only* if we intend on actually + // honoring it + if (d->m_honorStyle) +//US d->IconTextDefault = gconfig->readEntry(attrIconText, d->IconTextDefault); + d->IconTextDefault = gconfig->readEntry("IconText", d->IconTextDefault); + else + d->IconTextDefault = "IconOnly"; + + // Use the default icon size for toolbar icons. +//US d->IconSizeDefault = gconfig->readNumEntry(attrSize, d->IconSizeDefault); + d->IconSizeDefault = gconfig->readNumEntry("IconSize", d->IconSizeDefault); + + if ( !forceGlobal && config->hasGroup(configGroup) ) + { + config->setGroup(configGroup); + + // first, get the generic settings +//US highlight = config->readBoolEntry(attrHighlight, highlight); + highlight = config->readBoolEntry("Highlighting", highlight); +//US transparent = config->readBoolEntry(attrTrans, transparent); + transparent = config->readBoolEntry("TransparentMoving", transparent); + // now we always read in the IconText property +//US icontext = config->readEntry(attrIconText, d->IconTextDefault); + icontext = config->readEntry("IconText", d->IconTextDefault); + + // now get the size +//US iconsize = config->readNumEntry(attrSize, d->IconSizeDefault); + iconsize = config->readNumEntry("IconSize", d->IconSizeDefault); + } + else + { + iconsize = d->IconSizeDefault; + icontext = d->IconTextDefault; + } + + // revert back to the old group + } // end block for KConfigGroupSaver + + bool doUpdate = false; + + IconText icon_text; + if ( icontext == "IconTextRight" ) + icon_text = IconTextRight; + else if ( icontext == "IconTextBottom" ) + icon_text = IconTextBottom; + else if ( icontext == "TextOnly" ) + icon_text = TextOnly; + else + icon_text = IconOnly; + + // check if the icon/text has changed + if (icon_text != d->m_iconText) { + //kdDebug(220) << "KToolBar::applyAppearanceSettings setIconText " << icon_text << endl; + setIconText(icon_text, false); + doUpdate = true; + } + + // ...and check if the icon size has changed + if (iconsize != d->m_iconSize) { + setIconSize(iconsize, false); + doUpdate = true; + } + + QMainWindow *mw = mainWindow(); + + // ...and if we should highlight + if ( highlight != d->m_highlight ) { + d->m_highlight = highlight; + doUpdate = true; + } + + // ...and if we should move transparently + if ( mw && transparent != (!mw->opaqueMoving()) ) { + mw->setOpaqueMoving( !transparent ); + } + + if (doUpdate) + emit modechange(); // tell buttons what happened + if (isVisible ()) + updateGeometry(); +} + +void KToolBar::applySettings(KConfig *config, const QString &_configGroup) +{ + //kdDebug(220) << "KToolBar::applySettings group=" << _configGroup << endl; + + QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup; + + /* + Let's explain this a bit more in details. + The order in which we apply settings is : + Global config / <appnamerc> user settings if no XMLGUI is used + Global config / App-XML attributes / <appnamerc> user settings if XMLGUI is used + + So in the first case, we simply read everything from KConfig as below, + but in the second case we don't do anything here if there is no app-specific config, + and the XMLGUI uses the static methods of this class to get the global defaults. + + Global config doesn't include position (index, offset, newline and hidden/shown). + */ + + // First the appearance stuff - the one which has a global config + applyAppearanceSettings( config, _configGroup ); + + // ...and now the position stuff + if ( config->hasGroup(configGroup) ) + { + KConfigGroupSaver cgs(config, configGroup); +/*US + static const QString &attrPosition = KGlobal::staticQString("Position"); + static const QString &attrIndex = KGlobal::staticQString("Index"); + static const QString &attrOffset = KGlobal::staticQString("Offset"); + static const QString &attrNewLine = KGlobal::staticQString("NewLine"); + static const QString &attrHidden = KGlobal::staticQString("Hidden"); + + QString position = config->readEntry(attrPosition, d->PositionDefault); + int index = config->readNumEntry(attrIndex, d->IndexDefault); + int offset = config->readNumEntry(attrOffset, d->OffsetDefault); + bool newLine = config->readBoolEntry(attrNewLine, d->NewLineDefault); + bool hidden = config->readBoolEntry(attrHidden, d->HiddenDefault); +*/ + + QString position = config->readEntry("Position", d->PositionDefault); + int index = config->readNumEntry("Index", d->IndexDefault); + int offset = config->readNumEntry("Offset", d->OffsetDefault); + bool newLine = config->readBoolEntry("NewLine", d->NewLineDefault); + bool hidden = config->readBoolEntry("Hidden", d->HiddenDefault); + +/*US Dock pos(DockTop); + if ( position == "Top" ) + pos = DockTop; + else if ( position == "Bottom" ) + pos = DockBottom; + else if ( position == "Left" ) + pos = DockLeft; + else if ( position == "Right" ) + pos = DockRight; + else if ( position == "Floating" ) + pos = DockTornOff; + else if ( position == "Flat" ) + pos = DockMinimized; +*/ + QMainWindow::ToolBarDock pos(QMainWindow::Top); + if ( position == "Top" ) + pos = QMainWindow::Top; + else if ( position == "Bottom" ) + pos = QMainWindow::Bottom; + else if ( position == "Left" ) + pos = QMainWindow::Left; + else if ( position == "Right" ) + pos = QMainWindow::Right; + else if ( position == "Floating" ) + pos = QMainWindow::TornOff; + else if ( position == "Flat" ) + pos = QMainWindow::Minimized; + + //kdDebug(220) << "KToolBar::applySettings hidden=" << hidden << endl; + if (hidden) + hide(); + else + show(); + + if ( mainWindow() ) + { + QMainWindow *mw = mainWindow(); + + //kdDebug(220) << "KToolBar::applySettings updating ToolbarInfo" << endl; + d->toolBarInfo = KToolBarPrivate::ToolBarInfo( pos, index, newLine, offset ); + + // moveDockWindow calls QDockArea which does a reparent() on us with + // showIt = true, so we loose our visibility status + bool doHide = isHidden(); + +//US mw->moveDockWindow( this, pos, newLine, index, offset ); + mw->moveToolBar( this, pos, newLine, index, offset ); + + //kdDebug(220) << "KToolBar::applySettings " << name() << " moveDockWindow with pos=" << pos << " newLine=" << newLine << " idx=" << index << " offs=" << offset << endl; + if ( doHide ) + hide(); + } + if (isVisible ()) + updateGeometry(); + } +} + +bool KToolBar::event( QEvent *e ) +{ + if ( (e->type() == QEvent::LayoutHint) && isUpdatesEnabled() ) + d->repaintTimer.start( 100, true ); + + if (e->type() == QEvent::ChildInserted ) + { + // By pass QToolBar::event, + // it will show() the inserted child and we don't want to + // do that until we have rebuild the layout. + childEvent((QChildEvent *)e); + return true; + } + + return QToolBar::event( e ); +} + +void KToolBar::slotRepaint() +{ + setUpdatesEnabled( FALSE ); + // Send a resizeEvent to update the "toolbar extension arrow" + // (The button you get when your toolbar-items don't fit in + // the available space) + QResizeEvent ev(size(), size()); + resizeEvent(&ev); + //#ifdef DESKTOP_VERSION + QApplication::sendPostedEvents( this, QEvent::LayoutHint ); + //#endif //DESKTOP_VERSION + setUpdatesEnabled( TRUE ); + repaint( TRUE ); +} + +void KToolBar::toolBarPosChanged( QToolBar *tb ) +{ + if ( tb != this ) + return; +//US if ( d->oldPos == DockMinimized ) + if ( d->oldPos == QMainWindow::Minimized ) + rebuildLayout(); + d->oldPos = (QMainWindow::ToolBarDock)barPos(); +/*US + if ( mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + +/*US +void KToolBar::loadState( const QDomElement &element ) +{ + //kdDebug(220) << "KToolBar::loadState " << this << endl; + if ( !mainWindow() ) + return; + + { + QCString text = element.namedItem( "text" ).toElement().text().utf8(); + if ( text.isEmpty() ) + text = element.namedItem( "Text" ).toElement().text().utf8(); + if ( !text.isEmpty() ) + setText( i18n( text ) ); + } + + { + QCString attrFullWidth = element.attribute( "fullWidth" ).lower().latin1(); + if ( !attrFullWidth.isEmpty() ) + setFullSize( attrFullWidth == "true" ); + } + + Dock dock = DockTop; + { + QCString attrPosition = element.attribute( "position" ).lower().latin1(); + //kdDebug(220) << "KToolBar::loadState attrPosition=" << attrPosition << endl; + if ( !attrPosition.isEmpty() ) { + if ( attrPosition == "top" ) + dock = DockTop; + else if ( attrPosition == "left" ) + dock = DockLeft; + else if ( attrPosition == "right" ) + dock = DockRight; + else if ( attrPosition == "bottom" ) + dock = DockBottom; + else if ( attrPosition == "floating" ) + dock = DockTornOff; + else if ( attrPosition == "flat" ) + dock = DockMinimized; + } + } + + { + QCString attrIconText = element.attribute( "iconText" ).lower().latin1(); + if ( !attrIconText.isEmpty() ) { + //kdDebug(220) << "KToolBar::loadState attrIconText=" << attrIconText << endl; + if ( attrIconText == "icontextright" ) + setIconText( KToolBar::IconTextRight ); + else if ( attrIconText == "textonly" ) + setIconText( KToolBar::TextOnly ); + else if ( attrIconText == "icontextbottom" ) + setIconText( KToolBar::IconTextBottom ); + else if ( attrIconText == "icononly" ) + setIconText( KToolBar::IconOnly ); + } else + // Use global setting + setIconText( iconTextSetting() ); + } + + { + QString attrIconSize = element.attribute( "iconSize" ).lower(); + if ( !attrIconSize.isEmpty() ) + d->IconSizeDefault = attrIconSize.toInt(); + setIconSize( d->IconSizeDefault ); + } + + { + QString attrIndex = element.attribute( "index" ).lower(); + if ( !attrIndex.isEmpty() ) + d->IndexDefault = attrIndex.toInt(); + } + + { + QString attrOffset = element.attribute( "offset" ).lower(); + if ( !attrOffset.isEmpty() ) + d->OffsetDefault = attrOffset.toInt(); + } + + { + QString attrNewLine = element.attribute( "newline" ).lower(); + if ( !attrNewLine.isEmpty() ) + d->NewLineDefault = attrNewLine == "true"; + } + + { + QString attrHidden = element.attribute( "hidden" ).lower(); + if ( !attrHidden.isEmpty() ) + d->HiddenDefault = attrHidden == "true"; + } + + d->toolBarInfo = KToolBarPrivate::ToolBarInfo( dock, d->IndexDefault, d->NewLineDefault, d->OffsetDefault ); + mainWindow()->addDockWindow( this, dock, d->NewLineDefault ); +//US mainWindow()->moveDockWindow( this, dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + mainWindow()->moveToolBar( this, dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + + // Apply the highlight button setting + d->m_highlight = highlightSetting(); + + // Apply transparent-toolbar-moving setting (ok, this is global to the mainwindow, + // but we do it only if there are toolbars...) + if ( transparentSetting() != !mainWindow()->opaqueMoving() ) + mainWindow()->setOpaqueMoving( !transparentSetting() ); + + if ( d->HiddenDefault ) + hide(); + else + show(); + + getAttributes( d->PositionDefault, d->IconTextDefault, d->IndexDefault ); +} +*/ + +void KToolBar::getAttributes( QString &position, QString &icontext, int &index ) +{ + // get all of the stuff to save + switch ( barPos() ) { + case KToolBar::Flat: + position = "Flat"; + break; + case KToolBar::Bottom: + position = "Bottom"; + break; + case KToolBar::Left: + position = "Left"; + break; + case KToolBar::Right: + position = "Right"; + break; + case KToolBar::Floating: + position = "Floating"; + break; + case KToolBar::Top: + default: + position = "Top"; + break; + } + + if ( mainWindow() ) { + QMainWindow::ToolBarDock dock; + bool newLine; + int offset; + mainWindow()->getLocation( this, dock, index, newLine, offset ); + } + + switch (d->m_iconText) { + case KToolBar::IconTextRight: + icontext = "IconTextRight"; + break; + case KToolBar::IconTextBottom: + icontext = "IconTextBottom"; + break; + case KToolBar::TextOnly: + icontext = "TextOnly"; + break; + case KToolBar::IconOnly: + default: + icontext = "IconOnly"; + break; + } +} +/*US +void KToolBar::saveState( QDomElement ¤t ) +{ + QString position, icontext; + int index = -1; + getAttributes( position, icontext, index ); + + current.setAttribute( "noMerge", "1" ); + current.setAttribute( "position", position ); + current.setAttribute( "iconText", icontext ); + current.setAttribute( "index", index ); + current.setAttribute( "offset", offset() ); + current.setAttribute( "newline", newLine() ); + if ( isHidden() ) + current.setAttribute( "hidden", "true" ); + d->modified = true; +} +*/ + +void KToolBar::positionYourself( bool force ) +{ + if (force) + d->positioned = false; + + if ( d->positioned || !mainWindow() ) + { + //kdDebug(220) << "KToolBar::positionYourself d->positioned=true ALREADY DONE" << endl; + return; + } + // we can't test for ForceHide after moveDockWindow because QDockArea + // does a reparent() with showIt == true + bool doHide = isHidden(); + //kdDebug(220) << "positionYourself " << name() << " dock=" << d->toolBarInfo.dock << " newLine=" << d->toolBarInfo.newline << " offset=" << d->toolBarInfo.offset << endl; +/*US mainWindow()->moveDockWindow( this, d->toolBarInfo.dock, + d->toolBarInfo.newline, + d->toolBarInfo.index, + d->toolBarInfo.offset ); +*/ + mainWindow()->moveToolBar( this, d->toolBarInfo.dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + + if ( doHide ) + hide(); + // This method can only have an effect once - unless force is set + d->positioned = TRUE; +} + +//US KPopupMenu *KToolBar::contextMenu() +QPopupMenu *KToolBar::contextMenu() +{ + if ( context ) + return context; + + // Construct our context popup menu. Name it qt_dockwidget_internal so it + // won't be deleted by QToolBar::clear(). +//US context = new KPopupMenu( this, "qt_dockwidget_internal" ); + context = new QPopupMenu( this, "qt_dockwidget_internal" ); +//US context->insertTitle(i18n("Toolbar Menu")); + +//US KPopupMenu *orient = new KPopupMenu( context, "orient" ); + QPopupMenu *orient = new QPopupMenu( context, "orient" ); + orient->insertItem( i18n("toolbar position string","Top"), CONTEXT_TOP ); + orient->insertItem( i18n("toolbar position string","Left"), CONTEXT_LEFT ); + orient->insertItem( i18n("toolbar position string","Right"), CONTEXT_RIGHT ); + orient->insertItem( i18n("toolbar position string","Bottom"), CONTEXT_BOTTOM ); + orient->insertSeparator(-1); + //orient->insertItem( i18n("toolbar position string","Floating"), CONTEXT_FLOAT ); + orient->insertItem( i18n("min toolbar", "Flat"), CONTEXT_FLAT ); + +//US KPopupMenu *mode = new KPopupMenu( context, "mode" ); + QPopupMenu *mode = new QPopupMenu( context, "mode" ); + mode->insertItem( i18n("Icons Only"), CONTEXT_ICONS ); + mode->insertItem( i18n("Text Only"), CONTEXT_TEXT ); + mode->insertItem( i18n("Text Alongside Icons"), CONTEXT_TEXTRIGHT ); + mode->insertItem( i18n("Text Under Icons"), CONTEXT_TEXTUNDER ); + +//US KPopupMenu *size = new KPopupMenu( context, "size" ); + QPopupMenu *size = new QPopupMenu( context, "size" ); + size->insertItem( i18n("Default"), CONTEXT_ICONSIZES ); + // Query the current theme for available sizes + QValueList<int> avSizes; +/*US + KIconTheme *theme = KGlobal::instance()->iconLoader()->theme(); + if (!::qstrcmp(QObject::name(), "mainToolBar")) + avSizes = theme->querySizes( KIcon::MainToolbar); + else + avSizes = theme->querySizes( KIcon::Toolbar); +*/ + avSizes << 16; + avSizes << 32; + + d->iconSizes = avSizes; + + QValueList<int>::Iterator it; + for (it=avSizes.begin(); it!=avSizes.end(); it++) { + QString text; + if ( *it < 19 ) + text = i18n("Small (%1x%2)").arg(*it).arg(*it); + else if (*it < 25) + text = i18n("Medium (%1x%2)").arg(*it).arg(*it); + else + text = i18n("Large (%1x%2)").arg(*it).arg(*it); + //we use the size as an id, with an offset + size->insertItem( text, CONTEXT_ICONSIZES + *it ); + } + + context->insertItem( i18n("Orientation"), orient ); + orient->setItemChecked(CONTEXT_TOP, true); + context->insertItem( i18n("Text Position"), mode ); + context->setItemChecked(CONTEXT_ICONS, true); + context->insertItem( i18n("Icon Size"), size ); + +/*US + if (mainWindow()->inherits("KMainWindow")) + { + if ( (static_cast<KMainWindow*>(mainWindow())->toolBarMenuAction()) && + (static_cast<KMainWindow*>(mainWindow())->hasMenuBar()) ) + + (static_cast<KMainWindow*>(mainWindow()))->toolBarMenuAction()->plug(context); + } +*/ + + connect( context, SIGNAL( aboutToShow() ), this, SLOT( slotContextAboutToShow() ) ); + return context; +} + +void KToolBar::slotContextAboutToShow() +{ + if (!d->m_configurePlugged) + { + // try to find "configure toolbars" action + + KXMLGUIClient *xmlGuiClient = d->m_xmlguiClient; + if ( !xmlGuiClient && mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + xmlGuiClient = (KXMLGUIClient *)mainWindow(); + if ( xmlGuiClient ) + { + KAction *configureAction = xmlGuiClient->actionCollection()->action(KStdAction::stdName(KStdAction::ConfigureToolbars)); + if ( configureAction ) + { + configureAction->plug(context); + d->m_configurePlugged = true; + } + } + } + + for(int i = CONTEXT_ICONS; i <= CONTEXT_TEXTUNDER; ++i) + context->setItemChecked(i, false); + + switch( d->m_iconText ) + { + case IconOnly: + default: + context->setItemChecked(CONTEXT_ICONS, true); + break; + case IconTextRight: + context->setItemChecked(CONTEXT_TEXTRIGHT, true); + break; + case TextOnly: + context->setItemChecked(CONTEXT_TEXT, true); + break; + case IconTextBottom: + context->setItemChecked(CONTEXT_TEXTUNDER, true); + break; + } + + QValueList<int>::ConstIterator iIt = d->iconSizes.begin(); + QValueList<int>::ConstIterator iEnd = d->iconSizes.end(); + for (; iIt != iEnd; ++iIt ) + context->setItemChecked( CONTEXT_ICONSIZES + *iIt, false ); + + context->setItemChecked( CONTEXT_ICONSIZES, false ); + + context->setItemChecked( CONTEXT_ICONSIZES + d->m_iconSize, true ); + + for ( int i = CONTEXT_TOP; i <= CONTEXT_FLAT; ++i ) + context->setItemChecked( i, false ); + + switch ( barPos() ) + { + case KToolBar::Flat: + context->setItemChecked( CONTEXT_FLAT, true ); + break; + case KToolBar::Bottom: + context->setItemChecked( CONTEXT_BOTTOM, true ); + break; + case KToolBar::Left: + context->setItemChecked( CONTEXT_LEFT, true ); + break; + case KToolBar::Right: + context->setItemChecked( CONTEXT_RIGHT, true ); + break; + case KToolBar::Floating: + context->setItemChecked( CONTEXT_FLOAT, true ); + break; + case KToolBar::Top: + context->setItemChecked( CONTEXT_TOP, true ); + break; + default: break; + } +} + +void KToolBar::widgetDestroyed() +{ + removeWidgetInternal( (QWidget*)sender() ); +} + +void KToolBar::removeWidgetInternal( QWidget * w ) +{ + if ( inshutdownprocess ) + return; + widgets.removeRef( w ); + QMap< QWidget*, int >::Iterator it = widget2id.find( w ); + if ( it == widget2id.end() ) + return; + id2widget.remove( *it ); + widget2id.remove( it ); +} + +void KToolBar::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ktoolbar.moc" + diff --git a/microkde/kdeui/ktoolbar.h b/microkde/kdeui/ktoolbar.h new file mode 100644 index 0000000..2c061b5 --- a/dev/null +++ b/microkde/kdeui/ktoolbar.h @@ -0,0 +1,1107 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999, 2000 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ + +#ifndef KTOOLBAR_H +#define KTOOLBAR_H + +#ifndef DESKTOP_VERSION +#define private public +#include <qtoolbar.h> +#undef private +#include <qpe/qpetoolbar.h> +#else +#include <qtoolbar.h> +#endif + + +#include <qmainwindow.h> +#include <qcombobox.h> +#include <qmap.h> +#include <qptrlist.h> +#include <kglobal.h> +#include <qguardedptr.h> +#include <qframe.h> +#include <qiconset.h> + +class QDomElement; +class QSize; +class QPixmap; +class QPopupMenu; +class QStringList; +class QDomDocument; +class QTimer; + +class KLineEdit; +class KToolBar; +class KToolBarButton; +class KToolBoxManager; +//US class KAnimWidget; +//US class KPopupMenu; +//US class KInstance; +class KComboBox; +class KXMLGUIClient; + +class KToolBarPrivate; + +class KToolBarSeparator : public QFrame +{ + Q_OBJECT +public: + KToolBarSeparator( Orientation, bool l, QToolBar *parent, const char* name=0 ); + + QSize sizeHint() const; + Orientation orientation() const { return orient; } + QSizePolicy sizePolicy() const; + bool showLine() const { return line; } +public slots: + void setOrientation( Orientation ); +protected: + void styleChange( QStyle& ); +private: + Orientation orient; + bool line; +}; + + + /** + * A KDE-style toolbar. + * + * KToolBar can be dragged around in and between different docks. + * + * A KToolBar can contain all sorts of widgets. + * + * KToolBar can be used as a standalone widget, but @ref KMainWindow + * provides easy factories and management of one or more toolbars. + * Once you have a KToolBar object, you can insert items into it with the + * insert... methods, or remove them with the @ref removeItem() method. This + * can be done at any time; the toolbar will be automatically updated. + * There are also many methods to set per-child properties like alignment + * and toggle behaviour. + * + * KToolBar uses a global config group to load toolbar settings on + * construction. It will reread this config group on a + * @ref KApplication::appearanceChanged() signal. + * + * @short Floatable toolbar with auto resize. + * @version $Id$ + * @author Reginald Stadlbauer <reggie@kde.org>, Stephan Kulow <coolo@kde.org>, Sven Radej <radej@kde.org>. + */ + +// strange things are happening ... so I have to use strange define methods ... +// porting KToolBar back to Qt2 really needs some strange hacks + +#ifndef DESKTOP_VERSION +#define QToolBar QPEToolBar +#endif + + class KToolBar : public QToolBar +{ + Q_OBJECT + + + Q_ENUMS( IconText BarPosition ) + + Q_PROPERTY( IconText iconText READ iconText WRITE setIconText ) + Q_PROPERTY( BarPosition barPos READ barPos WRITE setBarPos ) + Q_PROPERTY( bool fullSize READ fullSize WRITE setFullSize ) + Q_PROPERTY( int iconSize READ iconSize WRITE setIconSize ) + Q_PROPERTY( QString text READ text WRITE setText ) +#ifndef DESKTOP_VERSION +#undef QToolBar +#endif +public: + enum IconText{IconOnly = 0, IconTextRight, TextOnly, IconTextBottom}; + /** + * The state of the status bar. + * @deprecated + **/ + enum BarStatus{Toggle, Show, Hide}; + /** + * Possible bar positions. + **/ + enum BarPosition{ Unmanaged, Floating, Top, Bottom, Right, Left, Flat}; + + /** + * Constructor. + * This constructor is used by the XML-GUI. If you use it, you need + * to call QMainWindow::addToolBar to specify the position of the toolbar. + * So it's simpler to use the other constructor. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parent The standard toolbar parent (usually a + * @ref KMainWindow) + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QWidget *parent, const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + /** + * Constructor for non-XML-GUI applications. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parentWindow The window that should be the parent of this toolbar + * @param dock The position of the toolbar. Usually QMainWindow::Top. + * @param newLine If true, start a new line in the dock for this toolbar. + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock /*= QMainWindow::Top*/, bool newLine = false, + const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + /** + * Constructor for non-XML-GUI applications. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parentWindow The window that should be the parent of this toolbar + * @param dock Another widget than the mainwindow to dock toolbar to. + * @param newLine If true, start a new line in the dock for this toolbar. + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine = false, + const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + virtual ~KToolBar(); + + /** + * Insert a button (a @ref KToolBarButton) with a pixmap. The + * pixmap is loaded by the button itself based on the global icon + * settings. + * + * You should connect to one or more signals in KToolBar: + * @ref clicked() , @ref pressed() , @ref released() , or + * @ref highlighted() and if the button is a toggle button + * (@ref setToggle() ) @ref toggled() . Those signals have @p id + * of a button that caused the signal. If you want to bind a popup + * to button, see @ref setButton(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QString& icon, int id, bool enabled = true, + const QString& text = QString::null, int index=-1/*US , + KInstance *_instance = KGlobal::instance()*/); + + /** + * This is the same as above, but with specified signals and + * slots to which this button will be connected. + * + * You can add more signals with @ref addConnection(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param signal The signal to connect to + * @param receiver The slot's parent + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QString& icon, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, const QString& text = QString::null, + int index=-1/*US, KInstance *_instance = KGlobal::instance()*/ ); + + /** + * Inserts a button (a @ref KToolBarButton) with the specified + * pixmap. This pixmap will be used as the "active" one and the + * disabled and default ones will be autogenerated. + * + * It is recommended that you use the insertButton function that + * allows you to specify the icon name rather then the pixmap + * itself. Specifying the icon name is much more flexible. + * + * You should connect to one or more signals in KToolBar: + * @ref clicked() , @ref pressed() , @ref released() , or + * @ref highlighted() and if the button is a toggle button + * (@ref setToggle() ) @ref toggled() . Those signals have @p id + * of a button that caused the signal. If you want to bind a popup + * to button, see @ref setButton(). + * + * @param pixmap The active pixmap + * @param id The id of this button + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QPixmap& pixmap, int id, bool enabled = true, + const QString& text = QString::null, int index=-1 ); + + /** + * This is the same as above, but with specified signals and + * slots to which this button will be connected. + * + * You can add more signals with @ref addConnection(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param signal The signal to connect to + * @param receiver The slot's parent + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QPixmap& pixmap, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, const QString& text = QString::null, + int index=-1 ); + + /** + * Inserts a button with popupmenu. + * + * Button will have small + * triangle. You have to connect to popup's signals. The + * signals @ref KButton::pressed(), @ref KButton::released(), + * @ref KButton::clicked() or @ref KButton::doubleClicked() are @p not + * emmited by + * this button (see @ref setDelayedPopup() for that). + * You can add custom popups which inherit @ref QPopupMenu to get popups + * with tables, drawings etc. Just don't fiddle with events there. + */ + int insertButton(const QString& icon, int id, QPopupMenu *popup, + bool enabled, const QString&_text, int index=-1); + + /** + * Inserts a button with popupmenu. + * + * Button will have small + * triangle. You have to connect to popup's signals. The + * signals @ref KButton::pressed(), @ref KButton::released(), + * @ref KButton::clicked() or @ref KButton::doubleClicked() are @p not + * emmited by + * this button (see @ref setDelayedPopup() for that). + * You can add custom popups which inherit @ref QPopupMenu to get popups + * with tables, drawings etc. Just don't fiddle with events there. + */ + int insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup, + bool enabled, const QString&_text, int index=-1); + + /** + * Inserts a @ref KLineEdit. You have to specify signals and slots to + * which KLineEdit will be connected. KLineEdit has all slots QLineEdit + * has, plus signals @ref KLineEdit::completion and @ref KLineEdit::textRotation + * KLineEdit can be set to autoresize itself to full free width + * in toolbar, that is to last right aligned item. For that, + * toolbar must be set to full width (which it is by default). + * @see setFullWidth() + * @see setItemAutoSized() + * @see KLineEdit + * @return Item index. + */ + int insertLined (const QString& text, int id, + const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, + const QString& toolTipText = QString::null, + int size = 70, int index =-1); + + /** + * Inserts a @ref KComboBox with list. + * + * Can be writable, but cannot contain + * pixmaps. By default inserting policy is AtBottom, i.e. typed items + * are placed at the bottom of the list. Can be autosized. If the size + * argument is specified as -1, the width of the combobox is automatically + * computed. + * + * @see setFullWidth() + * @see setItemAutoSized() + * @see KComboBox + * @return Item index. + */ + int insertCombo (const QStringList &list, int id, bool writable, + const char *signal, const QObject *receiver, + const char *slot, bool enabled=true, + const QString& tooltiptext=QString::null, + int size=70, int index=-1, + QComboBox::Policy policy = QComboBox::AtBottom); + + /** + * Insert a @ref KComboBox with text. + * + * The rest is the same as above. + * @see setItemAutoSized() + * + * @see KComboBox + * @return Item index. + */ + int insertCombo (const QString& text, int id, bool writable, + const char *signal, QObject *recevier, + const char *slot, bool enabled=true, + const QString& tooltiptext=QString::null, + int size=70, int index=-1, + QComboBox::Policy policy = QComboBox::AtBottom); + + /** + * Inserts a separator into the toolbar with the given id. + * Returns the separator's index + */ + int insertSeparator( int index = -1, int id = -1 ); + + /** + * Inserts a line separator into the toolbar with the given id. + * Returns the separator's index + */ + int insertLineSeparator( int index = -1, int id = -1 ); + + /** + * Inserts a user-defined widget. The widget @p must have this + * toolbar as its parent. + * + * Widget must have a QWidget for base class. Widget can be + * autosized to full width. If you forget about it, you can get a + * pointer to this widget with @ref getWidget(). + * @see setItemAutoSized() + * @return Item index. + */ + int insertWidget(int id, int width, QWidget *_widget, int index=-1); + + /** + * Inserts an animated widget. A @ref KAnimWidget will be created + * internally using the icon name you provide. + * This will emit a signal (clicked()) whenever the + * animation widget is clicked. + * + * @see animatedWidget() + * + * @param id The id for this toolbar item + * @param receiver The parent of your slot + * @param slot The slot to receive the clicked() signal + * @param icons The name of the animation icon group to use + * @param index The item index + * + * @return The item index + */ +/*US + int insertAnimatedWidget(int id, QObject *receiver, const char *slot, + const QString& icons, int index = -1); +*/ + /** + * This will return a pointer to the given animated widget, if it + * exists. + * + * @see insertAnimatedWidget + * + * @param id The id for the widget you want to get a pointer to + * + * @return A pointer to the current animated widget or 0L + */ +//US KAnimWidget *animatedWidget( int id ); + + /** + * Adds connections to items. + * + * It is important that you + * know the @p id of particular item. Nothing happens if you forget @p id. + */ + void addConnection (int id, const char *signal, + const QObject *receiver, const char *slot); + /** + * Enables/disables item. + */ + void setItemEnabled( int id, bool enabled ); + + /** + * Sets the icon for a button. + * + * Can be used while button is visible. + */ + void setButtonIcon( int id, const QString& _icon ); + + /** + * Sets button pixmap. + * + * Can be used while button is visible. + */ + void setButtonPixmap( int id, const QPixmap& _pixmap ); + + /** + * Sets a button icon from a QIconSet. + * + * Can be used while button is visible. + */ + void setButtonIconSet( int id, const QIconSet& iconset ); + + /** + * Sets a delayed popup for a button. + * + * Delayed popup is what you see in + * Netscape Navigator's Previous and Next buttons: If you click them you + * go back + * or forth. If you press them long enough, you get a history-menu. + * This is exactly what we do here. + * + * You will insert normal a button with connection (or use signals from + * toolbar): + * <pre> + * bar->insertButton(icon, id, SIGNAL(clicked ()), this, + * SLOT (slotClick()), true, "click or wait for popup"); + * </pre> And then add a delayed popup: + * <pre> + * bar->setDelayedPopup (id, historyPopup); </pre> + * + * Don't add delayed popups to buttons which have normal popups. + * + * You may add popups which are derived from @ref QPopupMenu. You may + * add popups that are already in the menu bar or are submenus of + * other popups. + */ + void setDelayedPopup (int id , QPopupMenu *_popup, bool toggle = false); + + /** + * Turns a button into an autorepeat button. + * + * Toggle buttons, buttons with menus, or + * buttons with delayed menus cannot be made into autorepeat buttons. + * Moreover, you can and will receive + * only the signal clicked(), but not pressed() or released(). + * When the user presses this button, you will receive the signal clicked(), + * and if the button is still pressed after some time, + * you will receive more clicked() signals separated by regular + * intervals. Since this uses @ref QButton::setAutoRepeat() , + * I can't quantify 'some'. + */ + void setAutoRepeat (int id, bool flag=true); + + + /** + * Turns button into a toggle button if @p flag is true. + */ + void setToggle (int id, bool flag = true); + + /** + * Toggles a togglebutton. + * + * If the button is a toggle button (see @ref setToggle()) + * the button state will be toggled. This will also cause the toolbar to + * emit the signal @ref KButton::toggled() with parameter @p id. You must connect to + * this signal, or use @ref addConnection() to connect directly to the + * button signal @ref KButton::toggled(). + */ + void toggleButton (int id); + + /** + * Sets a toggle button state. + * + * If the button is a toggle button (see @ref setToggle()) + * this will set its state flag. This will also emit the signal + * @ref KButton::toggled(). + * + * @see setToggle() + */ + void setButton (int id, bool flag); + + /** + * @return @p true if button is on, @p false if button is off or if the + * button is not a toggle button. + * @see setToggle() + */ + bool isButtonOn (int id) const; + + /** + * Sets the text of a line editor. + * + * Cursor is set at end of text. + */ + void setLinedText (int id, const QString& text); + + /** + * Returns a line editor text. + */ + QString getLinedText (int id) const; + + /** + * Inserts @p text in combobox @p id at position @p index. + */ + void insertComboItem (int id, const QString& text, int index); + + /** + * Inserts @p list in combobox @p id at position @p index. + */ + void insertComboList (int id, const QStringList &list, int index); + + /** + * Removes item @p index from combobox @p id. + */ + void removeComboItem (int id, int index); + + /** + * Sets item @p index to be current item in combobox @p id. + */ + void setCurrentComboItem (int id, int index); + + /** + * Changes item @p index in combobox @p id to text. + * + * @p index = -1 refers current item (one displayed in the button). + */ + void changeComboItem (int id, const QString& text, int index=-1); + + /** + * Clears the combobox @p id. + * + * Does not delete it or hide it. + */ + void clearCombo (int id); + + /** + * Returns text of item @p index from combobox @p id. + * + * @p index = -1 refers to current item. + */ + + QString getComboItem (int id, int index=-1) const; + + /** + * Returns a pointer to the combobox. + * + * Example: + * <pre> + * KComboBox *combo = toolbar->getCombo(combo_id); + * </pre> + * That way you can get access to other public methods + * that @ref KComboBox provides. + */ + KComboBox * getCombo(int id); + + /** + * Returns a pointer to KToolBarLined. + * + * Example: + * <pre> + * KLineEdit * lined = toolbar->getKToolBarLined(lined_id); + * </pre> + * That way you can get access to other public methods + * that @ref KLineEdit provides. @ref KLineEdit is the same thing + * as @ref QLineEdit plus completion signals. + */ + KLineEdit * getLined (int id); + + /** + * Returns a pointer to KToolBarButton. + * + * Example: + * <pre> + * KToolBarButton * button = toolbar->getButton(button_id); + * </pre> + * That way you can get access to other public methods + * that @ref KToolBarButton provides. + * + * Using this method is not recommended. + */ + KToolBarButton * getButton (int id); + + /** + * Align item to the right. + * + * This works only if toolbar is set to full width. + * @see setFullWidth() + */ + void alignItemRight (int id, bool right = true); + + /** + * Returns a pointer to an inserted widget. + * + * Wrong ids are not tested. + * You can do with this whatever you want, + * except change its height (hardcoded). If you change its width + * you will probably have to call QToolBar::updateRects(true) + * @see QWidget + * @see updateRects() + * + * KDE4: make this const! + */ + QWidget *getWidget (int id); + + /** + * Set item autosized. + * + * This works only if the toolbar is set to full width. + * Only @p one item can be autosized, and it has to be + * the last left-aligned item. Items that come after this must be right + * aligned. Items that can be right aligned are Lineds, Frames, Widgets and + * Combos. An autosized item will resize itself whenever the toolbar geometry + * changes to the last right-aligned item (or to end of toolbar if there + * are no right-aligned items.) + * @see setFullWidth() + * @see alignItemRight() + */ + void setItemAutoSized (int id, bool yes = true); + + /** + * Remove all items. + * + * The toolbar is redrawn after it. + */ + void clear (); + + /** + * Remove item @p id. + * + * Item is deleted. Toolbar is redrawn after it. + */ + void removeItem (int id); + + /** + * Remove item @p id. + * + * Item is deleted when toolbar is redrawn. + */ + void removeItemDelayed (int id); + + /** + * Hide item. + */ + void hideItem (int id); + + /** + * Show item. + */ + void showItem (int id); + + /** + * Returns the index of the given item. + * + * KDE4: make this const! + */ + int itemIndex (int id); + + /** + * Set toolbar to full parent size (default). + * + * In full size mode the bar + * extends over the parent's full width or height. If the mode is disabled + * the toolbar tries to take as much space as it needs without wrapping, but + * it does not exceed the parent box. You can force a certain width or + * height with @ref setMaxWidth() or @ref setMaxHeight(). + * + * If you want to use right-aligned items or auto-sized items you must use + * full size mode. + */ + void setFullSize(bool flag = true); + + /** + * @return @p true if the full-size mode is enabled. Otherwise + * it returns @false. + */ + bool fullSize() const; + + /** + * @deprecated use setMovingEnabled(bool) instead. + * Enable or disable moving of toolbar. + */ + void enableMoving(bool flag = true); + + /** + * Set position of toolbar. + * @see BarPosition() + */ + void setBarPos (BarPosition bpos); + + /** + * Returns position of toolbar. + */ + BarPosition barPos(); + + /** + * @deprecated + * Show, hide, or toggle toolbar. + * + * This method is provided for compatibility only, + * please use show() and/or hide() instead. + * @see BarStatus + */ + bool enable(BarStatus stat); + + /** + * @deprecated + * Use setMaximumHeight() instead. + */ + void setMaxHeight (int h); // Set max height for vertical toolbars + + /** + * @deprecated + * Use maximumHeight() instead. + * Returns the value that was set with @ref setMaxHeight(). + */ + int maxHeight(); + + /** + * @deprecated + * Use setMaximumWidth() instead. + * Set maximal width of horizontal (top or bottom) toolbar. + */ + void setMaxWidth (int dw); + + /** + * @deprecated + * Use maximumWidth() instead. + * Returns the value that was set with @ref setMaxWidth(). + */ + int maxWidth(); + + /** + * Set title for toolbar when it floats. + * + * Titles are however not (yet) + * visible. You can't change toolbar's title while it's floating. + */ + void setTitle (const QString& _title); + + /** + * @deprecated + * Use enableMoving() instead. + */ + void enableFloating (bool arrrrrrgh); + + /** + * Set the kind of painting for buttons. + * + * Choose from: + * @li IconOnly (only icons), + * @li IconTextRight (icon and text, text is left from icons), + * @li TextOnly (only text), + * @li IconTextBottom (icons and text, text is under icons). + * @see IconText + * + */ + void setIconText(IconText it); + // Note: don't merge with the next one, it breaks Qt properties + + /** + * Similar to @ref setIconText(IconText it) but allows you to + * disable or enable updating. If @p update is false, then the + * buttons will not be updated. This is useful only if you know + * that you will be forcing an update later. + */ + void setIconText(IconText it, bool update); + + /** + * @return The current text style for buttons. + */ + IconText iconText() const; + + /** + * Set the icon size to load. Usually you should not call + * this, the icon size is taken care of by KIconLoader + * and globally configured. + * By default, the toolbar will load icons of size 32 for main + * toolbars and 22 for other toolbars + * @see KIconLoader. + * + * @param size The size to use + */ + void setIconSize(int size); + // Note: don't merge with the next one, it breaks Qt properties + + /** + * Same as @ref setIconText(int size) but allows you + * to disable the toolbar update. + * + * @param size The size to use + * @param update If true, then the toolbar will be updated after + * this + */ + void setIconSize(int size, bool update); + + /** + * @return The current icon size for buttons. + */ + int iconSize() const; + + /** + * This allows you to enable or disable the context menu. + * + * @param enable If false, then the context menu will be disabled + */ + void setEnableContextMenu(bool enable = true); + + /** + * Returns whether or not the context menu is disabled + * + * @return The context menu state + */ + bool contextMenuEnabled() const; + + /** + * This will inform a toolbar button to ignore certain style + * changes. Specifically, it will ignore IconText (always IconOnly) + * and will not allow image effects to apply. + * + * @param id The button to exclude from styles + * @param no_style If true, then it is excluded (default: true). + */ + void setItemNoStyle(int id, bool no_style = true); + + void setFlat (bool flag); + + /** + * @return the number of items in the toolbar + */ + int count() const; + + /** + * Instruct the toolbar to save it's current state to either the app + * config file or to the XML-GUI resource file (whichever has + * precedence). + */ + void saveState(); + + /** + * Save the toolbar settings to group @p configGroup in @p config. + */ + void saveSettings(KConfig *config, const QString &configGroup); + + /** + * Read the toolbar settings from group @p configGroup in @p config + * and apply them. + */ + void applySettings(KConfig *config, const QString &configGroup); + + /** + * Tell the toolbar what XML-GUI resource file it should use to save + * it's state. The state of the toolbar (position, size, etc) is + * saved in KConfig files if the application does not use XML-GUI.. + * but if the app does, then it's saved the XML file. This function + * allows this to happen. + * + * @param xmlfile The XML-GUI resource file to write to + * @param xml The DOM document for the XML-GUI building + */ + // void setXML(const QString& xmlfile, const QDomDocument& xml); + /* @internal */ + void setXMLGUIClient( KXMLGUIClient *client ); + + /** + * Assign a (translated) text to this toolbar. This is used + * for the tooltip on the handle, and when listing the toolbars. + */ + void setText( const QString & txt ); + + /** + * @return the toolbar's text. + */ + QString text() const; + + void setStretchableWidget( QWidget *w ); + QSizePolicy sizePolicy() const; + bool highlight() const; + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSize minimumSize() const; + + void hide(); + void show(); + + void updateRects( bool = FALSE ) {} + +//US void loadState( const QDomElement &e ); +//US void saveState( QDomElement &e ); + + /** + * @internal + */ + void positionYourself( bool force = false); + +signals: + /** + * Emitted when button @p id is clicked. + */ + void clicked(int id); + + /** + * Emitted when button @p id is double-clicked. + * + * Note: you will always + * recive two @ref clicked() , @ref pressed() and @ref released() signals. + * There is no way to avoid it - at least no easy way. + * If you need to resolve this all you can do is set up timers + * which wait for @ref QApplication::doubleClickInterval() to expire. + * If in that time you don't get this signal, you may belive that + * button was only clicked and not double-clicked. + * And please note that butons with popup menus do not emit this signal, + * but those with delayed popup do. + */ + void doubleClicked (int id); + + /** + * Emitted when button @p id is pressed. + */ + void pressed(int); + + /** + * Emits when button @p id is released. + */ + void released(int); + + /** + * Emitted when a toggle button changes state. + * + * Emitted also if you change state + * with @ref setButton() or @ref toggleButton() + * If you make a button normal again, with + * setToggle(false), this signal won't + * be emitted. + */ + void toggled(int); + + /** + * This signal is emitted when item id gets highlighted/unhighlighted + * (i.e when mouse enters/exits). + * + * Note that this signal is emitted from + * all buttons (normal, disabled and toggle) even when there is no visible + * change in buttons (i.e., buttons do not raise when mouse enters). + * The parameter @p isHighlighted is @p true when mouse enters and @p false when + * mouse exits. + */ + void highlighted(int id, bool isHighlighted); + + /** + * This signal is emitted when item id gets highlighted/unhighlighted + * (i.e when mouse enters/exits). + * + * Note that this signal is emitted from + * all buttons (normal, disabled and toggle) even when there is no visible + * change in buttons (i.e., buttons do not raise when mouse enters). + */ + void highlighted(int id ); + + /** + * Emitted when toolbar changes position, or when + * an item is removed from toolbar. + * + * If you subclass @ref KMainWindow and reimplement + * @ref KMainWindow::resizeEvent() be sure to connect to + * this signal. Note: You can connect this signal to a slot that + * doesn't take parameter. + */ + void moved( BarPosition ); + + /** + * @internal + * This signal is emitted when toolbar detects changing of + * following parameters: + * highlighting, button-size, button-mode. This signal is + * internal, aimed to buttons. + */ + void modechange (); + + /** + * This signal is emitted when the toolbar is getting deleted, + * and before ~KToolbar finishes (so it's still time to remove + * widgets from the toolbar). + * Used by KWidgetAction. + * @since 3.2 + */ + void toolbarDestroyed(); + +public: + /** + * @return global setting for "Highlight buttons under mouse" + */ + static bool highlightSetting(); + + /** + * @return global setting for "Toolbars transparent when moving" + */ + static bool transparentSetting(); + + /** + * @return global setting for "Icon Text" + */ + static IconText iconTextSetting(); + +public slots: + virtual void setIconText( const QString &txt ) + { QToolBar::setIconText( txt ); } + +protected: + void mousePressEvent( QMouseEvent * ); + void childEvent( QChildEvent *e ); + void showEvent( QShowEvent *e ); + void resizeEvent( QResizeEvent *e ); + bool event( QEvent *e ); + void applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal = false); + QString settingsGroup(); + +private slots: + void rebuildLayout(); + void slotReadConfig (); + void slotAppearanceChanged(); + void slotIconChanged(int); + void slotRepaint(); + void toolBarPosChanged( QToolBar *tb ); + void slotContextAboutToShow(); + void widgetDestroyed(); + +private: + void init( bool readConfig = true, bool honorStyle = false ); + void doConnections( KToolBarButton *button ); + void insertWidgetInternal( QWidget *w, int &index, int id ); + void removeWidgetInternal( QWidget *w ); + void getAttributes( QString &position, QString &icontext, int &index ); +//US KPopupMenu *contextMenu(); + QPopupMenu *contextMenu(); + + QMap<QWidget*, int > widget2id; + typedef QMap<int, QWidget* > Id2WidgetMap; + Id2WidgetMap id2widget; +//US KPopupMenu *context; + QPopupMenu *context; + QPtrList<QWidget> widgets; + QTimer *layoutTimer; + QGuardedPtr<QWidget> stretchableWidget, rightAligned; +protected: + virtual void virtual_hook( int id, void* data ); +private: + KToolBarPrivate *d; + bool inshutdownprocess; +}; + +#endif diff --git a/microkde/kdeui/ktoolbarbutton.cpp b/microkde/kdeui/ktoolbarbutton.cpp new file mode 100644 index 0000000..1d5d0e5 --- a/dev/null +++ b/microkde/kdeui/ktoolbarbutton.cpp @@ -0,0 +1,756 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 1999 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//US #include <config.h> +#include <string.h> + +#include "ktoolbarbutton.h" +#include "ktoolbar.h" + +#include <qstyle.h> +#include <qimage.h> +#include <qtimer.h> +#include <qdrawutil.h> +#include <qtooltip.h> +#include <qbitmap.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qlayout.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> +//US #include <kiconeffect.h> +#include <kiconloader.h> + +// needed to get our instance +#include <kmainwindow.h> + +template class QIntDict<KToolBarButton>; + +class KToolBarButtonPrivate +{ +public: + KToolBarButtonPrivate() + { + m_noStyle = false; + m_isSeparator = false; + m_isRadio = false; + m_highlight = false; + m_isRaised = false; + m_isActive = false; + + m_iconName = QString::null; + m_iconText = KToolBar::IconOnly; + m_iconSize = 0; + +//US m_instance = KGlobal::instance(); + } + ~KToolBarButtonPrivate() + { + } + + int m_id; + bool m_noStyle: 1; + bool m_isSeparator: 1; + bool m_isRadio: 1; + bool m_highlight: 1; + bool m_isRaised: 1; + bool m_isActive: 1; + + QString m_iconName; + + KToolBar *m_parent; + KToolBar::IconText m_iconText; + int m_iconSize; + QSize size; + + QPoint m_mousePressPos; + +//US KInstance *m_instance; +}; + +// This will construct a separator +KToolBarButton::KToolBarButton( QWidget *_parent, const char *_name ) + : QToolButton( _parent , _name) +{ + d = new KToolBarButtonPrivate; + + resize(6,6); + hide(); + d->m_isSeparator = true; +} + +KToolBarButton::KToolBarButton( const QString& _icon, int _id, + QWidget *_parent, const char *_name, + const QString &_txt/*US, KInstance *_instance*/ ) + : QToolButton( _parent, _name ), d( 0 ) +{ + d = new KToolBarButtonPrivate; + + d->m_id = _id; + d->m_parent = (KToolBar*)_parent; + QToolButton::setTextLabel(_txt); +//US d->m_instance = _instance; + + setFocusPolicy( NoFocus ); + + // connect all of our slots and start trapping events + connect(d->m_parent, SIGNAL( modechange() ), + this, SLOT( modeChange() )); + + connect(this, SIGNAL( clicked() ), + this, SLOT( slotClicked() ) ); + connect(this, SIGNAL( pressed() ), + this, SLOT( slotPressed() ) ); + connect(this, SIGNAL( released() ), + this, SLOT( slotReleased() ) ); + installEventFilter(this); + + d->m_iconName = _icon; + + // do our initial setup + modeChange(); +} + +KToolBarButton::KToolBarButton( const QPixmap& pixmap, int _id, + QWidget *_parent, const char *name, + const QString& txt) + : QToolButton( _parent, name ), d( 0 ) +{ + d = new KToolBarButtonPrivate; + + d->m_id = _id; + d->m_parent = (KToolBar *) _parent; + QToolButton::setTextLabel(txt); + + setFocusPolicy( NoFocus ); + + // connect all of our slots and start trapping events + connect(d->m_parent, SIGNAL( modechange()), + this, SLOT(modeChange())); + + connect(this, SIGNAL( clicked() ), + this, SLOT( slotClicked() )); + connect(this, SIGNAL( pressed() ), + this, SLOT( slotPressed() )); + connect(this, SIGNAL( released() ), + this, SLOT( slotReleased() )); + installEventFilter(this); + + // set our pixmap and do our initial setup + setIconSet( QIconSet( pixmap )); + modeChange(); +} + +KToolBarButton::~KToolBarButton() +{ + delete d; d = 0; +} + +void KToolBarButton::modeChange() +{ + QSize mysize; + + // grab a few global variables for use in this function and others + d->m_highlight = d->m_parent->highlight(); + d->m_iconText = d->m_parent->iconText(); + + d->m_iconSize = d->m_parent->iconSize(); + if (!d->m_iconName.isNull()) + setIcon(d->m_iconName); + + // we'll start with the size of our pixmap + int pix_width = d->m_iconSize; + + if ( d->m_iconSize == 0 ) { + if (!strcmp(d->m_parent->name(), "mainToolBar")) +/*US + pix_width = IconSize( KIcon::MainToolbar ); + else + pix_width = IconSize( KIcon::Toolbar ); +*/ +//qDebug("KToolBarButton::modeChange make iconsize configurable"); + pix_width = 16; + } + int pix_height = pix_width; + + int text_height = 0; + int text_width = 0; + + QToolTip::remove(this); + if (d->m_iconText != KToolBar::IconOnly) + { + // okay, we have to deal with fonts. let's get our information now +/*US + QFont tmp_font = KGlobalSettings::toolBarFont(); + + // now parse out our font sizes from our chosen font + QFontMetrics fm(tmp_font); + + text_height = fm.lineSpacing(); + text_width = fm.width(textLabel()); +*/ +//qDebug("KToolBarButton::modeChange make textsize configurable"); + + // none of the other modes want tooltips + } + else + { + QToolTip::add(this, textLabel()); + } + + switch (d->m_iconText) + { + case KToolBar::IconOnly: + mysize = QSize(pix_width, pix_height); + break; + + case KToolBar::IconTextRight: + mysize = QSize(pix_width + text_width + 4, pix_height); + break; + + case KToolBar::TextOnly: + mysize = QSize(text_width + 4, text_height); + break; + + case KToolBar::IconTextBottom: + mysize = QSize((text_width + 4 > pix_width) ? text_width + 4 : pix_width, pix_height + text_height); + break; + + default: + break; + } +/*US + mysize = style().sizeFromContents(QStyle::CT_ToolButton, this, mysize). + expandedTo(QApplication::globalStrut()); +*/ + // make sure that this isn't taller then it is wide + if (mysize.height() > mysize.width()) + mysize.setWidth(mysize.height()); + + d->size = mysize; + setFixedSize(mysize); + updateGeometry(); +} + +void KToolBarButton::setTextLabel( const QString& text, bool tipToo) +{ + if (text.isNull()) + return; + + QString txt(text); + if (txt.right(3) == QString::fromLatin1("...")) + txt.truncate(txt.length() - 3); + + QToolButton::setTextLabel(txt, tipToo); + update(); +} + +void KToolBarButton::setText( const QString& text) +{ + setTextLabel(text, true); + modeChange(); +} + +void KToolBarButton::setIcon( const QString &icon ) +{ + d->m_iconName = icon; + d->m_iconSize = d->m_parent->iconSize(); + // QObject::name() return "const char *" instead of QString. + if (!strcmp(d->m_parent->name(), "mainToolBar")) +/*US QToolButton::setIconSet( d->m_instance->iconLoader()->loadIconSet( + d->m_iconName, KIcon::MainToolbar, d->m_iconSize )); +*/ + QToolButton::setIconSet( KGlobal::iconLoader()->loadIconSet(d->m_iconName )); + else +/*US QToolButton::setIconSet(d->m_instance->iconLoader()->loadIconSet( + d->m_iconName, KIcon::Toolbar, d->m_iconSize )); +*/ + QToolButton::setIconSet(KGlobal::iconLoader()->loadIconSet(d->m_iconName)); +} + +void KToolBarButton::setIconSet( const QIconSet &iconset ) +{ + QToolButton::setIconSet( iconset ); +} + +// remove? +void KToolBarButton::setPixmap( const QPixmap &pixmap ) +{ + if( pixmap.isNull()) // called by QToolButton + { + QToolButton::setPixmap( pixmap ); + return; + } + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Active ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDefaultPixmap( const QPixmap &pixmap ) +{ + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Normal ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDisabledPixmap( const QPixmap &pixmap ) +{ + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Disabled ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDefaultIcon( const QString& icon ) +{ + QIconSet set = iconSet(); + QPixmap pm; + if (!strcmp(d->m_parent->name(), "mainToolBar")) + pm = /*US d->m_instance->iconLoader()*/KGlobal::iconLoader()->loadIcon( icon, KIcon::MainToolbar, + d->m_iconSize ); + else + pm = /*US d->m_instance->iconLoader()*/KGlobal::iconLoader()->loadIcon( icon, KIcon::Toolbar, + d->m_iconSize ); + set.setPixmap( pm, QIconSet::Automatic, QIconSet::Normal ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDisabledIcon( const QString& icon ) +{ + QIconSet set = iconSet(); + QPixmap pm; + if (!strcmp(d->m_parent->name(), "mainToolBar")) + pm = /*US d->m_instance->iconLoader()*/ KGlobal::iconLoader()->loadIcon( icon, KIcon::MainToolbar, + d->m_iconSize ); + else + pm = /*US d->m_instance->iconLoader()*/ KGlobal::iconLoader()->loadIcon( icon, KIcon::Toolbar, + d->m_iconSize ); + set.setPixmap( pm, QIconSet::Automatic, QIconSet::Disabled ); + QToolButton::setIconSet( set ); +} + +QPopupMenu *KToolBarButton::popup() +{ + // obsolete + // KDE4: remove me + return QToolButton::popup(); +} + +void KToolBarButton::setPopup(QPopupMenu *p, bool) +{ + QToolButton::setPopup(p); + QToolButton::setPopupDelay(1); +} + + +void KToolBarButton::setDelayedPopup (QPopupMenu *p, bool) +{ + QToolButton::setPopup(p); +//US QToolButton::setPopupDelay(QApplication::startDragTime()); +} + +void KToolBarButton::leaveEvent(QEvent *) +{ + if( d->m_isRaised || d->m_isActive ) + { + d->m_isRaised = false; + d->m_isActive = false; + repaint(false); + } + + emit highlighted(d->m_id, false); +} + +void KToolBarButton::enterEvent(QEvent *) +{ + if (d->m_highlight) + { + if (isEnabled()) + { + d->m_isActive = true; + if (!isToggleButton()) + d->m_isRaised = true; + } + else + { + d->m_isRaised = false; + d->m_isActive = false; + } + + repaint(false); + } + emit highlighted(d->m_id, true); +} + +bool KToolBarButton::eventFilter(QObject *o, QEvent *ev) +{ + if ((KToolBarButton *)o == this) + { + + // Popup the menu when the left mousebutton is pressed and the mouse + // is moved by a small distance. + if (QToolButton::popup()) + { + if (ev->type() == QEvent::MouseButtonPress) + { + QMouseEvent* mev = static_cast<QMouseEvent*>(ev); + d->m_mousePressPos = mev->pos(); + } + else if (ev->type() == QEvent::MouseMove) + { + QMouseEvent* mev = static_cast<QMouseEvent*>(ev); + if ((mev->pos() - d->m_mousePressPos).manhattanLength() +//US > KGlobalSettings::dndEventDelay()) + > 5 ) + { +//US openPopup(); + return true; + } + } + } + + if ((ev->type() == QEvent::MouseButtonPress || + ev->type() == QEvent::MouseButtonRelease || + ev->type() == QEvent::MouseButtonDblClick) && d->m_isRadio && isOn()) + return true; + + // From Kai-Uwe Sattler <kus@iti.CS.Uni-Magdeburg.De> + if (ev->type() == QEvent::MouseButtonDblClick) + { + emit doubleClicked(d->m_id); + return true; + } + } + + return QToolButton::eventFilter(o, ev); +} + +void KToolBarButton::drawButton( QPainter *_painter ) +{ +#ifdef DESKTOP_VERSION + QStyle::SFlags flags = QStyle::Style_Default; + QStyle::SCFlags active = QStyle::SC_None; + + if (isDown()) { + flags |= QStyle::Style_Down; + active |= QStyle::SC_ToolButton; + } + if (isEnabled()) flags |= QStyle::Style_Enabled; + if (isOn()) flags |= QStyle::Style_On; + if (isEnabled() && d->m_isRaised) flags |= QStyle::Style_Raised; + if (hasFocus()) flags |= QStyle::Style_HasFocus; + + // Draw a styled toolbutton + style().drawComplexControl(QStyle::CC_ToolButton, _painter, this, rect(), + colorGroup(), flags, QStyle::SC_ToolButton, active, QStyleOption()); + +#else + style().drawToolButton(_painter, rect().x(), rect().y(), rect().width(), rect().height(), colorGroup()); +#endif + int dx, dy; + QFont tmp_font(KGlobalSettings::toolBarFont()); + QFontMetrics fm(tmp_font); + QRect textRect; + int textFlags = 0; + + if (d->m_iconText == KToolBar::IconOnly) // icon only + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = ( width() - pixmap.width() ) / 2; + dy = ( height() - pixmap.height() ) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + } + else if (d->m_iconText == KToolBar::IconTextRight) // icon and text (if any) + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = 4; + dy = ( height() - pixmap.height() ) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + + if (!textLabel().isNull()) + { + textFlags = AlignVCenter|AlignLeft; + if (!pixmap.isNull()) + dx = 4 + pixmap.width() + 2; + else + dx = 4; + dy = 0; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect(dx, dy, width()-dx, height()); + } + } + else if (d->m_iconText == KToolBar::TextOnly) + { + if (!textLabel().isNull()) + { + textFlags = AlignVCenter|AlignLeft; + dx = (width() - fm.width(textLabel())) / 2; + dy = (height() - fm.lineSpacing()) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() ); + } + } + else if (d->m_iconText == KToolBar::IconTextBottom) + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = (width() - pixmap.width()) / 2; + dy = (height() - fm.lineSpacing() - pixmap.height()) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + + if (!textLabel().isNull()) + { + textFlags = AlignBottom|AlignHCenter; + dx = (width() - fm.width(textLabel())) / 2; + dy = height() - fm.lineSpacing() - 4; + + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() ); + } + } + + // Draw the text at the position given by textRect, and using textFlags + if (!textLabel().isNull() && !textRect.isNull()) + { + _painter->setFont(KGlobalSettings::toolBarFont()); + if (!isEnabled()) + _painter->setPen(palette().disabled().dark()); + else if(d->m_isRaised) + _painter->setPen(KGlobalSettings::toolBarHighlightColor()); + else + _painter->setPen( colorGroup().buttonText() ); + _painter->drawText(textRect, textFlags, textLabel()); + } + + if (QToolButton::popup()) + { +#ifdef DESKTOP_VERSION + QStyle::SFlags arrowFlags = QStyle::Style_Default; + + if (isDown()) arrowFlags |= QStyle::Style_Down; + if (isEnabled()) arrowFlags |= QStyle::Style_Enabled; + + style().drawPrimitive(QStyle::PE_ArrowDown, _painter, + QRect(width()-7, height()-7, 7, 7), colorGroup(), + arrowFlags, QStyleOption() ); +#else + style().drawArrow(_painter, Qt::DownArrow, isDown(), + width()-7, height()-7, 7, 7, colorGroup(), isEnabled() ); +#endif + + } +} + +void KToolBarButton::paletteChange(const QPalette &) +{ + if(!d->m_isSeparator) + { + modeChange(); + repaint(false); // no need to delete it first therefore only false + } +} + +void KToolBarButton::showMenu() +{ + // obsolete + // KDE4: remove me +} + +void KToolBarButton::slotDelayTimeout() +{ + // obsolete + // KDE4: remove me +} + +void KToolBarButton::slotClicked() +{ + emit clicked( d->m_id ); +} + +void KToolBarButton::slotPressed() +{ + emit pressed( d->m_id ); +} + +void KToolBarButton::slotReleased() +{ + emit released( d->m_id ); +} + +void KToolBarButton::slotToggled() +{ + emit toggled( d->m_id ); +} + +void KToolBarButton::setNoStyle(bool no_style) +{ + d->m_noStyle = no_style; + + modeChange(); + d->m_iconText = KToolBar::IconTextRight; + repaint(false); +} + +void KToolBarButton::setRadio (bool f) +{ + if ( d ) + d->m_isRadio = f; +} + +void KToolBarButton::on(bool flag) +{ + if(isToggleButton() == true) + setOn(flag); + else + { + setDown(flag); + leaveEvent((QEvent *) 0); + } + repaint(); +} + +void KToolBarButton::toggle() +{ + setOn(!isOn()); + repaint(); +} + +void KToolBarButton::setToggle(bool flag) +{ + setToggleButton(flag); + if (flag == true) + connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); + else + disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); +} + +QSize KToolBarButton::sizeHint() const +{ + return d->size; +} + +QSize KToolBarButton::minimumSizeHint() const +{ + return d->size; +} + +QSize KToolBarButton::minimumSize() const +{ + return d->size; +} + +bool KToolBarButton::isRaised() const +{ + return d->m_isRaised; +} + +bool KToolBarButton::isActive() const +{ + return d->m_isActive; +} + +int KToolBarButton::iconTextMode() const +{ + return static_cast<int>( d->m_iconText ); +} + +int KToolBarButton::id() const +{ + return d->m_id; +} + +// KToolBarButtonList +KToolBarButtonList::KToolBarButtonList() +{ + setAutoDelete(false); +} + +void KToolBarButton::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ktoolbarbutton.moc" diff --git a/microkde/kdeui/ktoolbarbutton.h b/microkde/kdeui/ktoolbarbutton.h new file mode 100644 index 0000000..9aaa13c --- a/dev/null +++ b/microkde/kdeui/ktoolbarbutton.h @@ -0,0 +1,313 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 2000 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ +#ifndef _KTOOLBARBUTTON_H +#define _KTOOLBARBUTTON_H + +#include <qpixmap.h> +#include <qtoolbutton.h> +#include <qintdict.h> +#include <qstring.h> +#include <kglobal.h> + +class KToolBar; +class KToolBarButtonPrivate; +//USclass KInstance; +class QEvent; +class QPopupMenu; +class QPainter; + +/** + * A toolbar button. This is used internally by @ref KToolBar, use the + * KToolBar methods instead. + * @internal + */ +class KToolBarButton : public QToolButton +{ + Q_OBJECT + +public: + /** + * Construct a button with an icon loaded by the button itself. + * This will trust the button to load the correct icon with the + * correct size. + * + * @param icon Name of icon to load (may be absolute or relative) + * @param id Id of this button + * @param parent This button's parent + * @param name This button's internal name + * @param txt This button's text (in a tooltip or otherwise) + */ + KToolBarButton(const QString& icon, int id, QWidget *parent, + const char *name=0L, const QString &txt=QString::null/*US, + KInstance *_instance = KGlobal::instance()*/); + + /** + * Construct a button with an existing pixmap. It is not + * recommended that you use this as the internal icon loading code + * will almost always get it "right". + * + * @param icon Name of icon to load (may be absolute or relative) + * @param id Id of this button + * @param parent This button's parent + * @param name This button's internal name + * @param txt This button's text (in a tooltip or otherwise) + */ + KToolBarButton(const QPixmap& pixmap, int id, QWidget *parent, + const char *name=0L, const QString &txt=QString::null); + + /** + * Construct a separator button + * + * @param parent This button's parent + * @param name This button's internal name + */ + KToolBarButton(QWidget *parent=0L, const char *name=0L); + + /** + * Standard destructor + */ + ~KToolBarButton(); + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSize minimumSize() const; + +#ifndef KDE_NO_COMPAT + /** + * @deprecated + * Set the pixmap directly for this button. This pixmap should be + * the active one... the dimmed and disabled pixmaps are constructed + * based on this one. However, don't use this function unless you + * are positive that you don't want to use @ref setIcon. + * + * @param pixmap The active pixmap + */ + // this one is from QButton, so #ifdef-ing it out doesn't break BC + virtual void setPixmap(const QPixmap &pixmap); + + /** + * @deprecated + * Force the button to use this pixmap as the default one rather + * then generating it using effects. + * + * @param pixmap The pixmap to use as the default (normal) one + */ + void setDefaultPixmap(const QPixmap& pixmap); + + /** + * @deprecated + * Force the button to use this pixmap when disabled one rather then + * generating it using effects. + * + * @param pixmap The pixmap to use when disabled + */ + void setDisabledPixmap(const QPixmap& pixmap); +#endif + + /** + * Set the text for this button. The text will be either used as a + * tooltip (IconOnly) or will be along side the icon + * + * @param text The button (or tooltip) text + */ + virtual void setText(const QString &text); + + /** + * Set the icon for this button. The icon will be loaded internally + * with the correct size. This function is preferred over @ref setIconSet + * + * @param icon The name of the icon + */ + virtual void setIcon(const QString &icon); + + /// @since 3.1 + virtual void setIcon( const QPixmap &pixmap ) + { QToolButton::setIcon( pixmap ); } + + /** + * Set the pixmaps for this toolbar button from a QIconSet. + * If you call this you don't need to call any of the other methods + * that set icons or pixmaps. + * @param iconset The iconset to use + */ + virtual void setIconSet( const QIconSet &iconset ); + +#ifndef KDE_NO_COMPAT + /** + * @deprecated + * Set the active icon for this button. The pixmap itself is loaded + * internally based on the icon size... .. the disabled and default + * pixmaps, however will only be constructed if @ref #generate is + * true. This function is preferred over @ref setPixmap + * + * @param icon The name of the active icon + * @param generate If true, then the other icons are automagically + * generated from this one + */ + void setIcon(const QString &icon, bool /*generate*/ ) { setIcon( icon ); } + + /** + * @deprecated + * Force the button to use this icon as the default one rather + * then generating it using effects. + * + * @param icon The icon to use as the default (normal) one + */ + void setDefaultIcon(const QString& icon); + + /** + * @deprecated + * Force the button to use this icon when disabled one rather then + * generating it using effects. + * + * @param icon The icon to use when disabled + */ + void setDisabledIcon(const QString& icon); +#endif + + /** + * Turn this button on or off + * + * @param flag true or false + */ + void on(bool flag = true); + + /** + * Toggle this button + */ + void toggle(); + + /** + * Turn this button into a toggle button or disable the toggle + * aspects of it. This does not toggle the button itself. + * Use @ref toggle() for that. + * + * @param toggle true or false + */ + void setToggle(bool toggle = true); + + /** + * Return a pointer to this button's popup menu (if it exists) + */ + QPopupMenu *popup(); + + /** + * Returns the button's id. + * @since 3.2 + */ + int id() const; + + /** + * Give this button a popup menu. There will not be a delay when + * you press the button. Use @ref setDelayedPopup if you want that + * behavior. + * + * @param p The new popup menu + */ + void setPopup (QPopupMenu *p, bool unused = false); + + /** + * Gives this button a delayed popup menu. + * + * This function allows you to add a delayed popup menu to the button. + * The popup menu is then only displayed when the button is pressed and + * held down for about half a second. + * + * @param p the new popup menu + */ + void setDelayedPopup(QPopupMenu *p, bool unused = false); + + /** + * Turn this button into a radio button + * + * @param f true or false + */ + void setRadio(bool f = true); + + /** + * Toolbar buttons naturally will assume the global styles + * concerning icons, icons sizes, etc. You can use this function to + * explicitely turn this off, if you like. + * + * @param no_style Will disable styles if true + */ + void setNoStyle(bool no_style = true); + +signals: + void clicked(int); + void doubleClicked(int); + void pressed(int); + void released(int); + void toggled(int); + void highlighted(int, bool); + +public slots: + /** + * This slot should be called whenever the toolbar mode has + * potentially changed. This includes such events as text changing, + * orientation changing, etc. + */ + void modeChange(); + virtual void setTextLabel(const QString&, bool tipToo); + +protected: + void paletteChange(const QPalette &); + void leaveEvent(QEvent *e); + void enterEvent(QEvent *e); + void drawButton(QPainter *p); + bool eventFilter (QObject *o, QEvent *e); + void showMenu(); + + /// @since 3.1 + bool isRaised() const; + /// @since 3.1 + bool isActive() const; + /// @since 3.1 + int iconTextMode() const; + +protected slots: + void slotClicked(); + void slotPressed(); + void slotReleased(); + void slotToggled(); + void slotDelayTimeout(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KToolBarButtonPrivate *d; +}; + +/** +* List of @ref KToolBarButton objects. +* @internal +* @version $Id$ +*/ +class KToolBarButtonList : public QIntDict<KToolBarButton> +{ +public: + KToolBarButtonList(); + ~KToolBarButtonList() {} +}; + +#endif diff --git a/microkde/kdeui/ktoolbarhandler.cpp b/microkde/kdeui/ktoolbarhandler.cpp new file mode 100644 index 0000000..7b97233 --- a/dev/null +++ b/microkde/kdeui/ktoolbarhandler.cpp @@ -0,0 +1,253 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "ktoolbarhandler.h" + +#include <qpopupmenu.h> +#include <kapplication.h> +#include <ktoolbar.h> +#include <kmainwindow.h> +#include <klocale.h> +#include <kaction.h> +#include <assert.h> + +namespace +{ + const char *actionListName = "show_menu_and_toolbar_actionlist"; + + const char *guiDescription = "" + "<!DOCTYPE kpartgui><kpartgui name=\"StandardToolBarMenuHandler\">" + "<MenuBar>" + " <Menu name=\"settings\">" + " <ActionList name=\"%1\" />" + " </Menu>" + "</MenuBar>" + "</kpartgui>"; + + const char *resourceFileName = "barhandler.rc"; + + class BarActionBuilder + { + public: + BarActionBuilder( KActionCollection *actionCollection, KMainWindow *mainWindow, QPtrList<KToolBar> &oldToolBarList ) + : m_actionCollection( actionCollection ), m_mainWindow( mainWindow ), m_needsRebuild( false ) + { +/*US + QPtrList<QDockWindow> dockWindows = m_mainWindow->dockWindows(); + QPtrListIterator<QDockWindow> dockWindowIt( dockWindows ); + for ( ; dockWindowIt.current(); ++dockWindowIt ) { + +//US KToolBar *toolBar = dynamic_cast<KToolBar *>( dockWindowIt.current() ); + KToolBar *toolBar = (KToolBar *)( dockWindowIt.current() ); + if ( !toolBar ) + continue; + + if ( oldToolBarList.findRef( toolBar ) == -1 ) + m_needsRebuild = true; + + m_toolBars.append( toolBar ); + } +*/ + if ( !m_needsRebuild ) + m_needsRebuild = ( oldToolBarList.count() != m_toolBars.count() ); + + } + + bool needsRebuild() const { return m_needsRebuild; } + + QPtrList<KAction> create() + { + if ( !m_needsRebuild ) + return QPtrList<KAction>(); + + QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + for ( ; toolBarIt.current(); ++toolBarIt ) + handleToolBar( toolBarIt.current() ); + + QPtrList<KAction> actions; + + if ( m_toolBarActions.count() == 0 ) + return actions; + + if ( m_toolBarActions.count() == 1 ) { + m_toolBarActions.getFirst()->setText( i18n( "Show Toolbar" ) ); + return m_toolBarActions; + } + + KActionMenu *menuAction = new KActionMenu( i18n( "Toolbars" ), m_actionCollection, "toolbars_submenu_action" ); + + QPtrListIterator<KAction> actionIt( m_toolBarActions ); + for ( ; actionIt.current(); ++actionIt ) + menuAction->insert( actionIt.current() ); + + actions.append( menuAction ); + return actions; + } + + const QPtrList<KToolBar> &toolBars() const { return m_toolBars; } + + private: + void handleToolBar( KToolBar *toolBar ) + { + KAction *action = new KToggleToolBarAction( toolBar, + i18n( "Show %1" ).arg( toolBar->label() ), + m_actionCollection, + toolBar->name() ); + + m_toolBarActions.append( action ); + } + + KActionCollection *m_actionCollection; + KMainWindow *m_mainWindow; + + QPtrList<KToolBar> m_toolBars; + QPtrList<KAction> m_toolBarActions; + + bool m_needsRebuild : 1; + }; +} + +using namespace KDEPrivate; + +ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, const char *name ) + : QObject( mainWindow, name ), KXMLGUIClient( mainWindow ) +{ + init( mainWindow ); +} + +ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name ) + : QObject( parent, name ), KXMLGUIClient( mainWindow ) +{ + init( mainWindow ); +} + +ToolBarHandler::~ToolBarHandler() +{ + m_actions.setAutoDelete( true ); + m_actions.clear(); +} + +KAction *ToolBarHandler::toolBarMenuAction() +{ + assert( m_actions.count() == 1 ); + return m_actions.getFirst(); +} + +void ToolBarHandler::setupActions() +{ +//US if ( !factory() || !m_mainWindow ) + if ( !m_mainWindow ) + return; + + BarActionBuilder builder( actionCollection(), m_mainWindow, m_toolBars ); + + if ( !builder.needsRebuild() ) + return; + + unplugActionList( actionListName ); + + m_actions.setAutoDelete( true ); + + m_actions.clear(); + m_actions.setAutoDelete( false ); + + m_actions = builder.create(); + + /* + for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + toolBarIt.current(); ++toolBarIt ) + toolBarIt.current()->disconnect( this ); + */ + + m_toolBars = builder.toolBars(); + + /* + for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + toolBarIt.current(); ++toolBarIt ) + connect( toolBarIt.current(), SIGNAL( destroyed() ), + this, SLOT( setupActions() ) ); + */ + +//US if (kapp && kapp->authorizeKAction("options_show_toolbar")) + plugActionList( actionListName, m_actions ); + + connectToActionContainers(); +} + +/*US +void ToolBarHandler::clientAdded( KXMLGUIClient *client ) +{ + if ( client == this ) + setupActions(); +} +*/ + +void ToolBarHandler::init( KMainWindow *mainWindow ) +{ + d = 0; + m_mainWindow = mainWindow; + +/*US + connect( m_mainWindow->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ), + this, SLOT( clientAdded( KXMLGUIClient * ) ) ); +*/ + /* re-use an existing resource file if it exists. can happen if the user launches the + * toolbar editor */ + /* + setXMLFile( resourceFileName ); + */ +/*US + if ( domDocument().documentElement().isNull() ) { + + QString completeDescription = QString::fromLatin1( guiDescription ) + .arg( actionListName ); + + setXML( completeDescription, false*/ /*merge*/ /*); + } +*/ +} + +void ToolBarHandler::connectToActionContainers() +{ + QPtrListIterator<KAction> actionIt( m_actions ); + for ( ; actionIt.current(); ++actionIt ) + connectToActionContainer( actionIt.current() ); +} + +void ToolBarHandler::connectToActionContainer( KAction *action ) +{ + uint containerCount = action->containerCount(); + for ( uint i = 0; i < containerCount; ++i ) + connectToActionContainer( action->container( i ) ); +} + +void ToolBarHandler::connectToActionContainer( QWidget *container ) +{ +//US QPopupMenu *popupMenu = dynamic_cast<QPopupMenu *>( container ); + QPopupMenu *popupMenu = (QPopupMenu *)( container ); + if ( !popupMenu ) + return; + + connect( popupMenu, SIGNAL( aboutToShow() ), + this, SLOT( setupActions() ) ); +} + +//US #include "ktoolbarhandler.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/microkde/kdeui/ktoolbarhandler.h b/microkde/kdeui/ktoolbarhandler.h new file mode 100644 index 0000000..a1340ae --- a/dev/null +++ b/microkde/kdeui/ktoolbarhandler.h @@ -0,0 +1,70 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KBARHANDLER_H +#define KBARHANDLER_H + +#include <qobject.h> +#include <qguardedptr.h> +#include <qptrlist.h> +#include <kxmlguiclient.h> +#include <kaction.h> + +class KMainWindow; +class KToolBar; + +namespace KDEPrivate +{ + +/// @since 3.1 +class ToolBarHandler : public QObject, public KXMLGUIClient +{ + Q_OBJECT +public: + ToolBarHandler( KMainWindow *mainWindow, const char *name = 0 ); + ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name = 0 ); + virtual ~ToolBarHandler(); + + KAction *toolBarMenuAction(); + +public slots: + void setupActions(); + +private slots: +//US void clientAdded( KXMLGUIClient *client ); + +private: + void init( KMainWindow *mainWindow ); + void connectToActionContainers(); + void connectToActionContainer( KAction *action ); + void connectToActionContainer( QWidget *container ); + + struct Data; + Data *d; + + QGuardedPtr<KMainWindow> m_mainWindow; + QPtrList<KAction> m_actions; + QPtrList<KToolBar> m_toolBars; +}; + +} // namespace KDEPrivate + +#endif // KBARHANDLER_H + +/* vim: et sw=4 ts=4 + */ diff --git a/microkde/kdeui/kxmlguiclient.cpp b/microkde/kdeui/kxmlguiclient.cpp new file mode 100644 index 0000000..073e30b --- a/dev/null +++ b/microkde/kdeui/kxmlguiclient.cpp @@ -0,0 +1,958 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000 Kurt Granroth <granroth@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kxmlguiclient.h" + +/*US +#include "kxmlguifactory.h" +#include "kxmlguibuilder.h" +*/ + +/*US +#include <qdir.h> +#include <qfile.h> +#include <qdom.h> +#include <qtextstream.h> +#include <qregexp.h> +*/ + +//US #include <kinstance.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <kaction.h> +#include <kapplication.h> + +#include <assert.h> + +class KXMLGUIClientPrivate +{ +public: + KXMLGUIClientPrivate() + { +//US m_instance = KGlobal::instance(); +//US m_factory = 0L; + m_parent = 0L; +//US m_builder = 0L; + m_actionCollection = 0; + } + ~KXMLGUIClientPrivate() + { + } + +//US KInstance *m_instance; + +//US QDomDocument m_doc; + KActionCollection *m_actionCollection; +//US QDomDocument m_buildDocument; +//US KXMLGUIFactory *m_factory; + KXMLGUIClient *m_parent; + //QPtrList<KXMLGUIClient> m_supers; + QPtrList<KXMLGUIClient> m_children; +//US KXMLGUIBuilder *m_builder; +//US QString m_xmlFile; +//US QString m_localXMLFile; +}; + +KXMLGUIClient::KXMLGUIClient() +{ + d = new KXMLGUIClientPrivate; +} + +KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent ) +{ + d = new KXMLGUIClientPrivate; + parent->insertChildClient( this ); +} + +KXMLGUIClient::~KXMLGUIClient() +{ + if ( d->m_parent ) + d->m_parent->removeChildClient( this ); + + QPtrListIterator<KXMLGUIClient> it( d->m_children ); + for ( ; it.current(); ++it ) { + assert( it.current()->d->m_parent == this ); + it.current()->d->m_parent = 0; + } + + delete d->m_actionCollection; + delete d; +} + +KAction *KXMLGUIClient::action( const char *name ) const +{ + KAction* act = actionCollection()->action( name ); + if ( !act ) { + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) { + act = childIt.current()->actionCollection()->action( name ); + if ( act ) + break; + } + } + return act; +} + +KActionCollection *KXMLGUIClient::actionCollection() const +{ + if ( !d->m_actionCollection ) + d->m_actionCollection = new KActionCollection( 0, 0, + "KXMLGUILClient-KActionCollection" ); + return d->m_actionCollection; +} + +/*US +KAction *KXMLGUIClient::action( const QDomElement &element ) const +{ + static const QString &attrName = KGlobal::staticQString( "name" ); + return actionCollection()->action( element.attribute( attrName ).latin1() ); +} + +KInstance *KXMLGUIClient::instance() const +{ + return d->m_instance; +} + +QDomDocument KXMLGUIClient::domDocument() const +{ + return d->m_doc; +} + +QString KXMLGUIClient::xmlFile() const +{ + return d->m_xmlFile; +} + +QString KXMLGUIClient::localXMLFile() const +{ + if ( !d->m_localXMLFile.isEmpty() ) + return d->m_localXMLFile; + + if ( d->m_xmlFile[0] == '/' ) + return QString::null; // can't save anything here + + return locateLocal( "data", QString::fromLatin1( instance()->instanceName() + '/' ) + d->m_xmlFile ); +} + + +void KXMLGUIClient::reloadXML() +{ + QString file( xmlFile() ); + if ( !file.isEmpty() ) + setXMLFile( file ); +} + +void KXMLGUIClient::setInstance( KInstance *instance ) +{ + d->m_instance = instance; + actionCollection()->setInstance( instance ); + if ( d->m_builder ) + d->m_builder->setBuilderClient( this ); +} + +void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc ) +{ + // store our xml file name + if ( !_file.isNull() ) { + d->m_xmlFile = _file; + actionCollection()->setXMLFile( _file ); + } + + if ( !setXMLDoc ) + return; + + QString file = _file; + if ( file[0] != '/' ) + { + QString doc; + + QString filter = QString::fromLatin1( instance()->instanceName() + '/' ) + _file; + + QStringList allFiles = instance()->dirs()->findAllResources( "data", filter ) + instance()->dirs()->findAllResources( "data", _file ); + + file = findMostRecentXMLFile( allFiles, doc ); + + if ( file.isEmpty() ) + { + // this might or might not be an error. for the time being, + // let's treat this as if it isn't a problem and the user just + // wants the global standards file + setXML( QString::null, true ); + return; + } + else if ( !doc.isEmpty() ) + { + setXML( doc, merge ); + return; + } + } + + QString xml = KXMLGUIFactory::readConfigFile( file ); + setXML( xml, merge ); +} + +void KXMLGUIClient::setLocalXMLFile( const QString &file ) +{ + d->m_localXMLFile = file; +} + +void KXMLGUIClient::setXML( const QString &document, bool merge ) +{ + QDomDocument doc; + doc.setContent( document ); + setDOMDocument( doc, merge ); +} + +void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge ) +{ + if ( merge ) + { + QDomElement base = d->m_doc.documentElement(); + + QDomElement e = document.documentElement(); + KXMLGUIFactory::removeDOMComments( e ); + + // merge our original (global) xml with our new one + mergeXML(base, e, actionCollection()); + + // reassign our pointer as mergeXML might have done something + // strange to it + base = d->m_doc.documentElement(); + + // we want some sort of failsafe.. just in case + if ( base.isNull() ) + d->m_doc = document; + } + else + { + d->m_doc = document; + KXMLGUIFactory::removeDOMComments( d->m_doc ); + } + + setXMLGUIBuildDocument( QDomDocument() ); +} +*/ + +/*US +bool KXMLGUIClient::mergeXML( QDomElement &base, const QDomElement &additive, KActionCollection *actionCollection ) +{ + static const QString &tagAction = KGlobal::staticQString( "Action" ); + static const QString &tagMerge = KGlobal::staticQString( "Merge" ); + static const QString &tagSeparator = KGlobal::staticQString( "Separator" ); + static const QString &attrName = KGlobal::staticQString( "name" ); + static const QString &attrAppend = KGlobal::staticQString( "append" ); + static const QString &attrWeakSeparator = KGlobal::staticQString( "weakSeparator" ); + static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" ); + static const QString &tagText = KGlobal::staticQString( "text" ); + static const QString &attrAlreadyVisited = KGlobal::staticQString( "alreadyVisited" ); + static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" ); + static const QString &attrOne = KGlobal::staticQString( "1" ); + + // there is a possibility that we don't want to merge in the + // additive.. rather, we might want to *replace* the base with the + // additive. this can be for any container.. either at a file wide + // level or a simple container level. we look for the 'noMerge' + // tag, in any event and just replace the old with the new + if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon) + { + base.parentNode().replaceChild(additive, base); + return true; + } + + QString tag; + + QDomElement e = base.firstChild().toElement(); + // iterate over all elements in the container (of the global DOM tree) + while ( !e.isNull() ) + { + tag = e.tagName(); + + // if there's an action tag in the global tree and the action is + // not implemented, then we remove the element + if ( tag == tagAction ) + { + QCString name = e.attribute( attrName ).utf8(); // WABA + if ( !actionCollection->action( name ) || + (kapp && !kapp->authorizeKAction(name))) + { + // remove this child as we aren't using it + QDomElement oldChild = e; + e = e.nextSibling().toElement(); + base.removeChild( oldChild ); + continue; + } + } + + // if there's a separator defined in the global tree, then add an + // attribute, specifying that this is a "weak" separator + else if ( tag == tagSeparator ) + { + e.setAttribute( attrWeakSeparator, (uint)1 ); + + // okay, hack time. if the last item was a weak separator OR + // this is the first item in a container, then we nuke the + // current one + QDomElement prev = e.previousSibling().toElement(); + if ( prev.isNull() || + ( prev.tagName() == tagSeparator && !prev.attribute( attrWeakSeparator ).isNull() ) || + ( prev.tagName() == tagText ) ) + { + // the previous element was a weak separator or didn't exist + QDomElement oldChild = e; + e = e.nextSibling().toElement(); + base.removeChild( oldChild ); + continue; + } + } + + // the MergeLocal tag lets us specify where non-standard elements + // of the local tree shall be merged in. After inserting the + // elements we delete this element + else if ( tag == tagMergeLocal ) + { + QDomElement currElement = e; + + // switch our iterator "e" to the next sibling, so that we don't + // process the local tree's inserted items! + e = e.nextSibling().toElement(); + + QDomElement it = additive.firstChild().toElement(); + while ( !it.isNull() ) + { + QDomElement newChild = it; + + it = it.nextSibling().toElement(); + + if ( newChild.tagName() == tagText ) + continue; + + if ( newChild.attribute( attrAlreadyVisited ) == attrOne ) + continue; + + QString itAppend( newChild.attribute( attrAppend ) ); + QString elemName( currElement.attribute( attrName ) ); + + if ( ( itAppend.isNull() && elemName.isEmpty() ) || + ( itAppend == elemName ) ) + { + // first, see if this new element matches a standard one in + // the global file. if it does, then we skip it as it will + // be merged in, later + QDomElement matchingElement = findMatchingElement( newChild, base ); + if ( matchingElement.isNull() || newChild.tagName() == tagSeparator ) + base.insertBefore( newChild, currElement ); + } + } + + base.removeChild( currElement ); + continue; + } + + // in this last case we check for a separator tag and, if not, we + // can be sure that its a container --> proceed with child nodes + // recursively and delete the just proceeded container item in + // case its empty (if the recursive call returns true) + else if ( tag != tagMerge ) + { + // handle the text tag + if ( tag == tagText ) + { + e = e.nextSibling().toElement(); + continue; + } + + QDomElement matchingElement = findMatchingElement( e, additive ); + + QDomElement currElement = e; + e = e.nextSibling().toElement(); + + if ( !matchingElement.isNull() ) + { + matchingElement.setAttribute( attrAlreadyVisited, (uint)1 ); + + if ( mergeXML( currElement, matchingElement, actionCollection ) ) + { + base.removeChild( currElement ); + continue; + } + + // Merge attributes + QDomNamedNodeMap attribs = matchingElement.attributes(); + for(uint i = 0; i < attribs.count(); i++) + { + QDomNode node = attribs.item(i); + currElement.setAttribute(node.nodeName(), node.nodeValue()); + } + + continue; + } + else + { + // this is an important case here! We reach this point if the + // "local" tree does not contain a container definition for + // this container. However we have to call mergeXML recursively + // and make it check if there are actions implemented for this + // container. *If* none, then we can remove this container now + if ( mergeXML( currElement, QDomElement(), actionCollection ) ) + base.removeChild( currElement ); + continue; + } + } + + //I think this can be removed ;-) + e = e.nextSibling().toElement(); + } + + //here we append all child elements which were not inserted + //previously via the LocalMerge tag + e = additive.firstChild().toElement(); + while ( !e.isNull() ) + { + QDomElement matchingElement = findMatchingElement( e, base ); + + if ( matchingElement.isNull() ) + { + QDomElement newChild = e; + e = e.nextSibling().toElement(); + base.appendChild( newChild ); + } + else + e = e.nextSibling().toElement(); + } + + // do one quick check to make sure that the last element was not + // a weak separator + QDomElement last = base.lastChild().toElement(); + if ( (last.tagName() == tagSeparator) && (!last.attribute( attrWeakSeparator ).isNull()) ) + { + base.removeChild( base.lastChild() ); + } + + // now we check if we are empty (in which case we return "true", to + // indicate the caller that it can delete "us" (the base element + // argument of "this" call) + bool deleteMe = true; + e = base.firstChild().toElement(); + for ( ; !e.isNull(); e = e.nextSibling().toElement() ) + { + tag = e.tagName(); + + if ( tag == tagAction ) + { + // if base contains an implemented action, then we must not get + // deleted (note that the actionCollection contains both, + // "global" and "local" actions + if ( actionCollection->action( e.attribute( attrName ).utf8() ) ) + { + deleteMe = false; + break; + } + } + else if ( tag == tagSeparator ) + { + // if we have a separator which has *not* the weak attribute + // set, then it must be owned by the "local" tree in which case + // we must not get deleted either + QString weakAttr = e.attribute( attrWeakSeparator ); + if ( weakAttr.isEmpty() || weakAttr.toInt() != 1 ) + { + deleteMe = false; + break; + } + } + + // in case of a merge tag we have unlimited lives, too ;-) + else if ( tag == tagMerge ) + { +// deleteMe = false; +// break; + continue; + } + + // a text tag is NOT enough to spare this container + else if ( tag == tagText ) + { + continue; + } + + // what's left are non-empty containers! *don't* delete us in this + // case (at this position we can be *sure* that the container is + // *not* empty, as the recursive call for it was in the first loop + // which deleted the element in case the call returned "true" + else + { + deleteMe = false; + break; + } + } + + return deleteMe; +} + +QDomElement KXMLGUIClient::findMatchingElement( const QDomElement &base, const QDomElement &additive ) +{ + static const QString &tagAction = KGlobal::staticQString( "Action" ); + static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" ); + static const QString &attrName = KGlobal::staticQString( "name" ); + + QDomElement e = additive.firstChild().toElement(); + for ( ; !e.isNull(); e = e.nextSibling().toElement() ) + { + // skip all action and merge tags as we will never use them + if ( ( e.tagName() == tagAction ) || ( e.tagName() == tagMergeLocal ) ) + { + continue; + } + + // now see if our tags are equivalent + if ( ( e.tagName() == base.tagName() ) && + ( e.attribute( attrName ) == base.attribute( attrName ) ) ) + { + return e; + } + } + + // nope, return a (now) null element + return e; +} + +void KXMLGUIClient::conserveMemory() +{ + d->m_doc = QDomDocument(); + d->m_buildDocument = QDomDocument(); +} + +void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc ) +{ + d->m_buildDocument = doc; +} + +QDomDocument KXMLGUIClient::xmlguiBuildDocument() const +{ + return d->m_buildDocument; +} +*/ + +/*US +void KXMLGUIClient::setFactory( KXMLGUIFactory *factory ) +{ + d->m_factory = factory; +} + +KXMLGUIFactory *KXMLGUIClient::factory() const +{ + return d->m_factory; +} +*/ +KXMLGUIClient *KXMLGUIClient::parentClient() const +{ + return d->m_parent; +} + +void KXMLGUIClient::insertChildClient( KXMLGUIClient *child ) +{ + if ( child->d->m_parent ) + child->d->m_parent->removeChildClient( child ); + d->m_children.append( child ); + child->d->m_parent = this; +} + +void KXMLGUIClient::removeChildClient( KXMLGUIClient *child ) +{ + assert( d->m_children.containsRef( child ) ); + d->m_children.removeRef( child ); + child->d->m_parent = 0; +} + +/*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super ) +{ + if ( d->m_supers.contains( super ) ) + return false; + d->m_supers.append( super ); + return true; +}*/ + +const QPtrList<KXMLGUIClient> *KXMLGUIClient::childClients() +{ + return &d->m_children; +} +/*US +void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder ) +{ + d->m_builder = builder; + if ( builder ) + builder->setBuilderInstance( instance() ); +} + +KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const +{ + return d->m_builder; +} +*/ + +void KXMLGUIClient::plugActionList( const QString &name, const QPtrList<KAction> &actionList ) +{ +/*US + if ( !d->m_factory ) + return; + + d->m_factory->plugActionList( this, name, actionList ); +*/ +} + +void KXMLGUIClient::unplugActionList( const QString &name ) +{ +/*US + if ( !d->m_factory ) + return; + + d->m_factory->unplugActionList( this, name ); +*/ +} + +/*US +QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc ) +{ + + QValueList<DocStruct> allDocuments; + + QStringList::ConstIterator it = files.begin(); + QStringList::ConstIterator end = files.end(); + for (; it != end; ++it ) + { + //kdDebug() << "KXMLGUIClient::findMostRecentXMLFile " << *it << endl; + QString data = KXMLGUIFactory::readConfigFile( *it ); + DocStruct d; + d.file = *it; + d.data = data; + allDocuments.append( d ); + } + + QValueList<DocStruct>::Iterator best = allDocuments.end(); + uint bestVersion = 0; + + QValueList<DocStruct>::Iterator docIt = allDocuments.begin(); + QValueList<DocStruct>::Iterator docEnd = allDocuments.end(); + for (; docIt != docEnd; ++docIt ) + { + QString versionStr = findVersionNumber( (*docIt).data ); + if ( versionStr.isEmpty() ) + continue; + + bool ok = false; + uint version = versionStr.toUInt( &ok ); + if ( !ok ) + continue; + //kdDebug() << "FOUND VERSION " << version << endl; + + if ( version > bestVersion ) + { + best = docIt; + //kdDebug() << "best version is now " << version << endl; + bestVersion = version; + } + } + + if ( best != docEnd ) + { + if ( best != allDocuments.begin() ) + { + QValueList<DocStruct>::Iterator local = allDocuments.begin(); + + // load the local document and extract the action properties + QDomDocument document; + document.setContent( (*local).data ); + + ActionPropertiesMap properties = extractActionProperties( document ); + + // in case the document has a ActionProperties section + // we must not delete it but copy over the global doc + // to the local and insert the ActionProperties section + if ( !properties.isEmpty() ) + { + // now load the global one with the higher version number + // into memory + document.setContent( (*best).data ); + // and store the properties in there + storeActionProperties( document, properties ); + + (*local).data = document.toString(); + // make sure we pick up the new local doc, when we return later + best = local; + + // write out the new version of the local document + QFile f( (*local).file ); + if ( f.open( IO_WriteOnly ) ) + { + QCString utf8data = (*local).data.utf8(); + f.writeBlock( utf8data.data(), utf8data.length() ); + f.close(); + } + } + else + { + QString f = (*local).file; + QString backup = f + QString::fromLatin1( ".backup" ); + QDir dir; + dir.rename( f, backup ); + } + } + doc = (*best).data; + return (*best).file; + } + else if ( files.count() > 0 ) + { + //kdDebug() << "returning first one..." << endl; + doc = (*allDocuments.begin()).data; + return (*allDocuments.begin()).file; + } + + return QString::null; +} + + + +QString KXMLGUIClient::findVersionNumber( const QString &xml ) +{ + enum { ST_START, ST_AFTER_OPEN, ST_AFTER_GUI, + ST_EXPECT_VERSION, ST_VERSION_NUM} state = ST_START; + for (unsigned int pos = 0; pos < xml.length(); pos++) + { + switch (state) + { + case ST_START: + if (xml[pos] == '<') + state = ST_AFTER_OPEN; + break; + case ST_AFTER_OPEN: + { + //Jump to gui.. + int guipos = xml.find("gui", pos, false); + if (guipos == -1) + return QString::null; //Reject + + pos = guipos + 2; //Position at i, so we're moved ahead to the next character by the ++; + state = ST_AFTER_GUI; + break; + } + case ST_AFTER_GUI: + state = ST_EXPECT_VERSION; + break; + case ST_EXPECT_VERSION: + { + int verpos = xml.find("version=\"", pos, false ); + if (verpos == -1) + return QString::null; //Reject + + pos = verpos + 8; //v = 0, e = +1, r = +2, s = +3 , i = +4, o = +5, n = +6, = = +7, " = + 8 + state = ST_VERSION_NUM; + break; + } + case ST_VERSION_NUM: + { + unsigned int endpos; + for (endpos = pos; endpos < xml.length(); endpos++) + { + if (xml[endpos].unicode() >= '0' && xml[endpos].unicode() <= '9') + continue; //Number.. + if (xml[endpos].unicode() == '"') //End of parameter + break; + else //This shouldn't be here.. + { + endpos = xml.length(); + } + } + + if (endpos != pos && endpos < xml.length() ) + { + QString matchCandidate = xml.mid(pos, endpos - pos); //Don't include " ". + return matchCandidate; + } + + state = ST_EXPECT_VERSION; //Try to match a well-formed version.. + break; + } //case.. + } //switch + } //for + + return QString::null; +} + +KXMLGUIClient::ActionPropertiesMap KXMLGUIClient::extractActionProperties( const QDomDocument &doc ) +{ + ActionPropertiesMap properties; + + QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement(); + + if ( actionPropElement.isNull() ) + return properties; + + QDomNode n = actionPropElement.firstChild(); + for (; !n.isNull(); n = n.nextSibling() ) + { + QDomElement e = n.toElement(); + if ( e.isNull() ) + continue; + + if ( e.tagName().lower() != "action" ) + continue; + + QString actionName = e.attribute( "name" ); + + if ( actionName.isEmpty() ) + continue; + + QMap<QString, QMap<QString, QString> >::Iterator propIt = properties.find( actionName ); + if ( propIt == properties.end() ) + propIt = properties.insert( actionName, QMap<QString, QString>() ); + + QDomNamedNodeMap attributes = e.attributes(); + for ( uint i = 0; i < attributes.length(); ++i ) + { + QDomAttr attr = attributes.item( i ).toAttr(); + + if ( attr.isNull() ) + continue; + + QString name = attr.name(); + + if ( name == "name" || name.isEmpty() ) + continue; + + (*propIt)[ name ] = attr.value(); + } + + } + + return properties; +} + +void KXMLGUIClient::storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties ) +{ + QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement(); + + if ( actionPropElement.isNull() ) + { + actionPropElement = doc.createElement( "ActionProperties" ); + doc.documentElement().appendChild( actionPropElement ); + } + + while ( !actionPropElement.firstChild().isNull() ) + actionPropElement.removeChild( actionPropElement.firstChild() ); + + ActionPropertiesMap::ConstIterator it = properties.begin(); + ActionPropertiesMap::ConstIterator end = properties.end(); + for (; it != end; ++it ) + { + QDomElement action = doc.createElement( "Action" ); + action.setAttribute( "name", it.key() ); + actionPropElement.appendChild( action ); + + QMap<QString, QString> attributes = (*it); + QMap<QString, QString>::ConstIterator attrIt = attributes.begin(); + QMap<QString, QString>::ConstIterator attrEnd = attributes.end(); + for (; attrIt != attrEnd; ++attrIt ) + action.setAttribute( attrIt.key(), attrIt.data() ); + } +} +*/ + +void KXMLGUIClient::addStateActionEnabled(const QString& state, + const QString& action) +{ + StateChange stateChange = getActionsToChangeForState(state); + + stateChange.actionsToEnable.append( action ); + //kdDebug() << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")" << endl; + + m_actionsStateMap.replace( state, stateChange ); +} + + +void KXMLGUIClient::addStateActionDisabled(const QString& state, + const QString& action) +{ + StateChange stateChange = getActionsToChangeForState(state); + + stateChange.actionsToDisable.append( action ); + //kdDebug() << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")" << endl; + + m_actionsStateMap.replace( state, stateChange ); +} + + +KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state) +{ + return m_actionsStateMap[state]; +} + + +void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse) +{ + StateChange stateChange = getActionsToChangeForState(newstate); + + bool setTrue = (reverse == StateNoReverse); + bool setFalse = !setTrue; + + // Enable actions which need to be enabled... + // + for ( QStringList::Iterator it = stateChange.actionsToEnable.begin(); + it != stateChange.actionsToEnable.end(); ++it ) { + + KAction *action = actionCollection()->action((*it).latin1()); + if (action) action->setEnabled(setTrue); + } + + // and disable actions which need to be disabled... + // + for ( QStringList::Iterator it = stateChange.actionsToDisable.begin(); + it != stateChange.actionsToDisable.end(); ++it ) { + + KAction *action = actionCollection()->action((*it).latin1()); + if (action) action->setEnabled(setFalse); + } + +} +/*US +void KXMLGUIClient::beginXMLPlug( QWidget *w ) +{ + actionCollection()->beginXMLPlug( w ); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->beginXMLPlug( w ); +} + +void KXMLGUIClient::endXMLPlug() +{ + actionCollection()->endXMLPlug(); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->endXMLPlug(); +} + +void KXMLGUIClient::prepareXMLUnplug( QWidget * ) +{ + actionCollection()->prepareXMLUnplug(); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->prepareXMLUnplug(); +} +*/ +void KXMLGUIClient::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } diff --git a/microkde/kdeui/kxmlguiclient.h b/microkde/kdeui/kxmlguiclient.h new file mode 100644 index 0000000..cd74c8e --- a/dev/null +++ b/microkde/kdeui/kxmlguiclient.h @@ -0,0 +1,361 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000 Kurt Granroth <granroth@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _KXMLGUICLIENT_H +#define _KXMLGUICLIENT_H + + +//US #include <qdom.h> +#include <qptrlist.h> +#include <qmap.h> +#include <qstringlist.h> + +class QWidget; +class KAction; +class KActionCollection; +class KInstance; + +class KXMLGUIClientPrivate; +class KXMLGUIFactory; +class KXMLGUIBuilder; + +/** + * + * A KXMLGUIClient can be used with @ref KXMLGUIFactory to create a + * GUI from actions and an XML document, and can be dynamically merged + * with other KXMLGUIClients. + */ +class KXMLGUIClient +{ + friend class KEditToolbarWidget; // for setXMLFile(3 args) +public: + /** + * Constructs a KXMLGUIClient which can be used with a + * @ref KXMLGUIFactory to create a GUI from actions and an XML document, and + * which can be dynamically merged with other KXMLGUIClients. + */ + KXMLGUIClient(); + + /** + * Constructs a KXMLGUIClient which can be used with a @ref KXMLGUIFactory + * to create a GUI from actions and an XML document, + * and which can be dynamically merged with other KXMLGUIClients. + * + * This constructor takes an additional @p parent argument, which makes + * the client a child client of the parent. + * + * Child clients are automatically added to the GUI if the parent is added. + * + */ + KXMLGUIClient( KXMLGUIClient *parent ); + + /** + * Destructs the KXMLGUIClient. + */ + virtual ~KXMLGUIClient(); + + /** + * Retrieves an action of the client by name. If not found, it looks in its child clients. + * This method is provided for convenience, as it uses @ref #actionCollection() + * to get the action object. + */ + KAction* action( const char* name ) const; + + /** + * Retrieves an action for a given @ref QDomElement. The default + * implementation uses the "name" attribute to query the action + * object via the other action() method. + */ +//US virtual KAction *action( const QDomElement &element ) const; + + /** + * Retrieves the entire action collection for the GUI client + */ + virtual KActionCollection* actionCollection() const; + + /** + * @return The instance (@ref KInstance) for this part. + */ +//US virtual KInstance *instance() const; + + /** + * @return The parsed XML in a @ref QDomDocument, set by @ref + * setXMLFile() or @ref setXML(). + * This document describes the layout of the GUI. + */ +//US virtual QDomDocument domDocument() const; + + /** + * This will return the name of the XML file as set by @ref #setXMLFile(). + * If @ref #setXML() is used directly, then this will return NULL. + * + * The filename that this returns is obvious for components as each + * component has exactly one XML file. In non-components, however, + * there are usually two: the global file and the local file. This + * function doesn't really care about that, though. It will always + * return the last XML file set. This, in almost all cases, will + * be the local XML file. + * + * @return The name of the XML file or QString::null + */ +//US virtual QString xmlFile() const; + +//US virtual QString localXMLFile() const; + + /** + * @internal + */ +//US void setXMLGUIBuildDocument( const QDomDocument &doc ); + /** + * @internal + */ +//US QDomDocument xmlguiBuildDocument() const; + + /** + * This method is called by the @ref KXMLGUIFactory as soon as the client + * is added to the KXMLGUIFactory's GUI. + */ +//US void setFactory( KXMLGUIFactory *factory ); + /** + * Retrieves a pointer to the @ref KXMLGUIFactory this client is + * associated with (will return 0L if the client's GUI has not been built + * by a KXMLGUIFactory. + */ +//US KXMLGUIFactory *factory() const; + + /** + * KXMLGUIClients can form a simple child/parent object tree. This + * method returns a pointer to the parent client or 0L if it has no + * parent client assigned. + */ + KXMLGUIClient *parentClient() const; + + /** + * Use this method to make a client a child client of another client. + * Usually you don't need to call this method, as it is called + * automatically when using the second constructor, which takes a + * arent argument. + */ + void insertChildClient( KXMLGUIClient *child ); + + /** + * Removes the given @p child from the client's children list. + */ + void removeChildClient( KXMLGUIClient *child ); + + /** + * Retrieves a list of all child clients. + */ + const QPtrList<KXMLGUIClient> *childClients(); + + /** + * A client can have an own @ref KXMLGUIBuilder. + * Use this method to assign your builder instance to the client (so that the + * @ref KXMLGUIFactory can use it when building the client's GUI) + * + * Client specific guibuilders are useful if you want to create + * custom container widgets for your GUI. + */ +//US void setClientBuilder( KXMLGUIBuilder *builder ); + + /** + * Retrieves the client's GUI builder or 0L if no client specific + * builder has been assigned via @ref #setClientBuilder() + */ +//US KXMLGUIBuilder *clientBuilder() const; + + /** + * Forces this client to re-read its XML resource file. This is + * intended to be used when you know that the resource file has + * changed and you will soon be rebuilding the GUI. It has no + * useful effect with non-KParts GUIs, so don't bother using it + * unless your app is component based. + */ +//US void reloadXML(); + + /** + * ActionLists are a way for XMLGUI to support dynamic lists of + * actions. E.g. if you are writing a file manager, and there is a + * menu file whose contents depend on the mimetype of the file that + * is selected, then you can achieve this using ActionLists. It + * works as follows: + * In your xxxui.rc file ( the one that you set in @ref setXMLFile() + * ), you put an <ActionList name="xxx"> tag. E.g. + * \verbatim + * <kpartgui name="xxx_part" version="1"> + * <MenuBar> + * <Menu name="file"> + * ... <!-- some useful actions--> + * <ActionList name="xxx_file_actionlist" /> + * ... <!-- even more useful actions--> + * </Menu> + * ... + * </MenuBar> + * </kpartgui> + * \endverbatim + * + * This tag will get expanded to a list of actions. In the example + * above ( a file manager with a dynamic file menu ), you would call + * \code + * QPtrList<KAction> file_actions; + * for( ... ) + * if( ... ) + * file_actions.append( cool_action ); + * unplugActionList( "xxx_file_actionlist" ); + * plugActionList( "xxx_file_actionlist", file_actions ); + * \endcode + * every time a file is selected, unselected or ... + * + * \note You should not call createGUI() after calling this + * function. In fact, that would remove the newly added + * actionlists again... + * \note Forgetting to call unplugActionList() before + * plugActionList() would leave the previous actions in the + * menu too.. + */ + void plugActionList( const QString &name, const QPtrList<KAction> &actionList ); + + /** + * The complement of \ref plugActionList() ... + */ + void unplugActionList( const QString &name ); + +//US static QString findMostRecentXMLFile( const QStringList &files, QString &doc ); + + void addStateActionEnabled(const QString& state, const QString& action); + + void addStateActionDisabled(const QString& state, const QString& action); + + enum ReverseStateChange { StateNoReverse, StateReverse }; + struct StateChange + { + QStringList actionsToEnable; + QStringList actionsToDisable; + }; + + StateChange getActionsToChangeForState(const QString& state); + + /// @since 3.1 +//US void beginXMLPlug( QWidget * ); + /// @since 3.1 +//US void endXMLPlug(); + /// @since 3.1 +//US void prepareXMLUnplug( QWidget * ); + +protected: + /** + * Returns true if client was added to super client list. + * Returns false if client was already in list. + */ + //bool addSuperClient( KXMLGUIClient * ); + + /** + * Sets the instance (@ref KInstance) for this part. + * + * Call this first in the inherited class constructor. + * (At least before @ref setXMLFile().) + */ +//US virtual void setInstance( KInstance *instance ); + + /** + * Sets the name of the rc file containing the XML for the part. + * + * Call this in the Part-inherited class constructor. + * + * @param file Either an absolute path for the file, or simply the + * filename, which will then be assumed to be installed + * in the "data" resource, under a directory named like + * the instance. + * @param setXML Specify whether to call setXML. Default is true. + * and the DOM document at once. + **/ +//US virtual void setXMLFile( const QString& file, bool merge = false, bool setXMLDoc = true ); + +//US virtual void setLocalXMLFile( const QString &file ); + + /** + * Sets the XML for the part. + * + * Call this in the Part-inherited class constructor if you + * don't call @ref setXMLFile(). + **/ +//US virtual void setXML( const QString &document, bool merge = false ); + + /** + * Sets the Document for the part, describing the layout of the GUI. + * + * Call this in the Part-inherited class constructor if you don't call + * @ref setXMLFile or @ref setXML . + */ +//US virtual void setDOMDocument( const QDomDocument &document, bool merge = false ); + + /** + * This function will attempt to give up some memory after the GUI + * is built. It should never be used in apps where the GUI may be + * rebuilt at some later time (components, for instance). + */ +//US virtual void conserveMemory(); + + /** + * Actions can collectively be assigned a "State". To accomplish this + * the respective actions are tagged as <enable> or <disable> in + * a <State> </State> group of the XMLfile. During program execution the + * programmer can call stateChanged() to set actions to a defined state. + * + * @param newstate Name of a State in the XMLfile. + * @param reverse If the flag reverse is set to StateReverse, the State is reversed. + * (actions to be enabled will be disabled and action to be disabled will be enabled) + * Default is reverse=false. + */ + virtual void stateChanged(const QString &newstate, ReverseStateChange reverse = StateNoReverse); + + // Use this one for KDE 4.0 + //virtual void stateChanged(const QString &newstate, bool reverse = false); + +private: +/*US + struct DocStruct + { + QString file; + QString data; + }; + + bool mergeXML( QDomElement &base, const QDomElement &additive, + KActionCollection *actionCollection ); + + QDomElement findMatchingElement( const QDomElement &base, + const QDomElement &additive ); +*/ + typedef QMap<QString, QMap<QString, QString> > ActionPropertiesMap; + +//US static ActionPropertiesMap extractActionProperties( const QDomDocument &doc ); + +//US static void storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties ); + +//US static QString findVersionNumber( const QString &_xml ); + + // Actions to enable/disable on a state change + QMap<QString,StateChange> m_actionsStateMap; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KXMLGUIClientPrivate *d; +}; + +#endif diff --git a/microkde/kdialog.cpp b/microkde/kdialog.cpp new file mode 100644 index 0000000..3d62cdd --- a/dev/null +++ b/microkde/kdialog.cpp @@ -0,0 +1,17 @@ + +#include <kdialog.h> +#include <qapp.h> + + +KDialog::KDialog( QWidget *parent, const char *name, bool modal ) : + QDialog( parent, name, modal ) +{ + ; + +} + +int KDialog::spacingHint() { return 3; } +int KDialog::marginHint() { return 3; } + +int KDialog::spacingHintSmall() { if (QApplication::desktop()->width() < 700 ) return 1;else return 3; } +int KDialog::marginHintSmall() { if (QApplication::desktop()->width() < 700 ) return 1;else return 3; } diff --git a/microkde/kdialog.h b/microkde/kdialog.h new file mode 100644 index 0000000..703d268 --- a/dev/null +++ b/microkde/kdialog.h @@ -0,0 +1,18 @@ +#ifndef MINIKDE_KDIALOG_H +#define MINIKDE_KDIALOG_H + +#include <qdialog.h> + +class KDialog : public QDialog +{ + Q_OBJECT + public: + KDialog( QWidget *parent=0, const char *name=0, bool modal=true ); + + static int spacingHint(); + static int marginHint(); + static int spacingHintSmall(); + static int marginHintSmall(); +}; + +#endif diff --git a/microkde/kdialogbase.cpp b/microkde/kdialogbase.cpp new file mode 100644 index 0000000..2ea2053 --- a/dev/null +++ b/microkde/kdialogbase.cpp @@ -0,0 +1,278 @@ +#include <qtabwidget.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qframe.h> + + +#include "klocale.h" +#include "kdebug.h" + +#include "kdialogbase.h" + +KDialogBase::KDialogBase() +{ +} + +KDialogBase::KDialogBase( QWidget *parent, const char *name, bool modal, + const QString &caption, + int buttonMask, ButtonCode defaultButton, + bool separator, + const QString &user1, + const QString &user2, + const QString &user3) : + KDialog( parent, name, modal ) +{ + init( caption, buttonMask, user1, user2 ); + if (findButton( defaultButton ) ) + (findButton( defaultButton ) )->setFocus(); + +} + +KDialogBase::KDialogBase( int dialogFace, const QString &caption, + int buttonMask, ButtonCode defaultButton, + QWidget *parent, const char *name, bool modal, + bool separator, + const QString &user1, + const QString &user2, + const QString &user3) : + KDialog( parent, name, modal ) +{ + init( caption, buttonMask, user1, user2 ); + if (findButton( defaultButton ) ) + (findButton( defaultButton ) )->setFocus(); + +} + +KDialogBase::~KDialogBase() +{ +} + +void KDialogBase::init( const QString &caption, int buttonMask, + const QString &user1 ,const QString &user2 ) +{ + mMainWidget = 0; + mTabWidget = 0; + mPlainPage = 0; + mTopLayout = 0; + if ( !caption.isEmpty() ) { + setCaption( caption ); + } + + if ( buttonMask & User1 ) { + mUser1Button = new QPushButton( user1, this ); + connect( mUser1Button, SIGNAL( clicked() ), SLOT( slotUser1() ) ); + } else { + mUser1Button = 0; + } + if ( buttonMask & User2 ) { + mUser2Button = new QPushButton( user2, this ); + connect( mUser2Button, SIGNAL( clicked() ), SLOT( slotUser2() ) ); + } else { + mUser2Button = 0; + } + + if ( buttonMask & Ok ) { + mOkButton = new QPushButton( i18n("Ok"), this ); + connect( mOkButton, SIGNAL( clicked() ), SLOT( slotOk() ) ); + } else { + mOkButton = 0; + } + + if ( buttonMask & Apply ) { + mApplyButton = new QPushButton( i18n("Apply"), this ); + connect( mApplyButton, SIGNAL( clicked() ), SLOT( slotApply() ) ); + } else { + mApplyButton = 0; + } + + if ( buttonMask & Cancel ) { + mCancelButton = new QPushButton( i18n("Cancel"), this ); + connect( mCancelButton, SIGNAL( clicked() ), SLOT( slotCancel() ) ); + } else { + mCancelButton = 0; + } + + if ( buttonMask & Close ) { + mCloseButton = new QPushButton( i18n("Close"), this ); + connect( mCloseButton, SIGNAL( clicked() ), SLOT( slotClose() ) ); + } else { + mCloseButton = 0; + } +} + +QTabWidget *KDialogBase::tabWidget() +{ + if ( !mTabWidget ) { + mTabWidget = new QTabWidget( this ); + setMainWidget( mTabWidget ); + } + return mTabWidget; +} + +void KDialogBase::hideButtons() +{ + if ( mUser1Button ) mUser1Button->hide() ; + if ( mUser2Button ) mUser2Button->hide() ; + if ( mOkButton ) mOkButton->hide() ; + if ( mApplyButton ) mApplyButton->hide() ; + if ( mCancelButton ) mCancelButton->hide() ; + if ( mCloseButton ) mCloseButton->hide() ; + +} +void KDialogBase::initLayout() +{ + + delete mTopLayout; + mTopLayout = new QVBoxLayout( this ); + mTopLayout->setMargin( marginHint() ); + mTopLayout->setSpacing( spacingHint() ); + + mTopLayout->addWidget( mMainWidget ); + + QBoxLayout *buttonLayout = new QHBoxLayout; + mTopLayout->addLayout( buttonLayout ); + + if ( mUser1Button ) buttonLayout->addWidget( mUser1Button ); + if ( mUser2Button ) buttonLayout->addWidget( mUser2Button ); + if ( mOkButton ) buttonLayout->addWidget( mOkButton ); + if ( mApplyButton ) buttonLayout->addWidget( mApplyButton ); + if ( mCancelButton ) buttonLayout->addWidget( mCancelButton ); + if ( mCloseButton ) buttonLayout->addWidget( mCloseButton ); +} + +QFrame *KDialogBase::addPage( const QString &name ) +{ +// kdDebug() << "KDialogBase::addPage(): " << name << endl; + QFrame *frame = new QFrame( tabWidget() ); + tabWidget()->addTab( frame, name ); + return frame; +} + +QFrame *KDialogBase::addPage( const QString &name, int, const QPixmap & ) +{ + return addPage( name ); +} + + +void KDialogBase::setMainWidget( QWidget *widget ) +{ + kdDebug() << "KDialogBase::setMainWidget()" << endl; + + mMainWidget = widget; + initLayout(); +} + +void KDialogBase::setButtonText( ButtonCode id, const QString &text ) +{ + QPushButton *button = findButton( id ); + if ( button ) { + button->setText( text ); + } +} + +void KDialogBase::enableButton( ButtonCode id, bool state ) +{ + QPushButton *button = findButton( id ); + if ( button ) { + button->setEnabled( state ); + } +} + +QPushButton *KDialogBase::findButton( ButtonCode id ) +{ + QPushButton *button = 0; + switch ( id ) { + case Ok: + button = mOkButton; + break; + case Apply: + button = mApplyButton; + break; + case User1: + button = mUser1Button; + break; + case User2: + button = mUser2Button; + break; + case Cancel: + button = mCancelButton; + break; + case Close: + button = mCloseButton; + break; + default: + break; + } + return button; +} + +void KDialogBase::enableButtonOK( bool state ) +{ + enableButton( Ok, state ); +} + +void KDialogBase::enableButtonApply( bool state ) +{ + enableButton( Apply, state ); +} + +void KDialogBase::showButton( ButtonCode id, bool show ) +{ + QPushButton *button = findButton( id ); + if ( button ) { + if ( show ) button->show(); + else button->hide(); + } +} + +int KDialogBase::pageIndex( QWidget *widget ) const +{ + return 0; +} + + +bool KDialogBase::showPage( int index ) +{ + tabWidget()->setCurrentPage( index );return false; +} + +QFrame *KDialogBase::plainPage() +{ + if ( !mPlainPage ) { + mPlainPage = new QFrame( this ); + setMainWidget( mPlainPage ); + } + return mPlainPage; +} + +void KDialogBase::slotOk() +{ + emit okClicked(); + accept(); +} + +void KDialogBase::slotApply() +{ + emit applyClicked(); +} + +void KDialogBase::slotCancel() +{ + emit cancelClicked(); + reject(); +} + +void KDialogBase::slotClose() +{ + emit closeClicked(); + reject(); +} + +void KDialogBase::slotUser1() +{ + emit user1Clicked(); +} +void KDialogBase::slotUser2() +{ + emit user2Clicked(); +} diff --git a/microkde/kdialogbase.h b/microkde/kdialogbase.h new file mode 100644 index 0000000..199d2fa --- a/dev/null +++ b/microkde/kdialogbase.h @@ -0,0 +1,139 @@ +#ifndef MINIKDE_KDIALOGBASE_H +#define MINIKDE_KDIALOGBASE_H + +#include <qframe.h> + +#include "kdialog.h" + +class QPushButton; +class QLayout; +class QTabWidget; +class QBoxLayout; + +class KDialogBase : public KDialog +{ + Q_OBJECT + public: + enum ButtonCode + { + Help = 0x00000001, + Default = 0x00000002, + Ok = 0x00000004, + Apply = 0x00000008, + Try = 0x00000010, + Cancel = 0x00000020, + Close = 0x00000040, + User1 = 0x00000080, + User2 = 0x00000100, + User3 = 0x00000200, + No = 0x00000080, + Yes = 0x00000100, + Details = 0x00000400, + Filler = 0x40000000, + Stretch = 0x80000000 + }; + + enum DialogType + { + TreeList, + Tabbed, + Plain, + Swallow, + IconList + }; + + KDialogBase(); + KDialogBase( QWidget *parent=0, const char *name=0, bool modal=true, + const QString &caption=QString::null, + int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok, + bool separator=false, + const QString &user1=QString::null, + const QString &user2=QString::null, + const QString &user3=QString::null); + KDialogBase( int dialogFace, const QString &caption, + int buttonMask, ButtonCode defaultButton, + QWidget *parent=0, const char *name=0, bool modal=true, + bool separator=false, + const QString &user1=QString::null, + const QString &user2=QString::null, + const QString &user3=QString::null); + virtual ~KDialogBase(); + + QFrame *addPage( const QString & ); + QFrame *addPage( const QString &, int, const QPixmap & ); + + void setMainWidget( QWidget *widget ); + + void setButtonText( ButtonCode id, const QString &text ); + + void enableButton( ButtonCode id, bool state ); + void enableButtonOK( bool state ); + void enableButtonApply( bool state ); + + void showButton( ButtonCode, bool show ); + + int pageIndex( QWidget *widget ) const; + + bool showPage( int index ); + void hideButtons(); + + QFrame *plainPage(); + + signals: + void user1Clicked(); + void user2Clicked(); + /** + * The Apply button was pressed. This signal is only emitted if + * @ref slotApply() is not replaced. + */ + void applyClicked(); + + /** + * The OK button was pressed. This signal is only emitted if + * @ref slotOk() is not replaced. + */ + void okClicked(); + + /** + * The Cancel button was pressed. This signal is only emitted if + * @ref slotCancel() is not replaced. + */ + void cancelClicked(); + + /** + * The Close button was pressed. This signal is only emitted if + * @ref slotClose() is not replaced. + */ + void closeClicked(); + + protected slots: + virtual void slotOk(); + virtual void slotApply(); + virtual void slotCancel(); + virtual void slotClose(); + virtual void slotUser1(); + virtual void slotUser2(); + + protected: + QPushButton *findButton( ButtonCode ); + + private: + QTabWidget *tabWidget(); + void init( const QString &caption, int buttonMask, + const QString &user1=QString::null, const QString &user2=QString::null ); + void initLayout(); + + QWidget *mMainWidget; + QTabWidget *mTabWidget; + QFrame *mPlainPage; + QBoxLayout *mTopLayout; + + QPushButton *mUser1Button; + QPushButton *mUser2Button; + QPushButton *mCloseButton; + QPushButton *mOkButton; + QPushButton *mApplyButton; + QPushButton *mCancelButton; +}; + +#endif diff --git a/microkde/kdirwatch.h b/microkde/kdirwatch.h new file mode 100644 index 0000000..22b4dec --- a/dev/null +++ b/microkde/kdirwatch.h @@ -0,0 +1,14 @@ +#ifndef MICROKDE_KDIRWATCH_H +#define MICROKDE_KDIRWATCH_H + +#include <qobject.h> + +class KDirWatch : public QObject +{ + public: + KDirWatch() {} + + void addDir( const QString & ) {} +}; + +#endif diff --git a/microkde/keditlistbox.cpp b/microkde/keditlistbox.cpp new file mode 100644 index 0000000..55b7784 --- a/dev/null +++ b/microkde/keditlistbox.cpp @@ -0,0 +1,389 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org> + 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qstringlist.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <qlistbox.h> +#include <qwhatsthis.h> +#include <qlabel.h> + +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klineedit.h> +#include <klocale.h> +#include <kapplication.h> +#include <knotifyclient.h> + +#include "keditlistbox.h" + +#include <assert.h> + +class KEditListBoxPrivate +{ +public: + bool m_checkAtEntering; + int buttons; +}; + +KEditListBox::KEditListBox(QWidget *parent, const char *name, + bool checkAtEntering, int buttons ) + :QGroupBox(parent, name ) +{ + init( checkAtEntering, buttons ); +} + +KEditListBox::KEditListBox(const QString& title, QWidget *parent, + const char *name, bool checkAtEntering, int buttons) + :QGroupBox(title, parent, name ) +{ + init( checkAtEntering, buttons ); +} + +KEditListBox::KEditListBox(const QString& title, const CustomEditor& custom, + QWidget *parent, const char *name, + bool checkAtEntering, int buttons) + :QGroupBox(title, parent, name ) +{ + m_lineEdit = custom.lineEdit(); + init( checkAtEntering, buttons, custom.representationWidget() ); +} + +KEditListBox::~KEditListBox() +{ + delete d; + d=0; +} + +void KEditListBox::init( bool checkAtEntering, int buttons, + QWidget *representationWidget ) +{ + d=new KEditListBoxPrivate; + d->m_checkAtEntering=checkAtEntering; + d->buttons = buttons; + + int lostButtons = 0; + if ( (buttons & Add) == 0 ) + lostButtons++; + if ( (buttons & Remove) == 0 ) + lostButtons++; + if ( (buttons & UpDown) == 0 ) + lostButtons += 2; + + + servNewButton = servRemoveButton = servUpButton = servDownButton = 0L; + setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding)); + + QWidget * gb = this; + QGridLayout * grid = new QGridLayout(gb, 7 - lostButtons, 2, + KDialog::marginHint(), + KDialog::spacingHint()); + grid->addRowSpacing(0, fontMetrics().lineSpacing()); + for ( int i = 1; i < 7 - lostButtons; i++ ) + grid->setRowStretch(i, 1); + + grid->setMargin(15); + + if ( representationWidget ) + representationWidget->reparent( gb, QPoint(0,0) ); + else + m_lineEdit=new KLineEdit(gb); + + m_listBox = new QListBox(gb); + + QWidget *editingWidget = representationWidget ? + representationWidget : m_lineEdit; + grid->addMultiCellWidget(editingWidget,1,1,0,1); + grid->addMultiCellWidget(m_listBox, 2, 6 - lostButtons, 0, 0); + int row = 2; + if ( buttons & Add ) { + servNewButton = new QPushButton(i18n("&Add"), gb); + servNewButton->setEnabled(false); + connect(servNewButton, SIGNAL(clicked()), SLOT(addItem())); + + grid->addWidget(servNewButton, row++, 1); + } + + if ( buttons & Remove ) { + servRemoveButton = new QPushButton(i18n("&Remove"), gb); + servRemoveButton->setEnabled(false); + connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeItem())); + + grid->addWidget(servRemoveButton, row++, 1); + } + + if ( buttons & UpDown ) { + servUpButton = new QPushButton(i18n("Move &Up"), gb); + servUpButton->setEnabled(false); + connect(servUpButton, SIGNAL(clicked()), SLOT(moveItemUp())); + + servDownButton = new QPushButton(i18n("Move &Down"), gb); + servDownButton->setEnabled(false); + connect(servDownButton, SIGNAL(clicked()), SLOT(moveItemDown())); + + grid->addWidget(servUpButton, row++, 1); + grid->addWidget(servDownButton, row++, 1); + } + + connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&))); + m_lineEdit->setTrapReturnKey(true); + connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem())); + connect(m_listBox, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int))); + + // maybe supplied lineedit has some text already + typedSomething( m_lineEdit->text() ); +} + +void KEditListBox::typedSomething(const QString& text) +{ + if(currentItem() >= 0) { + if(currentText() != m_lineEdit->text()) + { + // IMHO changeItem() shouldn't do anything with the value + // of currentItem() ... like changing it or emitting signals ... + // but TT disagree with me on this one (it's been that way since ages ... grrr) + bool block = m_listBox->signalsBlocked(); + m_listBox->blockSignals( true ); + m_listBox->changeItem(text, currentItem()); + m_listBox->blockSignals( block ); + emit changed(); + } + } + + if ( !servNewButton ) + return; + + if (!d->m_checkAtEntering) + servNewButton->setEnabled(!text.isEmpty()); + else + { + if (text.isEmpty()) + { + servNewButton->setEnabled(false); + } + else + { + bool enable = (m_listBox->findItem( text ) == 0L); + servNewButton->setEnabled( enable ); + } + } +} + +void KEditListBox::moveItemUp() +{ + if (!m_listBox->isEnabled()) + { + KNotifyClient::beep(); + return; + } + + unsigned int selIndex = m_listBox->currentItem(); + if (selIndex == 0) + { + KNotifyClient::beep(); + return; + } + + QListBoxItem *selItem = m_listBox->item(selIndex); + m_listBox->takeItem(selItem); + m_listBox->insertItem(selItem, selIndex-1); + m_listBox->setCurrentItem(selIndex - 1); + + emit changed(); +} + +void KEditListBox::moveItemDown() +{ + if (!m_listBox->isEnabled()) + { + KNotifyClient::beep(); + return; + } + + unsigned int selIndex = m_listBox->currentItem(); + if (selIndex == m_listBox->count() - 1) + { + KNotifyClient::beep(); + return; + } + + QListBoxItem *selItem = m_listBox->item(selIndex); + m_listBox->takeItem(selItem); + m_listBox->insertItem(selItem, selIndex+1); + m_listBox->setCurrentItem(selIndex + 1); + + emit changed(); +} + +void KEditListBox::addItem() +{ + // when m_checkAtEntering is true, the add-button is disabled, but this + // slot can still be called through Key_Return/Key_Enter. So we guard + // against this. + if ( !servNewButton || !servNewButton->isEnabled() ) + return; + + const QString& currentTextLE=m_lineEdit->text(); + bool alreadyInList(false); + //if we didn't check for dupes at the inserting we have to do it now + if (!d->m_checkAtEntering) + { + // first check current item instead of dumb iterating the entire list + if ( m_listBox->currentText() == currentTextLE ) + alreadyInList = true; + else + { + alreadyInList =(m_listBox->findItem(currentTextLE) != 0); + } + } + + if ( servNewButton ) + servNewButton->setEnabled(false); + + bool block = m_lineEdit->signalsBlocked(); + m_lineEdit->blockSignals(true); + m_lineEdit->clear(); + m_lineEdit->blockSignals(block); + + m_listBox->setSelected(currentItem(), false); + + if (!alreadyInList) + { + block = m_listBox->signalsBlocked(); + m_listBox->blockSignals( true ); + m_listBox->insertItem(currentTextLE); + m_listBox->blockSignals( block ); + emit changed(); + } +} + +int KEditListBox::currentItem() const +{ + int nr = m_listBox->currentItem(); + if(nr >= 0 && !m_listBox->item(nr)->selected()) return -1; + return nr; +} + +void KEditListBox::removeItem() +{ + int selected = m_listBox->currentItem(); + + if ( selected >= 0 ) + { + m_listBox->removeItem( selected ); + if ( count() > 0 ) + m_listBox->setSelected( QMIN( selected, count() - 1 ), true ); + + emit changed(); + } + + if ( servRemoveButton && m_listBox->currentItem() == -1 ) + servRemoveButton->setEnabled(false); +} + +void KEditListBox::enableMoveButtons(int index) +{ + // Update the lineEdit when we select a different line. + if(currentText() != m_lineEdit->text()) + m_lineEdit->setText(currentText()); + + bool moveEnabled = servUpButton && servDownButton; + + if (moveEnabled ) + { + if (m_listBox->count() <= 1) + { + servUpButton->setEnabled(false); + servDownButton->setEnabled(false); + } + else if ((uint) index == (m_listBox->count() - 1)) + { + servUpButton->setEnabled(true); + servDownButton->setEnabled(false); + } + else if (index == 0) + { + servUpButton->setEnabled(false); + servDownButton->setEnabled(true); + } + else + { + servUpButton->setEnabled(true); + servDownButton->setEnabled(true); + } + } + + if ( servRemoveButton ) + servRemoveButton->setEnabled(true); +} + +void KEditListBox::clear() +{ + m_lineEdit->clear(); + m_listBox->clear(); + emit changed(); +} + +void KEditListBox::insertStringList(const QStringList& list, int index) +{ + m_listBox->insertStringList(list,index); +} + +void KEditListBox::insertStrList(const QStrList* list, int index) +{ + m_listBox->insertStrList(list,index); +} + +void KEditListBox::insertStrList(const QStrList& list, int index) +{ + m_listBox->insertStrList(list,index); +} + +void KEditListBox::insertStrList(const char ** list, int numStrings, int index) +{ + m_listBox->insertStrList(list,numStrings,index); +} + +QStringList KEditListBox::items() const +{ + QStringList list; + for ( uint i = 0; i < m_listBox->count(); i++ ) + list.append( m_listBox->text( i )); + + return list; +} + +void KEditListBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +KEditListBox::CustomEditor::CustomEditor( KComboBox *combo ) +{ + m_representationWidget = combo; + m_lineEdit = static_cast<KLineEdit*>( combo->lineEdit() ); + assert( m_lineEdit ); +} + diff --git a/microkde/keditlistbox.h b/microkde/keditlistbox.h new file mode 100644 index 0000000..130d933 --- a/dev/null +++ b/microkde/keditlistbox.h @@ -0,0 +1,226 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KEDITLISTBOX_H +#define KEDITLISTBOX_H + +#include <qgroupbox.h> +#include <qlistbox.h> + +class KLineEdit; +class KComboBox; +class QPushButton; + +class KEditListBoxPrivate; +/** + * An editable listbox + * + * This class provides a editable listbox ;-), this means + * a listbox which is accompanied by a line edit to enter new + * items into the listbox and pushbuttons to add and remove + * items from the listbox and two buttons to move items up and down. + */ +class KEditListBox : public QGroupBox +{ + Q_OBJECT + +public: + /// @since 3.1 + class CustomEditor + { + public: + CustomEditor() + : m_representationWidget( 0L ), + m_lineEdit( 0L ) {} + CustomEditor( QWidget *repWidget, KLineEdit *edit ) + : m_representationWidget( repWidget ), + m_lineEdit( edit ) {} + CustomEditor( KComboBox *combo ); + + void setRepresentationWidget( QWidget *repWidget ) { + m_representationWidget = repWidget; + } + void setLineEdit( KLineEdit *edit ) { + m_lineEdit = edit; + } + + virtual QWidget *representationWidget() const { + return m_representationWidget; + } + virtual KLineEdit *lineEdit() const { + return m_lineEdit; + } + + protected: + QWidget *m_representationWidget; + KLineEdit *m_lineEdit; + }; + + public: + + /** + * Enumeration of the buttons, the listbox offers. Specify them in the + * constructor in the buttons parameter. + */ + enum Button { Add = 1, Remove = 2, UpDown = 4, All = Add|Remove|UpDown }; + + /** + * Create an editable listbox. + * + * If @p checkAtEntering is true, after every character you type + * in the line edit KEditListBox will enable or disable + * the Add-button, depending whether the current content of the + * line edit is already in the listbox. Maybe this can become a + * performance hit with large lists on slow machines. + * If @p checkAtEntering is false, + * it will be checked if you press the Add-button. It is not + * possible to enter items twice into the listbox. + */ + KEditListBox(QWidget *parent = 0, const char *name = 0, + bool checkAtEntering=false, int buttons = All ); + /** + * Create an editable listbox. + * + * The same as the other constructor, additionally it takes + * @title, which will be the title of the frame around the listbox. + */ + KEditListBox(const QString& title, QWidget *parent = 0, + const char *name = 0, bool checkAtEntering=false, + int buttons = All ); + + /** + * Another constructor, which allows to use a custom editing widget + * instead of the standard KLineEdit widget. E.g. you can use a + * @ref KURLRequester or a @ref KComboBox as input widget. The custom + * editor must consist of a lineedit and optionally another widget that + * is used as representation. A KComboBox or a KURLRequester have a + * KLineEdit as child-widget for example, so the KComboBox is used as + * the representation widget. + * + * @see KURLRequester::customEditor() + * @since 3.1 + */ + KEditListBox( const QString& title, + const CustomEditor &customEditor, + QWidget *parent = 0, const char *name = 0, + bool checkAtEntering = false, int buttons = All ); + + virtual ~KEditListBox(); + + /** + * Return a pointer to the embedded QListBox. + */ + QListBox* listBox() const { return m_listBox; } + /** + * Return a pointer to the embedded QLineEdit. + */ + KLineEdit* lineEdit() const { return m_lineEdit; } + /** + * Return a pointer to the Add button + */ + QPushButton* addButton() const { return servNewButton; } + /** + * Return a pointer to the Remove button + */ + QPushButton* removeButton() const { return servRemoveButton; } + /** + * Return a pointer to the Up button + */ + QPushButton* upButton() const { return servUpButton; } + /** + * Return a pointer to the Down button + */ + QPushButton* downButton() const { return servDownButton; } + + /** + * See @ref QListBox::count() + */ + int count() const { return int(m_listBox->count()); } + /** + * See @ref QListBox::insertStringList() + */ + void insertStringList(const QStringList& list, int index=-1); + /** + * See @ref QListBox::insertStringList() + */ + void insertStrList(const QStrList* list, int index=-1); + /** + * See @ref QListBox::insertStrList() + */ + void insertStrList(const QStrList& list, int index=-1); + /** + * See @ref QListBox::insertStrList() + */ + void insertStrList(const char ** list, int numStrings=-1, int index=-1); + /** + * See @ref QListBox::insertItem() + */ + void insertItem(const QString& text, int index=-1) {m_listBox->insertItem(text,index);} + /** + * Clears both the listbox and the line edit. + */ + void clear(); + /** + * See @ref QListBox::text() + */ + QString text(int index) const { return m_listBox->text(index); } + /** + * See @ref QListBox::currentItem() + */ + int currentItem() const; + /** + * See @ref QListBox::currentText() + */ + QString currentText() const { return m_listBox->currentText(); } + + /** + * @returns a stringlist of all items in the listbox + */ + QStringList items() const; + + signals: + void changed(); + + protected slots: + //the names should be self-explaining + void moveItemUp(); + void moveItemDown(); + void addItem(); + void removeItem(); + void enableMoveButtons(int index); + void typedSomething(const QString& text); + + private: + QListBox *m_listBox; + QPushButton *servUpButton, *servDownButton; + QPushButton *servNewButton, *servRemoveButton; + KLineEdit *m_lineEdit; + + //this is called in both ctors, to avoid code duplication + void init( bool checkAtEntering, int buttons, + QWidget *representationWidget = 0L ); + + protected: + virtual void virtual_hook( int id, void* data ); + private: + //our lovely private d-pointer + KEditListBoxPrivate *d; +}; + +#endif diff --git a/microkde/kemailsettings.cpp b/microkde/kemailsettings.cpp new file mode 100644 index 0000000..9a9ad84 --- a/dev/null +++ b/microkde/kemailsettings.cpp @@ -0,0 +1,6 @@ +#include "kemailsettings.h" + +QString KEMailSettings::getSetting(KEMailSettings::Setting s) +{ + return QString::null; +} diff --git a/microkde/kemailsettings.h b/microkde/kemailsettings.h new file mode 100644 index 0000000..cf43f17 --- a/dev/null +++ b/microkde/kemailsettings.h @@ -0,0 +1,32 @@ +#ifndef MINIKDE_KEMAILSETTINGS_H +#define MINIKDE_KEMAILSETTINGS_H + +#include <qstring.h> + +class KEMailSettings +{ + public: + enum Setting { + ClientProgram, + ClientTerminal, + RealName, + EmailAddress, + ReplyToAddress, + Organization, + OutServer, + OutServerLogin, + OutServerPass, + OutServerType, + OutServerCommand, + OutServerTLS, + InServer, + InServerLogin, + InServerPass, + InServerType, + InServerMBXType, + InServerTLS + }; + QString getSetting(KEMailSettings::Setting s); +}; + +#endif diff --git a/microkde/kfiledialog.cpp b/microkde/kfiledialog.cpp new file mode 100644 index 0000000..977499e --- a/dev/null +++ b/microkde/kfiledialog.cpp @@ -0,0 +1,74 @@ +#include <kfiledialog.h> +#include <qdialog.h> +#include <qlayout.h> +#include <qdir.h> +#include <qfileinfo.h> +#include <qapplication.h> + +#ifndef DESKTOP_VERSION +//US orig#include <ofileselector.h> +#include <ofileselector_p.h> +QString KFileDialog::getSaveFileName( const QString & fn, + const QString & cap , QWidget * par ) +{ + QString retfile = ""; + QDialog dia ( par, "input-dialog", true ); + QVBoxLayout lay( &dia ); + lay.setMargin(7); + lay.setSpacing(7); + dia.setCaption( cap ); + QString file = fn; + if ( file.isEmpty() ) + file = QDir::homeDirPath()+"/*"; + QFileInfo fi ( file ); + OFileSelector o ( &dia,OFileSelector::FileSelector, OFileSelector::Save, fi.dirPath(true), fi.fileName() ); + lay.addWidget( &o); + // o.setNewVisible( true ); + // o.setNameVisible( true ); + dia.showMaximized(); + int res = dia.exec(); + if ( res ) + retfile = o.selectedName(); + return retfile; +} + +QString KFileDialog::getOpenFileName( const QString & fn, + const QString & cap, QWidget * par ) +{ + QString retfile = ""; + QDialog dia ( par, "input-dialog", true ); + // QLineEdit lab ( &dia ); + QVBoxLayout lay( &dia ); + lay.setMargin(7); + lay.setSpacing(7); + dia.setCaption( cap ); + QString file = fn; + if ( file.isEmpty() ) + file = QDir::homeDirPath()+"/*";; + QFileInfo fi ( file ); + OFileSelector o ( &dia,OFileSelector::FileSelector, OFileSelector::Open, fi.dirPath(true), fi.fileName() ); + lay.addWidget( &o); + dia.showMaximized(); + int res = dia.exec(); + if ( res ) + retfile = o.selectedName(); + return retfile; +} + +#else + +#include <qfiledialog.h> + +QString KFileDialog::getSaveFileName( const QString & fn, + const QString & cap , QWidget * par ) +{ + return QFileDialog::getSaveFileName( fn, QString::null, par, "openfile", cap ); +} +QString KFileDialog::getOpenFileName( const QString & fn, + const QString & cap, QWidget * par ) +{ + + return QFileDialog::getOpenFileName( fn, QString::null, par, "openfile", cap ); +} +#endif + diff --git a/microkde/kfiledialog.h b/microkde/kfiledialog.h new file mode 100644 index 0000000..0825872 --- a/dev/null +++ b/microkde/kfiledialog.h @@ -0,0 +1,20 @@ +#ifndef MICROKDE_KFILEDIALOG_H +#define MICROKDE_KFILEDIALOG_H + +#include <qstring.h> +#include <qwidget.h> + +class KFileDialog +{ + public: + + static QString getSaveFileName( const QString &, + const QString &, QWidget * ); + + + static QString getOpenFileName( const QString &, + const QString &, QWidget * ); + +}; + +#endif diff --git a/microkde/kfontdialog.cpp b/microkde/kfontdialog.cpp new file mode 100644 index 0000000..174123c --- a/dev/null +++ b/microkde/kfontdialog.cpp @@ -0,0 +1,32 @@ +#include "kfontdialog.h" +#ifndef DESKTOP_VERSION +#include "ofontselector.h" +#else +#include <qfontdialog.h> +#endif +#include <qdialog.h> +#include <qlayout.h> +#include <qpushbutton.h> +QFont KFontDialog::getFont( const QFont & f, bool & ok ) +{ +#ifndef DESKTOP_VERSION + QDialog d( 0, "fd", true );; + OFontSelector s ( true, &d, "fontsel"); + QVBoxLayout l ( &d ); + l.addWidget( &s ); + s.setSelectedFont ( f ); + QPushButton b ( "OK", &d ); + l.addWidget( &b ); + qDebug("size %d ", f.bold()); + QObject::connect( &b, SIGNAL( clicked () ), &d, SLOT ( accept () ) ); + d.show(); + ok = false; + if ( d.exec () ) { + ok = true; + return s.selectedFont ( ); + } + return f; +#else + return QFontDialog::getFont ( &ok, f, 0, "fontdialog" ); +#endif +} diff --git a/microkde/kfontdialog.h b/microkde/kfontdialog.h new file mode 100644 index 0000000..f2ac6ac --- a/dev/null +++ b/microkde/kfontdialog.h @@ -0,0 +1,15 @@ +#ifndef MINIKDE_KFONTDIALOG_H +#define MINIKDE_KFONTDIALOG_H + +#include <qfont.h> +#include <qdialog.h> + +class KFontDialog +{ + public: + enum { Accepted }; + + static QFont getFont( const QFont & f, bool & ok); +}; + +#endif diff --git a/microkde/kglobal.cpp b/microkde/kglobal.cpp new file mode 100644 index 0000000..0aba952 --- a/dev/null +++ b/microkde/kglobal.cpp @@ -0,0 +1,166 @@ +#include "kglobal.h" +#include <qkeycode.h> +#include <qapplication.h> + +KLocale *KGlobal::mLocale = 0; +KConfig *KGlobal::mConfig = 0; +KIconLoader *KGlobal::mIconLoader = 0; +KStandardDirs *KGlobal::mDirs = 0; + +QString KGlobal::mAppName = "godot"; + +KLocale *KGlobal::locale() +{ + if ( !mLocale ) { + ASSERT(mAppName); + + mLocale = new KLocale();//mAppName); + } + + return mLocale; +} + +//US +void KGlobal::setLocale(KLocale *kg) +{ + mLocale = kg; +} + +KConfig *KGlobal::config() +{ + if ( !mConfig ) { + mConfig = new KConfig( KStandardDirs::appDir() + mAppName + "rc" ); + } + + return mConfig; +} + +KGlobal::Size KGlobal::getDesktopSize() +{ +#ifdef DESKTOP_VERSION + return KGlobal::Desktop; +#else + if ( QApplication::desktop()->width() < 480 ) + return KGlobal::Small; + else + return KGlobal::Medium; +#endif +} + +KGlobal::Orientation KGlobal::getOrientation() +{ + if (QApplication::desktop()->width() > QApplication::desktop()->height()) + return KGlobal::Landscape; + else + return KGlobal::Portrait; +} + +int KGlobal::getDesktopWidth() +{ + return QApplication::desktop()->width(); +} + +int KGlobal::getDesktopHeight() +{ + return QApplication::desktop()->height(); +} + + +KIconLoader *KGlobal::iconLoader() +{ + if ( !mIconLoader ) { + mIconLoader = new KIconLoader(); + } + + return mIconLoader; +} + +KStandardDirs *KGlobal::dirs() +{ + if ( !mDirs ) { + mDirs = new KStandardDirs(); + } + + return mDirs; +} + +void KGlobal::setAppName( const QString &appName ) +{ + mAppName = appName; +} + +//US +QString KGlobal::getAppName() +{ + return mAppName; +} +QString KGlobal::formatMessage ( QString mess, int maxlen ) +{ + //int maxlen = 80; + int start = 0; + int end = mess.length(); + QString retVal = ""; + int nl, space; + while ( (end - start) > maxlen ) { + nl = mess.find( "\n", start ); + if ( nl > 0 && nl < start + maxlen ) { + nl += 1; + retVal += mess.mid( start, nl - start); + start = nl; + } else { + space = mess.findRev( " ", start + maxlen ); + if ( space < start ) { + retVal += mess.mid( start, maxlen) +"\n"; + start += maxlen ; + } else { + retVal += mess.mid( start, space - start ) +"\n"; + start = space+ 1; + } + } + } + retVal += mess.mid( start, end - start ); + return retVal; +} +int KGlobal::knumkeykonv( int k ) +{ + int key; +switch( k ) { + case Qt::Key_Q : + key = Qt::Key_1; + break; + case Qt::Key_W : + key = Qt::Key_2; + break; + case Qt::Key_E : + key = Qt::Key_3; + break; + case Qt::Key_R : + key = Qt::Key_4; + break; + case Qt::Key_T : + key = Qt::Key_5; + break; + case Qt::Key_Z : + key = Qt::Key_6; + break; + case Qt::Key_Y : + key = Qt::Key_6; + break; + case Qt::Key_U : + key = Qt::Key_7; + break; + case Qt::Key_I : + key = Qt::Key_8; + break; + case Qt::Key_O : + key = Qt::Key_9; + break; + case Qt::Key_P : + key = Qt::Key_0; + break; + default: + key = k; + break; + } // switch + return key; +} diff --git a/microkde/kglobal.h b/microkde/kglobal.h new file mode 100644 index 0000000..1e03bea --- a/dev/null +++ b/microkde/kglobal.h @@ -0,0 +1,68 @@ +#ifndef MINIKDE_KGLOBAL_H +#define MINIKDE_KGLOBAL_H + +#include "klocale.h" +#include "kconfig.h" +#include "kiconloader.h" +#include <kstandarddirs.h> +#include <qevent.h> +class KStandardDirs; +class KGlobal { + public: + static KLocale *locale(); + static KConfig *config(); + static KIconLoader *iconLoader(); + static KStandardDirs *dirs(); + static int knumkeykonv( int ); + + static void setAppName( const QString & ); + static QString formatMessage( QString mess, int maxlen ) ; + +//US begin: added the following methods for convenience + static QString getAppName(); + static void setLocale(KLocale *); + + enum Orientation { Portrait, Landscape }; + enum Size { Small, Medium, Desktop }; + + static int getDesktopWidth(); + static int getDesktopHeight(); + static KGlobal::Size getDesktopSize(); + static KGlobal::Orientation getOrientation(); + + + private: + static KLocale *mLocale; + static KConfig *mConfig; + static KIconLoader *mIconLoader; + static KStandardDirs *mDirs; + + static QString mAppName; +}; + + +/** @ref KGlobal + * A typesafe function to find the minimum of the two arguments. + */ +#define KMIN(a,b) kMin(a,b) +/** @ref KGlobal + * A typesafe function to find the maximum of the two arguments. + */ +#define KMAX(a,b) kMax(a,b) +/** @ref KGlobal + * A typesafe function to determine the absolute value of the argument. + */ +#define KABS(a) kAbs(a) + + +template<class T> +inline const T& kMin (const T& a, const T& b) { return a < b ? a : b; } + +template<class T> +inline const T& kMax (const T& a, const T& b) { return b < a ? a : b; } + +template<class T> +inline T kAbs (const T& a) { return a < 0 ? -a : a; } + + +#endif diff --git a/microkde/kglobalsettings.cpp b/microkde/kglobalsettings.cpp new file mode 100644 index 0000000..2fff8fc --- a/dev/null +++ b/microkde/kglobalsettings.cpp @@ -0,0 +1,41 @@ +#include "kglobalsettings.h" +#include "kconfig.h" +#include "kglobal.h" +#include "kconfigbase.h" + +#include <qapplication.h> + +QFont KGlobalSettings::generalFont() +{ + int size = 12; + if (QApplication::desktop()->width() < 480 ) + size = 10; + return QFont("helvetica",size); +} +QFont KGlobalSettings::toolBarFont() +{ + return QFont("helevetica",12); +} + +QColor KGlobalSettings::toolBarHighlightColor() +{ + return QColor("black"); +} + +QRect KGlobalSettings::desktopGeometry( QWidget * ) +{ + return QApplication::desktop()->rect(); +} + + /** + * Returns whether KDE runs in single (default) or double click + * mode. + * see http://developer.kde.org/documentation/standards/kde/style/mouse/index.html + * @return true if single click mode, or false if double click mode. + **/ +bool KGlobalSettings::singleClick() +{ + KConfig *c = KGlobal::config(); + KConfigGroupSaver cgs( c, "KDE" ); + return c->readBoolEntry("SingleClick", KDE_DEFAULT_SINGLECLICK); +} diff --git a/microkde/kglobalsettings.h b/microkde/kglobalsettings.h new file mode 100644 index 0000000..7df8012 --- a/dev/null +++ b/microkde/kglobalsettings.h @@ -0,0 +1,30 @@ +#ifndef MICROKDE_KGLOBALSETTINGS_H +#define MICROKDE_KGLOBALSETTINGS_H + +#include <qfont.h> +#include <qrect.h> + + +#define KDE_DEFAULT_SINGLECLICK true + + +class KGlobalSettings +{ + public: + static QFont generalFont(); + static QFont toolBarFont(); + + static QColor toolBarHighlightColor(); + static QRect desktopGeometry( QWidget * ); + + /** + * Returns whether KDE runs in single (default) or double click + * mode. + * see http://developer.kde.org/documentation/standards/kde/style/mouse/index.html + * @return true if single click mode, or false if double click mode. + **/ + static bool singleClick(); + +}; + +#endif diff --git a/microkde/kiconloader.cpp b/microkde/kiconloader.cpp new file mode 100644 index 0000000..4842d71 --- a/dev/null +++ b/microkde/kiconloader.cpp @@ -0,0 +1,140 @@ + +#include "kiconloader.h" +#include "kglobal.h" + +#ifndef DESKTOP_VERSION_OEGEL +#include <qdir.h> +QPixmap KIconLoader::loadIcon( const QString& name, KIcon::Group, int, + int, QString *, bool ) const +{ + QPixmap pix; + QString file; + file = iconPath() + name+".png"; + pix.load ( file ); + // qDebug("KIconLoader::loadIcon %s -----------", file.latin1()); + return pix; +} +QIconSet KIconLoader::loadIconSet( const QString& name) const +{ + QPixmap pixmapLoader; + QString file; + file = iconPath() + name+".png"; + pixmapLoader.load( file ); + //qDebug("KIconLoader::loadIconSet: %s ************", file.latin1() ); + QIconSet is ( pixmapLoader ); + return is; +} + +QPixmap BarIcon( const QString &name ) +{ + QPixmap pix; + pix.load ( KGlobal::iconLoader()->iconPath() + name +".png" ); + return pix; +} + +QPixmap DesktopIcon( const QString &name, int ) +{ + QPixmap pix; + pix.load ( KGlobal::iconLoader()->iconPath() + name +".png" ); + return pix; + +} + +QPixmap SmallIcon( const QString &name ) +{ + QPixmap pixmapLoader; + QString file; + file =KGlobal::iconLoader()->iconPath() + name +".png"; + pixmapLoader.load( file ); + return pixmapLoader; + +} + +QPixmap SmallIconSet( const QString &name ) +{ + QPixmap pixmapLoader; + QString file; + file =KGlobal::iconLoader()->iconPath() + name +".png"; + pixmapLoader.load( file ); + return pixmapLoader; +} + + +#else + +#include <qpe/resource.h> +#include <kglobal.h> +QPixmap KIconLoader::loadIcon( const QString& name, KIcon::Group, int, + int, QString *, bool ) const +{ + QString px = this->iconPath() + "/" + name; + + QPixmap p = Resource::loadPixmap( px ); + QPixmap* pPtr = &p; + if (pPtr == 0) + qDebug("KIconLoader::loadIcon: %s not found", px.latin1()); + + return p; +} + +QIconSet KIconLoader::loadIconSet( const QString& name) const +{ + QString px = this->iconPath() + "/" + name; + + QIconSet is ;//= Resource::loadIconSet( px ); + QIconSet* isPtr = 0;//LR&is; + if (isPtr == 0) + qDebug("KIconLoader::loadIconSet: %s not foun", px.latin1()); + + return is; +} + +QPixmap BarIcon( const QString &name ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +QPixmap DesktopIcon( const QString &name, int ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +QPixmap SmallIcon( const QString &name ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +QPixmap SmallIconSet( const QString &name ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +#endif + +//US +QString KIconLoader::setIconPath( const QString &iconpath) +{ + QString _old = mIconpath; + mIconpath = iconpath; + + return _old; +} +QString KIconLoader::iconPath( const QString & name, int ) const +{ + return mIconpath + name + ".png"; +} + +QString KIconLoader::iconPath( /*US const QString &, int */) const +{ + // LR we set the path at startup + // if (KGlobal::getDesktopSize() == KGlobal::Small) + //return mIconpath + "/icons16"; + + //Fall back to the defaultpath + return mIconpath; +} + diff --git a/microkde/kiconloader.h b/microkde/kiconloader.h new file mode 100644 index 0000000..68fec4e --- a/dev/null +++ b/microkde/kiconloader.h @@ -0,0 +1,52 @@ +#ifndef MINIKDE_KICONLOADER_H +#define MINIKDE_KICONLOADER_H + +#include <qpixmap.h> +#include <qstring.h> +//US +#include <qiconset.h> + +class KIcon +{ + public: + enum Group { NoGroup=-1, Desktop=0, Toolbar, MainToolbar, Small, + Panel, LastGroup, User }; + enum StdSizes { SizeSmall=16, SizeMedium=32, SizeLarge=48 }; + enum States { DefaultState, ActiveState, DisabledState, LastState }; +}; + +class KIconLoader +{ + public: + KIconLoader() + : mIconpath(0) {} + + KIconLoader( const QString &iconpath ) + : mIconpath(iconpath) {} + +//US QPixmap loadIcon( const QString &name, int ); + + QPixmap loadIcon(const QString& name, KIcon::Group group, int size=0, + int state=KIcon::DefaultState, QString *path_store=0, + bool canReturnNull=false) const; + +//US + QString setIconPath( const QString &); + QString iconPath( /*US const QString &, int */) const; + QString iconPath( const QString &, int ) const; + QIconSet loadIconSet( const QString &name) const; + +//US to make this class usable for different applications, we have to add a iconpathvariable + private: + QString mIconpath; +}; + +QPixmap BarIcon(const QString& name); + +QPixmap DesktopIcon(const QString& name, int); + +QPixmap SmallIcon(const QString& name); + +QPixmap SmallIconSet( const QString &name ); + +#endif diff --git a/microkde/kio/job.h b/microkde/kio/job.h new file mode 100644 index 0000000..21c56b0 --- a/dev/null +++ b/microkde/kio/job.h @@ -0,0 +1,12 @@ +#ifndef MINIKDE_KIO_JOB_H +#define MINIKDE_KIO_JOB_H + +namespace KIO { + +class Job +{ +}; + +} + +#endif diff --git a/microkde/kio/kfile/kurlrequester.cpp b/microkde/kio/kfile/kurlrequester.cpp new file mode 100644 index 0000000..6d39308 --- a/dev/null +++ b/microkde/kio/kfile/kurlrequester.cpp @@ -0,0 +1,406 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> + + library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#include <sys/stat.h> +#ifdef _WIN32_ + +#else +#include <unistd.h> +#endif +#include <qstring.h> +//US #include <qtooltip.h> + +#include <qpushbutton.h> + +//US #include <kaccel.h> +//US #include <kcombobox.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +//US #include <kurlcompletion.h> +//US #include <kurldrag.h> +//US #include <kprotocolinfo.h> + + +#include "kurlrequester.h" + + +class KURLDragPushButton : public QPushButton +{ +public: + KURLDragPushButton( QWidget *parent, const char *name=0 ) + : QPushButton( parent, name ) { +//US setDragEnabled( true ); + } + ~KURLDragPushButton() {} + + void setURL( const KURL& url ) { + m_urls.clear(); + m_urls.append( url ); + } + + /* not needed so far + void setURLs( const KURL::List& urls ) { + m_urls = urls; + } + const KURL::List& urls() const { return m_urls; } + */ + +protected: +/*US + virtual QDragObject *dragObject() { + if ( m_urls.isEmpty() ) + return 0L; + + QDragObject *drag = KURLDrag::newDrag( m_urls, this, "url drag" ); + return drag; + } +*/ +private: + KURL::List m_urls; + +}; + + +/* +************************************************************************* +*/ + +class KURLRequester::KURLRequesterPrivate +{ +public: + KURLRequesterPrivate() { + edit = 0L; +//US combo = 0L; +//US fileDialogMode = KFile::File | KFile::ExistingOnly | KFile::LocalOnly; + } + + void setText( const QString& text ) { +/*US + if ( combo ) + { + if (combo->editable()) + { + combo->setEditText( text ); + } + else + { + combo->insertItem( text ); + combo->setCurrentItem( combo->count()-1 ); + } + } + else +*/ + { + edit->setText( text ); + } + } + + void connectSignals( QObject *receiver ) { + QObject *sender; +/*US if ( combo ) + sender = combo; + else +*/ + sender = edit; + + connect( sender, SIGNAL( textChanged( const QString& )), + receiver, SIGNAL( textChanged( const QString& ))); + connect( sender, SIGNAL( returnPressed() ), + receiver, SIGNAL( returnPressed() )); +//US connect( sender, SIGNAL( returnPressed( const QString& ) ), +//US receiver, SIGNAL( returnPressed( const QString& ) )); + } +/*US + void setCompletionObject( KCompletion *comp ) { + if ( combo ) + combo->setCompletionObject( comp ); + else + edit->setCompletionObject( comp ); + } +*/ + /** + * replaces ~user or $FOO, if necessary + */ + QString url() { + QString txt = /*US combo ? combo->currentText() : */ edit->text(); +/*US KURLCompletion *comp; + if ( combo ) + comp = dynamic_cast<KURLCompletion*>(combo->completionObject()); + else + comp = dynamic_cast<KURLCompletion*>(edit->completionObject()); + + if ( comp ) + return comp->replacedPath( txt ); + else +*/ + return txt; + } + + KLineEdit *edit; +//US KComboBox *combo; + int fileDialogMode; + QString fileDialogFilter; +}; + + +/*US +KURLRequester::KURLRequester( QWidget *editWidget, QWidget *parent, + const char *name ) + : QHBox( parent, name ) +{ + d = new KURLRequesterPrivate; + + // must have this as parent + editWidget->reparent( this, 0, QPoint(0,0) ); +//US d->edit = dynamic_cast<KLineEdit*>( editWidget ); + d->edit = (KLineEdit*)( editWidget ); +//US d->combo = dynamic_cast<KComboBox*>( editWidget ); + + init(); +} +*/ + +KURLRequester::KURLRequester( QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + d = new KURLRequesterPrivate; + init(); +} + + +KURLRequester::KURLRequester( const QString& url, QWidget *parent, + const char *name ) + : QHBox( parent, name ) +{ + d = new KURLRequesterPrivate; + init(); + setURL( url ); +} + + +KURLRequester::~KURLRequester() +{ +//US delete myCompletion; + delete myFileDialog; + delete d; +} + + +void KURLRequester::init() +{ + myFileDialog = 0L; + myShowLocalProt = false; + + if (/*US !d->combo && */ !d->edit ) + d->edit = new KLineEdit( this, "KURLRequester::KLineEdit" ); + + myButton = new KURLDragPushButton( this, "kfile button"); + QIconSet iconSet = SmallIconSet("fileopen"); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + myButton->setIconSet( iconSet ); + myButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); +//US QToolTip::add(myButton, i18n("Open file dialog")); + + connect( myButton, SIGNAL( pressed() ), SLOT( slotUpdateURL() )); + + setSpacing( KDialog::spacingHint() ); + + QWidget *widget = /*US d->combo ? (QWidget*) d->combo : */ (QWidget*) d->edit; + setFocusProxy( widget ); + + d->connectSignals( this ); + connect( myButton, SIGNAL( clicked() ), this, SLOT( slotOpenDialog() )); +/*US + myCompletion = new KURLCompletion(); + d->setCompletionObject( myCompletion ); + + KAccel *accel = new KAccel( this ); + accel->insert( KStdAccel::Open, this, SLOT( slotOpenDialog() )); + accel->readSettings(); +*/ +} + + +void KURLRequester::setURL( const QString& url ) +{ + bool hasLocalPrefix = (url.startsWith("file:")); + + if ( !myShowLocalProt && hasLocalPrefix ) + d->setText( url.mid( 5, url.length()-5 )); + else + d->setText( url ); +} + +void KURLRequester::setCaption( const QString& caption ) +{ +//US fileDialog()->setCaption( caption ); +//US QWidget::setCaption( caption ); +} + +QString KURLRequester::url() const +{ + return d->url(); +} + + +void KURLRequester::slotOpenDialog() +{ + emit openFileDialog( this ); + +//US use our special KFIleDialog instead + KURL u( url() ); + //QString fn = u.url(); + QString fn = d->edit->text(); + fn = KFileDialog::getSaveFileName( fn, "Save backup filename", this ); + + if ( fn == "" ) + return; + + setURL( fn ); + emit urlSelected( d->url() ); +/*US + KFileDialog *dlg = fileDialog(); + if ( !d->url().isEmpty() ) { + KURL u( url() ); + // If we won't be able to list it (e.g. http), then don't try :) + if ( KProtocolInfo::supportsListing( u.protocol() ) ) + dlg->setSelection( u.url() ); + } + + if ( dlg->exec() == QDialog::Accepted ) + { + setURL( dlg->selectedURL().prettyURL() ); + emit urlSelected( d->url() ); + } +*/ + +} + +void KURLRequester::setMode(unsigned int mode) +{ +/*US + Q_ASSERT( (mode & KFile::Files) == 0 ); + d->fileDialogMode = mode; + if ( (mode & KFile::Directory) && !(mode & KFile::File) ) + myCompletion->setMode( KURLCompletion::DirCompletion ); + + if (myFileDialog) + myFileDialog->setMode( d->fileDialogMode ); +*/ +} + +void KURLRequester::setFilter(const QString &filter) +{ +/*US + d->fileDialogFilter = filter; + if (myFileDialog) + myFileDialog->setFilter( d->fileDialogFilter ); +*/ +} + +KFileDialog * KURLRequester::fileDialog() const +{ +/*US + if ( !myFileDialog ) { + QWidget *p = parentWidget(); + myFileDialog = new KFileDialog( QString::null, QString::null, p, + "file dialog", true ); + + myFileDialog->setMode( d->fileDialogMode ); + myFileDialog->setFilter( d->fileDialogFilter ); + } + + return myFileDialog; +*/ + return 0; +} + + +void KURLRequester::setShowLocalProtocol( bool b ) +{ + if ( myShowLocalProt == b ) + return; + + myShowLocalProt = b; + setURL( url() ); +} + +void KURLRequester::clear() +{ + d->setText( QString::null ); +} + +KLineEdit * KURLRequester::lineEdit() const +{ + return d->edit; +} +/*US +KComboBox * KURLRequester::comboBox() const +{ + return d->combo; +} +*/ +void KURLRequester::slotUpdateURL() +{ + // bin compat, myButton is declared as QPushButton +//US KURL u( QDir::currentDirPath() + '/', url() ); + KURL u( url() ); + (static_cast<KURLDragPushButton *>( myButton))->setURL( u ); +} + +QPushButton * KURLRequester::button() const +{ + return myButton; +} +/*US +KEditListBox::CustomEditor KURLRequester::customEditor() +{ + setSizePolicy(QSizePolicy( QSizePolicy::Preferred, + QSizePolicy::Fixed)); + + KLineEdit *edit = d->edit; + if ( !edit && d->combo ) + edit = dynamic_cast<KLineEdit*>( d->combo->lineEdit() ); + +#ifndef NDEBUG + if ( !edit ) + kdWarning() << "KURLRequester's lineedit is not a KLineEdit!??\n"; +#endif + + KEditListBox::CustomEditor editor( this, edit ); + return editor; +} +*/ +void KURLRequester::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/*US +KURLComboRequester::KURLComboRequester( QWidget *parent, + const char *name ) + : KURLRequester( new KComboBox(false), parent, name) +{ +} +*/ + +//US #include "kurlrequester.moc" diff --git a/microkde/kio/kfile/kurlrequester.h b/microkde/kio/kfile/kurlrequester.h new file mode 100644 index 0000000..3253dd5 --- a/dev/null +++ b/microkde/kio/kfile/kurlrequester.h @@ -0,0 +1,269 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> + + library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#ifndef KURLREQUESTER_H +#define KURLREQUESTER_H + +#include <qhbox.h> + +#include <keditlistbox.h> +//US #include <kfile.h> +//US #include <kpushbutton.h> +#include <kurl.h> + +//US class KComboBox; + +class KFileDialog; +class KLineEdit; +//US class KURLCompletion; +class KURLDragPushButton; + +class QPushButton; +class QString; +class QTimer; + +/** + * This class is a widget showing a lineedit and a button, which invokes a + * filedialog. File name completion is available in the lineedit. + * + * The defaults for the filedialog are to ask for one existing local file, i.e. + * KFileDialog::setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly ) + * The default filter is "*", i.e. show all files, and the start directory is + * the current working directory, or the last directory where a file has been + * selected. + * + * You can change this behavior by using @ref setMode() or @ref setFilter(). + * + * @short A widget to request a filename/url from the user + * @author Carsten Pfeiffer <pfeiffer@kde.org> + */ +class KURLRequester : public QHBox +{ + Q_OBJECT + Q_PROPERTY( QString url READ url WRITE setURL ) + +public: + /** + * Constructs a KURLRequester widget. + */ + KURLRequester( QWidget *parent=0, const char *name=0 ); + + /** + * Constructs a KURLRequester widget with the initial URL @p url. + */ + KURLRequester( const QString& url, QWidget *parent=0, const char *name=0 ); + + /** + * Special constructor, which creates a KURLRequester widget with a custom + * edit-widget. The edit-widget can be either a KComboBox or a KLineEdit + * (or inherited thereof). Note: for geometry management reasons, the + * edit-widget is reparented to have the KURLRequester as parent. + * @param modal specifies whether the filedialog should be opened as modal + * or not. + */ +//US KURLRequester( QWidget *editWidget, QWidget *parent, const char *name=0 ); + /** + * Destructs the KURLRequester. + */ + ~KURLRequester(); + + /** + * @returns the current url in the lineedit. May be malformed, if the user + * entered something weird. ~user or environment variables are substituted + * for local files. + */ + QString url() const; + + /** + * Enables/disables showing file:/ in the lineedit, when a local file has + * been selected in the filedialog or was set via @ref setURL(). + * Default is false, not showing file:/ + * @see #showLocalProtocol + */ + void setShowLocalProtocol( bool b ); + + /** + * Sets the mode of the file dialog. + * Note: you can only select one file with the filedialog, + * so KFile::Files doesn't make much sense. + * @see KFileDialog::setMode() + */ + void setMode( unsigned int m ); + + /** + * Sets the filter for the file dialog. + * @see KFileDialog::setFilter() + */ + void setFilter( const QString& filter ); + + /** + * @returns whether local files will be prefixed with file:/ in the + * lineedit + * @see #setShowLocalProtocol + */ + bool showLocalProtocol() const { return myShowLocalProt; } + + /** + * @returns a pointer to the filedialog + * You can use this to customize the dialog, e.g. to specify a filter. + * Never returns 0L. + */ + virtual KFileDialog * fileDialog() const; + + /** + * @returns a pointer to the lineedit, either the default one, or the + * special one, if you used the special constructor. + * + * It is provided so that you can e.g. set an own completion object + * (e.g. @ref KShellCompletion) into it. + */ + KLineEdit * lineEdit() const; + + /** + * @returns a pointer to the combobox, in case you have set one using the + * special constructor. Returns 0L otherwise. + */ +//US KComboBox * comboBox() const; + + /** + * @returns a pointer to the pushbutton. It is provided so that you can + * specify an own pixmap or a text, if you really need to. + */ + QPushButton * button() const; + + /** + * @returns the KURLCompletion object used in the lineedit/combobox. + */ +//US KURLCompletion *completionObject() const { return myCompletion; } + + /** + * @returns an object, suitable for use with KEditListBox. It allows you + * to put this KURLRequester into a KEditListBox. + * Basically, do it like this: + * <pre> + * KURLRequester *req = new KURLRequester( someWidget ); + * [...] + * KEditListBox *editListBox = new KEditListBox( i18n("Some Title"), req->customEditor(), someWidget ); + * </pre> + * @since 3.1 + */ +//US KEditListBox::CustomEditor customEditor(); + +public slots: + /** + * Sets the url in the lineedit to @p url. Depending on the state of + * @ref showLocalProtocol(), file:/ on local files will be shown or not. + * @since 3.1 + */ + void setURL( const QString& url ); + + /** + * @reimp + * Sets the caption of the file dialog. + * @since 3.1 + */ + virtual void setCaption( const QString& caption ); + + /** + * Clears the lineedit/combobox. + */ + void clear(); + +signals: + // forwards from LineEdit + /** + * Emitted when the text in the lineedit changes. + * The parameter contains the contents of the lineedit. + * @since 3.1 + */ + void textChanged( const QString& ); + + /** + * Emitted when return or enter was pressed in the lineedit. + */ + void returnPressed(); + + /** + * Emitted when return or enter was pressed in the lineedit. + * The parameter contains the contents of the lineedit. + */ + void returnPressed( const QString& ); + + /** + * Emitted before the filedialog is going to open. Connect + * to this signal to "configure" the filedialog, e.g. set the + * filefilter, the mode, a preview-widget, etc. It's usually + * not necessary to set a URL for the filedialog, as it will + * get set properly from the editfield contents. + * + * If you use multiple KURLRequesters, you can connect all of them + * to the same slot and use the given KURLRequester pointer to know + * which one is going to open. + */ + void openFileDialog( KURLRequester * ); + + /** + * Emitted when the user changed the URL via the file dialog. + * The parameter contains the contents of the lineedit. + */ + void urlSelected( const QString& ); + +protected: + void init(); + +//US KURLCompletion * myCompletion; + + +private: + KURLDragPushButton * myButton; + bool myShowLocalProt; + mutable KFileDialog * myFileDialog; + + +protected slots: + /** + * Called when the button is pressed to open the filedialog. + * Also called when @ref KStdAccel::Open (default is Ctrl-O) is pressed. + */ + void slotOpenDialog(); + +private slots: + void slotUpdateURL(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KURLRequesterPrivate; + KURLRequesterPrivate *d; +}; +/*US +class KURLComboRequester : public KURLRequester // For use in Qt Designer +{ + Q_OBJECT +public: +*/ + /** + * Constructs a KURLRequester widget with a combobox. + */ +/*US + KURLComboRequester( QWidget *parent=0, const char *name=0 ); +}; +*/ + +#endif // KURLREQUESTER_H diff --git a/microkde/klineedit.h b/microkde/klineedit.h new file mode 100644 index 0000000..65e2f59 --- a/dev/null +++ b/microkde/klineedit.h @@ -0,0 +1,24 @@ +#ifndef MINIKDE_KLINEEDIT_H +#define MINIKDE_KLINEEDIT_H + +#include <qlineedit.h> + +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + + +class KLineEdit : public QLineEdit +{ + public: + KLineEdit( QWidget *parent=0, const char *name=0 ) : + QLineEdit( parent, name ) { +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( this, QPEApplication::RightOnHold ); +#endif +} + + void setTrapReturnKey( bool ) {} +}; + +#endif diff --git a/microkde/klineeditdlg.h b/microkde/klineeditdlg.h new file mode 100644 index 0000000..68e9252 --- a/dev/null +++ b/microkde/klineeditdlg.h @@ -0,0 +1,34 @@ +#ifndef MICROKDE_KLINEEDITDLG_H +#define MICROKDE_KLINEEDITDLG_H + +#include "kdialogbase.h" +#include <klineedit.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qdialog.h> +#include <qpushbutton.h> + +class KLineEditDlg : public QDialog +{ + public: + KLineEditDlg( const QString & text, const QString & editText, QWidget *parent ) : + QDialog( parent,"lineedit", true ) { + QLabel* lab = new QLabel( text, this ); + mEdit = new KLineEdit( this ); + QVBoxLayout* vl = new QVBoxLayout( this ); + vl->setSpacing(5); + vl->setMargin(7); + vl->addWidget( lab ); + vl->addWidget( mEdit ); + mEdit->setText( editText ); + QPushButton * p = new QPushButton (" OK ", this ); + vl->addWidget( p ); + connect( p, SIGNAL ( clicked () ), this , SLOT (accept() ) ); + } + + QString text() { return mEdit->text(); } + private: + KLineEdit* mEdit; +}; + +#endif diff --git a/microkde/kmessagebox.cpp b/microkde/kmessagebox.cpp new file mode 100644 index 0000000..f06708a --- a/dev/null +++ b/microkde/kmessagebox.cpp @@ -0,0 +1,90 @@ +#include "kmessagebox.h" +#include "klocale.h" + +#include <qmessagebox.h> + +void KMessageBox::sorry( QWidget *parent, + const QString &text, + const QString &caption, bool ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Sorry"); + } + + QMessageBox::warning( parent, cap, text ); +} + +int KMessageBox::warningContinueCancel( QWidget *parent, + const QString &text, + const QString &caption, + const QString &buttonContinue, + const QString &dontAskAgainName, + bool notify ) +{ + QString cap = caption; + + int result = QMessageBox::warning( parent, cap, text, buttonContinue, + dontAskAgainName); + + if ( result == 0 ) return KMessageBox::Continue; + return KMessageBox::Cancel; +} + +int KMessageBox::warningYesNoCancel( QWidget *parent, + const QString &text, + const QString &caption, + const QString &buttonYes, + const QString &buttonNo ) +{ + QString cap = caption; + + int result = QMessageBox::warning( parent, cap, text,buttonYes ,buttonNo, + i18n("Cancel") ); + + if ( result == 0 ) return KMessageBox::Yes; + else if ( result == 1 ) return KMessageBox::No; + return KMessageBox::Cancel; +} + +int KMessageBox::questionYesNo(QWidget *parent, + const QString &text, + const QString &caption) +{ + QString cap = caption; + + int result = QMessageBox::warning( parent, cap, text, i18n("Yes"), + i18n("No") ); + + if ( result == 0 ) return KMessageBox::Yes; + else return KMessageBox::No; +} + +void KMessageBox::error( QWidget *parent, + const QString &text, + const QString &caption, bool notify ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Error"); + } + + QMessageBox::critical( parent, cap, text ); +} + +void KMessageBox::information( QWidget *parent, + const QString &text, + const QString &caption, + const QString &, + bool ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Information"); + } + + QMessageBox::information( parent, cap, text ); +} diff --git a/microkde/kmessagebox.h b/microkde/kmessagebox.h new file mode 100644 index 0000000..01d83b1 --- a/dev/null +++ b/microkde/kmessagebox.h @@ -0,0 +1,47 @@ +#ifndef MINIKDE_KMESSAGEBOX_H +#define MINIKDE_KMESSAGEBOX_H + +#include <qstring.h> + +#include "klocale.h" +class QWidget; + +class KMessageBox +{ + public: + enum { Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 }; + + static void sorry(QWidget *parent, + const QString &text, + const QString &caption = QString::null, bool notify=true); + + static int warningContinueCancel(QWidget *parent, + const QString &text, + const QString &caption = i18n("Warning"), + const QString &buttonContinue =i18n("Continue"), + const QString &dontAskAgainName = i18n("Cancel"), + bool notify=true ); + + static int warningYesNoCancel(QWidget *parent, + const QString &text, + const QString &caption = i18n("Warning"), + const QString &buttonYes = i18n("Yes"), + const QString &buttonNo = i18n("No")); + + static int questionYesNo(QWidget *parent, + const QString &text, + const QString &caption = i18n("Question")); + + static void error(QWidget *parent, + const QString &text, + const QString &caption = i18n("Error"), bool notify=true); + + static void information(QWidget *parent, + const QString &text, + const QString &caption = i18n("Information"), + const QString &dontShowAgainName = QString::null, + bool notify=true); +}; + + +#endif diff --git a/microkde/knotifyclient.h b/microkde/knotifyclient.h new file mode 100644 index 0000000..118026a --- a/dev/null +++ b/microkde/knotifyclient.h @@ -0,0 +1,14 @@ +#ifndef MINIKDE_KNOTIFYCLIENT_H +#define MINIKDE_KNOTIFYCLIENT_H + +#include <qstring.h> + +class KNotifyClient +{ + public: + + static void beep() {} + static void beep( const QString & ) {} +}; + +#endif diff --git a/microkde/kprinter.h b/microkde/kprinter.h new file mode 100644 index 0000000..b99d689 --- a/dev/null +++ b/microkde/kprinter.h @@ -0,0 +1,8 @@ +#ifndef MINIKDE_KPRINTER_H +#define MINIKDE_KPRINTER_H + +#include <qprinter.h> + +#define KPrinter QPrinter + +#endif diff --git a/microkde/kprocess.cpp b/microkde/kprocess.cpp new file mode 100644 index 0000000..665d0bd --- a/dev/null +++ b/microkde/kprocess.cpp @@ -0,0 +1,19 @@ +#include "kprocess.h" + +void KProcess::clearArguments() +{ +// mProcess.clearArguments(); +} + +KProcess & KProcess::operator<<( const QString &arg ) +{ +// mProcess.addArgument( arg ); + + return *this; +} + +bool KProcess::start( KProcess::RunMode ) +{ +// return mProcess.start(); + return false; +} diff --git a/microkde/kprocess.h b/microkde/kprocess.h new file mode 100644 index 0000000..dffe96d --- a/dev/null +++ b/microkde/kprocess.h @@ -0,0 +1,22 @@ +#ifndef MINIKDE_KPROCESS_H +#define MINIKDE_KPROCESS_H + +#include <qobject.h> +//#include <qpe/qprocess.h> + +class KProcess : public QObject +{ + public: + enum RunMode { DontCare, NotifyOnExit, Block }; + + void clearArguments(); + + KProcess & operator<<( const QString & ); + + bool start( RunMode mode = DontCare ); + + private: +// QProcess mProcess; +}; + +#endif diff --git a/microkde/kresources/configdialog.cpp b/microkde/kresources/configdialog.cpp new file mode 100644 index 0000000..48d9137 --- a/dev/null +++ b/microkde/kresources/configdialog.cpp @@ -0,0 +1,137 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <klocale.h> +#include <kglobal.h> +#include <kmessagebox.h> + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> + +#include <qcheckbox.h> + +#include <kbuttonbox.h> +#include <kdialog.h> +#include <klineedit.h> + +#include "factory.h" +#include "configwidget.h" +#include "configdialog.h" + +using namespace KRES; + +ConfigDialog::ConfigDialog( QWidget *parent, const QString& resourceFamily, + /*const QString& type,*/ Resource* resource, /*KConfig *config, */const char *name ) + : KDialogBase( parent, name, true, i18n( "Resource Configuration" ), + Ok|Cancel, Ok, true )/*, mConfig( config )*/, mResource( resource ) +{ + Factory *factory = Factory::self( resourceFamily ); + +//US resize( 250, 240 ); + resize( KMIN(KGlobal::getDesktopWidth(), 250), KMIN(KGlobal::getDesktopHeight(), 240)); + +//US QFrame *main = makeMainWidget(); + QFrame *main = plainPage(); + + QVBoxLayout *mainLayout = new QVBoxLayout( main, 0, spacingHint() ); + + QGroupBox *generalGroupBox = new QGroupBox( 2, Qt::Horizontal, main ); + generalGroupBox->layout()->setSpacing( spacingHint() ); + generalGroupBox->setTitle( i18n( "General Settings" ) ); + + new QLabel( i18n( "Name:" ), generalGroupBox ); + + mName = new KLineEdit( generalGroupBox ); + + mReadOnly = new QCheckBox( i18n( "Read-only" ), generalGroupBox ); + + mName->setText( mResource->resourceName() ); + mReadOnly->setChecked( mResource->readOnly() ); + + mainLayout->addWidget( generalGroupBox ); + + QGroupBox *resourceGroupBox = new QGroupBox( 2, Qt::Horizontal, main ); + resourceGroupBox->layout()->setSpacing( spacingHint()); + resourceGroupBox->setTitle( i18n( "%1 Resource Settings" ) + .arg( factory->typeName( resource->type() ) ) ); + mainLayout->addWidget( resourceGroupBox ); + + mainLayout->addStretch(); + + mConfigWidget = factory->configWidget( resource->type(), resourceGroupBox ); + if ( mConfigWidget ) { + mConfigWidget->setInEditMode( false ); + mConfigWidget->loadSettings( mResource ); + mConfigWidget->show(); + connect( mConfigWidget, SIGNAL( setReadOnly( bool ) ), + SLOT( setReadOnly( bool ) ) ); + } + + connect( mName, SIGNAL( textChanged(const QString &)), + SLOT( slotNameChanged(const QString &))); + + slotNameChanged( mName->text() ); + +//US setMinimumSize( 400, 250 ); + setMinimumSize( KMIN(KGlobal::getDesktopWidth(), 400), KMIN(KGlobal::getDesktopHeight(), 250)); + +} + +void ConfigDialog::setInEditMode( bool value ) +{ + if ( mConfigWidget ) + mConfigWidget->setInEditMode( value ); +} + +void ConfigDialog::slotNameChanged( const QString &text) +{ + enableButtonOK( !text.isEmpty() ); +} + +void ConfigDialog::setReadOnly( bool value ) +{ + mReadOnly->setChecked( value ); +} + +void ConfigDialog::accept() +{ + if ( mName->text().isEmpty() ) { + KMessageBox::sorry( this, i18n( "Please enter a resource name" ) ); + return; + } + + mResource->setResourceName( mName->text() ); + mResource->setReadOnly( mReadOnly->isChecked() ); + + if ( mConfigWidget ) { + // First save generic information + // Also save setting of specific resource type + mConfigWidget->saveSettings( mResource ); + } + + KDialog::accept(); +} + +//US #include "configdialog.moc" diff --git a/microkde/kresources/configdialog.h b/microkde/kresources/configdialog.h new file mode 100644 index 0000000..6acc5d9 --- a/dev/null +++ b/microkde/kresources/configdialog.h @@ -0,0 +1,60 @@ +/* + This file is part of libkresources. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_CONFIGDIALOG_H +#define KRESOURCES_CONFIGDIALOG_H + +#include <kdialogbase.h> + +class KLineEdit; +class QCheckBox; +class KButtonBox; + +namespace KRES { + class Resource; + class ConfigWidget; + +class ConfigDialog : public KDialogBase +{ + Q_OBJECT + public: + // Resource=0: create new resource + ConfigDialog( QWidget *parent, const QString& resourceFamily, + Resource* resource, const char *name = 0); + + void setInEditMode( bool value ); + + protected slots: + void accept(); + void setReadOnly( bool value ); + void slotNameChanged( const QString &text); + + private: + ConfigWidget *mConfigWidget; + Resource* mResource; + + KLineEdit *mName; + QCheckBox *mReadOnly; +}; + +} + +#endif diff --git a/microkde/kresources/configpage.cpp b/microkde/kresources/configpage.cpp new file mode 100644 index 0000000..0f1469d --- a/dev/null +++ b/microkde/kresources/configpage.cpp @@ -0,0 +1,507 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qgroupbox.h> +#include <qinputdialog.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <kapplication.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kurlrequester.h> +#include <klistview.h> +#include <kbuttonbox.h> +//US #include <ktrader.h> + +#include "resource.h" +#include "configdialog.h" + +#include "configpage.h" + +//US +#include <qpushbutton.h> +#include <qfile.h> +#include <kglobal.h> + +using namespace KRES; + +class ConfigViewItem : public QCheckListItem +{ + public: + ConfigViewItem( QListView *parent, Resource* resource ) : + QCheckListItem( parent, resource->resourceName(), CheckBox ), + mResource( resource ), + mIsStandard( false ) + { + setText( 1, mResource->type() ); + setOn( mResource->isActive() ); + } + + void setStandard( bool value ) + { + setText( 2, ( value ? i18n( "Yes" ) : QString::null ) ); + mIsStandard = value; + } + + bool standard() const { return mIsStandard; } + bool readOnly() const { return mResource->readOnly(); } + + Resource *resource() { return mResource; } + + private: + Resource* mResource; + + bool mIsStandard; +}; + +ConfigPage::ConfigPage( QWidget *parent, const char *name ) + : QWidget( parent, name ), + mCurrentManager( 0 ), + mCurrentConfig( 0 ) +{ + setCaption( i18n( "Resource Configuration" ) ); + + QVBoxLayout *mainLayout = new QVBoxLayout( this ); + + QGroupBox *groupBox = new QGroupBox( i18n( "Resources" ), this ); + groupBox->setColumnLayout(0, Qt::Vertical ); + groupBox->layout()->setSpacing( 6 ); + groupBox->layout()->setMargin( 11 ); + QGridLayout *groupBoxLayout = new QGridLayout( groupBox->layout(), 2, 2 ); + +//US mFamilyCombo = new KComboBox( false, groupBox ); + mFamilyCombo = new KComboBox( groupBox ); + groupBoxLayout->addMultiCellWidget( mFamilyCombo, 0, 0, 0, 1 ); + + mListView = new KListView( groupBox ); + mListView->setAllColumnsShowFocus( true ); + mListView->addColumn( i18n( "Name" ) ); + mListView->addColumn( i18n( "Type" ) ); + mListView->addColumn( i18n( "Standard" ) ); + + groupBoxLayout->addWidget( mListView, 1, 0 ); + + KButtonBox *buttonBox = new KButtonBox( groupBox, Vertical ); + mAddButton = buttonBox->addButton( i18n( "&Add..." ), this, SLOT(slotAdd()) ); + mRemoveButton = buttonBox->addButton( i18n( "&Remove" ), this, SLOT(slotRemove()) ); + mRemoveButton->setEnabled( false ); + mEditButton = buttonBox->addButton( i18n( "&Edit..." ), this, SLOT(slotEdit()) ); + mEditButton->setEnabled( false ); + mStandardButton = buttonBox->addButton( i18n( "&Use as Standard" ), this, SLOT(slotStandard()) ); + mStandardButton->setEnabled( false ); + buttonBox->layout(); + + groupBoxLayout->addWidget( buttonBox, 1, 1 ); + + mainLayout->addWidget( groupBox ); + + connect( mFamilyCombo, SIGNAL( activated( int ) ), + SLOT( slotFamilyChanged( int ) ) ); + connect( mListView, SIGNAL( selectionChanged() ), + SLOT( slotSelectionChanged() ) ); + connect( mListView, SIGNAL( clicked( QListViewItem * ) ), + SLOT( slotItemClicked( QListViewItem * ) ) ); + + mLastItem = 0; + +//US mConfig = new KConfig( "kcmkresourcesrc" ); + mConfig = new KConfig( locateLocal( "config", "kcmkresourcesrc") ); + mConfig->setGroup( "General" ); + + load(); +} + +ConfigPage::~ConfigPage() +{ + QValueList<ResourcePageInfo>::Iterator it; + for ( it = mInfoMap.begin(); it != mInfoMap.end(); ++it ) { + (*it).mManager->removeListener( this ); + delete (*it).mManager; + delete (*it).mConfig; + } + + mConfig->writeEntry( "CurrentFamily", mFamilyCombo->currentItem() ); + delete mConfig; + mConfig = 0; +} + +void ConfigPage::load() +{ + kdDebug(5650) << "ConfigPage::load()" << endl; + + mListView->clear(); + +//US we remove the dynamic pluginloader, and set the one family we need (contact) manually. + +//US KTrader::OfferList plugins = KTrader::self()->query( "KResources/Plugin" ); +//US KTrader::OfferList::ConstIterator it; +//US for ( it = plugins.begin(); it != plugins.end(); ++it ) { +//US QVariant tmp = (*it)->property( "X-KDE-ResourceFamily" ); +//US QString family = tmp.toString(); + + QString family = "contact"; + if ( !family.isEmpty() ) { + if ( !mFamilyMap.contains( family ) ) { + mCurrentManager = new Manager<Resource>( family ); + if ( mCurrentManager ) { + mFamilyMap.append( family ); + mCurrentManager->addListener( this ); + + ResourcePageInfo info; + info.mManager = mCurrentManager; + QString configDir = KGlobal::dirs()->saveLocation( "config" ); + //QString configDir = KStandardDirs::appDir() + "/config"; + if ( family == "contact" && QFile::exists( configDir + "/kabcrc" ) ) { + info.mConfig = new KConfig( locateLocal( "config", "kabcrc" ) ); + } else if ( family == "calendar" && QFile::exists( configDir + "/kcalrc" ) ) { + info.mConfig = new KConfig( locateLocal( "config", "kcalrc" ) ); + } else { + QString configFile = locateLocal( "config", QString( "kresources/%1/stdrc" ).arg( family ) ); + info.mConfig = new KConfig( configFile ); + } + info.mManager->readConfig( info.mConfig ); + + mInfoMap.append( info ); + } + } + } +//US } + mCurrentManager = 0; + + mFamilyCombo->insertStringList( mFamilyMap ); + + int currentFamily = mConfig->readNumEntry( "CurrentFamily", 0 ); + mFamilyCombo->setCurrentItem( currentFamily ); + slotFamilyChanged( currentFamily ); +} + +void ConfigPage::save() +{ + saveResourceSettings(); + + QValueList<ResourcePageInfo>::Iterator it; + for ( it = mInfoMap.begin(); it != mInfoMap.end(); ++it ) + (*it).mManager->writeConfig( (*it).mConfig ); + + emit changed( false ); +} + +void ConfigPage::defaults() +{ +} + +void ConfigPage::slotFamilyChanged( int pos ) +{ + if ( pos < 0 || pos >= (int)mFamilyMap.count() ) + return; + + saveResourceSettings(); + + mFamily = mFamilyMap[ pos ]; + +//US qDebug("ConfigPage::slotFamilyChanged 4 family=%s", mFamily.latin1()); + + mCurrentManager = mInfoMap[ pos ].mManager; + mCurrentConfig = mInfoMap[ pos ].mConfig; + + if ( !mCurrentManager ) + kdDebug(5650) << "ERROR: cannot create ResourceManager<Resource>( mFamily )" << endl; + + mListView->clear(); + + if ( mCurrentManager->isEmpty() ) { +//US qDebug("ConfigPage::slotFamilyChanged 4.1 mCurrentManager=%ul", mCurrentManager ); + + defaults(); + } + + Resource *standardResource = mCurrentManager->standardResource(); + +//US qDebug("ConfigPage::slotFamilyChanged 4.4 resourcename=%s", standardResource->resourceName().latin1()); + + + Manager<Resource>::Iterator it; + for ( it = mCurrentManager->begin(); it != mCurrentManager->end(); ++it ) { + ConfigViewItem *item = new ConfigViewItem( mListView, *it ); + if ( *it == standardResource ) + item->setStandard( true ); + } + + if ( mListView->childCount() == 0 ) { +//US qDebug("ConfigPage::slotFamilyChanged 4.5 "); + + defaults(); + emit changed( true ); + mCurrentManager->writeConfig( mCurrentConfig ); + } else { +//US qDebug("ConfigPage::slotFamilyChanged 4.6 "); + + if ( !standardResource ) { + KMessageBox::sorry( this, i18n( "There is no standard resource! Please select one." ) ); + +//US qDebug("ConfigPage::slotFamilyChanged 4.7" ); + + } + + emit changed( false ); + } +} + +void ConfigPage::slotAdd() +{ + if ( !mCurrentManager ) + return; + + QStringList types = mCurrentManager->resourceTypeNames(); + QStringList descs = mCurrentManager->resourceTypeDescriptions(); + bool ok = false; + QString desc = QInputDialog::getItem( i18n( "Resource Configuration" ), + i18n( "Please select type of the new resource:" ), descs, 0, + false, &ok, this ); + if ( !ok ) + return; + + QString type = types[ descs.findIndex( desc ) ]; + + // Create new resource + Resource *resource = mCurrentManager->createResource( type ); + if ( !resource ) { + KMessageBox::error( this, i18n("Unable to create resource of type '%1'.") + .arg( type ) ); + return; + } + + resource->setResourceName( type + "-resource" ); + + ConfigDialog dlg( this, mFamily, resource, "KRES::ConfigDialog" ); + + if ( dlg.exec() ) { + mCurrentManager->add( resource ); + + ConfigViewItem *item = new ConfigViewItem( mListView, resource ); + + mLastItem = item; + + // if there are only read-only resources we'll set this resource + // as standard resource + if ( !resource->readOnly() ) { + bool onlyReadOnly = true; + QListViewItem *it = mListView->firstChild(); + while ( it != 0 ) { + ConfigViewItem *confIt = static_cast<ConfigViewItem*>( it ); + if ( !confIt->readOnly() && confIt != item ) + onlyReadOnly = false; + + it = it->itemBelow(); + } + + if ( onlyReadOnly ) + item->setStandard( true ); + } + + emit changed( true ); + } else { + delete resource; + resource = 0; + } +} + +void ConfigPage::slotRemove() +{ + if ( !mCurrentManager ) + return; + + QListViewItem *item = mListView->currentItem(); + ConfigViewItem *confItem = static_cast<ConfigViewItem*>( item ); + + if ( !confItem ) + return; + + if ( confItem->standard() ) { + KMessageBox::sorry( this, i18n( "You cannot remove your standard resource!\n Please select a new standard resource first." ) ); + return; + } + + mCurrentManager->remove( confItem->resource() ); + + if ( item == mLastItem ) + mLastItem = 0; + + mListView->takeItem( item ); + delete item; + + emit changed( true ); +} + +void ConfigPage::slotEdit() +{ + if ( !mCurrentManager ) + return; + + QListViewItem *item = mListView->currentItem(); + ConfigViewItem *configItem = static_cast<ConfigViewItem*>( item ); + if ( !configItem ) + return; + + Resource *resource = configItem->resource(); + + ConfigDialog dlg( this, mFamily, resource, "KRES::ConfigDialog" ); + + if ( dlg.exec() ) { + configItem->setText( 0, resource->resourceName() ); + configItem->setText( 1, resource->type() ); + + if ( configItem->standard() && configItem->readOnly() ) { + KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard!" ) ); + configItem->setStandard( false ); + } + + mCurrentManager->resourceChanged( resource ); + emit changed( true ); + } +} + +void ConfigPage::slotStandard() +{ + if ( !mCurrentManager ) + return; + + ConfigViewItem *item = static_cast<ConfigViewItem*>( mListView->currentItem() ); + if ( !item ) + return; + + if ( item->readOnly() ) { + KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard!" ) ); + return; + } + + if ( !item->isOn() ) { + KMessageBox::sorry( this, i18n( "You cannot use an inactive resource as standard!" ) ); + return; + } + + QListViewItem *it = mListView->firstChild(); + while ( it != 0 ) { + ConfigViewItem *configItem = static_cast<ConfigViewItem*>( it ); + if ( configItem->standard() ) + configItem->setStandard( false ); + it = it->itemBelow(); + } + + item->setStandard( true ); + mCurrentManager->setStandardResource( item->resource() ); + emit changed( true ); + +} + +void ConfigPage::slotSelectionChanged() +{ + bool state = ( mListView->currentItem() != 0 ); + + mRemoveButton->setEnabled( state ); + mEditButton->setEnabled( state ); + mStandardButton->setEnabled( state ); +} + +void ConfigPage::resourceAdded( Resource* resource ) +{ + qDebug("ConfigPage::resourceAdded : %s", resource->resourceName().latin1()); + kdDebug(5650) << "ConfigPage::resourceAdded( " << resource->resourceName() << " )" << endl; + ConfigViewItem *item = new ConfigViewItem( mListView, resource ); + + // FIXME: this sucks. This should be in the config file, + // or application-dependent, in which case it's always Off + item->setOn( false ); + + mLastItem = item; + + emit changed( true ); +} + +void ConfigPage::resourceModified( Resource* resource ) +{ + qDebug("ConfigPage::resourceModified : %s", resource->resourceName().latin1()); + kdDebug(5650) << "ConfigPage::resourceModified( " << resource->resourceName() << " )" << endl; +} + +void ConfigPage::resourceDeleted( Resource* resource ) +{ + qDebug("ConfigPage::resourceDeleted : %s", resource->resourceName().latin1()); + kdDebug(5650) << "ConfigPage::resourceDeleted( " << resource->resourceName() << " )" << endl; +} + +void ConfigPage::slotItemClicked( QListViewItem *item ) +{ + ConfigViewItem *configItem = static_cast<ConfigViewItem *>( item ); + if ( !configItem ) return; + + if ( configItem->standard() && !configItem->isOn() ) { + KMessageBox::sorry( this, i18n( "You cannot deactivate the standard resource. Choose another standard resource first." ) ); + configItem->setOn( true ); + return; + } + + if ( configItem->isOn() != configItem->resource()->isActive() ) { + emit changed( true ); + } +} + +void ConfigPage::saveResourceSettings() +{ + qDebug("ConfigPage::saveResourceSettings() begin"); + + if ( mCurrentManager ) { + + QListViewItem *item = mListView->firstChild(); + while ( item ) { + ConfigViewItem *configItem = static_cast<ConfigViewItem*>( item ); + + // check if standard resource + if ( configItem->standard() && !configItem->readOnly() && + configItem->isOn() ) { + + mCurrentManager->setStandardResource( configItem->resource() ); + } + + // check if active or passive resource + configItem->resource()->setActive( configItem->isOn() ); + + item = item->nextSibling(); + } + mCurrentManager->writeConfig( mCurrentConfig ); + + if ( !mCurrentManager->standardResource() ) + KMessageBox::sorry( this, i18n( "There is no valid standard resource! Please select one which is neither read-only nor inactive." ) ); + } + + qDebug("ConfigPage::saveResourceSettings() end"); + +} + +//US #include "configpage.moc" + diff --git a/microkde/kresources/configpage.h b/microkde/kresources/configpage.h new file mode 100644 index 0000000..492ea54 --- a/dev/null +++ b/microkde/kresources/configpage.h @@ -0,0 +1,103 @@ +/* + This file is part of libkresources. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#ifndef KRESOURCES_CONFIGPAGE_H +#define KRESOURCES_CONFIGPAGE_H + +#include <qstringlist.h> +#include <qwidget.h> + +#include "manager.h" + +class KComboBox; +class KListView; + +class QListViewItem; +class QPushButton; + + +namespace KRES { + +class ResourcePageInfo +{ + public: + Manager<Resource> *mManager; + KConfig *mConfig; +}; + +class Resource; + +class ConfigPage : public QWidget, public ManagerListener<Resource> +{ + Q_OBJECT + + public: + ConfigPage( QWidget *parent = 0, const char *name = 0 ); + virtual ~ConfigPage(); + + void load(); + void save(); + virtual void defaults(); + + public slots: + void slotFamilyChanged( int ); + void slotAdd(); + void slotRemove(); + void slotEdit(); + void slotStandard(); + void slotSelectionChanged(); + + // From ManagerListener<Resource> + public: + virtual void resourceAdded( Resource* resource ); + virtual void resourceModified( Resource* resource ); + virtual void resourceDeleted( Resource* resource ); + + protected slots: + void slotItemClicked( QListViewItem * ); + + signals: + void changed( bool ); + + private: + void saveResourceSettings(); + + Manager<Resource>* mCurrentManager; + KConfig* mCurrentConfig; + KConfig* mConfig; + QString mFamily; + QStringList mFamilyMap; + QValueList<ResourcePageInfo> mInfoMap; + + KComboBox* mFamilyCombo; + KListView* mListView; + QPushButton* mAddButton; + QPushButton* mRemoveButton; + QPushButton* mEditButton; + QPushButton* mStandardButton; + + QListViewItem* mLastItem; +}; + +} + +#endif diff --git a/microkde/kresources/configwidget.cpp b/microkde/kresources/configwidget.cpp new file mode 100644 index 0000000..c42cbd4 --- a/dev/null +++ b/microkde/kresources/configwidget.cpp @@ -0,0 +1,45 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "configwidget.h" + +using namespace KRES; + +ConfigWidget::ConfigWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ +} + +void ConfigWidget::setInEditMode( bool ) +{ +} + +void ConfigWidget::loadSettings( Resource * ) +{ +} + +void ConfigWidget::saveSettings( Resource * ) +{ +} + +//US #include "configwidget.moc" diff --git a/microkde/kresources/configwidget.h b/microkde/kresources/configwidget.h new file mode 100644 index 0000000..04dd696 --- a/dev/null +++ b/microkde/kresources/configwidget.h @@ -0,0 +1,59 @@ +/* + This file is part of libkresources. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_CONFIGWIDGET_H +#define KRESOURCES_CONFIGWIDGET_H + +#include <qwidget.h> + +#include <kconfig.h> + +#include "resource.h" + +namespace KRES { + +class ConfigWidget : public QWidget +{ + Q_OBJECT + +public: + ConfigWidget( QWidget *parent = 0, const char *name = 0 ); + + /** + Sets the widget to 'edit' mode. Reimplement this method if you are + interested in the mode change (to disable some GUI element for + example). By default the widget is in 'create new' mode. + */ + virtual void setInEditMode( bool value ); + +public slots: + virtual void loadSettings( Resource *resource ); + virtual void saveSettings( Resource *resource ); + +signals: + void setReadOnly( bool value ); + +protected: + Resource* mResource; +}; + +} +#endif diff --git a/microkde/kresources/factory.cpp b/microkde/kresources/factory.cpp new file mode 100644 index 0000000..709cd4a --- a/dev/null +++ b/microkde/kresources/factory.cpp @@ -0,0 +1,216 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <klocale.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kstaticdeleter.h> + +#include <qfile.h> + +#include <plugins/file/resourcefile.h> +#include <plugins/file/resourcefileconfig.h> +#include <plugins/dir/resourcedir.h> +#include <plugins/dir/resourcedirconfig.h> +//#include <plugins/ldap/resourceldap.h> +//#include <plugins/ldap/resourceldapconfig.h> + + +#include "resource.h" +#include "factory.h" + +using namespace KRES; + +QDict<Factory> *Factory::mSelves = 0; +static KStaticDeleter< QDict<Factory> > staticDeleter; + +Factory *Factory::self( const QString& resourceFamily ) +{ + kdDebug(5650) << "Factory::self()" << endl; + + Factory *factory = 0; + if ( !mSelves ) + { + mSelves = staticDeleter.setObject( new QDict<Factory> ); + } + + factory = mSelves->find( resourceFamily ); + + if ( !factory ) { + factory = new Factory( resourceFamily ); + mSelves->insert( resourceFamily, factory ); + } + + return factory; +} + +Factory::Factory( const QString& resourceFamily ) : + mResourceFamily( resourceFamily ) +{ +//US so far we have three types available for resourceFamily "contact" +// and that are "file", "dir", "ldap" +/*US + + KTrader::OfferList plugins = KTrader::self()->query( "KResources/Plugin", QString( "[X-KDE-ResourceFamily] == '%1'" ) + .arg( resourceFamily ) ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + QVariant type = (*it)->property( "X-KDE-ResourceType" ); + if ( !type.toString().isEmpty() ) + mTypeMap.insert( type.toString(), *it ); + } +*/ + +//US !!!!!!!!!!!!!!! + KRES::PluginFactoryBase* pf = (KRES::PluginFactoryBase*)new KRES::PluginFactory<KABC::ResourceFile,KABC::ResourceFileConfig>(); + mTypeMap.insert( "file", pf ); + + pf = (KRES::PluginFactoryBase*)new KRES::PluginFactory<KABC::ResourceDir,KABC::ResourceDirConfig>(); + mTypeMap.insert( "dir", pf ); + /* + pf = (KRES::PluginFactoryBase*)new KRES::PluginFactory<KABC::ResourceLDAP,KABC::ResourceLDAPConfig>(); + mTypeMap.insert( "ldap", pf ); + */ +} + +Factory::~Factory() +{ +} + +QStringList Factory::typeNames() const +{ +//US method QMap::keys() not available yet. SO collect the data manually +//US return mTypeMap.keys(); + + QStringList result; + + QMap<QString, PluginFactoryBase*>::ConstIterator it; + for( it = mTypeMap.begin(); it != mTypeMap.end(); ++it ) { + result << it.key().latin1(); +// qDebug("Factory::typeNames() : %s ", it.key().latin1()); + + } + return result; +} + +ConfigWidget *Factory::configWidget( const QString& type, QWidget *parent ) +{ + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return 0; + +/*US load the lib not dynamically. !! + KService::Ptr ptr = mTypeMap[ type ]; + KLibFactory *factory = KLibLoader::self()->factory( ptr->library().latin1() ); + if ( !factory ) { + kdDebug() << "KRES::Factory::configWidget(): Factory creation failed" << endl; + return 0; + } +*/ + PluginFactoryBase *factory = mTypeMap[ type ]; + if ( !factory ) { + kdDebug() << "KRES::Factory::configWidget(): Factory creation failed" << endl; + return 0; + } + + + PluginFactoryBase *pluginFactory = static_cast<PluginFactoryBase *>( factory ); + + if ( !pluginFactory ) { + kdDebug() << "KRES::Factory::configWidget(): no plugin factory." << endl; + return 0; + } + + ConfigWidget *wdg = pluginFactory->configWidget( parent ); + if ( !wdg ) { +//US kdDebug() << "'" << ptr->library() << "' is not a " + mResourceFamily + " plugin." << endl; + kdDebug() << " is not a " + mResourceFamily + " plugin." << endl; + return 0; + } + return wdg; + +} + +QString Factory::typeName( const QString &type ) const +{ + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return QString(); + +//US KService::Ptr ptr = mTypeMap[ type ]; +//US return ptr->name(); +//US I guess this is correct since we loaded the factory staticly. + return type; + +} + +QString Factory::typeDescription( const QString &type ) const +{ + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return QString(); + +//US KService::Ptr ptr = mTypeMap[ type ]; +//US return ptr->comment(); +//US I guess this is correct since we loaded the factory staticly. + return type; + +} + +Resource *Factory::resource( const QString& type, const KConfig *config ) +{ + kdDebug() << "Factory::resource( " << type << ", config)" << endl; + + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return 0; + +/*US load the lib not dynamicly. !! + KService::Ptr ptr = mTypeMap[ type ]; + KLibFactory *factory = KLibLoader::self()->factory( ptr->library().latin1() ); + if ( !factory ) { + kdDebug() << "KRES::Factory::resource(): Factory creation failed" << endl; + return 0; + } +*/ + PluginFactoryBase *factory = mTypeMap[ type ]; + if ( !factory ) { + kdDebug() << "KRES::Factory::resource(): Factory creation failed" << endl; + return 0; + } + + PluginFactoryBase *pluginFactory = static_cast<PluginFactoryBase *>( factory ); + + if ( !pluginFactory ) { + kdDebug() << "KRES::Factory::resource(): no plugin factory." << endl; + return 0; + } + + Resource *resource = pluginFactory->resource( config ); + if ( !resource ) { +//US kdDebug() << "'" << ptr->library() << "' is not a " + mResourceFamily + " plugin." << endl; + kdDebug() << " is not a " + mResourceFamily + " plugin." << endl; + return 0; + } + + resource->setType( type ); + + return resource; +} diff --git a/microkde/kresources/factory.h b/microkde/kresources/factory.h new file mode 100644 index 0000000..f391bb3 --- a/dev/null +++ b/microkde/kresources/factory.h @@ -0,0 +1,113 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_FACTORY_H +#define KRESOURCES_FACTORY_H + +#include <qdict.h> +#include <qstring.h> + +#include <kconfig.h> + + +#include "resource.h" + +namespace KRES { + +/** + * Class for loading resource plugins. + * Do not use this class directly. Use ResourceManager instead + * + * Example: + * + * <pre> + * KABC::Factory<Calendar> *factory = KABC::Factory<Calendar>::self(); + * + * QStringList list = factory->resources(); + * QStringList::Iterator it; + * for ( it = list.begin(); it != list.end(); ++it ) { + * Resource<Calendar> *resource = factory->resource( (*it), + * KABC::StdAddressBook::self(), 0 ); + * // do something with resource + * } + * </pre> + */ +class Factory +{ + public: + + /** + * Returns the global resource factory. + */ + static Factory *self( const QString& resourceFamily ); + + ~Factory(); + + /** + * Returns the config widget for the given resource type, + * or a null pointer if resource type doesn't exist. + * + * @param type The type of the resource, returned by @ref resources() + * @param resource The resource to be editted. + * @param parent The parent widget + */ + ConfigWidget *configWidget( const QString& type, QWidget *parent = 0 ); + + /** + * Returns a pointer to a resource object or a null pointer + * if resource type doesn't exist. + * + * @param type The type of the resource, returned by @ref resources() + * @param ab The address book, the resource should belong to + * @param config The config object where the resource get it settings from, or 0 if a new resource should be created. + */ + Resource *resource( const QString& type, const KConfig *config ); + + /** + * Returns a list of all available resource types. + */ + QStringList typeNames() const; + + /** + * Returns the name for a special type. + */ + QString typeName( const QString &type ) const; + + /** + * Returns the description for a special type. + */ + QString typeDescription( const QString &type ) const; + + protected: + Factory( const QString& resourceFamily ); + + private: + static QDict<Factory> *mSelves; + + QString mResourceFamily; +//US QMap<QString, KService::Ptr> mTypeMap; + QMap<QString, PluginFactoryBase*> mTypeMap; +}; + +} +#endif diff --git a/microkde/kresources/kcmkresources.cpp b/microkde/kresources/kcmkresources.cpp new file mode 100644 index 0000000..d600a31 --- a/dev/null +++ b/microkde/kresources/kcmkresources.cpp @@ -0,0 +1,89 @@ +/* + This file is part of libkresources. + + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qlayout.h> + +//US #include <kaboutdata.h> +//US #include <kgenericfactory.h> +#include <klocale.h> + +#include "configpage.h" + +#include "kcmkresources.h" + +using namespace KRES; + +//US typedef KGenericFactory<KCMKResources, QWidget> ResourcesFactory; +//US K_EXPORT_COMPONENT_FACTORY( kcm_kresources, ResourcesFactory( "kcmkresources" ) ); + +//US KCMKResources::KCMKResources( QWidget *parent, const char *name, const QStringList& ) +//US : KCModule( ResourcesFactory::instance(), parent, name ) +KCMKResources::KCMKResources( QWidget *parent, const char *name, const QStringList& ) + : KDialogBase( parent, name, true, i18n( "Configure Resources" ), + Ok|Cancel, Ok, true ) +{ + QFrame *main = plainPage(); + + QVBoxLayout *layout = new QVBoxLayout( main ); + mConfigPage = new KRES::ConfigPage( main ); + layout->addWidget( mConfigPage ); + + + connect( mConfigPage, SIGNAL( changed( bool ) ), SLOT( changed( bool ) ) ); +#ifndef DESKTOP_VERSION + showMaximized(); +#endif +} + +void KCMKResources::changed( bool changed) +{ + modified = changed; +} + +void KCMKResources::slotOk() +{ + if (modified) { + mConfigPage->save(); + modified = false; + } + + KDialogBase::slotOk(); +} + +void KCMKResources::load() +{ + qDebug("KCMKResources::load" ); + mConfigPage->load(); +} + +void KCMKResources::save() +{ + qDebug("KCMKResources::save" ); + mConfigPage->save(); +} + +void KCMKResources::defaults() +{ + qDebug("KCMKResources::defaults" ); + mConfigPage->defaults(); +} + +//US #include "kcmkresources.moc" diff --git a/microkde/kresources/kcmkresources.h b/microkde/kresources/kcmkresources.h new file mode 100644 index 0000000..a83bb33 --- a/dev/null +++ b/microkde/kresources/kcmkresources.h @@ -0,0 +1,54 @@ +/* + This file is part of libkresources. + + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_KCMKRESOURCES_H +#define KRESOURCES_KCMKRESOURCES_H + +#include <kdialogbase.h> + +namespace KRES { + +class ConfigPage; + + +//US class KCMKResources : public KCModule +class KCMKResources : public KDialogBase +{ + Q_OBJECT + + public: + KCMKResources( QWidget *parent, const char *name, const QStringList& ); + + void load(); + void save(); + void defaults(); + + protected slots: + virtual void slotOk(); + void changed( bool ); + + private: + KRES::ConfigPage *mConfigPage; + bool modified; +}; + +} +#endif diff --git a/microkde/kresources/manager.h b/microkde/kresources/manager.h new file mode 100644 index 0000000..b5e97fc --- a/dev/null +++ b/microkde/kresources/manager.h @@ -0,0 +1,332 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_MANAGER_H +#define KRESOURCES_MANAGER_H + +#include <qdict.h> +#include <qstringlist.h> + +#include "factory.h" +#include "managerimpl.h" + +namespace KRES { + +class Resource; + +template<class T> +class ManagerListener +{ + public: + virtual void resourceAdded( T *resource ) = 0; + virtual void resourceModified( T *resource ) = 0; + virtual void resourceDeleted( T *resource ) = 0; +}; + +// TODO: +// The resource manager should provide some signals +// to warn applications that resources have been added, +// removed or modified. +// +// The manager should also keep track of which (or at least +// how many) applications hve opened a resource, so that it +// is only closed if none of them is using it any more + +template<class T> +class Manager : private ManagerImplListener +{ + public: + class Iterator + { + friend class Manager; + public: + Iterator() {}; + Iterator( const Iterator &it ) { mIt = it.mIt; } + + T *operator*() { return static_cast<T *>( *mIt ); } + Iterator &operator++() { mIt++; return *this; } + Iterator &operator++(int) { mIt++; return *this; } + Iterator &operator--() { mIt--; return *this; } + Iterator &operator--(int) { mIt--; return *this; } + bool operator==( const Iterator &it ) { return mIt == it.mIt; } + bool operator!=( const Iterator &it ) { return mIt != it.mIt; } + + private: + Resource::List::Iterator mIt; + }; + + Iterator begin() + { + Iterator it; + it.mIt = mImpl->resourceList()->begin(); + return it; + } + + Iterator end() + { + Iterator it; + it.mIt = mImpl->resourceList()->end(); + return it; + } + + class ActiveIterator + { + friend class Manager; + public: + ActiveIterator() : mList( 0 ) {}; + ActiveIterator( const ActiveIterator &it ) + { + mIt = it.mIt; + mList = it.mList; + } + + T *operator*() { return static_cast<T *>( *mIt ); } + ActiveIterator &operator++() + { + do { mIt++; } while ( checkActive() ); + return *this; + } + ActiveIterator &operator++(int) + { + do { mIt++; } while ( checkActive() ); + return *this; + } + ActiveIterator &operator--() + { + do { mIt--; } while ( checkActive() ); + return *this; + } + ActiveIterator &operator--(int) + { + do { mIt--; } while ( checkActive() ); + return *this; + } + bool operator==( const ActiveIterator &it ) { return mIt == it.mIt; } + bool operator!=( const ActiveIterator &it ) { return mIt != it.mIt; } + + private: + /** + Check if iterator needs to be advanced once more. + */ + bool checkActive() + { + if ( !mList || mIt == mList->end() ) return false; + return !(*mIt)->isActive(); + } + + Resource::List::Iterator mIt; + Resource::List *mList; + }; + + ActiveIterator activeBegin() + { + ActiveIterator it; + it.mIt = mImpl->resourceList()->begin(); + it.mList = mImpl->resourceList(); + if ( it.mIt != mImpl->resourceList()->end() ) { + if ( !(*it)->isActive() ) it++; + } + return it; + } + + ActiveIterator activeEnd() + { + ActiveIterator it; + it.mIt = mImpl->resourceList()->end(); + it.mList = mImpl->resourceList(); + return it; + } + + bool isEmpty() const { return mImpl->resourceList()->isEmpty(); } + + Manager( const QString &family ) + { + mFactory = Factory::self( family ); + // The managerimpl will use the same Factory object as the manager + // because of the Factory::self() pattern + mImpl = new ManagerImpl( family ); + mImpl->setListener( this ); + + mListeners = new QPtrList<ManagerListener<T> >; + } + + virtual ~Manager() + { + mImpl->setListener( 0 ); + delete mListeners; + delete mImpl; + } + + /** + Recreate Resource objects from configuration file. If cfg is 0, read standard + configuration file. + */ + void readConfig( KConfig *cfg = 0 ) + { + mImpl->readConfig( cfg ); + } + + /** + Write configuration of Resource objects to configuration file. If cfg is 0, write + to standard configuration file. + */ + void writeConfig( KConfig *cfg = 0 ) + { + mImpl->writeConfig( cfg ); + } + + /** + Add resource to manager. This passes ownership of the Resource object + to the manager. + */ + void add( Resource *resource ) + { + if ( resource ) mImpl->add( resource ); + } + + void remove( Resource *resource ) + { + if ( resource ) mImpl->remove( resource ); + } + + T* standardResource() + { + return static_cast<T *>( mImpl->standardResource() ); + } + + void setStandardResource( T *resource ) + { + if ( resource ) mImpl->setStandardResource( resource ); + } + + void setActive( Resource *resource, bool active ) + { + if ( resource ) mImpl->setActive( resource, active ); + } + + /** + Returns a list of the names of the reources managed by the + Manager for this family. + */ + QStringList resourceNames() const + { + return mImpl->resourceNames(); + } + + ConfigWidget *configWidget( const QString& type, QWidget *parent = 0 ) + { + return mFactory->resourceConfigWidget( type, parent ); + } + + /** + Creates a new resource of type @param type, with default + settings. The resource is + not added to the manager, the application has to do that. + Returns a pointer to a resource object or a null pointer + if resource type doesn't exist. + + @param type The type of the resource, one of those returned + by @ref resourceTypeNames() + */ + T *createResource( const QString& type ) + { + return (T *)( mFactory->resource( type, 0 ) ); + } + + /** + Returns a list of the names of all available resource types. + */ + QStringList resourceTypeNames() const + { + return mFactory->typeNames(); + } + + QStringList resourceTypeDescriptions() const + { + QStringList typeDescs; + QStringList types = mFactory->typeNames(); + + for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) { + QString desc = mFactory->typeName( *it ); + if ( !mFactory->typeDescription( *it ).isEmpty() ) + desc += " (" + mFactory->typeDescription( *it ) + ")"; + + typeDescs.append( desc ); + } + + return typeDescs; + } + + void resourceChanged( T *resource ) + { + mImpl->resourceChanged( resource ); + } + + void addListener( ManagerListener<T> *listener ) + { + mListeners->append( listener ); + } + + void removeListener( ManagerListener<T> *listener ) + { + mListeners->remove( listener ); + } + + virtual void resourceAdded( Resource *res ) + { + kdDebug(5650) << "Manager::resourceAdded " << res->resourceName() << endl; + T* resource = (T *)( res ); + ManagerListener<T> *listener; + for ( listener = mListeners->first(); listener; listener = mListeners->next() ) + listener->resourceAdded( resource ); + } + + virtual void resourceModified( Resource *res ) + { + kdDebug(5650) << "Manager::resourceModified " << res->resourceName() << endl; + T* resource = (T *)( res ); + ManagerListener<T> *listener; + for ( listener = mListeners->first(); listener; listener = mListeners->next() ) + listener->resourceModified( resource ); + } + + virtual void resourceDeleted( Resource *res ) + { + kdDebug(5650) << "Manager::resourceDeleted " << res->resourceName() << endl; + T* resource = (T *)( res ); + ManagerListener<T> *listener; + for ( listener = mListeners->first(); listener; listener = mListeners->next() ) { + kdDebug(5650) << "Notifying a listener to Manager..." << endl; + listener->resourceDeleted( resource ); + } + } + + private: + ManagerImpl *mImpl; + Factory *mFactory; + QPtrList<ManagerListener<T> > *mListeners; +}; + +} + +#endif diff --git a/microkde/kresources/managerimpl.cpp b/microkde/kresources/managerimpl.cpp new file mode 100644 index 0000000..1baa6be --- a/dev/null +++ b/microkde/kresources/managerimpl.cpp @@ -0,0 +1,353 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kglobal.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kstandarddirs.h> + +#include "resource.h" +#include "factory.h" +#include "managerimpl.h" + +using namespace KRES; + +ManagerImpl::ManagerImpl( const QString &family ) + : mFamily( family ), mConfig( 0 ), mStdConfig( 0 ), mStandard( 0 ), + mFactory( 0 ) + +{ + kdDebug(5650) << "ManagerImpl::ManagerImpl()" << endl; + + +} + +ManagerImpl::~ManagerImpl() +{ + kdDebug(5650) << "ManagerImpl::~ManagerImpl()" << endl; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + delete *it; + } + + delete mStdConfig; +} + +void ManagerImpl::createStandardConfig() +{ + if ( !mStdConfig ) { + QString file = locateLocal( "data", KGlobal::getAppName() + + "/kresources/" + mFamily + "rc" ); + mStdConfig = new KConfig( file ); + } + + mConfig = mStdConfig; +} + +void ManagerImpl::readConfig( KConfig *cfg ) +{ + kdDebug(5650) << "ManagerImpl::readConfig()" << endl; + + delete mFactory; + mFactory = Factory::self( mFamily ); + + if ( !cfg ) { + createStandardConfig(); + } else { + mConfig = cfg; + } + + mStandard = 0; + + mConfig->setGroup( "General" ); + + QStringList keys = mConfig->readListEntry( "ResourceKeys" ); + keys += mConfig->readListEntry( "PassiveResourceKeys" ); + + QString standardKey = mConfig->readEntry( "Standard" ); + + for ( QStringList::Iterator it = keys.begin(); it != keys.end(); ++it ) { + readResourceConfig( *it, false ); + } + +} + +void ManagerImpl::writeConfig( KConfig *cfg ) +{ +//USqDebug("ManagerImpl::writeConfig begin this= %ul cfg=%ul", this, cfg); + + + kdDebug(5650) << "ManagerImpl::writeConfig()" << endl; + + if ( !cfg ) { + createStandardConfig(); + } else { + mConfig = cfg; + } + + QStringList activeKeys; + QStringList passiveKeys; + + // First write all keys, collect active and passive keys on the way + Resource::List::Iterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + writeResourceConfig( *it, false ); + + QString key = (*it)->identifier(); + if( (*it)->isActive() ) + activeKeys.append( key ); + else + passiveKeys.append( key ); + } + + // And then the general group + + kdDebug(5650) << "Saving general info" << endl; + mConfig->setGroup( "General" ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + mConfig->writeEntry( "PassiveResourceKeys", passiveKeys ); + if ( mStandard ) + mConfig->writeEntry( "Standard", mStandard->identifier() ); + else + mConfig->writeEntry( "Standard", "" ); + + mConfig->sync(); + kdDebug(5650) << "ManagerImpl::save() finished" << endl; + +//US qDebug("ManagerImpl::writeConfig end this= %ul cfg=%ul", this, cfg); + +} + +void ManagerImpl::add( Resource *resource, bool useDCOP ) +{ +qDebug("ManagerImpl::add begin this= %ul resource=%ul", this, resource); + + resource->setActive( true ); + + if ( mResources.isEmpty() ) { + mStandard = resource; + } + + mResources.append( resource ); + + writeResourceConfig( resource, true ); + + qDebug("ManagerImpl::add end this= %ul resource=%ul", this, resource); + +} + +void ManagerImpl::remove( Resource *resource, bool useDCOP ) +{ + if ( mStandard == resource ) mStandard = 0; + removeResource( resource ); + + mResources.remove( resource ); + + delete resource; + + kdDebug(5650) << "Finished ManagerImpl::remove()" << endl; +} + +void ManagerImpl::setActive( Resource *resource, bool active ) +{ + if ( resource && resource->isActive() != active ) { + resource->setActive( active ); + } +} + +Resource *ManagerImpl::standardResource() +{ + return mStandard; +} + +void ManagerImpl::setStandardResource( Resource *resource ) +{ + mStandard = resource; +} + +void ManagerImpl::resourceChanged( Resource *resource ) +{ + writeResourceConfig( resource, true ); + + +// ManagerIface_stub allManagers( "*", "ManagerIface_" + mFamily.utf8() ); +// allManagers.dcopResourceModified( resource->identifier() ); +} + +// DCOP asynchronous functions +//US since we work from inside the application, we call the methods directly. + +QStringList ManagerImpl::resourceNames() +{ + QStringList result; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + result.append( (*it)->resourceName() ); + } + return result; +} + +Resource::List *ManagerImpl::resourceList() +{ + return &mResources; +} + +QPtrList<Resource> ManagerImpl::resources() +{ + QPtrList<Resource> result; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + result.append( *it ); + } + return result; +} + +QPtrList<Resource> ManagerImpl::resources( bool active ) +{ + QPtrList<Resource> result; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + if ( (*it)->isActive() == active ) { + result.append( *it ); + } + } + return result; +} + +void ManagerImpl::setListener( ManagerImplListener *listener ) +{ + mListener = listener; +} + +Resource* ManagerImpl::readResourceConfig( const QString& identifier, + bool checkActive ) +{ + kdDebug() << "ManagerImpl::readResourceConfig() " << identifier << endl; + +// qDebug("ManagerImpl::readResourceConfig() %s", identifier.latin1()); + + mConfig->setGroup( "Resource_" + identifier ); + + QString type = mConfig->readEntry( "ResourceType" ); + QString name = mConfig->readEntry( "ResourceName" ); + Resource *resource = mFactory->resource( type, mConfig ); + if ( !resource ) { + kdDebug(5650) << "Failed to create resource with id " << identifier << endl; + return 0; + } + + if ( resource->identifier().isEmpty() ) + resource->setIdentifier( identifier ); + + mConfig->setGroup( "General" ); + + QString standardKey = mConfig->readEntry( "Standard" ); + if ( standardKey == identifier ) { + mStandard = resource; + } + + if ( checkActive ) { + QStringList activeKeys = mConfig->readListEntry( "ResourceKeys" ); + resource->setActive( activeKeys.contains( identifier ) ); + } + mResources.append( resource ); + + return resource; +} + +void ManagerImpl::writeResourceConfig( Resource *resource, + bool checkActive ) +{ + QString key = resource->identifier(); + + kdDebug(5650) << "Saving resource " << key << endl; + + if ( !mConfig ) createStandardConfig(); + + mConfig->setGroup( "Resource_" + key ); + resource->writeConfig( mConfig ); + + mConfig->setGroup( "General" ); + QString standardKey = mConfig->readEntry( "Standard" ); + + if ( resource == mStandard && standardKey != key ) + mConfig->writeEntry( "Standard", resource->identifier() ); + else if ( resource != mStandard && standardKey == key ) + mConfig->writeEntry( "Standard", "" ); + + if ( checkActive ) { + QStringList activeKeys = mConfig->readListEntry( "ResourceKeys" ); + if ( resource->isActive() && !activeKeys.contains( key ) ) { + activeKeys.append( resource->identifier() ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + } else if ( !resource->isActive() && activeKeys.contains( key ) ) { + activeKeys.remove( key ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + } + } + + mConfig->sync(); +} + +void ManagerImpl::removeResource( Resource *resource ) +{ + QString key = resource->identifier(); + + if ( !mConfig ) createStandardConfig(); + + mConfig->setGroup( "General" ); + QStringList activeKeys = mConfig->readListEntry( "ResourceKeys" ); + if ( activeKeys.contains( key ) ) { + activeKeys.remove( key ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + } else { + QStringList passiveKeys = mConfig->readListEntry( "PassiveResourceKeys" ); + passiveKeys.remove( key ); + mConfig->writeEntry( "PassiveResourceKeys", passiveKeys ); + } + + QString standardKey = mConfig->readEntry( "Standard" ); + if ( standardKey == key ) { + mConfig->writeEntry( "Standard", "" ); + } + + mConfig->deleteGroup( "Resource_" + resource->identifier() ); + + mConfig->sync(); +} + +Resource* ManagerImpl::getResource( const QString& identifier ) +{ + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + if ( (*it)->identifier() == identifier ) + return *it; + } + return 0; +} diff --git a/microkde/kresources/managerimpl.h b/microkde/kresources/managerimpl.h new file mode 100644 index 0000000..a049bcc --- a/dev/null +++ b/microkde/kresources/managerimpl.h @@ -0,0 +1,113 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_MANAGERIMPL_H +#define KRESOURCES_MANAGERIMPL_H + +#include <qstring.h> +#include <qptrlist.h> +#include <qdict.h> +//US +#include <qobject.h> + +#include "resource.h" + + +class KConfig; + +namespace KRES { + +class Resource; +class Factory; + +class ManagerImplListener +{ + public: + virtual void resourceAdded( Resource *resource ) = 0; + virtual void resourceModified( Resource *resource ) = 0; + virtual void resourceDeleted( Resource *resource ) = 0; +}; + + +/** + @internal + + Do not use this class directly. Use ResourceManager instead +*/ +class ManagerImpl : public QObject +{ + Q_OBJECT + public: + ManagerImpl( const QString &family ); + ~ManagerImpl(); + + void readConfig( KConfig * ); + void writeConfig( KConfig * ); + + void add( Resource *resource, bool useDCOP = true ); + void remove( Resource *resource, bool useDCOP = true ); + + Resource *standardResource(); + void setStandardResource( Resource *resource ); + + void setActive( Resource *resource, bool active ); + + Resource::List *resourceList(); + + QPtrList<Resource> resources(); + + // Get only active or passive resources + QPtrList<Resource> resources( bool active ); + + QStringList resourceNames(); + + void setListener( ManagerImplListener *listener ); + + public slots: + void resourceChanged( Resource *resource ); + + private: + // dcop calls + + private: + void createStandardConfig(); + + Resource *readResourceConfig( const QString& identifier, bool checkActive ); + void writeResourceConfig( Resource *resource, bool checkActive ); + + void removeResource( Resource *resource ); + Resource *getResource( Resource *resource ); + Resource *getResource( const QString& identifier ); + + QString mFamily; + KConfig *mConfig; + KConfig *mStdConfig; + Resource *mStandard; + Factory *mFactory; + Resource::List mResources; + ManagerImplListener *mListener; +}; + +} + +#endif diff --git a/microkde/kresources/resource.cpp b/microkde/kresources/resource.cpp new file mode 100644 index 0000000..169eaa4 --- a/dev/null +++ b/microkde/kresources/resource.cpp @@ -0,0 +1,185 @@ +/* + This file is part of libkresources. + + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <kapplication.h> +#include <kconfig.h> + +#include "resource.h" + +using namespace KRES; + +class Resource::ResourcePrivate +{ + public: +#ifdef QT_THREAD_SUPPORT + QMutex mMutex; +#endif + int mOpenCount; + QString mType; + QString mIdentifier; + bool mReadOnly; + QString mName; + bool mActive; + bool mIsOpen; +}; + +Resource::Resource( const KConfig* config ) + : QObject( 0, "" ), d( new ResourcePrivate ) +{ + d->mOpenCount = 0; + d->mIsOpen = false; + + //US compiler claimed that const discards qualifier + KConfig* cfg = (KConfig*)config; + if ( cfg ) { + d->mType = cfg->readEntry( "ResourceType" ); + d->mName = cfg->readEntry( "ResourceName" ); + d->mReadOnly = cfg->readBoolEntry( "ResourceIsReadOnly", false ); + d->mActive = cfg->readBoolEntry( "ResourceIsActive", true ); + d->mIdentifier = cfg->readEntry( "ResourceIdentifier" ); + } else { + d->mType = "type"; + d->mName = "resource-name"; + d->mReadOnly = false; + d->mActive = true; + d->mIdentifier = KApplication::randomString( 10 ); + } +} + +Resource::~Resource() +{ + delete d; + d = 0; +} + +void Resource::writeConfig( KConfig* config ) +{ + kdDebug(5650) << "Resource::writeConfig()" << endl; + + config->writeEntry( "ResourceType", d->mType ); + config->writeEntry( "ResourceName", d->mName ); + config->writeEntry( "ResourceIsReadOnly", d->mReadOnly ); + config->writeEntry( "ResourceIsActive", d->mActive ); + config->writeEntry( "ResourceIdentifier", d->mIdentifier ); +} + +bool Resource::open() +{ + d->mIsOpen = true; +#ifdef QT_THREAD_SUPPORT + QMutexLocker guard( &(d->mMutex) ); +#endif + if ( !d->mOpenCount ) { + kdDebug(5650) << "Opening resource " << resourceName() << endl; + d->mIsOpen = doOpen(); + } + d->mOpenCount++; + return d->mIsOpen; +} + +void Resource::close() +{ +#ifdef QT_THREAD_SUPPORT + QMutexLocker guard( &(d->mMutex) ); +#endif + if ( !d->mOpenCount ) { + kdDebug(5650) << "ERROR: Resource " << resourceName() << " closed more times than previously opened" << endl; + return; + } + d->mOpenCount--; + if ( !d->mOpenCount ) { + kdDebug(5650) << "Closing resource " << resourceName() << endl; + doClose(); + d->mIsOpen = false; + } else { + kdDebug(5650) << "Not yet closing resource " << resourceName() << ", open count = " << d->mOpenCount << endl; + } +} + +bool Resource::isOpen() const +{ + return d->mIsOpen; +} + +void Resource::setIdentifier( const QString& identifier ) +{ + d->mIdentifier = identifier; +} + +QString Resource::identifier() const +{ + return d->mIdentifier; +} + +void Resource::setType( const QString& type ) +{ + d->mType = type; +} + +QString Resource::type() const +{ + return d->mType; +} + +void Resource::setReadOnly( bool value ) +{ + d->mReadOnly = value; +} + +bool Resource::readOnly() const +{ + return d->mReadOnly; +} + +void Resource::setResourceName( const QString &name ) +{ + d->mName = name; +} + +QString Resource::resourceName() const +{ + return d->mName; +} + +void Resource::setActive( bool value ) +{ + d->mActive = value; +} + +bool Resource::isActive() const +{ + return d->mActive; +} + +void Resource::dump() const +{ + kdDebug(5650) << "Resource:" << endl; + kdDebug(5650) << " Name: " << d->mName << endl; + kdDebug(5650) << " Identifier: " << d->mIdentifier << endl; + kdDebug(5650) << " Type: " << d->mType << endl; + kdDebug(5650) << " OpenCount: " << d->mOpenCount << endl; + kdDebug(5650) << " ReadOnly: " << ( d->mReadOnly ? "yes" : "no" ) << endl; + kdDebug(5650) << " Active: " << ( d->mActive ? "yes" : "no" ) << endl; + kdDebug(5650) << " IsOpen: " << ( d->mIsOpen ? "yes" : "no" ) << endl; +} diff --git a/microkde/kresources/resource.h b/microkde/kresources/resource.h new file mode 100644 index 0000000..7ff4f23 --- a/dev/null +++ b/microkde/kresources/resource.h @@ -0,0 +1,401 @@ +/* + This file is part of libkresources + + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_RESOURCE_H +#define KRESOURCES_RESOURCE_H + +//US +#ifdef QT_THREAD_SUPPORT +#include <qmutex.h> +#endif //QT_THREAD_SUPPORT + +#include <qvaluelist.h> +#include <qwidget.h> + +#include <qobject.h> + +class KConfig; + +namespace KRES { + +class KLibFactory; +class ConfigWidget; + +/** + * @internal + * @libdoc The KDE Resource library + * + * NOTE: this library is NOT (YET?) PUBLIC. Do not publish this + * interface, it is in constant flux. + * + * The KDE Resource framework can be used to manage resources of + * different types, organized in families. The Resource framework + * is currently used for addressbook resources in libkabc and for + * calendar resources in libkcal. + * + * When you want to use the framework for a new family, you need to + * <ul><li>Define a name for your resource family</li> + * <li>subclass Resource and add the fields and method that are needed + * in your application</li> + * <li>If needed, override the doOpen() and doClose() methods. + * <li> Provide a configuration possibility for resources in your + * new family. You can use @ref ResourcesConfigPage to easily create a + * KControl applet</li> + * <li>In your application, you can use @ref ResourceManager to keep track + * of the resources in your family, and you can use @ref ResourceSelectDialog + * to let the user select a single resource.</li> + * </ul> + * + * When you want to add a new resource type to an existing resource family, + * you need to + * <ul><li>Further subclass the family-specific Resource to implement + * resource type-specific operation</li> + * <li>Subclass ResourceConfigWidget to provide a configuration widget + * for your new resource type</li> + * <li>Provide a .desktop file so that the new resource type can be found + * automatically by the ResourceManager</li> + * </ul> + * + * Example: + * +<B>resourceexample.h</B>: +<pre> +#include <kconfig.h> +#include <kresources/resource.h> + +class ResourceExample : public KRES::ResourceExample +{ +public: + ResourceExample( const KConfig * ); + ~ResourceCalendarExchange(); + void writeConfig( KConfig *config ); +private: + QString mLocation; + QString mPassword; +} +</pre> +<B>resourceexample.cpp</B>: +<pre> +#include <kconfig.h> + +#include "resourceexample.h" + +ResourceExample::ResourceExample( const KConfig *config ) + : Resource( config ) +{ + if ( config ) { + mLocation = config->readEntry( "Location" ); + mPassword = KStringHandler::obscure( config->readEntry( "Password" ) ); + } else { + mLocation = ""; // Or some sensible default + mPassword = ""; + } +} + +void ResourceExample::writeConfig( KConfig *config ) +{ + KRES::Resource::writeConfig( config ); + config->writeEntry( "Location", mLocation ); + config->writeEntry( "Password", KStringHandler::obscure( mPassword ) ); +} + +extern "C" +{ + KRES::ResourceExample *config_widget( QWidget *parent ) { + return new ResourceExampleConfig( parent, "Configure Example Resource" ); + } + + KRES::Resource *resource( const KConfig *config ) { + return new ResourceExample( config ); + } +} +</pre> +* <B>resourceexampleconfig.h</B>: +<pre> +#include <klineedit.h> +#include <kresources/resourceconfigwidget.h> + +#include "resourceexample.h" + +class ResourceExampleConfig : public KRES::ResourceConfigWidget +{ + Q_OBJECT + +public: + ResourceExampleConfig( QWidget* parent = 0, const char* name = 0 ); + +public slots: + virtual void loadSettings( KRES::Resource *resource); + virtual void saveSettings( KRES::Resource *resource ); + +private: + KLineEdit* mLocationEdit; + KLineEdit* mPasswordEdit; +}; +</pre> +* <B>resourceexampleconfig.cpp</B>: +<pre> +#include <qlayout.h> +#include <qlabel.h" +#include <kresources/resourceconfigwidget.h> +#include "resourceexample.h" +#include "resourceexampleconfig.h" + +ResourceExampleConfig::ResourceExampleConfig( QWidget* parent, const char* name ) + : KRES::ResourceConfigWidget( parent, name ) +{ + resize( 245, 115 ); + QGridLayout *mainLayout = new QGridLayout( this, 2, 2 ); + + QLabel *label = new QLabel( i18n( "Location:" ), this ); + mHostEdit = new KLineEdit( this ); + mainLayout->addWidget( label, 1, 0 ); + mainLayout->addWidget( mHostEdit, 1, 1 ); + + label = new QLabel( i18n( "Password:" ), this ); + mPasswordEdit = new KLineEdit( this ); + mPasswordEdit->setEchoMode( QLineEdit::Password ); + mainLayout->addWidget( label, 2, 0 ); + mainLayout->addWidget( mPasswordEdit, 2, 1 ); +} + +void ResourceExampleConfig::loadSettings( KRES::Resource *resource ) +{ + ResourceExample* res = dynamic_cast<ResourceExample *>( resource ); + if (res) { + mHostEdit->setText( res->host() ); + mPasswordEdit->setText( res->password() ); + } else + kdDebug(5700) << "ERROR: ResourceExampleConfig::loadSettings(): no ResourceExample, cast failed" << endl; +} + +void ResourceExampleConfig::saveSettings( KRES::Resource *resource ) +{ + ResourceExample* res = dynamic_cast<ResourceExample *>( resource ); + if (res) { + res->setHost(mHostEdit->text()); + res->setPassword(mPasswordEdit->text()); + } else + kdDebug(5700) << "ERROR: ResourceExampleConfig::saveSettings(): no ResourceExample, cast failed" << endl; +} +</pre> +* <B>resourceexample.desktop</B>: +<pre> +[Desktop Entry] +Type=Service + +[Misc] +Encoding=UTF-8 +Name=Example Resource + +[Plugin] +Type=exchange +X-KDE-Library=resourceexample +</pre> +* <B>Makefile.am</B> +<pre> +kde_module_LTLIBRARIES = resourceexample.la + +resourceexample_la_SOURCES = resourceexample.cpp resourceexampleconfig.cpp +resourceexample_la_LDFLAGS= $(all_libraries) -module $(KDE_PLUGIN) +resourceexample_la_LIBADD= -lkderesources + +linkdir= $(kde_datadir)/resources/family +link_DATA= resourceexample.desktop +</pre> + * + * + */ + +/** + * A @ref Resource is a ... + * + * A subclass should reimplement at least the constructor and the + * @ref writeConfig method. + * + */ +class Resource : public QObject +{ + Q_OBJECT + + public: + typedef QValueList<Resource *> List; + + /** + * Constructor. Construct resource from config. + * @param config Configuration to read persistence information from. + * If config==0, create object using default settings. + */ + Resource( const KConfig* config ); + + /** + * Destructor. + */ + virtual ~Resource(); + + /** + * Write configuration information for this resource to a configuration + * file. If you override this method, remember to call Resource::writeConfig + * or Terrible Things(TM) will happen. + * @param config Configuration to write persistence information to. + */ + virtual void writeConfig( KConfig* config ); + + /** + * Open this resource, if it not already open. Increase the open + * count of this object, and open the resource by calling @ref doOpen(). + * This method may block while another thread is concurrently opening + * or closing the resource. + * + * Returns true if the resource was already opened or if it was opened + * successfully; returns false if the resource was not opened successfully. + */ + bool open(); + + /** + * Decrease the open count of this object, and if the count reaches + * zero, close this resource by calling @ref doClose(). + * This method may block while another thread is concurrently closing + * or opening the resource. + */ + void close(); + + /** + * Returns whether the resource is open or not. + */ + bool isOpen() const; + + /** + * Returns a unique identifier. The identifier is unique for this resource. + * It is created when the resource is first created, and it is retained + * in the resource family configuration file for this resource. + * @return This resource's identifier + */ + QString identifier() const; + + /** + * Returns the type of this resource. + */ + QString type() const; + + /** + * Mark the resource as read-only. You can override this method, + * but also remember to call Resource::setReadOnly(). + */ + virtual void setReadOnly( bool value ); + + /** + * Returns, if the resource is read-only. + */ + virtual bool readOnly() const; + + /** + * Set the name of resource.You can override this method, + * but also remember to call Resource::setResourceName(). + */ + virtual void setResourceName( const QString &name ); + + /** + * Returns the name of resource. + */ + virtual QString resourceName() const; + + /** + Sets, if the resource is active. + */ + void setActive( bool active ); + + /** + Return true, if the resource is active. + */ + bool isActive() const; + + friend class Factory; + friend class ManagerImpl; + + /** + Print resource information as debug output. + */ + virtual void dump() const; + + protected: + /** + * Open this resource. When called, the resource must be in + * a closed state. + * + * Returns true if the resource was opened successfully; + * returns false if the resource was not opened successfully. + * + * The result of this call can be accessed later by @ref isOpen() + */ + virtual bool doOpen() { return true; } + + /** + * Close this resource. Pre-condition: resource is open. + * Post-condition: resource is closed. + */ + virtual void doClose() {} + + void setIdentifier( const QString& identifier ); + void setType( const QString& type ); + + private: + class ResourcePrivate; + ResourcePrivate *d; +}; + +//US class PluginFactoryBase : public KLibFactory +class PluginFactoryBase +{ + public: + virtual Resource *resource( const KConfig *config ) = 0; + + virtual ConfigWidget *configWidget( QWidget *parent ) = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + +template<class TR,class TC> +class PluginFactory : public PluginFactoryBase +{ + public: + Resource *resource( const KConfig *config ) + { + return new TR( config ); + } + + ConfigWidget *configWidget( QWidget *parent ) + { + return new TC( parent ); + } +}; + + + +} + +#endif diff --git a/microkde/kresources/resourceselectdialog.h b/microkde/kresources/resourceselectdialog.h new file mode 100644 index 0000000..fef689d --- a/dev/null +++ b/microkde/kresources/resourceselectdialog.h @@ -0,0 +1,12 @@ +#ifndef MICRO_KRES_RESOURCESELECTDIALOG_H +#define MICRO_KRES_RESOURCESELECTDIALOG_H + +namespace KRES { + +class ResourceSelectDialog +{ +}; + +} + +#endif diff --git a/microkde/kresources/selectdialog.cpp b/microkde/kresources/selectdialog.cpp new file mode 100644 index 0000000..fba8648 --- a/dev/null +++ b/microkde/kresources/selectdialog.cpp @@ -0,0 +1,154 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/*US +#include <kbuttonbox.h> +#include <klistbox.h> +#include <klocale.h> +#include <kmessagebox.h> + +*/ +#include <klocale.h> +#include <kmessagebox.h> + +//US +#include <kglobal.h> + +#include <qlistbox.h> +#include <qlayout.h> +#include <qgroupbox.h> + +#include "resource.h" + +#include "selectdialog.h" + +using namespace KRES; + +//US I am using KBaseDialog instead of KDialog +//US : KDialog( parent, name, true ) +SelectDialog::SelectDialog( QPtrList<Resource> list, QWidget *parent, + const char *name ) + : KDialogBase( parent, name, true, i18n( "Resource Selection" ), Help | Ok | Cancel, + Ok, true) + +{ +//US setCaption( i18n( "Resource Selection" ) ); +//US resize( 300, 200 ); + resize( KMIN(KGlobal::getDesktopWidth(), 300), KMIN(KGlobal::getDesktopHeight(), 200) ); + +//US + QFrame *main = plainPage(); +/*US + QVBoxLayout *layout = new QVBoxLayout( main ); + mConfigPage = new KRES::ConfigPage( main ); + layout->addWidget( mConfigPage ); +*/ + +//US QVBoxLayout *mainLayout = new QVBoxLayout( this ); + QVBoxLayout *mainLayout = new QVBoxLayout( main ); + mainLayout->setMargin( marginHint() ); + +//US QGroupBox *groupBox = new QGroupBox( 2, Qt::Horizontal, this ); + QGroupBox *groupBox = new QGroupBox( 2, Qt::Horizontal, main ); + groupBox->setTitle( i18n( "Resources" ) ); + +//US mResourceId = new KListBox( groupBox ); + mResourceId = new QListBox( groupBox ); + + mainLayout->addWidget( groupBox ); + + mainLayout->addSpacing( 40 ); + +/*US + KButtonBox *buttonBox = new KButtonBox( this ); + + buttonBox->addStretch(); + buttonBox->addButton( i18n( "&OK" ), this, SLOT( accept() ) ); + buttonBox->addButton( i18n( "&Cancel" ), this, SLOT( reject() ) ); + buttonBox->layout(); + + mainLayout->addWidget( buttonBox ); +*/ + // setup listbox + uint counter = 0; + for ( uint i = 0; i < list.count(); ++i ) { + Resource *resource = list.at( i ); + if ( resource && !resource->readOnly() ) { + mResourceMap.insert( counter, resource ); + mResourceId->insertItem( resource->resourceName() ); + counter++; + } + } + + mResourceId->setCurrentItem( 0 ); + connect( mResourceId, SIGNAL(returnPressed(QListBoxItem*)), + SLOT(accept()) ); +} + +Resource *SelectDialog::resource() +{ + if ( mResourceId->currentItem() != -1 ) + return mResourceMap[ mResourceId->currentItem() ]; + else + return 0; +} + +Resource *SelectDialog::getResource( QPtrList<Resource> list, QWidget *parent ) +{ + if ( list.count() == 0 ) { + KMessageBox::error( parent, i18n( "There is no resource available!" ) ); + return 0; + } + + if ( list.count() == 1 ) return list.first(); + + // the following lines will return a writeable resource if only _one_ writeable + // resource exists + Resource *found = 0; + Resource *it = list.first(); + while ( it ) { + if ( !it->readOnly() ) { + if ( found ) { + found = 0; + break; + } else + found = it; + } + it = list.next(); + } + + if ( found ) + return found; + + SelectDialog dlg( list, parent); +//US if ( dlg.exec() == KDialog::Accepted ) + if ( dlg.exec() ) + return dlg.resource(); + else + return 0; +} + +/*US +#include "selectdialog.moc" +*/ + diff --git a/microkde/kresources/selectdialog.h b/microkde/kresources/selectdialog.h new file mode 100644 index 0000000..7026212 --- a/dev/null +++ b/microkde/kresources/selectdialog.h @@ -0,0 +1,92 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_SELECTDIALOG_H +#define KRESOURCES_SELECTDIALOG_H + +#include <qobject.h> +#include <qptrlist.h> +#include <qmap.h> + +#include <kdialogbase.h> + +//US class KListBox; +class QListBox; + +namespace KRES { + +class Resource; + +/** + * Dialog for selecting a resource. + * + * Example: + * + * <pre> + * KABC::Resource *res = KABC::SelectDialog::getResource(); + * if ( !( res ) ) { + * // no resource selected + * } else { + * // do something with resource + * } + * </pre> + */ +//US class SelectDialog : KDialog +class SelectDialog : KDialogBase +{ + // Q_OBJECT + public: + /** + * Constructor. + * @param ab The address book you want to select the resource from + * @param parent The parent widget + * @param name The name of the dialog + */ + SelectDialog( QPtrList<Resource> list, QWidget *parent = 0, + const char *name = 0); + + // ~SelectDialog(); + + /** + * Return selected resource. + */ + Resource *resource(); + + /** + * Open a dialog showing the available resources and return the resource the + * user has selected. Returns 0, if the dialog was canceled. + */ + static Resource *getResource( QPtrList<Resource> list, QWidget *parent = 0 ); + + private: +//US KListBox *mResourceId; + QListBox *mResourceId; + + QMap<int, Resource*> mResourceMap; +}; + + + +} + +#endif diff --git a/microkde/krestrictedline.h b/microkde/krestrictedline.h new file mode 100644 index 0000000..200546c --- a/dev/null +++ b/microkde/krestrictedline.h @@ -0,0 +1,13 @@ +#ifndef MINIKDE_KRESTRICTEDLINE_H +#define MINIKDE_KRESTRICTEDLINE_H + +#include "klineedit.h" + +class KRestrictedLine : public KLineEdit +{ + public: + KRestrictedLine( QWidget *parent, const char *, const QString & ) : + KLineEdit( parent ) {} +}; + +#endif diff --git a/microkde/krun.cpp b/microkde/krun.cpp new file mode 100644 index 0000000..a170add --- a/dev/null +++ b/microkde/krun.cpp @@ -0,0 +1,6 @@ +#include "krun.h" + +bool KRun::runCommand(const QString &, const QString &, const QString &) +{ + return false; +} diff --git a/microkde/krun.h b/microkde/krun.h new file mode 100644 index 0000000..1b63cb7 --- a/dev/null +++ b/microkde/krun.h @@ -0,0 +1,13 @@ +#ifndef MINIKDE_KRUN_H +#define MINIKDE_KRUN_H + +#include <qstring.h> + +class KRun +{ + public: + static bool runCommand(const QString &a, const QString &b=QString::null, + const QString &c=QString::null); +}; + +#endif diff --git a/microkde/ksimpleconfig.h b/microkde/ksimpleconfig.h new file mode 100644 index 0000000..1efd982 --- a/dev/null +++ b/microkde/ksimpleconfig.h @@ -0,0 +1,12 @@ +#ifndef MINIKDE_KSIMPLECONFIG_H +#define MINIKDE_KSIMPLECONFIG_H + +#include "kconfig.h" + +class KSimpleConfig : public KConfig +{ + public: + KSimpleConfig( const QString &file ) : KConfig( file ) {} +}; + +#endif diff --git a/microkde/kstandarddirs_old.cpp b/microkde/kstandarddirs_old.cpp new file mode 100644 index 0000000..ac2c085 --- a/dev/null +++ b/microkde/kstandarddirs_old.cpp @@ -0,0 +1,151 @@ +#include "kdebug.h" +#include "kurl.h" + +#include "kstandarddirs.h" +#ifdef DESKTOP_VERSION +#include <qregexp.h> +#include <qmessagebox.h> + +#endif + + +#include <qfile.h> +#include <qdir.h> + +QString KStandardDirs::mAppDir = QString::null; + +QString locate( const char *type, const QString& filename ) +{ +/*US why do we put all files into one directory. It is quit complicated. +why not staying with the original directorystructure ? + + + QString escapedFilename = filename; + escapedFilename.replace( QRegExp( "/" ), "_" ); + + QString path = KStandardDirs::appDir() + type + "_" + escapedFilename; + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; +*/ +//US so my proposal is this: + +// QString escapedFilename = filename; +// escapedFilename.replace( QRegExp( "/" ), "_" ); + +#ifdef _WIN32_ + QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename); +#else + QString path = KStandardDirs::appDir() + type + "/" + filename; +#endif + + //US Create the containing dir if needed + KURL pathurl; + pathurl.setPath(path); + QString dir=pathurl.directory(); + // QMessageBox::information( 0,"path", path, 1 ); +#ifdef _WIN32_ + KStandardDirs::makeDir(path); +#else + KStandardDirs::makeDir(dir); +#endif + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; + + +} + +QString locateLocal( const char *type, const QString& filename ) +{ + return locate( type, filename ); +} + +QStringList KStandardDirs::findAllResources( const QString &, const QString &, bool, bool) +{ + return QStringList(); +} + +QString KStandardDirs::findResourceDir( const QString &, const QString & ) +{ + return QString::null; +} + +void KStandardDirs::setAppDir( const QString &appDir ) +{ + mAppDir = appDir; + + if ( mAppDir.right( 1 ) != "/" ) mAppDir += "/"; +} + +bool KStandardDirs::makeDir(const QString& dir, int mode) +{ + QDir dirObj; + + + // we want an absolute path +#ifndef _WIN32_ + if (dir.at(0) != '/') + return false; +#endif + + + + QString target = dir; + uint len = target.length(); +#ifndef _WIN32_ + // append trailing slash if missing + if (dir.at(len - 1) != '/') + target += '/'; +#endif + + QString base(""); + uint i = 1; + + while( i < len ) + { +//US struct stat st; +#ifndef _WIN32_ + int pos = target.find('/', i); +#else + int pos = target.find('\\', i); +#endif + if ( pos < 0 ) + return true; + base += target.mid(i - 1, pos - i + 1); + //QMessageBox::information( 0,"cap111", base, 1 ); +/*US + QCString baseEncoded = QFile::encodeName(base); + // bail out if we encountered a problem + if (stat(baseEncoded, &st) != 0) + { + // Directory does not exist.... + // Or maybe a dangling symlink ? + if (lstat(baseEncoded, &st) == 0) + (void)unlink(baseEncoded); // try removing + + + if ( mkdir(baseEncoded, (mode_t) mode) != 0) { + perror("trying to create local folder"); + return false; // Couldn't create it :-( + } + } +*/ + + if (dirObj.exists(base) == false) + { + qDebug("KStandardDirs::makeDir try to create : %s" , base.latin1()); + if (dirObj.mkdir(base) != true) + { + qDebug("KStandardDirs::makeDir could not create: %s" , base.latin1()); + return false; + } + } + + i = pos + 1; + } + return true; +} + diff --git a/microkde/kstandarddirs_old.h b/microkde/kstandarddirs_old.h new file mode 100644 index 0000000..87f8d69 --- a/dev/null +++ b/microkde/kstandarddirs_old.h @@ -0,0 +1,35 @@ +#ifndef MINIKDE_KSTANDARDDIRS_H +#define MINIKDE_KSTANDARDDIRS_H + +#include <qstring.h> +#include <qstringlist.h> + +QString locate( const char *type, const QString& filename ); +QString locateLocal( const char *type, const QString& filename ); + +class KStandardDirs +{ + public: + QStringList findAllResources( const QString &, const QString &, bool, bool); + QString findResourceDir( const QString &, const QString & ); + + static void setAppDir( const QString & ); + static QString appDir() { return mAppDir; } + + /** + * Recursively creates still-missing directories in the given path. + * + * The resulting permissions will depend on the current umask setting. + * permission = mode & ~umask. + * + * @param dir Absolute path of the directory to be made. + * @param mode Directory permissions. + * @return true if successful, false otherwise + */ + static bool makeDir(const QString& dir, int mode = 0755); + + private: + static QString mAppDir; +}; + +#endif diff --git a/microkde/kstaticdeleter.h b/microkde/kstaticdeleter.h new file mode 100644 index 0000000..190f3e4 --- a/dev/null +++ b/microkde/kstaticdeleter.h @@ -0,0 +1,35 @@ +/* + * This file is part of the KDE Libraries + * Copyright (C) 2000 Stephan Kulow <coolo@kde.org> + * 2001 KDE Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _KSTATIC_DELETER_H_ +#define _KSTATIC_DELETER_H_ + +template<class type> +class KStaticDeleter +{ + public: + KStaticDeleter() {}; + type *setObject( type *obj, bool isArray = false) { return obj; } + virtual ~KStaticDeleter() {}; +}; + +#endif diff --git a/microkde/ksystemtray.cpp b/microkde/ksystemtray.cpp new file mode 100644 index 0000000..4f81d02 --- a/dev/null +++ b/microkde/ksystemtray.cpp @@ -0,0 +1,11 @@ +#include "ksystemtray.h" + +void KSystemTray::mousePressEvent( QMouseEvent *) +{ + ; //qDebug("hallo"); +} + +KSystemTray::KSystemTray( QWidget *parent ) : QLabel( parent ) +{ + +} diff --git a/microkde/ksystemtray.h b/microkde/ksystemtray.h new file mode 100644 index 0000000..f3e4f6a --- a/dev/null +++ b/microkde/ksystemtray.h @@ -0,0 +1,14 @@ +#ifndef MICROKDE_KSYSTEMTRAY_H +#define MICROKDE_KSYSTEMTRAY_H + +#include <qlabel.h> + +class KSystemTray : public QLabel +{ + Q_OBJECT + public: + KSystemTray( QWidget *parent = 0 ); + void mousePressEvent( QMouseEvent *); +}; + +#endif diff --git a/microkde/ktempfile.cpp b/microkde/ktempfile.cpp new file mode 100644 index 0000000..b9166bd --- a/dev/null +++ b/microkde/ktempfile.cpp @@ -0,0 +1,25 @@ +#include <qtextstream.h> + +#include "ktempfile.h" + +KTempFile::KTempFile() +{ +} + +KTempFile::KTempFile( const QString &filename, const QString &extension ) +{ +} + +void KTempFile::setAutoDelete( bool ) +{ +} + +QString KTempFile::name() +{ + return QString::null; +} + +QTextStream *KTempFile::textStream() +{ + return 0; +} diff --git a/microkde/ktempfile.h b/microkde/ktempfile.h new file mode 100644 index 0000000..20dfa82 --- a/dev/null +++ b/microkde/ktempfile.h @@ -0,0 +1,20 @@ +#ifndef MINIKDE_KTEMPFILE_H +#define MINIKDE_KTEMPFILE_H + +#include <qstring.h> + +class QTextStream; + +class KTempFile +{ + public: + KTempFile(); + KTempFile( const QString &filename, const QString &extension ); + + void setAutoDelete( bool ); + QString name(); + + QTextStream *textStream(); +}; + +#endif diff --git a/microkde/ktextedit.cpp b/microkde/ktextedit.cpp new file mode 100644 index 0000000..4dd6875 --- a/dev/null +++ b/microkde/ktextedit.cpp @@ -0,0 +1,53 @@ + +#include <ktextedit.h> +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + + +KTextEdit::KTextEdit ( QWidget *parent ) : QMultiLineEdit( parent ) +{ + mAllowPopupMenu = false; + mMouseDown = false; + mIgnoreMark = false; +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( this, QPEApplication::RightOnHold ); +#endif +} + +void KTextEdit::mousePressEvent(QMouseEvent *e) +{ + if ( e->button() == LeftButton ) { + mAllowPopupMenu = true; + mYMousePos = mapToGlobal( (e->pos())).y(); + mXMousePos = mapToGlobal( (e->pos())).x(); + } + if ( e->button() == RightButton && !mAllowPopupMenu ) + return; + if ( e->button() == LeftButton ) { + if ( hasMarkedText () ) + mIgnoreMark = !mIgnoreMark; + if ( mIgnoreMark && hasMarkedText () ) { + mMouseDown = false; + return ; + } + } + QMultiLineEdit::mousePressEvent( e ); +} + +void KTextEdit::mouseReleaseEvent(QMouseEvent *e) +{ + QMultiLineEdit::mouseReleaseEvent(e); +} + +void KTextEdit::mouseMoveEvent(QMouseEvent *e) +{ + int diff = mYMousePos - mapToGlobal( (e->pos())).y(); + if ( diff < 0 ) diff = -diff; + int diff2 = mXMousePos - mapToGlobal( (e->pos())).x(); + if ( diff2 < 0 ) diff2 = -diff2; + if ( diff+ diff2 > 20 ) + mAllowPopupMenu = false; + QMultiLineEdit::mouseMoveEvent(e); +} + diff --git a/microkde/ktextedit.h b/microkde/ktextedit.h new file mode 100644 index 0000000..c912f3b --- a/dev/null +++ b/microkde/ktextedit.h @@ -0,0 +1,22 @@ +#ifndef MICROKDE_KTEXTEDIT_H +#define MICROKDE_KTEXTEDIT_H + +#include <qmultilineedit.h> + +class KTextEdit : public QMultiLineEdit +{ + public: + KTextEdit( QWidget *parent ) ; + + private: + bool mAllowPopupMenu; + bool mMouseDown; + bool mIgnoreMark; + int mYMousePos; + int mXMousePos; + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); +}; + +#endif diff --git a/microkde/kunload.h b/microkde/kunload.h new file mode 100644 index 0000000..1c3d00f --- a/dev/null +++ b/microkde/kunload.h @@ -0,0 +1,6 @@ +#ifndef MINIKDE_KUNLOAD_H +#define MINIKDE_KUNLOAD_H + +#define _UNLOAD(p) + +#endif diff --git a/microkde/kurl.cpp b/microkde/kurl.cpp new file mode 100644 index 0000000..2574e25 --- a/dev/null +++ b/microkde/kurl.cpp @@ -0,0 +1,1942 @@ +/* + Copyright (C) 1999 Torben Weis <weis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kurl.h" + +#ifndef KDE_QT_ONLY +#include <kdebug.h> +#include <kglobal.h> +//US#include <kidna.h> +#endif + +#include <stdio.h> +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> +#ifdef _WIN32_ + +#else +#include <unistd.h> +#endif +#include <qurl.h> +#include <qdir.h> +#include <qstringlist.h> +#include <qregexp.h> +//US#include <qstylesheet.h> +#include <qmap.h> +#include <qtextcodec.h> + +static const QString fileProt = "file"; + +static QTextCodec * codecForHint( int encoding_hint /* not 0 ! */ ) +{ + return QTextCodec::codecForMib( encoding_hint ); +} + +static QString encode( const QString& segment, bool encode_slash, int encoding_hint ) +{ + const char *encode_string; + if (encode_slash) + encode_string = "<>#@\"&%?={}|^~[]\'`\\:+/"; + else + encode_string = "<>#@\"&%?={}|^~[]\'`\\:+"; + + QCString local; + if (encoding_hint==0) + local = segment.local8Bit(); + else + { + QTextCodec * textCodec = codecForHint( encoding_hint ); + if (!textCodec) + local = segment.local8Bit(); + else + local = textCodec->fromUnicode( segment ); + } + + int old_length = local.length(); + + if ( !old_length ) + return segment.isNull() ? QString::null : QString(""); // differenciate null and empty + + // a worst case approximation + QChar *new_segment = new QChar[ old_length * 3 + 1 ]; + int new_length = 0; + + for ( int i = 0; i < old_length; i++ ) + { + // 'unsave' and 'reserved' characters + // according to RFC 1738, + // 2.2. URL Character Encoding Issues (pp. 3-4) + // WABA: Added non-ascii + unsigned char character = local[i]; + if ( (character <= 32) || (character >= 127) || + strchr(encode_string, character) ) + { + new_segment[ new_length++ ] = '%'; + + unsigned int c = character / 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + + c = character % 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + + } + else + new_segment[ new_length++ ] = local[i]; + } + + QString result = QString(new_segment, new_length); + delete [] new_segment; + return result; +} + +static QString encodeHost( const QString& segment, bool encode_slash, int encoding_hint ) +{ + // Hostnames are encoded differently + // we use the IDNA transformation instead + + // Note: when merging qt-addon, use QResolver::domainToAscii here +#ifndef KDE_QT_ONLY + Q_UNUSED( encode_slash ); + Q_UNUSED( encoding_hint ); + return KIDNA::toAscii(segment); +#else + return encode(segment, encode_slash, encoding_hint); +#endif +} + +static int hex2int( unsigned int _char ) +{ + if ( _char >= 'A' && _char <='F') + return _char - 'A' + 10; + if ( _char >= 'a' && _char <='f') + return _char - 'a' + 10; + if ( _char >= '0' && _char <='9') + return _char - '0'; + return -1; +} + +// WABA: The result of lazy_encode isn't usable for a URL which +// needs to satisfies RFC requirements. However, the following +// operation will make it usable again: +// encode(decode(...)) +// +// As a result one can see that url.prettyURL() does not result in +// a RFC compliant URL but that the following sequence does: +// KURL(url.prettyURL()).url() + + +static QString lazy_encode( const QString& segment ) +{ + int old_length = segment.length(); + + if ( !old_length ) + return QString::null; + + // a worst case approximation + QChar *new_segment = new QChar[ old_length * 3 + 1 ]; + int new_length = 0; + + for ( int i = 0; i < old_length; i++ ) + { + unsigned int character = segment[i].unicode(); // Don't use latin1() + // It returns 0 for non-latin1 values + // Small set of really ambiguous chars + if ((character < 32) || // Low ASCII + ((character == '%') && // The escape character itself + (i+2 < old_length) && // But only if part of a valid escape sequence! + (hex2int(segment[i+1].unicode())!= -1) && + (hex2int(segment[i+2].unicode())!= -1)) || + (character == '?') || // Start of query delimiter + (character == '@') || // Username delimiter + (character == '#') || // Start of reference delimiter + ((character == 32) && (i+1 == old_length))) // A trailing space + { + new_segment[ new_length++ ] = '%'; + + unsigned int c = character / 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + + c = character % 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + } + else + new_segment[ new_length++ ] = segment[i]; + } + + QString result = QString(new_segment, new_length); + delete [] new_segment; + return result; +} + +static void decode( const QString& segment, QString &decoded, QString &encoded, int encoding_hint=0, bool updateDecoded = true ) +{ + decoded = QString::null; + encoded = segment; + + int old_length = segment.length(); + if ( !old_length ) + return; + + QTextCodec *textCodec = 0; + if (encoding_hint) + textCodec = codecForHint( encoding_hint ); + + if (!textCodec) + textCodec = QTextCodec::codecForLocale(); + + QCString csegment = textCodec->fromUnicode(segment); + // Check if everything went ok + if (textCodec->toUnicode(csegment) != segment) + { + // Uh oh + textCodec = codecForHint( 106 ); // Fall back to utf-8 + csegment = textCodec->fromUnicode(segment); + } + old_length = csegment.length(); + + int new_length = 0; + int new_length2 = 0; + + // make a copy of the old one + char *new_segment = new char[ old_length + 1 ]; + QChar *new_usegment = new QChar[ old_length * 3 + 1 ]; + + int i = 0; + while( i < old_length ) + { + bool bReencode = false; + unsigned char character = csegment[ i++ ]; + if ((character <= ' ') || (character > 127)) + bReencode = true; + + new_usegment [ new_length2++ ] = character; + if (character == '%' ) + { + int a = i+1 < old_length ? hex2int( csegment[i] ) : -1; + int b = i+1 < old_length ? hex2int( csegment[i+1] ) : -1; + if ((a == -1) || (b == -1)) // Only replace if sequence is valid + { + // Contains stray %, make sure to re-encode! + bReencode = true; + } + else + { + // Valid %xx sequence + character = a * 16 + b; // Replace with value of %dd + if (!character && updateDecoded) + break; // Stop at %00 + + new_usegment [ new_length2++ ] = (unsigned char) csegment[i++]; + new_usegment [ new_length2++ ] = (unsigned char) csegment[i++]; + } + } + if (bReencode) + { + new_length2--; + new_usegment [ new_length2++ ] = '%'; + + unsigned int c = character / 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_usegment[ new_length2++ ] = c; + + c = character % 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_usegment[ new_length2++ ] = c; + } + + new_segment [ new_length++ ] = character; + } + new_segment [ new_length ] = 0; + + encoded = QString( new_usegment, new_length2); + + // Encoding specified + if (updateDecoded) + { + QByteArray array; + array.setRawData(new_segment, new_length); + decoded = textCodec->toUnicode( array, new_length ); + array.resetRawData(new_segment, new_length); + QCString validate = textCodec->fromUnicode(decoded); + + if (strcmp(validate.data(), new_segment) != 0) + { + decoded = QString::fromLocal8Bit(new_segment, new_length); + } + } + + delete [] new_segment; + delete [] new_usegment; +} + +static QString decode(const QString &segment, int encoding_hint = 0) +{ + QString result; + QString tmp; + decode(segment, result, tmp, encoding_hint); + return result; +} + +static QString cleanpath(const QString &path, bool cleanDirSeparator=true) +{ + if (path.isEmpty()) return QString::null; + int len = path.length(); + bool slash = (len && path[len-1] == '/') || + (len > 1 && path[len-2] == '/' && path[len-1] == '.'); + + // The following code cleans up directory path much like + // QDir::cleanDirPath() except it can be made to ignore multiple + // directory separators by setting the flag to false. That fixes + // bug# 15044, mail.altavista.com and other similar brain-dead server + // implementations that do not follow what has been specified in + // RFC 2396!! (dA) + QString result; + int cdUp, orig_pos, pos; + + cdUp = 0; + pos = orig_pos = len; + while ( pos && (pos = path.findRev('/',--pos)) != -1 ) + { + len = orig_pos - pos - 1; + if ( len == 2 && path[pos+1] == '.' && path[pos+2] == '.' ) + cdUp++; + else + { + // Ignore any occurances of '.' + // This includes entries that simply do not make sense like /..../ + if ( (len || !cleanDirSeparator) && + (len != 1 || path[pos+1] != '.' ) ) + { + if ( !cdUp ) + result.prepend(path.mid(pos, len+1)); + else + cdUp--; + } + } + orig_pos = pos; + } + + if ( result.isEmpty() ) + result = "/"; + else if ( slash && result.at(result.length()-1) != '/' ) + result.append('/'); + + return result; +} + +bool KURL::isRelativeURL(const QString &_url) +{ + int len = _url.length(); + if (!len) return true; // Very short relative URL. + const QChar *str = _url.unicode(); + + // Absolute URL must start with alpha-character + if (!isalpha(str[0].latin1())) + return true; // Relative URL + + for(int i = 1; i < len; i++) + { + char c = str[i].latin1(); // Note: non-latin1 chars return 0! + if (c == ':') + return false; // Absolute URL + + // Protocol part may only contain alpha, digit, + or - + if (!isalpha(c) && !isdigit(c) && (c != '+') && (c != '-')) + return true; // Relative URL + } + // URL did not contain ':' + return true; // Relative URL +} + +KURL::List::List(const KURL &url) +{ + append( url ); +} + +KURL::List::List(const QStringList &list) +{ + for (QStringList::ConstIterator it = list.begin(); + it != list.end(); + it++) + { + append( KURL(*it) ); + } +} + +QStringList KURL::List::toStringList() const +{ + QStringList lst; + for( KURL::List::ConstIterator it = begin(); + it != end(); + it++) + { + lst.append( (*it).url() ); + } + return lst; +} + + +KURL::KURL() +{ + reset(); +} + +KURL::~KURL() +{ +} + + +KURL::KURL( const QString &url, int encoding_hint ) +{ + reset(); + parse( url, encoding_hint ); +} + +KURL::KURL( const char * url, int encoding_hint ) +{ + reset(); + parse( QString::fromLatin1(url), encoding_hint ); +} + +KURL::KURL( const QCString& url, int encoding_hint ) +{ + reset(); + parse( QString::fromLatin1(url), encoding_hint ); +} + +KURL::KURL( const KURL& _u ) +{ + *this = _u; +} + +QDataStream & operator<< (QDataStream & s, const KURL & a) +{ + QString QueryForWire=a.m_strQuery_encoded; + if (!a.m_strQuery_encoded.isNull()) + QueryForWire.prepend("?"); + + s << a.m_strProtocol << a.m_strUser << a.m_strPass << a.m_strHost + << a.m_strPath << a.m_strPath_encoded << QueryForWire << a.m_strRef_encoded + << Q_INT8(a.m_bIsMalformed ? 1 : 0) << a.m_iPort; + return s; +} + +QDataStream & operator>> (QDataStream & s, KURL & a) +{ + Q_INT8 malf; + QString QueryFromWire; + s >> a.m_strProtocol >> a.m_strUser >> a.m_strPass >> a.m_strHost + >> a.m_strPath >> a.m_strPath_encoded >> QueryFromWire >> a.m_strRef_encoded + >> malf >> a.m_iPort; + a.m_bIsMalformed = (malf != 0); + + if ( QueryFromWire.isEmpty() ) + a.m_strQuery_encoded = QString::null; + else + a.m_strQuery_encoded = QueryFromWire.mid(1); + + return s; +} + +#ifndef QT_NO_NETWORKPROTOCOL +KURL::KURL( const QUrl &u ) +{ + *this = u; +} +#endif + +KURL::KURL( const KURL& _u, const QString& _rel_url, int encoding_hint ) +{ + // WORKAROUND THE RFC 1606 LOOPHOLE THAT ALLOWS + // http:/index.html AS A VALID SYNTAX FOR RELATIVE + // URLS. ( RFC 2396 section 5.2 item # 3 ) + QString rUrl = _rel_url; + int len = _u.m_strProtocol.length(); + if ( !_u.m_strHost.isEmpty() && !rUrl.isEmpty() && + rUrl.find( _u.m_strProtocol, 0, false ) == 0 && + rUrl[len] == ':' && (rUrl[len+1] != '/' || + (rUrl[len+1] == '/' && rUrl[len+2] != '/')) ) + { + rUrl.remove( 0, rUrl.find( ':' ) + 1 ); + } + + if ( rUrl.isEmpty() ) + { + *this = _u; + } + else if ( rUrl[0] == '#' ) + { + *this = _u; + QString ref = decode(rUrl.mid(1), encoding_hint); + if ( ref.isNull() ) + ref = ""; // we know there was an (empty) html ref, we saw the '#' + setHTMLRef( ref ); + } + else if ( isRelativeURL( rUrl) ) + { + *this = _u; + m_strQuery_encoded = QString::null; + m_strRef_encoded = QString::null; + if ( rUrl[0] == '/') + { + if ((rUrl.length() > 1) && (rUrl[1] == '/')) + { + m_strHost = QString::null; + } + m_strPath = QString::null; + m_strPath_encoded = QString::null; + } + else if ( rUrl[0] != '?' ) + { + int pos = m_strPath.findRev( '/' ); + if (pos >= 0) + m_strPath.truncate(pos); + m_strPath += '/'; + if (!m_strPath_encoded.isEmpty()) + { + pos = m_strPath_encoded.findRev( '/' ); + if (pos >= 0) + m_strPath_encoded.truncate(pos); + m_strPath_encoded += '/'; + } + } + else + { + if ( m_strPath.isEmpty() ) + m_strPath = '/'; + } + KURL tmp( url() + rUrl, encoding_hint); + *this = tmp; + cleanPath(false); + } + else + { + KURL tmp( rUrl, encoding_hint); + *this = tmp; + // Preserve userinfo if applicable. + if (!_u.m_strUser.isEmpty() && m_strUser.isEmpty() && (_u.m_strHost == m_strHost) && (_u.m_strProtocol == m_strProtocol)) + { + m_strUser = _u.m_strUser; + m_strPass = _u.m_strPass; + } + } +} + +void KURL::reset() +{ + m_strProtocol = QString::null; + m_strUser = QString::null; + m_strPass = QString::null; + m_strHost = QString::null; + m_strPath = QString::null; + m_strPath_encoded = QString::null; + m_strQuery_encoded = QString::null; + m_strRef_encoded = QString::null; + m_bIsMalformed = true; + m_iPort = 0; +} + +bool KURL::isEmpty() const +{ + return (m_strPath.isEmpty() && m_strProtocol.isEmpty()); +} + +void KURL::parse( const QString& _url, int encoding_hint ) +{ + //kdDebug(126) << "parse " << _url << endl; + // Return immediately whenever the given url + // is empty or null. + if ( _url.isEmpty() ) + { + m_strProtocol = _url; + return; + } + + QString port; + bool badHostName = false; + int start = 0; + uint len = _url.length(); + const QChar* buf = _url.unicode(); + const QChar* orig = buf; + + QChar delim; + QString tmp; + + uint pos = 0; + + // Node 1: Accept alpha or slash + QChar x = buf[pos++]; + if ( x == '/' ) + goto Node9; + if ( !isalpha( (int)x ) ) + goto NodeErr; + + // Node 2: Accept any amount of (alpha|digit|'+'|'-') + // '.' is not currently accepted, because current KURL may be confused. + // Proceed with :// :/ or : + while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) || + buf[pos] == '+' || buf[pos] == '-')) pos++; + + if ( pos+2 < len && buf[pos] == ':' && buf[pos+1] == '/' && buf[pos+2] == '/' ) + { + m_strProtocol = QString( orig, pos ).lower(); + pos += 3; + } + else if (pos+1 < len && buf[pos] == ':' ) // Need to always compare length()-1 otherwise KURL passes "http:" as legal!! + { + m_strProtocol = QString( orig, pos ).lower(); + //kdDebug(126)<<"setting protocol to "<<m_strProtocol<<endl; + pos++; + start = pos; + goto Node9; + } + else + goto NodeErr; + + //Node 3: We need at least one character here + if ( pos == len ) + goto NodeErr; + start = pos; + + // Node 4: Accept any amount of characters. + if (buf[pos] == '[') // An IPv6 host follows. + goto Node8; + // Terminate on / or @ or ? or # or " or ; or < + x = buf[pos]; + while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') ) + { + if ((x == '\"') || (x == ';') || (x == '<')) + badHostName = true; + if (++pos == len) + break; + x = buf[pos]; + } + if ( pos == len ) + { + if (badHostName) + goto NodeErr; + + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + goto NodeOk; + } + if ( x == '@' ) + { + m_strUser = decode(QString( buf + start, pos - start ), encoding_hint); + pos++; + goto Node7; + } + else if ( (x == '/') || (x == '?') || (x == '#')) + { + if (badHostName) + goto NodeErr; + + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + start = pos; + goto Node9; + } + else if ( x != ':' ) + goto NodeErr; + m_strUser = decode(QString( buf + start, pos - start ), encoding_hint); + pos++; + + // Node 5: We need at least one character + if ( pos == len ) + goto NodeErr; + start = pos++; + + // Node 6: Read everything until @, /, ? or # + while( (pos < len) && + (buf[pos] != '@') && + (buf[pos] != '/') && + (buf[pos] != '?') && + (buf[pos] != '#')) pos++; + // If we now have a '@' the ':' seperates user and password. + // Otherwise it seperates host and port. + if ( (pos == len) || (buf[pos] != '@') ) + { + // Ok the : was used to separate host and port + if (badHostName) + goto NodeErr; + setHost(m_strUser); + m_strUser = QString::null; + QString tmp( buf + start, pos - start ); + char *endptr; + m_iPort = (unsigned short int)strtol(tmp.ascii(), &endptr, 10); + if ((pos == len) && (strlen(endptr) == 0)) + goto NodeOk; + // there is more after the digits + pos -= strlen(endptr); + start = pos++; + goto Node9; + } + m_strPass = decode(QString( buf + start, pos - start), encoding_hint); + pos++; + + // Node 7: We need at least one character + Node7: + if ( pos == len ) + goto NodeErr; + + Node8: + if (buf[pos] == '[') + { + // IPv6 address + start = ++pos; // Skip '[' + + if (pos == len) + { + badHostName = true; + goto NodeErr; + } + // Node 8b: Read everything until ] or terminate + badHostName = false; + x = buf[pos]; + while( (x != ']') ) + { + if ((x == '\"') || (x == ';') || (x == '<')) + badHostName = true; + if (++pos == len) + { + badHostName = true; + break; + } + x = buf[pos]; + } + if (badHostName) + goto NodeErr; + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + if (pos < len) pos++; // Skip ']' + if (pos == len) + goto NodeOk; + } + else + { + // Non IPv6 address + start = pos; + + // Node 8b: Read everything until / : or terminate + badHostName = false; + x = buf[pos]; + while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') ) + { + if ((x == '\"') || (x == ';') || (x == '<')) + badHostName = true; + if (++pos == len) + break; + x = buf[pos]; + } + if (badHostName) + goto NodeErr; + if ( pos == len ) + { + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + goto NodeOk; + } + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + } + x = buf[pos]; + if ( x == '/' ) + { + start = pos++; + goto Node9; + } + else if ( x != ':' ) + goto NodeErr; + pos++; + + // Node 8a: Accept at least one digit + if ( pos == len ) + goto NodeErr; + start = pos; + if ( !isdigit( buf[pos++] ) ) + goto NodeErr; + + // Node 8b: Accept any amount of digits + while( pos < len && isdigit( buf[pos] ) ) pos++; + port = QString( buf + start, pos - start ); + m_iPort = port.toUShort(); + if ( pos == len ) + goto NodeOk; + start = pos++; + + Node9: // parse path until query or reference reached + + while( pos < len && buf[pos] != '#' && buf[pos]!='?' ) pos++; + + tmp = QString( buf + start, pos - start ); + //kdDebug(126)<<" setting encoded path&query to:"<<tmp<<endl; + setEncodedPath( tmp, encoding_hint ); + + if ( pos == len ) + goto NodeOk; + + //Node10: // parse query or reference depending on what comes first + delim = (buf[pos++]=='#'?'?':'#'); + + start = pos; + + while(pos < len && buf[pos]!=delim ) pos++; + + tmp = QString(buf + start, pos - start); + if (delim=='#') + setQuery(tmp, encoding_hint); + else + m_strRef_encoded = tmp; + + if (pos == len) + goto NodeOk; + + //Node11: // feed the rest into the remaining variable + tmp = QString( buf + pos + 1, len - pos - 1); + if (delim == '#') + m_strRef_encoded = tmp; + else + setQuery(tmp, encoding_hint); + + NodeOk: + //kdDebug(126)<<"parsing finished. m_strProtocol="<<m_strProtocol<<" m_strHost="<<m_strHost<<" m_strPath="<<m_strPath<<endl; + m_bIsMalformed = false; // Valid URL + + //kdDebug()<<"Prot="<<m_strProtocol<<"\nUser="<<m_strUser<<"\nPass="<<m_strPass<<"\nHost="<<m_strHost<<"\nPath="<<m_strPath<<"\nQuery="<<m_strQuery_encoded<<"\nRef="<<m_strRef_encoded<<"\nPort="<<m_iPort<<endl; + if (m_strProtocol.isEmpty()) + { + m_strProtocol = fileProt; + } + return; + + NodeErr: +// kdDebug(126) << "KURL couldn't parse URL \"" << _url << "\"" << endl; + reset(); + m_strProtocol = _url; +} + +KURL& KURL::operator=( const QString& _url ) +{ + reset(); + parse( _url ); + + return *this; +} + +KURL& KURL::operator=( const char * _url ) +{ + reset(); + parse( QString::fromLatin1(_url) ); + + return *this; +} + +#ifndef QT_NO_NETWORKPROTOCOL +KURL& KURL::operator=( const QUrl & u ) +{ + m_strProtocol = u.protocol(); + m_strUser = u.user(); + m_strPass = u.password(); + m_strHost = u.host(); + m_strPath = u.path( FALSE ); + m_strPath_encoded = QString::null; + m_strQuery_encoded = u.query(); + m_strRef_encoded = u.ref(); + m_bIsMalformed = !u.isValid(); + m_iPort = u.port(); + + return *this; +} +#endif + +KURL& KURL::operator=( const KURL& _u ) +{ + m_strProtocol = _u.m_strProtocol; + m_strUser = _u.m_strUser; + m_strPass = _u.m_strPass; + m_strHost = _u.m_strHost; + m_strPath = _u.m_strPath; + m_strPath_encoded = _u.m_strPath_encoded; + m_strQuery_encoded = _u.m_strQuery_encoded; + m_strRef_encoded = _u.m_strRef_encoded; + m_bIsMalformed = _u.m_bIsMalformed; + m_iPort = _u.m_iPort; + + return *this; +} + +bool KURL::operator==( const KURL& _u ) const +{ + if ( isMalformed() || _u.isMalformed() ) + return false; + + if ( m_strProtocol == _u.m_strProtocol && + m_strUser == _u.m_strUser && + m_strPass == _u.m_strPass && + m_strHost == _u.m_strHost && + m_strPath == _u.m_strPath && + // The encoded path may be null, but the URLs are still equal (David) + ( m_strPath_encoded.isNull() || _u.m_strPath_encoded.isNull() || + m_strPath_encoded == _u.m_strPath_encoded ) && + m_strQuery_encoded == _u.m_strQuery_encoded && + m_strRef_encoded == _u.m_strRef_encoded && + m_iPort == _u.m_iPort ) + { + return true; + } + + return false; +} + +bool KURL::operator==( const QString& _u ) const +{ + KURL u( _u ); + return ( *this == u ); +} + +bool KURL::cmp( const KURL &u, bool ignore_trailing ) const +{ + return equals( u, ignore_trailing ); +} + +bool KURL::equals( const KURL &_u, bool ignore_trailing ) const +{ + if ( isMalformed() || _u.isMalformed() ) + return false; + + if ( ignore_trailing ) + { + QString path1 = path(1); + QString path2 = _u.path(1); + if ( path1 != path2 ) + return false; + + if ( m_strProtocol == _u.m_strProtocol && + m_strUser == _u.m_strUser && + m_strPass == _u.m_strPass && + m_strHost == _u.m_strHost && + m_strQuery_encoded == _u.m_strQuery_encoded && + m_strRef_encoded == _u.m_strRef_encoded && + m_iPort == _u.m_iPort ) + return true; + + return false; + } + + return ( *this == _u ); +} + +bool KURL::isParentOf( const KURL& _u ) const +{ + if ( isMalformed() || _u.isMalformed() ) + return false; + + if ( m_strProtocol == _u.m_strProtocol && + m_strUser == _u.m_strUser && + m_strPass == _u.m_strPass && + m_strHost == _u.m_strHost && + m_strQuery_encoded == _u.m_strQuery_encoded && + m_strRef_encoded == _u.m_strRef_encoded && + m_iPort == _u.m_iPort ) + { + if ( path().isEmpty() || _u.path().isEmpty() ) + return false; // can't work with implicit paths + + QString p1( cleanpath( path() ) ); + if ( p1.at(p1.length()-1) != '/' ) + p1 += '/'; + QString p2( cleanpath( _u.path() ) ); + if ( p2.at(p2.length()-1) != '/' ) + p2 += '/'; + + //kdDebug(126) << "p1=" << p1 << endl; + //kdDebug(126) << "p2=" << p2 << endl; + //kdDebug(126) << "p1.length()=" << p1.length() << endl; + //kdDebug(126) << "p2.left(!$)=" << p2.left( p1.length() ) << endl; + return p2.startsWith( p1 ); + } + return false; +} + +void KURL::setFileName( const QString& _txt ) +{ + m_strRef_encoded = QString::null; + int i = 0; + while( _txt[i] == '/' ) ++i; + QString tmp; + if ( i ) + tmp = _txt.mid( i ); + else + tmp = _txt; + + QString path = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded; + if ( path.isEmpty() ) + path = "/"; + else + { + int lastSlash = path.findRev( '/' ); + if ( lastSlash == -1) + { + // The first character is not a '/' ??? + // This looks strange ... + path = "/"; + } + else if ( path.right(1) != "/" ) + path.truncate( lastSlash+1 ); // keep the "/" + } + if (m_strPath_encoded.isEmpty()) + { + path += tmp; + setPath( path ); + } + else + { + path += encode_string(tmp); + setEncodedPath( path ); + } + cleanPath(); +} + +void KURL::cleanPath( bool cleanDirSeparator ) // taken from the old KURL +{ + m_strPath = cleanpath(m_strPath, cleanDirSeparator); + // WABA: Is this safe when "/../" is encoded with %? + m_strPath_encoded = cleanpath(m_strPath_encoded, cleanDirSeparator); +} + +static QString trailingSlash( int _trailing, const QString &path ) +{ + QString result = path; + + if ( _trailing == 0 ) + return result; + else if ( _trailing == 1 ) + { + int len = result.length(); + if ( len == 0 ) + result = QString::null; + else if ( result[ len - 1 ] != '/' ) + result += "/"; + return result; + } + else if ( _trailing == -1 ) + { + if ( result == "/" ) + return result; + int len = result.length(); + if ( len != 0 && result[ len - 1 ] == '/' ) + result.truncate( len - 1 ); + return result; + } + else { + assert( 0 ); + return QString::null; + } +} + +void KURL::adjustPath( int _trailing ) +{ + if (!m_strPath_encoded.isEmpty()) + { + m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded ); + } + m_strPath = trailingSlash( _trailing, m_strPath ); +} + + +QString KURL::encodedPathAndQuery( int _trailing, bool _no_empty_path, int encoding_hint ) const +{ + QString tmp; + if (!m_strPath_encoded.isEmpty() && encoding_hint == 0) + { + tmp = trailingSlash( _trailing, m_strPath_encoded ); + } + else + { + tmp = path( _trailing ); + if ( _no_empty_path && tmp.isEmpty() ) + tmp = "/"; + tmp = encode( tmp, false, encoding_hint ); + } + + // TODO apply encoding_hint to the query + if (!m_strQuery_encoded.isNull()) + tmp += '?' + m_strQuery_encoded; + return tmp; +} + +void KURL::setEncodedPath( const QString& _txt, int encoding_hint ) +{ + m_strPath_encoded = _txt; + + decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint ); + // Throw away encoding for local files, makes file-operations faster. + if (m_strProtocol == fileProt) + m_strPath_encoded = QString::null; +} + + +void KURL::setEncodedPathAndQuery( const QString& _txt, int encoding_hint ) +{ + int pos = _txt.find( '?' ); + if ( pos == -1 ) + { + setEncodedPath(_txt, encoding_hint); + m_strQuery_encoded = QString::null; + } + else + { + setEncodedPath(_txt.left( pos ), encoding_hint); + setQuery(_txt.right(_txt.length() - pos - 1), encoding_hint); + } +} + +QString KURL::path( int _trailing ) const +{ + return trailingSlash( _trailing, path() ); +} + +bool KURL::isLocalFile() const +{ + if ( (m_strProtocol != fileProt ) || hasSubURL() ) + return false; + + if (m_strHost.isEmpty() || (m_strHost == "localhost")) + return true; + + char hostname[ 256 ]; + hostname[ 0 ] = '\0'; +#ifdef _WIN32_ + // pending LR fixme + //hostname = "localhost"; +#else + if (!gethostname( hostname, 255 )) + hostname[sizeof(hostname)-1] = '\0'; +#endif + for(char *p = hostname; *p; p++) + *p = tolower(*p); + + return (m_strHost == hostname); +} + +void KURL::setFileEncoding(const QString &encoding) +{ + if (!isLocalFile()) + return; + + QString q = query(); + + if (!q.isEmpty() && (q[0] == '?')) + q = q.mid(1); + + QStringList args = QStringList::split('&', q); + for(QStringList::Iterator it = args.begin(); + it != args.end();) + { + QString s = decode_string(*it); + if (s.startsWith("charset=")) +//US changed erase into remove ??? + it = args.remove(it); + else + ++it; + } + if (!encoding.isEmpty()) + args.append("charset="+encode_string(encoding)); + + if (args.isEmpty()) + setQuery(QString::null); + else + setQuery(args.join("&")); +} + +QString KURL::fileEncoding() const +{ + if (!isLocalFile()) + return QString::null; + + QString q = query(); + + if (q.isEmpty()) + return QString::null; + + if (q[0] == '?') + q = q.mid(1); + + QStringList args = QStringList::split('&', q); + for(QStringList::ConstIterator it = args.begin(); + it != args.end(); + ++it) + { + QString s = decode_string(*it); + if (s.startsWith("charset=")) + return s.mid(8); + } + return QString::null; +} + +bool KURL::hasSubURL() const +{ + if ( m_strProtocol.isEmpty() || m_bIsMalformed ) + return false; + if (m_strRef_encoded.isEmpty()) + return false; + if (m_strRef_encoded.startsWith("gzip:")) + return true; + if (m_strRef_encoded.startsWith("bzip:")) + return true; + if (m_strRef_encoded.startsWith("bzip2:")) + return true; + if (m_strRef_encoded.startsWith("tar:")) + return true; + if ( m_strProtocol == "error" ) // anything that starts with error: has suburls + return true; + return false; +} + +QString KURL::url( int _trailing, int encoding_hint ) const +{ + if( m_bIsMalformed ) + { + // Return the whole url even when the url is + // malformed. Under such conditions the url + // is stored in m_strProtocol. + return m_strProtocol; + } + + QString u = m_strProtocol; + if (!u.isEmpty()) + u += ":"; + + if ( hasHost() ) + { + u += "//"; + if ( hasUser() ) + { + u += encode(m_strUser, true, encoding_hint); + if ( hasPass() ) + { + u += ":"; + u += encode(m_strPass, true, encoding_hint); + } + u += "@"; + } + bool IPv6 = (m_strHost.find(':') != -1); + if (IPv6) + u += '[' + m_strHost + ']'; + else + u += encodeHost(m_strHost, true, encoding_hint); + if ( m_iPort != 0 ) { + QString buffer; + buffer.sprintf( ":%u", m_iPort ); + u += buffer; + } + } + + u += encodedPathAndQuery( _trailing, false, encoding_hint ); + + if ( hasRef() ) + { + u += "#"; + u += m_strRef_encoded; + } + + return u; +} + +QString KURL::prettyURL( int _trailing ) const +{ + if( m_bIsMalformed ) + { + // Return the whole url even when the url is + // malformed. Under such conditions the url + // is stored in m_strProtocol. + return m_strProtocol; + } + + QString u = m_strProtocol; + if (!u.isEmpty()) + u += ":"; + + if ( hasHost() ) + { + u += "//"; + if ( hasUser() ) + { + u += lazy_encode(m_strUser); + // Don't show password! + u += "@"; + } + bool IPv6 = (m_strHost.find(':') != -1); + if (IPv6) + { + u += '[' + m_strHost + ']'; + } + else + { + u += lazy_encode(m_strHost); + } + if ( m_iPort != 0 ) { + QString buffer; + buffer.sprintf( ":%u", m_iPort ); + u += buffer; + } + } + + u += trailingSlash( _trailing, lazy_encode( m_strPath ) ); + if (!m_strQuery_encoded.isNull()) + u += '?' + m_strQuery_encoded; + + if ( hasRef() ) + { + u += "#"; + u += m_strRef_encoded; + } + + return u; +} + +QString KURL::prettyURL( int _trailing, AdjustementFlags _flags) const +{ + QString u = prettyURL(_trailing); + if (_flags & StripFileProtocol && u.startsWith("file:")) + u.remove(0, 5); + return u; +} + +QString KURL::htmlURL() const +{ +//US QStyleSheet::escape was not in my Qt distribution. Why ??? +//US return QStyleSheet::escape(prettyURL()); + return prettyURL(); +} + +KURL::List KURL::split( const KURL& _url ) +{ + QString ref; + KURL::List lst; + KURL url = _url; + + while(true) + { + KURL u = url; + u.m_strRef_encoded = QString::null; + lst.append(u); + if (url.hasSubURL()) + { + url = KURL(url.m_strRef_encoded); + } + else + { + ref = url.m_strRef_encoded; + break; + } + } + + // Set HTML ref in all URLs. + KURL::List::Iterator it; + for( it = lst.begin() ; it != lst.end(); ++it ) + { + (*it).m_strRef_encoded = ref; + } + + return lst; +} + +KURL::List KURL::split( const QString& _url ) +{ + return split(KURL(_url)); +} + +KURL KURL::join( const KURL::List & lst ) +{ + if (lst.isEmpty()) return KURL(); + KURL tmp; + + KURL::List::ConstIterator first = lst.fromLast(); + for( KURL::List::ConstIterator it = first; it != lst.end(); --it ) + { + KURL u(*it); + if (it != first) + { + if (!u.m_strRef_encoded) u.m_strRef_encoded = tmp.url(); + else u.m_strRef_encoded += "#" + tmp.url(); // Support more than one suburl thingy + } + tmp = u; + } + + return tmp; +} + +QString KURL::fileName( bool _strip_trailing_slash ) const +{ + QString fname; + if (hasSubURL()) { // If we have a suburl, then return the filename from there + KURL::List list = KURL::split(*this); + KURL::List::Iterator it = list.fromLast(); + return (*it).fileName(_strip_trailing_slash); + } + const QString &path = m_strPath; + + int len = path.length(); + if ( len == 0 ) + return fname; + + if ( _strip_trailing_slash ) + { + while ( len >= 1 && path[ len - 1 ] == '/' ) + len--; + } + else if ( path[ len - 1 ] == '/' ) + return fname; + + // Does the path only consist of '/' characters ? + if ( len == 1 && path[ 0 ] == '/' ) + return fname; + + // Skip last n slashes + int n = 1; + if (!m_strPath_encoded.isEmpty()) + { + // This is hairy, we need the last unencoded slash. + // Count in the encoded string how many encoded slashes follow the last + // unencoded one. + int i = m_strPath_encoded.findRev( '/', len - 1 ); + QString fileName_encoded = m_strPath_encoded.mid(i+1); + n += fileName_encoded.contains("%2f", false); + } + int i = len; + do { + i = path.findRev( '/', i - 1 ); + } + while (--n && (i > 0)); + + // If ( i == -1 ) => the first character is not a '/' + // So it's some URL like file:blah.tgz, return the whole path + if ( i == -1 ) { + if ( len == (int)path.length() ) + fname = path; + else + // Might get here if _strip_trailing_slash is true + fname = path.left( len ); + } + else + { + fname = path.mid( i + 1, len - i - 1 ); // TO CHECK + } + return fname; +} + +void KURL::addPath( const QString& _txt ) +{ + if (hasSubURL()) + { + KURL::List lst = split( *this ); + KURL &u = lst.last(); + u.addPath(_txt); + *this = join( lst ); + return; + } + + m_strPath_encoded = QString::null; + + if ( _txt.isEmpty() ) + return; + + int i = 0; + int len = m_strPath.length(); + // NB: avoid three '/' when building a new path from nothing + if ( len == 0 ) { + while( _txt[i] == '/' ) ++i; + } + // Add the trailing '/' if it is missing + else if ( _txt[0] != '/' && ( len == 0 || m_strPath[ len - 1 ] != '/' ) ) + m_strPath += "/"; + + // No double '/' characters + i = 0; + if ( len != 0 && m_strPath[ len - 1 ] == '/' ) + { + while( _txt[i] == '/' ) + ++i; + } + + m_strPath += _txt.mid( i ); +} + +QString KURL::directory( bool _strip_trailing_slash_from_result, + bool _ignore_trailing_slash_in_path ) const +{ + QString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded; + if ( _ignore_trailing_slash_in_path ) + result = trailingSlash( -1, result ); + + if ( result.isEmpty() || result == "/" ) + return result; + + int i = result.findRev( "/" ); + // If ( i == -1 ) => the first character is not a '/' + // So it's some URL like file:blah.tgz, with no path + if ( i == -1 ) + return QString::null; + + if ( i == 0 ) + { + result = "/"; + return result; + } + + if ( _strip_trailing_slash_from_result ) + result = result.left( i ); + else + result = result.left( i + 1 ); + + if (!m_strPath_encoded.isEmpty()) + result = decode(result); + + return result; +} + + +bool KURL::cd( const QString& _dir ) +{ + if ( _dir.isEmpty() || m_bIsMalformed ) + return false; + + if (hasSubURL()) + { + KURL::List lst = split( *this ); + KURL &u = lst.last(); + u.cd(_dir); + *this = join( lst ); + return true; + } + + // absolute path ? + if ( _dir[0] == '/' ) + { + m_strPath_encoded = QString::null; + m_strPath = _dir; + setHTMLRef( QString::null ); + m_strQuery_encoded = QString::null; + return true; + } + + // Users home directory on the local disk ? + if ( ( _dir[0] == '~' ) && ( m_strProtocol == fileProt )) + { + m_strPath_encoded = QString::null; + m_strPath = QDir::homeDirPath(); + m_strPath += "/"; + m_strPath += _dir.right(m_strPath.length() - 1); + setHTMLRef( QString::null ); + m_strQuery_encoded = QString::null; + return true; + } + + // relative path + // we always work on the past of the first url. + // Sub URLs are not touched. + + // append '/' if necessary + QString p = path(1); + p += _dir; + p = cleanpath( p ); + setPath( p ); + + setHTMLRef( QString::null ); + m_strQuery_encoded = QString::null; + + return true; +} + +KURL KURL::upURL( ) const +{ + if (!query().isEmpty()) + { + KURL u(*this); + u.setQuery(QString::null); + return u; + }; + + if (!hasSubURL()) + { + KURL u(*this); + u.cd("../"); + return u; + } + + // We have a subURL. + KURL::List lst = split( *this ); + if (lst.isEmpty()) + return KURL(); // Huh? + while (true) + { + KURL &u = lst.last(); + QString old = u.path(); + u.cd("../"); + if (u.path() != old) + break; // Finshed. + if (lst.count() == 1) + break; // Finished. + lst.remove(lst.fromLast()); + } + return join( lst ); +} + +QString KURL::htmlRef() const +{ + if ( !hasSubURL() ) + { + return decode( ref() ); + } + + List lst = split( *this ); + return decode( (*lst.begin()).ref() ); +} + +QString KURL::encodedHtmlRef() const +{ + if ( !hasSubURL() ) + { + return ref(); + } + + List lst = split( *this ); + return (*lst.begin()).ref(); +} + +void KURL::setHTMLRef( const QString& _ref ) +{ + if ( !hasSubURL() ) + { + m_strRef_encoded = encode( _ref, true, 0 /*?*/); + return; + } + + List lst = split( *this ); + + (*lst.begin()).setRef( encode( _ref, true, 0 /*?*/) ); + + *this = join( lst ); +} + +bool KURL::hasHTMLRef() const +{ + if ( !hasSubURL() ) + { + return hasRef(); + } + + List lst = split( *this ); + return (*lst.begin()).hasRef(); +} + +void +KURL::setProtocol( const QString& _txt ) +{ + m_strProtocol = _txt; + m_bIsMalformed = false; +} + +void +KURL::setUser( const QString& _txt ) +{ + m_strUser = _txt; +} + +void +KURL::setPass( const QString& _txt ) +{ + m_strPass = _txt; +} + +void +KURL::setHost( const QString& _txt ) +{ +#ifndef KDE_QT_ONLY + m_strHost = KIDNA::toUnicode(_txt); + if (m_strHost.isEmpty()) + m_strHost = _txt.lower(); // Probably an invalid hostname, but... +#else + m_strHost = _txt.lower(); +#endif +} + +void +KURL::setPort( unsigned short int _p ) +{ + m_iPort = _p; +} + +void KURL::setPath( const QString & path ) +{ + if (isEmpty()) + m_bIsMalformed = false; + if (m_strProtocol.isEmpty()) + { + m_strProtocol = fileProt; + } + m_strPath = path; + m_strPath_encoded = QString::null; +} + +void KURL::setDirectory( const QString &dir) +{ +//US this has to be fixed. endsWith is not available in my distribution +//US if ( dir.endsWith("/")) +//US setPath(dir); +//US else + setPath(dir+"/"); +} + +void KURL::setQuery( const QString &_txt, int encoding_hint) +{ + if (!_txt.length()) + { + m_strQuery_encoded = _txt; + return; + } + if (_txt[0] =='?') + m_strQuery_encoded = _txt.mid(1); + else + m_strQuery_encoded = _txt; + + int l = m_strQuery_encoded.length(); + int i = 0; + QString result; + while (i < l) + { + int s = i; + // Re-encode. Break encoded string up according to the reserved + // characters '&:;=/?' and re-encode part by part. + while(i < l) + { + char c = m_strQuery_encoded[i].latin1(); + if ((c == '&') || (c == ':') || (c == ';') || + (c == '=') || (c == '/') || (c == '?')) + break; + i++; + } + if (i > s) + { + QString tmp = m_strQuery_encoded.mid(s, i-s); + QString newTmp; + decode( tmp, newTmp, tmp, encoding_hint, false ); + result += tmp; + } + if (i < l) + { + result += m_strQuery_encoded[i]; + i++; + } + } + m_strQuery_encoded = result; +} + +QString KURL::query() const +{ + if (m_strQuery_encoded.isNull()) + return QString::null; + return '?'+m_strQuery_encoded; +} + +QString KURL::decode_string(const QString &str, int encoding_hint) +{ + return decode(str, encoding_hint); +} + +QString KURL::encode_string(const QString &str, int encoding_hint) +{ + return encode(str, false, encoding_hint); +} + +QString KURL::encode_string_no_slash(const QString &str, int encoding_hint) +{ + return encode(str, true, encoding_hint); +} + +bool urlcmp( const QString& _url1, const QString& _url2 ) +{ + // Both empty ? + if ( _url1.isEmpty() && _url2.isEmpty() ) + return true; + // Only one empty ? + if ( _url1.isEmpty() || _url2.isEmpty() ) + return false; + + KURL::List list1 = KURL::split( _url1 ); + KURL::List list2 = KURL::split( _url2 ); + + // Malformed ? + if ( list1.isEmpty() || list2.isEmpty() ) + return false; + + return ( list1 == list2 ); +} + +bool urlcmp( const QString& _url1, const QString& _url2, bool _ignore_trailing, bool _ignore_ref ) +{ + // Both empty ? + if ( _url1.isEmpty() && _url2.isEmpty() ) + return true; + // Only one empty ? + if ( _url1.isEmpty() || _url2.isEmpty() ) + return false; + + KURL::List list1 = KURL::split( _url1 ); + KURL::List list2 = KURL::split( _url2 ); + + // Malformed ? + if ( list1.isEmpty() || list2.isEmpty() ) + return false; + + unsigned int size = list1.count(); + if ( list2.count() != size ) + return false; + + if ( _ignore_ref ) + { + (*list1.begin()).setRef(QString::null); + (*list2.begin()).setRef(QString::null); + } + + KURL::List::Iterator it1 = list1.begin(); + KURL::List::Iterator it2 = list2.begin(); + for( ; it1 != list1.end() ; ++it1, ++it2 ) + if ( !(*it1).equals( *it2, _ignore_trailing ) ) + return false; + + return true; +} +/*US we do not need this functions + +QMap< QString, QString > KURL::queryItems( int options ) const { + return queryItems(options, 0); +} + +QMap< QString, QString > KURL::queryItems( int options, int encoding_hint ) const { + if ( m_strQuery_encoded.isEmpty() ) + return QMap<QString,QString>(); + + QMap< QString, QString > result; + QStringList items = QStringList::split( '&', m_strQuery_encoded ); + for ( QStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) { + int equal_pos = (*it).find( '=' ); + if ( equal_pos > 0 ) { // = is not the first char... + QString name = (*it).left( equal_pos ); + if ( options & CaseInsensitiveKeys ) + name = name.lower(); + QString value = (*it).mid( equal_pos + 1 ); + if ( value.isEmpty() ) + result.insert( name, QString::fromLatin1("") ); + else { + // ### why is decoding name not neccessary? + value.replace( '+', ' ' ); // + in queries means space + result.insert( name, decode_string( value, encoding_hint ) ); + } + } else if ( equal_pos < 0 ) { // no = + QString name = (*it); + if ( options & CaseInsensitiveKeys ) + name = name.lower(); + result.insert( name, QString::null ); + } + } + + return result; +} + +QString KURL::queryItem( const QString& _item ) const +{ + return queryItem( _item, 0 ); +} + +QString KURL::queryItem( const QString& _item, int encoding_hint ) const +{ + QString item = _item + '='; + if ( m_strQuery_encoded.length() <= 1 ) + return QString::null; + + QStringList items = QStringList::split( '&', m_strQuery_encoded ); + unsigned int _len = item.length(); + for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it ) + { + if ( (*it).startsWith( item ) ) + { + if ( (*it).length() > _len ) + { + QString str = (*it).mid( _len ); + str.replace( '+', ' ' ); // + in queries means space. + return decode_string( str, encoding_hint ); + } + else // empty value + return QString::fromLatin1(""); + } + } + + return QString::null; +} +US we do not need this functions*/ + +void KURL::removeQueryItem( const QString& _item ) +{ + QString item = _item + '='; + if ( m_strQuery_encoded.length() <= 1 ) + return; + + QStringList items = QStringList::split( '&', m_strQuery_encoded ); + for ( QStringList::Iterator it = items.begin(); it != items.end(); ) + { + if ( (*it).startsWith( item ) || (*it == _item) ) + { + QStringList::Iterator deleteIt = it; + ++it; + items.remove(deleteIt); + } + else + { + ++it; + } + } + m_strQuery_encoded = items.join( "&" ); +} + +void KURL::addQueryItem( const QString& _item, const QString& _value, int encoding_hint ) +{ + QString item = _item + '='; + QString value = encode( _value, true, encoding_hint ); + + if (!m_strQuery_encoded.isEmpty()) + m_strQuery_encoded += '&'; + m_strQuery_encoded += item + value; +} + +// static +KURL KURL::fromPathOrURL( const QString& text ) +{ + if ( text.isEmpty() ) + return KURL(); + + KURL url; + if ( text[0] == '/' ) + url.setPath( text ); + else + url = text; + + return url; +} diff --git a/microkde/kurl.h b/microkde/kurl.h new file mode 100644 index 0000000..cd65a1c --- a/dev/null +++ b/microkde/kurl.h @@ -0,0 +1,853 @@ +/* This file is part of the KDE libraries + * Copyright (C) 1999 Torben Weis <weis@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + **/ + +#ifndef __kurl_h__ +#define __kurl_h__ "$Id$" + +#include <qstring.h> +#include <qvaluelist.h> + +class QUrl; +class QStringList; +template <typename K, typename V> class QMap; + +class KURLPrivate; +/** + * Represents and parses a URL. + * + * A prototypical URL looks like: + * <pre> + * protocol:/user:password\@hostname:port/path/to/file.ext#reference + * </pre> + * + * KURL has some restrictions regarding the path + * encoding. KURL works internally with the decoded path and + * and encoded query. For example, + * <pre> + * http://localhost/cgi-bin/test%20me.pl?cmd=Hello%20you + * </pre> + * would result in a decoded path "/cgi-bin/test me.pl" + * and in the encoded query "?cmd=Hello%20you". + * Since path is internally always encoded you may @em not use + * "%00" in the path, although this is OK for the query. + * + * @author Torben Weis <weis@kde.org> + */ +class KURL +{ +public: + enum AdjustementFlags + { + NoAdjustements = 0, + StripFileProtocol = 1 + }; + + /** + * KURL::List is a QValueList that contains KURLs with a few + * convenience methods. + * @see KURL + * @see QValueList + */ + class List : public QValueList<KURL> + { + public: + /** + * Creates an empty List. + */ + List() { } + /** + * Creates a list that contains the given URL as only + * item. + * @param url the url to add. + */ + List(const KURL &url); + /** + * Creates a list that contains the URLs from the given + * list. + * @param list the list containing the URLs as strings + */ + List(const QStringList &list); + /** + * Converts the URLs of this list to a list of strings. + * @return the list of strings + */ + QStringList toStringList() const; + }; + /** + * Constructs an empty URL. + */ + KURL(); + + /** + * Destructs the KURL object. + */ + ~KURL(); + + /** + * Usual constructor, to construct from a string. + * @param url A URL, not a filename. If the URL does not have a protocol + * part, "file:" is assumed. + * It is dangerous to feed unix filenames into this function, + * this will work most of the time but not always. + * For example "/home/Torben%20Weis" will be considered a URL + * pointing to the file "/home/Torben Weis" instead of to the + * file "/home/Torben%20Weis". + * This means that if you have a usual UNIX like path you + * should not use this constructor. + * Instead create an empty url and set the path by using + * @ref setPath(). + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const QString& url, int encoding_hint = 0 ); + /** + * Constructor taking a char * @p url, which is an _encoded_ representation + * of the URL, exactly like the usual constructor. This is useful when + * then URL, in its encoded form, is strictly ascii. + * @param url A encoded URL. If the URL does not have a protocol part, + * "file:" is assumed. + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const char * url, int encoding_hint = 0 ); + /** + * Constructor taking a QCString @p url, which is an _encoded_ representation + * of the URL, exactly like the usual constructor. This is useful when + * then URL, in its encoded form, is strictly ascii. + * @param url A encoded URL. If the URL does not have a protocol part, + * "file:" is assumed. + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const QCString& url, int encoding_hint = 0 ); + /** + * Copy constructor. + * @param u the KURL to copy + */ + KURL( const KURL& u ); + /** + * Converts from a @ref QUrl. + * @param u the QUrl + */ + KURL( const QUrl &u ); + /** + * Constructor allowing relative URLs. + * + * @param _baseurl The base url. + * @param _rel_url A relative or absolute URL. + * If this is an absolute URL then @p _baseurl will be ignored. + * If this is a relative URL it will be combined with @p _baseurl. + * Note that _rel_url should be encoded too, in any case. + * So do NOT pass a path here (use setPath or addPath instead). + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const KURL& _baseurl, const QString& _rel_url, int encoding_hint=0 ); + + /** + * Returns the protocol for the URL (i.e., file, http, etc.). + * @return the protocol of the URL, does not include the colon. If the + * URL is malformed, QString::null will be returned. + **/ + QString protocol() const { return m_bIsMalformed ? QString::null : m_strProtocol; } + /** + * Sets the protocol for the URL (i.e., file, http, etc.) + * @param _txt the new protocol of the URL (without colon) + **/ + void setProtocol( const QString& _txt ); + + /** + * Returns the decoded user name (login, user id, ...) included in the URL. + * @return the user name or QString::null if there is no user name + **/ + QString user() const { return m_strUser; } + /** + * Sets the user name (login, user id, ...) included in the URL. + * + * Special characters in the user name will appear encoded in the URL. + * @param _txt the name of the user or QString::null to remove the user + **/ + void setUser( const QString& _txt ); + /** + * Test to see if this URL has a user name included in it. + * @return true if the URL has an non-empty user name + **/ + bool hasUser() const { return !m_strUser.isEmpty(); } + + /** + * Returns the decoded password (corresponding to \ref user()) included in the URL. + * @return the password or QString::null if it does not exist + **/ + QString pass() const { return m_strPass; } + /** + * Sets the password (corresponding to @ref user()) included in the URL. + * + * Special characters in the password will appear encoded in the URL. + * Note that a password can only appear in a URL string if you also set + * a user. + * @param _txt the password to set or QString::null to remove the password + * @see #setUser + * @see #hasUser + **/ + void setPass( const QString& _txt ); + /** + * Test to see if this URL has a password included in it. + * @return true if there is a non-empty password set + **/ + bool hasPass() const { return !m_strPass.isEmpty(); } + + /** + * Returns the decoded hostname included in the URL. + * @return the name of the host or QString::null if no host is set + **/ + QString host() const { return m_strHost; } + + /** + * Sets the hostname included in the URL. + * + * Special characters in the hostname will appear encoded in the URL. + * @param _txt the new name of the host or QString::null to remove the host + **/ + void setHost( const QString& _txt ); + /** + * Test to see if this URL has a hostname included in it. + * @return true if the URL has a host + **/ + bool hasHost() const { return !m_strHost.isEmpty(); } + + /** + * Returns the port number included in the URL. + * @return the port number. If there is no port number specified in the + * URL, returns 0. + **/ + unsigned short int port() const { return m_iPort; } + /** + * Sets the port number included in the URL. + * @param _p the new port number or 0 to have no port number + **/ + void setPort( unsigned short int _p ); + + /** + * Returns the current decoded path. This does @em not include the query. + * @return the path of the URL (without query), or QString::null if no + * path set. + */ + QString path() const { return m_strPath; } + + /** + * @param _trailing May be ( -1, 0 +1 ). -1 strips a trailing '/', +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. If the URL has no path, then no '/' is added + * anyway. And on the other side: If the path is "/", then this + * character won't be stripped. Reason: "ftp://weis\@host" means something + * completely different than "ftp://weis\@host/". So adding or stripping + * the '/' would really alter the URL, while "ftp://host/path" and + * "ftp://host/path/" mean the same directory. + * + * @return The current decoded path. This does not include the query. Can + * be QString::null if no path is set. + */ + QString path( int _trailing ) const; + + /** + * Sets the path of the URL. The query is not changed by this function. + * + * @param path The new path. This is considered to be decoded. This + * means: %3f does not become decoded + * and the ? does not indicate the start of the query part. + * Can be QString::null to delete the path. + */ + void setPath( const QString& path ); + + /** + * Test to see if this URL has a path is included in it. + * @return true if there is a path + **/ + bool hasPath() const { return !m_strPath.isEmpty(); } + + /** + * Resolves "." and ".." components in path. + * Some servers seem not to like the removal of extra '/' + * even though it is against the specification in RFC 2396. + * + * @param cleanDirSeparator if true, occurrances of consecutive + * directory separators (e.g. /foo//bar) are cleaned up as well. + */ + void cleanPath(bool cleanDirSeparator = true); + + /** + * Add or remove a trailing slash to/from the path. + * @param _trailing May be ( -1, 0 +1 ). -1 strips a trailing '/', +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. If the URL has no path, then no '/' is added + * anyway. And on the other side: If the path is "/", then this + * character won't be stripped. Reason: "ftp://weis\@host" means something + * completely different than "ftp://weis\@host/". So adding or stripping + * the '/' would really alter the URL, while "ftp://host/path" and + * "ftp://host/path/" mean the same directory. + */ + void adjustPath(int _trailing); + + /** + * This is useful for HTTP. It looks first for '?' and decodes then. + * The encoded path is the concatenation of the current path and the query. + * @param _txt the new path and query. + * @param encoding_hint MIB of original encoding of @p _txt . + * @see QTextCodec::mibEnum() + */ + void setEncodedPathAndQuery( const QString& _txt, int encoding_hint = 0 ); + + /** + * Sets the (already encoded) path + * @param _txt the new path + * @param encoding_hint MIB of original encoding of @p _txt . + * @see QTextCodec::mibEnum() + */ + void setEncodedPath(const QString& _txt, int encoding_hint = 0 ); + + /** + * Returns the encoded path and the query. + * + * @param _trailing May be ( -1, 0 +1 ). -1 strips a trailing '/', +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. If the URL has no path, then no '/' is added + * anyway. And on the other side: If the path is "/", then this + * character won't be stripped. Reason: "ftp://weis\@host" means something + * completely different than "ftp://weis\@host/". So adding or stripping + * the '/' would really alter the URL, while "ftp://host/path" and + * "ftp://host/path/" mean the same directory. + * @param _no_empty_path If set to true then an empty path is substituted by "/". + * @param encoding_hint MIB of desired encoding of URL. + * @see QTextCodec::mibEnum() + * @return The concatenation if the encoded path , '?' and the encoded query. + * + */ + QString encodedPathAndQuery( int _trailing = 0, bool _no_empty_path = false, int encoding_hint = 0) const; + + /** + * @param _txt This is considered to be encoded. This has a good reason: + * The query may contain the 0 character. + * + * The query should start with a '?'. If it doesn't '?' is prepended. + * @param encoding_hint Reserved, should be 0. + * @see QTextCodec::mibEnum() + */ + void setQuery( const QString& _txt, int encoding_hint = 0); + + /** + * Returns the query of the URL. + * The query may contain the 0 character. + * If a query is present it always starts with a '?'. + * A single '?' means an empty query. + * An empty string means no query. + * @return The encoded query, or QString::null if there is none. + */ + QString query() const; + + /** + * The reference is @em never decoded automatically. + * @return the undecoded reference, or QString::null if there is none + */ + QString ref() const { return m_strRef_encoded; } + + /** + * Sets the reference part (everything after '#'). + * @param _txt The encoded reference (or QString::null to remove it). + */ + void setRef( const QString& _txt ) { m_strRef_encoded = _txt; } + + /** + * Checks whether the URL has a reference part. + * @return true if the URL has a reference part. In a URL like + * http://www.kde.org/kdebase.tar#tar:/README it would + * return true, too. + */ + bool hasRef() const { return !m_strRef_encoded.isNull(); } + + /** + * Returns the HTML reference (the part of the URL after "#"). + * @return The HTML-style reference. + * @see #split + * @see #hasSubURL + * @see #encodedHtmlRef + */ + QString htmlRef() const; + + /** + * Returns the HTML reference (the part of the URL after "#") in + * encoded form. + * @return The HTML-style reference in its original form. + */ + QString encodedHtmlRef() const; + + /** + * Sets the HTML-style reference. + * + * @param _ref The new reference. This is considered to be @em not encoded in + * contrast to @ref setRef(). Use QString::null to remove it. + * @see htmlRef() + */ + void setHTMLRef( const QString& _ref ); + + /** + * Checks whether there is a HTML reference. + * @return true if the URL has an HTML-style reference. + * @see htmlRef() + */ + bool hasHTMLRef() const; + + /** + * Checks whether the URL is well formed. + * @return false if the URL is malformed. This function does @em not test + * whether sub URLs are well-formed, too. + */ + bool isValid() const { return !m_bIsMalformed; } + /** + * @deprecated + */ + bool isMalformed() const { return !isValid(); } + + /** + * Checks whether the file is local. + * @return true if the file is a plain local file and has no filter protocols + * attached to it. + */ + bool isLocalFile() const; + + /** + * Adds encoding information to url by adding a "charset" parameter. If there + * is already a charset parameter, it will be replaced. + * @param encoding the encoding to add or QString::null to remove the + * encoding. + */ + void setFileEncoding(const QString &encoding); + + /** + * Returns encoding information from url, the content of the "charset" + * parameter. + * @return An encoding suitable for QTextCodec::codecForName() + * or QString::null if not encoding was specified. + */ + QString fileEncoding() const; + + /** + * Checks whether the URL has any sub URLs. See @ref #split() + * for examples for sub URLs. + * @return true if the file has at least one sub URL. + * @see #split + */ + bool hasSubURL() const; + + /** + * Adds to the current path. + * Assumes that the current path is a directory. @p _txt is appended to the + * current path. The function adds '/' if needed while concatenating. + * This means it does not matter whether the current path has a trailing + * '/' or not. If there is none, it becomes appended. If @p _txt + * has a leading '/' then this one is stripped. + * + * @param _txt The text to add. It is considered to be decoded. + */ + void addPath( const QString& _txt ); + + /** + * Returns the value of a certain query item. + * + * @param _item Item whose value we want + * @param encoding_hint MIB of encoding of query. + * + * @return the value of the given query item name or QString::null if the + * specified item does not exist. + */ +/*US we do not need this functions + QString queryItem( const QString& _item ) const; + QString queryItem( const QString& _item, int encoding_hint ) const; +*/ + /** + * Options for @ref #queryItems. Currently, only one option is + * defined: + * + * @param CaseInsensitiveKeys normalize query keys to lowercase. + * + * @since 3.1 + **/ + enum QueryItemsOptions { CaseInsensitiveKeys = 1 }; + + /** + * Returns the list of query items as a map mapping keys to values. + * + * @param options any of @ref QueryItemsOptions <em>or</or>ed together. + * @param encoding_hint MIB of encoding of query. + * + * @return the map of query items or the empty map if the url has no + * query items. + * + * @since 3.1 + */ + QMap< QString, QString > queryItems( int options=0 ) const; + QMap< QString, QString > queryItems( int options, int encoding_hint ) const; + + /** + * Add an additional query item. + * To replace an existing query item, the item should first be + * removed with @ref removeQueryItem() + * + * @param _item Name of item to add + * @param _value Value of item to add + * @param encoding_hint MIB of encoding to use for _value. + * @see QTextCodec::mibEnum() + */ + void addQueryItem( const QString& _item, const QString& _value, int encoding_hint = 0 ); + + /** + * Remove an item from the query. + * + * @param _item Item to be removed + */ + void removeQueryItem( const QString& _item ); + + /** + * Sets the filename of the path. + * In comparison to @ref addPath() this function does not assume that the current + * path is a directory. This is only assumed if the current path ends with '/'. + * + * Any reference is reset. + * + * @param _txt The filename to be set. It is considered to be decoded. If the + * current path ends with '/' then @p _txt int just appended, otherwise + * all text behind the last '/' in the current path is erased and + * @p _txt is appended then. It does not matter whether @p _txt starts + * with '/' or not. + */ + void setFileName( const QString&_txt ); + + /** + * Returns the filename of the path. + * @param _ignore_trailing_slash_in_path This tells whether a trailing '/' should + * be ignored. This means that the function would return "torben" for + * <tt>file:/hallo/torben/</tt> and <tt>file:/hallo/torben</tt>. + * If the flag is set to false, then everything behind the last '/' + * is considered to be the filename. + * @return The filename of the current path. The returned string is decoded. Null + * if there is no file (and thus no path). + */ + QString fileName( bool _ignore_trailing_slash_in_path = true ) const; + + /** + * Returns the directory of the path. + * @param _strip_trailing_slash_from_result tells whether the returned result should end with '/' or not. + * If the path is empty or just "/" then this flag has no effect. + * @param _ignore_trailing_slash_in_path means that <tt>file:/hallo/torben</tt> and + * <tt>file:/hallo/torben/"</tt> would both return <tt>/hallo/</tt> + * or <tt>/hallo</tt> depending on the other flag + * @return The directory part of the current path. Everything between the last and the second last '/' + * is returned. For example <tt>file:/hallo/torben/</tt> would return "/hallo/torben/" while + * <tt>file:/hallo/torben</tt> would return "hallo/". The returned string is decoded. QString::null is returned when there is no path. + */ + QString directory( bool _strip_trailing_slash_from_result = true, + bool _ignore_trailing_slash_in_path = true ) const; + + /** + * Set the directory to @p dir, leaving the filename empty. + */ + void setDirectory(const QString &dir); + + /** + * Changes the directory by descending into the given directory. + * It is assumed the current URL represents a directory. + * If @p dir starts with a "/" the + * current URL will be "protocol://host/dir" otherwise @p _dir will + * be appended to the path. @p _dir can be ".." + * This function won't strip protocols. That means that when you are in + * file:/dir/dir2/my.tgz#tar:/ and you do cd("..") you will + * still be in file:/dir/dir2/my.tgz#tar:/ + * + * @param _dir the directory to change to + * @return true if successful + */ + bool cd( const QString& _dir ); + + /** + * Returns the URL as string, with all escape sequences intact, + * encoded in a given charset. + * This is used in particular for encoding URLs in UTF-8 before using them + * in a drag and drop operation. + * Please note that the string returned by @ref url() will include + * the password of the URL. If you want to show the URL to the + * user, use @ref prettyURL(). + * + * @param _trailing This may be ( -1, 0 +1 ). -1 strips a trailing '/' from the path, +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. + * @param encoding_hint MIB of encoding to use. + * @return The complete URL, with all escape sequences intact, encoded + * in a given charset. + * @see QTextCodec::mibEnum() + * @see prettyURL() + */ + QString url( int _trailing = 0, int encoding_hint = 0) const; + + /** + * Returns the URL as string in human-friendly format. + * Example: + * <pre> + * http://localhost:8080/test.cgi?test=hello world&name=fred + * </pre> + * @param _trailing -1 to strip a trailing '/' from the path, +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. + * @return A human readable URL, with no non-necessary encodings/escaped + * characters. Password will not be shown. + * @see url() + */ + QString prettyURL( int _trailing = 0) const; + + + /** + * Returns the URL as string, escaped for HTML. + * @return A human readable URL, with no non-necessary encodings/escaped + * characters which is html encoded for safe inclusion in html or + * rich text. Password will not be shown. + */ + QString htmlURL() const; + + /** + * Returns the URL as string, escaped for HTML. + * Example: + * <pre> + * http://localhost:8080/test.cgi?test=hello world&name=fred + * </pre> + * @return A human readable URL, with no non-necessary encodings/escaped + * characters. Password will not be shown. + */ + QString prettyURL( int _trailing, AdjustementFlags _flags) const; + // ### BIC: Merge the two above + + /** + * Test to see if the KURL is empty. + * @return true if the URL is empty + **/ + bool isEmpty() const; + + /** + * This function is useful to implement the "Up" button in a file manager for example. + * @ref cd() never strips a sub-protocol. That means that if you are in + * file:/home/x.tgz#gzip:/#tar:/ and hit the up button you expect to see + * file:/home. The algorithm tries to go up on the right-most URL. If that is not + * possible it strips the right most URL. It continues stripping URLs. + * @return a URL that is a level higher + */ + KURL upURL( ) const; + + KURL& operator=( const KURL& _u ); + KURL& operator=( const QString& _url ); + KURL& operator=( const char * _url ); + KURL& operator=( const QUrl & u ); + + bool operator==( const KURL& _u ) const; + bool operator==( const QString& _u ) const; + bool operator!=( const KURL& _u ) const { return !( *this == _u ); } + bool operator!=( const QString& _u ) const { return !( *this == _u ); } + + /** + * The same as equals(), just with a less obvious name. + * Compares this url with @p u. + * @param ignore_trailing set to true to ignore trailing '/' characters. + * @return true if both urls are the same + * @see operator==. This function should be used if you want to + * ignore trailing '/' characters. + * @deprecated + */ + bool cmp( const KURL &u, bool ignore_trailing = false ) const; + + /** + * Compares this url with @p u. + * @param ignore_trailing set to true to ignore trailing '/' characters. + * @return true if both urls are the same + * @see operator==. This function should be used if you want to + * ignore trailing '/' characters. + * @since 3.1 + */ + bool equals( const KURL &u, bool ignore_trailing = false ) const; + + /** + * Checks whether the given URL is parent of this URL. + * For instance, ftp://host/dir/ is a parent of ftp://host/dir/subdir/subsubdir/. + * @return true if this url is a parent of @p u (or the same URL as @p u) + */ + bool isParentOf( const KURL& u ) const; + + /** + * Splits nested URLs like file:/home/weis/kde.tgz#gzip:/#tar:/kdebase + * A URL like http://www.kde.org#tar:/kde/README.hml#ref1 will be split in + * http://www.kde.org and tar:/kde/README.html#ref1. + * That means in turn that "#ref1" is an HTML-style reference and not a new sub URL. + * Since HTML-style references mark + * a certain position in a document this reference is appended to every URL. + * The idea behind this is that browsers, for example, only look at the first URL while + * the rest is not of interest to them. + * + * + * @param _url The URL that has to be split. + * @return An empty list on error or the list of split URLs. + * @see #hasSubURL + */ + static List split( const QString& _url ); + + /** + * Splits nested URLs like file:/home/weis/kde.tgz#gzip:/#tar:/kdebase + * A URL like http://www.kde.org#tar:/kde/README.hml#ref1 will be split in + * http://www.kde.org and tar:/kde/README.html#ref1. + * That means in turn that "#ref1" is an HTML-style reference and not a new sub URL. + * Since HTML-style references mark + * a certain position in a document this reference is appended to every URL. + * The idea behind this is that browsers, for example, only look at the first URL while + * the rest is not of interest to them. + * + * @return An empty list on error or the list of split URLs. + * + * @param _url The URL that has to be split. + * @see #hasSubURL + */ + static List split( const KURL& _url ); + + /** + * Reverses @ref #split(). Only the first URL may have a reference. This reference + * is considered to be HTML-like and is appended at the end of the resulting + * joined URL. + * @param _list the list to join + * @return the joined URL + */ + static KURL join( const List& _list ); + + /** + * Creates a KURL object from a QString representing either an absolute path + * or a real URL. Use this method instead of + * <pre> + * QString someDir = ... + * KURL url = someDir; + * </pre> + * + * Otherwise some characters (e.g. the '#') won't be encoded properly. + * @param text the string representation of the URL to convert + * @return the new KURL + * @since 3.1 + */ + static KURL fromPathOrURL( const QString& text ); + +/** + * Convenience function. + * + * Convert unicoded string to local encoding and use %-style + * encoding for all common delimiters / non-ascii characters. + * @param str String to encode (can be QString::null). + * @param encoding_hint MIB of encoding to use. + * @see QTextCodec::mibEnum() + * @return the encoded string + **/ + static QString encode_string(const QString &str, int encoding_hint = 0); + + /** + * Convenience function. + * + * Convert unicoded string to local encoding and use %-style + * encoding for all common delimiters / non-ascii characters + * as well as the slash '/'. + * @param str String to encode + * @param encoding_hint MIB of encoding to use. + * @see QTextCodec::mibEnum() + **/ + static QString encode_string_no_slash(const QString &str, int encoding_hint = 0); + + /** + * Convenience function. + * + * Decode %-style encoding and convert from local encoding to unicode. + * + * Reverse of encode_string() + * @param str String to decode (can be QString::null). + * @param encoding_hint MIB of original encoding of @p str . + * @see QTextCodec::mibEnum() + **/ + static QString decode_string(const QString &str, int encoding_hint = 0); + + /** + * Convenience function. + * + * Returns whether '_url' is likely to be a "relative" URL instead of + * an "absolute" URL. + * @param _url URL to examine + * @return true when the URL is likely to be "relative", false otherwise. + */ + static bool isRelativeURL(const QString &_url); + +#ifdef KDE_NO_COMPAT +private: +#endif + QString filename( bool _ignore_trailing_slash_in_path = true ) const + { + return fileName(_ignore_trailing_slash_in_path); + } + +protected: + void reset(); + void parse( const QString& _url, int encoding_hint = 0); + +private: + QString m_strProtocol; + QString m_strUser; + QString m_strPass; + QString m_strHost; + QString m_strPath; + QString m_strRef_encoded; + QString m_strQuery_encoded; + bool m_bIsMalformed : 1; + int freeForUse : 7; + unsigned short int m_iPort; + QString m_strPath_encoded; + + friend QDataStream & operator<< (QDataStream & s, const KURL & a); + friend QDataStream & operator>> (QDataStream & s, KURL & a); +private: + KURLPrivate* d; +}; + +/** + * Compares URLs. They are parsed, split and compared. + * Two malformed URLs with the same string representation + * are nevertheless considered to be unequal. + * That means no malformed URL equals anything else. + */ +bool urlcmp( const QString& _url1, const QString& _url2 ); + +/** + * Compares URLs. They are parsed, split and compared. + * Two malformed URLs with the same string representation + * are nevertheless considered to be unequal. + * That means no malformed URL equals anything else. + * + * @param _ignore_trailing Described in @ref KURL::cmp + * @param _ignore_ref If true, disables comparison of HTML-style references. + */ +bool urlcmp( const QString& _url1, const QString& _url2, bool _ignore_trailing, bool _ignore_ref ); + +QDataStream & operator<< (QDataStream & s, const KURL & a); +QDataStream & operator>> (QDataStream & s, KURL & a); + +#endif diff --git a/microkde/kutils/kcmultidialog.cpp b/microkde/kutils/kcmultidialog.cpp new file mode 100644 index 0000000..4136622 --- a/dev/null +++ b/microkde/kutils/kcmultidialog.cpp @@ -0,0 +1,201 @@ +/* + Copyright (c) 2000 Matthias Elter <elter@kde.org> + Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include <qhbox.h> +#include <qvbox.h> +#include <qcursor.h> +#include <qlayout.h> + +#include <klocale.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kmessagebox.h> +//US #include <klibloader.h> +#include <krun.h> +#include <kprocess.h> + +#include "kcmultidialog.h" +//US #include "kcmultidialog.moc" +//US #include "kcmoduleloader.h" + +KCMultiDialog::KCMultiDialog(const QString& baseGroup, QWidget *parent, const char *name, bool modal) + : KDialogBase(IconList, i18n("Configure"), Default |Cancel | Apply | Ok, Ok, + parent, name, modal, true), d(0L) +{ + enableButton(Apply, false); + //connect(this, SIGNAL(aboutToShowPage(QWidget *)), this, SLOT(slotAboutToShow(QWidget *))); + _baseGroup = baseGroup; + mMainWidget = new KJanusWidget( this, "JanusWidget", KJanusWidget::Tabbed ); + setMainWidget(mMainWidget ); +#ifdef DESKTOP_VERSION + resize(640,480); +#else + resize(640,480); + setMaximumSize( KMIN(KGlobal::getDesktopWidth()-5, 640), KMIN(KGlobal::getDesktopHeight()-20, 480)); + //showMaximized(); +#endif + +} + +KCMultiDialog::~KCMultiDialog() +{ +//US moduleDict.setAutoDelete(true); +} + +void KCMultiDialog::slotDefault() +{ + + int curPageIndex = mMainWidget->activePageIndex(); + + QPtrListIterator<KCModule> it(modules); + for (; it.current(); ++it) + { + if (pageIndex((QWidget *)(*it)->parent()) == curPageIndex) + { + (*it)->defaults(); + clientChanged(true); + return; + } + } + +} + +void KCMultiDialog::slotApply() +{ +qDebug("KCMultiDialog::slotApply clicked"); + + QPtrListIterator<KCModule> it(modules); + for (; it.current(); ++it) + (*it)->save(); + clientChanged(false); + + emit applyClicked(); + +} + + +void KCMultiDialog::slotOk() +{ +qDebug("KCMultiDialog::slotOk clicked"); + + QPtrListIterator<KCModule> it(modules); + for (; it.current(); ++it) + (*it)->save(); + accept(); + + emit okClicked(); +} + +void KCMultiDialog::slotHelp() +{ +/*US + KURL url( KURL("help:/"), _docPath ); + + if (url.protocol() == "help" || url.protocol() == "man" || url.protocol() == "info") { + KProcess process; + process << "khelpcenter" + << url.url(); + process.start(KProcess::DontCare); + process.detach(); + } else { + new KRun(url); + } +*/ +} + +void KCMultiDialog::clientChanged(bool state) +{ + enableButton(Apply, state); +} + +/*US +void KCMultiDialog::addModule(const QString& path, bool withfallback) +{ + kdDebug(1208) << "KCMultiDialog::addModule " << path << endl; + + KCModuleInfo info(path, _baseGroup); + + QHBox* page = addHBoxPage(info.moduleName(), info.comment(), + KGlobal::iconLoader()->loadIcon(info.icon(), KIcon::Desktop, KIcon::SizeMedium)); + if(!page) { + KCModuleLoader::unloadModule(info); + return; + } + moduleDict.insert(page, new LoadInfo(path, withfallback)); + if (modules.isEmpty()) + slotAboutToShow(page); +} +*/ +QVBox * KCMultiDialog::getNewVBoxPage( const QString & modulename ) +{ + QVBox *page = mMainWidget->addVBoxPage(modulename , QString::null,QPixmap() ); + return page; + +} +//US special method for microkde. We dop noty want to load everything dynamically. +void KCMultiDialog::addModule(KCModule* module ) //, const QString& modulename, const QString& iconname) +{ + + modules.append(module); + connect(module, SIGNAL(changed(bool)), this, SLOT(clientChanged(bool))); + + +} + +void KCMultiDialog::slotAboutToShow(QWidget *page) +{ +/*US + LoadInfo *loadInfo = moduleDict[page]; + if (!loadInfo) + return; + + QApplication::setOverrideCursor(Qt::WaitCursor); + + moduleDict.remove(page); + + KCModuleInfo info(loadInfo->path, _baseGroup); + + KCModule *module = KCModuleLoader::loadModule(info, loadInfo->withfallback); + + if (!module) + { + QApplication::restoreOverrideCursor(); + KCModuleLoader::showLastLoaderError(this); + delete loadInfo; + return; + } + + module->reparent(page,0,QPoint(0,0),true); + connect(module, SIGNAL(changed(bool)), this, SLOT(clientChanged(bool))); + //setHelp( docpath, QString::null ); + _docPath = info.docPath(); + modules.append(module); + + //KCGlobal::repairAccels( topLevelWidget() ); + + delete loadInfo; + + QApplication::restoreOverrideCursor(); +*/ + +qDebug("KCMultiDialog::slotAboutToShow not implemented"); +} diff --git a/microkde/kutils/kcmultidialog.h b/microkde/kutils/kcmultidialog.h new file mode 100644 index 0000000..63d5d42 --- a/dev/null +++ b/microkde/kutils/kcmultidialog.h @@ -0,0 +1,147 @@ +/* + Copyright (c) 2000 Matthias Elter <elter@kde.org> + Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#ifndef KCMULTIDIALOG_H +#define KCMULTIDIALOG_H + +#include <qptrlist.h> +#include <qptrdict.h> + +#include <kdialogbase.h> +#include <kjanuswidget.h> +#include <kcmodule.h> + + +/** + * A class that offers a @ref KDialogBase containing arbitrary KControl Modules + * + * @short A method that offers a @ref KDialogBase containing arbitrary + * KControl Modules. + * + * @author Matthias Elter <elter@kde.org>, Daniel Molkentin <molkentin@kde.org> + * @since 3.2 + */ +class KCMultiDialog : public KDialogBase +{ + Q_OBJECT + +public: + /** + * Constructs a new KCMultiDialog + * + * @param parent The parent Widget + * @param name The widget name + * @param baseGroup The baseGroup, if you want to call a module out of + * kcontrol, just keep "settings" + * @param modal If you pass true here, the dialog will be modal + **/ + KCMultiDialog(const QString& baseGroup = QString::fromLatin1("settings"), + QWidget *parent=0, const char *name=0, + bool modal=false); + + /** + * Destructor + **/ + virtual ~KCMultiDialog(); + + /** + * Add a module. + * + * @param module Specify the name of the module that is to be added + * to the list of modules the dialog will show. + * + * @param withfallback Try harder to load the module. Might result + * in the module appearing outside the dialog. + **/ +//US void addModule(const QString& module, bool withfallback=true); + + +//US special method for microkde. We dop noty want to load everything dynamically. + void addModule(KCModule* module );//, const QString& modulename, const QString& iconname); + QVBox* getNewVBoxPage(const QString & modulename) ; + + + +protected slots: + /** + * This slot is called when the user presses the "Default" Button + * You can reimplement it if needed. + * + * @note Make sure you call the original implementation! + **/ + virtual void slotDefault(); + + /** + * This slot is called when the user presses the "Apply" Button + * You can reimplement it if needed + * + * @note Make sure you call the original implementation! + **/ + virtual void slotApply(); + + /** + * This slot is called when the user presses the "OK" Button + * You can reimplement it if needed + * + * @note Make sure you call the original implementation! + **/ + virtual void slotOk(); + + /** + * This slot is called when the user presses the "Help" Button + * You can reimplement it if needed + * + * @note Make sure you call the original implementation! + **/ + virtual void slotHelp(); + +private slots: + + void slotAboutToShow(QWidget *); + + void clientChanged(bool state); + +private: +/*US + struct LoadInfo { + LoadInfo(const QString &_path, bool _withfallback) + : path(_path), withfallback(_withfallback) + { } + QString path; + bool withfallback; + }; +*/ + QPtrList<KCModule> modules; +/* + QPtrDict<LoadInfo> moduleDict; + QString _docPath; +*/ + QString _baseGroup; + +//US + KJanusWidget* mMainWidget; + + // For future use + class KCMultiDialogPrivate; + KCMultiDialogPrivate *d; +}; + +#endif //KCMULTIDIALOG_H diff --git a/microkde/microkde.pro b/microkde/microkde.pro new file mode 100644 index 0000000..1e9b022 --- a/dev/null +++ b/microkde/microkde.pro @@ -0,0 +1,170 @@ +TEMPLATE = lib +CONFIG += qt warn_on +#INCLUDEPATH += $(QTDIR)/include . +#DEPENDPATH += $(QTDIR)/include +INCLUDEPATH += . ../ ../kabc ./kdecore ./kdeui ./kio/kfile +#LIBS += -lqtcompat + +TARGET = microkde +DESTDIR= ../bin +DEFINES += DESKTOP_VERSION KDE_QT_ONLY +unix : { +OBJECTS_DIR = obj/unix +MOC_DIR = moc/unix +} +win32: { +DEFINES += _WIN32_ +OBJECTS_DIR = obj/win +MOC_DIR = moc/win +} +include( ../variables.pri ) + + + +HEADERS = \ +qlayoutengine_p.h \ +KDGanttMinimizeSplitter.h \ + kapplication.h \ + kaudioplayer.h \ + kcalendarsystem.h \ + kcalendarsystemgregorian.h \ + kcolorbutton.h \ + kcolordialog.h \ + kcombobox.h \ + kconfig.h \ + kdatetbl.h \ + kdebug.h \ + kdialog.h \ + kdialogbase.h \ + kdirwatch.h \ + keditlistbox.h \ + kemailsettings.h \ + kfiledialog.h \ + kfontdialog.h \ + kglobal.h \ + kglobalsettings.h \ + kiconloader.h \ + klineedit.h \ + klineeditdlg.h \ + kmessagebox.h \ + knotifyclient.h \ + kprinter.h \ + kprocess.h \ + krestrictedline.h \ + krun.h \ + ksimpleconfig.h \ + kstaticdeleter.h \ + ksystemtray.h \ + ktempfile.h \ + ktextedit.h \ + kunload.h \ + kurl.h \ + kdeui/kguiitem.h \ + kdeui/kcmodule.h \ + kdeui/kbuttonbox.h \ + kdeui/klistbox.h \ + kdeui/klistview.h \ + kdeui/kjanuswidget.h \ + kdeui/kseparator.h \ + kdeui/knuminput.h \ + kdeui/knumvalidator.h \ + kdeui/ksqueezedtextlabel.h \ + kio/job.h \ + kio/kfile/kurlrequester.h \ + kresources/resource.h \ + kresources/factory.h \ + kresources/managerimpl.h \ + kresources/manager.h \ + kresources/selectdialog.h \ + kresources/configpage.h \ + kresources/configwidget.h \ + kresources/configdialog.h \ + kresources/kcmkresources.h \ + kdecore/kmdcodec.h \ + kdecore/kconfigbase.h \ + kdecore/klocale.h \ + kdecore/kcatalogue.h \ + kdecore/ksharedptr.h \ + kdecore/kshell.h \ + kdecore/kstandarddirs.h \ + kdecore/kstringhandler.h \ + kdecore/kshortcut.h \ + kutils/kcmultidialog.h \ + kdeui/kxmlguiclient.h \ + kdeui/kstdaction.h \ + kdeui/kmainwindow.h \ + kdeui/ktoolbar.h \ + kdeui/ktoolbarbutton.h \ + kdeui/ktoolbarhandler.h \ + kdeui/kaction.h \ + kdeui/kactionclasses.h \ + kdeui/kactioncollection.h + + +# kdecore/klibloader.h \ + + +SOURCES = \ +KDGanttMinimizeSplitter.cpp \ + kapplication.cpp \ + kcalendarsystem.cpp \ + kcalendarsystemgregorian.cpp \ + kcolorbutton.cpp \ + kcolordialog.cpp \ + kconfig.cpp \ + kdatetbl.cpp \ + kdialog.cpp \ + kdialogbase.cpp \ + keditlistbox.cpp \ + kemailsettings.cpp \ + kfontdialog.cpp \ + kfiledialog.cpp \ + kglobal.cpp \ + kglobalsettings.cpp \ + kiconloader.cpp \ + kmessagebox.cpp \ + ktextedit.cpp \ + kprocess.cpp \ + krun.cpp \ + ksystemtray.cpp \ + ktempfile.cpp \ + kurl.cpp \ + kdecore/kcatalogue.cpp \ + kdecore/klocale.cpp \ + kdecore/kmdcodec.cpp \ + kdecore/kshell.cpp \ + kdecore/kstandarddirs.cpp \ + kdecore/kstringhandler.cpp \ + kdeui/kbuttonbox.cpp \ + kdeui/kcmodule.cpp \ + kdeui/kguiitem.cpp \ + kdeui/kjanuswidget.cpp \ + kdeui/klistbox.cpp \ + kdeui/klistview.cpp \ + kdeui/knuminput.cpp \ + kdeui/knumvalidator.cpp \ + kdeui/kseparator.cpp \ + kdeui/ksqueezedtextlabel.cpp \ + kio/kfile/kurlrequester.cpp \ + kresources/configpage.cpp \ + kresources/configdialog.cpp \ + kresources/configwidget.cpp \ + kresources/factory.cpp \ + kresources/kcmkresources.cpp \ + kresources/managerimpl.cpp \ + kresources/resource.cpp \ + kresources/selectdialog.cpp \ + kutils/kcmultidialog.cpp \ + kdeui/kaction.cpp \ + kdeui/kactionclasses.cpp \ + kdeui/kactioncollection.cpp \ + kdeui/kmainwindow.cpp \ + kdeui/ktoolbar.cpp \ + kdeui/ktoolbarbutton.cpp \ + kdeui/ktoolbarhandler.cpp \ + kdeui/kstdaction.cpp \ + kdeui/kxmlguiclient.cpp + + + +# kdecore/klibloader.cpp \
\ No newline at end of file diff --git a/microkde/microkde.pro.back b/microkde/microkde.pro.back new file mode 100644 index 0000000..d2889ac --- a/dev/null +++ b/microkde/microkde.pro.back @@ -0,0 +1,80 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +INCLUDEPATH += $(QPEDIR)/include . ../qtcompat +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe -lqtcompat +TARGET = microkde +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/lib + +INTERFACES = \ + +HEADERS = \ + kapplication.h \ + kaudioplayer.h \ + kcalendarsystem.h \ + kcalendarsystemgregorian.h \ + kcolorbutton.h \ + kcolordialog.h \ + kcombobox.h \ + kconfig.h \ + kdatepicker.h \ + kdatetbl.h \ + kdebug.h \ + kdialog.h \ + kdialogbase.h \ + kdirwatch.h \ + keditlistbox.h \ + kemailsettings.h \ + kfiledialog.h \ + kfontdialog.h \ + kglobal.h \ + kglobalsettings.h \ + kiconloader.h \ + kio/job.h \ + klineedit.h \ + klineeditdlg.h \ + klistview.h \ + klocale.h \ + kmessagebox.h \ + knotifyclient.h \ + knumvalidator.h \ + kprinter.h \ + kprocess.h \ + krestrictedline.h \ + krun.h \ + kseparator.h \ + ksimpleconfig.h \ + kstandarddirs.h \ + kstaticdeleter.h \ + ksystemtray.h \ + ktempfile.h \ + ktextedit.h \ + kunload.h \ + kurlrequester.h \ + +SOURCES = \ + kapplication.cpp \ + kcalendarsystem.cpp \ + kcalendarsystemgregorian.cpp \ + kcolordialog.cpp \ + kconfig.cpp \ + kdatepicker.cpp \ + kdatetbl.cpp \ + kdialogbase.cpp \ + keditlistbox.cpp \ + kemailsettings.cpp \ + kfontdialog.cpp \ + kglobal.cpp \ + kglobalsettings.cpp \ + kiconloader.cpp \ + klocale.cpp \ + kmessagebox.cpp \ + knumvalidator.cpp \ + kprocess.cpp \ + krun.cpp \ + kstandarddirs.cpp \ + ktempfile.cpp \ + kurlrequester.cpp \ + diff --git a/microkde/microkdeE.pro b/microkde/microkdeE.pro new file mode 100644 index 0000000..8d04123 --- a/dev/null +++ b/microkde/microkdeE.pro @@ -0,0 +1,166 @@ +TEMPLATE = lib +CONFIG += qt warn_on +INCLUDEPATH += . ../qtcompat ../kabc ./kdecore ./kdeui ./kio/kfile $(QPEDIR)/include + +DEPENDPATH += $(QPEDIR)/include +LIBS += -lmicroqtcompat -L$(QPEDIR)/lib + +DEFINES += KDE_QT_ONLY + +TARGET = microkde +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=$(QPEDIR)/lib + + +INTERFACES = \ + +HEADERS = \ +qlayoutengine_p.h \ +KDGanttMinimizeSplitter.h \ + kapplication.h \ + kaudioplayer.h \ + kcalendarsystem.h \ + kcalendarsystemgregorian.h \ + kcolorbutton.h \ + kcolordialog.h \ + kcombobox.h \ + kconfig.h \ + kdatetbl.h \ + kdebug.h \ + kdialog.h \ + kdialogbase.h \ + kdirwatch.h \ + keditlistbox.h \ + kemailsettings.h \ + kfiledialog.h \ + kfontdialog.h \ + kglobal.h \ + kglobalsettings.h \ + kiconloader.h \ + klineedit.h \ + klineeditdlg.h \ + kmessagebox.h \ + knotifyclient.h \ + kprinter.h \ + kprocess.h \ + krestrictedline.h \ + krun.h \ + ksimpleconfig.h \ + kstaticdeleter.h \ + ksystemtray.h \ + ktempfile.h \ + ktextedit.h \ + kunload.h \ + kurl.h \ + ofileselector_p.h \ + ofontselector.h \ + kdeui/kguiitem.h \ + kdeui/kaction.h \ + kdeui/kactionclasses.h \ + kdeui/kactioncollection.h \ + kdeui/kcmodule.h \ + kdeui/kstdaction.h \ + kdeui/kbuttonbox.h \ + kdeui/klistbox.h \ + kdeui/klistview.h \ + kdeui/kjanuswidget.h \ + kdeui/kseparator.h \ + kdeui/kmainwindow.h \ + kdeui/knuminput.h \ + kdeui/knumvalidator.h \ + kdeui/ksqueezedtextlabel.h \ + kdeui/ktoolbar.h \ + kdeui/ktoolbarbutton.h \ + kdeui/ktoolbarhandler.h \ + kdeui/kxmlguiclient.h \ + kio/job.h \ + kio/kfile/kurlrequester.h \ + kresources/resource.h \ + kresources/factory.h \ + kresources/managerimpl.h \ + kresources/manager.h \ + kresources/selectdialog.h \ + kresources/configpage.h \ + kresources/configwidget.h \ + kresources/configdialog.h \ + kresources/kcmkresources.h \ + kdecore/kmdcodec.h \ + kdecore/kconfigbase.h \ + kdecore/klocale.h \ + kdecore/klibloader.h \ + kdecore/kcatalogue.h \ + kdecore/ksharedptr.h \ + kdecore/kshell.h \ + kdecore/kstandarddirs.h \ + kdecore/kstringhandler.h \ + kdecore/kshortcut.h \ + kutils/kcmultidialog.h + + + + +SOURCES = \ +KDGanttMinimizeSplitter.cpp \ + kapplication.cpp \ + kcalendarsystem.cpp \ + kcalendarsystemgregorian.cpp \ + kcolorbutton.cpp \ + kcolordialog.cpp \ + kconfig.cpp \ + kdatetbl.cpp \ + kdialog.cpp \ + kdialogbase.cpp \ + keditlistbox.cpp \ + kemailsettings.cpp \ + kfontdialog.cpp \ + kfiledialog.cpp \ + kglobal.cpp \ + kglobalsettings.cpp \ + kiconloader.cpp \ + kmessagebox.cpp \ + kprocess.cpp \ + krun.cpp \ + ksystemtray.cpp \ + ktempfile.cpp \ + kurl.cpp \ + ktextedit.cpp \ + ofileselector_p.cpp \ + ofontselector.cpp \ + kdecore/kcatalogue.cpp \ + kdecore/klibloader.cpp \ + kdecore/klocale.cpp \ + kdecore/kmdcodec.cpp \ + kdecore/kshell.cpp \ + kdecore/kstandarddirs.cpp \ + kdecore/kstringhandler.cpp \ + kdeui/kaction.cpp \ + kdeui/kactionclasses.cpp \ + kdeui/kactioncollection.cpp \ + kdeui/kbuttonbox.cpp \ + kdeui/kcmodule.cpp \ + kdeui/kguiitem.cpp \ + kdeui/kjanuswidget.cpp \ + kdeui/klistbox.cpp \ + kdeui/klistview.cpp \ + kdeui/kmainwindow.cpp \ + kdeui/knuminput.cpp \ + kdeui/knumvalidator.cpp \ + kdeui/kseparator.cpp \ + kdeui/kstdaction.cpp \ + kdeui/ksqueezedtextlabel.cpp \ + kdeui/ktoolbar.cpp \ + kdeui/ktoolbarbutton.cpp \ + kdeui/ktoolbarhandler.cpp \ + kdeui/kxmlguiclient.cpp \ + kio/kfile/kurlrequester.cpp \ + kresources/configpage.cpp \ + kresources/configdialog.cpp \ + kresources/configwidget.cpp \ + kresources/factory.cpp \ + kresources/kcmkresources.cpp \ + kresources/managerimpl.cpp \ + kresources/resource.cpp \ + kresources/selectdialog.cpp \ + kutils/kcmultidialog.cpp + diff --git a/microkde/ofileselector_p.cpp b/microkde/ofileselector_p.cpp new file mode 100644 index 0000000..cf6074d --- a/dev/null +++ b/microkde/ofileselector_p.cpp @@ -0,0 +1,863 @@ +#include <qcombobox.h> +#include <qdir.h> +#include <qhbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qpopupmenu.h> +#include <qwidgetstack.h> +#include <qregexp.h> +#include <qobjectlist.h> + +/* hacky but we need to get FileSelector::filter */ +#define private public +#include <qpe/fileselector.h> +#undef private + +#include <qpe/qpeapplication.h> +#include <qpe/mimetype.h> +#include <qpe/resource.h> +#include <qpe/storage.h> + +#include "ofileselector_p.h" +//US#include "ofileselector.h" + +#include "klocale.h" + +OFileViewInterface::OFileViewInterface( OFileSelector* selector ) + : m_selector( selector ) { +} +OFileViewInterface::~OFileViewInterface() { +} +QString OFileViewInterface::name()const{ + return m_name; +} +void OFileViewInterface::setName( const QString& name ) { + m_name = name; +} +OFileSelector* OFileViewInterface::selector()const { + return m_selector; +} + +DocLnk OFileViewInterface::selectedDocument()const { + return DocLnk( selectedName() ); +} + +bool OFileViewInterface::showNew()const { + return selector()->showNew(); +} +bool OFileViewInterface::showClose()const { + return selector()->showClose(); +} +MimeTypes OFileViewInterface::mimeTypes()const { + return selector()->mimeTypes(); +} +QStringList OFileViewInterface::currentMimeType()const { + return selector()->currentMimeType(); +} +void OFileViewInterface::activate( const QString& ) { + // not implemented here +} +void OFileViewInterface::ok() { + emit selector()->ok(); +} +void OFileViewInterface::cancel() { + emit selector()->cancel(); +} +void OFileViewInterface::closeMe() { + emit selector()->closeMe(); +} +void OFileViewInterface::fileSelected( const QString& str) { + emit selector()->fileSelected( str); +} +void OFileViewInterface::fileSelected( const DocLnk& lnk) { + emit selector()->fileSelected( lnk ); +} +void OFileViewInterface::setCurrentFileName( const QString& str ) { + selector()->m_lneEdit->setText( str ); +} +QString OFileViewInterface::currentFileName()const{ + return selector()->m_lneEdit->text(); +} +QString OFileViewInterface::startDirectory()const{ + return selector()->m_startDir; +} + + +ODocumentFileView::ODocumentFileView( OFileSelector* selector ) + : OFileViewInterface( selector ) { + m_selector = 0; + setName( i18n("Documents") ); +} +ODocumentFileView::~ODocumentFileView() { + +} +QString ODocumentFileView::selectedName()const { + if (!m_selector) + return QString::null; + + return m_selector->selected()->file(); +} +QString ODocumentFileView::selectedPath()const { + return QPEApplication::documentDir(); +} +QString ODocumentFileView::directory()const { + return selectedPath(); +} +void ODocumentFileView::reread() { + if (!m_selector) + return; + + m_selector->setNewVisible( showNew() ); + m_selector->setCloseVisible( showClose() ); + m_selector->filter = currentMimeType().join(";"); + m_selector->reread(); +} +int ODocumentFileView::fileCount()const { + if (!m_selector) + return -1; + + return m_selector->fileCount(); +} + +DocLnk ODocumentFileView::selectedDocument()const { + if (!m_selector) + return DocLnk(); + DocLnk lnk = *m_selector->selected(); + return lnk; +} + +QWidget* ODocumentFileView::widget( QWidget* parent ) { + if (!m_selector ) { + m_selector = new FileSelector(currentMimeType().join(";"), parent, "fileselector", showNew(), showClose() ); + QObject::connect(m_selector, SIGNAL(fileSelected( const DocLnk& ) ), + selector(), SLOT(slotDocLnkBridge(const DocLnk&) ) ); + QObject::connect(m_selector, SIGNAL(closeMe() ), + selector(), SIGNAL(closeMe() ) ); + QObject::connect(m_selector, SIGNAL(newSelected(const DocLnk& ) ), + selector(), SIGNAL(newSelected(const DocLnk& ) ) ); + } + + return m_selector; +} + +/* + * This is the file system view used + * we use a QListView + QListViewItems for it + */ + +OFileSelectorItem::OFileSelectorItem( QListView* view, const QPixmap& pixmap, + const QString& path, const QString& date, + const QString& size, const QString& dir, + bool isLocked, bool isDir ) + : QListViewItem( view ) +{ + setPixmap(0, pixmap ); + setText(1, path ); + setText(2, size ); + setText(3, date ); + m_isDir = isDir; + m_dir = dir; + m_locked = isLocked; +} +OFileSelectorItem::~OFileSelectorItem() { + +} +bool OFileSelectorItem::isLocked()const { + return m_locked; +} +QString OFileSelectorItem::directory()const { + return m_dir; +} +bool OFileSelectorItem::isDir()const { + return m_isDir; +} +QString OFileSelectorItem::path()const { + return text( 1 ); +} +QString OFileSelectorItem::key( int id, bool )const { + QString ke; + if( id == 0 || id == 1 ){ // name + if( m_isDir ){ + ke.append("0" ); + ke.append( text(1) ); + }else{ + ke.append("1" ); + ke.append( text(1) ); + } + return ke; + }else + return text( id ); + +} + +OFileViewFileListView::OFileViewFileListView( QWidget* parent, const QString& startDir, + OFileSelector* sel) + : QWidget( parent ), m_sel( sel ) { + m_all = false; + QVBoxLayout* lay = new QVBoxLayout( this ); + m_currentDir = startDir; + + /* + * now we add a special bar + * One Button For Up + * Home + * Doc + * And a dropdown menu with FileSystems + * FUTURE: one to change dir with lineedit + * Bookmarks + * Create Dir + */ + QHBox* box = new QHBox(this ); + box->setBackgroundMode( PaletteButton ); + box->setSpacing( 0 ); + + QToolButton *btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("up") ); + connect(btn, SIGNAL(clicked() ), + this, SLOT( cdUP() ) ); + + btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("home") ); + connect(btn, SIGNAL(clicked() ), + this, SLOT( cdHome() ) ); + + btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("DocsIcon") ); + connect(btn, SIGNAL(clicked() ), + this, SLOT(cdDoc() ) ); + + m_btnNew = new QToolButton( box ); + m_btnNew->setIconSet( Resource::loadPixmap("new") ); + connect(m_btnNew, SIGNAL(clicked() ), + this, SLOT(slotNew() ) ); + + + m_btnClose = new QToolButton( box ); + m_btnClose->setIconSet( Resource::loadPixmap("close") ); + connect(m_btnClose, SIGNAL(clicked() ), + selector(), SIGNAL(closeMe() ) ); + + btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("cardmon/pcmcia") ); + + /* let's fill device parts */ + QPopupMenu* pop = new QPopupMenu(this); + connect(pop, SIGNAL( activated(int) ), + this, SLOT(slotFSActivated(int) ) ); + + StorageInfo storage; + const QList<FileSystem> &fs = storage.fileSystems(); + QListIterator<FileSystem> it(fs); + for ( ; it.current(); ++it ) { + const QString disk = (*it)->name(); + const QString path = (*it)->path(); + m_dev.insert( disk, path ); + pop->insertItem( disk ); + } + m_fsPop = pop; + + + btn->setPopup( pop ); + btn->setPopupDelay ( 0 ); + lay->addWidget( box ); + + m_view = new QListView( this ); + + m_view->installEventFilter(this); + + QPEApplication::setStylusOperation( m_view->viewport(), + QPEApplication::RightOnHold); + m_view->addColumn(" " ); + m_view->addColumn(i18n("Name"), 135 ); + m_view->addColumn(i18n("Size"), -1 ); + m_view->addColumn(i18n("Date"), 60 ); + m_view->addColumn(i18n("Mime Type"), -1 ); + + + m_view->setSorting( 1 ); + m_view->setAllColumnsShowFocus( TRUE ); + + lay->addWidget( m_view, 1000 ); + connectSlots(); +} +OFileViewFileListView::~OFileViewFileListView() { +} +void OFileViewFileListView::slotNew() { + DocLnk lnk; + emit selector()->newSelected( lnk ); +} +OFileSelectorItem* OFileViewFileListView::currentItem()const{ + QListViewItem* item = m_view->currentItem(); + if (!item ) + return 0l; + + return static_cast<OFileSelectorItem*>(item); +} +void OFileViewFileListView::reread( bool all ) { + m_view->clear(); + + if (selector()->showClose() ) + m_btnClose->show(); + else + m_btnClose->hide(); + + if (selector()->showNew() ) + m_btnNew->show(); + else + m_btnNew->hide(); + + m_mimes = selector()->currentMimeType(); + m_all = all; + + QDir dir( m_currentDir ); + if (!dir.exists() ) + return; + topLevelWidget()->setCaption( dir.path() ); + dir.setSorting( QDir::Name | QDir::DirsFirst | QDir::Reversed ); + int filter; + if (m_all ) + filter = QDir::Files | QDir::Dirs | QDir::Hidden | QDir::All; + else + filter = QDir::Files | QDir::Dirs | QDir::All; + dir.setFilter( filter ); + + // now go through all files + const QFileInfoList *list = dir.entryInfoList(); + if (!list) { + cdUP(); + return; + } + QFileInfoListIterator it( *list ); + QFileInfo *fi; + while( (fi=it.current() ) ){ + if( fi->fileName() == QString::fromLatin1("..") || fi->fileName() == QString::fromLatin1(".") ){ + ++it; + continue; + } + + /* + * It is a symlink we try to resolve it now but don't let us attack by DOS + * + */ + if( fi->isSymLink() ){ + QString file = fi->dirPath( true ) + "/" + fi->readLink(); + for( int i = 0; i<=4; i++) { // 5 tries to prevent dos + QFileInfo info( file ); + if( !info.exists() ){ + addSymlink( fi, TRUE ); + break; + }else if( info.isDir() ){ + addDir( fi, TRUE ); + break; + }else if( info.isFile() ){ + addFile( fi, TRUE ); + break; + }else if( info.isSymLink() ){ + file = info.dirPath(true ) + "/" + info.readLink() ; + break; + }else if( i == 4){ // couldn't resolve symlink add it as symlink + addSymlink( fi ); + } + } // off for loop for symlink resolving + }else if( fi->isDir() ) + addDir( fi ); + else if( fi->isFile() ) + addFile( fi ); + + ++it; + } // of while loop + m_view->sort(); + +} +int OFileViewFileListView::fileCount()const{ + return m_view->childCount(); +} +QString OFileViewFileListView::currentDir()const{ + return m_currentDir; +} +OFileSelector* OFileViewFileListView::selector() { + return m_sel; +} + +bool OFileViewFileListView::eventFilter (QObject *o, QEvent *e) { + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *k = (QKeyEvent *)e; + if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) { + slotClicked( Qt::LeftButton,m_view->currentItem(),QPoint(0,0),0); + return true; + } + } + return false; +} + + +void OFileViewFileListView::connectSlots() { + connect(m_view, SIGNAL(clicked(QListViewItem*) ), + this, SLOT(slotCurrentChanged(QListViewItem*) ) ); + connect(m_view, SIGNAL(mouseButtonClicked(int, QListViewItem*, const QPoint&, int ) ), + this, SLOT(slotClicked(int, QListViewItem*, const QPoint&, int ) ) ); +} +void OFileViewFileListView::slotCurrentChanged( QListViewItem* item) { + if (!item) + return; +#if 0 + + OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item); + + if (!sel->isDir() ) { + selector()->m_lneEdit->setText( sel->text(1) ); + // if in fileselector mode we will emit selected + if ( selector()->mode() == OFileSelector::FileSelector ) { + qWarning("slot Current Changed"); + QStringList str = QStringList::split("->", sel->text(1) ); + QString path = sel->directory() + "/" + str[0].stripWhiteSpace(); + emit selector()->fileSelected( path ); + DocLnk lnk( path ); + emit selector()->fileSelected( lnk ); + } + } +#endif +} +void OFileViewFileListView::slotClicked(int button , QListViewItem* item, const QPoint&, int ) { + if (!item || ( button != Qt::LeftButton) ) + return; + + OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item); + if (!sel->isLocked() ) { + QStringList str = QStringList::split("->", sel->text(1) ); + if (sel->isDir() ) { + m_currentDir = sel->directory() + "/" + str[0].stripWhiteSpace(); + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); + }else { // file + qWarning("slot Clicked"); + selector()->m_lneEdit->setText( str[0].stripWhiteSpace() ); + QString path = sel->directory() + "/" + str[0].stripWhiteSpace(); + emit selector()->fileSelected( path ); + DocLnk lnk( path ); + emit selector()->fileSelected( lnk ); + } + } // not locked +} +void OFileViewFileListView::addFile( QFileInfo* info, bool symlink ) { + MimeType type( info->absFilePath() ); + if (!compliesMime( type.id() ) ) + return; + + QPixmap pix = type.pixmap(); + QString dir, name; bool locked; + if ( pix.isNull() ) { + QWMatrix matrix; + QPixmap pixer(Resource::loadPixmap("UnknownDocument") ); + matrix.scale( .4, .4 ); + pix = pixer.xForm( matrix ); + } + dir = info->dirPath( true ); + locked = false; + if ( symlink ) + name = info->fileName() + " -> " + info->dirPath() + "/" + info->readLink(); + else{ + name = info->fileName(); + if ( ( (selector()->mode() == OFileSelector::Open)&& !info->isReadable() ) || + ( (selector()->mode() == OFileSelector::Save)&& !info->isWritable() ) ) { + locked = true; pix = Resource::loadPixmap("locked"); + } + } + (void)new OFileSelectorItem( m_view, pix, name, + info->lastModified().toString(), QString::number( info->size() ), + dir, locked ); +} +void OFileViewFileListView::addDir( QFileInfo* info, bool symlink ) { + bool locked = false; QString name; QPixmap pix; + + if ( ( ( selector()->mode() == OFileSelector::Open ) && !info->isReadable() ) || + ( ( selector()->mode() == OFileSelector::Save ) && !info->isWritable() ) ) { + locked = true; + if ( symlink ) + pix = Resource::loadPixmap( "symlink" ); + else + pix = Resource::loadPixmap( "lockedfolder" ); + }else + pix = symlink ? Resource::loadPixmap( "symlink") : Resource::loadPixmap("folder"); + + name = symlink ? info->fileName() + " -> " + info->dirPath(true) + "/" + info->readLink() : + info->fileName(); + + (void)new OFileSelectorItem( m_view, pix, name, + info->lastModified().toString(), + QString::number( info->size() ), + info->dirPath( true ), locked, true ); + + +} +void OFileViewFileListView::addSymlink( QFileInfo* , bool ) { + +} +void OFileViewFileListView::cdUP() { + QDir dir( m_currentDir ); + dir.cdUp(); + + if (!dir.exists() ) + m_currentDir = "/"; + else + m_currentDir = dir.absPath(); + + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::cdHome() { + m_currentDir = QDir::homeDirPath(); + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::cdDoc() { + m_currentDir = QPEApplication::documentDir(); + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::changeDir( const QString& dir ) { + m_currentDir = dir; + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::slotFSActivated( int id ) { + changeDir ( m_dev[m_fsPop->text(id)] ); +} + +/* check if the mimetype in mime + * complies with the one which is current + */ +/* + * We've the mimetype of the file + * We need to get the stringlist of the current mimetype + * + * mime = image@slashjpeg + * QStringList = 'image@slash*' + * or QStringList = image/jpeg;image/png;application/x-ogg + * or QStringList = application/x-ogg;image@slash*; + * with all these mime filters it should get acceptes + * to do so we need to look if mime is contained inside + * the stringlist + * if it's contained return true + * if not ( I'm no RegExp expert at all ) we'll look if a '@slash*' + * is contained in the mimefilter and then we will + * look if both are equal until the '/' + */ +bool OFileViewFileListView::compliesMime( const QString& str) { + if (str.isEmpty() || m_mimes.isEmpty() || str.stripWhiteSpace().isEmpty() ) + return true; + + for (QStringList::Iterator it = m_mimes.begin(); it != m_mimes.end(); ++it ) { + QRegExp reg( (*it) ); + reg.setWildcard( true ); + if ( str.find( reg ) != -1 ) + return true; + + } + return false; +} +/* + * The listView giving access to the file system! + */ +class OFileViewFileSystem : public OFileViewInterface { +public: + OFileViewFileSystem( OFileSelector* ); + ~OFileViewFileSystem(); + + QString selectedName() const; + QString selectedPath() const; + + QString directory()const; + void reread(); + int fileCount()const; + + QWidget* widget( QWidget* parent ); + void activate( const QString& ); +private: + OFileViewFileListView* m_view; + bool m_all : 1; +}; +OFileViewFileSystem::OFileViewFileSystem( OFileSelector* sel) + : OFileViewInterface( sel ) { + m_view = 0; + m_all = false; +} +OFileViewFileSystem::~OFileViewFileSystem() { +} +QString OFileViewFileSystem::selectedName()const{ + if (!m_view ) + return QString::null; + + QString cFN=currentFileName(); + if (cFN.startsWith("/")) return cFN; + return m_view->currentDir() + "/" + cFN; +} +QString OFileViewFileSystem::selectedPath()const{ + return QString::null; +} +QString OFileViewFileSystem::directory()const{ + if (!m_view) + return QString::null; + + OFileSelectorItem* item = m_view->currentItem(); + if (!item ) + return QString::null; + + return QDir(item->directory() ).absPath(); +} +void OFileViewFileSystem::reread() { + if (!m_view) + return; + + m_view->reread( m_all ); +} +int OFileViewFileSystem::fileCount()const{ + if (!m_view ) + return -1; + return m_view->fileCount(); +} +QWidget* OFileViewFileSystem::widget( QWidget* parent ) { + if (!m_view ) { + m_view = new OFileViewFileListView( parent, startDirectory(), selector() ); + } + return m_view; +} +void OFileViewFileSystem::activate( const QString& str) { + m_all = (str !=i18n("Files") ); + + +} + +/* Selector */ +OFileSelector::OFileSelector( QWidget* parent, int mode, int sel, + const QString& dirName, const QString& fileName, + const MimeTypes& mimetypes, + bool showNew, bool showClose) + : QWidget( parent, "OFileSelector" ) +{ + m_current = 0; + m_shNew = showNew; + m_shClose = showClose; + m_mimeType = mimetypes; + m_startDir = dirName; + m_mode = mode; + m_selector = sel; + + initUI(); + m_lneEdit->setText( fileName ); + initMime(); + initViews(); + + QString str; + switch ( m_selector ) { + default: + case Normal: + str = i18n("Documents"); + m_cmbView->setCurrentItem( 0 ); + break; + case Extended: + str = i18n("Files"); + m_cmbView->setCurrentItem( 1 ); + break; + case ExtendedAll: + str = i18n("All Files"); + m_cmbView->setCurrentItem( 2 ); + break; + } + slotViewChange( str ); + +} +OFileSelector::OFileSelector( const QString& mimeFilter, QWidget* parent, const char* name, + bool showNew, bool showClose ) + : QWidget( parent, name ) +{ + m_current = 0; + m_shNew = showNew; + m_shClose = showClose; + m_startDir = QPEApplication::documentDir(); + + if (!mimeFilter.isEmpty() ) + m_mimeType.insert(mimeFilter, QStringList::split(";", mimeFilter ) ); + + m_mode = OFileSelector::FileSelector; + m_selector = OFileSelector::Normal; + + initUI(); + initMime(); + initViews(); + m_cmbView->setCurrentItem( 0 ); + slotViewChange( i18n("Documents") ); +} +/* + * INIT UI will set up the basic GUI + * Layout: Simple VBoxLayout + * On top a WidgetStack containing the Views... + * - List View + * - Document View + * Below we will have a Label + LineEdit + * Below we will have two ComoBoxes one for choosing the view one for + * choosing the mimetype + */ +void OFileSelector::initUI() { + QVBoxLayout* lay = new QVBoxLayout( this ); + + m_stack = new QWidgetStack( this ); + lay->addWidget( m_stack, 1000 ); + + m_nameBox = new QHBox( this ); + (void)new QLabel( i18n("Name:"), m_nameBox ); + m_lneEdit = new QLineEdit( m_nameBox ); + m_lneEdit ->installEventFilter(this); + lay->addWidget( m_nameBox ); + + m_cmbBox = new QHBox( this ); + m_cmbView = new QComboBox( m_cmbBox ); + m_cmbMime = new QComboBox( m_cmbBox ); + lay->addWidget( m_cmbBox ); +} + +/* + * This will make sure that the return key in the name edit causes dialogs to close + */ + +bool OFileSelector::eventFilter (QObject *o, QEvent *e) { + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *k = (QKeyEvent *)e; + if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) { + emit ok(); + return true; + } + } + return false; +} + +/* + * This will insert the MimeTypes into the Combo Box + * And also connect the changed signal + * + * AutoMimeTyping is disabled for now. It used to reparse a dir and then set available mimetypes + */ +void OFileSelector::initMime() { + MimeTypes::Iterator it; + for ( it = m_mimeType.begin(); it != m_mimeType.end(); ++it ) { + m_cmbMime->insertItem( it.key() ); + } + m_cmbMime->setCurrentItem( 0 ); + + connect( m_cmbMime, SIGNAL(activated(int) ), + this, SLOT(slotMimeTypeChanged() ) ); + +} +void OFileSelector::initViews() { + m_cmbView->insertItem( i18n("Documents") ); + m_cmbView->insertItem( i18n("Files") ); + m_cmbView->insertItem( i18n("All Files") ); + connect(m_cmbView, SIGNAL(activated( const QString& ) ), + this, SLOT(slotViewChange( const QString& ) ) ); + + + m_views.insert( i18n("Documents"), new ODocumentFileView(this) ); + + /* see above why add both */ + OFileViewInterface* in = new OFileViewFileSystem( this ); + m_views.insert( i18n("Files"), in ); + m_views.insert( i18n("All Files"), in ); +} +OFileSelector::~OFileSelector() { + +} + +const DocLnk* OFileSelector::selected() { + DocLnk* lnk = ¤tView()->selectedDocument() ; + return lnk; +} + +QString OFileSelector::selectedName()const{ + return currentView()->selectedName(); +} +QString OFileSelector::selectedPath()const { + return currentView()->selectedPath(); +} +QString OFileSelector::directory()const { + return currentView()->directory(); +} + +DocLnk OFileSelector::selectedDocument()const { + return currentView()->selectedDocument(); +} + +int OFileSelector::fileCount()const { + return currentView()->fileCount(); +} +void OFileSelector::reread() { + return currentView()->reread(); +} +OFileViewInterface* OFileSelector::currentView()const{ + return m_current; +} +bool OFileSelector::showNew()const { + return m_shNew; +} +bool OFileSelector::showClose()const { + return m_shClose; +} +MimeTypes OFileSelector::mimeTypes()const { + return m_mimeType; +} +int OFileSelector::mode()const{ + return m_mode; +} +int OFileSelector::selector()const{ + return m_selector; +} +QStringList OFileSelector::currentMimeType()const { + return m_mimeType[m_cmbMime->currentText()]; +} +void OFileSelector::slotMimeTypeChanged() { + reread(); +} +void OFileSelector::slotDocLnkBridge( const DocLnk& lnk) { + m_lneEdit->setText( lnk.name() ); + emit fileSelected( lnk ); + emit fileSelected( lnk.name() ); +} +void OFileSelector::slotFileBridge( const QString& str) { + DocLnk lnk( str ); + emit fileSelected( lnk ); +} +void OFileSelector::slotViewChange( const QString& view ) { + OFileViewInterface* interface = m_views[view]; + if (!interface) + return; + + interface->activate( view ); + if (m_current) + m_stack->removeWidget( m_current->widget( m_stack ) ); + + static int id = 1; + + m_stack->addWidget( interface->widget(m_stack), id ); + m_stack->raiseWidget( id ); + + interface->reread(); + m_current = interface; + + id++; +} +void OFileSelector::setNewVisible( bool b ) { + m_shNew = b; + currentView()->reread(); +} +void OFileSelector::setCloseVisible( bool b ) { + m_shClose = b; + currentView()->reread(); +} +void OFileSelector::setNameVisible( bool b ) { + if ( b ) + m_nameBox->show(); + else + m_nameBox->hide(); +} diff --git a/microkde/ofileselector_p.h b/microkde/ofileselector_p.h new file mode 100644 index 0000000..b371806 --- a/dev/null +++ b/microkde/ofileselector_p.h @@ -0,0 +1,258 @@ +#ifndef OPIE_OFILE_SELECTOR_PRIVATE_H +#define OPIE_OFILE_SELECTOR_PRIVATE_H + +//US +#pragma message("microkde/ofileselector_p.h") + +#include <qmap.h> +#include <qstringlist.h> +#include <qwidget.h> +#include <qlistview.h> + +#include <qpe/applnk.h> +#include <qpe/fileselector.h> + + +/* + * How to avoid having really two different objects + * for Extended and ExtendedAll + * The only difference is the Lister... + * a) static object? + * b) leave some object inside the OFileSelector which can be used? + * c) when switching views tell which view we want o have.. internally we can switch then + * + * I'll take c) -zecke + */ + + +/* the View Interface */ +class OFileSelector; +typedef QMap<QString, QStringList> MimeTypes; +class QFileInfo; +class QToolButton; +class OFileViewInterface { +public: + OFileViewInterface( OFileSelector* selector ); + virtual ~OFileViewInterface(); + virtual QString selectedName()const = 0; + virtual QString selectedPath()const = 0; + virtual QString directory()const = 0; + virtual void reread() = 0; + virtual int fileCount()const = 0; + virtual DocLnk selectedDocument()const; + virtual QWidget* widget( QWidget* parent) = 0; + virtual void activate( const QString& ); + QString name()const; +protected: + OFileSelector* selector()const; + void setName( const QString& ); + bool showNew()const; + bool showClose()const; + MimeTypes mimeTypes()const; + QStringList currentMimeType()const; + QString startDirectory()const; +protected: + void ok(); + void cancel(); + void closeMe(); + void fileSelected( const QString& ); + void fileSelected( const DocLnk& ); + void setCurrentFileName( const QString& ); + QString currentFileName()const; + +private: + QString m_name; + OFileSelector* m_selector; +}; + + +/* THE Document View hosting a FileSelector*/ +class ODocumentFileView : public OFileViewInterface { +public: + ODocumentFileView( OFileSelector* selector ); + ~ODocumentFileView(); + + QString selectedName() const; + QString selectedPath() const; + + QString directory() const; + void reread(); + int fileCount()const; + DocLnk selectedDocument()const; + + QWidget* widget( QWidget* parent ); + +private: + mutable FileSelector* m_selector; + +}; + +class OFileSelectorItem : public QListViewItem { +public: + OFileSelectorItem( QListView* view, const QPixmap& pixmap, + const QString& path, const QString& date, + const QString& size, const QString& mDir, + bool isLocked = false, bool isDir = false ); + ~OFileSelectorItem(); + bool isLocked()const; + bool isDir()const; + QString directory()const; + QString path()const; + QString key(int id, bool )const; + +private: + bool m_locked : 1; + bool m_isDir : 1; + QString m_dir; +}; + +class OFileViewFileListView : public QWidget { + Q_OBJECT +public: + OFileViewFileListView( QWidget* parent, const QString& dir, OFileSelector* selector ); + ~OFileViewFileListView(); + + OFileSelectorItem* currentItem()const; + void reread( bool all = false ); + int fileCount()const; + QString currentDir()const; +protected: + bool eventFilter (QObject *o, QEvent *e); +private slots: + void slotNew(); // will emit newSelected + void cdUP(); + void cdHome(); + void cdDoc(); + void changeDir( const QString& ); + void slotCurrentChanged( QListViewItem* ); + void slotClicked(int, QListViewItem*, const QPoint&, int ); + void slotFSActivated(int); + +protected: + + OFileSelector* selector(); + +private: + QMap<QString, QString> m_dev; + bool m_all : 1; + OFileSelector* m_sel; + QPopupMenu* m_fsPop; + bool compliesMime( const QString& ); + QStringList m_mimes; // used in compy mime + QString m_currentDir; + QToolButton *m_btnNew, *m_btnClose; + void connectSlots(); + void addFile( QFileInfo* info, bool symlink = FALSE ); + void addDir ( QFileInfo* info, bool symlink = FALSE ); + void addSymlink( QFileInfo* info, bool = FALSE ); + + +private: + QListView* m_view; +}; + +typedef QMap<QString, QStringList> MimeTypes; + +class OFileViewInterface; +class OFileViewFileListView; +class QLineEdit; +class QComboBox; +class QWidgetStack; +class QHBox; +class OFileSelector : public QWidget { + Q_OBJECT + friend class OFileViewInterface; + friend class OFileViewFileListView; +public: + enum Mode { Open=1, Save=2, FileSelector=4, OPEN=1, SAVE=2, FILESELECTOR=4 }; +// enum OldMode { OPEN=1, SAVE=2, FILESELECTOR = 4 }; + enum Selector { Normal = 0, Extended=1, ExtendedAll =2, Default=3, NORMAL=0,EXTENDED=1, EXTENDED_ALL =2, DEFAULT=3 }; +// enum OldSelector { NORMAL = 0, EXTENDED =1, EXTENDED_ALL = 2}; + + OFileSelector(QWidget* parent, int mode, int selector, + const QString& dirName, + const QString& fileName, + const MimeTypes& mimetypes = MimeTypes(), + bool newVisible = FALSE, bool closeVisible = FALSE ); + + OFileSelector(const QString& mimeFilter, QWidget* parent, + const char* name = 0, bool newVisible = TRUE, bool closeVisible = FALSE ); + ~OFileSelector(); + + const DocLnk* selected(); + + QString selectedName()const; + QString selectedPath()const; + QString directory()const; + + DocLnk selectedDocument()const; + + int fileCount()const; + void reread(); + + int mode()const; + int selector()const; + + + void setNewVisible( bool b ); + void setCloseVisible( bool b ); + void setNameVisible( bool b ); + +signals: + void dirSelected( const QString& ); + void fileSelected( const DocLnk& ); + void fileSelected( const QString& ); + void newSelected( const DocLnk& ); + void closeMe(); + void ok(); + void cancel(); + +/* used by the ViewInterface */ +private: + bool showNew()const; + bool showClose()const; + MimeTypes mimeTypes()const; + QStringList currentMimeType()const; + +private: + /* inits the Widgets */ + void initUI(); + /* inits the MimeType ComboBox content + connects signals and slots */ + void initMime(); + /* init the Views :) */ + void initViews(); + +private: + QLineEdit* m_lneEdit; // the LineEdit for the Name + QComboBox *m_cmbView, *m_cmbMime; // two ComboBoxes to select the View and MimeType + QWidgetStack* m_stack; // our widget stack which will contain the views + OFileViewInterface* currentView()const; // returns the currentView + OFileViewInterface* m_current; // here is the view saved + bool m_shNew : 1; // should we show New? + bool m_shClose : 1; // should we show Close? + MimeTypes m_mimeType; // list of mimetypes + + QMap<QString, OFileViewInterface*> m_views; // QString translated view name + ViewInterface Ptr + QHBox* m_nameBox; // the LineEdit + Label is hold here + QHBox* m_cmbBox; // this holds the two combo boxes + + QString m_startDir; + int m_mode; + int m_selector; + + struct Data; // used for future versions + Data *d; + +private slots: + void slotMimeTypeChanged(); + + /* will set the text of the lineedit and emit a fileChanged signal */ + void slotDocLnkBridge( const DocLnk& ); + void slotFileBridge( const QString& ); + void slotViewChange( const QString& ); + + bool eventFilter (QObject *o, QEvent *e); + +}; + +#endif diff --git a/microkde/ofontselector.cpp b/microkde/ofontselector.cpp new file mode 100644 index 0000000..c8471cc --- a/dev/null +++ b/microkde/ofontselector.cpp @@ -0,0 +1,412 @@ +/* + =. This file is part of the OPIE Project + .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org> + .>+-= + _;:, .> :=|. This library is free software; you can +.> <`_, > . <= redistribute it and/or modify it under +:`=1 )Y*s>-.-- : the terms of the GNU Library General Public +.="- .-=="i, .._ License as published by the Free Software + - . .-<_> .<> Foundation; either version 2 of the License, + ._= =} : or (at your option) any later version. + .%`+i> _;_. + .i_,=:_. -<s. This library is distributed in the hope that + + . -:. = it will be useful, but WITHOUT ANY WARRANTY; + : .. .:, . . . without even the implied warranty of + =_ + =;=|` MERCHANTABILITY or FITNESS FOR A + _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU +..}^=.= = ; Library General Public License for more +++= -. .` .: details. + : = ...= . :.=- + -. .:....=;==+<; You should have received a copy of the GNU + -_. . . )=. = Library General Public License along with + -- :-=` this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include <qlayout.h> +#include <qlistbox.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qfont.h> +#include <qmultilineedit.h> + +#include <qpe/fontdatabase.h> + +#include "ofontselector.h" + +class OFontSelectorPrivate { +public: + QListBox * m_font_family_list; + QComboBox * m_font_style_list; + QComboBox * m_font_size_list; + QMultiLineEdit *m_preview; + + bool m_pointbug : 1; + + FontDatabase m_fdb; +}; + +namespace { + +class FontListItem : public QListBoxText { +public: + FontListItem ( const QString &t, const QStringList &styles, const QValueList<int> &sizes ) : QListBoxText ( ) + { + m_name = t; + m_styles = styles; + m_sizes = sizes; + + QString str = t; + str [0] = str [0]. upper ( ); + setText ( str ); + } + + QString family ( ) const + { + return m_name; + } + + const QStringList &styles ( ) const + { + return m_styles; + } + + const QValueList<int> &sizes ( ) const + { + return m_sizes; + } + +private: + QStringList m_styles; + QValueList<int> m_sizes; + QString m_name; +}; + + +static int findItemCB ( QComboBox *box, const QString &str ) +{ + for ( int i = 0; i < box-> count ( ); i++ ) { + if ( box-> text ( i ) == str ) + return i; + } + return -1; +} + +} +/* static same as anon. namespace */ +static int qt_version ( ) +{ + const char *qver = qVersion ( ); + + return ( qver [0] - '0' ) * 100 + ( qver [2] - '0' ) * 10 + ( qver [4] - '0' ); +} + +/** + * Constructs the Selector object + * @param withpreview If a font preview should be given + * @param parent The parent of the Font Selector + * @param name The name of the object + * @param fl WidgetFlags + */ +OFontSelector::OFontSelector ( bool withpreview, QWidget *parent, const char *name, WFlags fl ) : QWidget ( parent, name, fl ) +{ + d = new OFontSelectorPrivate ( ); + + QGridLayout *gridLayout = new QGridLayout ( this, 0, 0, 4, 4 ); + gridLayout->setRowStretch ( 4, 10 ); + + d-> m_font_family_list = new QListBox( this, "FontListBox" ); + gridLayout->addMultiCellWidget( d-> m_font_family_list, 0, 4, 0, 0 ); + connect( d-> m_font_family_list, SIGNAL( highlighted( int ) ), this, SLOT( fontFamilyClicked( int ) ) ); + + QLabel *label = new QLabel( tr( "Style" ), this ); + gridLayout->addWidget( label, 0, 1 ); + + d-> m_font_style_list = new QComboBox( this, "StyleListBox" ); + connect( d-> m_font_style_list, SIGNAL( activated( int ) ), this, SLOT( fontStyleClicked( int ) ) ); + gridLayout->addWidget( d-> m_font_style_list, 1, 1 ); + + label = new QLabel( tr( "Size" ), this ); + gridLayout->addWidget( label, 2, 1 ); + + d-> m_font_size_list = new QComboBox( this, "SizeListBox" ); + connect( d-> m_font_size_list, SIGNAL( activated( int ) ), + this, SLOT( fontSizeClicked( int ) ) ); + gridLayout->addWidget( d-> m_font_size_list, 3, 1 ); + + d-> m_pointbug = ( qt_version ( ) <= 233 ); + + if ( withpreview ) { + d-> m_preview = new QMultiLineEdit ( this, "Preview" ); + d-> m_preview-> setAlignment ( AlignCenter ); + d-> m_preview-> setWordWrap ( QMultiLineEdit::WidgetWidth ); + d-> m_preview-> setMargin ( 3 ); + d-> m_preview-> setText ( tr( "The Quick Brown Fox Jumps Over The Lazy Dog" )); + gridLayout-> addRowSpacing ( 5, 4 ); + gridLayout-> addMultiCellWidget ( d-> m_preview, 6, 6, 0, 1 ); + gridLayout-> setRowStretch ( 6, 5 ); + } + else + d-> m_preview = 0; + + loadFonts ( d-> m_font_family_list ); +} + +OFontSelector::~OFontSelector ( ) +{ + delete d; +} + +/** + * This methods tries to set the font + * @param f The wishes font + * @return success or failure + */ +bool OFontSelector::setSelectedFont ( const QFont &f ) +{ + return setSelectedFont ( f. family ( ), d-> m_fdb. styleString ( f ), f. pointSize ( ), QFont::encodingName ( f. charSet ( ))); +} + + +/** + * This is an overloaded method @see setSelectedFont + * @param familyStr The family of the font + * @param styleStr The style of the font + * @param sizeVal The size of font + * @param charset The charset to be used. Will be deprecated by QT3 + */ +bool OFontSelector::setSelectedFont ( const QString &familyStr, const QString &styleStr, int sizeVal, const QString & charset ) +{ + QString sizeStr = QString::number ( sizeVal ); + + QListBoxItem *family = d-> m_font_family_list-> findItem ( familyStr ); + if ( !family ) + family = d-> m_font_family_list-> findItem ( "Helvetica" ); + if ( !family ) + family = d-> m_font_family_list-> firstItem ( ); + d-> m_font_family_list-> setCurrentItem ( family ); + fontFamilyClicked ( d-> m_font_family_list-> index ( family )); + + int style = findItemCB ( d-> m_font_style_list, styleStr ); + if ( style < 0 ) + style = findItemCB ( d-> m_font_style_list, "Regular" ); + if ( style < 0 && d-> m_font_style_list-> count ( ) > 0 ) + style = 0; + d-> m_font_style_list-> setCurrentItem ( style ); + fontStyleClicked ( style ); + + int size = findItemCB ( d-> m_font_size_list, sizeStr ); + if ( size < 0 ) + size = findItemCB ( d-> m_font_size_list, "10" ); + if ( size < 0 && d-> m_font_size_list-> count ( ) > 0 ) + size = 0; + d-> m_font_size_list-> setCurrentItem ( size ); + fontSizeClicked ( size ); + + return (( family ) && ( style >= 0 ) && ( size >= 0 )); +} + +/** + * This method returns the name, style and size of the currently selected + * font or false if no font is selected + * @param family The font family will be written there + * @param style The style will be written there + * @param size The size will be written there + * @return success or failure + */ +bool OFontSelector::selectedFont ( QString &family, QString &style, int &size ) +{ + QString dummy; + return selectedFont ( family, style, size, dummy ); +} + + +/** + * This method does return the font family or QString::null if there is + * no font item selected + * @return the font family + */ +QString OFontSelector::fontFamily ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + + return fli ? fli-> family ( ) : QString::null; +} + +/** + * This method will return the style of the font or QString::null + * @return the style of the font + */ +QString OFontSelector::fontStyle ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + int fst = d-> m_font_style_list-> currentItem ( ); + + return ( fli && fst >= 0 ) ? fli-> styles ( ) [fst] : QString::null; +} + +/** + * This method will return the font size or 10 if no font size is available + */ +int OFontSelector::fontSize ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + int fsi = d-> m_font_size_list-> currentItem ( ); + + return ( fli && fsi >= 0 ) ? fli-> sizes ( ) [fsi] : 10; +} + +/** + * returns the charset of the font or QString::null + */ +QString OFontSelector::fontCharSet ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + + return fli ? d-> m_fdb. charSets ( fli-> family ( )) [0] : QString::null; +} + +/** + * Overloaded member function see above + * @see selectedFont + */ +bool OFontSelector::selectedFont ( QString &family, QString &style, int &size, QString &charset ) +{ + int ffa = d-> m_font_family_list-> currentItem ( ); + int fst = d-> m_font_style_list-> currentItem ( ); + int fsi = d-> m_font_size_list-> currentItem ( ); + + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa ); + + if ( fli ) { + family = fli-> family ( ); + style = fst >= 0 ? fli-> styles ( ) [fst] : QString::null; + size = fsi >= 0 ? fli-> sizes ( ) [fsi] : 10; + charset = d-> m_fdb. charSets ( fli-> family ( )) [0]; + + return true; + } + else + return false; +} + + + + +void OFontSelector::loadFonts ( QListBox *list ) +{ + QStringList f = d-> m_fdb. families ( ); + + for ( QStringList::ConstIterator it = f. begin ( ); it != f. end ( ); ++it ) { + QValueList <int> ps = d-> m_fdb. pointSizes ( *it ); + + if ( d-> m_pointbug ) { + for ( QValueList <int>::Iterator it = ps. begin ( ); it != ps. end ( ); it++ ) + *it /= 10; + } + + list-> insertItem ( new FontListItem ( *it, d-> m_fdb. styles ( *it ), ps )); + } +} + +void OFontSelector::fontFamilyClicked ( int index ) +{ + QString oldstyle = d-> m_font_style_list-> currentText ( ); + QString oldsize = d-> m_font_size_list-> currentText ( ); + + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( index ); + + d-> m_font_style_list-> clear ( ); + d-> m_font_style_list-> insertStringList ( fli-> styles ( )); + d-> m_font_style_list-> setEnabled ( !fli-> styles ( ). isEmpty ( )); + + int i; + + i = findItemCB ( d-> m_font_style_list, oldstyle ); + if ( i < 0 ) + i = findItemCB ( d-> m_font_style_list, "Regular" ); + if (( i < 0 ) && ( d-> m_font_style_list-> count ( ) > 0 )) + i = 0; + + if ( i >= 0 ) { + d-> m_font_style_list-> setCurrentItem ( i ); + fontStyleClicked ( i ); + } + + d-> m_font_size_list-> clear ( ); + QValueList<int> sl = fli-> sizes ( ); + + for ( QValueList<int>::Iterator it = sl. begin ( ); it != sl. end ( ); ++it ) + d-> m_font_size_list-> insertItem ( QString::number ( *it )); + + i = findItemCB ( d-> m_font_size_list, oldsize ); + if ( i < 0 ) + i = findItemCB ( d-> m_font_size_list, "10" ); + if (( i < 0 ) && ( d-> m_font_size_list-> count ( ) > 0 )) + i = 0; + + if ( i >= 0 ) { + d-> m_font_size_list-> setCurrentItem ( i ); + fontSizeClicked ( i ); + } + changeFont ( ); +} + +void OFontSelector::fontStyleClicked ( int /*index*/ ) +{ + changeFont ( ); +} + +void OFontSelector::fontSizeClicked ( int /*index*/ ) +{ + changeFont ( ); +} + +void OFontSelector::changeFont ( ) +{ + QFont f = selectedFont ( ); + + if ( d-> m_preview ) + d-> m_preview-> setFont ( f ); + + emit fontSelected ( f ); +} + +/** + * Return the selected font + */ +QFont OFontSelector::selectedFont ( ) +{ + int ffa = d-> m_font_family_list-> currentItem ( ); + int fst = d-> m_font_style_list-> currentItem ( ); + int fsi = d-> m_font_size_list-> currentItem ( ); + + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa ); + + if ( fli ) { + return d-> m_fdb. font ( fli-> family ( ), \ + fst >= 0 ? fli-> styles ( ) [fst] : QString::null, \ + fsi >= 0 ? fli-> sizes ( ) [fsi] : 10, \ + d-> m_fdb. charSets ( fli-> family ( )) [0] ); + } + else + return QFont ( ); +} + + +void OFontSelector::resizeEvent ( QResizeEvent *re ) +{ + if ( d-> m_preview ) { + d-> m_preview-> setMinimumHeight ( 1 ); + d-> m_preview-> setMaximumHeight ( 32767 ); + } + + QWidget::resizeEvent ( re ); + + if ( d-> m_preview ) + d-> m_preview-> setFixedHeight ( d-> m_preview-> height ( )); + +} diff --git a/microkde/ofontselector.h b/microkde/ofontselector.h new file mode 100644 index 0000000..b819c45 --- a/dev/null +++ b/microkde/ofontselector.h @@ -0,0 +1,96 @@ +/* + =. This file is part of the OPIE Project + .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org> + .>+-= + _;:, .> :=|. This library is free software; you can +.> <`_, > . <= redistribute it and/or modify it under +:`=1 )Y*s>-.-- : the terms of the GNU Library General Public +.="- .-=="i, .._ License as published by the Free Software + - . .-<_> .<> Foundation; either version 2 of the License, + ._= =} : or (at your option) any later version. + .%`+i> _;_. + .i_,=:_. -<s. This library is distributed in the hope that + + . -:. = it will be useful, but WITHOUT ANY WARRANTY; + : .. .:, . . . without even the implied warranty of + =_ + =;=|` MERCHANTABILITY or FITNESS FOR A + _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU +..}^=.= = ; Library General Public License for more +++= -. .` .: details. + : = ...= . :.=- + -. .:....=;==+<; You should have received a copy of the GNU + -_. . . )=. = Library General Public License along with + -- :-=` this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#ifndef OPIE_FONTSELECTOR_H__ +#define OPIE_FONTSELECTOR_H__ + +#include <qwidget.h> + +class QListBox; +class OFontSelectorPrivate; + +/** + * This class lets you chose a Font out of a list of Fonts. + * It can show a preview too. This selector will use all available + * fonts + * + * + * @short A widget to select a font + * @see QWidget + * @see QFont + * @author Rober Griebl + */ +class OFontSelector : public QWidget +{ + Q_OBJECT + +public: + OFontSelector ( bool withpreview, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + virtual ~OFontSelector ( ); + + bool selectedFont ( QString &family, QString &style, int &size ); + bool selectedFont ( QString &family, QString &style, int &size, QString &charset ); + + QFont selectedFont ( ); + + bool setSelectedFont ( const QFont & ); + bool setSelectedFont ( const QString &family, const QString &style, int size, const QString &charset = 0 ); + + QString fontFamily ( ) const; + QString fontStyle ( ) const; + int fontSize ( ) const; + QString fontCharSet ( ) const; + +signals: + /** + * This signal gets emitted when a font got chosen + */ + void fontSelected ( const QFont & ); + +protected slots: + /** @internal */ + virtual void fontFamilyClicked ( int ); + /** @internal */ + virtual void fontStyleClicked ( int ); + /** @internal */ + virtual void fontSizeClicked ( int ); + +protected: + virtual void resizeEvent ( QResizeEvent *re ); + +private: + void loadFonts ( QListBox * ); + + void changeFont ( ); + +private: + OFontSelectorPrivate *d; +}; + +#endif + diff --git a/microkde/qlayoutengine_p.h b/microkde/qlayoutengine_p.h new file mode 100644 index 0000000..2d6a556 --- a/dev/null +++ b/microkde/qlayoutengine_p.h @@ -0,0 +1,111 @@ +// THIS IS A COPY OF THE FILE FOUND IN $QTDIR/src/kernel. Needed to modify qsplitter + +/**************************************************************************** +** $Id$ +** +** Internal header file. +** +** Created : 981027 +** +** Copyright (C) 1998-99 by Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QLAYOUTENGINE_P_H +#define QLAYOUTENGINE_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qlayout.cpp, qlayoutengine.cpp, qmainwindow.cpp and qsplitter.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "qabstractlayout.h" +#endif // QT_H + +#ifndef QT_NO_LAYOUT +struct QLayoutStruct +{ + void initParameters() { minimumSize = sizeHint = 0; + maximumSize = QWIDGETSIZE_MAX; expansive = FALSE; empty = TRUE; } + void init() { stretch = 0; initParameters(); } + //permanent storage: + int stretch; + //parameters: + QCOORD sizeHint; + QCOORD maximumSize; + QCOORD minimumSize; + bool expansive; + bool empty; + //temporary storage: + bool done; + //result: + int pos; + int size; +}; + + +void qGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos, + int space, int spacer ); + + + +/* + Modify total maximum (max) and total expansion (exp) + when adding boxmax/boxexp. + + Expansive boxes win over non-expansive boxes. +*/ +static inline void qMaxExpCalc( QCOORD & max, bool &exp, + QCOORD boxmax, bool boxexp ) +{ + if ( exp ) { + if ( boxexp ) + max = QMAX( max, boxmax ); + } else { + if ( boxexp ) + max = boxmax; + else + max = QMIN( max, boxmax ); + } + exp = exp || boxexp; +} + +#endif //QT_NO_LAYOUT +#endif diff --git a/microkde/words.sort.txt b/microkde/words.sort.txt new file mode 100644 index 0000000..a477be7 --- a/dev/null +++ b/microkde/words.sort.txt @@ -0,0 +1,549 @@ + +{ "10 minutes", "10 Minuten", }, +{ "10th", "10." }, +{ "11th", "11." }, +{ "12 pm Format", "12 AM/PM Format" }, +{ "12th", "12." }, +{ "13th", "13." }, +{ "14th", "14." }, +{ "15th", "15." }, +{ "16th", "16." }, +{ "17th", "17." }, +{ "18th", "18." }, +{ "19th", "19." }, +{ "1 Day", "1 Tag" }, +{ "1 h", "1 Std" }, +{ "1 (Highest)", "1 (Höchster)" }, +{ "1st", "1." }, +{ "1st", "2." }, +{ "20th", "20." }, +{ "21st", "21." }, +{ "22nd", "22." }, +{ "23rd", "23." }, +{ "24:00 Hour Format", "24:00 Stunden Format" }, +{ "24th", "24." }, +{ "25th", "25." }, +{ "26th", "26." }, +{ "27th", "27." }, +{ "28th", "28." }, +{ "29th", "29." }, +{ "2nd", "2." }, +{ "30 minutes", "30 Minuten" }, +{ "30th", "30." }, +{ "31st", "31." }, +{ "3rd", "3." }, +{ "4th", "4." }, +{ "5 (lowest)", "5 (Niedrigster)" }, +{ "5th", "5." }, +{ "6th", "6." }, +{ "7th", "7." }, +{ "8th", "8." }, +{ "9th", "9." }, +{ "&Accept", "&Akzeptieren" }, +{ "Accept", "Akzeptieren" }, +{ "Accept A&ll", "A&lles Akzepieren" }, +{ "Access:", "Zugriff:" }, +{ "A corresponding event is missing in your calendar!", "Ein zugehöriges Ereignis fehlt in ihrem Kalender!" }, +{ "Actions", "Aktionen" }, +{ "Add Filter", "Filter Hinzufügen" }, +{ "&Add", "Hinzufügen" }, +{ "Add", "Hinzufügen" }, +{ "Additional email addresses:", "Zusätzliche E-Mail Adressen:" }, +{ "Additional email address:", "Zusätzliche E-Mail Adresse:" }, +{ "&Addressbook", "&Adressbuch" }, +{ "Address &Book...", "Adress&buch..." }, +{ "Agenda Size", "Agende Größe" }, +{ "Agenda Size:", "Größe der Agenda:" }, +{ "Agenda view:", "Agenda Anzeige:" }, +{ "Agenda view background color:", "Hintergrundfarbe der Agenda Anzeige:" }, +{ "All attendees", "Alle Teilnehmer" }, +{ "AllDayAgenda Height:", "Ganztagesagenda Höhe" }, +{ "Allday", "Ganztägig" }, +{ "Anonymous", "Anonym" }, +{ "Apply", "Bestätigen" }, +//{ "Appointment Time ", "" }, +{ "Apr", "Apr" }, +{ "April", "April" }, +//"Ask for every entry on conflict", "", +{ "Ask for preferences before syncing", "Vor dem Syncronisieren nachfragen" }, +{ "Ask for quit when closing KO/Pi", "Vor dem Beenden von KO/Pi nachfragen" }, +{ "Attendees", "Teilnehmer" }, +{ "Aug", "Aug" }, +{ "August", "August" }, +//"Auto Insert IMIP Replies"), +//"Auto Insert IMIP Requests"), +{ "Auto-Save", "Automatisches Abspeichern" }, +{ "Auto save delay in minutes:", "Auto Save Intervall in Minuten" }, +//"Auto Save FreeBusy Replies", "" +//"Auto Send FreeBusy Information"), +//"Auto Send Refresh"), +//"<b>Due on:</b> %1", "", +//"be added to the standard resource", "", +//"be asked which resource to use", "", +{ "Begin on:", "Starte mit:" }, +{ "Begins on: %1", "Starte mit: %1" }, +{ "<b>From:</b> %1 <b>To:</b> %2", "<b>Vom:</b> %1 <b>Zum:</b> %2" }, +{ "Bigger", "Größer" }, +{ "Biggest", "Am größten" }, +{ "Big", "Groß" }, +{ "<b>On:</b> %1", "<b>Am:</b> %1" }, +{ "<b>On:</b> %1 <b>From:S</b> %2 <b>To:</b> %3", "<b>Am:</b> %1 <b>Vom:S</b> %2 <b>Zum:</b> %3" }, +{ "<b>Original event:</b><p>", "<b>Original Ereignis:</b><p>" }, +{ " - both are modified after last sync", " - beide wurden nach der letzten Syncronisation verändert" }, +{ "Busy", "Belegt" }, +{ "&Cancel", "Abbre&chen" }, +{ "Cancel", "Abbrechen" }, +{ "Cannot delete To-Do\nwhich has children.", "Kann Todo nicht löschen,\n da noch Einträge vorhanden sind" }, +{ "Cannot delete To-Do which has children.", "Kann Todo nicht löschen, da noch Einträge vorhanden sind" }, +//"Cannot move To-Do to itself or a child of itself"), +//"Cannot purge To-Do which\nhas uncompleted children." +//"Can't generate mail:\nNo attendees defined.\n")); +{ "Can't generate mail:\nNo event selected.", "Kann e-Mail nicht erstellen:\nKein Ereignis ausgewählt." }, +{ "Categories...", "Kategorien..." }, +{ "Categories", "Kategorien" }, +{ "Category", "Kategorie" }, +{ "Center View", "Mittenansicht" }, +{ "Change", "Verändere" }, +{ "Cinema", "Kino" }, +{ "Click to add a new Todo", "Klicken, um ein neues Todo anzulegen" }, +{ "Clone Item", "Klone Eintrag" }, +{ "&Close", "S&chließen" }, +{ "Close", "Schließen" }, +{ "Close this dialog to abort deletion!", "Zum Abbrechen des Löschvorganges Dialog schließen!" }, +{ "Colors", "Farben" }, +{ "completed", "fertiggestellt" }, +{ "completed on %1", "fertiggestellt um %1" }, +{ "Complete", "Fertigstellen" }, +//{ "concatenation of dates and time", "%1 %2" }, +{ "Confirm &deletes", "Löschvogang bestätigen" }, +//"Copying succeed. Syncing not yet implemented" +//"Copy remote file to local machine..." +//{ "Could not find your attendee entry.\nPlease check the emails.")) }, +{ "Couldn't load calendar\n '%1'.", "Kann Kalender\n '%1' nicht laden." }, +{ "Counter-event Viewer", "Ereigniszähler Anzeige" }, +//{ "counter proposal event","<b>Counter-event:</b><p>" }, +{ "Daily ending hour:", "Tägl. Schlusszeit:" }, +{ "Daily starting hour:", "Tägliche Anfangszeit:" }, +{ "Daily", "Täglich" }, +{ "Date Format", "Datum Format" }, +{ "DateNavigator:(nr)" , "Datums Navigator" }, +//{ "Date Range") }, +{ "Dates: ", "Datum: " }, +{ "Date && Time", "Datum && Zeit" }, +{ "Day begins at:", "Der Tag beginnt um:" }, +{ "Days in Next-X-Days:", "Tage in den Nächsten-X-Tagen:" }, +{ "Days in What's Next:", "Tage in Was-kommt-Nun:" }, +{ "day(s)", "Tag(e)" }, +{ "Days to show in Next-X-Days view:", "Welche Tage in Nächste-X-Tagen anzeigen:" }, +{ "day", "Tag" }, +{ "Dec", "Dez" }, +{ "December", "Dezember" }, +{ "Default alarm time:", "Standard Alarm Zeit:" }, +//{ "Default appointment time:") }, +//{ "Default Calendar Format") }, +//{ "Default event color:") }, +//{ "Default export file", "calendar.html")) }, +{ "Default", "Standard" }, +//{ "Def. duration of new app.:") }, +{ "Delete All", "Lösche alles" }, +{ "Delete all selected", "Lösche alle ausgewählten" }, +//{ "delete completed To-Dos","Purge Completed") }, +//{ "delete completed To-Dos","Purge Completed") }, +{ "Delete Current", "Aktuellen löschen" }, +{ "Delete Event...", "Lösche Ereignis..." }, +{ "Delete Event", "Lösche Ereignis" }, +{ "&Delete", "Löschen" }, +{ "Delete", "Löschen" }, +{ "Delete Todo...", "Lösche Todo..." }, +{ "Delete To-Do", "Lösche Todo" }, +{ "Deleting item %d ...", "Lösche Eintrag %d..." }, +{ "Descriptions", "Beschreibungen" }, +{ "Deselect All", "Alles deselektieren" }, +{ "Details", "Details" }, +{ "Dinner", "Abendessen" }, +//{ "%d item(s) found."), mMatchedEvents.count() ) }, +//{ "%d items remaining in list."), count() ) }, +{ "Do you really want\nto close KO/Pi?", "Möchten Sie wirklich\nKO/PI verlassen?" }, +//"Do you really want\nto remote sync?\n \n" +//{ "Drop Event }, +//{ "Drop To-Do")) }, +//{ "Due Date")) }, +//{ "Due: ")+ (static_cast<Todo*>(mIncidence))->dtDueTimeStr() }, +//{ "Due Time")) }, +//{ "Due:"),timeBoxFrame) }, +{ "Duration: ", "Dauer: " }, +{ "Edit...", "Bearbeite..." }, +{ "Edit", "Bearbeite" }, +//{ "Edit Calendar Filters }, +{ "Edit Event...", "Bearbeite Ereignis..." }, +{ "Edit Event", "Bearbeite Ereignis" }, +//{ "Edit exceptions"), Ok|Cancel }, +{ "EditorBox:", "Editor Fenster:" }, +{ "Edit Recurrence Range", "Bearbeite Wiederholung" }, +//{ "&Edit..."),this,SLOT(popupEdit()))) }, +{ "Edit Todo...", "Berabeite Todo..." }, +{ "Edit To-Do", "Todo bearbeiten" }, +//{ "Email:" ) ) }, +{ "E&mail address:", "E&mail Adresse" }, +{ "(EmptyEmail)" , "(KeineEmail)" }, +{ "(EmptyName)", "(KeinName)" }, +//{ "Enable automatic saving of calendar") }, +//{ "Enable group scheduling") }, +//{ "Enable project view") }, +//{ "Enable Recurrence"), this ) }, +//{ "Enable scrollbars in month view cells") }, +//{ "Enable tooltips displaying summary of ev.") }, +//{ "End after"), rangeBox ) }, +//{ "End by:"), rangeBox ) }, +//{ "End Date")) }, +{ "End:", "Ende:" }, +//{ "End Time", "E)) }, +{ "English", "Englisch" }, +//{ "Enter filter name: }, +//{ "Error", "Fehler" }, +//{ "Error loading template file '%1'." }, +//{ "Event already exists in this calendar.") }, +{ "Event", "Ereignis" }, +{ "Event list", "Ereignis Liste" }, +//{ "Event list view uses full window") }, +//{ "Events and To-Dos that need a reply:") + "</h2>\n" }, +//{ "Events: ") + "</h2>\n" }, +//{ "Events have to be completely included"), topFrame) }, +//{ "Events"),incidenceGroup) }, +{ "Event Viewer:", "Ereignis Anzeige" }, +//{ "Event Viewer"),Ok|User1,Ok,false }, +//{ "Event will be sent to:")+"</h4>" }, +//{ "every"), this ) }, +{ "Exceptions...", "Ausnahmen..." }, +{ "Exceptions", "Ausnahmen" }, +{ "Exclude holidays", "Ohne Ferien" }, +{ "Exclude Saturdays", "Ohne Samstage" }, +//{ "Export to HTML with every save"),&(KOPrefs::instance()->mHtmlWithSave) }, +{ "Feb", "Feb" }, +{ "February", "Februar" }, +//{ "Filter disabled }, +//{ "Filter position: ") + QString::number ( mSelectionCombo->currentItem()+1 )) }, +//{ "Filter selected: }, +{ "&Find", "Finden" }, +{ "Fonts", "Zeichensätze" }, +//{ "Force take local entry always")) }, +//{ "Force take remote entry always")) }, +//{ "Form1" ) ) }, +//{ "Free Busy Object")) }, +{ "Free", "Frei" }, +{ "Friday", "Freitag" }, +{ "Fri", "Fr" }, +//{ "From: %1 To: %2 %3").arg(from).arg(to }, +//{ "From:"),rangeWidget)) }, +{ "Full &name:", "Vor- und &Nachname:" }, +//{ "Full path and file name required!"), topFrame) }, +{ "General", "Allgemein" }, +{ "German", "Deutsch" }, +{ "Gifts", "Geschenke" }, +//{ "Group Automation"),0 }, +//{ "Group Scheduling"),0 }, +{ "Help", "Hilfe" }, +{ "Hide Dates", "Daten ausblenden" }, +{ "Highlight color:" "Hervorhebungsfarbe" }, +{ "Holiday color:", "Ferien Farbe" }, +{ "hour(s)", "Stunde(n)" }, +//{ "iCalendar")) }, +//{ "If attendee is in addressbook")) }, +//{ "If organizer is in addressbook")) }, +//{ "If requested from an email in addressbook")) }, +//{ "If this counter-event is a good proposal for your event, press 'Accept'. All Attendees will then get the new version of this event }, +//{ "In %1 days: ").arg( i ) + "</font></em>"+day }, +//{ "Incomplete Todo:") + "</strong></big></big>\n" }, +{ "Information", "Information" }, +{ "Invalid search expression,\ncannot perform ", "Kann Suche nicht ausführen" }, +{ "Jan", "Jan" }, +{ "January", "Januar" }, +{ "JournalView:", "Journal Ansicht" }, +{ "Jul", "Jul" }, +{ "July", "Juli" }, +{ "Jump to date", "Springe zum Datum" }, +{ "June", "Juni" }, +{ "Jun", "Jun" }, +{ "Kids", "Kinder" }, +//{ "KMail", "KMail" }, +{ "KO/E Find ", "KO/E Suchen " }, +{ "KO/E Find: ", "KO/E Suchen: " }, +{ "KO/Pi is starting ... ", "KO/Pi startet ..." }, +{ "Language:(nyi)", "Sprache" }, +{ "Language:", "Sprache" }, +{ "Large", "Etwas mehr" }, +{ "List View:", "Listenansicht" }, +{ "Load/Save", "Laden/Speichern" }, +{ "Load Template", "Lade Vorlage" }, +{ "Locale", "Spracheinstellung" }, +{ "Local temp file:", "Lokales temp. Datei:" }, +//"Local temp file:\n " +//"Local temp file:\n..." +{ "Location: ", "Ort: " }, +{ "Location:", "Ort:" }, +{ "Mail client", "Mail Programm" }, +{ "Mail Client", "Mail Programm" }, +{ "March", "März" }, +{ "Mar", "Mär" }, +{ "May", "Mai" }, +{ "M. Bains line:", "M. Bains Linie:" }, +{ "Medium", "Medium" }, +{ "Method", "Methode" }, +{ "minute(s)", "Minute(n)" }, +{ "Monday", "Montag" }, +{ "Mon", "Mo" }, +{ "Monthly", "Monatlich" }, +{ "Month not long enough", "Monat ist nicht lang genug" }, +{ "month(s)", "Monat(e)" }, +{ "Month view:", "Monatsansicht" }, +{ "Month view uses category colors", "Monatsansicht benutzt die Kategorie Farben" }, +{ "Move &Down", "Nach unten verschieben" }, +{ "Move &Up", "Nach oben verschieben" }, +{ "Name:", "Name:" }, +{ "Name", "Name" }, +{ "\nAre you sure you want\nto delete this event?", "Sind Sie sicher, dass\n sie das Ereignis löschen möchten?" }, +{ "%n Days", "%n Tage" }, +{ "Never", "Nie" }, +{ "New event...", "Neues Ereignis..." }, +{ "New event", "Neues Ereignis" }, +{ "New Events/Todos should", "Meue Ereignisse/Todos sollten" }, +{ "&New", "&Neu" }, +{ "New", "Neu", }, +{ "New Sub-Todo...", "Neues Sub-Todo..." }, +{ "New Todo...", "Neues Todo..." }, +{ "New Todo", "Neues Todo" }, +{ "Next Alarm: ", "Nächster Alarm: ", }, +{ "&Next Day", "&Nächster Tag", }, +{ "Next days view uses full window", "Die Ansicht des nächsten Tages maximieren" }, +{ "Next month", "Nächster Monat" }, +{ "&Next Week", "&Nächste Woche" }, +{ "Next year", "Nächstes Jahr" }, +{ "Next Year", "Nächstes Jahr" }, +{ "%n h", "%n Std" }, +//"\n \nTry command on console to get more\ndetailed info about the reason.\n" +//{ "nobody@nowhere", " }, +{ "No ending date", "Kein End-Datum", }, +{ "No event, nothing to do.", "Kein Ereignis, nichts zu tun.", }, +{ "No event selected.", "Kein Ereignis selektiert" }, +//{ "No event/todo were found matching\nyour search expression.\nUse the wildcard characters\n ' * ' and ' ? ' where needed."));"KO/E Find ")) }, +{ "No", "Nein" }, +{ "No program set", "Kein Programm ausgewählt", }, +{ "Normal", "Normal" }, +{ "[No selection]", "Keine Selektion", }, +{ "No sound set", "Kein Sound ausgewählt", }, +{ "no time ", "keine Zeit ", }, +{ "no time", "keine Zeit", }, +{ "No Time", "Keine Zeit" }, +{ "November", "November" }, +{ "Nov", "Nov", }, +{ "\nThis event recurs\nover multiple dates.\n", "\nDieses Ereignis wiederholt sich an mehreren Tagen.\n" }, +//{ "occurrence(s)"), rangeBox ) }, +{ "October", "Oktober" }, +{ "Oct", "Okt", }, +//{ "O-due!", " }, +//{ "Okay, another question:\n\nDo you really want\nto erase your complete disk?\nI hope, the decision is now\na little bit easier! }, +{ "&OK", "&OK" }, +{ "Ok+Show!", "Ok+Anzeigen" }, +{ "Organizer: %1","Organizer %1" }, +{ "Organizer","Organizer" }, +//{ "Overdue To-Do:") + "</h2>\n" }, +{ "Owner: ", "Besitzer: " }, +{ "Owner:", "Besitzer:" }, +{ "<p><b>Priority:</b> %2</p>", "<p><b>Priorität:</b> %2</p>" }, +//{ "Personal Travel", }, +//{ "<p><i>%1 % completed</i></p>" }, +{ "Pick a date to display", "Wähle einen Tag zum anzeigen aus" }, +//{ "Playing '%1'").arg(fileName) }, +//{ "Playing '%1'").arg(mAlarmSound) }, +//{ "Please specify a valid due date.")) }, +//{ "Please specify a valid end date, for example '%1'." }, +//{ "Please specify a valid start date.")) }, +//{ "Please specify a valid start date, for example '%1'." }, +//{ "Please specify a valid start time.")) }, +//{ "Please specify a valid start time, for example '%1'." }, +//{ "Preferences - some settings need a restart (nr)")) }, +{ "Preferences - some settings need a restart (nr)", "Einstellungen - teilweise Neustart erforderlich" }, +{ "&Previous Day", "Vorheriger Tag" }, +{ "Previous month", "Vorheriger Monat" }, +{ "Previous Month", "Vorheriger Monat" }, +{ "&Previous Week", "Vorherige Woche" }, +{ "Previous year", "Vorheriges Jahr" }, +{ "Previous Year", "Vorheriges Jahr" }, +{ "Printing", "Drucken" }, +//{ "Prio")) }, +//{ "Priority:"), h) }, +{ "Proceed", "Weiter" }, +//{ "Purge }, +//{ "read-only") + ")</em>") }, +{ "Recur every", "Wiederh. alle" }, +{ "Recur in the month of", "Wiederh. im Monat" }, +{ "Recur on the", "Wiederh. am" }, +{ "Recur on this day", "Wiederh. am diesen Tag" }, +{ "Recurrence Range...", "Wiederholungs Zeitraum..." }, +{ "Recurrence Range", "Wiederholungs Zeitraum" }, +{ "Recurrence Rule", "Wiederholungs Regel" }, +{ "Recurrence", "Wiederholung" }, +{ "Recurs", "Wiederhole" }, +"&Reject", "Abweisen", +{ "Reminder:", "Erinnerung:" }, +//"Remote file:\n " +//"Remote file:\n..." +//{ "Remote file:"), topFrame) }, +//{ "Remote IP:"), topFrame) }, +//{ "Remote passwd:"), topFrame) }, +//{ "Remote syncing (via ssh/scp) network settings "), topFrame) }, +//{ "Remote user:"), topFrame) }, +{ "&Remove", "Entfe&rnen" }, +{ "Remove", "Entfernen" }, +{ "Request response", "Bemerkung anfordern" }, +//{ "Retrieve &Messages" ) ) }, +{ "Role:", "Rolle:" }, +{ "Role", "Rolle" }, +//{ "RSVP"),35) }, +//{ "Running '%1'").arg(fileName) }, +//{ "Running '%1'").arg(mAlarmProgram) }, +{ "Sat", "Sa" }, +{ "Saturday", "Samstag" }, +//{ "Save Template"), Ok | Cancel, Ok, parent, 0 }, +//{ "Scheduler - Incoming Messages" ) ) }, +//{ "Scheduler Mail Client"),&(KOPrefs::instance()->mIMIPScheduler) }, +//{ "Scheduler Mails Should Be"),&(KOPrefs::instance()->mIMIPSend) }, +//{ "Scheduler - Outgoing Messages" ) ) }, +{ "Search for:", "Suche nach:" }, +{ "Search In", "Suche in" }, +{ "Search", "Suche" }, +{ "Select Addresses", "Wähle Adressen" }, +{ "Select all", "Wähle alles" }, +{ "Select a month", "Wähle Monat" }, +//{ "Select a template to load:"), templates, 0, &ok ) }, +{ "Select a week", "Wähle Woche" }, +{ "Select a year", "Wähle Jahr" }, +//{ "selected emails")) }, +//{ "Select Template Name"), topFrame }, +//{ "Select the current day")) }, +//{ "Send copy to owner when mailing events") }, +{ "Send directly", "Sende direkt" }, +//{ "Sendmail")) }, +{ "&Send Messages", "&Sende Nachrichten", }, +//{ "Send to outbox")) }, +{ "Sep", "Sep" }, +{ "September", "September" }, +//{ "Set your status }, +//{ "Set Your Status")) }, +{ "Shopping", "Einkaufen" }, +{ "Short date in (WN/E) view", "Kurzdatum in (WN/E) Anzeige" }, +{ "Show Dates", "Zeige Daten" }, +//{ "Show events that recur daily in date nav.") }, +{ "Show Event...", "Zeige Ereignis..." }, +//{ "Show ev. that recur weekly in date nav.") }, +//{ "Show Marcus Bains line") }, +//{ "Show seconds on Marcus Bains line") }, +//{ "Show summary after syncing") }, +{ "Show time as:", "Zeige Zeit als" }, +{ "Show Todo...", "Zeige To-Do" }, +//{ "Show topmost todo prios in What's N.:") }, +//{ "Show topmost todo prios in What's Next:") }, +//{ "Show vertical screen (Needs restart)") }, +{ "&Show", "Zeige" }, +{ "Show...", "Zeige..." }, +{ "Show", "Zeige" }, +{ "Small", "Klein" }, +{ "Sorry", "Entschuldigung" }, +//"Sorry, the copy command failed!\nCommand was:\n" +//{ "Sort Id")) }, +{ "Start:", "Anfang:" }, +{ "Start Date", "Start Datum" }, +{ "Start Time", "Start Zeit" }, +{ "Status:", "Status:" }, +{ "Status","Status:" }, +//{ "Stretched TB", " +{ "Summaries","Zusammenfassungen" }, +{ "Summary:","Zusammenfassung:" }, +{ "Summary","Zusammenfassung" }, +{ "Sunday", "Sonntag" }, +{ "Sun", "So" }, +//{ "Sync Network"),0,0) }, +{ "Sync preferences:", "Sync Einstellungen" }, +{ "Sync Prefs", "Sync Einstellungen" }, +{ "Syncronize", "Daten abgleich" }, +//{ "Take local entry on conflict")) }, +//{ "Take newest entry on conflict")) }, +//{ "Take remote entry on conflict")) }, +//{ "Template '%1' does not contain a valid Todo." }, +//{ "Template does not contain a valid Event." }, +{ "Template...", "Vorlage..." }, +//{ "The event ends before it starts.\n }, +//{ "The event has no attendees.")) }, +//{ "The journal entries can not be\nexported to a vCalendar file.") }, +//{ "The organizer %1", " }, +//{ "The start date cannot be after the due date.")) }, +//{ " - they have the same unique ID "), topFrame) }, +{ "This day", "Dieser Tag" }, +{ "This is an experimental feature. ", "Dieses Feature ist experimentel" }, +//{ "This is a recurring event.") + "</em>") }, +{ "This item will be\npermanently deleted.", "Dieser Eintrag wird\nkomplett gelöscht." }, +{ "This item will be permanently deleted.", "Dieser Eintrag wird komplett gelöscht." }, +{ "Thu", "Do" }, +{ "Thursday", "Donnerstag" }, +{ "Time associated", "Dazugehörige Zeit" }, +{ "Time bar:", "Zeit Intervall" }, +{ "Time && Date", "Zeit und Datum" }, +{ "Time Format", "Zeit Format" }, +{ "Time Labels:", "Zeit Markierungen:" }, +{ "Time: ", "Zeit: " }, +{ "Timezone:", "Zeitzone:" }, +{ "Tiny", "Sehr klein" }, +{ "To: ", "An: " }, +{ "To:", "An:" }, +{ "Today: ", "Heute: " }, +//{ "To-Do: %1 }, +//{ "Todo due today color:") }, +//{ "To-do items:"),this) }, +//{ "Todo overdue color:") }, +//{ "Todos"),incidenceGroup) }, +{ "Todo", "Todo" }, +{ "To-do view shows completed Todos", "To-do Anzeige zeigt erledigte To-dos" }, +{ "ToDoView:", "Todo Anzeige:" }, +{ "Toggle Alarm", "Wechsle Alarm" }, +{ "Toggle Allday", "Umschalten Ganztag" }, +//{ "toggle completed To-Dos","Hide/Show Completed") }, +//{ "toggle completed To-Dos","Hide/Show Completed") }, +{ "Tomorrow: ", "Morgen: " }, +// { "Toolbar", "Zugriffsleiste" }, +{ "Tue", "Di" }, +{ "Tuesday", "Dienstag" }, +{ "Two entries are in conflict, if: ", "Zwei Einträge haben einen Konflikt, wenn:" }, +{ "Unable to find template '%1'.", "Kann Vorlage '%1' nicht finden." }, +{ "University", "Universität" }, +{ "Unknown", "Unbekannt" }, +{ "Up", "Hinauf" }, +//{ "&Use email settings from Control Center", " }, +{ "Use password (if not, ask when syncing)", "Passwort: (sonst jedesmal anfragen)" }, +{ "User defined (next page)", "Benutzer definiert (Nächste Seite)" }, +{ "User long date", "Benutz. lang. Datum" }, +{ "User short date", "Benutz. kurz. Datum" }, +//{ "vCalendar")) }, +{ "View", "Ansicht" }, +{ "View", "Anzeige" }, +{ "View Fonts", "Zeige Schriften" }, +{ "Views", "Ansichten" }, +//{ "VIP") }, +{ "Wed", "Mi" }, +{ "Wednesday", "Mittwoch" }, +{ "Week %1", "Woche %1" }, +{ "Weekly", "Wöchentlich" }, +//{ "week(s) on:"), this ) }, +{ "Week starts on Sunday", "Wochenanfang Sonntags" }, +{ "What's Next View:", "What's Next Anzeige" }, +{ "What's next ?", "Was kommt als nächstes?" }, +{ "Working Hours", "Arbeitsstunden" }, +{ "Working hours color:", "Farbe der Arbeitsstunden" }, +{ "Write back existing entries only", "Nur exisitierende Einträge zurückschreiben" }, +{ "Write back synced file", "Syncronisierte Datei zurückschreiben" }, +{ "Yearly", "Jährlich" }, +{ "year(s)", "Jahr(e)" }, +{ "Yes", "Ja" }, +{ "You have %d item(s) selected.\n", "Sie haben %d Einträge ausgewählt.\n" }, +{ "You have to restart KOrganizer for this setting to take effect.","Sie müssem Korganizer neu starten, damit diese Einstellung aktiviert wird." }, +//{ "Zoom In", "Hineinzoomen" }, +//{ "Zoom Out", "Herauszoomen" }, |