diff options
Diffstat (limited to 'lib/kotext/KoParagDia.cpp')
-rw-r--r-- | lib/kotext/KoParagDia.cpp | 2289 |
1 files changed, 2289 insertions, 0 deletions
diff --git a/lib/kotext/KoParagDia.cpp b/lib/kotext/KoParagDia.cpp new file mode 100644 index 00000000..589cfb80 --- /dev/null +++ b/lib/kotext/KoParagDia.cpp @@ -0,0 +1,2289 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2005 Martin Ellis <martin.ellis@kdemail.net> + Copyright (C) 2006 Thomas Zander <zander@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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "KoParagDia.h" +#include "KoParagDia_p.h" +#include "KoDocument.h" +#include "KoTextFormat.h" +#include "KoTextParag.h" +#include "KoTextDocument.h" +#include "KoTextZoomHandler.h" +#include "KoParagDecorationTab.h" + +#include <KoCharSelectDia.h> +#include <KoUnitWidgets.h> +#include <kcolorbutton.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <knumvalidator.h> +#include <KoGlobal.h> +#include <qgroupbox.h> +#include <knuminput.h> +#include <kdeversion.h> +#include <kpushbutton.h> +#include <kcombobox.h> + +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qhbuttongroup.h> +#include <qlabel.h> +#include <qradiobutton.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qtooltip.h> +#include <qlayout.h> +#include <qapplication.h> +#include <qwidgetstack.h> + +KoCounterStyleWidget::KoCounterStyleWidget( bool displayDepth, bool onlyStyleTypeLetter, bool disableAll, QWidget * parent, const char* name ) + :QWidget( parent, name ), + stylesList() +{ + noSignals = true; + styleBuffer = 999; + QVBoxLayout *vbox = new QVBoxLayout( this,0, 0/*KDialog::marginHint(), KDialog::spacingHint()*/ ); + gStyle = new QGroupBox( i18n( "St&yle" ), this, "styleLayout" ); + vbox->addWidget( gStyle); + QGridLayout * grid = new QGridLayout(gStyle, 12, 5, KDialog::marginHint(), KDialog::spacingHint()); + grid->addRowSpacing(0, fontMetrics().height()/2); + + makeCounterRepresenterList( stylesList, onlyStyleTypeLetter ); + + lstStyle = new QListBox( gStyle, "styleListBox" ); + grid->addMultiCellWidget( lstStyle, 1, 11, 0, 0); + fillStyleCombo(); + connect( lstStyle, SIGNAL( selectionChanged() ), this, SLOT( numStyleChanged() ) ); + + + QLabel *lPrefix = new QLabel( gStyle, "lPrefix" ); + lPrefix->setText( i18n( "Pre&fix text:" ) ); + grid->addWidget( lPrefix, 1, 1); + + sPrefix = new QLineEdit( gStyle, "sPrefix" ); + lPrefix->setBuddy( sPrefix ); + grid->addWidget( sPrefix, 1, 2); + + QLabel *lSuffix = new QLabel( gStyle, "lSuffix" ); + lSuffix->setText( i18n( "Suffi&x text:" ) ); + grid->addWidget( lSuffix, 1, 3); + + sSuffix = new QLineEdit( gStyle, "sSuffix" ); + lSuffix->setBuddy( sSuffix ); + grid->addWidget( sSuffix, 1, 4 ); + + lStart = new QLabel( gStyle, "lStart" ); + lStart->setText( i18n( "&Start at:" ) ); + grid->addWidget( lStart, 2, 1 ); + + + spnDepth = new QSpinBox( 0, 15, 1, gStyle ); + if ( displayDepth ) + grid->addWidget( spnDepth, 3, 2 ); + else + spnDepth->hide(); + + spnDisplayLevels = new QSpinBox( 0, 15, 1, gStyle ); + spnDisplayLevels->setMinValue( 1 ); + if ( displayDepth ) + grid->addWidget( spnDisplayLevels, 3, 4 ); + else + spnDisplayLevels->hide(); + + + QHBoxLayout *customCharBox = new QHBoxLayout(0, 0, 6); + lCustom = new QLabel( i18n( "Custo&m character:" ), gStyle, "custom char label" ); + customCharBox->addWidget( lCustom ); + + bCustom = new QPushButton( "", gStyle, "bCustom" ); + lCustom->setBuddy( bCustom ); + customCharBox->addWidget( bCustom ); + connect( bCustom, SIGNAL( clicked() ), this, SLOT( selectCustomBullet() ) ); + + QSpacerItem* spacer_2 = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ); + customCharBox->addItem( spacer_2 ); + + grid->addMultiCellLayout(customCharBox, 4, 4, 1, 4, Qt::AlignLeft); + + spnStart = new KoSpinBox( gStyle ); + spnStart->setMinValue ( 1); + lStart->setBuddy( spnStart ); + grid->addWidget( spnStart, 2, 2); + + lAlignment = new QLabel( gStyle, "lAlignment" ); + lAlignment->setText( i18n( "Counter alignment:" ) ); + grid->addWidget( lAlignment, 2, 3 ); + + cbAlignment = new KComboBox( gStyle, "cbAlignment" ); + cbAlignment->insertItem(i18n("Align Auto")); + cbAlignment->insertItem(i18n("Align Left")); + cbAlignment->insertItem(i18n("Align Right")); + cbAlignment->setCurrentItem(0); + grid->addWidget( cbAlignment, 2, 4 ); + + QLabel *lDepth = new QLabel( gStyle, "lDepth" ); + lDepth->setText( i18n( "&Depth:" ) ); + lDepth->setBuddy( spnDepth ); + if ( displayDepth ) + grid->addWidget( lDepth, 3, 1 ); + else + lDepth->hide(); + + QLabel *lDisplayLevels = new QLabel( gStyle ); + lDisplayLevels->setText( i18n( "Display le&vels:" ) ); + lDisplayLevels->setBuddy( spnDisplayLevels ); + if ( displayDepth ) + grid->addWidget( lDisplayLevels, 3, 3 ); + else + lDisplayLevels->hide(); + + cbRestart = new QCheckBox( i18n( "&Restart numbering at this paragraph" ), gStyle ); + grid->addMultiCellWidget( cbRestart, 5, 5, 1, 3 ); + + if ( onlyStyleTypeLetter ) + { + lCustom->hide(); + bCustom->hide(); + cbRestart->hide(); + } + + + connect( cbRestart, SIGNAL( toggled(bool) ), this, SLOT( restartChanged(bool) ) ); + + connect( sSuffix, SIGNAL( textChanged (const QString &) ), this, SLOT( suffixChanged(const QString &) ) ); + connect( sPrefix, SIGNAL( textChanged (const QString &) ), this, SLOT( prefixChanged(const QString &) ) ); + connect( spnStart, SIGNAL( valueChanged (int) ), this, SLOT( startChanged(int) ) ); + connect( spnDepth, SIGNAL( valueChanged (int) ), this, SLOT( depthChanged(int) ) ); + connect( spnDisplayLevels, SIGNAL( valueChanged (int) ), this, SLOT( displayLevelsChanged(int) ) ); + connect( cbAlignment, SIGNAL( activated (const QString&) ), this, SLOT( alignmentChanged(const QString&) ) ); + noSignals = false; + if ( disableAll ) + { + gStyle->setEnabled( false ); + lstStyle->setEnabled( false ); + sSuffix->setEnabled( false ); + sPrefix->setEnabled( false ); + bCustom->setEnabled( false ); + spnStart->setEnabled( false ); + spnDepth->setEnabled( false ); + spnDisplayLevels->setEnabled( false ); + lStart->setEnabled( false ); + lCustom->setEnabled( false ); + cbRestart->setEnabled( false ); + cbAlignment->setEnabled( false ); + } +} + +void KoCounterStyleWidget::alignmentChanged(const QString& s) +{ + int a; + if(s==i18n("Align Left")) + a=Qt::AlignLeft; + else if(s==i18n("Align Right")) + a=Qt::AlignRight; + else if(s==i18n("Align Auto")) + a=Qt::AlignAuto; + else { + kdError()<<"Not Implemented"<<endl; + return; + } + m_counter.setAlignment(a); + emit sig_alignmentChanged(a); +} + +void KoCounterStyleWidget::setCounter( const KoParagCounter& counter ) +{ + noSignals = true; + KoParagCounter::Style st = counter.style(); + m_counter = counter; + // Huh? doesn't the line above do this already? + //m_counter.setStyle( st ); + changeKWSpinboxType( st); + displayStyle( st ); + noSignals = false; +} + +void KoCounterStyleWidget::changeKWSpinboxType(KoParagCounter::Style st) { + switch(st) + { + case KoParagCounter::STYLE_NONE: + spnStart->setCounterType(KoSpinBox::NONE); + break; + case KoParagCounter::STYLE_NUM: + spnStart->setCounterType(KoSpinBox::NUM); + break; + case KoParagCounter::STYLE_ALPHAB_L: + spnStart->setCounterType(KoSpinBox::ALPHAB_L); + break; + case KoParagCounter::STYLE_ALPHAB_U: + spnStart->setCounterType(KoSpinBox::ALPHAB_U); + break; + case KoParagCounter::STYLE_ROM_NUM_L: + spnStart->setCounterType(KoSpinBox::ROM_NUM_L); + break; + case KoParagCounter::STYLE_ROM_NUM_U: + spnStart->setCounterType(KoSpinBox::ROM_NUM_U); + break; + default: + spnStart->setCounterType(KoSpinBox::NONE); + } +} + + +void KoCounterStyleWidget::fillStyleCombo(KoParagCounter::Numbering type) { + if(lstStyle==NULL) return; + noSignals=true; + unsigned int cur = lstStyle->currentItem(); + lstStyle->clear(); + QPtrListIterator<StyleRepresenter> style( stylesList ); + while ( style.current() ) { + if(style.current()->style() == KoParagCounter::STYLE_NONE) { + if(type == KoParagCounter::NUM_NONE) + lstStyle->insertItem( style.current()->name() ); + } + else if(type == KoParagCounter::NUM_LIST || !style.current()->isBullet()) + if(type != KoParagCounter::NUM_NONE) + lstStyle->insertItem( style.current()->name() ); + ++style; + } + + if(styleBuffer <= lstStyle->count()) + lstStyle->setCurrentItem(styleBuffer); + else + if(cur <= lstStyle->count()) + lstStyle->setCurrentItem(cur); + + if(cur > lstStyle->count()) { + styleBuffer = cur; + } + noSignals=false; +} + +void KoCounterStyleWidget::displayStyle( KoParagCounter::Style style ) +{ + unsigned int i = 0; + while ( stylesList.count() > i && stylesList.at(i)->style() != style ) + ++i; + lstStyle->setCurrentItem(i); + + bCustom->setText( m_counter.customBulletCharacter() ); + if ( !m_counter.customBulletFont().isEmpty() ) + bCustom->setFont( QFont( m_counter.customBulletFont() ) ); + + sPrefix->setText( m_counter.prefix() ); + sSuffix->setText( m_counter.suffix() ); + + spnDepth->setValue( m_counter.depth() ); + spnDisplayLevels->setValue( m_counter.displayLevels() ); + spnStart->setValue( m_counter.startNumber() ); + + cbRestart->setChecked( m_counter.restartCounter() ); + if(m_counter.alignment()==Qt::AlignLeft) + cbAlignment->setCurrentText(i18n("Align Left")); + else if(m_counter.alignment()==Qt::AlignRight) + cbAlignment->setCurrentText(i18n("Align Right")); + else if(m_counter.alignment()==Qt::AlignAuto) + cbAlignment->setCurrentText(i18n("Align Auto")); + else + kdError()<<"Not Implemented"<<endl; +} + +void KoCounterStyleWidget::display( const KoParagLayout & lay ) { + KoParagCounter::Style style = KoParagCounter::STYLE_NONE; + if ( lay.counter ) + { + style=lay.counter->style(); + m_counter = *lay.counter; + } + else + { + m_counter = KoParagCounter(); + } + styleBuffer = 999; + + numTypeChanged( m_counter.numbering() ); + emit sig_numTypeChanged( m_counter.numbering() ); + + displayStyle( style ); +} + + +void KoCounterStyleWidget::numTypeChanged( int nType ) { + m_counter.setNumbering( static_cast<KoParagCounter::Numbering>( nType ) ); + gStyle->setEnabled( m_counter.numbering() != KoParagCounter::NUM_NONE ); + fillStyleCombo(m_counter.numbering()); + bool state=m_counter.numbering()==KoParagCounter::NUM_LIST; + bCustom->setEnabled(state); + lCustom->setEnabled(state); +} + + +void KoCounterStyleWidget::makeCounterRepresenterList( QPtrList<StyleRepresenter>& stylesList, bool onlyStyleTypeLetter ) +{ + stylesList.setAutoDelete( true ); + stylesList.append( new StyleRepresenter(i18n( "Arabic Numbers" ) + , KoParagCounter::STYLE_NUM)); + stylesList.append( new StyleRepresenter(i18n( "Lower Alphabetical" ) + , KoParagCounter::STYLE_ALPHAB_L )); + stylesList.append( new StyleRepresenter(i18n( "Upper Alphabetical" ) + , KoParagCounter::STYLE_ALPHAB_U )); + stylesList.append( new StyleRepresenter(i18n( "Lower Roman Numbers" ) + , KoParagCounter::STYLE_ROM_NUM_L )); + stylesList.append( new StyleRepresenter(i18n( "Upper Roman Numbers" ) + , KoParagCounter::STYLE_ROM_NUM_U )); + if ( !onlyStyleTypeLetter ) + { + stylesList.append( new StyleRepresenter(i18n( "Disc Bullet" ) + , KoParagCounter::STYLE_DISCBULLET , true)); + stylesList.append( new StyleRepresenter(i18n( "Square Bullet" ) + , KoParagCounter::STYLE_SQUAREBULLET , true)); + stylesList.append( new StyleRepresenter(i18n( "Box Bullet" ) + , KoParagCounter::STYLE_BOXBULLET , true)); + stylesList.append( new StyleRepresenter(i18n( "Circle Bullet" ) + , KoParagCounter::STYLE_CIRCLEBULLET , true)); + stylesList.append( new StyleRepresenter(i18n( "Custom Bullet" ) + , KoParagCounter::STYLE_CUSTOMBULLET , true)); + } + stylesList.append( new StyleRepresenter(i18n( "None" ), KoParagCounter::STYLE_NONE)); +} + + +void KoCounterStyleWidget::selectCustomBullet() { + unsigned int i = 0; + while ( stylesList.count() > i && stylesList.at(i)->style() != KoParagCounter::STYLE_CUSTOMBULLET ) + ++i; + lstStyle->setCurrentItem(i); + + QString f = m_counter.customBulletFont(); + if ( f.isEmpty() ) + f = "symbol"; + QChar c = m_counter.customBulletCharacter(); + + if ( KoCharSelectDia::selectChar( f, c ) ) { + emit changeCustomBullet( f, c ); + m_counter.setCustomBulletFont( f ); + m_counter.setCustomBulletCharacter( c ); + if ( !f.isEmpty() ) + bCustom->setFont( QFont( f ) ); + bCustom->setText( c ); + } +} + +void KoCounterStyleWidget::numStyleChanged() { + if ( noSignals ) + return; + // We selected another style from the list box. + styleBuffer = 999; + StyleRepresenter *sr = stylesList.at(lstStyle->currentItem()); + emit changeStyle( sr->style() ); + m_counter.setStyle( sr->style() ); + bool isNumbered = !sr->isBullet() && !sr->style() == KoParagCounter::STYLE_NONE; + lStart->setEnabled( isNumbered ); + spnStart->setEnabled( isNumbered ); + cbRestart->setEnabled( isNumbered ); + spnDisplayLevels->setEnabled( isNumbered ); + changeKWSpinboxType(sr->style() ); +} + + + +KoSpinBox::KoSpinBox( QWidget * parent, const char * name ) + : QSpinBox(parent,name) +{ + m_Etype=NONE; + //max value supported by roman number + setMaxValue ( 3999 ); +} +KoSpinBox::~KoSpinBox( ) +{ +} + +KoSpinBox::KoSpinBox( int minValue, int maxValue, int step , + QWidget * parent , const char * name ) + : QSpinBox(minValue, maxValue,step , + parent , name) +{ + m_Etype=NONE; +} + +void KoSpinBox::setCounterType(counterType _type) +{ + m_Etype=_type; + editor()->setText(mapValueToText(value())); +} + + +QString KoSpinBox::mapValueToText( int value ) +{ + if(value==0 && m_Etype==NUM) + return QString("0"); + else if(value==0 && m_Etype!=NUM) + return QString::null; + switch(m_Etype) + { + case NUM: + return QString::number(value); + case ALPHAB_L: + return KoParagCounter::makeAlphaLowerNumber( value ); + case ALPHAB_U: + return KoParagCounter::makeAlphaUpperNumber( value ); + case ROM_NUM_L: + return KoParagCounter::makeRomanNumber( value ); + case ROM_NUM_U: + return KoParagCounter::makeRomanNumber( value ).upper(); + case NONE: + default: + return QString::null; + } + //never here + return QString::null; +} + +int KoSpinBox::mapTextToValue( bool * ok ) +{ + int ret; + QString txt = text(); + + *ok = TRUE; + switch(m_Etype) + { + case NUM: + ret = txt.toInt ( ok ); + break; + case ALPHAB_L: + ret = KoParagCounter::fromAlphaLowerNumber( txt.lower() ); + break; + case ALPHAB_U: + ret = KoParagCounter::fromAlphaUpperNumber( txt.upper() ); + break; + case ROM_NUM_L: + ret = KoParagCounter::fromRomanNumber( txt.lower() ); + break; + case ROM_NUM_U: + ret = KoParagCounter::fromRomanNumber( txt.lower() ); // _not_ upper() + break; + case NONE: + default: + ret = -1; + break; + } + + if (ret == -1) + *ok = FALSE; + + return ret; +} + + +/******************************************************************/ +/* class KPagePreview */ +/******************************************************************/ + +KPagePreview::KPagePreview( QWidget* parent, const char* name ) + : QGroupBox( i18n( "Preview" ), parent, name ) +{ + left = 0; + right = 0; + first = 0; + spacing = 0; + before = 0; + after = 0; +} + +void KPagePreview::drawContents( QPainter* p ) +{ + int wid = 148; + int hei = 210; + int _x = ( width() - wid ) / 5; + int _y = ( height() - hei ) / 5; + + int dl = convert(left); + int dr = convert(right); + + //first+left because firstlineIndent is relative to leftIndent + int df = convert(first + left); + + int spc = convert(spacing); + + // draw page + p->setPen( QPen( black ) ); + p->setBrush( QBrush( black ) ); + + p->drawRect( _x + 1, _y + 1, wid, hei ); + + p->setBrush( QBrush( white ) ); + p->drawRect( _x, _y, wid, hei ); + + // draw parags + p->setPen( NoPen ); + p->setBrush( QBrush( lightGray ) ); + + for ( int i = 1; i <= 4; i++ ) + p->drawRect( _x + 6, _y + 6 + ( i - 1 ) * 12 + 2, wid - 12 - ( ( i / 4 ) * 4 == i ? 50 : 0 ), 6 ); + + p->setBrush( QBrush( darkGray ) ); + + for ( int i = 5; i <= 8; i++ ) + { + QRect rect( ( i == 5 ? df : dl ) + _x + 6, _y + 6 + ( i - 1 ) * 12 + 2 + ( i - 5 ) * spc + static_cast<int>( before / 2 ), + wid - 12 - ( ( i / 4 ) * 4 == i ? 50 : 0 ) - ( ( i == 12 ? 0 : dr ) + ( i == 5 ? df : dl ) ), 6); + + if(rect.width ()>=0) + p->drawRect( rect ); + } + p->setBrush( QBrush( lightGray ) ); + + for ( int i = 9; i <= 12; i++ ) + p->drawRect( _x + 6, _y + 6 + ( i - 1 ) * 12 + 2 + 3 * spc + + static_cast<int>( before / 2 ) + static_cast<int>( after / 2 ), + wid - 12 - ( ( i / 4 ) * 4 == i ? 50 : 0 ), 6 ); + +} + +int KPagePreview::convert(double input) { + if(input < 1) return 0; + if(input <= 5) return 3; + if(input <= 10) return 4 + static_cast<int>( (input-5) / 2.5 ); + if(input <= 20) return 6 + static_cast<int>( (input-10) / 4 ); + if(input <= 100) return 10 + static_cast<int>( (input-20) / 8 ); + return static_cast<int>( input / 5); +} + +/******************************************************************/ +/* class KPagePreview2 */ +/******************************************************************/ + +KPagePreview2::KPagePreview2( QWidget* parent, const char* name ) + : QGroupBox( i18n( "Preview" ), parent, name ) +{ + align = Qt::AlignLeft; +} + +void KPagePreview2::drawContents( QPainter* p ) +{ + int wid = 148; + int hei = 210; + int _x = ( width() - wid ) / 2; + int _y = ( height() - hei ) / 2; + + // draw page + p->setPen( QPen( black ) ); + p->setBrush( QBrush( black ) ); + + p->drawRect( _x + 1, _y + 1, wid, hei ); + + p->setBrush( QBrush( white ) ); + p->drawRect( _x, _y, wid, hei ); + + // draw parags + p->setPen( NoPen ); + p->setBrush( QBrush( lightGray ) ); + + for ( int i = 1; i <= 4; i++ ) + p->drawRect( _x + 6, _y + 6 + ( i - 1 ) * 12 + 2, wid - 12 - ( ( i / 4 ) * 4 == i ? 50 : 0 ), 6 ); + + p->setBrush( QBrush( darkGray ) ); + + int __x = 0, __w = 0; + for ( int i = 5; i <= 8; i++ ) { + switch ( i ) { + case 5: __w = wid - 12; + break; + case 6: __w = wid - 52; + break; + case 7: __w = wid - 33; + break; + case 8: __w = wid - 62; + default: break; + } + + switch ( align ) { + case Qt::AlignAuto: + case Qt::AlignLeft: + __x = _x + 6; + break; + case Qt::AlignHCenter: + __x = _x + ( wid - __w ) / 2; + break; + case Qt::AlignRight: + __x = _x + ( wid - __w ) - 6; + break; + case Qt::AlignJustify: + { + if ( i < 8 ) __w = wid - 12; + __x = _x + 6; + } break; + } + + p->drawRect( __x, _y + 6 + ( i - 1 ) * 12 + 2 + ( i - 5 ), __w, 6 ); + } + + p->setBrush( QBrush( lightGray ) ); + + for ( int i = 9; i <= 12; i++ ) + p->drawRect( _x + 6, _y + 6 + ( i - 1 ) * 12 + 2 + 3, wid - 12 - ( ( i / 4 ) * 4 == i ? 50 : 0 ), 6 ); + +} + +/******************************************************************/ +/* class KoBorderPreview */ +/******************************************************************/ + + +KoBorderPreview::KoBorderPreview( QWidget* parent, const char* name ) + :QFrame(parent,name) +{ +} + +void KoBorderPreview::mousePressEvent( QMouseEvent *_ev ) +{ + emit choosearea(_ev); +} + +void KoBorderPreview::setBorder( KoBorder::BorderType which, const KoBorder& border) +{ + switch( which ) { + case KoBorder::TopBorder: + setTopBorder( border ); + break; + case KoBorder::BottomBorder: + setBottomBorder( border ); + break; + case KoBorder::LeftBorder: + setLeftBorder( border ); + break; + case KoBorder::RightBorder: + setRightBorder( border ); + break; + default: + kdError() << "KoBorderPreview: unknown border type" << endl; + } +} + +void KoBorderPreview::drawContents( QPainter* painter ) +{ + QRect r = contentsRect(); + QFontMetrics fm( font() ); + + painter->fillRect( r.x() + fm.width( 'W' ), r.y() + fm.height(), r.width() - 2 * fm.width( 'W' ), + r.height() - 2 * fm.height(), white ); + painter->setClipRect( r.x() + fm.width( 'W' ), r.y() + fm.height(), r.width() - 2 * fm.width( 'W' ), + r.height() - 2 * fm.height() ); + + bool leftdouble = m_leftBorder.width() > 0 && m_leftBorder.getStyle() == KoBorder::DOUBLE_LINE; + bool rightdouble = m_rightBorder.width() > 0 && m_rightBorder.getStyle() == KoBorder::DOUBLE_LINE; + bool topdouble = m_topBorder.width() > 0 && m_topBorder.getStyle() == KoBorder::DOUBLE_LINE; + bool bottomdouble = m_bottomBorder.width() > 0 && m_bottomBorder.getStyle() == KoBorder::DOUBLE_LINE; + + if ( m_topBorder.width() > 0 ) { + painter->setPen( setBorderPen( m_topBorder ) ); + painter->drawLine( r.x() + 20, r.y() + 30, r.right() - 19, r.y() + 30 ); + if ( m_topBorder.getStyle()==KoBorder::DOUBLE_LINE) + painter->drawLine( int(r.x() + 20 + ( leftdouble ? m_leftBorder.width() + 1 : 0) ), + int(r.y() + 30 + m_topBorder.width()+1), + int(r.right() - 19 - ( rightdouble ? m_rightBorder.width() + 1 : 0) ), + int(r.y() + 30 + m_topBorder.width()+1) + ); + } + + if ( m_bottomBorder.width() > 0 ) { + painter->setPen( setBorderPen( m_bottomBorder ) ); + painter->drawLine( r.x() + 20, r.bottom() - 30, r.right() - 19, r.bottom() - 30 ); + if ( m_bottomBorder.getStyle()==KoBorder::DOUBLE_LINE) + painter->drawLine( int(r.x() + 20 + ( leftdouble ? m_leftBorder.width() + 1 : 0) ), + int(r.bottom() - 30 - m_bottomBorder.width()-1), + int(r.right() - 19 - ( rightdouble ? m_rightBorder.width() + 1 : 0) ), + int(r.bottom() - 30 - m_bottomBorder.width() - 1) + ); + } + + if ( m_leftBorder.width() > 0 ) { + painter->setPen( setBorderPen( m_leftBorder ) ); + painter->drawLine( r.x() + 20, r.y() + 30, r.x() + 20, r.bottom() - 29 ); + if ( m_leftBorder.getStyle()==KoBorder::DOUBLE_LINE) + painter->drawLine( int(r.x() + 20 + m_leftBorder.width() +1), + int(r.y() + 30 + ( topdouble ? m_topBorder.width() + 1 : 0) ), + int(r.x() + 20 + m_leftBorder.width() +1), + int(r.bottom() - 29 - ( bottomdouble ? m_bottomBorder.width() + 1 : 0) ) + ); + } + + if ( m_rightBorder.width() > 0 ) { + painter->setPen( setBorderPen( m_rightBorder ) ); + painter->drawLine( r.right() - 20, r.y() + 30, r.right() - 20, r.bottom() - 29 ); + if ( m_rightBorder.getStyle()==KoBorder::DOUBLE_LINE) + painter->drawLine( int(r.right() - 20 - m_rightBorder.width() - 1 ), + int(r.y() + 30 + ( topdouble ? m_topBorder.width() + 1 : 0) ), + int(r.right() - 20 - m_rightBorder.width() - 1), + int(r.bottom() - 29 - ( bottomdouble ? m_bottomBorder.width() + 1 : 0) ) + ); + } +} + +QPen KoBorderPreview::setBorderPen( KoBorder _brd ) +{ + QPen pen( black, 1, SolidLine ); + + pen.setWidth( static_cast<int>( _brd.penWidth() ) ); + pen.setColor( _brd.color ); + + switch ( _brd.getStyle() ) { + case KoBorder::SOLID: + pen.setStyle( SolidLine ); + break; + case KoBorder::DASH: + pen.setStyle( DashLine ); + break; + case KoBorder::DOT: + pen.setStyle( DotLine ); + break; + case KoBorder::DASH_DOT: + pen.setStyle( DashDotLine ); + break; + case KoBorder::DASH_DOT_DOT: + pen.setStyle( DashDotDotLine ); + break; + case KoBorder::DOUBLE_LINE: + pen.setStyle( SolidLine ); + break; + } + + return QPen( pen ); +} + +/******************************************************************/ +/* Class: KoStylePreview. Previewing text with style ;) */ +/******************************************************************/ +class MyFlow : public KoTextFlow { + public: + MyFlow(QWidget *parent, KoTextZoomHandler *zoom) { + m_parent = parent; + m_zoomHandler = zoom; + } + int availableHeight() const { + return m_zoomHandler->pixelToLayoutUnitY(m_parent->height()); + } + private: + QWidget *m_parent; + KoTextZoomHandler *m_zoomHandler; +}; + +KoStylePreview::KoStylePreview( const QString& title, const QString& text, QWidget* parent, const char* name ) + : QGroupBox( title, parent, name ) +{ + setMinimumHeight(80); + m_zoomHandler = new KoTextZoomHandler; + QFont font = KoGlobal::defaultFont(); + m_textdoc = new KoTextDocument( m_zoomHandler, new KoTextFormatCollection( font, QColor(), KGlobal::locale()->language(), false ) ); + + m_textdoc->setFlow( new MyFlow(this, m_zoomHandler) ); + //m_textdoc->setWidth( KoTextZoomHandler::ptToLayoutUnitPt( 1000 ) ); + KoTextParag * parag = m_textdoc->firstParag(); + parag->insert( 0, text ); +} + +KoStylePreview::~KoStylePreview() +{ + delete m_textdoc; + delete m_zoomHandler; +} + +void KoStylePreview::setCounter( const KoParagCounter & counter ) +{ + KoTextParag * parag = m_textdoc->firstParag(); + parag->setCounter( counter ); + repaint( true ); +} + +void KoStylePreview::setStyle( KoParagStyle * style ) +{ + KoTextParag * parag = m_textdoc->firstParag(); + parag->applyStyle( style ); + repaint(true); +} + +void KoStylePreview::drawContents( QPainter *painter ) +{ + painter->save(); + QRect r = contentsRect(); + //kdDebug(32500) << "KoStylePreview::drawContents contentsRect=" << DEBUGRECT(r) << endl; + + QRect whiteRect( r.x() + 10, r.y() + 10, + r.width() - 20, r.height() - 20 ); + QColorGroup cg = QApplication::palette().active(); + painter->fillRect( whiteRect, cg.brush( QColorGroup::Base ) ); + + KoTextParag * parag = m_textdoc->firstParag(); + int widthLU = m_zoomHandler->pixelToLayoutUnitX( whiteRect.width() - 2 ); // keep one pixel border horizontally + if ( m_textdoc->width() != widthLU ) + { + // For centering to work, and to even get word wrapping when the thing is too big :) + m_textdoc->setWidth( widthLU ); + parag->invalidate(0); + } + + parag->format(); + QRect textRect = parag->pixelRect( m_zoomHandler ); + + // Center vertically, but not horizontally, to keep the parag alignment working, + textRect.moveTopLeft( QPoint( whiteRect.x(), + whiteRect.y() + ( whiteRect.height() - textRect.height() ) / 2 ) ); + // Move it from the left border a little + textRect.rLeft() += 4; + textRect.rRight() += 4; + //kdDebug(32500) << "KoStylePreview::drawContents textRect=" << DEBUGRECT(textRect) + // << " textSize=" << textSize.width() << "," << textSize.height() << endl; + painter->setClipRect( textRect.intersect( whiteRect ) ); + painter->translate( textRect.x(), textRect.y() ); + + m_textdoc->drawWYSIWYG( painter, 0, 0, textRect.width(), textRect.height(), cg, m_zoomHandler ); + painter->restore(); +} + +KoIndentSpacingWidget::KoIndentSpacingWidget( KoUnit::Unit unit, double _frameWidth,QWidget * parent, const char * name ) + : KoParagLayoutWidget( KoParagDia::PD_SPACING, parent, name ), m_unit( unit ) +{ + QString unitName = KoUnit::unitName( m_unit ); + QGridLayout *mainGrid = new QGridLayout( this, 3, 2, KDialog::marginHint(), KDialog::spacingHint() ); + + // mainGrid gives equal space to each groupbox, apparently + // I tried setRowStretch but the result is awful (much space between them and not equal!) + // Any other way (in order to make the 2nd, the one with a single checkbox, a bit + // smaller than the other 3) ? (DF) + + + // --------------- indent --------------- + double frameWidth=_frameWidth; + QString length; + if(frameWidth==-1) { + frameWidth=9999; + } else { + length=i18n("Frame width: %1 %2") + .arg(KoUnit::toUserStringValue(frameWidth,m_unit)) + .arg(KoUnit::unitName(m_unit)); + frameWidth=KoUnit::toUserValue(frameWidth,m_unit); + } + + QGroupBox * indentFrame = new QGroupBox( i18n( "Indent" ), this ); + QGridLayout * indentGrid = new QGridLayout( indentFrame, 5, 2, KDialog::marginHint(), KDialog::spacingHint() ); + + QLabel * lLimit = new QLabel(length , indentFrame ); + if(frameWidth!=-1) + { + lLimit->setAlignment( AlignRight ); + indentGrid->addWidget( lLimit, 1,0 ); + } + + QLabel * lLeft = new QLabel( i18n("&Left:"), indentFrame ); + lLeft->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); + indentGrid->addWidget( lLeft, 1, 0 ); + + eLeft = new KoUnitDoubleSpinBox( indentFrame, 0, 9999, 1, 0.0, m_unit ); + lLeft->setBuddy( eLeft ); + indentGrid->addWidget( eLeft, 1, 1 ); + connect( eLeft, SIGNAL( valueChangedPt(double ) ), this, SLOT( leftChanged( double ) ) ); + + QLabel * lRight = new QLabel( i18n("&Right:"), indentFrame ); + lRight->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); + indentGrid->addWidget( lRight, 2, 0 ); + + eRight = new KoUnitDoubleSpinBox( indentFrame, 0, 9999, 1, 0.0, m_unit ); + lRight->setBuddy( eRight ); + indentGrid->addWidget( eRight, 2, 1 ); + connect( eRight, SIGNAL( valueChangedPt( double ) ), this, SLOT( rightChanged( double ) ) ); + + QLabel * lFirstLine = new QLabel( i18n("&First line:"), indentFrame ); + lFirstLine->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); + indentGrid->addWidget( lFirstLine, 3, 0 ); + + eFirstLine = new KoUnitDoubleSpinBox( indentFrame, -9999, 9999, 1, 0.0, m_unit ); + lFirstLine->setBuddy( eFirstLine ); + connect( eFirstLine, SIGNAL( valueChangedPt( double ) ), this, SLOT( firstChanged( double ) ) ); + indentGrid->addWidget( eFirstLine, 3, 1 ); + + // grid row spacing + indentGrid->addRowSpacing( 0, fontMetrics().height() / 2 ); // groupbox title + for ( int i = 1 ; i < indentGrid->numRows() ; ++i ) + indentGrid->setRowStretch( i, 1 ); + mainGrid->addWidget( indentFrame, 0, 0 ); + + // --------------- line spacing --------------- + QGroupBox * spacingFrame = new QGroupBox( i18n( "Line &Spacing" ), this, "spacingFrame" ); + QGridLayout * spacingGrid = new QGridLayout( spacingFrame, 2, 1, + KDialog::marginHint(), KDialog::spacingHint() ); + + cSpacing = new QComboBox( false, spacingFrame, "" ); + // Keep order in sync with lineSpacingType() and display() + cSpacing->insertItem( i18n( "Line spacing value", "Single" ) ); + cSpacing->insertItem( i18n( "Line spacing value", "1.5 Lines" ) ); + cSpacing->insertItem( i18n( "Line spacing value", "Double" ) ); + cSpacing->insertItem( i18n( "Proportional") ); // LS_MULTIPLE, called Proportional like in OO + cSpacing->insertItem( i18n( "Line Distance (%1)" ).arg(unitName) ); // LS_CUSTOM + cSpacing->insertItem( i18n( "At Least (%1)" ).arg(unitName) ); + cSpacing->insertItem( i18n( "Fixed (%1)").arg(unitName) ); // LS_FIXED + + connect( cSpacing, SIGNAL( activated( int ) ), this, SLOT( spacingActivated( int ) ) ); + spacingGrid->addWidget( cSpacing, 1, 0 ); + + sSpacingStack = new QWidgetStack( spacingFrame ); + + eSpacing = new KoUnitDoubleSpinBox( spacingFrame, 0, 9999, CM_TO_POINT(1), + 0.0, m_unit ); + eSpacing->setRange( 0, 9999, 1, false); + connect( eSpacing, SIGNAL( valueChanged( double ) ), this, SLOT( spacingChanged( double ) ) ); + eSpacingPercent = new KIntNumInput( 100, spacingFrame ); + eSpacingPercent->setRange( 0, 1000, 10, false ); + eSpacingPercent->setSuffix( " %" ); + connect( eSpacingPercent, SIGNAL( valueChanged( int ) ), this, SLOT( spacingChanged( int ) ) ); + + sSpacingStack->addWidget( eSpacing ); + sSpacingStack->addWidget( eSpacingPercent ); + spacingGrid->addWidget( sSpacingStack, 1, 1 ); + + // grid row spacing + spacingGrid->addRowSpacing( 0, fontMetrics().height() / 2 ); // groupbox title + for ( int i = 1 ; i < spacingGrid->numRows() ; ++i ) + spacingGrid->setRowStretch( i, 1 ); + mainGrid->addWidget( spacingFrame, 1, 0 ); + + eSpacing->setEnabled( true ); + + // --------------- paragraph spacing --------------- + QGroupBox * pSpaceFrame = new QGroupBox( i18n( "Para&graph Space" ), this, "pSpaceFrame" ); + QGridLayout * pSpaceGrid = new QGridLayout( pSpaceFrame, 3, 2, + KDialog::marginHint(), KDialog::spacingHint() ); + + QLabel * lBefore = new QLabel( i18n("Before:"), pSpaceFrame ); + lBefore->setAlignment( AlignRight ); + pSpaceGrid->addWidget( lBefore, 1, 0 ); + + eBefore = new KoUnitDoubleSpinBox( pSpaceFrame, 0, 9999, CM_TO_POINT(1), 0.0, m_unit ); + eBefore->setRange( 0 , 9999, 1, false); + connect( eBefore, SIGNAL( valueChanged( double ) ), this, SLOT( beforeChanged( double ) ) ); + pSpaceGrid->addWidget( eBefore, 1, 1 ); + + QLabel * lAfter = new QLabel( i18n("After:"), pSpaceFrame ); + lAfter->setAlignment( AlignRight ); + pSpaceGrid->addWidget( lAfter, 2, 0 ); + + eAfter = new KoUnitDoubleSpinBox( pSpaceFrame, 0, 9999, 1, 0.0, m_unit ); + eAfter->setRange( 0, 9999, 1, false); + connect( eAfter, SIGNAL( valueChanged( double ) ), this, SLOT( afterChanged( double ) ) ); + pSpaceGrid->addWidget( eAfter, 2, 1 ); + + // grid row spacing + pSpaceGrid->addRowSpacing( 0, fontMetrics().height() / 2 ); // groupbox title + for ( int i = 1 ; i < pSpaceGrid->numRows() ; ++i ) + pSpaceGrid->setRowStretch( i, 1 ); + mainGrid->addWidget( pSpaceFrame, 2, 0 ); + + // --------------- preview -------------------- + prev1 = new KPagePreview( this, "KPagePreview" ); + mainGrid->addMultiCellWidget( prev1, 0, mainGrid->numRows()-1, 1, 1 ); + + mainGrid->setColStretch( 1, 1 ); + //mainGrid->setRowStretch( 4, 1 ); +} + +double KoIndentSpacingWidget::leftIndent() const +{ + return QMAX(0, eLeft->value() ); +} + +double KoIndentSpacingWidget::rightIndent() const +{ + return QMAX(0,eRight->value() ); +} + +double KoIndentSpacingWidget::firstLineIndent() const +{ + return eFirstLine->value(); +} + +double KoIndentSpacingWidget::spaceBeforeParag() const +{ + return QMAX(0, eBefore->value() ); +} + +double KoIndentSpacingWidget::spaceAfterParag() const +{ + return QMAX(0, eAfter->value() ); +} + +KoParagLayout::SpacingType KoIndentSpacingWidget::lineSpacingType() const +{ + int index = cSpacing->currentItem(); + switch ( index ) { + case 0: + return KoParagLayout::LS_SINGLE; + case 1: + return KoParagLayout::LS_ONEANDHALF; + case 2: + return KoParagLayout::LS_DOUBLE; + case 3: + return KoParagLayout::LS_MULTIPLE; + case 4: + return KoParagLayout::LS_CUSTOM; + case 5: + return KoParagLayout::LS_AT_LEAST; + case 6: + return KoParagLayout::LS_FIXED; + default: + kdError(32500) << "Error in KoIndentSpacingWidget::lineSpacingType" << endl; + return KoParagLayout::LS_SINGLE; + } +} + +double KoIndentSpacingWidget::lineSpacing() const +{ + return (lineSpacingType() == KoParagLayout::LS_MULTIPLE) + ? QMAX( 1, eSpacingPercent->value() ) / 100.0 + : QMAX( 0, eSpacing->value() ); +} + + +void KoIndentSpacingWidget::display( const KoParagLayout & lay ) +{ + double _left = lay.margins[QStyleSheetItem::MarginLeft]; + eLeft->changeValue( _left ); + //prev1->setLeft( _left ); done by leftChanged() below + leftChanged( _left ); // sets min value for eFirstLine + + double _right = lay.margins[QStyleSheetItem::MarginRight]; + eRight->changeValue( _right ); + prev1->setRight( _right ); + + double _first = lay.margins[QStyleSheetItem::MarginFirstLine]; + eFirstLine->changeValue( _first ); + prev1->setFirst( _first ); + + double _before = lay.margins[QStyleSheetItem::MarginTop]; + eBefore->changeValue( _before ); + prev1->setBefore( _before ); + + double _after = lay.margins[QStyleSheetItem::MarginBottom]; + eAfter->changeValue( _after ); + prev1->setAfter( _after ); + + double _spacing = lay.lineSpacingValue(); + KoParagLayout::SpacingType _type = lay.lineSpacingType; + switch ( _type ) { + case KoParagLayout::LS_SINGLE: // single + cSpacing->setCurrentItem( 0 ); + break; + case KoParagLayout::LS_ONEANDHALF: + cSpacing->setCurrentItem( 1 ); + break; + case KoParagLayout::LS_DOUBLE: + cSpacing->setCurrentItem( 2 ); + break; + case KoParagLayout::LS_MULTIPLE: + cSpacing->setCurrentItem( 3 ); + break; + case KoParagLayout::LS_CUSTOM: + cSpacing->setCurrentItem( 4 ); + break; + case KoParagLayout::LS_AT_LEAST: + cSpacing->setCurrentItem( 5 ); + break; + case KoParagLayout::LS_FIXED: + cSpacing->setCurrentItem( 6 ); + break; + default: + cSpacing->setCurrentItem( 0 ); + break; + } + + updateLineSpacing( _type ); + eSpacing->setValue( (_type == KoParagLayout::LS_MULTIPLE) ? QMAX( 1, _spacing ) + : KoUnit::toUserValue( _spacing, m_unit ) ); + eSpacingPercent->setValue( ( _type == KoParagLayout::LS_MULTIPLE ) ? qRound( _spacing * 100 ) : 100 ); +} + +void KoIndentSpacingWidget::save( KoParagLayout & lay ) +{ + lay.setLineSpacingValue(lineSpacing()); + lay.lineSpacingType = lineSpacingType(); + lay.margins[QStyleSheetItem::MarginLeft] = leftIndent(); + lay.margins[QStyleSheetItem::MarginRight] = rightIndent(); + lay.margins[QStyleSheetItem::MarginFirstLine] = firstLineIndent(); + lay.margins[QStyleSheetItem::MarginTop] = spaceBeforeParag(); + lay.margins[QStyleSheetItem::MarginBottom] = spaceAfterParag(); +} + +QString KoIndentSpacingWidget::tabName() +{ + return i18n( "Indent && S&pacing" ); +} + +void KoIndentSpacingWidget::leftChanged( double val ) +{ + prev1->setLeft( val ); + // The minimum first-line margin is -leftMargin() (where leftMargin>=0) + eFirstLine->setMinValue( -QMAX( 0, val ) ); +} + +void KoIndentSpacingWidget::rightChanged( double val ) +{ + prev1->setRight( val ); +} + +void KoIndentSpacingWidget::firstChanged( double val ) +{ + prev1->setFirst( val ); +} + +void KoIndentSpacingWidget::updateLineSpacing( KoParagLayout::SpacingType _type ) +{ + bool needsValue = (_type != KoParagLayout::LS_SINGLE && + _type != KoParagLayout::LS_ONEANDHALF && + _type != KoParagLayout::LS_DOUBLE); + + if ( _type == KoParagLayout::LS_MULTIPLE ) + { + sSpacingStack->raiseWidget( eSpacingPercent ); + } + else + { + sSpacingStack->raiseWidget( eSpacing ); + } + eSpacing->setEnabled( needsValue ); + if ( needsValue ) + prev1->setSpacing( eSpacing->value() ); + else + { + prev1->setSpacing( _type == KoParagLayout::LS_ONEANDHALF ? 8 : + _type == KoParagLayout::LS_DOUBLE ? 16 :0 ); + } +} + +void KoIndentSpacingWidget::spacingActivated( int /*_index*/ ) +{ + updateLineSpacing( lineSpacingType() ); + if ( eSpacing->isEnabled() ) // i.e. needsValue = true + eSpacing->setFocus(); +} + +void KoIndentSpacingWidget::spacingChanged( double _val ) +{ + prev1->setSpacing( _val ); +} + +void KoIndentSpacingWidget::spacingChanged( int _val ) +{ + prev1->setSpacing( _val / 100.0 ); +} + +void KoIndentSpacingWidget::beforeChanged( double _val ) +{ + prev1->setBefore( KoUnit::fromUserValue( _val, m_unit ) ); +} + +void KoIndentSpacingWidget::afterChanged( double _val ) +{ + prev1->setAfter( KoUnit::fromUserValue( _val, m_unit ) ); +} + + +KoParagAlignWidget::KoParagAlignWidget( bool breakLine, QWidget * parent, const char * name ) + : KoParagLayoutWidget( KoParagDia::PD_ALIGN, parent, name ) +{ + QGridLayout *grid = new QGridLayout( this, 3, 2, KDialog::marginHint(), KDialog::spacingHint() ); + + QVGroupBox * AlignGroup = new QVGroupBox( i18n( "Alignment" ), this ); + + rLeft = new QRadioButton( i18n( "&Left" ), AlignGroup ); + connect( rLeft, SIGNAL( clicked() ), this, SLOT( alignLeft() ) ); + + rCenter = new QRadioButton( i18n( "C&enter" ), AlignGroup ); + connect( rCenter, SIGNAL( clicked() ), this, SLOT( alignCenter() ) ); + + rRight = new QRadioButton( i18n( "&Right" ), AlignGroup ); + connect( rRight, SIGNAL( clicked() ), this, SLOT( alignRight() ) ); + + rJustify = new QRadioButton( i18n( "&Justify" ), AlignGroup ); + connect( rJustify, SIGNAL( clicked() ), this, SLOT( alignJustify() ) ); + + clearAligns(); + rLeft->setChecked( true ); + + grid->addWidget(AlignGroup, 0, 0); + + // --------------- End of page /frame --------------- + QGroupBox * endFramePage = new QGroupBox( i18n( "Behavior at &End of Frame/Page" ), this ); + QGridLayout * endFramePageGrid = new QGridLayout( endFramePage, 4, 1, + KDialog::marginHint(), KDialog::spacingHint() ); + + cKeepLinesTogether = new QCheckBox( i18n("&Keep lines together"),endFramePage); + endFramePageGrid->addWidget( cKeepLinesTogether, 1, 0 ); + cHardBreakBefore = new QCheckBox( i18n("Insert break before paragraph"),endFramePage); + endFramePageGrid->addWidget( cHardBreakBefore, 2, 0 ); + cHardBreakAfter = new QCheckBox( i18n("Insert break after paragraph"),endFramePage); + endFramePageGrid->addWidget( cHardBreakAfter, 3, 0 ); + + endFramePageGrid->addRowSpacing( 0, fontMetrics().height() / 2 ); // groupbox title + for ( int i = 0 ; i < endFramePageGrid->numRows()-1 ; ++i ) + endFramePageGrid->setRowStretch( 0, 0 ); + endFramePageGrid->setRowStretch( endFramePageGrid->numRows()-1, 1 ); + grid->addWidget( endFramePage, 2, 0 ); + + endFramePage->setEnabled(breakLine); + + // --------------- preview -------------------- + prev2 = new KPagePreview2( this, "KPagePreview2" ); + grid->addMultiCellWidget( prev2, 0, 2, 1, 1 ); + + // --------------- main grid ------------------ + grid->setColStretch( 1, 1 ); + grid->setRowStretch( 1, 1 ); +} + +int KoParagAlignWidget::pageBreaking() const +{ + int pb = 0; + if ( cKeepLinesTogether->isChecked() ) + pb |= KoParagLayout::KeepLinesTogether; + if ( cHardBreakBefore->isChecked() ) + pb |= KoParagLayout::HardFrameBreakBefore; + if ( cHardBreakAfter->isChecked() ) + pb |= KoParagLayout::HardFrameBreakAfter; + return pb; +} + + +void KoParagAlignWidget::display( const KoParagLayout & lay ) +{ + int align = lay.alignment; + prev2->setAlign( align ); + + clearAligns(); + switch ( align ) { + case Qt::AlignAuto: // see KoView::setAlign + case Qt::AlignLeft: + rLeft->setChecked( true ); + break; + case Qt::AlignHCenter: + rCenter->setChecked( true ); + break; + case Qt::AlignRight: + rRight->setChecked( true ); + break; + case Qt::AlignJustify: + rJustify->setChecked( true ); + } + + cKeepLinesTogether->setChecked( lay.pageBreaking & KoParagLayout::KeepLinesTogether ); + cHardBreakBefore->setChecked( lay.pageBreaking & KoParagLayout::HardFrameBreakBefore ); + cHardBreakAfter->setChecked( lay.pageBreaking & KoParagLayout::HardFrameBreakAfter ); + // ## preview support for end-of-frame ? +} + +void KoParagAlignWidget::save( KoParagLayout & lay ) +{ + lay.alignment = align(); + lay.pageBreaking = pageBreaking(); +} + +int KoParagAlignWidget::align() const +{ + if ( rLeft->isChecked() ) return Qt::AlignLeft; + else if ( rCenter->isChecked() ) return Qt::AlignHCenter; + else if ( rRight->isChecked() ) return Qt::AlignRight; + else if ( rJustify->isChecked() ) return Qt::AlignJustify; + + return Qt::AlignLeft; +} + +QString KoParagAlignWidget::tabName() +{ + return i18n( "General &Layout" ); +} + +void KoParagAlignWidget::alignLeft() +{ + prev2->setAlign( Qt::AlignLeft ); + clearAligns(); + rLeft->setChecked( true ); +} + +void KoParagAlignWidget::alignCenter() +{ + prev2->setAlign( Qt::AlignHCenter ); + clearAligns(); + rCenter->setChecked( true ); +} + +void KoParagAlignWidget::alignRight() +{ + prev2->setAlign( Qt::AlignRight ); + clearAligns(); + rRight->setChecked( true ); +} + +void KoParagAlignWidget::alignJustify() +{ + prev2->setAlign( Qt::AlignJustify ); + clearAligns(); + rJustify->setChecked( true ); +} + +void KoParagAlignWidget::clearAligns() +{ + rLeft->setChecked( false ); + rCenter->setChecked( false ); + rRight->setChecked( false ); + rJustify->setChecked( false ); +} + +//////////////////////////////////////////////////////////////////////////////// + +KoParagDecorationWidget::KoParagDecorationWidget( QWidget * parent, + const char * name ) + : KoParagLayoutWidget( KoParagDia::PD_DECORATION, parent, name ) +{ + QVBoxLayout *tabLayout = new QVBoxLayout( this ); + wDeco = new KoParagDecorationTab( this ); + tabLayout->add( wDeco ); + + // Set up Border Style combo box + wDeco->cbBorderStyle->insertItem( KoBorder::getStyle( KoBorder::SOLID ) ); + wDeco->cbBorderStyle->insertItem( KoBorder::getStyle( KoBorder::DASH ) ); + wDeco->cbBorderStyle->insertItem( KoBorder::getStyle( KoBorder::DOT ) ); + wDeco->cbBorderStyle->insertItem( KoBorder::getStyle( KoBorder::DASH_DOT ) ); + wDeco->cbBorderStyle->insertItem( KoBorder::getStyle( KoBorder::DASH_DOT_DOT ) ); + wDeco->cbBorderStyle->insertItem( KoBorder::getStyle( KoBorder::DOUBLE_LINE ) ); + + // Set up Border Width combo box + for( unsigned int i = 1; i <= 10; i++ ) + wDeco->cbBorderWidth->insertItem(QString::number(i)); + + // Setup the border toggle buttons, and merge checkbox + connect( wDeco->bBorderLeft, SIGNAL( toggled( bool ) ), + this, SLOT( brdLeftToggled( bool ) ) ); + connect( wDeco->bBorderRight, SIGNAL( toggled( bool ) ), + this, SLOT( brdRightToggled( bool ) ) ); + connect( wDeco->bBorderTop, SIGNAL( toggled( bool ) ), + this, SLOT( brdTopToggled( bool ) ) ); + connect( wDeco->bBorderBottom, SIGNAL( toggled( bool ) ), + this, SLOT( brdBottomToggled( bool ) ) ); + connect( wDeco->cbJoinBorder, SIGNAL( toggled( bool ) ), + this, SLOT( brdJoinToggled( bool ) ) ); + + // Set up Border preview widget + wPreview = new KoBorderPreview( wDeco->borderPreview ); + QVBoxLayout *previewLayout = new QVBoxLayout( wDeco->borderPreview ); + previewLayout->addWidget( wPreview ); + connect( wPreview, SIGNAL( choosearea(QMouseEvent * ) ), + this, SLOT( slotPressEvent(QMouseEvent *) ) ); +} + +/////// +// Current GUI selections +KoBorder::BorderStyle KoParagDecorationWidget::curBorderStyle() const +{ + QString selection = wDeco->cbBorderStyle->currentText(); + return KoBorder::getStyle( selection ); +} + +unsigned int KoParagDecorationWidget::curBorderWidth() const { + return wDeco->cbBorderWidth->currentText().toUInt(); +} + +QColor KoParagDecorationWidget::curBorderColor() const { + return wDeco->bBorderColor->color(); +} +/////// + +// Check whether a border is the same as that selected in the GUI +bool KoParagDecorationWidget::borderChanged( const KoBorder& border ) { + return (unsigned int)border.penWidth() != curBorderWidth() || + border.color != curBorderColor() || + border.getStyle() != curBorderStyle(); +} + +// Set a given border according to the values selected in the GUI +void KoParagDecorationWidget::updateBorder( KoBorder& border ) +{ + border.setPenWidth( curBorderWidth() ); + border.color = curBorderColor(); + border.setStyle( curBorderStyle () ); +} + +void KoParagDecorationWidget::clickedBorderPreview( KoBorder& border, + KoBorder::BorderType position, + KPushButton *corresponding ) +{ + if ( borderChanged( border ) && corresponding->isOn() ) { + updateBorder( border ); + wPreview->setBorder( position, border ); + } + else + corresponding->setOn( !corresponding->isOn() ); +} + +// Establish which border position was clicked in the border preview, +// and update the appropriate border +void KoParagDecorationWidget::slotPressEvent(QMouseEvent *_ev) +{ + const int OFFSETX = 15; + const int OFFSETY = 7; + const int Ko_SPACE = 30; + + QRect r = wPreview->contentsRect(); + QRect rect(r.x() + OFFSETX, r.y() + OFFSETY, + r.width() - OFFSETX, r.y() + OFFSETY + Ko_SPACE); + if(rect.contains(QPoint(_ev->x(),_ev->y()))) + { + clickedBorderPreview( m_topBorder, KoBorder::TopBorder, + wDeco->bBorderTop ); + } + + rect.setCoords(r.x() + OFFSETX, r.height() - OFFSETY - Ko_SPACE, + r.width() - OFFSETX, r.height() - OFFSETY); + if(rect.contains(QPoint(_ev->x(),_ev->y()))) + { + clickedBorderPreview( m_bottomBorder, KoBorder::BottomBorder, + wDeco->bBorderBottom ); + } + + rect.setCoords(r.x() + OFFSETX, r.y() + OFFSETY, + r.x() + Ko_SPACE + OFFSETX, r.height() - OFFSETY); + if(rect.contains(QPoint(_ev->x(),_ev->y()))) + { + clickedBorderPreview( m_leftBorder, KoBorder::LeftBorder, + wDeco->bBorderLeft ); + } + + rect.setCoords(r.width() - OFFSETX - Ko_SPACE, r.y() + OFFSETY, + r.width() - OFFSETX, r.height() - OFFSETY); + if(rect.contains(QPoint(_ev->x(),_ev->y()))) + { + clickedBorderPreview( m_rightBorder, KoBorder::RightBorder, + wDeco->bBorderRight ); + } +} + +void KoParagDecorationWidget::display( const KoParagLayout & lay ) +{ + wDeco->bBackgroundColor->setColor( lay.backgroundColor ); + + m_leftBorder = lay.leftBorder; + m_rightBorder = lay.rightBorder; + m_topBorder = lay.topBorder; + m_bottomBorder = lay.bottomBorder; + m_joinBorder = lay.joinBorder; + + wDeco->bBorderLeft->blockSignals( true ); + wDeco->bBorderRight->blockSignals( true ); + wDeco->bBorderTop->blockSignals( true ); + wDeco->bBorderBottom->blockSignals( true ); + updateBorders(); + wDeco->bBorderLeft->blockSignals( false ); + wDeco->bBorderRight->blockSignals( false ); + wDeco->bBorderTop->blockSignals( false ); + wDeco->bBorderBottom->blockSignals( false ); +} + +void KoParagDecorationWidget::updateBorders() +{ + wDeco->bBorderLeft->setOn( m_leftBorder.penWidth() > 0 ); + wDeco->bBorderRight->setOn( m_rightBorder.penWidth() > 0 ); + wDeco->bBorderTop->setOn( m_topBorder.penWidth() > 0 ); + wDeco->bBorderBottom->setOn( m_bottomBorder.penWidth() > 0 ); + wDeco->cbJoinBorder->setChecked( m_joinBorder ); + wPreview->setLeftBorder( m_leftBorder ); + wPreview->setRightBorder( m_rightBorder ); + wPreview->setTopBorder( m_topBorder ); + wPreview->setBottomBorder( m_bottomBorder ); +} + + +void KoParagDecorationWidget::save( KoParagLayout & lay ) +{ + lay.backgroundColor = wDeco->bBackgroundColor->color(); + lay.topBorder = m_topBorder; + lay.bottomBorder = m_bottomBorder; + lay.leftBorder = m_leftBorder; + lay.rightBorder = m_rightBorder; + lay.joinBorder = m_joinBorder; +} + +QColor KoParagDecorationWidget::backgroundColor() const { + return wDeco->bBackgroundColor->color(); +} + +QString KoParagDecorationWidget::tabName() { + // Why D&e..? Because &De.. conflicts with &Delete in + // the style manager. + return i18n( "D&ecorations" ); +} + +void KoParagDecorationWidget::brdLeftToggled( bool _on ) +{ + if ( !_on ) + m_leftBorder.setPenWidth(0); + else { + m_leftBorder.setPenWidth( curBorderWidth() ); + m_leftBorder.color = curBorderColor(); + m_leftBorder.setStyle( curBorderStyle() ); + } + wPreview->setLeftBorder( m_leftBorder ); +} + +void KoParagDecorationWidget::brdRightToggled( bool _on ) +{ + if ( !_on ) + m_rightBorder.setPenWidth(0); + else { + m_rightBorder.setPenWidth( curBorderWidth() ); + m_rightBorder.color = curBorderColor(); + m_rightBorder.setStyle( curBorderStyle() ); + } + wPreview->setRightBorder( m_rightBorder ); +} + +void KoParagDecorationWidget::brdTopToggled( bool _on ) +{ + if ( !_on ) + m_topBorder.setPenWidth(0); + else { + m_topBorder.setPenWidth( curBorderWidth() ); + m_topBorder.color = curBorderColor(); + m_topBorder.setStyle( curBorderStyle() ); + } + wPreview->setTopBorder( m_topBorder ); +} + +void KoParagDecorationWidget::brdBottomToggled( bool _on ) +{ + if ( !_on ) + m_bottomBorder.setPenWidth ( 0 ); + else { + m_bottomBorder.setPenWidth( curBorderWidth() ); + m_bottomBorder.color = curBorderColor(); + m_bottomBorder.setStyle( curBorderStyle() ); + } + wPreview->setBottomBorder( m_bottomBorder ); +} + +void KoParagDecorationWidget::brdJoinToggled( bool _on ) { + m_joinBorder = _on; +} +//////////////////////////////////////////////////////////////////////////////// + + +KoParagCounterWidget::KoParagCounterWidget( bool disableAll, QWidget * parent, const char * name ) + : KoParagLayoutWidget( KoParagDia::PD_NUMBERING, parent, name ) +{ + + QVBoxLayout *Form1Layout = new QVBoxLayout( this ); + Form1Layout->setSpacing( KDialog::spacingHint() ); + Form1Layout->setMargin( KDialog::marginHint() ); + + gNumbering = new QButtonGroup( this, "numberingGroup" ); + gNumbering->setTitle( i18n( "Numbering" ) ); + gNumbering->setColumnLayout(0, Qt::Vertical ); + gNumbering->layout()->setSpacing( 0 ); + gNumbering->layout()->setMargin( 0 ); + QHBoxLayout *numberingGroupLayout = new QHBoxLayout( gNumbering->layout() ); + numberingGroupLayout->setAlignment( Qt::AlignTop ); + numberingGroupLayout->setSpacing( KDialog::spacingHint() ); + numberingGroupLayout->setMargin( KDialog::marginHint() ); + + // What type of numbering is required? + QRadioButton *rNone = new QRadioButton( gNumbering, "rNone" ); + rNone->setText( i18n( "&None" ) ); + numberingGroupLayout->addWidget( rNone ); + + gNumbering->insert( rNone , KoParagCounter::NUM_NONE); + + QRadioButton *rList = new QRadioButton( gNumbering, "rList" ); + rList->setText( i18n( "&List" ) ); + gNumbering->insert( rList , KoParagCounter::NUM_LIST); + numberingGroupLayout->addWidget( rList ); + + QRadioButton *rChapter = new QRadioButton( gNumbering, "rChapter" ); + rChapter->setText( i18n( "Chapt&er" ) ); + gNumbering->insert( rChapter , KoParagCounter::NUM_CHAPTER); + numberingGroupLayout->addWidget( rChapter ); + Form1Layout->addWidget( gNumbering ); + connect( gNumbering, SIGNAL( clicked( int ) ), this, SLOT( numTypeChanged( int ) ) ); + + m_styleWidget = new KoCounterStyleWidget( true, false, disableAll, this ); + + connect( m_styleWidget, SIGNAL( sig_suffixChanged (const QString &) ), this, SLOT( suffixChanged(const QString &) ) ); + connect( m_styleWidget, SIGNAL( sig_prefixChanged (const QString &) ), this, SLOT( prefixChanged(const QString &) ) ); + connect( m_styleWidget, SIGNAL( sig_startChanged(int) ), this, SLOT( startChanged(int) ) ); + connect( m_styleWidget, SIGNAL( sig_restartChanged(bool) ), this, SLOT( restartChanged(bool) ) ); + connect( m_styleWidget, SIGNAL( sig_depthChanged (int) ), this, SLOT( depthChanged(int) ) ); + connect( m_styleWidget, SIGNAL( sig_displayLevelsChanged (int) ), this, SLOT( displayLevelsChanged(int) ) ); + connect( m_styleWidget, SIGNAL( sig_alignmentChanged (int) ), this, SLOT( alignmentChanged(int) ) ); + connect( m_styleWidget, SIGNAL( changeCustomBullet( const QString & , QChar ) ), this, SLOT( slotChangeCustomBullet( const QString & , QChar ) ) ); + + connect( m_styleWidget, SIGNAL( sig_numTypeChanged( int ) ), this, SLOT( numTypeChanged(int ) ) ); + connect( m_styleWidget, SIGNAL( changeStyle( KoParagCounter::Style ) ), this, SLOT( styleChanged (KoParagCounter::Style ) ) ); + + Form1Layout->addWidget( m_styleWidget ); + + + preview = new KoStylePreview( i18n( "Preview" ), i18n("Normal paragraph text"), this, "counter preview" ); + Form1Layout->addWidget( preview ); + if ( disableAll) + { + gNumbering->setEnabled( false); + preview->setEnabled( false ); + } + + QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); + Form1Layout->addItem( spacer ); +} + +void KoParagCounterWidget::styleChanged( KoParagCounter::Style st ) +{ + m_counter.setStyle( st ); + updatePreview(); +} + +void KoParagCounterWidget::slotChangeCustomBullet( const QString & f, QChar c) +{ + m_counter.setCustomBulletFont( f ); + m_counter.setCustomBulletCharacter( c ); + preview->setCounter( m_counter ); +} + +QString KoParagCounterWidget::tabName() { + return i18n( "B&ullets/Numbers" ); +} + +void KoParagCounterWidget::numTypeChanged( int nType ) { + // radio buttons pressed to change numbering type + m_counter.setNumbering( static_cast<KoParagCounter::Numbering>( nType ) ); + preview->setEnabled( m_counter.numbering() != KoParagCounter::NUM_NONE ); + m_styleWidget->numTypeChanged( nType ); + + updatePreview(); +} + +void KoParagCounterWidget::display( const KoParagLayout & lay ) { + KoParagCounter::Style style = KoParagCounter::STYLE_NONE; + if ( lay.counter ) + { + style=lay.counter->style(); + m_counter = *lay.counter; + } + else + { + m_counter = KoParagCounter(); + } + gNumbering->setButton( m_counter.numbering() ); + preview->setStyle( lay.style ); + preview->setCounter( m_counter ); + m_styleWidget->display( lay ); +} + +void KoParagCounterWidget::updatePreview() { + preview->setCounter(m_counter); + preview->repaint(true); +} + +void KoParagCounterWidget::save( KoParagLayout & lay ) { +/* m_counter.setDepth(spnDepth->value()); + m_counter.setStartNumber(spnStart->value()); + m_counter.setPrefix(sPrefix->text()); + m_counter.setSuffix(sSuffix->text()); */ + + if ( lay.counter ) + *lay.counter = m_counter; + else + lay.counter = new KoParagCounter( m_counter ); +} + +KoTabulatorsLineEdit::KoTabulatorsLineEdit( QWidget *parent, double lower, double upper, double step, double value /*= 0.0*/, KoUnit::Unit unit /*= KoUnit::U_PT*/, unsigned int precision /*= 2*/, const char *name /*= 0*/ ) + : KoUnitDoubleSpinBox ( parent, lower, upper, step, value, unit, precision, name ) +{ + setRange( 0, 9999, 1, false); +} + +void KoTabulatorsLineEdit::keyPressEvent ( QKeyEvent *ke ) +{ + if( ke->key() == QKeyEvent::Key_Return || + ke->key() == QKeyEvent::Key_Enter ) + { + emit keyReturnPressed(); + return; + } + KoUnitDoubleSpinBox::keyPressEvent (ke); +} + +KoParagTabulatorsWidget::KoParagTabulatorsWidget( KoUnit::Unit unit, double frameWidth,QWidget * parent, const char * name ) + : KoParagLayoutWidget( KoParagDia::PD_TABS, parent, name ), m_unit(unit) { + QString length; + if(frameWidth==-1) { + frameWidth=9999; + m_toplimit=9999; + } else { + m_toplimit=frameWidth; + length=i18n("Frame width: %1 %2") + .arg(KoUnit::toUserStringValue(frameWidth,m_unit)) + .arg(KoUnit::unitName(m_unit)); + frameWidth=KoUnit::toUserValue(frameWidth,m_unit); + } + QVBoxLayout* Form1Layout = new QVBoxLayout( this ); + Form1Layout->setSpacing( KDialog::spacingHint() ); + Form1Layout->setMargin( KDialog::marginHint() ); + + QHBoxLayout* Layout13 = new QHBoxLayout; + Layout13->setSpacing( KDialog::spacingHint() ); + Layout13->setMargin( 0 ); //? + + lstTabs = new QListBox( this); + lstTabs->insertItem( "mytabvalue" ); + lstTabs->setMaximumSize( QSize( 300, 32767 ) ); + Layout13->addWidget( lstTabs ); + + editLayout = new QVBoxLayout; + editLayout->setSpacing( KDialog::spacingHint() ); + editLayout->setMargin( 0 ); //? + + gPosition = new QGroupBox( this, "gPosition" ); + gPosition->setTitle( i18n( "Po&sition" ) ); + gPosition->setColumnLayout(0, Qt::Vertical ); + gPosition->layout()->setSpacing( 0 ); + gPosition->layout()->setMargin( 0 ); + QVBoxLayout* GroupBox2Layout = new QVBoxLayout( gPosition->layout() ); + GroupBox2Layout->setAlignment( Qt::AlignTop ); + GroupBox2Layout->setSpacing( KDialog::spacingHint() ); + GroupBox2Layout->setMargin( KDialog::marginHint() ); + + QHBoxLayout* Layout5 = new QHBoxLayout; + Layout5->setSpacing( KDialog::spacingHint() ); + Layout5->setMargin( 0 ); //? + + sTabPos = new KoTabulatorsLineEdit( gPosition, 0, 9999, 1, 0.0, m_unit ); + sTabPos->setRange( 0, 9999, 1 ); + sTabPos->setMaximumSize( QSize( 100, 32767 ) ); + Layout5->addWidget( sTabPos ); + QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + Layout5->addItem( spacer ); + GroupBox2Layout->addLayout( Layout5 ); + editLayout->addWidget( gPosition ); + + QLabel* TextLabel1 = new QLabel( gPosition ); + QString unitDescription = KoUnit::unitDescription( m_unit ); + TextLabel1->setText( length ); + GroupBox2Layout->addWidget( TextLabel1 ); + + bgAlign = new QButtonGroup( this ); + bgAlign->setTitle( i18n( "Alignment" ) ); + bgAlign->setColumnLayout(0, Qt::Vertical ); + bgAlign->layout()->setSpacing( 0 ); + bgAlign->layout()->setMargin( 0 ); + QVBoxLayout* ButtonGroup1Layout = new QVBoxLayout( bgAlign->layout() ); + ButtonGroup1Layout->setAlignment( Qt::AlignTop ); + ButtonGroup1Layout->setSpacing( KDialog::spacingHint() ); + ButtonGroup1Layout->setMargin( KDialog::marginHint() ); + + rAlignLeft = new QRadioButton( bgAlign ); + rAlignLeft->setText( i18n( "&Left" ) ); + ButtonGroup1Layout->addWidget( rAlignLeft ); + + rAlignCentre = new QRadioButton( bgAlign ); + rAlignCentre->setText( i18n( "C&enter" ) ); + ButtonGroup1Layout->addWidget( rAlignCentre ); + + rAlignRight = new QRadioButton( bgAlign ); + rAlignRight->setText( i18n( "&Right" ) ); + ButtonGroup1Layout->addWidget( rAlignRight ); + + QHBoxLayout* Layout8 = new QHBoxLayout; + Layout8->setSpacing( KDialog::spacingHint() ); + Layout8->setMargin( 0 ); + + rAlignVar = new QRadioButton( bgAlign ); + rAlignVar->setText( i18n( "On followin&g character: " ) ); + Layout8->addWidget( rAlignVar ); + + sAlignChar = new QLineEdit( bgAlign); + sAlignChar->setMaximumSize( QSize( 60, 32767 ) ); + sAlignChar->setText(QString(KGlobal::locale()->decimalSymbol()[0])); + Layout8->addWidget( sAlignChar ); + QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + Layout8->addItem( spacer_2 ); + ButtonGroup1Layout->addLayout( Layout8 ); + editLayout->addWidget( bgAlign ); + + gTabLeader = new QGroupBox( this, "gTabLeader" ); + gTabLeader->setTitle( i18n( "Tab Leader" ) ); + QVBoxLayout* GroupBox5Layout = new QVBoxLayout( gTabLeader ); + GroupBox5Layout->setAlignment( Qt::AlignTop ); + GroupBox5Layout->setSpacing( KDialog::spacingHint() ); + GroupBox5Layout->setMargin( KDialog::marginHint() ); + GroupBox5Layout->addSpacing( fontMetrics().height() / 2 ); // groupbox title + + QLabel* TextLabel1_2 = new QLabel( gTabLeader ); + TextLabel1_2->setText( i18n( "The space a tab uses can be filled with a pattern." ) ); + GroupBox5Layout->addWidget( TextLabel1_2 ); + + QGridLayout *fillingGrid = new QGridLayout( 0L, 2, 2, 0, KDialog::spacingHint() ); + + QLabel* TextLabel2 = new QLabel( gTabLeader); + TextLabel2->setText( i18n( "&Filling:" ) ); + TextLabel2->setAlignment( AlignRight ); + fillingGrid->addWidget( TextLabel2, 0, 0 ); + + cFilling = new QComboBox( FALSE, gTabLeader); + cFilling->insertItem( i18n( "Blank" ) ); + cFilling->insertItem( "_ _ _ _ _ _"); // DOT + cFilling->insertItem( "_________"); // SOLID + cFilling->insertItem( "___ ___ __"); // DASH + cFilling->insertItem( "___ _ ___ _"); // DASH_DOT + cFilling->insertItem( "___ _ _ ___"); // DASH_DOT_DOT + TextLabel2->setBuddy( cFilling ); + fillingGrid->addWidget( cFilling, 0, 1 ); + + QLabel * TextLabel3 = new QLabel( i18n("&Width:"), gTabLeader ); + TextLabel3->setAlignment( AlignRight ); + fillingGrid->addWidget( TextLabel3, 1, 0 ); + + eWidth = new KoUnitDoubleSpinBox( gTabLeader ); + eWidth->setMinValue(0.01); + eWidth->setUnit( m_unit ); + TextLabel3->setBuddy( eWidth ); + fillingGrid->addWidget( eWidth, 1, 1 ); + + GroupBox5Layout->addLayout( fillingGrid ); + editLayout->addWidget( gTabLeader ); + QSpacerItem* spacer_4 = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding ); + editLayout->addItem( spacer_4 ); + Layout13->addLayout( editLayout ); + Form1Layout->addLayout( Layout13 ); + + QHBoxLayout* Layout4 = new QHBoxLayout; + Layout4->setSpacing( KDialog::spacingHint() ); + Layout4->setMargin( 0 ); + + bNew = new QPushButton( this); + bNew->setText( i18n( "&New" ) ); + Layout4->addWidget( bNew ); + + bDelete = new QPushButton( this); + bDelete->setText( i18n( "&Delete" ) ); + Layout4->addWidget( bDelete ); + + bDeleteAll = new QPushButton( this); + bDeleteAll->setText( i18n( "Delete All" ) ); + Layout4->addWidget( bDeleteAll ); + + QSpacerItem* spacer_5 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + Layout4->addItem( spacer_5 ); + Form1Layout->addLayout( Layout4 ); + + //signal valueChanged passes value which the user see (unlike the value() function) + //so fromUserValue has to be used in slotTabValueChanged + connect(sTabPos,SIGNAL(valueChanged(double)), this, SLOT(slotTabValueChanged(double ))); + connect(sTabPos,SIGNAL( keyReturnPressed()),this,SLOT(newClicked())); + connect(sAlignChar,SIGNAL(textChanged( const QString & )), this, SLOT(slotAlignCharChanged( const QString & ))); + connect(bNew,SIGNAL(clicked ()),this,SLOT(newClicked())); + connect(bDelete,SIGNAL(clicked ()),this,SLOT(deleteClicked())); + connect(bDeleteAll,SIGNAL(clicked ()),this,SLOT(deleteAllClicked())); + connect(bgAlign,SIGNAL(clicked (int)),this,SLOT(updateAlign(int))); + connect(cFilling,SIGNAL(activated (int)),this,SLOT(updateFilling(int))); + connect(eWidth,SIGNAL(valueChangedPt( double ) ),this,SLOT(updateWidth())); + connect(lstTabs,SIGNAL(highlighted (int)),this,SLOT(setActiveItem(int))); + noSignals=false; +} + +void KoParagTabulatorsWidget::slotTabValueChanged( double val ) { + if(noSignals) return; + noSignals=true; + //see comment where this slot is connected + m_tabList[lstTabs->currentItem()].ptPos = KoUnit::fromUserValue( val, m_unit ); + + lstTabs->changeItem(tabToString(m_tabList[lstTabs->currentItem()]), lstTabs->currentItem()); + + sortLists(); + noSignals=false; +} + +void KoParagTabulatorsWidget::slotAlignCharChanged( const QString &/*_text*/ ) { + // select align 3 and update data structures. + bgAlign->setButton(3); + m_tabList[lstTabs->currentItem()].alignChar=sAlignChar->text()[0]; + m_tabList[lstTabs->currentItem()].type=T_DEC_PNT; +} + +void KoParagTabulatorsWidget::newClicked() { + int selected=lstTabs->currentItem(); + KoTabulator newTab; + if(selected < 0) { + newTab.ptPos=0; + newTab.type=T_LEFT; + newTab.filling=TF_BLANK; + newTab.ptWidth=0.5; + m_tabList.append(newTab); + lstTabs->insertItem(tabToString(newTab)); + lstTabs->setCurrentItem(0); + } else { + double pos = m_tabList[selected].ptPos; + double add=1.0; + if(m_unit==KoUnit::U_INCH) // inches are 25 times as big as mm, take it easy with adding.. + add=0.1; + + pos=pos + KoUnit::fromUserValue( add, m_unit ); + if(pos<m_toplimit) + { + newTab.ptPos=pos + KoUnit::fromUserValue( add, m_unit ); + newTab.type=m_tabList[selected].type; + newTab.filling=m_tabList[selected].filling; + newTab.ptWidth=m_tabList[selected].ptWidth; + m_tabList.insert(m_tabList.at(selected), newTab); + lstTabs->insertItem( tabToString(newTab), selected); + lstTabs->setCurrentItem(lstTabs->findItem(tabToString(newTab))); + sortLists(); + } + } +} + +void KoParagTabulatorsWidget::deleteClicked() { + int selected = lstTabs->currentItem(); + if (selected < 0) return; + noSignals=true; + sTabPos->changeValue(0.0); + noSignals=false; + lstTabs->removeItem(selected); + m_tabList.remove(m_tabList[selected]); + if(lstTabs->count() >0) { + lstTabs->setCurrentItem(QMIN(static_cast<unsigned int>(selected), lstTabs->count()-1 )); + } else { + bDeleteAll->setEnabled(false); + bDelete->setEnabled(false); + gPosition->setEnabled(false); + bgAlign->setEnabled(false); + gTabLeader->setEnabled(false); + } +} + +void KoParagTabulatorsWidget::deleteAllClicked() +{ + noSignals=true; + sTabPos->changeValue(0.0); + noSignals=false; + lstTabs->clear(); + m_tabList.clear(); + bDeleteAll->setEnabled(false); + bDelete->setEnabled(false); + gPosition->setEnabled(false); + bgAlign->setEnabled(false); + gTabLeader->setEnabled(false); +} + +void KoParagTabulatorsWidget::setActiveItem(int selected) { + if(noSignals) return; + if(selected < 0) return; + noSignals=true; + KoTabulator *selectedTab = &m_tabList[selected]; + switch( selectedTab->type) { + case T_CENTER: + bgAlign->setButton(1); break; + case T_RIGHT: + bgAlign->setButton(2); break; + case T_DEC_PNT: + bgAlign->setButton(3); + sAlignChar->setText(QString(selectedTab->alignChar)); + break; + case T_LEFT: + default: + bgAlign->setButton(0); + } + switch( selectedTab->filling) { + case TF_DOTS: + cFilling->setCurrentItem(1); break; + case TF_LINE: + cFilling->setCurrentItem(2); break; + case TF_DASH: + cFilling->setCurrentItem(3); break; + case TF_DASH_DOT: + cFilling->setCurrentItem(4); break; + case TF_DASH_DOT_DOT: + cFilling->setCurrentItem(5); break; + case TF_BLANK: + default: + cFilling->setCurrentItem(0); + } + eWidth->changeValue( selectedTab->ptWidth ); + sTabPos->setValue( KoUnit::toUserValue(selectedTab->ptPos, m_unit)); + bDelete->setEnabled(true); + bDeleteAll->setEnabled(true); + gPosition->setEnabled(true); + bgAlign->setEnabled(true); + gTabLeader->setEnabled(true); + noSignals=false; +} + +void KoParagTabulatorsWidget::setCurrentTab( double tabPos ) { + KoTabulatorList::ConstIterator it = m_tabList.begin(); + for ( int i = 0; it != m_tabList.end(); ++it, ++i ) + if ( (*it).ptPos == tabPos ) { + lstTabs->setCurrentItem(i); + setActiveItem( i ); + return; + } + kdWarning() << "KoParagTabulatorsWidget::setCurrentTab: no tab found at pos=" << tabPos << endl; +} + +QString KoParagTabulatorsWidget::tabToString(const KoTabulator &tab) { + return KoUnit::toUserStringValue( tab.ptPos, m_unit); +} + +void KoParagTabulatorsWidget::updateAlign(int selected) { + KoTabulator *selectedTab = &m_tabList[lstTabs->currentItem()]; + + switch( selected) { + case 1: + selectedTab->type=T_CENTER; break; + case 2: + selectedTab->type=T_RIGHT; break; + case 3: + selectedTab->type=T_DEC_PNT; + selectedTab->alignChar=sAlignChar->text()[0]; + break; + case 0: + default: + selectedTab->type=T_LEFT; + } +} + +void KoParagTabulatorsWidget::updateFilling(int selected) { + KoTabulator *selectedTab = &m_tabList[lstTabs->currentItem()]; + + switch( selected) { + case 1: + selectedTab->filling=TF_DOTS; break; + case 2: + selectedTab->filling=TF_LINE; break; + case 3: + selectedTab->filling=TF_DASH; break; + case 4: + selectedTab->filling=TF_DASH_DOT; break; + case 5: + selectedTab->filling=TF_DASH_DOT_DOT; break; + case 0: + default: + selectedTab->filling=TF_BLANK; + } +} + +void KoParagTabulatorsWidget::updateWidth() { + KoTabulator *selectedTab = &m_tabList[lstTabs->currentItem()]; + selectedTab->ptWidth = QMAX( 0, eWidth->value() ); +} + +void KoParagTabulatorsWidget::sortLists() { + + noSignals=true; + qHeapSort( m_tabList ); + + // we could just sort the listView, but to make sure we never have any problems with + // inconsistent lists, just re-add.. + QString curValue=lstTabs->currentText(); + lstTabs->clear(); + KoTabulatorList::ConstIterator it = m_tabList.begin(); + for ( ; it != m_tabList.end(); ++it ) + lstTabs->insertItem( KoUnit::toUserStringValue( (*it).ptPos, m_unit ) ); + + lstTabs->setCurrentItem(lstTabs->findItem(curValue)); + noSignals=false; +} + +void KoParagTabulatorsWidget::display( const KoParagLayout &lay ) { + m_tabList.clear(); + lstTabs->clear(); + m_tabList = lay.tabList(); + KoTabulatorList::ConstIterator it = m_tabList.begin(); + for ( ; it != m_tabList.end(); ++it ) + lstTabs->insertItem( KoUnit::toUserStringValue( (*it).ptPos, m_unit ) ); + + if(lstTabs->count() > 0) + lstTabs->setCurrentItem(0); + else { + bDelete->setEnabled(false); + bDeleteAll->setEnabled(false); + gPosition->setEnabled(false); + bgAlign->setEnabled(false); + gTabLeader->setEnabled(false); + } +} + +void KoParagTabulatorsWidget::save( KoParagLayout & lay ) { + lay.setTabList( m_tabList ); +} + +QString KoParagTabulatorsWidget::tabName() { + return i18n( "&Tabulators" ); +} + +/******************************************************************/ +/* Class: KoParagDia */ +/******************************************************************/ +KoParagDia::KoParagDia( QWidget* parent, const char* name, + int flags, KoUnit::Unit unit, double _frameWidth, bool breakLine, bool disableAll ) + : KDialogBase(Tabbed, QString::null, Ok | Cancel | User1 | Apply, Ok, parent, name, true ) +{ + m_decorationsWidget = 0; + m_flags = flags; + setButtonText( KDialogBase::User1, i18n("Reset") ); + + if ( m_flags & PD_SPACING ) + { + QVBox * page = addVBoxPage( i18n( "Indent && S&pacing" ) ); + m_indentSpacingWidget = new KoIndentSpacingWidget( unit,_frameWidth,page, "indent-spacing" ); + m_indentSpacingWidget->layout()->setMargin(0); + } + if ( m_flags & PD_ALIGN ) + { + QVBox * page = addVBoxPage( i18n( "General &Layout" ) ); + m_alignWidget = new KoParagAlignWidget( breakLine, page, "align" ); + m_alignWidget->layout()->setMargin(0); + } + if ( m_flags & PD_DECORATION ) + { + QVBox * page = addVBoxPage( i18n( "D&ecorations" ) ); + m_decorationsWidget = new KoParagDecorationWidget( page, "decorations"); + m_decorationsWidget->layout()->setMargin(0); + } + if ( m_flags & PD_NUMBERING ) + { + QVBox * page = addVBoxPage( i18n( "B&ullets/Numbers" ) ); + m_counterWidget = new KoParagCounterWidget( disableAll , page, "numbers" ); + m_counterWidget->layout()->setMargin(0); + } + if ( m_flags & PD_TABS ) + { + QVBox * page = addVBoxPage( i18n( "&Tabulators" ) ); + m_tabulatorsWidget = new KoParagTabulatorsWidget( unit,_frameWidth, page, "tabs"); + m_tabulatorsWidget->layout()->setMargin(0); + } + + connect( this, SIGNAL( user1Clicked() ), this, SLOT(slotReset())); + setInitialSize( QSize(630, 500) ); +} + +KoParagDia::~KoParagDia() +{ +} + +void KoParagDia::slotApply() +{ + emit applyParagStyle(); +} + +void KoParagDia::slotOk() +{ + slotApply(); + KDialogBase::slotOk(); +} + +void KoParagDia::setCurrentPage( int page ) +{ + switch( page ) + { + case PD_SPACING: + showPage( pageIndex( m_indentSpacingWidget->parentWidget() ) ); + break; + case PD_ALIGN: + showPage( pageIndex( m_alignWidget->parentWidget() ) ); + break; + case PD_DECORATION: + showPage( pageIndex( m_decorationsWidget->parentWidget() ) ); + break; + case PD_NUMBERING: + showPage( pageIndex( m_counterWidget->parentWidget() ) ); + break; + case PD_TABS: + showPage( pageIndex( m_tabulatorsWidget->parentWidget() ) ); + break; + default: + break; + } +} + +void KoParagDia::setParagLayout( const KoParagLayout & lay ) +{ + m_indentSpacingWidget->display( lay ); + m_alignWidget->display( lay ); + m_decorationsWidget->display( lay ); + m_counterWidget->display( lay ); + m_tabulatorsWidget->display( lay ); + oldLayout = lay; +} + +void KoParagDia::slotReset() +{ + if( m_indentSpacingWidget ) + m_indentSpacingWidget->display( oldLayout ); + if( m_alignWidget ) + m_alignWidget->display( oldLayout ); + if ( m_decorationsWidget ) + m_decorationsWidget->display( oldLayout ); + if( m_counterWidget ) + m_counterWidget->display( oldLayout ); + if( m_tabulatorsWidget ) + m_tabulatorsWidget->display( oldLayout ); +} + +bool KoParagDia::isCounterChanged() const +{ + if ( oldLayout.counter ) // We had a counter + return ! ( *oldLayout.counter == counter() ); + else // We had no counter -> changed if we have one now + return counter().numbering() != KoParagCounter::NUM_NONE; +} + +int KoParagDia::changedFlags() const +{ + return paragLayout().compare( oldLayout ); +} + +KoParagLayout KoParagDia::paragLayout() const +{ + KoParagLayout newLayout; + newLayout.setLineSpacingValue( lineSpacing() ); + newLayout.lineSpacingType = lineSpacingType(); + newLayout.setTabList( tabListTabulator() ); + newLayout.alignment = align(); + newLayout.margins[QStyleSheetItem::MarginFirstLine] = firstLineIndent(); + newLayout.margins[QStyleSheetItem::MarginLeft] = leftIndent(); + newLayout.margins[QStyleSheetItem::MarginRight] = rightIndent(); + newLayout.margins[QStyleSheetItem::MarginTop] = spaceBeforeParag(); + newLayout.margins[QStyleSheetItem::MarginBottom] = spaceAfterParag(); + newLayout.pageBreaking = pageBreaking(); + newLayout.leftBorder = leftBorder(); + newLayout.rightBorder = rightBorder(); + newLayout.topBorder = topBorder(); + newLayout.bottomBorder = bottomBorder(); + newLayout.joinBorder = joinBorder(); + newLayout.backgroundColor = backgroundColor(); + newLayout.counter = new KoParagCounter( counter() ); + return newLayout; +} + +#include "KoParagDia.moc" +#include "KoParagDia_p.moc" |