diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/kofficeui | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/kofficeui')
94 files changed, 18518 insertions, 0 deletions
diff --git a/lib/kofficeui/KoBrush.cpp b/lib/kofficeui/KoBrush.cpp new file mode 100644 index 00000000..62b3fa96 --- /dev/null +++ b/lib/kofficeui/KoBrush.cpp @@ -0,0 +1,64 @@ +// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* This file is part of the KDE project + Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@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 "KoBrush.h" + +#include <KoGenStyles.h> +#include <KoXmlNS.h> + +KoBrush::KoBrush() +: m_gColor1( Qt::red ) +, m_gColor2( Qt::green ) +, m_gType( BCT_GHORZ ) +, m_fillType( FT_BRUSH ) +, m_unbalanced( false ) +, m_xfactor( 100 ) +, m_yfactor( 100 ) +{ +} + + +KoBrush::KoBrush( const QBrush &brush, const QColor &gColor1, const QColor &gColor2, + BCType gType, FillType fillType, bool unbalanced, + int xfactor, int yfactor ) +: m_brush( brush ) +, m_gColor1( gColor1 ) +, m_gColor2( gColor2 ) +, m_gType( gType ) +, m_fillType( fillType ) +, m_unbalanced( unbalanced ) +, m_xfactor( xfactor ) +, m_yfactor( yfactor ) +{ +} + + +KoBrush & KoBrush::operator=( const KoBrush &brush ) +{ + m_brush = brush.m_brush; + m_gColor1 = brush.m_gColor1; + m_gColor2 = brush.m_gColor2; + m_gType = brush.m_gType; + m_fillType = brush.m_fillType; + m_unbalanced = brush.m_unbalanced; + m_xfactor = brush.m_xfactor; + m_yfactor = brush.m_yfactor; + return *this; +} diff --git a/lib/kofficeui/KoBrush.h b/lib/kofficeui/KoBrush.h new file mode 100644 index 00000000..142dbb92 --- /dev/null +++ b/lib/kofficeui/KoBrush.h @@ -0,0 +1,106 @@ +// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* This file is part of the KDE project + Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@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. +*/ + +#ifndef KOBRUSH_H +#define KOBRUSH_H + +#include <qbrush.h> + +class KoGenStyle; +class KoGenStyles; +class KoOasisContext; +class QDomElement; + + +enum BCType { + BCT_PLAIN = 0, + BCT_GHORZ = 1, + BCT_GVERT = 2, + BCT_GDIAGONAL1 = 3, + BCT_GDIAGONAL2 = 4, + BCT_GCIRCLE = 5, + BCT_GRECT = 6, + BCT_GPIPECROSS = 7, + BCT_GPYRAMID = 8 +}; + +enum FillType +{ + FT_BRUSH = 0, + FT_GRADIENT = 1 +}; + +class KoBrush +{ +public: + KoBrush(); + KoBrush( const QBrush &brush, const QColor &gColor1, const QColor &gColor2, + BCType gType, FillType fillType, bool unbalanced, + int xfactor, int yfactor ); + + KoBrush &operator=( const KoBrush &brush ); + + void setBrush( const QBrush &brush ) + { m_brush = brush; } + void setGColor1( const QColor &gColor1 ) + { m_gColor1 = gColor1; } + void setGColor2( const QColor &gColor2 ) + { m_gColor2 = gColor2; } + void setGType( BCType gType ) + { m_gType = gType; } + void setFillType( FillType fillType ) + { m_fillType = fillType; } + void setGUnbalanced( bool unbalanced ) + { m_unbalanced = unbalanced; } + void setGXFactor( int xfactor ) + { m_xfactor = xfactor; } + void setGYFactor( int yfactor ) + { m_yfactor = yfactor; } + + QBrush getBrush() const + { return m_brush; } + QColor getGColor1() const + { return m_gColor1; } + QColor getGColor2() const + { return m_gColor2; } + BCType getGType() const + { return m_gType; } + FillType getFillType() const + { return m_fillType; } + bool getGUnbalanced() const + { return m_unbalanced; } + int getGXFactor() const + { return m_xfactor; } + int getGYFactor() const + { return m_yfactor; } + +private: + QBrush m_brush; + QColor m_gColor1; + QColor m_gColor2; + BCType m_gType; + FillType m_fillType; + bool m_unbalanced; + int m_xfactor; + int m_yfactor; +}; + +#endif /* KOBRUSH_H */ + diff --git a/lib/kofficeui/KoCharSelectDia.cpp b/lib/kofficeui/KoCharSelectDia.cpp new file mode 100644 index 00000000..5a0105c6 --- /dev/null +++ b/lib/kofficeui/KoCharSelectDia.cpp @@ -0,0 +1,116 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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 "KoCharSelectDia.h" +#include "KoCharSelectDia.moc" + +#include <qlayout.h> + +#include <klocale.h> +#include <kcharselect.h> +#include <kdebug.h> +/******************************************************************/ +/* class KoCharSelectDia */ +/******************************************************************/ + +KoCharSelectDia::KoCharSelectDia( QWidget *parent, const char *name, const QChar &_chr, const QString &_font, bool _enableFont , bool _modal) + : KDialogBase( Plain, i18n("Select Character"), Ok | Cancel, Ok , parent, name, _modal ) +{ + initDialog(_chr,_font,_enableFont); + + KGuiItem okItem = KStdGuiItem::ok(); // start from std item to keep the OK icon... + okItem.setText( i18n("&Insert") ); + okItem.setWhatsThis( i18n("Insert the selected character in the text") ); + setButtonOK( okItem ); +} + +KoCharSelectDia::KoCharSelectDia( QWidget *parent, const char *name, const QString &_font, const QChar &_chr, bool _modal ) + : KDialogBase( Plain, i18n("Select Character"), User1 | Close, User1 , parent, name, _modal ) +{ + initDialog(_chr,_font,true); + + setButtonText( User1, i18n("&Insert") ); + setButtonTip( User1, i18n("Insert the selected character in the text") ); + +} + +void KoCharSelectDia::initDialog(const QChar &_chr, const QString &_font, bool /*_enableFont*/) +{ + QWidget *page = plainPage(); + + grid = new QGridLayout( page, 1, 1, 0, KDialog::spacingHint() ); + + charSelect = new KCharSelect( page, "", _font, _chr ); + connect(charSelect, SIGNAL(doubleClicked()),this, SLOT(slotDoubleClicked())); + charSelect->resize( charSelect->sizeHint() ); + charSelect->enableFontCombo( true ); + grid->addWidget( charSelect, 0, 0 ); + + grid->addColSpacing( 0, charSelect->width() ); + grid->addRowSpacing( 0, charSelect->height() ); + grid->setRowStretch( 0, 0 ); + charSelect->setFocus(); +} + +KoCharSelectDia::~KoCharSelectDia() +{ +} + +void KoCharSelectDia::closeDialog() +{ + KDialogBase::close(); +} + +bool KoCharSelectDia::selectChar( QString &_font, QChar &_chr, bool _enableFont, QWidget* parent, const char* name ) +{ + bool res = false; + + KoCharSelectDia *dlg = new KoCharSelectDia( parent, name, _chr, _font, _enableFont ); + dlg->setFocus(); + if ( dlg->exec() == Accepted ) + { + _font = dlg->font(); + _chr = dlg->chr(); + res = true; + } + + delete dlg; + + return res; +} + +QChar KoCharSelectDia::chr() const +{ + return charSelect->chr(); +} + +QString KoCharSelectDia::font() const +{ + return charSelect->font(); +} + +void KoCharSelectDia::slotUser1() +{ + emit insertChar(chr(),font()); +} + +void KoCharSelectDia::slotDoubleClicked() +{ + emit insertChar(chr(),font()); +} diff --git a/lib/kofficeui/KoCharSelectDia.h b/lib/kofficeui/KoCharSelectDia.h new file mode 100644 index 00000000..dba5e76e --- /dev/null +++ b/lib/kofficeui/KoCharSelectDia.h @@ -0,0 +1,76 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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. +*/ + +#ifndef KOCHARSELECTDIA_H +#define KOCHARSELECTDIA_H + +#include <kdialogbase.h> +#include <koffice_export.h> + +class QWidget; +class QGridLayout; +class QPushButton; +class KCharSelect; +class KButtonBox; + +/******************************************************************/ +/* class KoCharSelectDia */ +/******************************************************************/ + +class KOFFICEUI_EXPORT KoCharSelectDia : public KDialogBase +{ + Q_OBJECT + +public: + + // constructor - destructor + KoCharSelectDia( QWidget *parent, const char *name, const QChar &_chr, + const QString &_font, bool _enableFont, bool _modal=true ); + + //constructor when you want to insert multi char + KoCharSelectDia( QWidget *parent, const char *name, const QString &_font, + const QChar &_chr, bool _modal=true ); + ~KoCharSelectDia(); + // select char dialog + KOFFICEUI_EXPORT static bool selectChar( QString &_font, QChar &_chr, bool _enableFont = true, QWidget* parent = 0, const char* name = 0); + + // internal + QChar chr() const; + QString font() const; + void closeDialog(); + +private: + void initDialog(const QChar &_chr, const QString &_font, bool _enableFont); + +private slots: + void slotUser1(); + void slotDoubleClicked(); + +protected: + // dialog objects + QGridLayout *grid; + KButtonBox *bbox; + QPushButton *bOk, *bCancel; + KCharSelect *charSelect; + + signals: + void insertChar(QChar,const QString &); +}; + +#endif diff --git a/lib/kofficeui/KoCommandHistory.cpp b/lib/kofficeui/KoCommandHistory.cpp new file mode 100644 index 00000000..79f0a14f --- /dev/null +++ b/lib/kofficeui/KoCommandHistory.cpp @@ -0,0 +1,446 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Werner Trobin <trobin@kde.org> + Copyright (C) 2000 David Faure <faure@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 <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> + +#include <kaction.h> +#include <kcommand.h> +#include <kdebug.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kshortcutlist.h> +#include <kstdaccel.h> +#include <kstdaction.h> + +#include "KoCommandHistory.h" + +KoListBox::KoListBox( QWidget *parent , const char *name , WFlags f) + : QListBox( parent, name, f) +{ + setVScrollBarMode( AlwaysOn ); +} + +void KoListBox::contentsMouseMoveEvent ( QMouseEvent * e) +{ + QListBoxItem *item_p = itemAt( contentsToViewport(e->pos())); + if ( item_p ) + { + int itemIndex = index( item_p ); + for ( int i = 0; i<=itemIndex;i++) + setSelected ( i, true ); + for ( int i = itemIndex+1; i<(int)count();i++) + setSelected ( i, false ); + emit changeNumberOfSelectedItem( itemIndex); + } +} + +QSize KoListBox::sizeHint() const +{ + return QSize(QMIN(maxItemWidth() + verticalScrollBar()->width() + 4, 400), + QMIN(count() * itemHeight() + horizontalScrollBar()->height() + 4,300)); +} + +class KoCommandHistory::KoCommandHistoryPrivate { +public: + KoCommandHistoryPrivate() { + m_savedAt=-1; + m_present=0; + } + ~KoCommandHistoryPrivate() {} + int m_savedAt; + KCommand *m_present; + KoListBox *m_undoListBox; + KoListBox *m_redoListBox; + QLabel *m_undoLabel; + QLabel *m_redoLabel; +}; + +//////////// + +KoCommandHistory::KoCommandHistory() : + m_undo(0), m_redo(0), m_undoLimit(50), m_redoLimit(30), m_first(false) +{ + d=new KoCommandHistoryPrivate(); + m_commands.setAutoDelete(true); + clear(); +} + +KoCommandHistory::KoCommandHistory(KActionCollection * actionCollection, bool withMenus) : + m_undoLimit(50), m_redoLimit(30), m_first(false) +{ + d=new KoCommandHistoryPrivate(); + if (withMenus) + { + KToolBarPopupAction * undo = new KToolBarPopupAction( i18n("&Undo"), "undo", + KStdAccel::undo(), this, SLOT( undo() ), + actionCollection, /*KStdAction::stdName( KStdAction::Undo )*/"koffice_undo" ); + connect( undo->popupMenu(), SIGNAL( aboutToShow() ), this, SLOT( slotUndoAboutToShow() ) ); + connect( undo->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotUndoActivated( int ) ) ); + m_undo = undo; + m_undoPopup = undo->popupMenu(); + d->m_undoListBox = new KoListBox( m_undoPopup ); + d->m_undoListBox->setSelectionMode( QListBox::Multi ); + + m_undoPopup->insertItem(d->m_undoListBox); + d->m_undoLabel = new QLabel( m_undoPopup); + m_undoPopup->insertItem(d->m_undoLabel); + + connect( d->m_undoListBox, SIGNAL( selected( int ) ), this, SLOT( slotUndoActivated( int ) ) ); + connect( d->m_undoListBox, SIGNAL(clicked ( QListBoxItem *)), this, SLOT( slotUndoActivated( QListBoxItem * ) ) ); + + connect( d->m_undoListBox, SIGNAL( changeNumberOfSelectedItem( int )), this, SLOT( slotChangeUndoNumberOfSelectedItem( int ))); + + KToolBarPopupAction * redo = new KToolBarPopupAction( i18n("&Redo"), "redo", + KStdAccel::redo(), this, SLOT( redo() ), + actionCollection, /*KStdAction::stdName( KStdAction::Redo )*/ + "koffice_redo"); + connect( redo->popupMenu(), SIGNAL( aboutToShow() ), this, SLOT( slotRedoAboutToShow() ) ); + connect( redo->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotRedoActivated( int ) ) ); + m_redo = redo; + m_redoPopup = redo->popupMenu(); + d->m_redoListBox = new KoListBox( m_redoPopup ); + d->m_redoListBox->setSelectionMode( QListBox::Multi ); + m_redoPopup->insertItem(d->m_redoListBox); + + d->m_redoLabel = new QLabel( m_redoPopup); + m_redoPopup->insertItem(d->m_redoLabel); + + + connect( d->m_redoListBox, SIGNAL( selected( int ) ), this, SLOT( slotRedoActivated( int ) ) ); + connect( d->m_redoListBox, SIGNAL(clicked ( QListBoxItem *)), this, SLOT( slotRedoActivated( QListBoxItem * ) ) ); + connect( d->m_redoListBox, SIGNAL( changeNumberOfSelectedItem( int )), this, SLOT( slotChangeRedoNumberOfSelectedItem( int ))); + + } + else + { + m_undo = KStdAction::undo( this, SLOT( undo() ), actionCollection, "koffice_undo"); + m_redo = KStdAction::redo( this, SLOT( redo() ), actionCollection, "koffice_redo"); + m_undoPopup = 0L; + m_redoPopup = 0L; + d->m_redoListBox = 0L; + d->m_undoListBox = 0L; + d->m_redoLabel = 0L; + d->m_undoLabel = 0L; + } + m_commands.setAutoDelete(true); + clear(); +} + +KoCommandHistory::~KoCommandHistory() { + delete d; +} + +KCommand * KoCommandHistory::presentCommand ( ) +{ return d->m_present; +} + + +void KoCommandHistory::clear() { + if (m_undo != 0) { + m_undo->setEnabled(false); + m_undo->setText(i18n("&Undo")); + } + if (m_redo != 0) { + m_redo->setEnabled(false); + m_redo->setText(i18n("&Redo")); + } + d->m_present = 0L; + d->m_savedAt=-42; +} + +void KoCommandHistory::addCommand(KCommand *command, bool execute) { + + if(command==0L) + return; + + int index; + if(d->m_present!=0L && (index=m_commands.findRef(d->m_present))!=-1) { + if (m_first) + --index; + m_commands.insert(index+1, command); + // truncate history + unsigned int count=m_commands.count(); + for(unsigned int i=index+2; i<count; ++i) + m_commands.removeLast(); + // check whether we still can reach savedAt + if(index<d->m_savedAt) + d->m_savedAt=-1; + d->m_present=command; + m_first=false; + if (m_undo != 0) { + m_undo->setEnabled(true); + m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); + } + if((m_redo != 0) && m_redo->isEnabled()) { + m_redo->setEnabled(false); + m_redo->setText(i18n("&Redo")); + } + clipCommands(); + } + else { // either this is the first time we add a Command or something has gone wrong + kdDebug(230) << "KoCommandHistory: Initializing the Command History" << endl; + m_commands.clear(); + m_commands.append(command); + d->m_present=command; + if (m_undo != 0) { + m_undo->setEnabled(true); + m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); + } + if (m_redo != 0) { + m_redo->setEnabled(false); + m_redo->setText(i18n("&Redo")); + } + m_first=false; // Michael B: yes, that *is* correct :-) + } + if ( execute ) + { + command->execute(); + emit commandExecuted(); + emit commandExecuted(command); + } +} + +void KoCommandHistory::undo() { + + if (m_first || (d->m_present == 0L)) + return; + + d->m_present->unexecute(); + KCommand *commandUndone = d->m_present; + + if (m_redo != 0) { + m_redo->setEnabled(true); + m_redo->setText(i18n("&Redo: %1").arg(d->m_present->name())); + } + int index; + if((index=m_commands.findRef(d->m_present))!=-1 && m_commands.prev()!=0) { + d->m_present=m_commands.current(); + emit commandExecuted(); + emit commandExecuted(commandUndone); + if (m_undo != 0) { + m_undo->setEnabled(true); + m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); + } + --index; + if(index==d->m_savedAt) + emit documentRestored(); + } + else { + emit commandExecuted(); + emit commandExecuted(commandUndone); + if (m_undo != 0) { + m_undo->setEnabled(false); + m_undo->setText(i18n("&Undo")); + } + if(d->m_savedAt==-42) + emit documentRestored(); + m_first=true; + } + clipCommands(); // only needed here and in addCommand, NOT in redo +} + +void KoCommandHistory::redo() { + + int index; + if(m_first) { + d->m_present->execute(); + emit commandExecuted(); + emit commandExecuted(d->m_present); + m_first=false; + m_commands.first(); + if(d->m_savedAt==0) + emit documentRestored(); + } + else if((index=m_commands.findRef(d->m_present))!=-1 && m_commands.next()!=0) { + d->m_present=m_commands.current(); + d->m_present->execute(); + emit commandExecuted(); + emit commandExecuted(d->m_present); + ++index; + if(index==d->m_savedAt) + emit documentRestored(); + } + + if (m_undo != 0) { + m_undo->setEnabled(true); + m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); + } + + if(m_commands.next()!=0) { + if (m_redo != 0) { + m_redo->setEnabled(true); + m_redo->setText(i18n("&Redo: %1").arg(m_commands.current()->name())); + } + } + else { + if((m_redo != 0) && m_redo->isEnabled()) { + m_redo->setEnabled(false); + m_redo->setText(i18n("&Redo")); + } + } +} + +void KoCommandHistory::documentSaved() { + if(d->m_present!=0 && !m_first) + d->m_savedAt=m_commands.findRef(d->m_present); + else if(d->m_present==0 && !m_first) + d->m_savedAt=-42; // this value signals that the document has + // been saved with an empty history. + else if(m_first) + d->m_savedAt=-42; +} + +void KoCommandHistory::setUndoLimit(int limit) { + + if(limit>0 && limit!=m_undoLimit) { + m_undoLimit=limit; + clipCommands(); + } +} + +void KoCommandHistory::setRedoLimit(int limit) { + + if(limit>0 && limit!=m_redoLimit) { + m_redoLimit=limit; + clipCommands(); + } +} + +void KoCommandHistory::clipCommands() { + + int count=m_commands.count(); + if(count<=m_undoLimit && count<=m_redoLimit) + return; + + int index=m_commands.findRef(d->m_present); + if(index>=m_undoLimit) { + for(int i=0; i<=(index-m_undoLimit); ++i) { + m_commands.removeFirst(); + --d->m_savedAt; + if(d->m_savedAt==-1) + d->m_savedAt=-42; + } + index=m_commands.findRef(d->m_present); // calculate the new + count=m_commands.count(); // values (for the redo-branch :) + // make it easier for us... d->m_savedAt==-1 -> invalid + if(d->m_savedAt!=-42 && d->m_savedAt<-1) + d->m_savedAt=-1; + } + // adjust the index if it's the first command + if(m_first) + index=-1; + if((index+m_redoLimit+1)<count) { + if(d->m_savedAt>(index+m_redoLimit)) + d->m_savedAt=-1; + for(int i=0; i<(count-(index+m_redoLimit+1)); ++i) + m_commands.removeLast(); + } +} + +void KoCommandHistory::slotUndoAboutToShow() +{ + d->m_undoListBox->clear(); + slotChangeUndoNumberOfSelectedItem( -1 ); + int i = 0; + QStringList lst; + if (m_commands.findRef(d->m_present)!=-1) + while ( m_commands.current() && i<10 ) // TODO make number of items configurable ? + { + lst.append(i18n("Undo: %1").arg(m_commands.current()->name())); + m_commands.prev(); + } + d->m_undoListBox->insertStringList( lst ); +} + +void KoCommandHistory::slotUndoActivated( int pos ) +{ + kdDebug(230) << "KoCommandHistory::slotUndoActivated " << pos << endl; + for ( int i = 0 ; i < pos+1; ++i ) + undo(); + m_undoPopup->hide(); +} + +void KoCommandHistory::slotUndoActivated( QListBoxItem * item) +{ + if ( item ) + slotUndoActivated( item->listBox()->index(item)); +} + +void KoCommandHistory::slotRedoActivated( QListBoxItem * item) +{ + if ( item ) + slotRedoActivated( item->listBox()->index(item)); +} + +void KoCommandHistory::slotChangeUndoNumberOfSelectedItem( int pos) +{ + d->m_undoLabel->setText( i18n("Undo %n action", "Undo %n actions", pos+1) ); +} + +void KoCommandHistory::slotChangeRedoNumberOfSelectedItem( int pos) +{ + d->m_redoLabel->setText( i18n("Redo %n action", "Redo %n actions", pos+1) ); +} + + +void KoCommandHistory::slotRedoAboutToShow() +{ + d->m_redoListBox->clear(); + slotChangeRedoNumberOfSelectedItem( -1 ); + QStringList lst; + int i = 0; + if (m_first) + { + d->m_present = m_commands.first(); + lst.append(i18n("Redo: %1").arg(d->m_present->name())); + } + if (m_commands.findRef(d->m_present)!=-1 && m_commands.next()) + while ( m_commands.current() && i<10 ) // TODO make number of items configurable ? + { + lst.append(i18n("Redo: %1").arg(m_commands.current()->name())); + m_commands.next(); + } + d->m_redoListBox->insertStringList( lst ); + +} + +void KoCommandHistory::slotRedoActivated( int pos ) +{ + kdDebug(230) << "KoCommandHistory::slotRedoActivated " << pos << endl; + for ( int i = 0 ; i < pos+1; ++i ) + redo(); + m_redoPopup->hide(); +} + +void KoCommandHistory::updateActions() +{ + if ( m_undo && m_redo ) + { + m_undo->setEnabled( !m_first && ( d->m_present != 0L ) ); + m_redo->setEnabled(m_first || (m_commands.findRef(d->m_present)!=-1 && m_commands.next()!=0)); + } +} + +void KoCommandHistory::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +#include "KoCommandHistory.moc" diff --git a/lib/kofficeui/KoCommandHistory.h b/lib/kofficeui/KoCommandHistory.h new file mode 100644 index 00000000..a36ce670 --- /dev/null +++ b/lib/kofficeui/KoCommandHistory.h @@ -0,0 +1,198 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Werner Trobin <trobin@kde.org> + Copyright (C) 2000 David Faure <faure@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. +*/ + +#ifndef kocommandhistory_h +#define kocommandhistory_h + +#include <qptrlist.h> +#include <qstring.h> +#include <qobject.h> +#include <koffice_export.h> + +class KAction; +class KActionCollection; +class QPopupMenu; +class KCommand; +#include <qlistbox.h> + +class KoListBox : public QListBox { + Q_OBJECT +public: + KoListBox( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); +protected: + virtual void contentsMouseMoveEvent ( QMouseEvent * ); + virtual QSize sizeHint() const; +signals: + void changeNumberOfSelectedItem( int ); +}; + +/** + * The command history stores a (user) configurable amount of + * Commands. It keeps track of its size and deletes commands + * if it gets too large. The user can set a maximum undo and + * a maximum redo limit (e.g. max. 50 undo / 30 redo commands). + * The KoCommandHistory keeps track of the "borders" and deletes + * commands, if appropriate. It also activates/deactivates the + * undo/redo actions in the menu and changes the text according + * to the name of the command. + * + * @short History of user commands (for undo/redo) + */ +class KOFFICEUI_EXPORT KoCommandHistory : public QObject { + Q_OBJECT +public: + /** + * Creates a command history, to store commands. + * This constructor doesn't create actions, so you need to call + * #undo and #redo yourself. + */ + KoCommandHistory(); + + /** + * Creates a command history, to store commands. + * This also creates an undo and a redo action, in the @p actionCollection, + * using the standard names ("edit_undo" and "edit_redo"). + * + * @param actionCollection the collection to put the history in. + * @param withMenus if true, the actions will display a menu when plugged + * into a toolbar. + */ + KoCommandHistory(KActionCollection *actionCollection, bool withMenus = true); + + /** + * Destructs the command history object. + */ + virtual ~KoCommandHistory(); + + /** + * Erases all the undo/redo history. + * Use this when reloading the data, for instance, since this invalidates + * all the commands. + */ + void clear(); + + /** + * Adds a command to the history. Call this for each @p command you create. + * Unless you set @p execute to false, this will also execute the command. + * This means, most of the application's code will look like: + * + * MyCommand * cmd = new MyCommand(i18n("The Name"), parameters); + * m_historyCommand.addCommand( cmd ); + */ + void addCommand(KCommand *command, bool execute=true); + + /** + * @return the maximum number of items in the undo history + */ + int undoLimit() const { return m_undoLimit; } + /** + * Sets the maximum number of items in the undo history. + */ + void setUndoLimit(int limit); + /** + * @return the maximum number of items in the redo history + */ + int redoLimit() const { return m_redoLimit; } + /** + * Sets the maximum number of items in the redo history. + */ + void setRedoLimit(int limit); + + /** + * Enable or disable the undo and redo actions. + * This isn't usually necessary, but this method can be useful if + * you disable all actions (to go to a "readonly" state), and then + * want to come back to a readwrite mode. + */ + void updateActions(); + + /** + * @return the current top item on the history stack + */ + KCommand * presentCommand(); + +public slots: + /** + * Undoes the last action. + * Call this if you don't use the builtin KActions. + */ + virtual void undo(); + /** + * Redoes the last undone action. + * Call this if you don't use the builtin KActions. + */ + virtual void redo(); + /** + * Remembers when you saved the document. + * Call this right after saving the document. As soon as + * the history reaches the current index again (via some + * undo/redo operations) it will emit @ref documentRestored + * If you implemented undo/redo properly the document is + * the same you saved before. + */ + virtual void documentSaved(); + +protected slots: + void slotUndoAboutToShow(); + void slotUndoActivated( int ); + void slotRedoAboutToShow(); + void slotRedoActivated( int ); + void slotUndoActivated( QListBoxItem *); + void slotRedoActivated( QListBoxItem *); + void slotChangeRedoNumberOfSelectedItem( int ); + void slotChangeUndoNumberOfSelectedItem( int ); +signals: + /** + * Emitted every time a command is executed + * (whether by addCommand, undo or redo). + * You can use this to update the GUI, for instance. + */ + void commandExecuted(); + + /** + * Emitted every time a command is executed + * (whether by addCommand, undo or redo). + * You can use this to update the GUI, for instance. + * @param command was executed + */ + void commandExecuted(KCommand *cmd); + + /** + * Emitted every time we reach the index where you + * saved the document for the last time. See @ref #documentSaved + */ + void documentRestored(); + +private: + void clipCommands(); // ensures that the limits are kept + + QPtrList<KCommand> m_commands; + KAction *m_undo, *m_redo; + QPopupMenu *m_undoPopup, *m_redoPopup; + int m_undoLimit, m_redoLimit; + bool m_first; // attention: it's the first command in the list! +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KoCommandHistoryPrivate; + KoCommandHistoryPrivate *d; +}; + +#endif diff --git a/lib/kofficeui/KoContextCelp.cpp b/lib/kofficeui/KoContextCelp.cpp new file mode 100644 index 00000000..ae28b61e --- /dev/null +++ b/lib/kofficeui/KoContextCelp.cpp @@ -0,0 +1,595 @@ +/* This file is part of the KDE project + Copyright (C) 2002, Benoit Vautrin <benoit.vautrin@free.fr> + + 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 "KoContextCelp.h" + +#include <qpainter.h> +#include <qregion.h> +#include <qfont.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qsimplerichtext.h> + +#include <kpixmap.h> +#include <klocale.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kcursor.h> +#include <kapplication.h> +#include <qstring.h> + +KoVerticalLabel::KoVerticalLabel( QWidget* parent, const char* name ) + : QWidget( parent, name, Qt::WRepaintNoErase ) +{ + QFont f( font() ); + f.setPointSize( f.pointSize() + 2 ); + f.setBold( true ); + setFont( f ); + setBackgroundMode( PaletteLight ); +} // KoVerticalLabel::KoVerticalLabel + +KoVerticalLabel::~KoVerticalLabel() +{ +} // KoVerticalLabel::~KoVerticalLabel + +void KoVerticalLabel::setText( const QString& text ) +{ + m_text = text; + QFontMetrics fm( font() ); + setMinimumSize( fm.height() + 2, fm.width( m_text ) + 4 ); + update(); +} // KoVerticalLabel::setText + +void KoVerticalLabel::paintEvent( QPaintEvent* ) +{ + KPixmap pm; + pm.resize( height(), width() ); + QPainter p( &pm ); + p.fillRect( 0, 0, height(), width(), colorGroup().background() ); + p.setFont( font() ); + p.drawText( 0, 0, height(), width(), AlignCenter, m_text ); + p.end(); + QPainter ap( this ); + ap.rotate( 270. ); + ap.translate( -height(), 0 ); + ap.drawPixmap( 0, 0, pm ); +} // KoVerticalLabel::paintEvent + +static unsigned char upbits[] = { 0xc, 0x1e, 0x3f, 0x3f }; +static unsigned char downbits[] = { 0x3f, 0x3f, 0x1e, 0xc }; + +KoHelpNavButton::KoHelpNavButton( NavDirection d, QWidget* parent ) + : QWidget( parent ) +{ + m_pressed = false; + m_bitmap = QBitmap( 8, 4, ( d == Up ? upbits : downbits ), true ); + m_bitmap.setMask( m_bitmap ); + setFixedSize( 8, 6 ); + setBackgroundMode( PaletteLight ); +} // KoHelpNavButton::KoHelpNavButton + +void KoHelpNavButton::paintEvent( QPaintEvent* ) +{ + QPainter p( this ); + if ( isEnabled() ) + { + if ( m_pressed ) + p.setPen( colorGroup().highlight() ); + else + p.setPen( colorGroup().text() ); + p.drawPixmap( 1, 1, m_bitmap ); + } +} // KoHelpNavButton::paintEvent + +void KoHelpNavButton::enterEvent( QEvent* ) +{ + if ( isEnabled() ) + emit pressed(); + m_pressed = true; + update(); +} // KoHelpNavButton::enterEvent + +void KoHelpNavButton::leaveEvent( QEvent* ) +{ + if ( isEnabled() ) + emit released(); + m_pressed = false; + update(); +} // KoHelpNavButton::leaveEvent + +static unsigned char notstickybits[] = { 0x8, 0x1e, 0xc, 0xa, 0x1 }; +static unsigned char stickybits[] = { 0xe, 0x11, 0x15, 0x11, 0xe }; +static unsigned char closebits[] = { 0x11, 0xa, 0x4, 0xa, 0x11 }; + +KoTinyButton::KoTinyButton( Action a, QWidget* parent ) + : QWidget( parent ), m_action( a ) +{ + m_pressed = false; + m_toggled = false; + switch ( a ) + { + case Sticky: + m_bitmap = QBitmap( 5, 5, notstickybits, true ); + break; + + default: + m_bitmap = QBitmap( 5, 5, closebits, true ); + } + m_bitmap.setMask( m_bitmap ); + setMinimumSize( 7, 7 ); + setBackgroundMode( PaletteBackground ); +} // KoTinyButton::KoTinyButton + +void KoTinyButton::paintEvent( QPaintEvent* ) +{ + QPainter p( this ); + if ( isEnabled() ) + { + if ( m_pressed ) + p.setPen( colorGroup().highlight() ); + else + p.setPen( colorGroup().text() ); + p.drawPixmap( width() / 2 - 2, 1, m_bitmap ); + } +} // KoTinyButton::paintEvent + +void KoTinyButton::mousePressEvent( QMouseEvent* ) +{ + if ( isEnabled() ) + { + m_pressed = true; + update(); + } +} // KoTinyButton::mousePressEvent + +void KoTinyButton::mouseReleaseEvent( QMouseEvent* ) +{ + if ( isEnabled() && m_pressed ) + { + m_pressed = false; + emit( clicked() ); + if ( ( m_action == Sticky ) ) + { + m_toggled = !m_toggled; + emit( toggled( m_toggled ) ); + //switch ( m_action ) + //{ + // case Sticky: + m_bitmap = QBitmap( 5, 5, ( m_toggled ? stickybits : notstickybits ), true ); + //} + m_bitmap.setMask( m_bitmap ); + } + update(); + } +} // KoTinyButton::mouseReleaseEvent + +KoHelpView::KoHelpView( QWidget* parent ) + : QWidget( parent ) +{ + currentText = 0L; + setBackgroundMode( PaletteLight ); + parent->installEventFilter( this ); + setMouseTracking( true ); +} // KoHelpView::KoHelpView + +KoHelpView::~KoHelpView() +{ + if ( currentText ) + delete currentText; +} // KoHelpView::~KoHelpView + +void KoHelpView::setText( const QString& text ) +{ + if ( currentText ) + delete currentText; + currentText = new QSimpleRichText( text, font() ); + currentText->setWidth( width() ); + setFixedHeight( currentText->height() ); +} // KoHelpView::setText + +void KoHelpView::mousePressEvent( QMouseEvent* e ) +{ + currentAnchor = currentText->anchorAt( e->pos() ); + if ( !currentAnchor.isEmpty() ) + e->accept(); + else + e->ignore(); +} // KoHelpView::mousePressEvent + +void KoHelpView::mouseReleaseEvent( QMouseEvent* e ) +{ + if ( ( !currentAnchor.isEmpty() ) && ( currentAnchor == currentText->anchorAt( e->pos() ) ) ) + { + e->accept(); + if (currentAnchor.startsWith("help://#")) { + //that's not really useful, since koffice documents can be embedded + kapp->invokeHelp(currentAnchor.right(currentAnchor.length()-8)); + } + else + if (currentAnchor.startsWith("help://")) { + // that's the useful version of a help link + QString helpapp=currentAnchor.right(currentAnchor.length()-7); + QString helpanchor; + int pos; + if ((pos=helpapp.find("#"))!=-1) { + helpanchor=helpapp.right(helpapp.length()-pos-1); + helpapp=helpapp.left(pos); + } + kapp->invokeHelp(helpanchor,helpapp); + } + else + emit linkClicked( currentAnchor ); + currentAnchor = ""; + } + else + e->ignore(); +} // KoHelpView::mouseReleaseEvent + +void KoHelpView::mouseMoveEvent( QMouseEvent* e ) +{ + if ( !currentText->anchorAt( e->pos() ).isEmpty() ) + setCursor( KCursor::handCursor() ); + else + setCursor( KCursor::arrowCursor() ); +} // KoHelpView::mouseMove + +bool KoHelpView::eventFilter( QObject*, QEvent* e ) +{ + if ( ( currentText ) && ( e->type() == QEvent::Resize ) ) + { + setFixedWidth( ( (QResizeEvent*)e )->size().width() ); + currentText->setWidth( width() ); + setFixedHeight( currentText->height() ); + + return true; + } + return false; +} // KoHelpView::resizeEvent + +void KoHelpView::paintEvent( QPaintEvent* ) +{ + QPainter p( this ); + currentText->draw( &p, 0, 0, QRect(), colorGroup() ); +} // KoHelpView::paintEvent + +KoHelpWidget::KoHelpWidget( QString help, QWidget* parent ) + : QWidget( parent ) +{ + QGridLayout* layout = new QGridLayout( this, 3, 3 ); + layout->setMargin( 2 ); + layout->addWidget( m_upButton = new KoHelpNavButton( KoHelpNavButton::Up, this ), 0, 1, AlignHCenter ); + layout->addWidget( m_helpViewport = new QWidget( this ), 1, 1 ); + layout->addWidget( m_downButton = new KoHelpNavButton( KoHelpNavButton::Down, this ), 2, 1, AlignHCenter ); + layout->addColSpacing( 0, 5 ); + layout->addColSpacing( 2, 5 ); + layout->setColStretch( 1, 1 ); + + m_helpView = new KoHelpView( m_helpViewport ); + m_helpViewport->setBackgroundMode( PaletteLight ); + setText( help ); + + setBackgroundMode( PaletteLight ); + + connect( m_upButton, SIGNAL( pressed() ), this, SLOT( startScrollingUp() ) ); + connect( m_downButton, SIGNAL( pressed() ), this, SLOT( startScrollingDown() ) ); + connect( m_upButton, SIGNAL( released() ), this, SLOT( stopScrolling() ) ); + connect( m_downButton, SIGNAL( released() ), this, SLOT( stopScrolling() ) ); + connect( m_helpView, SIGNAL( linkClicked( const QString& ) ), this, SIGNAL( linkClicked( const QString& ) ) ); +} // KoHelpWidget::KoHelpWidget + +void KoHelpWidget::updateButtons() +{ + m_upButton->setEnabled( m_ypos < 0 ); + m_downButton->setEnabled( m_helpViewport->height() - m_ypos < m_helpView->height() ); +} // KoHelpWidget::updateButtons + +void KoHelpWidget::setText( QString text ) +{ + m_helpView->setText( text ); + m_helpView->move( 0, 0 ); + m_ypos = 0; + updateButtons(); +} // KoHelpWidget::setText + +void KoHelpWidget::resizeEvent( QResizeEvent* ) +{ + updateButtons(); +} // KoHelpWidget::resizeEvent + +void KoHelpWidget::startScrollingUp() +{ + if ( !m_upButton->isEnabled() ) + return; + m_scrollDown = false; + startTimer( 80 ); +} // KoHelpWidget::startScrollingUp + +void KoHelpWidget::startScrollingDown() +{ + if ( !m_downButton->isEnabled() ) + return; + m_scrollDown = true; + startTimer( 80 ); +} // KoHelpWidget::startScrollingDown + +void KoHelpWidget::scrollUp() +{ + if ( m_ypos > 0 ) + stopScrolling(); + else + { + m_ypos += 2; + m_helpViewport->scroll( 0, 2 ); + m_helpViewport->update(); + updateButtons(); + } +} // KoHelpWidget::scrollUp() + +void KoHelpWidget::scrollDown() +{ + if ( m_helpViewport->height() - m_helpView->height() - m_ypos > 0 ) + stopScrolling(); + else + { + m_ypos -= 2; + m_helpViewport->scroll( 0, -2 ); + m_helpViewport->update(); + updateButtons(); + } +} // KoHelpWidget::scrollUp() + +void KoHelpWidget::timerEvent( QTimerEvent* ) +{ + if ( m_scrollDown ) + scrollDown(); + else + scrollUp(); +} // KoHelpWidget::timerEvent + +void KoHelpWidget::stopScrolling() +{ + killTimers(); +} // KoHelpWidget::stopScrolling + +KoContextHelpPopup::KoContextHelpPopup( QWidget* parent ) + : QWidget( parent, "", WType_Dialog | WStyle_Customize | WStyle_NoBorder ) +{ + QGridLayout* layout = new QGridLayout( this ); + QHBoxLayout* buttonLayout; + layout->addWidget( m_helpIcon = new QLabel( this ), 0, 0 ); + layout->addWidget( m_helpTitle = new KoVerticalLabel( this ), 1, 0 ); + buttonLayout = new QHBoxLayout( layout ); + //layout->addLayout( buttonLayout, 2, 0 ); + layout->addMultiCellWidget( m_helpViewer = new KoHelpWidget( "", this ), 0, 2, 1, 1 ); + buttonLayout->add( m_close = new KoTinyButton( KoTinyButton::Close, this ) ); + buttonLayout->add( m_sticky = new KoTinyButton( KoTinyButton::Sticky, this ) ); + layout->addColSpacing( 2, 2 ); + layout->addRowSpacing( 3, 2 ); + layout->setMargin( 3 ); + layout->setSpacing( 1 ); + layout->setRowStretch( 1, 1 ); + buttonLayout->setSpacing( 1 ); + setMinimumSize( 180, 180 ); + + m_isSticky = false; + setFocusPolicy( StrongFocus ); + + connect( m_close, SIGNAL( clicked() ), this, SIGNAL( wantsToBeClosed() ) ); + connect( m_sticky, SIGNAL( toggled( bool ) ), this, SLOT( setSticky( bool ) ) ); + connect( m_helpViewer, SIGNAL( linkClicked( const QString& ) ), this, SIGNAL( linkClicked( const QString& ) ) ); +} // KoContextHelpPopup::KoContextHelpPopup + +KoContextHelpPopup::~KoContextHelpPopup() +{ +} // KoContextHelpPopup::~KoContextHelpPopup + +void KoContextHelpPopup::setContextHelp( const QString& title, const QString& text, const QPixmap* icon ) +{ + m_helpIcon->setPixmap( icon ? *icon : BarIcon( "help" ) ); + m_helpTitle->setText( title ); + m_helpViewer->setText( text ); +} // KoContextHelpPopup::updateHelp + +void KoContextHelpPopup::mousePressEvent( QMouseEvent* e ) +{ + m_mousePos = e->globalPos() - pos(); +} // KoContextHelpPopup::mousePressEvent + +void KoContextHelpPopup::mouseMoveEvent( QMouseEvent* e ) +{ + move( e->globalPos() - m_mousePos ); +} // KoContextHelpPopup::mouseMoveEvent + +void KoContextHelpPopup::resizeEvent( QResizeEvent* ) +{ + QBitmap mask( width(), height() ); + QPointArray a; + QPainter p( &mask ); + p.fillRect( 0, 0, width(), height(), color1 ); + p.setPen( color0 ); + p.setBrush( color0 ); + p.drawLine( 0, 0, 0, 3 ); + p.drawLine( 0, 0, 3, 0 ); + p.drawPoint( 1, 1 ); + a.setPoints( 3, 0, height() - 5, 4, height() - 1, 0, height() - 1 ); + p.drawPolygon( a ); + a.setPoints( 3, width() - 5, 0, width() - 1, 4, width() - 1, 0 ); + p.drawPolygon( a ); + p.drawLine( width() - 1, height() - 1, width() - 4, height() - 1 ); + p.drawLine( width() - 1, height() - 1, width() - 1, height() - 4 ); + p.drawPoint( width() - 2, height() - 2 ); + p.drawPoint( 0, height() - 6 ); + p.drawPoint( width() - 6, 0 ); + p.drawPoint( width() - 5, height() - 3 ); + p.drawPoint( width() - 3, height() - 5 ); + p.setPen( NoPen ); + p.setBrush( QBrush( color0, Dense4Pattern ) ); + p.drawRect( 0, height() - 2, width() - 1, height() - 1 ); + p.drawRect( width() - 2, 0, width() - 1, height() - 1 ); + p.drawRect( width() - 4, height() - 4, width() - 2, height() - 2 ); + p.end(); + setMask( QRegion( mask ) ); +} // KoContextHelpPopup::resizeEvent + +void KoContextHelpPopup::paintEvent( QPaintEvent* ) +{ + QPainter p( this ); + p.fillRect( 0, 0, width(), height(), colorGroup().light() ); + p.setPen( black ); + p.drawRect( 0, 0, width(), height() ); + p.fillRect( width() - 3, 0, width() - 1, height() - 1, black ); + p.fillRect( 0, height() - 3, width() - 1, height() - 1, black ); + p.drawLine( 1, 2, 1, 3 ); + p.drawLine( 2, 1, 3, 1 ); + p.drawLine( width() - 4, 2, width() - 4, 3 ); + p.drawLine( width() - 5, 1, width() - 6, 1 ); + p.drawLine( 1, height() - 5, 1, height() - 6 ); + p.drawLine( 2, height() - 4, 3, height() - 4 ); + p.drawLine( width() - 4, height() - 5, width() - 4, height() - 6 ); + p.drawLine( width() - 4, height() - 4, width() - 6, height() - 4 ); +} // KoContextHelpPopup::paintEvent + +void KoContextHelpPopup::windowActivationChange( bool ) +{ + if ( !isActiveWindow() && !m_isSticky ) + emit wantsToBeClosed(); +} // KoContestHelpPopup::windowActivationChange + +void KoContextHelpPopup::keyPressEvent( QKeyEvent* e ) +{ + switch ( e->key() ) + { +/* case Key_Up: + m_helpViewer->startScrollingUp(); + break; + + case Key_Down: + m_helpViewer->startScrollingDown(); + break;*/ + case Key_Up: + m_helpViewer->scrollUp(); + break; + + case Key_Down: + m_helpViewer->scrollDown(); + break; + } +} // KoContextHelpPopup::keyPressEvent + +void KoContextHelpPopup::keyReleaseEvent( QKeyEvent* e ) +{ + switch ( e->key() ) + { + /*case Key_Up: + case Key_Down: + m_helpViewer->stopScrolling(); + break;*/ + + case Key_Escape: + emit wantsToBeClosed(); + break; + } +} // KoContextHelpPopup::keyPressEvent + +KoContextHelpAction::KoContextHelpAction( KActionCollection* parent, QWidget* /*popupParent*/ ) + : KToggleAction( i18n( "Context Help" ), BarIcon( "help" ), KShortcut( "CTRL+SHIFT+F1" ), 0, 0, parent, "help_context" ) +{ + m_popup = new KoContextHelpPopup( 0L ); + connect( m_popup, SIGNAL( wantsToBeClosed() ), this, SLOT( closePopup() ) ); + connect( this, SIGNAL( toggled( bool ) ), m_popup, SLOT( setShown( bool ) ) ); + connect( m_popup, SIGNAL( linkClicked( const QString& ) ), this, SIGNAL( linkClicked( const QString& ) ) ); +} // KoContextHelpAction::KoContextHelpAction + +KoContextHelpAction::~KoContextHelpAction() +{ + delete m_popup; +} // KoContextHelpAction::~KoContextHelpAction + +void KoContextHelpAction::updateHelp( const QString& title, const QString& text, const QPixmap* icon ) +{ + m_popup->setContextHelp( title, text, icon ); +} // KoContextHelpAction::updateHelp + +void KoContextHelpAction::closePopup() +{ + activate(); + setChecked( false ); // For a unknown reason, this is needed... +} // KoContextHelpAction::closePopup + + +KoContextHelpWidget::KoContextHelpWidget( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + setCaption( i18n( "Context Help" ) ); + QGridLayout* layout = new QGridLayout( this ); + layout->addWidget( m_helpIcon = new QLabel( this ), 0, 0 ); + layout->addWidget( m_helpTitle = new KoVerticalLabel( this ), 1, 0 ); + layout->addMultiCellWidget( m_helpViewer = new KoHelpWidget( "", this ), 0, 1, 1, 1 ); + layout->setMargin( 2 ); + layout->setSpacing( 1 ); + layout->setRowStretch( 1, 1 ); + this->setMinimumSize( 180, 120 ); + this->show(); + setContextHelp( i18n( "Context Help" ), i18n( "Here will be shown help according to your actions" ), 0 ); + connect( m_helpViewer, SIGNAL( linkClicked( const QString& ) ), this, SIGNAL( linkClicked( const QString& ) ) ); +} // KoContextHelpWidget::KoContextHelpWidget + +KoContextHelpWidget::~KoContextHelpWidget() +{ +} // KoContextHelpWidget::~KoContextHelpWidget + +void KoContextHelpWidget::setContextHelp( const QString& title, const QString& text, const QPixmap* icon ) +{ + m_helpIcon->setPixmap( icon ? *icon : BarIcon( "help" ) ); + m_helpTitle->setText( title ); + m_helpViewer->setText( text ); +} // KoContextHelpWidget::updateHelp + + +KoContextHelpDocker::KoContextHelpDocker( QWidget* parent, const char* name ) + : QDockWindow( parent, name ) +{ + setCaption( i18n( "Context Help" ) ); + QWidget* mainWidget = new QWidget( this ); + QGridLayout* layout = new QGridLayout( mainWidget ); + layout->addWidget( m_helpIcon = new QLabel( mainWidget ), 0, 0 ); + layout->addWidget( m_helpTitle = new KoVerticalLabel( mainWidget ), 1, 0 ); + layout->addMultiCellWidget( m_helpViewer = new KoHelpWidget( "", mainWidget ), 0, 1, 1, 1 ); + layout->setMargin( 2 ); + layout->setSpacing( 1 ); + layout->setRowStretch( 1, 1 ); + mainWidget->setMinimumSize( 180, 120 ); + mainWidget->show(); + setWidget( mainWidget ); + setContextHelp( i18n( "Context Help" ), i18n( "Here will be shown help according to your actions" ), 0 ); + connect( m_helpViewer, SIGNAL( linkClicked( const QString& ) ), this, SIGNAL( linkClicked( const QString& ) ) ); +} // KoContextHelpDocker::KoContextHelpDocker + +KoContextHelpDocker::~KoContextHelpDocker() +{ +} // KoContextHelpDocker::~KoContextHelpDocker + +void KoContextHelpDocker::setContextHelp( const QString& title, const QString& text, const QPixmap* icon ) +{ + m_helpIcon->setPixmap( icon ? *icon : BarIcon( "help" ) ); + m_helpTitle->setText( title ); + m_helpViewer->setText( text ); +} // KoContextHelpDocker::updateHelp + +#include "KoContextCelp.moc" diff --git a/lib/kofficeui/KoContextCelp.h b/lib/kofficeui/KoContextCelp.h new file mode 100644 index 00000000..07f80d8f --- /dev/null +++ b/lib/kofficeui/KoContextCelp.h @@ -0,0 +1,279 @@ +/* This file is part of the KDE project + Copyright (C) 2002, Benoit Vautrin <benoit.vautrin@free.fr> + + 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. +*/ + +#ifndef __KOCONTEXTHELPACTION_H__ +#define __KOCONTEXTHELPACTION_H__ + +#include <qwidget.h> +#include <qbitmap.h> +#include <qdockwindow.h> + +#include <kaction.h> +#include <koffice_export.h> +class QPixmap; +class QLabel; +class QSimpleRichText; + +class KoVerticalLabel : public QWidget +{ + Q_OBJECT + + public: + KoVerticalLabel( QWidget* parent = 0, const char* name = 0 ); + ~KoVerticalLabel(); + + public slots: + void setText( const QString& text ); + + protected: + void paintEvent( QPaintEvent* ); + + private: + QString m_text; +}; // KoVerticalLabel + +class KoHelpNavButton : public QWidget +{ + Q_OBJECT + + public: + enum NavDirection { + Up, + Down + }; + + KoHelpNavButton( NavDirection d, QWidget* parent ); + + signals: + void pressed(); + void released(); + + protected: + void paintEvent( QPaintEvent* ); + void enterEvent( QEvent* ); + void leaveEvent( QEvent* ); + + private: + QBitmap m_bitmap; + bool m_pressed; +}; // KoHelpNavButton + +class KoTinyButton : public QWidget +{ + Q_OBJECT + + public: + enum Action { + Close, + Sticky + }; + + KoTinyButton( Action a, QWidget* parent ); + + signals: + void clicked(); + void toggled( bool ); + + protected: + void paintEvent( QPaintEvent* ); + void mousePressEvent( QMouseEvent* ); + void mouseReleaseEvent( QMouseEvent* ); + + private: + QBitmap m_bitmap; + bool m_pressed; + Action m_action; + bool m_toggled; +}; // KoTinyButton + +class KoHelpView : public QWidget +{ + Q_OBJECT + + public: + KoHelpView( QWidget* parent ); + ~KoHelpView(); + + void setText( const QString& text ); + bool eventFilter( QObject* watched, QEvent* e ); + + signals: + void linkClicked( const QString& link ); + + protected: + virtual void mousePressEvent( QMouseEvent* e ); + virtual void mouseReleaseEvent( QMouseEvent* e ); + virtual void mouseMoveEvent( QMouseEvent* e ); + virtual void paintEvent( QPaintEvent* e ); + + private: + QSimpleRichText* currentText; + QString currentAnchor; +}; // KoHelpView + +class KoHelpWidget : public QWidget +{ + Q_OBJECT + + public: + KoHelpWidget( QString help, QWidget* parent ); + + void setText( QString text ); + void timerEvent( QTimerEvent* ); + void updateButtons(); + + signals: + void linkClicked( const QString& link ); + + public slots: + void scrollUp(); + void scrollDown(); + void startScrollingUp(); + void startScrollingDown(); + void stopScrolling(); + + protected: + void resizeEvent( QResizeEvent* ); + + private: + int m_ypos; + bool m_scrollDown; + QWidget* m_helpViewport; + KoHelpView* m_helpView; + KoHelpNavButton* m_upButton; + KoHelpNavButton* m_downButton; +}; // KoHelpWidget + +/** + * KoContextHelpPopup is the popup displayed by ContextHelpAction. + */ +class KoContextHelpPopup : public QWidget +{ + Q_OBJECT + + public: + KoContextHelpPopup( QWidget* parent = 0 ); + ~KoContextHelpPopup(); + + public slots: + void setContextHelp( const QString& title, const QString& text, const QPixmap* icon = 0 ); + void setSticky( bool sticky ) { m_isSticky = sticky; } + + protected: + virtual void mousePressEvent( QMouseEvent* ); + virtual void mouseMoveEvent( QMouseEvent* ); + virtual void resizeEvent( QResizeEvent* ); + virtual void paintEvent( QPaintEvent* ); + virtual void windowActivationChange( bool ); + virtual void keyPressEvent ( QKeyEvent* ); + virtual void keyReleaseEvent ( QKeyEvent* ); + + signals: + void wantsToBeClosed(); + /** + * Connect to this signal to receive the href value of the links clicked. + */ + void linkClicked( const QString& link ); + + private: + KoHelpWidget* m_helpViewer; + KoVerticalLabel* m_helpTitle; + QLabel* m_helpIcon; + KoTinyButton* m_close; + KoTinyButton* m_sticky; + + QPoint m_mousePos; + bool m_isSticky; +}; // KoContextHelpPopup + +/** + * KoContextHelpAction provides a easy to use context help system. + * + * This action displays on demand a context help in a popup. + * The context help is set by the updateHelp slot. + */ +class KOFFICEUI_EXPORT KoContextHelpAction : public KToggleAction +{ + Q_OBJECT + + public: + KoContextHelpAction( KActionCollection* parentCollection, QWidget* parent = 0 ); + virtual ~KoContextHelpAction(); + + public slots: + void updateHelp( const QString& title, const QString& text, const QPixmap* icon = 0 ); + void closePopup(); + + signals: + /** + * Connect to this signal to receive the href value of the links clicked. + */ + void linkClicked( const QString& link ); + + private: + KoContextHelpPopup* m_popup; +}; // KoContextHelpAction + +class KoContextHelpWidget : public QWidget +{ + Q_OBJECT + + public: + KoContextHelpWidget( QWidget* parent = 0, const char* name = 0 ); + ~KoContextHelpWidget(); + + public slots: + void setContextHelp( const QString& title, const QString& text, const QPixmap* icon = 0 ); + + signals: + /** + * Connect to this signal to receive the href value of the links clicked. + */ + void linkClicked( const QString& link ); + + private: + KoHelpWidget* m_helpViewer; + KoVerticalLabel* m_helpTitle; + QLabel* m_helpIcon; +}; // KoContextHelpWidget + +class KoContextHelpDocker : public QDockWindow +{ + Q_OBJECT + + public: + KoContextHelpDocker( QWidget* parent = 0, const char* name = 0 ); + ~KoContextHelpDocker(); + + public slots: + void setContextHelp( const QString& title, const QString& text, const QPixmap* icon = 0 ); + + signals: + /** + * Connect to this signal to receive the href value of the links clicked. + */ + void linkClicked( const QString& link ); + + private: + KoHelpWidget* m_helpViewer; + KoVerticalLabel* m_helpTitle; + QLabel* m_helpIcon; +}; // KoContextHelpDocker + +#endif /* __KOCONTEXTHELPACTION_H__ */ diff --git a/lib/kofficeui/KoEditPath.cpp b/lib/kofficeui/KoEditPath.cpp new file mode 100644 index 00000000..8f7aa19e --- /dev/null +++ b/lib/kofficeui/KoEditPath.cpp @@ -0,0 +1,98 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <kdeversion.h> +#include <klocale.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qlistbox.h> +#include "KoEditPath.h" +#include <keditlistbox.h> +#include <kfiledialog.h> +#include <kurlrequester.h> +#include <qhbox.h> +#include <klineedit.h> +#include <qvbox.h> +#include <qcheckbox.h> +#include <qlabel.h> + +KoEditPathDia::KoEditPathDia( const QString & _path, QWidget *parent, const char *name ) + : KDialogBase( parent, name , true, "", Ok|Cancel, Ok, true ) +{ + setCaption( i18n("Edit Path") ); + QWidget *page = new QWidget( this ); + setMainWidget(page); + QGridLayout * grid = new QGridLayout(page, 5, 2, KDialog::marginHint(), KDialog::spacingHint()); + + urlReq = new KURLRequester(); + urlReq->fileDialog()->setMode(KFile::Directory | KFile::LocalOnly); + + KEditListBox::CustomEditor tmp(urlReq, urlReq->lineEdit()); + + m_listpath = new KEditListBox( i18n("Expression Path"), + tmp,page, "list_editor" , false, KEditListBox::Add|KEditListBox::Remove ); + + grid->addMultiCellWidget(m_listpath, 0, 4, 0, 0); + m_listpath->listBox()->insertStringList(QStringList::split(QString(";"), _path)); + setFocus(); + resize( 500, 300); +} + +QString KoEditPathDia::newPath()const +{ + QString tmp; + for (int i = 0; i <(int)m_listpath->listBox()->count(); i++) + { + if ( i!=0) + tmp +=";"; + tmp += m_listpath->listBox()->text( i ); + } + return tmp; +} + + +KoChangePathDia::KoChangePathDia( const QString & _path, QWidget *parent, const char *name ) + : KDialogBase( parent, name , true, "", Ok|Cancel, Ok, true ) +{ + setCaption( i18n("Edit Path") ); + + QVBox *page =makeVBoxMainWidget(); + new QLabel( i18n("Location:"), page); + m_urlReq = new KURLRequester(page); + m_urlReq->setMinimumWidth( m_urlReq->sizeHint().width() * 3 ); + + m_urlReq->lineEdit()->setText( _path ); + m_urlReq->fileDialog()->setMode(KFile::Directory | KFile::LocalOnly); + m_defaultPath = new QCheckBox( i18n("Default path"), page ); + connect( m_defaultPath, SIGNAL(toggled ( bool )), this, SLOT( slotChangeDefaultValue( bool ))); + slotChangeDefaultValue( _path.isEmpty() ); + m_defaultPath->setChecked( _path.isEmpty() ); +} + +QString KoChangePathDia::newPath() const +{ + return m_defaultPath->isChecked() ? QString::null : m_urlReq->lineEdit()->text(); +} + +void KoChangePathDia::slotChangeDefaultValue( bool _b) +{ + m_urlReq->setEnabled( !_b); +} + +#include "KoEditPath.moc" diff --git a/lib/kofficeui/KoEditPath.h b/lib/kofficeui/KoEditPath.h new file mode 100644 index 00000000..6ec99333 --- /dev/null +++ b/lib/kofficeui/KoEditPath.h @@ -0,0 +1,55 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __KOEditPathDia__ +#define __KOEditPathDia__ + +#include <kdialogbase.h> +#include <qstringlist.h> +#include <koffice_export.h> +class KEditListBox; +class KURLRequester; +class QCheckBox; + +class KOFFICEUI_EXPORT KoEditPathDia : public KDialogBase +{ + Q_OBJECT +public: + KoEditPathDia( const QString & _path, QWidget *parent, const char *name ); + QString newPath()const; + +private: + KEditListBox *m_listpath; + KURLRequester *urlReq; +}; + +class KOFFICEUI_EXPORT KoChangePathDia : public KDialogBase +{ + Q_OBJECT +public: + KoChangePathDia( const QString & _path, QWidget *parent, const char *name ); + QString newPath()const; +private slots: + void slotChangeDefaultValue( bool ); +private: + KURLRequester *m_urlReq; + QCheckBox *m_defaultPath; +}; + +#endif diff --git a/lib/kofficeui/KoGeneralPropertyUi.ui b/lib/kofficeui/KoGeneralPropertyUi.ui new file mode 100644 index 00000000..41d4bb98 --- /dev/null +++ b/lib/kofficeui/KoGeneralPropertyUi.ui @@ -0,0 +1,193 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KoGeneralPropertyUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KoGeneralPropertyUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>292</width> + <height>222</height> + </rect> + </property> + <property name="caption"> + <string>General</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout13</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>nameLabel</cstring> + </property> + <property name="text"> + <string>Na&me:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>nameInput</cstring> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>nameInput</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>protect</cstring> + </property> + <property name="text"> + <string>Protect si&ze and position</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>keepRatio</cstring> + </property> + <property name="text"> + <string>Keep &aspect ratio</string> + </property> + </widget> + <widget class="QGroupBox" row="3" column="0"> + <property name="name"> + <cstring>positionGroup</cstring> + </property> + <property name="title"> + <string>Position</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>widthLabel</cstring> + </property> + <property name="text"> + <string>&Width:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>widthInput</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>heightLabel</cstring> + </property> + <property name="text"> + <string>&Height:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>heightInput</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>topLabel</cstring> + </property> + <property name="text"> + <string>&Top:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>yInput</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>leftLabel</cstring> + </property> + <property name="text"> + <string>&Left:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>xInput</cstring> + </property> + </widget> + <widget class="KoUnitDoubleSpinBox" row="0" column="1"> + <property name="name"> + <cstring>xInput</cstring> + </property> + </widget> + <widget class="KoUnitDoubleSpinBox" row="0" column="3"> + <property name="name"> + <cstring>yInput</cstring> + </property> + </widget> + <widget class="KoUnitDoubleSpinBox" row="1" column="3"> + <property name="name"> + <cstring>heightInput</cstring> + </property> + </widget> + <widget class="KoUnitDoubleSpinBox" row="1" column="1"> + <property name="name"> + <cstring>widthInput</cstring> + </property> + </widget> + </grid> + </widget> + <spacer row="4" column="0"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>21</height> + </size> + </property> + </spacer> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>KoUnitDoubleSpinBox</class> + <header location="local">KoUnitWidgets.h</header>> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1008">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b749444154388db59541681d551486bf49aef55c4965061b98815a5e20a5790b912c0d66d12c0381361004219bae0a45041111a92d28086a4110eaa68a8bd8b8a97121348b96b810cca6988281111a9c27446720afcc8516efa94e3b2e665e6244832e3c70b8cce5f2cf77cffc734e50d735830882600818060c3004046d1e14759b8f800a7858d7f5a360207cfe8df34f7627ba679d7367f27e7ea27425168bc71fb896ae24bd936eaddf5a5fa6e213e02ef0c00c48af5dbd76364a7837390e9d4a5b98128c0025d608e0f7f6d97b4eefc8389f8617d66f3a0b7c0894a63d395cf48b33d1d390f5bf40ef65f84ab116fcefe00a212f1441b04760ec38882854a0801c866854015e00aeee1203a6ec97273c0ebd57e02b873d1c926dc0daaab271ab400c68a5880989c785d98588a9698fd0ec872302e83120fa33f150ee7226517c95636dc8b73794e52b0e2a08432119174420ef29bd2de5a3b7338ac598f9451069c4dbb0c0a18170608d05147b58c83660a5159d3d1573720e92c482f1a846acad7a56ae3856967ac4719799d316314a53188681606820ec2b0f08dec3f5af1c5a29b3a762e6cf4094286a72dc8ee5fa9725b30b112fbe148211969772b4bfcf7e01100c88b1c682297145447a3b230c1b5291e68aee7ec2e5f74bb24d47b903e75e4b58bfe1c87e50d2d423b2dfdc03627ce5b146c88b120c241d884641519c8bb8fc564ebae99050989a8e60a4a43b19a295926f8356ff20dcd41804814a0947da8fb29370f99d926cb3b157382224472112c08018412b90bf20ef2306b047001392f61455cbda4ddf908e08f1d1905eafe0d2c59c742322cf14ad94b18e853d5734fedd4f5cd23d0e9d8e50f494b555cffc6244b9a34c9d8c4862b874117a5b05e75fced1fb8e380ee94e425e1c50631010657641d04a59b9e2585b2d39f74ac2e4b4a733e979f5cd84380e71fd022a989a0b199bd8e7e3bf23f6500953d3506cc7ac2cf558fe00d66f38bacf846020cf4a5c5f9bdaa2a4df28e96d4b2842ebe37dc275d92fdb7f5f11607e5188e32e2b9fe7a49b4a7abbd79cae203c1232733ae4bbaf95fcbe43ab88a2bf2b5a03f5ae707a27dd4a331997a821110333739ea9e98434f5e4db8d68d2b17427616c02d2390b5502a624fb1e805f8087401dd4754d100416c3ebcf3d2f17a2a4b194aa3270bdb4af17d37633da9b19c139483794bc505cc155e063e047da46ff18700c780ff889bda9f06ff367e033e034f02c303a201ea2e94a11f054bb5ada86c2c151b7d7f73413e02e50ee8ea620080cf038f0442b7a88ff36f37e6bc57f051e04ffd730fd03ef8bd61b5b2ca6900000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/lib/kofficeui/KoGuideLineDia.cpp b/lib/kofficeui/KoGuideLineDia.cpp new file mode 100644 index 00000000..db58ed28 --- /dev/null +++ b/lib/kofficeui/KoGuideLineDia.cpp @@ -0,0 +1,131 @@ +// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* This file is part of the KDE project + Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com> + Copyright (C) 2005 Thorsten Zachmann <zachmann@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 "KoGuideLineDia.h" + +#include <qbuttongroup.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> + +#include <klocale.h> +#include <KoUnitWidgets.h> + + +KoGuideLineDia::KoGuideLineDia( QWidget *parent, double pos, double minPos, double maxPos, + KoUnit::Unit unit, const char *name ) +: KDialogBase( parent, name , true, "", Ok | Cancel, Ok, true ) +, m_hButton( 0 ) +, m_vButton( 0 ) +{ + setCaption( i18n("Set Guide Line Position") ); + QHBox *page = makeHBoxMainWidget(); + new QLabel( i18n( "Position:" ), page ); + m_position= new KoUnitDoubleSpinBox( page, QMAX( 0.00, minPos ), QMAX( 0.00, maxPos ), 1, QMAX( 0.00, pos ), unit ); + m_position->setFocus(); +} + + +KoGuideLineDia::KoGuideLineDia( QWidget *parent, KoPoint &pos, KoRect &rect, + KoUnit::Unit unit, const char *name ) +: KDialogBase( parent, name , true, "", Ok | Cancel, Ok, true ) +, m_rect( rect ) +, m_pos( pos ) +, m_positionChanged( false ) +, m_hButton( 0 ) +, m_vButton( 0 ) +{ + setCaption( i18n("Add Guide Line") ); + QVBox * vbox = makeVBoxMainWidget(); + + QButtonGroup *group = new QButtonGroup( 1, QGroupBox::Horizontal, i18n( "Orientation" ), vbox ); + group->setRadioButtonExclusive( true ); + //group->layout(); + m_hButton = new QRadioButton( i18n( "Horizontal" ), group ); + m_vButton = new QRadioButton( i18n( "Vertical" ), group ); + + connect( group, SIGNAL( clicked( int ) ), this, SLOT( slotOrientationChanged() ) ); + + m_vButton->setChecked( true );; + + QHBox *hbox = new QHBox( vbox ); + QLabel *label = new QLabel( i18n( "&Position:" ), hbox ); + m_position= new KoUnitDoubleSpinBox( hbox, QMAX( 0.0, m_rect.left() ), QMAX( 0.0, m_rect.right() ), 1, QMAX( 0.0, pos.x() ), unit ); + m_position->setFocus(); + label->setBuddy( m_position ); + + connect( m_position, SIGNAL( valueChanged( double ) ), this, SLOT( slotPositionChanged() ) ); +} + + +double KoGuideLineDia::pos() const +{ + return m_position->value(); +} + + +Qt::Orientation KoGuideLineDia::orientation() const +{ + Qt::Orientation o = Qt::Horizontal; + if ( m_vButton && m_vButton->isChecked() ) + { + o = Qt::Vertical; + } + return o; +} + + +void KoGuideLineDia::slotOrientationChanged() +{ + if ( m_hButton && m_vButton ) + { + if ( m_hButton->isChecked() ) + { + m_position->setMinValue( QMAX( 0.0, m_rect.top() ) ); + m_position->setMaxValue( QMAX( 0.0, m_rect.bottom() ) ); + if ( ! m_positionChanged ) + { + disconnect( m_position, SIGNAL( valueChanged( double ) ), this, SLOT( slotPositionChanged() ) ); + m_position->changeValue( m_pos.y() ); + connect( m_position, SIGNAL( valueChanged( double ) ), this, SLOT( slotPositionChanged() ) ); + } + } + else if ( m_vButton->isChecked() ) + { + m_position->setMinValue( QMAX( 0.0, m_rect.left() ) ); + m_position->setMaxValue( QMAX( 0.0, m_rect.right() ) ); + if ( ! m_positionChanged ) + { + disconnect( m_position, SIGNAL( valueChanged( double ) ), this, SLOT( slotPositionChanged() ) ); + m_position->changeValue( m_pos.x() ); + connect( m_position, SIGNAL( valueChanged( double ) ), this, SLOT( slotPositionChanged() ) ); + } + } + } +} + +void KoGuideLineDia::slotPositionChanged() +{ + m_positionChanged = true; +} +#include "KoGuideLineDia.moc" diff --git a/lib/kofficeui/KoGuideLineDia.h b/lib/kofficeui/KoGuideLineDia.h new file mode 100644 index 00000000..8545f35d --- /dev/null +++ b/lib/kofficeui/KoGuideLineDia.h @@ -0,0 +1,96 @@ +// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* This file is part of the KDE project + Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com> + Copyright (C) 2005 Thorsten Zachmann <zachmann@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. +*/ + +#ifndef KOGUIDELINEDIA_H +#define KOGUIDELINEDIA_H + +#include <kdialogbase.h> +#include <KoUnit.h> +#include "KoRect.h" +#include "KoPoint.h" + + +class KoUnitDoubleSpinBox; +class QRadioButton; + +/** + * @brief Class for setting a guide line position. + */ +class KoGuideLineDia : public KDialogBase +{ + Q_OBJECT +public: + /** + * @brief Constructor + * + * @param parent The parent widget + * @param pos the actual position of the guide line + * @param minPos the minimal position of the guide line + * @param maxPos the maximal position of the guide line + * @param unit The unit used in the document + * @param name The name is send to the QObject constructor + */ + KoGuideLineDia( QWidget *parent, double pos, double minPos, double maxPos, + KoUnit::Unit unit, const char *name = 0L ); + + /** + * @brief Constructor + * + * This shows a dialog to add a guide line. As long the position is not changed + * and the orientation of the guide line is changed the value will be set to pos.x() + * or pos.y() according to the orientation. + * + * @param parent the parent widget + * @param pos the actual position of cursor + * @param rect the rect in where the guide can be placed + * @param unit the unit used in the document + * @param name the name is send to the QObject constructor + */ + KoGuideLineDia( QWidget *parent, KoPoint &pos, KoRect &rect, + KoUnit::Unit unit, const char *name = 0L ); + /** + * @brief the position + * + * @return the value of the position input + */ + double pos() const; + + /** + * @brief the orientation + * + * @return the orientation of the added guide line + */ + Qt::Orientation orientation() const; + +protected slots: + void slotOrientationChanged(); + void slotPositionChanged(); + +protected: + KoRect m_rect; + KoPoint m_pos; + bool m_positionChanged; + QRadioButton * m_hButton; + QRadioButton * m_vButton; + KoUnitDoubleSpinBox* m_position; +}; + +#endif // KOGUIDELINEDIA_H diff --git a/lib/kofficeui/KoGuides.cpp b/lib/kofficeui/KoGuides.cpp new file mode 100644 index 00000000..f6d375f6 --- /dev/null +++ b/lib/kofficeui/KoGuides.cpp @@ -0,0 +1,926 @@ +// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* This file is part of the KDE project + Copyright (C) 2005 Thorsten Zachmann <zachmann@kde.org> + Copyright (C) 2005 Casper Boemann Rasmussen <cbr@boemann.dk> + + 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 "KoGuides.h" + +#include <qcursor.h> +#include <qpainter.h> +#include <qpixmap.h> + +#include <klocale.h> +#include <kpopupmenu.h> + +#include <KoDocument.h> +#include <KoPoint.h> +#include <KoRect.h> +#include <KoView.h> +#include <KoZoomHandler.h> + +#include "KoGuideLineDia.h" + +class KoGuides::Popup : public KPopupMenu +{ +public: + Popup( KoGuides * guides ) + { + m_title = insertTitle( i18n( "Guide Line" ) ); + m_delete = insertItem( i18n( "&Delete" ), guides, SLOT( slotRemove() ) ); + m_seperator = insertSeparator(); + m_pos = insertItem( i18n( "&Set Position..." ), guides, SLOT( slotChangePosition() ) ); + } + + void update( int count ) + { + if ( count == 1 ) + { + changeTitle( m_title, i18n( "Guide Line" ) ); + setItemVisible( m_seperator, true ); + setItemVisible( m_pos, true ); + } + else + { + changeTitle( m_title, i18n( "Guide Lines" ) ); + setItemVisible( m_seperator, false ); + setItemVisible( m_pos, false ); + } + } +private: + int m_title; + int m_delete; + int m_seperator; + int m_pos; +}; + +const KoGuides::SnapStatus KoGuides::SNAP_NONE = 0; +const KoGuides::SnapStatus KoGuides::SNAP_HORIZ = 1; +const KoGuides::SnapStatus KoGuides::SNAP_VERT = 2; +const KoGuides::SnapStatus KoGuides::SNAP_BOTH = 3; + +KoGuides::KoGuides( KoView *view, KoZoomHandler *zoomHandler ) +: m_view( view ) +, m_zoomHandler( zoomHandler ) +{ + m_popup = new Popup( this ); + m_mouseSelected = false; +} + + +KoGuides::~KoGuides() +{ + delete m_popup; +} + + +void KoGuides::paintGuides( QPainter &painter ) +{ + //painter.setRasterOp( NotROP ); + const KoPageLayout& pl = m_view->koDocument()->pageLayout(); + int width = QMAX( m_view->canvas()->width(), m_zoomHandler->zoomItX( pl.ptWidth ) ); + int height = QMAX( m_view->canvas()->height(), m_zoomHandler->zoomItY( pl.ptHeight ) ); + + for ( int i = 0; i < GL_END; ++i ) + { + QValueList<KoGuideLine *>::iterator it = m_guideLines[i].begin(); + for ( ; it != m_guideLines[i].end(); ++it ) + { + if ( !( *it )->automatic || ( *it )->snapping ) // dont paint autoStyle guides when they are not snapping + { + if ( ( *it )->snapping ) + painter.setPen( QPen( green, 0, DotLine ) ); + else if ( ( *it )->selected ) + painter.setPen( QPen( red, 0, DotLine ) ); + else + painter.setPen( QPen( blue, 0, DotLine ) ); + + painter.save(); + if ( ( *it )->orientation == Qt::Vertical ) + { + painter.translate( m_zoomHandler->zoomItX( ( *it )->position ), 0 ); + painter.drawLine( 0, 0, 0, height ); + } + else + { + painter.translate( 0, m_zoomHandler->zoomItY( ( *it )->position ) ); + painter.drawLine( 0, 0, width, 0 ); + } + painter.restore(); + } + } + } +} + +bool KoGuides::mousePressEvent( QMouseEvent *e ) +{ + bool eventProcessed = true; + bool changed = false; + m_mouseSelected = false; + + KoPoint p( mapFromScreen( e->pos() ) ); + KoGuideLine * guideLine = find( p, m_zoomHandler->unzoomItY( 2 ) ); + if ( guideLine ) + { + m_lastPoint = e->pos(); + if ( e->button() == Qt::LeftButton || e->button() == Qt::RightButton ) + { + if ( e->button() == Qt::LeftButton ) + { + m_mouseSelected = true; + } + if ( e->state() & Qt::ControlButton ) + { + if ( guideLine->selected ) + { + unselect( guideLine ); + m_mouseSelected = false; + } + else + { + select( guideLine ); + } + changed = true; + } + else if ( ! guideLine->selected ) + { + unselectAll(); + select( guideLine ); + changed = true; + } + } + } + else + { + if ( !( e->state() & Qt::ControlButton ) ) + { + changed = unselectAll(); + } + eventProcessed = false; + } + + if ( changed || hasSelected() ) + { + emit moveGuides( true ); + } + + if ( changed ) + { + paint(); + } + + if ( changed && ! hasSelected() ) + { + emit moveGuides( false ); + } + + if ( e->button() == Qt::RightButton && hasSelected() ) + { + m_popup->update( m_guideLines[GL_SELECTED].count() ); + m_popup->exec( QCursor::pos() ); + emit moveGuides( false ); + } + + return eventProcessed; +} + + +bool KoGuides::mouseMoveEvent( QMouseEvent *e ) +{ + bool eventProcessed = false; + if ( m_mouseSelected ) + { + QPoint p( e->pos() ); + p -= m_lastPoint; + m_lastPoint = e->pos(); + moveSelectedBy( p ); + paint(); + emit guideLinesChanged( m_view ); + eventProcessed = true; + } + else if ( e->state() == Qt::NoButton ) + { + KoPoint p( mapFromScreen( e->pos() ) ); + KoGuideLine * guideLine = find( p, m_zoomHandler->unzoomItY( 2 ) ); + if ( guideLine ) + { + m_view->canvas()->setCursor( guideLine->orientation == Qt::Vertical ? Qt::sizeHorCursor : Qt::sizeVerCursor ); + eventProcessed = true; + } + } + return eventProcessed; +} + + +bool KoGuides::mouseReleaseEvent( QMouseEvent *e ) +{ + bool eventProcessed = false; + if ( m_mouseSelected ) + { + KoPoint p( mapFromScreen( e->pos() ) ); + if ( m_guideLines[GL_SELECTED].count() == 1 ) + { + int x1, y1, x2, y2; + m_view->canvas()->rect().coords( &x1, &y1, &x2, &y2 ); + QPoint gp( m_view->canvas()->mapFromGlobal( e->globalPos() ) ); + if ( m_guideLines[GL_SELECTED].first()->orientation == Qt::Vertical ) + { + if ( gp.x() < x1 || gp.x() > x2 ) + removeSelected(); + } + else + { + if ( gp.y() < y1 || gp.y() > y2 ) + removeSelected(); + } + } + KoGuideLine * guideLine = find( p, m_zoomHandler->unzoomItY( 2 ) ); + if ( guideLine ) + { + m_view->canvas()->setCursor( guideLine->orientation == Qt::Vertical ? Qt::sizeHorCursor : Qt::sizeVerCursor ); + } + m_mouseSelected = false; + eventProcessed = true; + emit guideLinesChanged( m_view ); + } + emit moveGuides( false ); + return eventProcessed; +} + + +bool KoGuides::keyPressEvent( QKeyEvent *e ) +{ + bool eventProcessed = false; + switch( e->key() ) + { + case Qt::Key_Delete: + if ( hasSelected() ) + { + removeSelected(); + paint(); + emit guideLinesChanged( m_view ); + eventProcessed = true; + } + break; + default: + break; + } + return eventProcessed; +} + +void KoGuides::setGuideLines( const QValueList<double> &horizontalPos, const QValueList<double> &verticalPos ) +{ + removeSelected(); + + QValueList<KoGuideLine *>::iterator it = m_guideLines[GL].begin(); + for ( ; it != m_guideLines[GL].end(); ++it ) + { + delete ( *it ); + } + m_guideLines[GL].clear(); + + QValueList<double>::ConstIterator posIt = horizontalPos.begin(); + for ( ; posIt != horizontalPos.end(); ++posIt ) + { + KoGuideLine *guideLine = new KoGuideLine( Qt::Horizontal, *posIt, false ); + m_guideLines[GL].append( guideLine ); + } + posIt = verticalPos.begin(); + for ( ; posIt != verticalPos.end(); ++posIt ) + { + KoGuideLine *guideLine = new KoGuideLine( Qt::Vertical, *posIt, false ); + m_guideLines[GL].append( guideLine ); + } + paint(); +} + +void KoGuides::setAutoGuideLines( const QValueList<double> &horizontalPos, const QValueList<double> &verticalPos ) +{ + QValueList<KoGuideLine *>::iterator it = m_guideLines[GL_AUTOMATIC].begin(); + for ( ; it != m_guideLines[GL_AUTOMATIC].end(); ++it ) + { + delete ( *it ); + } + m_guideLines[GL_AUTOMATIC].clear(); + + QValueList<double>::ConstIterator posIt = horizontalPos.begin(); + for ( ; posIt != horizontalPos.end(); ++posIt ) + { + KoGuideLine *guideLine = new KoGuideLine( Qt::Horizontal, *posIt, true ); + m_guideLines[GL_AUTOMATIC].append( guideLine ); + } + posIt = verticalPos.begin(); + for ( ; posIt != verticalPos.end(); ++posIt ) + { + KoGuideLine *guideLine = new KoGuideLine( Qt::Vertical, *posIt, true ); + m_guideLines[GL_AUTOMATIC].append( guideLine ); + } +} + + +void KoGuides::getGuideLines( QValueList<double> &horizontalPos, QValueList<double> &verticalPos ) const +{ + horizontalPos.clear(); + verticalPos.clear(); + + QValueList<KoGuideLine *>::const_iterator it = m_guideLines[GL].begin(); + for ( ; it != m_guideLines[GL].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Horizontal ) + { + horizontalPos.append( ( *it )->position ); + } + else + { + verticalPos.append( ( *it )->position ); + } + } + it = m_guideLines[GL_SELECTED].begin(); + for ( ; it != m_guideLines[GL_SELECTED].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Horizontal ) + { + horizontalPos.append( ( *it )->position ); + } + else + { + verticalPos.append( ( *it )->position ); + } + } +} + + +void KoGuides::snapToGuideLines( KoRect &rect, int snap, SnapStatus &snapStatus, KoPoint &diff ) +{ + if( !(snapStatus & SNAP_VERT)) + diff.setX(10000); + if( !(snapStatus & SNAP_HORIZ)) + diff.setY(10000); + + for ( int i = 0; i < GL_END; ++i ) + { + QValueList<KoGuideLine *>::const_iterator it = m_guideLines[i].begin(); + for ( ; it != m_guideLines[i].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Horizontal ) + { + double tmp = (*it)->position - rect.top(); + if ( snapStatus & SNAP_HORIZ || QABS( tmp ) < m_zoomHandler->unzoomItY( snap ) ) + { + if(QABS( tmp ) < QABS(diff.y())) + { + diff.setY( tmp ); + snapStatus |= SNAP_HORIZ; + } + } + tmp = (*it)->position - rect.bottom(); + if ( snapStatus & SNAP_HORIZ || QABS( tmp ) < m_zoomHandler->unzoomItY( snap ) ) + { + if(QABS( tmp ) < QABS(diff.y())) + { + diff.setY( tmp ); + snapStatus |= SNAP_HORIZ; + } + } + } + else + { + double tmp = (*it)->position - rect.left(); + if ( snapStatus & SNAP_VERT || QABS( tmp ) < m_zoomHandler->unzoomItX( snap ) ) + { + if(QABS( tmp ) < QABS(diff.x())) + { + diff.setX( tmp ); + snapStatus |= SNAP_VERT; + } + } + tmp = (*it)->position - rect.right(); + if ( snapStatus & SNAP_VERT || QABS( tmp ) < m_zoomHandler->unzoomItX( snap ) ) + { + if(QABS( tmp ) < QABS(diff.x())) + { + diff.setX( tmp ); + snapStatus |= SNAP_VERT; + } + } + } + } + } + + if(!(snapStatus & SNAP_VERT)) + diff.setX( 0 ); + + if(!(snapStatus & SNAP_HORIZ)) + diff.setY( 0 ); +} + +void KoGuides::snapToGuideLines( KoPoint &pos, int snap, SnapStatus &snapStatus, KoPoint &diff ) +{ + if( !(snapStatus & SNAP_VERT)) + diff.setX(10000); + if( !(snapStatus & SNAP_HORIZ)) + diff.setY(10000); + + for ( int i = 0; i < GL_END; ++i ) + { + QValueList<KoGuideLine *>::const_iterator it = m_guideLines[i].begin(); + for ( ; it != m_guideLines[i].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Horizontal ) + { + double tmp = (*it)->position - pos.y(); + if ( snapStatus & SNAP_HORIZ || QABS( tmp ) < m_zoomHandler->unzoomItY( snap ) ) + { + if(QABS( tmp ) < QABS(diff.y())) + { + diff.setY( tmp ); + snapStatus |= SNAP_HORIZ; + } + } + } + else + { + double tmp = (*it)->position - pos.x(); + if ( snapStatus & SNAP_VERT || QABS( tmp ) < m_zoomHandler->unzoomItX( snap ) ) + { + if(QABS( tmp ) < QABS(diff.x())) + { + diff.setX( tmp ); + snapStatus |= SNAP_VERT; + } + } + } + } + } + + if(!(snapStatus & SNAP_VERT)) + diff.setX( 0 ); + + if(!(snapStatus & SNAP_HORIZ)) + diff.setY( 0 ); +} + + +void KoGuides::repaintSnapping( const KoRect &snappedRect ) +{ + bool needRepaint = false; + for ( int i = 0; i < GL_END; ++i ) + { + QValueList<KoGuideLine *>::const_iterator it = m_guideLines[i].begin(); + for ( ; it != m_guideLines[i].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Horizontal ) + { + if ( virtuallyEqual( snappedRect.top(), (*it)->position ) + || virtuallyEqual( snappedRect.bottom(), ( *it )->position ) ) + { + if ( ! ( *it )->snapping ) + { + ( *it )->snapping = true; + needRepaint = true; + } + } + else if ( ( *it )->snapping ) + { + ( *it )->snapping = false; + needRepaint = true; + } + } + else + { + if ( virtuallyEqual( snappedRect.left(), (*it)->position ) + || virtuallyEqual( snappedRect.right(), ( *it )->position ) ) + { + if ( ! ( *it )->snapping ) + { + ( *it )->snapping = true; + needRepaint = true; + } + } + else if ( ( *it )->snapping ) + { + ( *it )->snapping = false; + needRepaint = true; + } + } + } + } + + if ( needRepaint ) + { + emit paintGuides( true ); + paint(); + emit paintGuides( false ); + } +} + + +void KoGuides::repaintSnapping( const KoPoint &snappedPoint, SnapStatus snapStatus ) +{ + bool needRepaint = false; + for ( int i = 0; i < GL_END; ++i ) + { + QValueList<KoGuideLine *>::const_iterator it = m_guideLines[i].begin(); + for ( ; it != m_guideLines[i].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Horizontal && ( snapStatus & SNAP_HORIZ ) ) + { + if( virtuallyEqual( snappedPoint.y(), (*it)->position ) ) + { + if ( ! ( *it )->snapping ) + { + ( *it )->snapping = true; + needRepaint = true; + } + } + else if ( ( *it )->snapping ) + { + ( *it )->snapping = false; + needRepaint = true; + } + } + else + { + if ( snapStatus & SNAP_VERT ) + { + if( virtuallyEqual( snappedPoint.x(), (*it)->position ) ) + { + if ( ! ( *it )->snapping ) + { + ( *it )->snapping = true; + needRepaint = true; + } + } + else if ( ( *it )->snapping ) + { + ( *it )->snapping = false; + needRepaint = true; + } + } + } + } + } + + if ( needRepaint ) + { + emit paintGuides( true ); + paint(); + emit paintGuides( false ); + } +} + + +void KoGuides::repaintAfterSnapping() +{ + bool needRepaint = false; + + for ( int i = 0; i < GL_END; ++i ) + { + QValueList<KoGuideLine *>::const_iterator it = m_guideLines[i].begin(); + for ( ; it != m_guideLines[i].end(); ++it ) + { + if ( ( *it )->snapping ) + { + needRepaint = true; + ( *it )->snapping = false; + } + } + } + + if ( needRepaint ) + { + emit paintGuides( true ); + paint(); + emit paintGuides( false ); + } +} + + +void KoGuides::diffNextGuide( KoRect &rect, KoPoint &diff ) +{ + for ( int i = 0; i < GL_END; ++i ) + { + QValueList<KoGuideLine *>::const_iterator it = m_guideLines[i].begin(); + for ( ; it != m_guideLines[i].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Horizontal ) + { + double moveyl = ( *it )->position - rect.top(); + double moveyr = ( *it )->position - rect.bottom(); + if ( diff.y() > 0 ) + { + if ( moveyl < diff.y() && moveyl > 1E-10 ) + { + diff.setY( moveyl ); + } + if ( moveyr < diff.y() && moveyr > 1E-10 ) + { + diff.setY( moveyr ); + } + } + else if ( diff.y() < 0 ) + { + if ( moveyl > diff.y() && moveyl < -1E-10 ) + { + diff.setY( moveyl ); + } + if ( moveyr > diff.y() && moveyr < -1E-10 ) + { + diff.setY( moveyr ); + } + } + } + else + { + double movexl = ( *it )->position - rect.left(); + double movexr = ( *it )->position - rect.right(); + if ( diff.x() > 0 ) + { + if ( movexl < diff.x() && movexl > 1E-10 ) + { + diff.setX( movexl ); + } + if ( ( movexr < diff.x() ) && movexr > 1E-10 ) + { + diff.setX( movexr ); + } + } + else if ( diff.x() < 0 ) + { + if ( movexl > diff.x() && movexl < -1E-10 ) + { + diff.setX( movexl ); + } + if ( movexr > diff.x() && movexr < -1E-10 ) + { + diff.setX( movexr ); + } + } + } + } + } +} + + +void KoGuides::moveGuide( const QPoint &pos, bool horizontal, int rulerWidth ) +{ + int x = pos.x() - rulerWidth; + int y = pos.y() - rulerWidth; + QPoint p( x, y ); + if ( !m_insertGuide ) + { + if ( ! horizontal && x > 0 ) + { + m_insertGuide = true; + add( Qt::Vertical, p ); + } + else if ( horizontal && y > 0 ) + { + m_insertGuide = true; + add( Qt::Horizontal, p ); + } + if ( m_insertGuide ) + { + QMouseEvent e( QEvent::MouseButtonPress, p, Qt::LeftButton, Qt::LeftButton ); + mousePressEvent( &e ); + } + } + else + { + QMouseEvent e( QEvent::MouseMove, p, Qt::NoButton, Qt::LeftButton ); + mouseMoveEvent( &e ); + } +} + + +void KoGuides::addGuide( const QPoint &pos, bool /* horizontal */, int rulerWidth ) +{ + int x = pos.x() - rulerWidth; + int y = pos.y() - rulerWidth; + QPoint p( x, y ); + m_insertGuide = false; + QMouseEvent e( QEvent::MouseButtonRelease, p, Qt::LeftButton, Qt::LeftButton ); + mouseReleaseEvent( &e ); +} + + +void KoGuides::slotChangePosition() +{ + KoPoint p( mapFromScreen( m_lastPoint ) ); + KoGuideLine * guideLine = find( p, m_zoomHandler->unzoomItY( 2 ) ); + + const KoPageLayout& pl = m_view->koDocument()->pageLayout(); + double max = 0.0; + if ( guideLine->orientation == Qt::Vertical ) + { + max = QMAX( pl.ptWidth, m_zoomHandler->unzoomItX( m_view->canvas()->size().width() + m_view->canvasXOffset() - 1 ) ); + } + else + { + max = QMAX( pl.ptHeight, m_zoomHandler->unzoomItY( m_view->canvas()->size().height() + m_view->canvasYOffset() - 1 ) ); + } + + KoGuideLineDia dia( 0, guideLine->position, 0.0, max, m_view->koDocument()->unit() ); + if ( dia.exec() == QDialog::Accepted ) + { + guideLine->position = dia.pos(); + paint(); + emit guideLinesChanged( m_view ); + } +} + + +void KoGuides::slotRemove() +{ + removeSelected(); + paint(); +} + + +void KoGuides::paint() +{ + m_view->canvas()->repaint( false ); +} + + +void KoGuides::add( Qt::Orientation o, QPoint &pos ) +{ + KoPoint p( mapFromScreen( pos ) ); + KoGuideLine *guideLine = new KoGuideLine( o, o == Qt::Vertical ? p.x(): p.y() ); + m_guideLines[GL].append( guideLine ); +} + + +void KoGuides::select( KoGuideLine *guideLine ) +{ + guideLine->selected = true; + if ( m_guideLines[GL].remove( guideLine ) == 1 ) + { + m_guideLines[GL_SELECTED].append( guideLine ); + } +} + + +void KoGuides::unselect( KoGuideLine *guideLine ) +{ + guideLine->selected = false; + if ( m_guideLines[GL_SELECTED].remove( guideLine ) == 1 ) + { + m_guideLines[GL].append( guideLine ); + } +} + + +bool KoGuides::unselectAll() +{ + bool selected = m_guideLines[GL_SELECTED].empty() == false; + + QValueList<KoGuideLine *>::iterator it = m_guideLines[GL_SELECTED].begin(); + for ( ; it != m_guideLines[GL_SELECTED].end(); ++it ) + { + ( *it )->selected = false; + m_guideLines[GL].append( *it ); + } + m_guideLines[GL_SELECTED].clear(); + + return selected; +} + + +void KoGuides::removeSelected() +{ + QValueList<KoGuideLine *>::iterator it = m_guideLines[GL_SELECTED].begin(); + for ( ; it != m_guideLines[GL_SELECTED].end(); ++it ) + { + delete ( *it ); + } + m_guideLines[GL_SELECTED].clear(); +} + + +bool KoGuides::hasSelected() +{ + return m_guideLines[GL_SELECTED].empty() == false; +} + + +KoGuides::KoGuideLine * KoGuides::find( KoPoint &p, double diff ) +{ + QValueList<KoGuideLine *>::iterator it = m_guideLines[GL_SELECTED].begin(); + for ( ; it != m_guideLines[GL_SELECTED].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Vertical && QABS( ( *it )->position - p.x() ) < diff ) + { + return *it; + } + if ( ( *it )->orientation == Qt::Horizontal && QABS( ( *it )->position - p.y() ) < diff ) + { + return *it; + } + } + + it = m_guideLines[GL].begin(); + for ( ; it != m_guideLines[GL].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Vertical && QABS( ( *it )->position - p.x() ) < diff ) + { + return *it; + } + if ( ( *it )->orientation == Qt::Horizontal && QABS( ( *it )->position - p.y() ) < diff ) + { + return *it; + } + } + return 0; +} + + +void KoGuides::moveSelectedBy( QPoint &p ) +{ + KoPoint point( m_zoomHandler->unzoomPoint( p ) ); + if ( m_guideLines[GL_SELECTED].count() > 1 ) + { + const KoPageLayout& pl = m_view->koDocument()->pageLayout(); + double right = QMAX( pl.ptWidth, m_zoomHandler->unzoomItX( m_view->canvas()->width() + m_view->canvasXOffset() - 1 ) ); + double bottom = QMAX( pl.ptHeight, m_zoomHandler->unzoomItY( m_view->canvas()->height() + m_view->canvasYOffset() - 1 ) ); + + QValueList<KoGuideLine *>::iterator it = m_guideLines[GL_SELECTED].begin(); + for ( ; it != m_guideLines[GL_SELECTED].end(); ++it ) + { + if ( ( *it )->orientation == Qt::Vertical ) + { + double tmp = ( *it )->position + point.x(); + if ( tmp < 0 ) + { + point.setX( point.x() - tmp ); + } + else if ( tmp > right ) + { + point.setX( point.x() - ( tmp - right ) ); + } + } + else + { + double tmp = ( *it )->position + point.y(); + if ( tmp < 0 ) + { + point.setY( point.y() - tmp ); + } + else if ( tmp > bottom ) + { + point.setY( point.y() - ( tmp - bottom ) ); + } + } + } + } + QValueList<KoGuideLine *>::iterator it = m_guideLines[GL_SELECTED].begin(); + for ( ; it != m_guideLines[GL_SELECTED].end(); ++it ) + { + ( *it )->snapping = false; + + if ( ( *it )->orientation == Qt::Vertical && p.x() != 0 ) + { + ( *it )->position = ( *it )->position + point.x(); + } + else if ( ( *it )->orientation == Qt::Horizontal && p.y() != 0 ) + { + ( *it )->position = ( *it )->position + point.y(); + } + } +} + + +KoPoint KoGuides::mapFromScreen( const QPoint & pos ) +{ + int x = pos.x() + m_view->canvasXOffset(); + int y = pos.y() + m_view->canvasYOffset(); + double xf = m_zoomHandler->unzoomItX( x ); + double yf = m_zoomHandler->unzoomItY( y ); + return KoPoint( xf, yf ); +} + + +QPoint KoGuides::mapToScreen( const KoPoint & pos ) +{ + int x = m_zoomHandler->zoomItX( pos.x() ) - m_view->canvasXOffset(); + int y = m_zoomHandler->zoomItY( pos.y() ) - m_view->canvasYOffset(); + return QPoint( x, y ); +} + + +#include "KoGuides.moc" diff --git a/lib/kofficeui/KoGuides.h b/lib/kofficeui/KoGuides.h new file mode 100644 index 00000000..c084c013 --- /dev/null +++ b/lib/kofficeui/KoGuides.h @@ -0,0 +1,421 @@ +// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* This file is part of the KDE project + Copyright (C) 2005 Thorsten Zachmann <zachmann@kde.org> + Copyright (C) 2005 Casper Boemann Rasmussen <cbr@boemann.dk> + + 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. +*/ + +#ifndef KOGUIDES_H +#define KOGUIDES_H + +#include <qevent.h> +#include <qobject.h> + +#include <koffice_export.h> + +class QPaintDevice; +class KoPoint; +class KoRect; +class KoView; +class KoZoomHandler; + +class KOFFICEUI_EXPORT KoGuides : public QObject +{ + Q_OBJECT +public: + /** + * @brief Constructor + * + * @param view The view in which the guides will be shown + * @param zoomHandler The zoom handler of the view + */ + KoGuides( KoView *view, KoZoomHandler *zoomHandler ); + + /** + * @brief Destructor + */ + ~KoGuides(); + + /** + * @brief Paint the guides + * + * @param painter with which the guides are painted + */ + void paintGuides( QPainter &painter ); + + typedef int SnapStatus; + static const SnapStatus SNAP_NONE, SNAP_HORIZ, SNAP_VERT, SNAP_BOTH; + + /** + * @brief Handle mousePressEvent + * + * This checks if a mousePressEvent would affect a guide line. + * If the mouse is pressed over a guide line it gets selected. + * Guide lines which were select get unselect. + * If also the Ctrl Key is pressed the selection of the guide + * gets toggled. + * If no guide is under the position all guides get deselected. + * + * @param e QMouseEvent + * + * @return true if the event was handled + * @return false otherwise + * The event counts a not handled when only guides where + * deselected. + */ + bool mousePressEvent( QMouseEvent *e ); + + /** + * @brief Handle mouseMoveEvent + * + * If the mouse button is pressed and a guide was selected it moves the + * selected guides. + * If the mouse is moved over a guide line the cursor gets updated. + * + * @param e QMouseEvent + * + * @return true if the event was handled (guide moved, cursor changed as + * guide lies below) + * @return false otherwise + */ + bool mouseMoveEvent( QMouseEvent *e ); + + /** + * + * @param e QMouseEvent + * + * @return true if the event was handled + * @return false otherwise + */ + bool mouseReleaseEvent( QMouseEvent *e ); + + /** + * + * @param e QKeyEvent + * + * @return true if the event was handled + * @return false otherwise + */ + bool keyPressEvent( QKeyEvent *e ); + + /** + * @brief Set the guide lines. + * + * This removes all existing guides and set up new ones at the positions given. + * + * @param horizontalPos A list of the position of the horizontal guide lines. + * @param verticalPos A list of the position of the vertical guide lines. + */ + void setGuideLines( const QValueList<double> &horizontalPos, const QValueList<double> &verticalPos ); + + /** + * @brief Set the positions for snapping of auto guide lines + * + * This removes all existing auto guide lines and set up new ones at the positions given. + * + * @param horizontalPos A list of the position of the horizontal guide lines. + * @param verticalPos A list of the position of the vertical guide lines. + */ + void setAutoGuideLines( const QValueList<double> &horizontalPos, const QValueList<double> &verticalPos ); + + /** + * @brief Get the position of the guide lines + * + * This filles the passed lists with the positions of the guide lines. + * The lists will be emptied before any positions are added. + * + * @param horizontalPos A list of the position of the horizontal guide lines. + * @param verticalPos A list of the position of the vertical guide lines. + */ + void getGuideLines( QValueList<double> &horizontalPos, QValueList<double> &verticalPos ) const; + + /** + * @brief Snap rect to guidelines + * + * This looks for a guide which is in reach for the guide as defined in snap. + * This method has the abillity to combine more calls. The snapStatus and diff args are both input and + * output. On first call you should set snapStatus to 0. The return value would then show in which + * directions it has snapped. If you combine several KoGuides you can let these output arguments + * be input for the next koGuide. That way you'll always catch the nearest guide. + * + * @param rect the rect which should be snapped + * @param snap the distance within the guide should snap - but always snap if already snapped + * @param snapStatus if horiz,vert or both directions are snapped (both in and out param). + * @param diff distance away from guide. Only valid if status is snapping (both in and out param) + */ + void snapToGuideLines( KoRect &rect, int snap, SnapStatus &snapStatus, KoPoint &diff ); + + /** + * @brief Snap rect to guidelines + * + * This looks fo a guide which is in reach for the guide as defined in snap. + * + * @param pos the position which should be snapped + * @param snap the distance wherein the guide should snap - but always snap if already snapped + * @param snapStatus if horiz,vert or both directions are snapped (both in and out param) + * @param diff distance away from guide. Only valid if status is snapping (both in and out param) + */ + void snapToGuideLines( KoPoint &pos, int snap, SnapStatus &snapStatus, KoPoint &diff ); + + /** + * @brief repaint guides if any changed snapping status + * + * This issues a paint request if any guides have changed snapping status. + * + * @param snappedRect the rect after it has been snapped + */ + void repaintSnapping( const KoRect &snappedRect ); + + /** + * @brief repaint guides if any changed snapping status + * + * This issues a paint request if any guides have changed snapping status. + * + * @param snappedPoint the point after it has been snapped + */ + void repaintSnapping( const KoPoint &snappedPoint, SnapStatus snapStatus ); + + /** + * @brief repaint guides so none is snapped + * + * This issues a paint request if any guides have changed snapping status. + * It also effectively un-snaps all since it doesn't take an argument + */ + void repaintAfterSnapping( ); + + /** + * @brief Find the closesed disance to the next guide within the given distance + * + * @param rect The rect which should be snapped + * @param diff distance in which too look for the closesed guide. The parameter is updated + * with the closesed distance to a guide if one is found (both in and out param) + */ + void diffNextGuide( KoRect &rect, KoPoint &diff ); + +public slots: + /** + * @brief Move Guide + * + * This slot can be connected to void KoRuler::moveGuide( const QPoint &, bool, int ); + * It will add a new guide when you move from the ruler to the canvas. After that it + * moves the guide. + * + * @param pos The pos of the mouse + * @param horizontal true if the guide is horizontal, false if vertical + * @param rulerWidth The witdth of the ruler as the pos is seen from the ruler widget. + */ + void moveGuide( const QPoint &pos, bool horizontal, int rulerWidth ); + + /** + * @brief Add Guide + * + * This slot can be connected to void KoRuler::addGuide( const QPoint &, bool, int ); + * It will finish the inserting of a guide from moveGuide(). + * + * @param pos The pos of the mouse + * @param horizontal true if the guide is horizontal, false if vertical + * @param rulerWidth The witdth of the ruler as the pos is seen from the ruler widget. + */ + void addGuide( const QPoint &pos, bool horizontal, int rulerWidth ); + +signals: + /** + * @brief Signal that shows that the guide lines are changed + * + * This signal is emmited when the guide lines are changed ( moved / deleted ) + * + * @param view The view in which the guide lines are changed. + */ + void guideLinesChanged( KoView * view ); + + /** + * @brief This signal is emitted when guides start/stop moving. + * + * @param state true when starting moving guides, false when stopping. + */ + void moveGuides( bool state ); + + /** + * @brief This signal is emitted when guides start/stop painting. + * + * With this signal it is possible to only repaint the guides in the paint + * method of the canvas. Just set/unset a flag when this signal is emmited. + * This signal is emitted before and after a repaint is done. + * + * @param state true when starting painting guides, false when stopping. + */ + void paintGuides( bool state ); + +private slots: + /** + * @brief Execute a dialog to set the position of the guide + */ + void slotChangePosition(); + + /** + * @brief remove all selected guides + */ + void slotRemove(); + +private: + /// Strukt holding the data of a guide line + struct KoGuideLine + { + KoGuideLine( Qt::Orientation o, double pos, bool a = false ) + : orientation( o ) + , position( pos ) + , selected( false ) + , snapping( false ) + , automatic( a ) + {} + Qt::Orientation orientation; + double position; + bool selected; // if this guide is selected + bool snapping; // if this guide is being snapped to + bool automatic; // if this is a atomatic guide line + }; + + /** + * @brief Paint the canvas + */ + void paint(); + + /** + * @brief Add a guide line with the orientation o at the position pos + * + * @param pos where to insert the guide + * @param o orientation of the guide line + */ + void add( Qt::Orientation o, QPoint &pos ); + + /** + * @brief Select a guide + * + * @param gd guide to select + */ + void select( KoGuideLine *guideLine ); + + /** + * @brief Unselect a guide + * + * @param gd guide to unselect + */ + void unselect( KoGuideLine *guideLine ); + + /** + * @brief Unselect all selected KoGuideLineData + * + * @return true, when selection was changed + * @return false otherwise + */ + bool unselectAll(); + + /** + * @brief remove all selected guides + */ + void removeSelected(); + + /** + * @brief Check if at least one guide is selected + * + * @return true if at least on guide is seleted + * @return false otherwise + */ + bool hasSelected(); + + /** + * @brief Find a guide + * + * This function looks for a guide at x or y pos. The position can differ by + * diff. + * + * @param x x position to look for a guide + * @param y y position to look for a guide + * @param diff how far next to a guide sould it also be found + * + * @return the fould guide + * @return 0 if none is found + */ + KoGuideLine * find( KoPoint &p, double diff ); + + /** + * @brief Move selected guides. + * + * This moves all selected guides around. If more than one guide is selected it makes + * sure the guides are not moved of the canvas. + * + * @param pos position of the mouse + */ + void moveSelectedBy( QPoint &p ); + + /** + * @brief Map pos from screen + * + * @param pos on screen + * + * @return pos in document + */ + KoPoint mapFromScreen( const QPoint & pos ); + + /** + * @brief Map pos to screen + * + * @param pos in document + * + * @return pos on screen + */ + QPoint mapToScreen( const KoPoint & pos ); + + /** + * @brief Check if the both values are nearly the same. + * + * @param a first value + * @param a second value + * + * @return true if they are the same + * @return false otherwise + */ + bool virtuallyEqual( double a, double b ) { return QABS( a - b ) < 1E-4; } + + /// view + KoView * m_view; + /// zoom handler of the view + KoZoomHandler * m_zoomHandler; + + enum GuideLineType + { + GL, + GL_SELECTED, + GL_AUTOMATIC, + GL_END + }; + + /// array of list of the different guide line types + QValueList<KoGuideLine *> m_guideLines[GL_END]; + + /// used to save the last mouse position + QPoint m_lastPoint; + /// true if a guide is selected at the moment + bool m_mouseSelected; + /// true if a guide is inserted at the moment + bool m_insertGuide; + /// popup menu + class Popup; + Popup * m_popup; +}; + +#endif /* KOGUIDES_H */ diff --git a/lib/kofficeui/KoImageResource.cpp b/lib/kofficeui/KoImageResource.cpp new file mode 100644 index 00000000..9f92ef3d --- /dev/null +++ b/lib/kofficeui/KoImageResource.cpp @@ -0,0 +1,117 @@ +/* + * koImageResource.cc - part of KOffice + * + * Copyright (c) 2005 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;version 2. + * + * 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 "KoImageResource.h" + +namespace { + /* XPM -- copyright The Gimp */ + const char *chain_broken_24[] = { + /* columns rows colors chars-per-pixel */ + "9 24 10 1", + " c black", + ". c #020204", + "X c #5A5A5C", + "o c gray43", + "O c #8F8F91", + "+ c #9A9A98", + "@ c #B5B5B6", + "# c #D0D0D1", + "$ c #E8E8E9", + "% c None", + /* pixels */ + "%%.....%%", + "%.o##@X.%", + "%.+...$.%", + "%.#.%.#.%", + "%.#.%.#.%", + "%.@.%.#.%", + "%.+...#.%", + "%.O.o.O.%", + "%%..@..%%", + "%%%.#.%%%", + "%%%%%%%%%", + "%%%%%%%%%", + "%%%%%%%%%", + "%%%%%%%%%", + "%%%.#.%%%", + "%%..#..%%", + "%.o.@.O.%", + "%.@...@.%", + "%.@.%.$.%", + "%.@.%.$.%", + "%.@.%.$.%", + "%.#...$.%", + "%.o$#$@.%", + "%%.....%%" + }; + + /* XPM -- copyright The Gimp */ + const char *chain_24[] = { + /* columns rows colors chars-per-pixel */ + "9 24 10 1", + " c black", + ". c #020204", + "X c #5A5A5C", + "o c gray43", + "O c #8F8F91", + "+ c #9A9A98", + "@ c #B5B5B6", + "# c #D0D0D1", + "$ c #E8E8E9", + "% c None", + /* pixels */ + "%%%%%%%%%", + "%%%%%%%%%", + "%%.....%%", + "%.o##@X.%", + "%.+...$.%", + "%.#.%.#.%", + "%.#.%.#.%", + "%.@.%.#.%", + "%.+...#.%", + "%.O.o.O.%", + "%%..@..%%", + "%%%.#.%%%", + "%%%.#.%%%", + "%%..#..%%", + "%.o.@.O.%", + "%.@...@.%", + "%.@.%.$.%", + "%.@.%.$.%", + "%.@.%.$.%", + "%.#...$.%", + "%.o$#$@.%", + "%%.....%%", + "%%%%%%%%%", + "%%%%%%%%%" + }; +} + +KoImageResource::KoImageResource() {} + +const char** KoImageResource::chain() +{ + return chain_24; +} + +const char** KoImageResource::chainBroken() +{ + return chain_broken_24; +} diff --git a/lib/kofficeui/KoImageResource.h b/lib/kofficeui/KoImageResource.h new file mode 100644 index 00000000..97781c91 --- /dev/null +++ b/lib/kofficeui/KoImageResource.h @@ -0,0 +1,38 @@ +/* + * koImageResource.h - part of KOffice + * + * Copyright (c) 2005 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;version 2. + * + * 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. + */ + +#ifndef __ko_imageresource__ +#define __ko_imageresource__ +#include <koffice_export.h> + +class KOFFICEUI_EXPORT KoImageResource +{ + +public: + + KoImageResource(); + + /// returns a 24 pixels xpm-format image of a chain. + const char** chain(); + /// returns a 24 pixels xpm-format image of a broken chain. + const char** chainBroken(); +}; +#endif // __ko_imageresource__ + diff --git a/lib/kofficeui/KoInsertLink.cpp b/lib/kofficeui/KoInsertLink.cpp new file mode 100644 index 00000000..56c19081 --- /dev/null +++ b/lib/kofficeui/KoInsertLink.cpp @@ -0,0 +1,549 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Montel Laurent <lmontel@mandrakesoft.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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <kapplication.h> +#include <klocale.h> + +#include <qlayout.h> +#include <qvbox.h> +#include <kdebug.h> +#include <qlabel.h> +#include <qcombobox.h> + +#include <klineedit.h> +#include <kurlrequester.h> +#include <kseparator.h> +#include <kiconloader.h> +#include "KoInsertLink.h" +#include <kdesktopfile.h> +#include <krecentdocument.h> + +using namespace KOfficePrivate; + +KoInsertLinkDia::KoInsertLinkDia( QWidget *parent, const char *name, bool displayBookmarkLink ) + : KDialogBase( KDialogBase::IconList, i18n("Insert Link"), + KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok, parent, name ) +{ + bookmarkLink = 0L; + QVBox *page=addVBoxPage(i18n("Internet"), QString::null,BarIcon("html",KIcon::SizeMedium)); + internetLink = new internetLinkPage(page ); + connect(internetLink,SIGNAL(textChanged()),this,SLOT(slotTextChanged ( ))); + + page=addVBoxPage(i18n("Mail & News"), QString::null,BarIcon("mail_generic",KIcon::SizeMedium)); + mailLink = new mailLinkPage(page ); + connect(mailLink,SIGNAL(textChanged()),this,SLOT(slotTextChanged ())); + + page=addVBoxPage(i18n("File"), QString::null,BarIcon("filenew",KIcon::SizeMedium)); + fileLink = new fileLinkPage(page ); + connect(fileLink,SIGNAL(textChanged()),this,SLOT(slotTextChanged ())); + + if ( displayBookmarkLink) + { + page=addVBoxPage(i18n("Bookmark"), QString::null,BarIcon("bookmark",KIcon::SizeMedium)); + bookmarkLink = new bookmarkLinkPage(page ); + connect(bookmarkLink,SIGNAL(textChanged()),this,SLOT(slotTextChanged ())); + } + + connect( this, SIGNAL( aboutToShowPage(QWidget *) ), this, SLOT( tabChanged(QWidget *) ) ); + + slotTextChanged ( ); + resize(400,300); +} + +void KoInsertLinkDia::tabChanged(QWidget *) +{ + switch( activePageIndex() ) + { + case 0: + internetLink->setLinkName( currentText ); + break; + case 1: + mailLink->setLinkName( currentText ); + break; + case 2: + fileLink->setLinkName( currentText ); + break; + case 3: + { + if ( bookmarkLink) + bookmarkLink->setLinkName( currentText ); + } + break; + default: + kdDebug()<<"Error in linkName\n"; + } + enableButtonOK( !(linkName().isEmpty() || hrefName().isEmpty()) ); +} + +void KoInsertLinkDia::slotTextChanged ( ) +{ + enableButtonOK( !(linkName().isEmpty() || hrefName().isEmpty())); + currentText = linkName(); +} + +bool KoInsertLinkDia::createLinkDia(QString & _linkName, QString & _hrefName, const QStringList& bkmlist, bool displayBookmarkLink, QWidget* parent, const char* name) +{ + bool res = false; + + KoInsertLinkDia *dlg = new KoInsertLinkDia( parent, name, displayBookmarkLink ); + dlg->setHrefLinkName(_hrefName,_linkName, bkmlist); + if ( dlg->exec() == Accepted ) + { + _linkName = dlg->linkName(); + _hrefName = dlg->hrefName(); + res = true; + } + delete dlg; + + return res; +} + +void KoInsertLinkDia::setHrefLinkName(const QString &_href, const QString &_link, const QStringList & bkmlist) +{ + if ( bookmarkLink) + bookmarkLink->setBookmarkList(bkmlist); + if ( _href.isEmpty()) + { + if ( !_link.isEmpty() ) + { + internetLink->setLinkName(_link); + showPage(0); + slotTextChanged ( ); + } + return; + } + if(_href.find("http://")!=-1 || _href.find("https://")!=-1 ||_href.find("ftp://")!=-1 ) + { + internetLink->setHrefName(_href); + internetLink->setLinkName(_link); + showPage(0); + } + else if(_href.find("file:/")!=-1) + { + fileLink->setHrefName(_href); + fileLink->setLinkName(_link); + showPage(2); + } + else if(_href.find("mailto:")!=-1 || _href.find("news:")!=-1) + { + mailLink->setHrefName(_href); + mailLink->setLinkName(_link); + showPage(1); + } + else if(_href.find("bkm://")!=-1) + { + if ( bookmarkLink ) + { + bookmarkLink->setHrefName(_href.mid(6)); + bookmarkLink->setLinkName(_link); + showPage(3); + } + } + slotTextChanged ( ); +} + +QString KoInsertLinkDia::linkName() const +{ + QString result; + switch(activePageIndex()) + { + case 0: + result=internetLink->linkName(); + break; + case 1: + result=mailLink->linkName(); + break; + case 2: + result=fileLink->linkName(); + break; + case 3: + { + if ( bookmarkLink) + result=bookmarkLink->linkName(); + } + break; + default: + kdDebug()<<"Error in linkName\n"; + } + return result; +} + +QString KoInsertLinkDia::hrefName() const +{ + QString result; + switch(activePageIndex()) + { + case 0: + result=internetLink->hrefName(); + break; + case 1: + result=mailLink->hrefName(); + break; + case 2: + result=fileLink->hrefName(); + break; + case 3: + { + if ( bookmarkLink ) + result=bookmarkLink->hrefName(); + } + break; + default: + kdDebug()<<"Error in hrefName\n"; + } + return result; +} + +void KoInsertLinkDia::slotOk() +{ + KDialogBase::slotOk(); +} + + +internetLinkPage::internetLinkPage( QWidget *parent , char *name ) + : QWidget(parent,name) +{ + QVBoxLayout *lay1 = new QVBoxLayout( this ); + lay1->setSpacing( KDialog::spacingHint() ); + QVBoxLayout *lay2 = new QVBoxLayout( lay1); + lay2->setSpacing( KDialog::spacingHint() ); + + QLabel* tmpQLabel = new QLabel( this); + + lay2->addWidget(tmpQLabel); + tmpQLabel->setText(i18n("Text to display:")); + + m_linkName = new QLineEdit( this ); + lay2->addWidget(m_linkName); + + tmpQLabel = new QLabel( this); + lay2->addWidget(tmpQLabel); + + tmpQLabel->setText(i18n("Internet address:")); + m_hrefName = new QLineEdit( this ); + + lay2->addWidget(m_hrefName); + + lay2->addStretch( 1 ); + + m_linkName->setFocus(); + + connect(m_linkName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + connect(m_hrefName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + KSeparator* bar1 = new KSeparator( KSeparator::HLine, this); + bar1->setFixedHeight( 10 ); + lay2->addWidget( bar1 ); +} + +QString internetLinkPage::createInternetLink() +{ + QString result=m_hrefName->text(); + + if(result.isEmpty()) + return result; + + if(result.find("http://")==-1 && result.find("https://")==-1 && result.find("ftp://")==-1) + result = "http://"+result; + return result; +} + + +void internetLinkPage::setLinkName(const QString & _name) +{ + m_linkName->setText(_name); +} + +void internetLinkPage::setHrefName(const QString &_name) +{ + m_hrefName->setText(_name); +} + +QString internetLinkPage::linkName()const +{ + return m_linkName->text(); +} + +QString internetLinkPage::hrefName() +{ + return createInternetLink(); +} + +void internetLinkPage::textChanged ( const QString & ) +{ + emit textChanged(); +} + +bookmarkLinkPage::bookmarkLinkPage( QWidget *parent , char *name ) + : QWidget(parent,name) +{ + QVBoxLayout *lay1 = new QVBoxLayout( this ); + lay1->setSpacing( KDialog::spacingHint() ); + QVBoxLayout *lay2 = new QVBoxLayout( lay1); + lay2->setSpacing( KDialog::spacingHint() ); + + QLabel* tmpQLabel = new QLabel( this); + + lay2->addWidget(tmpQLabel); + tmpQLabel->setText(i18n("Text to display:")); + + m_linkName = new QLineEdit( this ); + lay2->addWidget(m_linkName); + + tmpQLabel = new QLabel( this); + lay2->addWidget(tmpQLabel); + + tmpQLabel->setText(i18n("Bookmark name:")); + m_hrefName = new QComboBox( this ); + + lay2->addWidget(m_hrefName); + + lay2->addStretch( 1 ); + + m_linkName->setFocus(); + + connect(m_linkName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + connect(m_hrefName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + KSeparator* bar1 = new KSeparator( KSeparator::HLine, this); + bar1->setFixedHeight( 10 ); + lay2->addWidget( bar1 ); +} + +QString bookmarkLinkPage::createBookmarkLink() +{ + QString result=m_hrefName->currentText(); + + if(result.isEmpty()) + return result; + + if(result.find("bkm://")==-1) + result = "bkm://"+result; + return result; +} + + +void bookmarkLinkPage::setLinkName(const QString & _name) +{ + m_linkName->setText(_name); +} + +void bookmarkLinkPage::setHrefName(const QString &_name) +{ + m_hrefName->setCurrentText(_name); +} + +void bookmarkLinkPage::setBookmarkList(const QStringList & bkmlist) +{ + m_hrefName->clear(); + m_hrefName->insertStringList(bkmlist, 0); + if ( bkmlist.isEmpty()) + m_linkName->setEnabled( false); + //m_hrefName->setEditable(true); +} + +QString bookmarkLinkPage::linkName()const +{ + return m_linkName->text(); +} + +QString bookmarkLinkPage::hrefName() +{ + return createBookmarkLink(); +} + +void bookmarkLinkPage::textChanged ( const QString & ) +{ + emit textChanged(); +} + +mailLinkPage::mailLinkPage( QWidget *parent , char *name ) + : QWidget(parent,name) +{ + QVBoxLayout *lay1 = new QVBoxLayout( this ); + lay1->setSpacing( KDialog::spacingHint() ); + QVBoxLayout *lay2 = new QVBoxLayout( lay1); + lay2->setSpacing( KDialog::spacingHint() ); + + QLabel* tmpQLabel = new QLabel( this); + + lay2->addWidget(tmpQLabel); + tmpQLabel->setText(i18n("Text to display:")); + + m_linkName = new QLineEdit( this ); + lay2->addWidget(m_linkName); + + tmpQLabel = new QLabel( this); + lay2->addWidget(tmpQLabel); + + tmpQLabel->setText(i18n("Target:")); + m_hrefName = new QLineEdit( this ); + + lay2->addWidget(m_hrefName); + lay2->addStretch( 1 ); + + connect(m_linkName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + connect(m_hrefName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + KSeparator* bar1 = new KSeparator( KSeparator::HLine, this); + bar1->setFixedHeight( 10 ); + lay2->addWidget( bar1 ); +} + +QString mailLinkPage::createMailLink() +{ + QString result=m_hrefName->text(); + + if(result.isEmpty()) + return result; + + if(result.find("mailto:")==-1 && result.find("news:")==-1) + result = "mailto:"+result; + return result; +} + + +void mailLinkPage::setLinkName(const QString & _name) +{ + m_linkName->setText(_name); +} + +void mailLinkPage::setHrefName(const QString &_name) +{ + m_hrefName->setText(_name); +} + +QString mailLinkPage::linkName()const +{ + return m_linkName->text(); +} + +QString mailLinkPage::hrefName() +{ + return createMailLink(); +} + +void mailLinkPage::textChanged ( const QString & ) +{ + emit textChanged(); +} + +fileLinkPage::fileLinkPage( QWidget *parent , char *name ) + : QWidget(parent,name) +{ + QVBoxLayout *lay1 = new QVBoxLayout( this ); + lay1->setSpacing( KDialog::spacingHint() ); + QVBoxLayout *lay2 = new QVBoxLayout( lay1); + lay2->setSpacing( KDialog::spacingHint() ); + + QLabel* tmpQLabel = new QLabel( this); + + lay2->addWidget(tmpQLabel); + tmpQLabel->setText(i18n("Text to display:")); + + m_linkName = new QLineEdit( this ); + lay2->addWidget(m_linkName); + + tmpQLabel = new QLabel( this); + lay2->addWidget(tmpQLabel); + tmpQLabel->setText(i18n("Recent file:")); + + QComboBox * recentFile = new QComboBox( this ); + recentFile->setMaximumWidth( kapp->desktop()->width()*3/4 ); + lay2->addWidget(recentFile); + + QStringList fileList = KRecentDocument::recentDocuments(); + QStringList lst; + lst <<""; + for (QStringList::ConstIterator it = fileList.begin();it != fileList.end(); ++it) + { + KDesktopFile f(*it, true /* read only */); + if ( !f.readURL().isEmpty()) + lst.append( f.readURL()); + } + if ( lst.count()<= 1 ) + { + recentFile->clear(); + recentFile->insertItem( i18n("No Entries") ); + recentFile->setEnabled( false ); + } + else + recentFile->insertStringList( lst); + + recentFile->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + + connect( recentFile , SIGNAL(highlighted ( const QString &)), this, SLOT( slotSelectRecentFile( const QString & ))); + + tmpQLabel = new QLabel( this); + lay2->addWidget(tmpQLabel); + + tmpQLabel->setText(i18n("File location:")); + m_hrefName = new KURLRequester( this ); + + lay2->addWidget(m_hrefName); + lay2->addStretch( 1 ); + + connect(m_linkName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + connect(m_hrefName,SIGNAL(textChanged ( const QString & )),this,SLOT(textChanged ( const QString & ))); + + KSeparator* bar1 = new KSeparator( KSeparator::HLine, this); + bar1->setFixedHeight( 10 ); + lay2->addWidget( bar1 ); +} + +void fileLinkPage::slotSelectRecentFile( const QString &_file ) +{ + m_hrefName->lineEdit()->setText(_file ); +} + +QString fileLinkPage::createFileLink() +{ + QString result=m_hrefName->lineEdit()->text(); + if(result.isEmpty()) + return result; + + if(result.find("file:/")==-1) + result = "file://"+result; + return result; +} + +void fileLinkPage::setLinkName(const QString & _name) +{ + m_linkName->setText(_name); +} + +void fileLinkPage::setHrefName(const QString &_name) +{ + m_hrefName->lineEdit()->setText(_name); +} + +QString fileLinkPage::linkName()const +{ + return m_linkName->text(); +} + +QString fileLinkPage::hrefName() +{ + return createFileLink(); +} + +void fileLinkPage::textChanged ( const QString & ) +{ + emit textChanged(); +} + +#include "KoInsertLink.moc" diff --git a/lib/kofficeui/KoInsertLink.h b/lib/kofficeui/KoInsertLink.h new file mode 100644 index 00000000..79d5eeca --- /dev/null +++ b/lib/kofficeui/KoInsertLink.h @@ -0,0 +1,148 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Montel Laurent <lmontel@mandrakesoft.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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __KoInsertLink__ +#define __KoInsertLink__ + +#include <kdialogbase.h> +#include <koffice_export.h> +class QLineEdit; +class KURLRequester; + +namespace KOfficePrivate { +/** + * @internal + */ +class internetLinkPage : public QWidget +{ + Q_OBJECT +public: + internetLinkPage( QWidget *parent = 0, char *name = 0 ); + QString linkName()const; + QString hrefName(); + void setLinkName(const QString & _name); + void setHrefName(const QString &_name); +private: + QString createInternetLink(); + QLineEdit* m_linkName, *m_hrefName; +private slots: + void textChanged ( const QString & ); +signals: + void textChanged(); +}; + +/** + * @internal + */ +class bookmarkLinkPage : public QWidget +{ + Q_OBJECT +public: + bookmarkLinkPage( QWidget *parent = 0, char *name = 0 ); + QString linkName()const; + QString hrefName(); + void setLinkName(const QString & _name); + void setHrefName(const QString &_name); + void setBookmarkList(const QStringList &bkmlist); +private: + QString createBookmarkLink(); + QLineEdit* m_linkName; + QComboBox *m_hrefName; +private slots: + void textChanged ( const QString & ); +signals: + void textChanged(); +}; + +/** + * @internal + */ +class mailLinkPage : public QWidget +{ + Q_OBJECT +public: + mailLinkPage( QWidget *parent = 0, char *name = 0 ); + QString linkName()const; + QString hrefName(); + void setLinkName(const QString & _name); + void setHrefName(const QString &_name); + +private slots: + void textChanged ( const QString & ); +private: + QString createMailLink(); + QLineEdit* m_linkName, *m_hrefName; +signals: + void textChanged(); +}; + +/** + * @internal + */ +class fileLinkPage : public QWidget +{ + Q_OBJECT +public: + fileLinkPage( QWidget *parent = 0, char *name = 0 ); + QString linkName()const; + QString hrefName(); + void setLinkName(const QString & _name); + void setHrefName(const QString &_name); + +private slots: + void textChanged ( const QString & ); + void slotSelectRecentFile( const QString & ); +private: + QString createFileLink(); + QLineEdit* m_linkName; + KURLRequester* m_hrefName; +signals: + void textChanged(); +}; +} + +/** + * Dialog to insert links to various sources (file, Internet, mail and bookmarks). + */ +class KOFFICEUI_EXPORT KoInsertLinkDia : public KDialogBase +{ + Q_OBJECT +public: + KoInsertLinkDia( QWidget *parent, const char *name = 0,bool displayBookmarkLink=true ); + static bool createLinkDia(QString & linkName, QString & hrefName, const QStringList& bkmlist, bool displayBookmarkLink = true, + QWidget* parent = 0, const char* name = 0); + + //internal + QString linkName() const; + QString hrefName() const; + void setHrefLinkName(const QString &_href, const QString &_link, const QStringList & bkmlist); +protected slots: + virtual void slotOk(); + void slotTextChanged ( ); + void tabChanged(QWidget *); + +private: + KOfficePrivate::fileLinkPage *fileLink; + KOfficePrivate::mailLinkPage *mailLink; + KOfficePrivate::internetLinkPage *internetLink; + KOfficePrivate::bookmarkLinkPage *bookmarkLink; + QString currentText; +}; + +#endif diff --git a/lib/kofficeui/KoKoolBar.cpp b/lib/kofficeui/KoKoolBar.cpp new file mode 100644 index 00000000..9715ce5e --- /dev/null +++ b/lib/kofficeui/KoKoolBar.cpp @@ -0,0 +1,489 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <KoKoolBar.h> +#include <kiconloader.h> + +#include <qpainter.h> +#include <qpushbutton.h> + +static int g_koKoolBarId = 0; + +KoKoolBar::KoKoolBar( QWidget *_parent, const char *_name ) : + QWidget( _parent, _name ), m_iActiveGroup( -1 ) +{ + m_mapGroups.setAutoDelete( true ); + m_pBox = new KoKoolBarBox( this ); +} + +int KoKoolBar::insertGroup( const QString& _text ) +{ + KoKoolBarGroup *p = new KoKoolBarGroup( this, _text ); + m_mapGroups.insert( p->id(), p ); + + if ( m_iActiveGroup == -1 ) + setActiveGroup( p->id() ); + else + resizeEvent( 0L ); + return p->id(); +} + +int KoKoolBar::insertItem( int _grp, const QPixmap& _pix, const QString& _text, + QObject *_obj, const char *_slot ) +{ + KoKoolBarGroup* g = m_mapGroups[ _grp ]; + if ( !g ) + return -1; + KoKoolBarItem *item = new KoKoolBarItem( g, _pix, _text ); + + if ( _obj != 0L && _slot != 0L ) + connect( item, SIGNAL( pressed( int, int ) ), _obj, _slot ); + g->append( item ); + + if ( g->id() == m_iActiveGroup ) + m_pBox->update(); + + return item->id(); +} + +void KoKoolBar::removeGroup( int _grp ) +{ + KoKoolBarGroup* g = m_mapGroups[ _grp ]; + if ( !g ) + return; + + m_mapGroups.remove( _grp ); + + if ( _grp == m_iActiveGroup ) + { + if ( m_mapGroups.count() == 0 ) + { + m_iActiveGroup = -1; + m_pBox->setActiveGroup( 0L ); + } + else + { + QIntDictIterator<KoKoolBarGroup> it( m_mapGroups ); + g = it.current(); + m_iActiveGroup = g->id(); + m_pBox->setActiveGroup( g ); + } + } + + resizeEvent( 0L ); +} + +void KoKoolBar::removeItem( int _grp, int _id ) +{ + KoKoolBarGroup* g = m_mapGroups[ _grp ]; + if ( !g ) + return; + + g->remove( _id ); + + if ( g->id() == m_iActiveGroup ) + m_pBox->update(); +} + +void KoKoolBar::renameItem( int _grp, int _id, const QString & _text ) +{ + KoKoolBarGroup* g = m_mapGroups[ _grp ]; + if ( !g ) + return; + + KoKoolBarItem * item = g->item( _id ); + if ( !item ) + return; + + item->setText( _text ); + + if ( g->id() == m_iActiveGroup ) + m_pBox->update(); +} + +void KoKoolBar::setActiveGroup( int _grp ) +{ + KoKoolBarGroup* g = m_mapGroups[ _grp ]; + if ( !g ) + return; + + m_iActiveGroup = g->id(); + m_pBox->setActiveGroup( g ); + + resizeEvent( 0L ); +} + +void KoKoolBar::resizeEvent( QResizeEvent * ev ) +{ + if ( m_iActiveGroup == -1 ) + return; + + int buttonheight = fontMetrics().height() + 4; + + KoKoolBarGroup *g = m_mapGroups[ m_iActiveGroup ]; + if ( !g ) + return; + + // Go behind g + QIntDictIterator<KoKoolBarGroup> it( m_mapGroups ); + while( it.current() != g ) + ++it; + // Position of g + QIntDictIterator<KoKoolBarGroup> pos = it; + ++it; + + // How many left ? + int result = 0; + QIntDictIterator<KoKoolBarGroup> i = it; + while( i.current() ) + { + ++result; + ++i; + } + + int y = height() - buttonheight * result; + for( ; it.current(); ++it ) + { + it.current()->button()->setGeometry( 0, y, width(), buttonheight ); + it.current()->button()->show(); + y += buttonheight; + } + + int y2 = 0; + it.toFirst(); + ++pos; + while( it.current() != pos.current() ) + { + it.current()->button()->setGeometry( 0, y2, width(), buttonheight ); + it.current()->button()->show(); + ++it; + y2 += buttonheight; + } + + if ( height() - y2 - result * buttonheight >= 0 ) + { + m_pBox->show(); + m_pBox->setGeometry( 0, y2, width(), height() - y2 - result * buttonheight ); + if ( !ev ) // fake event + m_pBox->sizeChanged(); + } + else + m_pBox->hide(); + +} + +void KoKoolBar::enableItem( int _grp, int _id, bool _enable ) +{ + KoKoolBarGroup* g = m_mapGroups[ _grp ]; + if ( !g ) + return; + KoKoolBarItem *item = g->item( _id ); + if ( !item ) + return; + item->setEnabled( _enable ); +} + +void KoKoolBar::enableGroup( int _grp, bool _enable ) +{ + KoKoolBarGroup* g = m_mapGroups[ _grp ]; + if ( !g ) + return; + g->setEnabled( _enable ); +} + +KoKoolBarBox::KoKoolBarBox( KoKoolBar *_bar ) : + QFrame( _bar ), m_pBar( _bar ), + m_pButtonUp( 0L ), m_pButtonDown( 0L ) +{ + m_iYOffset = 0; + m_iYIcon = 0; + m_pGroup = 0L; + + setFrameShape( StyledPanel ); + setFrameShadow( Sunken ); + // setBackgroundMode( PaletteBase ); + setBackgroundColor( colorGroup().background() ); +} + +void KoKoolBarBox::setActiveGroup( KoKoolBarGroup *_grp ) +{ + m_pGroup = _grp; + m_iYOffset = 0; + m_iYIcon = 0; + update(); +} + +bool KoKoolBarBox::needsScrolling() const +{ + if ( m_pGroup == 0L ) + return false; + + return ( maxHeight() > height() ); +} + +void KoKoolBarBox::resizeEvent( QResizeEvent * ) +{ + if ( needsScrolling() ) + { + if ( m_pButtonUp == 0L ) + { + m_pButtonUp = new QPushButton( this ); + m_pButtonUp->setPixmap( QPixmap( UserIcon( "koKoolBarUp" ) ) ); + connect( m_pButtonUp, SIGNAL( clicked() ), this, SLOT( scrollUp() ) ); + } + if ( m_pButtonDown == 0L ) + { + m_pButtonDown = new QPushButton( this ); + m_pButtonDown->setPixmap( QPixmap( UserIcon( "koKoolBarDown" ) ) ); + connect( m_pButtonDown, SIGNAL( clicked() ), this, SLOT( scrollDown() ) ); + } + m_pButtonUp->show(); + m_pButtonUp->raise(); + m_pButtonDown->show(); + m_pButtonDown->raise(); + updateScrollButtons(); + } + else + { + if ( m_pButtonUp ) + m_pButtonUp->hide(); + if ( m_pButtonDown ) + m_pButtonDown->hide(); + } +} + +KoKoolBarItem* KoKoolBarBox::findByPos( int _abs_y ) const +{ + if ( m_pGroup == 0L ) + return 0L; + + int y = 0; + + QIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator(); + for ( ; it.current(); ++it ) + { + int dy = it.current()->height(); + if ( y <= _abs_y && _abs_y <= y + dy ) + return it.current(); + y += dy; + } + + return 0L; +} + +int KoKoolBarBox::maxHeight() const +{ + int y = 0; + + QIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator(); + for ( ; it.current(); ++it ) + y += it.current()->height(); + + return y; +} + +bool KoKoolBarBox::isAtTop() const +{ + return ( m_iYIcon == 0 ); +} + +bool KoKoolBarBox::isAtBottom() const +{ + if ( m_pGroup->items() == 0 ) + return true; + int h = maxHeight(); + if ( height() + m_iYOffset >= h ) + return true; + if ( m_pGroup->items() - 1 == m_iYIcon ) + return true; + return false; +} + +void KoKoolBarBox::scrollUp() +{ + if ( isAtTop() ) + return; + + int y = 0; + int i = 0; + m_iYIcon--; + + QIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator(); + for ( ; i < m_iYIcon && it.current(); ++it ) + { + y += it.current()->height(); + ++i; + } + + int old = m_iYOffset; + m_iYOffset = y; + + QWidget::scroll( 0, old - m_iYOffset, contentsRect() ); + updateScrollButtons(); +} + +void KoKoolBarBox::scrollDown() +{ + if ( isAtBottom() ) + return; + + int y = 0; + int i = 0; + m_iYIcon++; + + QIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator(); + for ( ; i < m_iYIcon && it.current(); ++it ) + { + y += it.current()->height(); + i++; + } + int h = maxHeight(); + if ( y + height() > h ) // Don't go after last item + y = h - height(); + + int old = m_iYOffset; + m_iYOffset = y; + + QWidget::scroll( 0, old - m_iYOffset, contentsRect() ); + updateScrollButtons(); +} + +void KoKoolBarBox::updateScrollButtons() +{ + if ( isAtTop() ) + m_pButtonUp->setEnabled( false ); + else + m_pButtonUp->setEnabled( true ); + + if ( isAtBottom() ) + m_pButtonDown->setEnabled( false ); + else + m_pButtonDown->setEnabled( true ); + + const int bs = 14; // buttonSize + m_pButtonUp->setGeometry( width() - bs, height() - 2 * bs, bs, bs ); + m_pButtonDown->setGeometry( width() - bs, height() - bs, bs, bs ); +} + +void KoKoolBarBox::drawContents( QPainter * painter ) +{ + if ( m_pGroup == 0L ) + return; + + int y = -m_iYOffset; + + QIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator(); + for ( ; it.current(); ++it ) + { + if ( y + it.current()->height() >= 0 && y <= height() ) // visible ? + { + painter->drawPixmap( ( width() - it.current()->pixmap().width() ) / 2, y, it.current()->pixmap() ); + if ( !it.current()->text().isEmpty() ) + { + int y2 = y + it.current()->pixmap().height() + 2; + painter->drawText( ( width() - painter->fontMetrics().width( it.current()->text() ) ) / 2, + y2 + painter->fontMetrics().ascent(), it.current()->text() ); + } + } + + y += it.current()->height(); + } +} + +KoKoolBarGroup::KoKoolBarGroup( KoKoolBar *_bar, const QString& _text ) : + m_pBar( _bar ) +{ + m_mapItems.setAutoDelete( true ); + + m_pButton = new QPushButton( _text, _bar ); + + m_bEnabled = true; + + connect( m_pButton, SIGNAL( clicked() ), this, SLOT( pressed() ) ); + m_id = g_koKoolBarId++; +} + +KoKoolBarGroup::~KoKoolBarGroup() +{ + delete m_pButton; +} + +void KoKoolBarGroup::remove( int _id ) +{ + m_mapItems.remove( _id ); +} + +void KoKoolBarGroup::pressed() +{ + m_pBar->setActiveGroup( m_id ); +} + +KoKoolBarItem::KoKoolBarItem( KoKoolBarGroup *_grp, const QPixmap& _pix, const QString&_text ) + : m_pGroup( _grp ) +{ + m_pixmap = _pix; + m_strText = _text; + m_bEnabled = true; + m_id = g_koKoolBarId++; + calc( _grp->bar() ); +} + +void KoKoolBarItem::calc( QWidget *_widget ) +{ + m_iHeight = pixmap().height() + 8; + + if ( !m_strText.isEmpty() ) + m_iHeight += _widget->fontMetrics().height() + 2; +} + +void KoKoolBarItem::press() +{ + emit pressed(); + emit pressed( m_pGroup->id(), m_id ); +} + +/* + +int main( int argc, char **argv ) +{ + KApplication app( argc, argv ); + KoKoolBar bar; + int file = bar.insertGroup("File"); + QPixmap pix; + pix.load( "/opt/kde/share/icons/image.xpm" ); + bar.insertItem( file, pix ); + pix.load( "/opt/kde/share/icons/html.xpm" ); + bar.insertItem( file, pix ); + pix.load( "/opt/kde/share/icons/txt.xpm" ); + bar.insertItem( file, pix ); + pix.load( "/opt/kde/share/icons/kfm.xpm" ); + bar.insertItem( file, pix ); + + bar.insertGroup("Edit"); + bar.insertGroup("View"); + bar.insertGroup("Layout"); + bar.insertGroup("Help"); + bar.setGeometry( 100, 100, 80, 300 ); + bar.show(); + + app.exec(); +} +*/ + +#include <KoKoolBar.moc> diff --git a/lib/kofficeui/KoKoolBar.h b/lib/kofficeui/KoKoolBar.h new file mode 100644 index 00000000..5e6f91fc --- /dev/null +++ b/lib/kofficeui/KoKoolBar.h @@ -0,0 +1,166 @@ +/* + This file is part of the KDE project + Copyright (C) 1998, 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __ko_koolbar_h__ +#define __ko_koolbar_h__ + +#include <qframe.h> +#include <qpixmap.h> +#include <qintdict.h> +#include <koffice_export.h> +class QPushButton; +class QPixmap; +class KoKoolBar; +class KoKoolBarGroup; + +class KoKoolBarItem : public QObject +{ +private: + Q_OBJECT +public: + KoKoolBarItem( KoKoolBarGroup *_grp, const QPixmap& _pix, const QString& _text = QString::null ); + + int id() const { return m_id; } + void press(); + bool isEnabled() const { return m_bEnabled; } + void setEnabled( bool _e ) { m_bEnabled = _e; } + + int height() const { return m_iHeight; } + QPixmap pixmap() const { return m_pixmap; } + void setText( const QString & text ) { m_strText = text; } + QString text() const { return m_strText; } + +signals: + void pressed( int _group, int _id ); + void pressed(); +protected: + void calc( QWidget* ); + + int m_iHeight; + KoKoolBarGroup* m_pGroup; + QString m_strText; + QPixmap m_pixmap; + int m_id; + bool m_bEnabled; + class KoKoolBarItemPrivate; + KoKoolBarItemPrivate *d; +}; + +class KoKoolBarGroup : public QObject +{ + Q_OBJECT +public: + KoKoolBarGroup( KoKoolBar *_bar, const QString& _text ); + ~KoKoolBarGroup(); + + void append( KoKoolBarItem *_i ) { m_mapItems.insert( _i->id(), _i ); } + void remove( int _id ); + + KoKoolBar* bar() const { return m_pBar; } + QPushButton* button() const { return m_pButton; } + int id() const { return m_id; } + bool isEnabled() const { return m_bEnabled; } + void setEnabled( bool _e ) { m_bEnabled = _e; } + KoKoolBarItem* item( int _id ) const { return m_mapItems[ _id ]; } + int items() const { return m_mapItems.size(); } + QIntDictIterator<KoKoolBarItem> iterator() const { return QIntDictIterator<KoKoolBarItem>( m_mapItems ); } + +public slots: + void pressed(); + +protected: + QIntDict<KoKoolBarItem> m_mapItems; + KoKoolBar* m_pBar; + QString m_strText; + int m_id; + QPushButton* m_pButton; + bool m_bEnabled; + class KoKoolBarGroupPrivate; + KoKoolBarGroupPrivate *d; +}; + +class KoKoolBarBox : public QFrame +{ + Q_OBJECT +public: + KoKoolBarBox( KoKoolBar *_bar ); + + void setActiveGroup( KoKoolBarGroup *_grp ); + int maxHeight() const; + + void sizeChanged() { resizeEvent(0L); } + +protected slots: + void scrollUp(); + void scrollDown(); + +protected: + virtual void resizeEvent( QResizeEvent *_ev ); + virtual void drawContents( QPainter * ); + virtual void mousePressEvent( QMouseEvent *_ev ) + { KoKoolBarItem *item = findByPos( _ev->pos().y() + m_iYOffset ); if ( !item ) return; item->press(); } + + KoKoolBarItem* findByPos( int _abs_y ) const; + + bool needsScrolling() const; + bool isAtBottom() const; + bool isAtTop() const; + void updateScrollButtons(); + + KoKoolBar *m_pBar; + int m_iYOffset; + int m_iYIcon; + KoKoolBarGroup *m_pGroup; + QPushButton* m_pButtonUp; + QPushButton* m_pButtonDown; + class KoKoolBarBoxPrivate; + KoKoolBarBoxPrivate *d; +}; + +class KOFFICEUI_EXPORT KoKoolBar : public QWidget +{ + Q_OBJECT +public: + KoKoolBar( QWidget *_parent = 0L, const char *_name = 0L ); + virtual ~KoKoolBar() { }; + + virtual int insertGroup( const QString& _text ); + virtual int insertItem( int _grp, const QPixmap& _pix, const QString& _text = QString::null, + QObject *_obj = 0L, const char *_slot = 0L ); + virtual void removeGroup( int _grp ); + virtual void removeItem( int _grp, int _id ); + virtual void renameItem( int _grp, int _id, const QString & _text ); + virtual void setActiveGroup( int _grp ); + virtual int activeGroup() const { return m_iActiveGroup; } + virtual void enableItem( int _grp, int _id, bool _enable ); + virtual void enableGroup( int _grp, bool _enable ); + +protected: + virtual void resizeEvent( QResizeEvent *_ev ); + + QIntDict<KoKoolBarGroup> m_mapGroups; + + int m_iActiveGroup; + KoKoolBarBox* m_pBox; + class KoKoolBarPrivate; + KoKoolBarPrivate *d; +}; + +#endif diff --git a/lib/kofficeui/KoPageLayoutColumns.cpp b/lib/kofficeui/KoPageLayoutColumns.cpp new file mode 100644 index 00000000..db5e3e25 --- /dev/null +++ b/lib/kofficeui/KoPageLayoutColumns.cpp @@ -0,0 +1,70 @@ +/* This file is part of the KDE project + * Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + * Copyright (C) 2005 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; version 2. + * + * 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 <KoPageLayoutColumns.h> +#include <KoPageLayoutDia.h> +#include <KoUnit.h> +#include <KoUnitWidgets.h> + +#include <qlabel.h> +#include <qlayout.h> + +KoPageLayoutColumns::KoPageLayoutColumns(QWidget *parent, const KoColumns& columns, KoUnit::Unit unit, const KoPageLayout& layout) + : KoPageLayoutColumnsBase(parent) { + m_columns = columns; + QHBoxLayout *lay = new QHBoxLayout(previewPane); + m_preview = new KoPagePreview( previewPane, "Preview", layout ); + lay->addWidget(m_preview); + lay = new QHBoxLayout(columnSpacingPane); + m_spacing = new KoUnitDoubleSpinBox( columnSpacingPane ); + m_spacing->setValue( m_columns.ptColumnSpacing ); + m_spacing->setUnit( unit ); + double dStep = KoUnit::fromUserValue( 0.2, unit ); + m_spacing->setMinMaxStep( 0, layout.ptWidth/2, dStep ); + lay->addWidget(m_spacing); + labelSpacing->setBuddy( m_spacing ); + nColumns->setValue( m_columns.columns ); + m_preview->setPageColumns( m_columns ); + + connect( nColumns, SIGNAL( valueChanged( int ) ), this, SLOT( nColChanged( int ) ) ); + connect( m_spacing, SIGNAL( valueChangedPt(double) ), this, SLOT( nSpaceChanged( double ) ) ); +} + +void KoPageLayoutColumns::setEnableColumns(bool on) { + nColumns->setEnabled(on); + m_spacing->setEnabled(on); + nColChanged(on ? nColumns->value(): 1 ); +} + +void KoPageLayoutColumns::nColChanged( int columns ) { + m_columns.columns = columns; + m_preview->setPageColumns( m_columns ); + emit propertyChange(m_columns); +} + +void KoPageLayoutColumns::nSpaceChanged( double spacing ) { + m_columns.ptColumnSpacing = spacing; + emit propertyChange(m_columns); +} + +void KoPageLayoutColumns::setLayout(KoPageLayout &layout) { + m_preview->setPageLayout( layout ); +} + +#include <KoPageLayoutColumns.moc> diff --git a/lib/kofficeui/KoPageLayoutColumns.h b/lib/kofficeui/KoPageLayoutColumns.h new file mode 100644 index 00000000..be0a4a49 --- /dev/null +++ b/lib/kofficeui/KoPageLayoutColumns.h @@ -0,0 +1,75 @@ +/* This file is part of the KDE project + * Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + * Copyright (C) 2005 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; version 2. + * + * 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. + */ + +// Description: Page Layout Dialog (sources) + +#ifndef kopagelayoutcolumns_h +#define kopagelayoutcolumns_h + +#include <KoUnit.h> +#include <KoPageLayout.h> +#include <KoPageLayoutColumnsBase.h> + +class QWidget; +class KoUnitDoubleSpinBox; +class KoPagePreview; + +/** + * This class is a widget that shows the KoColumns data structure and allows the user to change it. + */ +class KoPageLayoutColumns : public KoPageLayoutColumnsBase { + Q_OBJECT + +public: + /** + * Contructor + * @param parent the parent widget + * @param columns the KoColumns data structure that this dialog should be initialzed with + * @param unit the unit-type (mm/cm/inch) that the dialog should show + * @param layout the page layout that the preview should be initialzed with. + */ + KoPageLayoutColumns(QWidget *parent, const KoColumns& columns, KoUnit::Unit unit, const KoPageLayout& layout); + + /** + * Update the page preview widget with the param layout. + * @param layout the new layout + */ + void setLayout(KoPageLayout &layout); +public slots: + + /** + * Enable the user to edit the columns + * @param on if true enable the user to change the columns count + */ + void setEnableColumns(bool on); + +signals: + void propertyChange(KoColumns &columns); + +protected: + KoColumns m_columns; + KoPagePreview *m_preview; + KoUnitDoubleSpinBox *m_spacing; + +private slots: + void nColChanged( int ); + void nSpaceChanged( double ); +}; + +#endif diff --git a/lib/kofficeui/KoPageLayoutColumnsBase.ui b/lib/kofficeui/KoPageLayoutColumnsBase.ui new file mode 100644 index 00000000..1ffe032d --- /dev/null +++ b/lib/kofficeui/KoPageLayoutColumnsBase.ui @@ -0,0 +1,99 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KoPageLayoutColumnsBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KoPageLayoutColumnsBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>361</width> + <height>169</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QFrame" row="1" column="1"> + <property name="name"> + <cstring>columnSpacingPane</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Columns:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>nColumns</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>labelSpacing</cstring> + </property> + <property name="text"> + <string>Column spacing:</string> + </property> + </widget> + <spacer row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QFrame" row="0" column="2" rowspan="3" colspan="1"> + <property name="name"> + <cstring>previewPane</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>nColumns</cstring> + </property> + <property name="maxValue"> + <number>16</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/lib/kofficeui/KoPageLayoutDia.cpp b/lib/kofficeui/KoPageLayoutDia.cpp new file mode 100644 index 00000000..13194df1 --- /dev/null +++ b/lib/kofficeui/KoPageLayoutDia.cpp @@ -0,0 +1,402 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2005 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. +*/ + +// Description: Page Layout Dialog (sources) + +/******************************************************************/ + +#include <KoPageLayoutDia.h> +#include <KoPageLayoutColumns.h> +#include <KoPageLayoutSize.h> +#include <KoPageLayoutHeader.h> +#include <KoUnit.h> +#include <KoUnitWidgets.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kmessagebox.h> + +#include <qlabel.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qlineedit.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qvgroupbox.h> +#include <qhbuttongroup.h> + +/******************************************************************/ +/* class KoPagePreview */ +/******************************************************************/ + +/*===================== constrcutor ==============================*/ +KoPagePreview::KoPagePreview( QWidget* parent, const char *name, const KoPageLayout& layout ) + : QGroupBox( i18n( "Page Preview" ), parent, name ) +{ + setPageLayout( layout ); + columns = 1; + setMinimumSize( 150, 150 ); +} + +/*====================== destructor ==============================*/ +KoPagePreview::~KoPagePreview() +{ +} + +/*=================== set layout =================================*/ +void KoPagePreview::setPageLayout( const KoPageLayout &layout ) +{ + // resolution[XY] is in pixel per pt + double resolutionX = POINT_TO_INCH( static_cast<double>(KoGlobal::dpiX()) ); + double resolutionY = POINT_TO_INCH( static_cast<double>(KoGlobal::dpiY()) ); + + m_pageWidth = layout.ptWidth * resolutionX; + m_pageHeight = layout.ptHeight * resolutionY; + + double zh = 110.0 / m_pageHeight; + double zw = 110.0 / m_pageWidth; + double z = QMIN( zw, zh ); + + m_pageWidth *= z; + m_pageHeight *= z; + + m_textFrameX = layout.ptLeft * resolutionX * z; + m_textFrameY = layout.ptTop * resolutionY * z; + m_textFrameWidth = m_pageWidth - ( layout.ptLeft + layout.ptRight ) * resolutionX * z; + m_textFrameHeight = m_pageHeight - ( layout.ptTop + layout.ptBottom ) * resolutionY * z; + + repaint( true ); +} + +/*=================== set layout =================================*/ +void KoPagePreview::setPageColumns( const KoColumns &_columns ) +{ + columns = _columns.columns; + repaint( true ); +} + +/*======================== draw contents =========================*/ +void KoPagePreview::drawContents( QPainter *painter ) +{ + double cw = m_textFrameWidth; + if(columns!=1) + cw/=static_cast<double>(columns); + + painter->setBrush( white ); + painter->setPen( QPen( black ) ); + + int x=static_cast<int>( ( width() - m_pageWidth ) * 0.5 ); + int y=static_cast<int>( ( height() - m_pageHeight ) * 0.5 ); + int w=static_cast<int>(m_pageWidth); + int h=static_cast<int>(m_pageHeight); + //painter->drawRect( x + 1, y + 1, w, h); + painter->drawRect( x, y, w, h ); + + painter->setBrush( QBrush( black, HorPattern ) ); + if ( m_textFrameWidth == m_pageWidth || m_textFrameHeight == m_pageHeight ) + painter->setPen( NoPen ); + else + painter->setPen( lightGray ); + + for ( int i = 0; i < columns; ++i ) + painter->drawRect( x + static_cast<int>(m_textFrameX) + static_cast<int>(i * cw), + y + static_cast<int>(m_textFrameY), static_cast<int>(cw), + static_cast<int>(m_textFrameHeight) ); +} + +/******************************************************************/ +/* class KoPageLayoutDia */ +/******************************************************************/ + +/*==================== constructor ===============================*/ +KoPageLayoutDia::KoPageLayoutDia( QWidget* parent, const char* name, + const KoPageLayout& layout, + const KoHeadFoot& hf, int tabs, + KoUnit::Unit unit, bool modal ) + : KDialogBase( KDialogBase::Tabbed, i18n("Page Layout"), KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok, parent, name, modal) +{ + + flags = tabs; + m_layout = layout; + m_unit = unit; + m_pageSizeTab = 0; + m_columnsTab = 0; + m_headerTab = 0; + + m_column.columns = 1; + + if ( tabs & FORMAT_AND_BORDERS ) setupTab1( true ); + if ( tabs & HEADER_AND_FOOTER ) setupTab2( hf ); + + setFocusPolicy( QWidget::StrongFocus ); + setFocus(); +} + +/*==================== constructor ===============================*/ +KoPageLayoutDia::KoPageLayoutDia( QWidget* parent, const char* name, + const KoPageLayout& layout, + const KoHeadFoot& hf, + const KoColumns& columns, + const KoKWHeaderFooter& kwhf, + int tabs, KoUnit::Unit unit ) + : KDialogBase( KDialogBase::Tabbed, i18n("Page Layout"), KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok, parent, name, true) +{ + flags = tabs; + + m_layout = layout; + m_column = columns; + m_unit = unit; + m_pageSizeTab = 0; + m_columnsTab = 0; + m_headerTab = 0; + + if ( tabs & FORMAT_AND_BORDERS ) setupTab1( !( tabs & DISABLE_BORDERS ) ); + if ( tabs & HEADER_AND_FOOTER ) setupTab2( hf ); + if ( tabs & COLUMNS ) setupTab3(); + if ( tabs & KW_HEADER_AND_FOOTER ) setupTab4(kwhf); + + setFocusPolicy( QWidget::StrongFocus ); + setFocus(); +} + +/*===================== destructor ===============================*/ +KoPageLayoutDia::~KoPageLayoutDia() +{ +} + +/*======================= show dialog ============================*/ +bool KoPageLayoutDia::pageLayout( KoPageLayout& layout, KoHeadFoot& hf, int tabs, KoUnit::Unit& unit, QWidget* parent ) +{ + bool res = false; + KoPageLayoutDia *dlg = new KoPageLayoutDia( parent, "PageLayout", layout, hf, tabs, unit ); + + if ( dlg->exec() == QDialog::Accepted ) { + res = true; + if ( tabs & FORMAT_AND_BORDERS ) layout = dlg->layout(); + if ( tabs & HEADER_AND_FOOTER ) hf = dlg->headFoot(); + unit = dlg->unit(); + } + + delete dlg; + + return res; +} + +/*======================= show dialog ============================*/ +bool KoPageLayoutDia::pageLayout( KoPageLayout& layout, KoHeadFoot& hf, KoColumns& columns, + KoKWHeaderFooter &_kwhf, int tabs, KoUnit::Unit& unit, QWidget* parent ) +{ + bool res = false; + KoPageLayoutDia *dlg = new KoPageLayoutDia( parent, "PageLayout", layout, hf, columns, _kwhf, tabs, unit ); + + if ( dlg->exec() == QDialog::Accepted ) { + res = true; + if ( tabs & FORMAT_AND_BORDERS ) layout = dlg->layout(); + if ( tabs & HEADER_AND_FOOTER ) hf = dlg->headFoot(); + if ( tabs & COLUMNS ) columns = dlg->columns(); + if ( tabs & KW_HEADER_AND_FOOTER ) _kwhf = dlg->headerFooter(); + unit = dlg->unit(); + } + + delete dlg; + + return res; +} + +/*===================== get a standard page layout ===============*/ +KoPageLayout KoPageLayoutDia::standardLayout() +{ + return KoPageLayout::standardLayout(); +} + +/*====================== get header - footer =====================*/ +KoHeadFoot KoPageLayoutDia::headFoot() const +{ + KoHeadFoot hf; + hf.headLeft = eHeadLeft->text(); + hf.headMid = eHeadMid->text(); + hf.headRight = eHeadRight->text(); + hf.footLeft = eFootLeft->text(); + hf.footMid = eFootMid->text(); + hf.footRight = eFootRight->text(); + return hf; +} + +/*================================================================*/ +const KoKWHeaderFooter& KoPageLayoutDia::headerFooter() +{ + return m_headerTab->headerFooter(); +} + +/*================ setup page size & margins tab ==================*/ +void KoPageLayoutDia::setupTab1( bool enableBorders ) +{ + QWidget *tab1 = addPage(i18n( "Page Size && &Margins" )); + QHBoxLayout *lay = new QHBoxLayout(tab1); + m_pageSizeTab = new KoPageLayoutSize(tab1, m_layout, m_unit, m_column, !(flags & DISABLE_UNIT), enableBorders ); + lay->addWidget(m_pageSizeTab); + m_pageSizeTab->show(); + connect (m_pageSizeTab, SIGNAL( propertyChange(KoPageLayout&)), + this, SLOT (sizeUpdated( KoPageLayout&))); +} + +void KoPageLayoutDia::sizeUpdated(KoPageLayout &layout) { + m_layout.ptWidth = layout.ptWidth; + m_layout.ptHeight = layout.ptHeight; + m_layout.ptLeft = layout.ptLeft; + m_layout.ptRight = layout.ptRight; + m_layout.ptTop = layout.ptTop; + m_layout.ptBottom = layout.ptBottom; + m_layout.format = layout.format; + m_layout.orientation = layout.orientation; + if(m_columnsTab) + m_columnsTab->setLayout(layout); +} + +/*================ setup header and footer tab ===================*/ +void KoPageLayoutDia::setupTab2( const KoHeadFoot& hf ) +{ + QWidget *tab2 = addPage(i18n( "H&eader && Footer" )); + QGridLayout *grid2 = new QGridLayout( tab2, 7, 2, 0, KDialog::spacingHint() ); + + // ------------- header --------------- + QGroupBox *gHead = new QGroupBox( 0, Qt::Vertical, i18n( "Head Line" ), tab2 ); + gHead->layout()->setSpacing(KDialog::spacingHint()); + gHead->layout()->setMargin(KDialog::marginHint()); + QGridLayout *headGrid = new QGridLayout( gHead->layout(), 2, 3 ); + + QLabel *lHeadLeft = new QLabel( i18n( "Left:" ), gHead ); + headGrid->addWidget( lHeadLeft, 0, 0 ); + + eHeadLeft = new QLineEdit( gHead ); + headGrid->addWidget( eHeadLeft, 1, 0 ); + eHeadLeft->setText( hf.headLeft ); + + QLabel *lHeadMid = new QLabel( i18n( "Mid:" ), gHead ); + headGrid->addWidget( lHeadMid, 0, 1 ); + + eHeadMid = new QLineEdit( gHead ); + headGrid->addWidget( eHeadMid, 1, 1 ); + eHeadMid->setText( hf.headMid ); + + QLabel *lHeadRight = new QLabel( i18n( "Right:" ), gHead ); + headGrid->addWidget( lHeadRight, 0, 2 ); + + eHeadRight = new QLineEdit( gHead ); + headGrid->addWidget( eHeadRight, 1, 2 ); + eHeadRight->setText( hf.headRight ); + + grid2->addMultiCellWidget( gHead, 0, 1, 0, 1 ); + + // ------------- footer --------------- + QGroupBox *gFoot = new QGroupBox( 0, Qt::Vertical, i18n( "Foot Line" ), tab2 ); + gFoot->layout()->setSpacing(KDialog::spacingHint()); + gFoot->layout()->setMargin(KDialog::marginHint()); + QGridLayout *footGrid = new QGridLayout( gFoot->layout(), 2, 3 ); + + QLabel *lFootLeft = new QLabel( i18n( "Left:" ), gFoot ); + footGrid->addWidget( lFootLeft, 0, 0 ); + + eFootLeft = new QLineEdit( gFoot ); + footGrid->addWidget( eFootLeft, 1, 0 ); + eFootLeft->setText( hf.footLeft ); + + QLabel *lFootMid = new QLabel( i18n( "Mid:" ), gFoot ); + footGrid->addWidget( lFootMid, 0, 1 ); + + eFootMid = new QLineEdit( gFoot ); + footGrid->addWidget( eFootMid, 1, 1 ); + eFootMid->setText( hf.footMid ); + + QLabel *lFootRight = new QLabel( i18n( "Right:" ), gFoot ); + footGrid->addWidget( lFootRight, 0, 2 ); + + eFootRight = new QLineEdit( gFoot ); + footGrid->addWidget( eFootRight, 1, 2 ); + eFootRight->setText( hf.footRight ); + + grid2->addMultiCellWidget( gFoot, 2, 3, 0, 1 ); + + QLabel *lMacros2 = new QLabel( i18n( "You can insert several tags in the text:" ), tab2 ); + grid2->addMultiCellWidget( lMacros2, 4, 4, 0, 1 ); + + QLabel *lMacros3 = new QLabel( i18n("<qt><ul><li><sheet> The sheet name</li>" + "<li><page> The current page</li>" + "<li><pages> The total number of pages</li>" + "<li><name> The filename or URL</li>" + "<li><file> The filename with complete path or the URL</li></ul></qt>"), tab2 ); + grid2->addMultiCellWidget( lMacros3, 5, 6, 0, 0, Qt::AlignTop ); + + QLabel *lMacros4 = new QLabel( i18n("<qt><ul><li><time> The current time</li>" + "<li><date> The current date</li>" + "<li><author> Your full name</li>" + "<li><org> Your organization</li>" + "<li><email> Your email address</li></ul></qt>"), tab2 ); + grid2->addMultiCellWidget( lMacros4, 5, 6, 1, 1, Qt::AlignTop ); +} + +/*================================================================*/ +void KoPageLayoutDia::setupTab3() +{ + QWidget *tab3 = addPage(i18n( "Col&umns" )); + QHBoxLayout *lay = new QHBoxLayout(tab3); + m_columnsTab = new KoPageLayoutColumns(tab3, m_column, m_unit, m_layout); + m_columnsTab->layout()->setMargin(0); + lay->addWidget(m_columnsTab); + m_columnsTab->show(); + connect (m_columnsTab, SIGNAL( propertyChange(KoColumns&)), + this, SLOT (columnsUpdated( KoColumns&))); +} + +void KoPageLayoutDia::columnsUpdated(KoColumns &columns) { + m_column.columns = columns.columns; + m_column.ptColumnSpacing = columns.ptColumnSpacing; + if(m_pageSizeTab) + m_pageSizeTab->setColumns(columns); +} + +/*================================================================*/ +void KoPageLayoutDia::setupTab4(const KoKWHeaderFooter kwhf ) +{ + QWidget *tab4 = addPage(i18n( "H&eader && Footer" )); + QHBoxLayout *lay = new QHBoxLayout(tab4); + m_headerTab = new KoPageLayoutHeader(tab4, m_unit, kwhf); + m_headerTab->layout()->setMargin(0); + lay->addWidget(m_headerTab); + m_headerTab->show(); + +} + + +/* Validation when closing. Error messages are never liked, but + better let the users enter all values in any order, and have one + final validation, than preventing them from entering values. */ +void KoPageLayoutDia::slotOk() +{ + if( m_pageSizeTab ) + m_pageSizeTab->queryClose(); + KDialogBase::slotOk(); // accept +} + +#include <KoPageLayoutDia.moc> diff --git a/lib/kofficeui/KoPageLayoutDia.h b/lib/kofficeui/KoPageLayoutDia.h new file mode 100644 index 00000000..f3f1d932 --- /dev/null +++ b/lib/kofficeui/KoPageLayoutDia.h @@ -0,0 +1,200 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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. +*/ + +// Description: Page Layout Dialog (header) + +#ifndef __KOPGLAYOUTDIA_H__ +#define __KOPGLAYOUTDIA_H__ + +#include <qgroupbox.h> +#include <KoGlobal.h> +#include <KoUnit.h> +#include <kdialogbase.h> +#include <KoPageLayout.h> + +class QButtonGroup; +class QComboBox; +class QLineEdit; +class QCheckBox; +class KoUnitDoubleSpinBox; +class KoPageLayoutColumns; +class KoPageLayoutSize; +class KoPageLayoutHeader; + +enum { FORMAT_AND_BORDERS = 1, HEADER_AND_FOOTER = 2, COLUMNS = 4, DISABLE_BORDERS = 8, + KW_HEADER_AND_FOOTER = 16, DISABLE_UNIT = 32 }; + +/** + * KoPagePreview. + * Internal to KoPageLayoutDia. + */ +class KoPagePreview : public QGroupBox +{ + Q_OBJECT + +public: + + /** + * constructor + */ + KoPagePreview( QWidget*, const char*, const KoPageLayout & ); + /** + * destructor + */ + ~KoPagePreview(); + + /** + * set page layout + */ + void setPageLayout( const KoPageLayout& ); + void setPageColumns( const KoColumns& ); + +protected: + + // paint page + void drawContents( QPainter* ); + + double m_pageHeight, m_pageWidth, m_textFrameX, m_textFrameY, m_textFrameWidth, m_textFrameHeight; + int columns; +}; + +class KoPageLayoutDiaPrivate; + +/** + * With this dialog the user can specify the layout of the paper during printing. + */ +class KOFFICEUI_EXPORT KoPageLayoutDia : public KDialogBase +{ + Q_OBJECT + +public: + + /** + * Constructor. + * + * @param parent The parent of the dialog. + * @param name The name of the dialog. + * @param layout The layout. + * @param headfoot The header and the footer. + * @param flags a variable with all features this dialog should show. + * @param unit The unit to use for displaying the values to the user. + * @param modal Whether the dialog is modal or not. + */ + KoPageLayoutDia( QWidget* parent, const char* name, + const KoPageLayout& layout, + const KoHeadFoot& headfoot, + int flags, KoUnit::Unit unit, bool modal=true ); + + /** + * Constructor. + * + * @param parent The parent of the dialog. + * @param name The name of the dialog. + * @param layout The layout. + * @param headfoot The header and the footer. + * @param columns The number of columns on the page. + * @param kwheadfoot The KWord header and footer. + * @param tabs The number of tabs. + * @param unit The unit to use for displaying the values to the user + */ + KoPageLayoutDia( QWidget* parent, const char* name, + const KoPageLayout& layout, + const KoHeadFoot& headfoot, + const KoColumns& columns, + const KoKWHeaderFooter& kwheadfoot, + int tabs, KoUnit::Unit unit ); + + /** + * Destructor. + */ + ~KoPageLayoutDia(); + + /** + * Show page layout dialog. + * See constructor for documentation on the parameters + */ + static bool pageLayout( KoPageLayout&, KoHeadFoot&, int tabs, KoUnit::Unit& unit, QWidget* parent = 0 ); + + /** + * Show page layout dialog. + * See constructor for documentation on the parameters + */ + static bool pageLayout( KoPageLayout&, KoHeadFoot&, KoColumns&, KoKWHeaderFooter&, int tabs, KoUnit::Unit& unit, QWidget* parent = 0 ); + /** + * Retrieves a standard page layout. + * Deprecated: better use KoPageLayout::standardLayout() + */ + static KDE_DEPRECATED KoPageLayout standardLayout(); + + /** + * Returns the layout + */ + const KoPageLayout& layout() const { return m_layout; } + + /** + * Returns the header and footer information + */ + KoHeadFoot headFoot() const; + + /** + * Returns the unit + */ + KoUnit::Unit unit() const { return m_unit; } + +private: + const KoColumns& columns() { return m_column; } + const KoKWHeaderFooter& headerFooter(); + + // setup tabs + void setupTab1( bool enableBorders ); + void setupTab2( const KoHeadFoot& hf ); + void setupTab3(); + void setupTab4( const KoKWHeaderFooter kwhf ); + + // dialog objects + QLineEdit *eHeadLeft; + QLineEdit *eHeadMid; + QLineEdit *eHeadRight; + QLineEdit *eFootLeft; + QLineEdit *eFootMid; + QLineEdit *eFootRight; + + // layout + KoPageLayout m_layout; + KoColumns m_column; + + KoUnit::Unit m_unit; + + int flags; + +protected slots: + virtual void slotOk(); + +private slots: + void sizeUpdated(KoPageLayout &layout); + void columnsUpdated(KoColumns &columns); + +private: + KoPageLayoutSize *m_pageSizeTab; + KoPageLayoutColumns *m_columnsTab; + KoPageLayoutHeader *m_headerTab; + KoPageLayoutDiaPrivate *d; +}; + +#endif diff --git a/lib/kofficeui/KoPageLayoutHeader.cpp b/lib/kofficeui/KoPageLayoutHeader.cpp new file mode 100644 index 00000000..ad5e018c --- /dev/null +++ b/lib/kofficeui/KoPageLayoutHeader.cpp @@ -0,0 +1,73 @@ +/* This file is part of the KDE project + * Copyright (C) 2005 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; version 2. + * + * 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 <KoPageLayoutHeader.h> +#include <KoPageLayoutHeader.moc> +#include <KoUnitWidgets.h> + +#include <qlayout.h> +#include <qcheckbox.h> + +KoPageLayoutHeader::KoPageLayoutHeader(QWidget *parent, KoUnit::Unit unit, const KoKWHeaderFooter &kwhf) + : KoPageLayoutHeaderBase(parent) { + m_headerFooters = kwhf; + QHBoxLayout *lay = new QHBoxLayout(headerSpacingPane); + m_headerSpacing = new KoUnitDoubleSpinBox( headerSpacingPane, 0.0, 999.0, 0.5, kwhf.ptHeaderBodySpacing, unit ); + lay->addWidget(m_headerSpacing); + + lay = new QHBoxLayout(footerSpacingPane); + m_footerSpacing = new KoUnitDoubleSpinBox( footerSpacingPane, 0.0, 999.0, 0.5, kwhf.ptFooterBodySpacing, unit ); + lay->addWidget(m_footerSpacing); + + lay = new QHBoxLayout(footnotePane); + m_footnoteSpacing = new KoUnitDoubleSpinBox( footnotePane, 0.0, 999.0, 0.5, kwhf.ptFootNoteBodySpacing, unit ); + lay->addWidget(m_footnoteSpacing); + + if ( kwhf.header == HF_FIRST_DIFF || kwhf.header == HF_FIRST_EO_DIFF ) + rhFirst->setChecked( true ); + if ( kwhf.header == HF_EO_DIFF || kwhf.header == HF_FIRST_EO_DIFF ) + rhEvenOdd->setChecked( true ); + if ( kwhf.footer == HF_FIRST_DIFF || kwhf.footer == HF_FIRST_EO_DIFF ) + rfFirst->setChecked( true ); + if ( kwhf.footer == HF_EO_DIFF || kwhf.footer == HF_FIRST_EO_DIFF ) + rfEvenOdd->setChecked( true ); +} + +const KoKWHeaderFooter& KoPageLayoutHeader::headerFooter() { + if ( rhFirst->isChecked() && rhEvenOdd->isChecked() ) + m_headerFooters.header = HF_FIRST_EO_DIFF; + else if ( rhFirst->isChecked() ) + m_headerFooters.header = HF_FIRST_DIFF; + else if ( rhEvenOdd->isChecked() ) + m_headerFooters.header = HF_EO_DIFF; + else + m_headerFooters.header = HF_SAME; + + m_headerFooters.ptHeaderBodySpacing = m_headerSpacing->value(); + m_headerFooters.ptFooterBodySpacing = m_footerSpacing->value(); + m_headerFooters.ptFootNoteBodySpacing = m_footnoteSpacing->value(); + if ( rfFirst->isChecked() && rfEvenOdd->isChecked() ) + m_headerFooters.footer = HF_FIRST_EO_DIFF; + else if ( rfFirst->isChecked() ) + m_headerFooters.footer = HF_FIRST_DIFF; + else if ( rfEvenOdd->isChecked() ) + m_headerFooters.footer = HF_EO_DIFF; + else + m_headerFooters.footer = HF_SAME; + return m_headerFooters; +} diff --git a/lib/kofficeui/KoPageLayoutHeader.h b/lib/kofficeui/KoPageLayoutHeader.h new file mode 100644 index 00000000..52239714 --- /dev/null +++ b/lib/kofficeui/KoPageLayoutHeader.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + * Copyright (C) 2005 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; version 2. + * + * 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. + */ + +#ifndef kopagelayoutheader_h +#define kopagelayoutheader_h + +#include <KoUnit.h> +#include <KoPageLayout.h> +#include <KoPageLayoutHeaderBase.h> + +class QWidget; +class KoUnitDoubleSpinBox; +class KoPagePreview; + +/** + * This class is a widget that shows the KoKWHeaderFooter data structure and allows the user to change it. + */ +class KoPageLayoutHeader : public KoPageLayoutHeaderBase { + Q_OBJECT + +public: + /** + * Contructor + * @param parent the parent widget + * @param unit the unit-type (mm/cm/inch) that the dialog should show + * @param kwhf the data that this widget will be filled with initially + */ + KoPageLayoutHeader(QWidget *parent, KoUnit::Unit unit, const KoKWHeaderFooter &kwhf); + /** + * @return the altered data as it is currently set by the user. + */ + const KoKWHeaderFooter& headerFooter(); + +private: + KoUnitDoubleSpinBox *m_headerSpacing, *m_footerSpacing, *m_footnoteSpacing; + + KoKWHeaderFooter m_headerFooters; +}; + +#endif + diff --git a/lib/kofficeui/KoPageLayoutHeaderBase.ui b/lib/kofficeui/KoPageLayoutHeaderBase.ui new file mode 100644 index 00000000..d46ca98e --- /dev/null +++ b/lib/kofficeui/KoPageLayoutHeaderBase.ui @@ -0,0 +1,221 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KoPageLayoutHeaderBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KoPageLayoutHeaderBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>445</width> + <height>437</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Header</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>rhFirst</cstring> + </property> + <property name="text"> + <string>Different header for the first page</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>rhEvenOdd</cstring> + </property> + <property name="text"> + <string>Different header for even and odd pages</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Spacing between header and body:</string> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>headerSpacingPane</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Footer</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>rfFirst</cstring> + </property> + <property name="text"> + <string>Different footer for the first page</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>rfEvenOdd</cstring> + </property> + <property name="text"> + <string>Different footer for even and odd pages</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>41</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Spacing between footer and body:</string> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>footerSpacingPane</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Footnote/Endnote</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Spacing between footnote and body:</string> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>footnotePane</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/lib/kofficeui/KoPageLayoutSize.cpp b/lib/kofficeui/KoPageLayoutSize.cpp new file mode 100644 index 00000000..6fdb23e6 --- /dev/null +++ b/lib/kofficeui/KoPageLayoutSize.cpp @@ -0,0 +1,350 @@ +/* This file is part of the KDE project + * Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + * Copyright (C) 2005 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; version 2. + * + * 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 <KoPageLayoutDia.h> +#include <KoPageLayoutSize.h> +#include <KoUnit.h> +#include <KoUnitWidgets.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kdebug.h> + +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <qhbox.h> +#include <qvgroupbox.h> +#include <qhbuttongroup.h> + +KoPageLayoutSize::KoPageLayoutSize(QWidget *parent, const KoPageLayout& layout, KoUnit::Unit unit,const KoColumns& columns, bool unitChooser, bool enableBorders) + : QWidget(parent), m_blockSignals(false) { + m_layout = layout; + m_unit = unit; + + QGridLayout *grid1 = new QGridLayout( this, 5, 2, 0, KDialog::spacingHint() ); + if ( unitChooser ) { + // ------------- unit _______________ + QWidget* unitFrame = new QWidget( this ); + grid1->addWidget( unitFrame, 0, 0, Qt::AlignLeft ); + QBoxLayout* unitLayout = new QHBoxLayout( unitFrame, 0, KDialog::spacingHint() ); + + // label unit + QLabel *lpgUnit = new QLabel( i18n( "Unit:" ), unitFrame ); + unitLayout->addWidget( lpgUnit, 0, Qt::AlignRight | Qt::AlignVCenter ); + + // combo unit + QComboBox *cpgUnit = new QComboBox( false, unitFrame, "cpgUnit" ); + lpgUnit->setBuddy( cpgUnit ); + cpgUnit->insertStringList( KoUnit::listOfUnitName() ); + cpgUnit->setCurrentItem( unit ); + unitLayout->addWidget( cpgUnit, 0, Qt::AlignLeft | Qt::AlignVCenter ); + connect( cpgUnit, SIGNAL( activated( int ) ), this, SLOT( setUnitInt( int ) ) ); + } + else { + QString str=KoUnit::unitDescription(unit); + + QLabel *lpgUnit = new QLabel( i18n("All values are given in %1.").arg(str), this ); + grid1->addWidget( lpgUnit, 0, 0, Qt::AlignLeft ); + } + + // -------------- page size ----------------- + QVGroupBox *formatFrame = new QVGroupBox( i18n( "Page Size" ), this ); + grid1->addWidget( formatFrame, 1, 0 ); + + QHBox *formatPageSize = new QHBox( formatFrame ); + formatPageSize->setSpacing( KDialog::spacingHint() ); + + // label page size + QLabel *lpgFormat = new QLabel( i18n( "&Size:" ), formatPageSize ); + + // combo size + cpgFormat = new QComboBox( false, formatPageSize, "cpgFormat" ); + cpgFormat->insertStringList( KoPageFormat::allFormats() ); + lpgFormat->setBuddy( cpgFormat ); + connect( cpgFormat, SIGNAL( activated( int ) ), this, SLOT( formatChanged( int ) ) ); + + // spacer + formatPageSize->setStretchFactor( new QWidget( formatPageSize ), 10 ); + + QHBox *formatCustomSize = new QHBox( formatFrame ); + formatCustomSize->setSpacing( KDialog::spacingHint() ); + + // label width + QLabel *lpgWidth = new QLabel( i18n( "&Width:" ), formatCustomSize ); + + // linedit width + epgWidth = new KoUnitDoubleSpinBox( formatCustomSize, "Width" ); + lpgWidth->setBuddy( epgWidth ); + if ( m_layout.format != PG_CUSTOM ) + epgWidth->setEnabled( false ); + connect( epgWidth, SIGNAL( valueChangedPt(double) ), this, SLOT( widthChanged(double) ) ); + + // label height + QLabel *lpgHeight = new QLabel( i18n( "&Height:" ), formatCustomSize ); + + // linedit height + epgHeight = new KoUnitDoubleSpinBox( formatCustomSize, "Height" ); + lpgHeight->setBuddy( epgHeight ); + if ( m_layout.format != PG_CUSTOM ) + epgHeight->setEnabled( false ); + connect( epgHeight, SIGNAL( valueChangedPt(double ) ), this, SLOT( heightChanged(double) ) ); + + // --------------- orientation --------------- + m_orientGroup = new QHButtonGroup( i18n( "Orientation" ), this ); + m_orientGroup->setInsideSpacing( KDialog::spacingHint() ); + grid1->addWidget( m_orientGroup, 2, 0 ); + + QLabel* lbPortrait = new QLabel( m_orientGroup ); + lbPortrait->setPixmap( QPixmap( UserIcon( "koPortrait" ) ) ); + lbPortrait->setMaximumWidth( lbPortrait->pixmap()->width() ); + new QRadioButton( i18n("&Portrait"), m_orientGroup ); + + QLabel* lbLandscape = new QLabel( m_orientGroup ); + lbLandscape->setPixmap( QPixmap( UserIcon( "koLandscape" ) ) ); + lbLandscape->setMaximumWidth( lbLandscape->pixmap()->width() ); + new QRadioButton( i18n("La&ndscape"), m_orientGroup ); + + connect( m_orientGroup, SIGNAL (clicked (int)), this, SLOT( orientationChanged(int) )); + + // --------------- page margins --------------- + QVGroupBox *marginsFrame = new QVGroupBox( i18n( "Margins" ), this ); + marginsFrame->setColumnLayout( 0, Qt::Vertical ); + marginsFrame->setMargin( KDialog::marginHint() ); + grid1->addWidget( marginsFrame, 3, 0 ); + + QGridLayout *marginsLayout = new QGridLayout( marginsFrame->layout(), 3, 3, + KDialog::spacingHint() ); + + // left margin + ebrLeft = new KoUnitDoubleSpinBox( marginsFrame, "Left" ); + marginsLayout->addWidget( ebrLeft, 1, 0 ); + connect( ebrLeft, SIGNAL( valueChangedPt( double ) ), this, SLOT( leftChanged( double ) ) ); + + // right margin + ebrRight = new KoUnitDoubleSpinBox( marginsFrame, "Right" ); + marginsLayout->addWidget( ebrRight, 1, 2 ); + connect( ebrRight, SIGNAL( valueChangedPt( double ) ), this, SLOT( rightChanged( double ) ) ); + + // top margin + ebrTop = new KoUnitDoubleSpinBox( marginsFrame, "Top" ); + marginsLayout->addWidget( ebrTop, 0, 1 , Qt::AlignCenter ); + connect( ebrTop, SIGNAL( valueChangedPt( double ) ), this, SLOT( topChanged( double ) ) ); + + // bottom margin + ebrBottom = new KoUnitDoubleSpinBox( marginsFrame, "Bottom" ); + marginsLayout->addWidget( ebrBottom, 2, 1, Qt::AlignCenter ); + connect( ebrBottom, SIGNAL( valueChangedPt( double ) ), this, SLOT( bottomChanged( double ) ) ); + + // ------------- preview ----------- + pgPreview = new KoPagePreview( this, "Preview", m_layout ); + grid1->addMultiCellWidget( pgPreview, 1, 3, 1, 1 ); + + // ------------- spacers ----------- + QWidget* spacer1 = new QWidget( this ); + QWidget* spacer2 = new QWidget( this ); + spacer1->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Expanding ) ); + spacer2->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Expanding ) ); + grid1->addWidget( spacer1, 4, 0 ); + grid1->addWidget( spacer2, 4, 1 ); + + setValues(); + updatePreview(); + pgPreview->setPageColumns( columns ); + setEnableBorders(enableBorders); +} + +void KoPageLayoutSize::setEnableBorders(bool on) { + m_haveBorders = on; + ebrLeft->setEnabled( on ); + ebrRight->setEnabled( on ); + ebrTop->setEnabled( on ); + ebrBottom->setEnabled( on ); + + // update m_layout + m_layout.ptLeft = on?ebrLeft->value():0; + m_layout.ptRight = on?ebrRight->value():0; + m_layout.ptTop = on?ebrTop->value():0; + m_layout.ptBottom = on?ebrBottom->value():0; + + // use updated m_layout + updatePreview(); + emit propertyChange(m_layout); +} + +void KoPageLayoutSize::updatePreview() { + pgPreview->setPageLayout( m_layout ); +} + +void KoPageLayoutSize::setValues() { + // page format + cpgFormat->setCurrentItem( m_layout.format ); + // orientation + m_orientGroup->setButton( m_layout.orientation == PG_PORTRAIT ? 0: 1 ); + + setUnit( m_unit ); + updatePreview(); +} + +void KoPageLayoutSize::setUnit( KoUnit::Unit unit ) { + m_unit = unit; + m_blockSignals = true; // due to non-atomic changes the propertyChange emits should be blocked + + epgWidth->setUnit( m_unit ); + epgWidth->setMinMaxStep( 0, KoUnit::fromUserValue( 9999, m_unit ), KoUnit::fromUserValue( 0.01, m_unit ) ); + epgWidth->changeValue( m_layout.ptWidth ); + + epgHeight->setUnit( m_unit ); + epgHeight->setMinMaxStep( 0, KoUnit::fromUserValue( 9999, m_unit ), KoUnit::fromUserValue( 0.01, m_unit ) ); + epgHeight->changeValue( m_layout.ptHeight ); + + double dStep = KoUnit::fromUserValue( 0.2, m_unit ); + + ebrLeft->setUnit( m_unit ); + ebrLeft->changeValue( m_layout.ptLeft ); + ebrLeft->setMinMaxStep( 0, m_layout.ptWidth, dStep ); + + ebrRight->setUnit( m_unit ); + ebrRight->changeValue( m_layout.ptRight ); + ebrRight->setMinMaxStep( 0, m_layout.ptWidth, dStep ); + + ebrTop->setUnit( m_unit ); + ebrTop->changeValue( m_layout.ptTop ); + ebrTop->setMinMaxStep( 0, m_layout.ptHeight, dStep ); + + ebrBottom->setUnit( m_unit ); + ebrBottom->changeValue( m_layout.ptBottom ); + ebrBottom->setMinMaxStep( 0, m_layout.ptHeight, dStep ); + + m_blockSignals = false; +} + +void KoPageLayoutSize::setUnitInt( int unit ) { + setUnit((KoUnit::Unit)unit); +} + +void KoPageLayoutSize::formatChanged( int format ) { + if ( ( KoFormat )format == m_layout.format ) + return; + m_layout.format = ( KoFormat )format; + bool enable = (KoFormat) format == PG_CUSTOM; + epgWidth->setEnabled( enable ); + epgHeight->setEnabled( enable ); + + if ( m_layout.format != PG_CUSTOM ) { + m_layout.ptWidth = MM_TO_POINT( KoPageFormat::width( + m_layout.format, m_layout.orientation ) ); + m_layout.ptHeight = MM_TO_POINT( KoPageFormat::height( + m_layout.format, m_layout.orientation ) ); + } + + epgWidth->changeValue( m_layout.ptWidth ); + epgHeight->changeValue( m_layout.ptHeight ); + + updatePreview( ); + emit propertyChange(m_layout); +} + +void KoPageLayoutSize::orientationChanged(int which) { + m_layout.orientation = which == 0 ? PG_PORTRAIT : PG_LANDSCAPE; + + // swap dimension + double val = epgWidth->value(); + epgWidth->changeValue(epgHeight->value()); + epgHeight->changeValue(val); + // and adjust margins + m_blockSignals = true; + val = ebrTop->value(); + if(m_layout.orientation == PG_PORTRAIT) { // clockwise + ebrTop->changeValue(ebrRight->value()); + ebrRight->changeValue(ebrBottom->value()); + ebrBottom->changeValue(ebrLeft->value()); + ebrLeft->changeValue(val); + } else { // counter clockwise + ebrTop->changeValue(ebrLeft->value()); + ebrLeft->changeValue(ebrBottom->value()); + ebrBottom->changeValue(ebrRight->value()); + ebrRight->changeValue(val); + } + m_blockSignals = false; + + setEnableBorders(m_haveBorders); // will update preview+emit +} + +void KoPageLayoutSize::widthChanged(double width) { + if(m_blockSignals) return; + m_layout.ptWidth = width; + updatePreview(); + emit propertyChange(m_layout); +} +void KoPageLayoutSize::heightChanged(double height) { + if(m_blockSignals) return; + m_layout.ptHeight = height; + updatePreview( ); + emit propertyChange(m_layout); +} +void KoPageLayoutSize::leftChanged( double left ) { + if(m_blockSignals) return; + m_layout.ptLeft = left; + updatePreview(); + emit propertyChange(m_layout); +} +void KoPageLayoutSize::rightChanged(double right) { + if(m_blockSignals) return; + m_layout.ptRight = right; + updatePreview(); + emit propertyChange(m_layout); +} +void KoPageLayoutSize::topChanged(double top) { + if(m_blockSignals) return; + m_layout.ptTop = top; + updatePreview(); + emit propertyChange(m_layout); +} +void KoPageLayoutSize::bottomChanged(double bottom) { + if(m_blockSignals) return; + m_layout.ptBottom = bottom; + updatePreview(); + emit propertyChange(m_layout); +} + +bool KoPageLayoutSize::queryClose() { + if ( m_layout.ptLeft + m_layout.ptRight > m_layout.ptWidth ) { + KMessageBox::error( this, + i18n("The page width is smaller than the left and right margins."), + i18n("Page Layout Problem") ); + return false; + } + if ( m_layout.ptTop + m_layout.ptBottom > m_layout.ptHeight ) { + KMessageBox::error( this, + i18n("The page height is smaller than the top and bottom margins."), + i18n("Page Layout Problem") ); + return false; + } + return true; +} + +void KoPageLayoutSize::setColumns(KoColumns &columns) { + pgPreview->setPageColumns(columns); +} + +#include <KoPageLayoutSize.moc> diff --git a/lib/kofficeui/KoPageLayoutSize.h b/lib/kofficeui/KoPageLayoutSize.h new file mode 100644 index 00000000..ebdf49b6 --- /dev/null +++ b/lib/kofficeui/KoPageLayoutSize.h @@ -0,0 +1,118 @@ +/* This file is part of the KDE project + * Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + * Copyright (C) 2005 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; version 2. + * + * 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. + */ + +#ifndef kopagelayoutsize_h +#define kopagelayoutsize_h + +#include <qgroupbox.h> +#include <KoGlobal.h> +#include <KoUnit.h> +#include <kdialogbase.h> +#include <KoPageLayout.h> +#include <KoPageLayoutDia.h> + +class QComboBox; +class KoUnitDoubleSpinBox; +class KoPageLayoutColumns; + +/** + * This class is a widget that shows the KoPageLayout data structure and allows the user to change it. + */ +class KoPageLayoutSize : public QWidget { + Q_OBJECT + +public: + /** + * Contructor + * @param parent the parent widget + * @param layout the page layout that this widget should be initialzed with. + * @param unit the unit-type (mm/cm/inch) that the dialog should show + * @param columns the KoColumns (amout of columns) that the preview should be initialized with + * @param unitChooser if true a combobox with the unit-type is shown for the user to change + * @param enableBorders if true enable the user to change the margins (aka borders) of the page + */ + KoPageLayoutSize(QWidget *parent, const KoPageLayout& layout, KoUnit::Unit unit, + const KoColumns& columns, bool unitChooser, bool enableBorders); + + /** + * @return if the dialog is in a sane state and the values can be used. + */ + bool queryClose(); + /** + * Update the page preview widget with the param columns. + * @param columns the new columns + */ + void setColumns(KoColumns &columns); + + KoUnit::Unit unit() { return m_unit; } + +public slots: + /** + * Set a new unit for the widget updating the widgets. + * @param unit the new unit + */ + void setUnit( KoUnit::Unit unit ); + /** + * Enable the user to edit the page border size + * @param on if true enable the user to change the margins (aka borders) of the page + */ + void setEnableBorders(bool on); + +signals: + /** + * Emitted whenever the user changed something in the dialog. + * @param layout the update layout structure with currently displayed info. + * Note that the info may not be fully correct and physically possible (in which + * case queryClose will return false) + */ + void propertyChange(KoPageLayout &layout); + +protected: + QComboBox *cpgFormat; + KoUnitDoubleSpinBox *epgWidth; + KoUnitDoubleSpinBox *epgHeight; + KoUnitDoubleSpinBox *ebrLeft; + KoUnitDoubleSpinBox *ebrRight; + KoUnitDoubleSpinBox *ebrTop; + KoUnitDoubleSpinBox *ebrBottom; + KoPagePreview *pgPreview; + QButtonGroup *m_orientGroup; + +protected slots: + void formatChanged( int ); + void widthChanged( double ); + void heightChanged( double ); + void leftChanged( double ); + void rightChanged( double ); + void topChanged( double ); + void bottomChanged( double ); + void orientationChanged( int ); + void setUnitInt( int unit ); + +private: + void updatePreview(); + void setValues(); + + KoUnit::Unit m_unit; + KoPageLayout m_layout; + + bool m_blockSignals, m_haveBorders; +}; + +#endif diff --git a/lib/kofficeui/KoPartSelectAction.cpp b/lib/kofficeui/KoPartSelectAction.cpp new file mode 100644 index 00000000..f6795cf9 --- /dev/null +++ b/lib/kofficeui/KoPartSelectAction.cpp @@ -0,0 +1,80 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 David Faure <faure@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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "KoPartSelectAction.h" +#include "KoPartSelectDia.h" + +#include <kdebug.h> + +KoPartSelectAction::KoPartSelectAction( const QString& text, QObject* parent, const char* name ) + : KActionMenu( text, parent, name ) +{ + init(); +} + +KoPartSelectAction::KoPartSelectAction( const QString& text, const QString& icon, + QObject* parent, const char* name ) + : KActionMenu( text, icon, parent, name ) +{ + init(); +} + +KoPartSelectAction::KoPartSelectAction( const QString& text, const QString& icon, + QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KActionMenu( text, icon, parent, name ) +{ + if (receiver) + connect( this, SIGNAL( activated() ), receiver, slot ); + init(); +} + +void KoPartSelectAction::init() +{ + // Query for documents + m_lstEntries = KoDocumentEntry::query(); + QValueList<KoDocumentEntry>::Iterator it = m_lstEntries.begin(); + for( ; it != m_lstEntries.end(); ++it ) { + KService::Ptr serv = (*it).service(); + if (!serv->genericName().isEmpty()) { + KAction *action = new KAction( serv->genericName().replace('&',"&&"), serv->icon(), 0, + this, SLOT( slotActionActivated() ), + parentCollection(), serv->name().latin1() ); + insert( action ); + } + } + +} + +// Called when selecting a part +void KoPartSelectAction::slotActionActivated() +{ + QString servName = QString::fromLatin1( sender()->name() ); + KService::Ptr serv = KService::serviceByName( servName ); + m_documentEntry = KoDocumentEntry( serv ); + emit activated(); +} + +// Called when activating the toolbar button +void KoPartSelectAction::slotActivated() +{ + m_documentEntry = KoPartSelectDia::selectPart( 0L ); + emit activated(); +} + +#include "KoPartSelectAction.moc" diff --git a/lib/kofficeui/KoPartSelectAction.h b/lib/kofficeui/KoPartSelectAction.h new file mode 100644 index 00000000..4926dd9e --- /dev/null +++ b/lib/kofficeui/KoPartSelectAction.h @@ -0,0 +1,57 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 David Faure <faure@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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef koPartSelectAction_h +#define koPartSelectAction_h + +#include <kaction.h> +#include <KoQueryTrader.h> + +/** + * An action for inserting an embedded object. + * In a toolbar it presents itself as a button that opens the part-select dialog, + * but in a popupmenu it presents itself as a submenu with all available parts. + */ +class KOFFICEUI_EXPORT KoPartSelectAction : public KActionMenu +{ + Q_OBJECT + +public: + KoPartSelectAction( const QString& text, QObject* parent = 0, const char* name = 0 ); + KoPartSelectAction( const QString& text, const QString& icon, + QObject* parent = 0, const char* name = 0 ); + KoPartSelectAction( const QString& text, const QString& icon, + QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + KoDocumentEntry documentEntry() const { return m_documentEntry; } + + //virtual void plug(QWidget* widget, int index); + +protected: + void init(); + +protected slots: + virtual void slotActivated(); + void slotActionActivated(); + +private: + QValueList<KoDocumentEntry> m_lstEntries; + KoDocumentEntry m_documentEntry; +}; + +#endif diff --git a/lib/kofficeui/KoPartSelectDia.cpp b/lib/kofficeui/KoPartSelectDia.cpp new file mode 100644 index 00000000..773d1b88 --- /dev/null +++ b/lib/kofficeui/KoPartSelectDia.cpp @@ -0,0 +1,93 @@ +/* This file is part of the KDE libraries + Copyright (C) 1998 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <KoPartSelectDia.h> + +#include <kiconloader.h> +#include <klocale.h> +#include <qlistview.h> + +/**************************************************** + * + * KoPartSelectDia + * + ****************************************************/ + +KoPartSelectDia::KoPartSelectDia( QWidget* parent, const char* name ) : + KDialogBase( parent, name, TRUE, i18n("Insert Object"), KDialogBase::Ok | KDialogBase::Cancel ) +{ + listview = new QListView( this ); + listview->addColumn( i18n( "Object" ) ); + listview->addColumn( i18n( "Comment" ) ); + listview->setAllColumnsShowFocus( TRUE ); + listview->setShowSortIndicator( TRUE ); + setMainWidget( listview ); + connect( listview, SIGNAL( doubleClicked( QListViewItem * ) ), + this, SLOT( slotOk() ) ); + connect( listview, SIGNAL( selectionChanged( QListViewItem * ) ), + this, SLOT( selectionChanged( QListViewItem * ) ) ); + + // Query for documents + m_lstEntries = KoDocumentEntry::query(); + QValueList<KoDocumentEntry>::Iterator it = m_lstEntries.begin(); + for( ; it != m_lstEntries.end(); ++it ) { + KService::Ptr serv = (*it).service(); + if (!serv->genericName().isEmpty()) { + QListViewItem *item = new QListViewItem( listview, serv->name(), serv->genericName() ); + item->setPixmap( 0, SmallIcon( serv->icon() ) ); + } + } + + selectionChanged( 0 ); + setFocus(); + resize( listview->sizeHint().width() + 20, 300 ); +} + +void KoPartSelectDia::selectionChanged( QListViewItem *item ) +{ + enableButtonOK( item != 0 ); +} + +KoDocumentEntry KoPartSelectDia::entry() +{ + if ( listview->currentItem() ) { + QValueList<KoDocumentEntry>::Iterator it = m_lstEntries.begin(); + for ( ; it != m_lstEntries.end(); ++it ) { + if ( ( *it ).service()->name() == listview->currentItem()->text( 0 ) ) + return *it; + } + } + return KoDocumentEntry(); +} + +KoDocumentEntry KoPartSelectDia::selectPart( QWidget *parent ) +{ + KoDocumentEntry e; + + KoPartSelectDia *dlg = new KoPartSelectDia( parent, "PartSelect" ); + dlg->setFocus(); + if (dlg->exec() == QDialog::Accepted) + e = dlg->entry(); + + delete dlg; + + return e; +} + +#include <KoPartSelectDia.moc> diff --git a/lib/kofficeui/KoPartSelectDia.h b/lib/kofficeui/KoPartSelectDia.h new file mode 100644 index 00000000..b7af305d --- /dev/null +++ b/lib/kofficeui/KoPartSelectDia.h @@ -0,0 +1,70 @@ +/* This file is part of the KDE libraries + Copyright (C) 1998 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef DlgPartSelect_included +#define DlgPartSelect_included + +#include <kdialogbase.h> +#include <KoQueryTrader.h> + +class QListView; +class QListViewItem; +class QPushButton; + +/** + * This dialog presents the user all available + * KOffice components ( KSpread, KWord etc ) with name + * and mini icon. The user may select one and + * the corresponding KoDocumentEntry is returned. + */ +class KOFFICEUI_EXPORT KoPartSelectDia : public KDialogBase +{ + Q_OBJECT + +public: + + /** + * Constructor. + */ + KoPartSelectDia( QWidget* parent = 0, const char* name = 0 ); + + /** + * Retrieves the result of the part selection. + * + * @return A document entry. + */ + KoDocumentEntry entry(); + + /** + * Convenience function for using the dialog. + * + * @returns the KoDocumentEntry of the selected KOffice components + * or an empty entry. + */ + static KoDocumentEntry selectPart( QWidget *parent = 0L ); + +private slots: + void selectionChanged( QListViewItem * ); + +private: + QValueList<KoDocumentEntry> m_lstEntries; + QListView *listview; +}; + +#endif diff --git a/lib/kofficeui/KoPen.cpp b/lib/kofficeui/KoPen.cpp new file mode 100644 index 00000000..4fa77af1 --- /dev/null +++ b/lib/kofficeui/KoPen.cpp @@ -0,0 +1,69 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 Thorsten Zachmann <zachmann@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 "KoPen.h" + +#include <../kotext/KoTextZoomHandler.h> + +KoPen::KoPen() + : QPen() +{ + m_pointWidth = 1.0; +} + +KoPen::KoPen(const QColor& _color, double _pointWidth, Qt::PenStyle _style) + : QPen() +{ + setColor(_color); + setPointWidth(_pointWidth); + setStyle(_style); +} + +KoPen::KoPen(const QColor& _color) + : QPen(_color) +{ + m_pointWidth = 1.0; +} + +KoPen::~KoPen() +{ +} + +bool KoPen::operator==( const KoPen &p ) const +{ + return color() == p.color() && style() == p.style() && m_pointWidth == p.pointWidth(); +} + +bool KoPen::operator!=( const KoPen &p ) const +{ + return color() != p.color() || style() != p.style() || m_pointWidth != p.pointWidth(); +} + +void KoPen::setPointWidth(double w) +{ + m_pointWidth = w; +} + +QPen KoPen::zoomedPen(KoZoomHandler* zoomHandler) +{ + QPen pen = *this; + pen.setWidth(zoomHandler->zoomItY(m_pointWidth)); + + return pen; +} diff --git a/lib/kofficeui/KoPen.h b/lib/kofficeui/KoPen.h new file mode 100644 index 00000000..87124cef --- /dev/null +++ b/lib/kofficeui/KoPen.h @@ -0,0 +1,68 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 Thorsten Zachmann <zachmann@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. +*/ +#ifndef KOPEN_H +#define KOPEN_H + +#include <qpen.h> + +class KoZoomHandler; + +/** + * Pen that handles line widths in points + */ +class KoPen : public QPen +{ + public: + KoPen(); + KoPen(const QColor& _color, double _pointWidth, Qt::PenStyle _style); + KoPen(const QColor& _color); + ~KoPen(); + + /** + * @brief Compare pens if they are equal + * + * Two pens are equal if they have equal styles, widths and colors. + * + * @return true if the pens are equal, false otherwise + */ + bool operator==( const KoPen &p ) const; + + /** + * @brief Compare pens if they differ + * + * Two pens are different if they have different styles, widths or colors. + * + * @return true if the pens are different, false otherwise + */ + bool operator!=( const KoPen &p ) const; + + /// Set the pen width in points + void setPointWidth(double width); + /// KoPen width in points + double pointWidth() const { return m_pointWidth; } + + /// Returns a zoomed QPen + QPen zoomedPen(KoZoomHandler* zoomHandler); + + private: + double m_pointWidth; +}; + +#endif diff --git a/lib/kofficeui/KoPictureFilePreview.cpp b/lib/kofficeui/KoPictureFilePreview.cpp new file mode 100644 index 00000000..7f27b940 --- /dev/null +++ b/lib/kofficeui/KoPictureFilePreview.cpp @@ -0,0 +1,121 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2002 Nicolas GOUTTE <goutte@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 "KoPictureFilePreview.h" +#include "KoPictureFilePreview.moc" +#include <kdialog.h> +#include <klocale.h> +#include <kurl.h> +#include <qbitmap.h> +#include <qlayout.h> +#include <qfileinfo.h> +#include <qpainter.h> +#include <qscrollview.h> + +#include <kdebug.h> + +#include <KoPicture.h> + +/** + * This class implements the actual widget that shows the image. + * It is a scrollview, to have scrollbars if the image is big, + * and it supports both pixmaps and cliparts + */ +class KoPictureFilePreviewWidget : public QScrollView +{ +public: + KoPictureFilePreviewWidget( QWidget *parent ) + : QScrollView( parent ) { viewport()->setBackgroundMode( PaletteBase ); } + + bool setPicture( const KURL& url ) + { + KoPicture picture; + if ( url.isLocalFile() ) + { + if ( !picture.loadFromFile( url.path() ) ) + { + return false; + } + } + else + { + // ### TODO: find a way to avoid to download the file again later + if ( !picture.setKeyAndDownloadPicture( url, this ) ) + { + return false; + } + } + m_size = picture.getOriginalSize(); + m_picture = picture; + resizeContents( m_size.width(), m_size.height() ); + repaintContents(); + return true; + } + + void setNullPicture(void) + { + m_picture=KoPicture(); + m_size=QSize(); + } + + void drawContents( QPainter *p, int, int, int, int ) + { + p->setBackgroundColor( Qt::white ); + // Be sure that the background is white (for transparency) + p->fillRect(0, 0, m_size.width(), m_size.height(), QBrush( Qt::white )); + m_picture.draw( *p, 0 ,0, m_size.width(), m_size.height()); + } + +private: + KoPicture m_picture; + QSize m_size; +}; + +KoPictureFilePreview::KoPictureFilePreview( QWidget *parent ) + : KPreviewWidgetBase( parent ) +{ + QVBoxLayout *vb = new QVBoxLayout( this, KDialog::marginHint() ); + m_widget = new KoPictureFilePreviewWidget( this ); + vb->addWidget( m_widget, 1 ); +} + +void KoPictureFilePreview::showPreview( const KURL &u ) +{ + m_widget->setPicture( u ); +} + +void KoPictureFilePreview::clearPreview() +{ + m_widget->setNullPicture(); +} + +QString KoPictureFilePreview::clipartPattern() +{ + return i18n( "*.svg *.wmf *.qpic|Clipart (*.svg *.wmf *.qpic)" ); +} + +QStringList KoPictureFilePreview::clipartMimeTypes() +{ + QStringList lst; + lst << "image/svg+xml"; + lst << "image/x-wmf"; + lst << "image/x-vnd.trolltech.qpicture"; + return lst; +} diff --git a/lib/kofficeui/KoPictureFilePreview.h b/lib/kofficeui/KoPictureFilePreview.h new file mode 100644 index 00000000..28d6a3e6 --- /dev/null +++ b/lib/kofficeui/KoPictureFilePreview.h @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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. +*/ + +#ifndef kopicturefilepreview_h +#define kopicturefilepreview_h + +#include <kpreviewwidgetbase.h> +#include <koffice_export.h> +class KoPictureFilePreviewWidget; + +/** + * A preview widget for KFileDialog that supports both pixmaps and cliparts. + * + * If fd is a KFileDialog *, + * fd->setPreviewWidget( new KoPictureFilePreview( fd ) ); + */ +class KOFFICEUI_EXPORT KoPictureFilePreview : public KPreviewWidgetBase +{ + Q_OBJECT + +public: + KoPictureFilePreview( QWidget *parent ); + + /** + * @return a list of patterns of all supported clipart formats. + * + * These patterns can be passed to KFileDialog::getOpenFileName + * for instance. + */ + static QString clipartPattern(); + + /** + * @return list of mimetypes for all supported clipart formats. + */ + static QStringList clipartMimeTypes(); + +public slots: + virtual void showPreview(const KURL &url); + virtual void clearPreview(); + +private: + KoPictureFilePreviewWidget *m_widget; + // m_widget can act as a d pointer for BC purposes, no need for another one +}; + +#endif + + + + + diff --git a/lib/kofficeui/KoRuler.cpp b/lib/kofficeui/KoRuler.cpp new file mode 100644 index 00000000..e0ced466 --- /dev/null +++ b/lib/kofficeui/KoRuler.cpp @@ -0,0 +1,1202 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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. +*/ + +// Description: Ruler (header) + +/******************************************************************/ + +#include "KoRuler.h" +#include <klocale.h> +#include <kglobalsettings.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qpopupmenu.h> +#include <qtooltip.h> +#include <KoPageLayout.h> + +class KoRulerPrivate { +public: + KoRulerPrivate() { + } + ~KoRulerPrivate() {} + + QWidget *canvas; + int flags; + int oldMx, oldMy; + bool whileMovingBorderLeft, whileMovingBorderRight; + bool whileMovingBorderTop, whileMovingBorderBottom; + QPixmap pmFirst, pmLeft; + KoPageLayout layout; + KoTabChooser *tabChooser; + KoTabulatorList tabList; + // Do we have to remove a certain tab in the DC Event? + KoTabulator removeTab; + // The tab we're moving / clicking on - basically only valid between press and release time + KoTabulator currTab; + // The action we're currently doing - basically only valid between press and release time + KoRuler::Action action; + QPopupMenu *rb_menu; + int mRemoveTab, mPageLayout; // menu item ids + int frameEnd; + double i_right; + bool m_bReadWrite; + bool doubleClickedIndent; + bool rtl; + bool mousePressed; +}; + +// Equality test for tab positions in particular +static inline bool equals( double a, double b ) { + return kAbs( a - b ) < 1E-4; +} + + +/******************************************************************/ +/* Class: KoRuler */ +/******************************************************************/ + +const int KoRuler::F_TABS = 1; +const int KoRuler::F_INDENTS = 2; +const int KoRuler::F_HELPLINES = 4; +const int KoRuler::F_NORESIZE = 8; + +/*================================================================*/ +KoRuler::KoRuler( QWidget *_parent, QWidget *_canvas, Orientation _orientation, + const KoPageLayout& _layout, int _flags, KoUnit::Unit _unit, KoTabChooser *_tabChooser ) + : QFrame( _parent ), buffer( width(), height() ), m_zoom(1.0), m_1_zoom(1.0), + m_unit( _unit ) +{ + setWFlags( WResizeNoErase | WRepaintNoErase ); + setFrameStyle( MenuBarPanel ); + + d=new KoRulerPrivate(); + + d->tabChooser = _tabChooser; + + d->canvas = _canvas; + orientation = _orientation; + d->layout = _layout; + d->flags = _flags; + + d->m_bReadWrite=true; + d->doubleClickedIndent=false; + diffx = 0; + diffy = 0; + i_left=0.0; + i_first=0.0; + d->i_right=0.0; + + setMouseTracking( true ); + d->mousePressed = false; + d->action = A_NONE; + + d->oldMx = 0; + d->oldMy = 0; + d->rtl = false; + + showMPos = false; + mposX = 0; + mposY = 0; + gridSize=0.0; + hasToDelete = false; + d->whileMovingBorderLeft = d->whileMovingBorderRight = d->whileMovingBorderTop = d->whileMovingBorderBottom = false; + + d->pmFirst = UserIcon( "koRulerFirst" ); + d->pmLeft = UserIcon( "koRulerLeft" ); + d->currTab.type = T_INVALID; + + d->removeTab.type = T_INVALID; + if ( orientation == Qt::Horizontal ) { + frameStart = qRound( zoomIt(d->layout.ptLeft) ); + d->frameEnd = qRound( zoomIt(d->layout.ptWidth - d->layout.ptRight) ); + } else { + frameStart = qRound( zoomIt(d->layout.ptTop) ); + d->frameEnd = qRound( zoomIt(d->layout.ptHeight - d->layout.ptBottom) ); + } + m_bFrameStartSet = false; + + setupMenu(); + + // For compatibility, emitting doubleClicked shall emit openPageLayoutDia + connect( this, SIGNAL( doubleClicked() ), this, SIGNAL( openPageLayoutDia() ) ); +} + +/*================================================================*/ +KoRuler::~KoRuler() +{ + delete d->rb_menu; + delete d; +} + +void KoRuler::setPageLayoutMenuItemEnabled(bool b) +{ + d->rb_menu->setItemEnabled(d->mPageLayout, b); +} + +/*================================================================*/ +void KoRuler::setMousePos( int mx, int my ) +{ + if ( !showMPos || ( mx == mposX && my == mposY ) ) return; + + QPainter p( this ); + p.setRasterOp( Qt::NotROP ); + + if ( orientation == Qt::Horizontal ) { + if ( hasToDelete ) + p.drawLine( mposX, 1, mposX, height() - 1 ); + p.drawLine( mx, 1, mx, height() - 1 ); + hasToDelete = true; + } + else { + if ( hasToDelete ) + p.drawLine( 1, mposY, width() - 1, mposY ); + p.drawLine( 1, my, width() - 1, my ); + hasToDelete = true; + } + p.end(); + + mposX = mx; + mposY = my; +} + +// distance between the main lines (those with a number) +double KoRuler::lineDistance() const +{ + switch( m_unit ) { + case KoUnit::U_INCH: + return INCH_TO_POINT( m_zoom ); // every inch + case KoUnit::U_PT: + return 100.0 * m_zoom; // every 100 pt + case KoUnit::U_MM: + case KoUnit::U_CM: + case KoUnit::U_DM: + return CM_TO_POINT ( m_zoom ); // every cm + case KoUnit::U_PI: + return PI_TO_POINT ( 10.0 * m_zoom ); // every 10 pica + case KoUnit::U_DD: + return DD_TO_POINT( m_zoom ); // every diderot + case KoUnit::U_CC: + return CC_TO_POINT( 10.0 * m_zoom ); // every 10 cicero + } + // should never end up here + return 100.0 * m_zoom; +} + +/*================================================================*/ +void KoRuler::drawHorizontal( QPainter *_painter ) +{ + QFont font = KGlobalSettings::toolBarFont(); + QFontMetrics fm( font ); + resize( width(), QMAX( fm.height() + 4, 20 ) ); + + // Use a double-buffer pixmap + QPainter p( &buffer ); + p.fillRect( 0, 0, width(), height(), QBrush( colorGroup().brush( QColorGroup::Background ) ) ); + + int totalw = qRound( zoomIt(d->layout.ptWidth) ); + QString str; + + p.setBrush( colorGroup().brush( QColorGroup::Base ) ); + + // Draw white rect + QRect r; + if ( !d->whileMovingBorderLeft ) + r.setLeft( -diffx + frameStart ); + else + r.setLeft( d->oldMx ); + r.setTop( 0 ); + if ( !d->whileMovingBorderRight ) + r.setWidth(d->frameEnd-frameStart); + else + r.setRight( d->oldMx ); + r.setBottom( height() ); + + p.drawRect( r ); + p.setFont( font ); + + // Draw the numbers + double dist = lineDistance(); + int maxwidth = 0; + + for ( double i = 0.0;i <= (double)totalw;i += dist ) { + str = QString::number( KoUnit::toUserValue( i / m_zoom, m_unit ) ); + int textwidth = fm.width( str ); + maxwidth = QMAX( maxwidth, textwidth ); + } + + // Make sure that the ruler stays readable at lower zoom levels + while( dist <= maxwidth ) { + dist += lineDistance(); + } + + for ( double i = 0.0;i <= (double)totalw;i += dist ) { + str = QString::number( KoUnit::toUserValue( i / m_zoom, m_unit ) ); + int textwidth = fm.width( str ); + maxwidth = QMAX( maxwidth, textwidth ); + p.drawText( qRound(i) - diffx - qRound(textwidth * 0.5), + qRound(( height() - fm.height() ) * 0.5), + textwidth, height(), AlignLeft | AlignTop, str ); + } + + // Draw the medium-sized lines + // Only if we have enough space (i.e. not at 33%) + if ( dist > maxwidth + 2 ) + { + for ( double i = dist * 0.5;i <= (double)totalw;i += dist ) { + int ii=qRound(i); + p.drawLine( ii - diffx, 7, ii - diffx, height() - 7 ); + } + } + + // Draw the small lines + // Only if we have enough space (i.e. not at 33%) + if ( dist * 0.5 > maxwidth + 2 ) + { + for ( double i = dist * 0.25;i <= (double)totalw;i += dist * 0.5 ) { + int ii=qRound(i); + p.drawLine( ii - diffx, 9, ii - diffx, height() - 9 ); + } + } + + // Draw ending bar (at page width) + //int constant=zoomIt(1); + //p.drawLine( totalw - diffx + constant, 1, totalw - diffx + constant, height() - 1 ); + //p.setPen( colorGroup().color( QColorGroup::Base ) ); + //p.drawLine( totalw - diffx, 1, totalw - diffx, height() - 1 ); + + // Draw starting bar (at 0) + //p.setPen( colorGroup().color( QColorGroup::Text ) ); + //p.drawLine( -diffx, 1, -diffx, height() - 1 ); + //p.setPen( colorGroup().color( QColorGroup::Base ) ); + //p.drawLine( -diffx - constant, 1, -diffx - constant, height() - 1 ); + + // Draw the indents triangles + if ( d->flags & F_INDENTS ) { + int top = 1; + double halfPixmapWidth = d->pmFirst.width() * 0.5; + // Cumulate i_first with correct indent + double firstLineIdent = i_first + ( d->rtl ? d->i_right : i_left ); + p.drawPixmap( qRound( static_cast<double>(r.left()) + applyRtlAndZoom( firstLineIdent ) - halfPixmapWidth ), + top, d->pmFirst ); + + int bottom = height() - d->pmLeft.height() - 1; + halfPixmapWidth = d->pmLeft.width() * 0.5; + p.drawPixmap( qRound( static_cast<double>(r.left()) + zoomIt(i_left) - halfPixmapWidth ), + bottom, d->pmLeft ); + p.drawPixmap( qRound( static_cast<double>(r.right()) - zoomIt(d->i_right) - halfPixmapWidth ), + bottom, d->pmLeft ); + } + + // Show the mouse position + if ( d->action == A_NONE && showMPos ) { + p.setPen( colorGroup().color( QColorGroup::Text ) ); + p.drawLine( mposX, 1, mposX, height() - 1 ); + } + hasToDelete = false; + + // Draw the tabs + if ( d->tabChooser && ( d->flags & F_TABS ) && !d->tabList.isEmpty() ) + drawTabs( p ); + + p.end(); + _painter->drawPixmap( 0, 0, buffer ); +} + +/*================================================================*/ +void KoRuler::drawTabs( QPainter &_painter ) +{ + int ptPos = 0; + + _painter.setPen( QPen( colorGroup().color( QColorGroup::Text ), 2, SolidLine ) ); + // Check if we're in a mousemove event, removing a tab. + // In that case, we'll have to skip drawing that one. + bool willRemove = d->mousePressed && willRemoveTab( d->oldMy ) && d->currTab.type != T_INVALID; + + KoTabulatorList::ConstIterator it = d->tabList.begin(); + for ( ; it != d->tabList.end() ; it++ ) { + if ( willRemove && equals( d->currTab.ptPos, (*it).ptPos ) ) + continue; + ptPos = qRound(applyRtlAndZoom((*it).ptPos)) - diffx + frameStart; + switch ( (*it).type ) { + case T_LEFT: { + ptPos -= 4; + _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 ); + _painter.drawLine( ptPos + 5, 4, ptPos + 5, height() - 4 ); + } break; + case T_CENTER: { + ptPos -= 10; + _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 ); + _painter.drawLine( ptPos + 20 / 2, 4, ptPos + 20 / 2, height() - 4 ); + } break; + case T_RIGHT: { + ptPos -= 16; + _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 ); + _painter.drawLine( ptPos + 20 - 5, 4, ptPos + 20 - 5, height() - 4 ); + } break; + case T_DEC_PNT: { + ptPos -= 10; + _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 ); + _painter.drawLine( ptPos + 20 / 2, 4, ptPos + 20 / 2, height() - 4 ); + _painter.fillRect( ptPos + 20 / 2 + 2, height() - 9, 3, 3, + colorGroup().color( QColorGroup::Text ) ); + } break; + default: break; + } + } +} + +/*================================================================*/ +void KoRuler::drawVertical( QPainter *_painter ) +{ + QFont font = KGlobalSettings::toolBarFont(); + QFontMetrics fm( font ); + resize( QMAX( fm.height() + 4, 20 ), height() ); + + QPainter p( &buffer ); + p.fillRect( 0, 0, width(), height(), QBrush( colorGroup().brush( QColorGroup::Background ) ) ); + + int totalh = qRound( zoomIt(d->layout.ptHeight) ); + // Clip rect - this gives basically always a rect like (2,2,width-2,height-2) + QRect paintRect = _painter->clipRegion( QPainter::CoordPainter ).boundingRect(); + // Ruler rect + QRect rulerRect( 0, -diffy, width(), totalh ); + + if ( paintRect.intersects( rulerRect ) ) { + QString str; + + p.setBrush( colorGroup().brush( QColorGroup::Base ) ); + + // Draw white rect + QRect r; + if ( !d->whileMovingBorderTop ) + r.setTop( -diffy + frameStart ); + else + r.setTop( d->oldMy ); + r.setLeft( 0 ); + if ( !d->whileMovingBorderBottom ) + r.setHeight(d->frameEnd-frameStart); + else + r.setBottom( d->oldMy ); + r.setRight( width() ); + + p.drawRect( r ); + p.setFont( font ); + + // Draw the numbers + double dist = lineDistance(); + int maxheight = 0; + + for ( double i = 0.0;i <= (double)totalh;i += dist ) { + str = QString::number( KoUnit::toUserValue( i / m_zoom, m_unit ) ); + int textwidth = fm.width( str ); + maxheight = QMAX( maxheight, textwidth ); + } + + // Make sure that the ruler stays readable at lower zoom levels + while( dist <= maxheight ) { + dist += lineDistance(); + } + + for ( double i = 0.0;i <= (double)totalh;i += dist ) { + str = QString::number( KoUnit::toUserValue( i / m_zoom, m_unit ) ); + int textwidth = fm.width( str ); + int yOffset = qRound(i) - diffy + qRound(textwidth * 0.5); + if(yOffset > paintRect.bottom()) + break; // stop drawing when outside the to-paint-region + int textheight = fm.height(); + maxheight = QMAX( maxheight, textwidth ); + p.save(); + p.translate( qRound(( width() - textheight ) * 0.5), yOffset); + p.rotate( -90 ); + p.drawText( 0, 0, textwidth + 1, textheight, AlignLeft | AlignTop, str ); + p.restore(); + } + + // Draw the medium-sized lines + if ( dist > maxheight + 2 ) + { + for ( double i = dist * 0.5;i <= (double)totalh;i += dist ) { + int ii=qRound(i) - diffy; + if(ii > paintRect.bottom()) + break; // stop drawing when outside the to-paint-region + p.drawLine( 7, ii, width() - 7, ii); + } + } + + // Draw the small lines + if ( dist * 0.5 > maxheight + 2 ) + { + for ( double i = dist * 0.25;i <=(double)totalh;i += dist *0.5 ) { + int ii=qRound(i) - diffy; + if(ii > paintRect.bottom()) + break; // stop drawing when outside the to-paint-region + p.drawLine( 9, ii, width() - 9, ii); + } + } + + // Draw ending bar (at page height) + //p.drawLine( 1, totalh - diffy + 1, width() - 1, totalh - diffy + 1 ); + //p.setPen( colorGroup().color( QColorGroup::Base ) ); + //p.drawLine( 1, totalh - diffy, width() - 1, totalh - diffy ); + + // Draw starting bar (at 0) + //p.setPen( colorGroup().color( QColorGroup::Text ) ); + //p.drawLine( 1, -diffy, width() - 1, -diffy ); + //p.setPen( colorGroup().color( QColorGroup::Base ) ); + //p.drawLine( 1, -diffy - 1, width() - 1, -diffy - 1 ); + } + + // Show the mouse position + if ( d->action == A_NONE && showMPos ) { + p.setPen( colorGroup().color( QColorGroup::Text ) ); + p.drawLine( 1, mposY, width() - 1, mposY ); + } + hasToDelete = false; + + p.end(); + _painter->drawPixmap( 0, 0, buffer ); +} + +void KoRuler::mousePressEvent( QMouseEvent *e ) +{ + if( !d->m_bReadWrite) + return; + + d->oldMx = e->x(); + d->oldMy = e->y(); + d->mousePressed = true; + d->removeTab.type = T_INVALID; + + switch ( e->button() ) { + case RightButton: + if(d->currTab.type == T_INVALID || !(d->flags & F_TABS)) + d->rb_menu->setItemEnabled(d->mRemoveTab, false); + else + d->rb_menu->setItemEnabled(d->mRemoveTab, true); + d->rb_menu->popup( QCursor::pos() ); + d->action = A_NONE; + d->mousePressed = false; + return; + case MidButton: + // MMB shall do like double-click (it opens a dialog). + handleDoubleClick(); + return; + case LeftButton: + if ( d->action == A_BR_RIGHT || d->action == A_BR_LEFT ) { + if ( d->action == A_BR_RIGHT ) + d->whileMovingBorderRight = true; + else + d->whileMovingBorderLeft = true; + + if ( d->canvas ) + drawLine(d->oldMx, -1); + update(); + } else if ( d->action == A_BR_TOP || d->action == A_BR_BOTTOM ) { + if ( d->action == A_BR_TOP ) + d->whileMovingBorderTop = true; + else + d->whileMovingBorderBottom = true; + + if ( d->canvas ) { + QPainter p( d->canvas ); + p.setRasterOp( Qt::NotROP ); + p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy ); + p.end(); + } + update(); + } else if ( d->action == A_FIRST_INDENT || d->action == A_LEFT_INDENT || d->action == A_RIGHT_INDENT ) { + if ( d->canvas ) + drawLine(d->oldMx, -1); + } else if ( d->action == A_TAB ) { + if ( d->canvas && d->currTab.type != T_INVALID ) { + drawLine( qRound( applyRtlAndZoom(d->currTab.ptPos) ) + frameStart - diffx, -1 ); + } + } else if ( d->tabChooser && ( d->flags & F_TABS ) && d->tabChooser->getCurrTabType() != 0 ) { + int left = frameStart - diffx; + int right = d->frameEnd - diffx; + + if( e->x()-left < 0 || right-e->x() < 0 ) + return; + KoTabulator tab; + tab.filling = TF_BLANK; + tab.ptWidth = 0.5; + switch ( d->tabChooser->getCurrTabType() ) { + case KoTabChooser::TAB_LEFT: + tab.type = T_LEFT; + break; + case KoTabChooser::TAB_CENTER: + tab.type = T_CENTER; + break; + case KoTabChooser::TAB_RIGHT: + tab.type = T_RIGHT; + break; + case KoTabChooser::TAB_DEC_PNT: + tab.type = T_DEC_PNT; + tab.alignChar = KGlobal::locale()->decimalSymbol()[0]; + break; + default: break; + } + tab.ptPos = unZoomItRtl( e->x() + diffx - frameStart ); + + KoTabulatorList::Iterator it=d->tabList.begin(); + while ( it!=d->tabList.end() && tab > (*it) ) + ++it; + + d->tabList.insert(it, tab); + + d->action = A_TAB; + d->removeTab = tab; + d->currTab = tab; + + emit tabListChanged( d->tabList ); + update(); + } + else if ( d->flags & F_HELPLINES ) + { + setCursor( orientation == Qt::Horizontal ? + Qt::sizeVerCursor : Qt::sizeHorCursor ); + d->action = A_HELPLINES; + } + default: + break; + } +} + +void KoRuler::mouseReleaseEvent( QMouseEvent *e ) +{ + d->mousePressed = false; + + // Hacky, but necessary to prevent multiple tabs with the same coordinates (Werner) + bool fakeMovement=false; + if(d->removeTab.type != T_INVALID) { + mouseMoveEvent(e); + fakeMovement=true; + } + + if ( d->action == A_BR_RIGHT || d->action == A_BR_LEFT ) { + d->whileMovingBorderRight = false; + d->whileMovingBorderLeft = false; + + if ( d->canvas ) + drawLine(d->oldMx, -1); + update(); + emit newPageLayout( d->layout ); + } else if ( d->action == A_BR_TOP || d->action == A_BR_BOTTOM ) { + d->whileMovingBorderTop = false; + d->whileMovingBorderBottom = false; + + if ( d->canvas ) { + QPainter p( d->canvas ); + p.setRasterOp( Qt::NotROP ); + p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy ); + p.end(); + } + update(); + emit newPageLayout( d->layout ); + } else if ( d->action == A_FIRST_INDENT ) { + if ( d->canvas ) + drawLine(d->oldMx, -1); + update(); + emit newFirstIndent( i_first ); + } else if ( d->action == A_LEFT_INDENT ) { + if ( d->canvas ) + drawLine(d->oldMx, -1); + update(); + emit newLeftIndent( i_left ); + } else if ( d->action == A_RIGHT_INDENT ) { + if ( d->canvas ) + drawLine(d->oldMx, -1); + update(); + emit newRightIndent( d->i_right ); + } else if ( d->action == A_TAB ) { + if ( d->canvas && !fakeMovement ) { + drawLine( qRound( applyRtlAndZoom( d->currTab.ptPos ) ) + frameStart - diffx, -1); + } + if ( willRemoveTab( e->y() ) ) + { + d->tabList.remove(d->currTab); + } + qHeapSort( d->tabList ); + + // Delete the new tabulator if it is placed on top of another. + KoTabulatorList::ConstIterator tmpTab=d->tabList.begin(); + int count=0; + while(tmpTab!=d->tabList.end()) { + if( equals( (*tmpTab).ptPos, d->currTab.ptPos ) ) { + count++; + if(count > 1) { + d->tabList.remove(d->currTab); + break; + } + } + tmpTab++; + } + //searchTab( e->x() ); // DF: why set currTab here? + emit tabListChanged( d->tabList ); + update(); + } + else if( d->action == A_HELPLINES ) + { + emit addGuide( e->pos(), orientation == Qt::Horizontal, orientation == Qt::Horizontal ? size().height() : size().width() ); + emit addHelpline( e->pos(), orientation == Qt::Horizontal); + setCursor( ArrowCursor ); + } + d->currTab.type = T_INVALID; // added (DF) +} + +void KoRuler::mouseMoveEvent( QMouseEvent *e ) +{ + hasToDelete = false; + + int pw = d->frameEnd - frameStart; + int ph = qRound(zoomIt(d->layout.ptHeight)); + int left = frameStart - diffx; + int top = qRound(zoomIt(d->layout.ptTop)); + top -= diffy; + int right = d->frameEnd - diffx; + int bottom = qRound(zoomIt(d->layout.ptBottom)); + bottom = ph - bottom - diffy; + // Cumulate first-line-indent + int ip_first = qRound( zoomIt( i_first + ( d->rtl ? d->i_right : i_left) ) ); + int ip_left = qRound(zoomIt(i_left)); + int ip_right = qRound(zoomIt(d->i_right)); + + int mx = e->x(); + mx = mx+diffx < 0 ? 0 : mx; + int my = e->y(); + my = my+diffy < 0 ? 0 : my; + + QToolTip::remove( this); + switch ( orientation ) { + case Qt::Horizontal: { + if ( !d->mousePressed ) { + setCursor( ArrowCursor ); + d->action = A_NONE; + /////// ###### + // At the moment, moving the left and right border indicators + // is disabled when setFrameStartEnd has been called (i.e. in KWord) + // Changing the layout margins directly from it would be utterly wrong + // (just try the 2-columns modes...). What needs to be done is: + // emitting a signal frameResized in mouseReleaseEvent, when a left/right + // border has been moved, and in kword we need to update the margins from + // there, if the left border of the 1st column or the right border of the + // last column was moved... and find what to do with the other borders. + // And for normal frames, resize the frame without touching the page layout. + // All that is too much for now -> disabling. + if ( !m_bFrameStartSet ) + { + if ( mx > left - 5 && mx < left + 5 ) { + setCursor( Qt::sizeHorCursor ); + d->action = A_BR_LEFT; + } else if ( mx > right - 5 && mx < right + 5 ) { + setCursor( Qt::sizeHorCursor ); + d->action = A_BR_RIGHT; + } + } + if ( d->flags & F_INDENTS ) { + int firstX = d->rtl ? right - ip_first : left + ip_first; + if ( mx > firstX - 5 && mx < firstX + 5 && + my >= 2 && my <= d->pmFirst.size().height() + 2 ) { + QToolTip::add( this, i18n("First line indent") ); + setCursor( ArrowCursor ); + d->action = A_FIRST_INDENT; + } else if ( mx > left + ip_left - 5 && mx < left + ip_left + 5 && + my >= height() - d->pmLeft.size().height() - 2 && my <= height() - 2 ) { + QToolTip::add( this, i18n("Left indent") ); + setCursor( ArrowCursor ); + d->action = A_LEFT_INDENT; + } else if ( mx > right - ip_right - 5 && mx < right - ip_right + 5 && + my >= height() - d->pmLeft.size().height() - 2 && my <= height() - 2 ) { + QToolTip::add( this, i18n("Right indent") ); + setCursor( ArrowCursor ); + d->action = A_RIGHT_INDENT; + } + } + if ( d->flags & F_TABS ) + searchTab(mx); + } else { + // Calculate the new value. + int newPos=mx; + if( newPos!=right && gridSize!=0.0 && (e->state() & ShiftButton)==0) { // apply grid. + double grid=zoomIt(gridSize * 16); + newPos=qRound( ((newPos * 16 / grid) * grid) / 16 ); + } + if(newPos-left < 0) newPos=left; + else if (right-newPos < 0) newPos=right; + double newValue = unZoomIt(static_cast<double>(newPos) - frameStart + diffx); + + switch ( d->action ) { + case A_BR_LEFT: { + if ( d->canvas && mx < right-10 && mx+diffx-2 > 0) { + drawLine( d->oldMx, mx ); + d->layout.ptLeft = unZoomIt(static_cast<double>(mx + diffx)); + if( ip_left > right-left-15 ) { + ip_left=right-left-15; + ip_left=ip_left<0 ? 0 : ip_left; + i_left=unZoomIt( ip_left ); + emit newLeftIndent( i_left ); + } + if ( ip_right > right-left-15 ) { + ip_right=right-left-15; + ip_right=ip_right<0? 0 : ip_right; + d->i_right=unZoomIt( ip_right ); + emit newRightIndent( d->i_right ); + } + d->oldMx = mx; + d->oldMy = my; + update(); + } + else + return; + } break; + case A_BR_RIGHT: { + if ( d->canvas && mx > left+10 && mx+diffx <= pw-2) { + drawLine( d->oldMx, mx ); + d->layout.ptRight = unZoomIt(static_cast<double>(pw - ( mx + diffx ))); + if( ip_left > right-left-15 ) { + ip_left=right-left-15; + ip_left=ip_left<0 ? 0 : ip_left; + i_left=unZoomIt( ip_left ); + emit newLeftIndent( i_left ); + } + if ( ip_right > right-left-15 ) { + ip_right=right-left-15; + ip_right=ip_right<0? 0 : ip_right; + d->i_right=unZoomIt( ip_right ); + emit newRightIndent( d->i_right ); + } + d->oldMx = mx; + d->oldMy = my; + update(); + } + else + return; + } break; + case A_FIRST_INDENT: { + if ( d->canvas ) { + if (d->rtl) + newValue = unZoomIt(pw) - newValue - d->i_right; + else + newValue -= i_left; + if(newValue == i_first) break; + drawLine( d->oldMx, newPos); + d->oldMx=newPos; + i_first = newValue; + update(); + } + } break; + case A_LEFT_INDENT: { + if ( d->canvas ) { + //if (d->rtl) newValue = unZoomIt(pw) - newValue; + if(newValue == i_left) break; + + drawLine( d->oldMx, newPos); + i_left = newValue; + d->oldMx = newPos; + update(); + } + } break; + case A_RIGHT_INDENT: { + if ( d->canvas ) { + double rightValue = unZoomIt(right - newPos); + //if (d->rtl) rightValue = unZoomIt(pw) - rightValue; + if(rightValue == d->i_right) break; + + drawLine( d->oldMx, newPos); + d->i_right=rightValue; + d->oldMx = newPos; + update(); + } + } break; + case A_TAB: { + if ( d->canvas) { + if (d->rtl) newValue = unZoomIt(pw) - newValue; + if(newValue == d->currTab.ptPos) break; // no change + QPainter p( d->canvas ); + p.setRasterOp( Qt::NotROP ); + // prevent 1st drawLine when we just created a new tab + // (it's a NOT line) + double pt; + int pt_fr; + if( d->currTab != d->removeTab ) + { + pt = applyRtlAndZoom(d->currTab.ptPos); + pt_fr = qRound(pt) + frameStart - diffx; + p.drawLine( pt_fr, 0, pt_fr, d->canvas->height() ); + } + + KoTabulatorList::Iterator it = d->tabList.find( d->currTab ); + Q_ASSERT( it != d->tabList.end() ); + if ( it != d->tabList.end() ) + (*it).ptPos = newValue; + d->currTab.ptPos = newValue; + + pt = applyRtlAndZoom( newValue ); + pt_fr = qRound(pt) + frameStart - diffx; + p.drawLine( pt_fr, 0, pt_fr, d->canvas->height() ); + + p.end(); + d->oldMx = mx; + d->oldMy = my; + d->removeTab.type = T_INVALID; + update(); + } + } break; + default: break; + } + } + if( d->action == A_HELPLINES ) + { + emit moveGuide( e->pos(), true, size().height() ); + emit moveHelpLines( e->pos(), true ); + } + + return; + } break; + case Qt::Vertical: { + if ( !d->mousePressed ) { + setCursor( ArrowCursor ); + d->action = A_NONE; + if ( d->flags & F_NORESIZE ) + break; + if ( my > top - 5 && my < top + 5 ) { + QToolTip::add( this, i18n("Top margin") ); + setCursor( Qt::sizeVerCursor ); + d->action = A_BR_TOP; + } else if ( my > bottom - 5 && my < bottom + 5 ) { + QToolTip::add( this, i18n("Bottom margin") ); + setCursor( Qt::sizeVerCursor ); + d->action = A_BR_BOTTOM; + } + } else { + switch ( d->action ) { + case A_BR_TOP: { + if ( d->canvas && my < bottom-20 && my+diffy-2 > 0) { + QPainter p( d->canvas ); + p.setRasterOp( Qt::NotROP ); + p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy ); + p.drawLine( 0, my, d->canvas->width(), my ); + p.end(); + d->layout.ptTop = unZoomIt(static_cast<double>(my + diffy)); + d->oldMx = mx; + d->oldMy = my; + update(); + } + else + return; + } break; + case A_BR_BOTTOM: { + if ( d->canvas && my > top+20 && my+diffy < ph-2) { + QPainter p( d->canvas ); + p.setRasterOp( Qt::NotROP ); + p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy ); + p.drawLine( 0, my, d->canvas->width(), my ); + p.end(); + d->layout.ptBottom = unZoomIt(static_cast<double>(ph - ( my + diffy ))); + d->oldMx = mx; + d->oldMy = my; + update(); + } + else + return; + } break; + default: break; + } + } + + if( d->action == A_HELPLINES ) + { + emit moveGuide( e->pos(), false, size().width() ); + emit moveHelpLines( e->pos(), false ); + } + } break; + } + + d->oldMx = mx; + d->oldMy = my; +} + +void KoRuler::resizeEvent( QResizeEvent *e ) +{ + QFrame::resizeEvent( e ); + buffer.resize( size() ); +} + +void KoRuler::mouseDoubleClickEvent( QMouseEvent* ) +{ + handleDoubleClick(); +} + +void KoRuler::handleDoubleClick() +{ + if ( !d->m_bReadWrite ) + return; + + d->doubleClickedIndent = false; + if ( d->tabChooser && ( d->flags & F_TABS ) ) { + // Double-click and mousePressed inserted a tab -> need to remove it + if ( d->tabChooser->getCurrTabType() != 0 && d->removeTab.type != T_INVALID && !d->tabList.isEmpty()) { + uint c = d->tabList.count(); + d->tabList.remove( d->removeTab ); + Q_ASSERT( d->tabList.count() < c ); + + d->removeTab.type = T_INVALID; + d->currTab.type = T_INVALID; + emit tabListChanged( d->tabList ); + setCursor( ArrowCursor ); + update(); + // --- we didn't click on a tab, fall out to indents test --- + } else if ( d->action == A_TAB ) { + // Double-click on a tab + emit doubleClicked( d->currTab.ptPos ); // usually paragraph dialog + return; + } + } + + // When Binary Compatibility is broken this will hopefully emit a + // doubleClicked(int) to differentiate between double-clicking an + // indent and double-clicking the ruler + if ( d->flags & F_INDENTS ) { + if ( d->action == A_LEFT_INDENT || d->action == A_RIGHT_INDENT || d->action == A_FIRST_INDENT ) { + d->doubleClickedIndent = true; + emit doubleClicked(); // usually paragraph dialog + return; + } + } + + // Double-clicked nothing + d->action = A_NONE; + emit doubleClicked(); // usually page layout dialog +} + +void KoRuler::setTabList( const KoTabulatorList & _tabList ) +{ + d->tabList = _tabList; + qHeapSort(d->tabList); // "Trust no one." as opposed to "In David we trust." + + // Note that d->currTab and d->removeTab could now point to + // tabs which don't exist in d->tabList + + update(); +} + +double KoRuler::makeIntern( double _v ) +{ + return KoUnit::fromUserValue( _v, m_unit ); +} + +void KoRuler::setupMenu() +{ + d->rb_menu = new QPopupMenu(); + Q_CHECK_PTR( d->rb_menu ); + for ( uint i = 0 ; i <= KoUnit::U_LASTUNIT ; ++i ) + { + KoUnit::Unit unit = static_cast<KoUnit::Unit>( i ); + d->rb_menu->insertItem( KoUnit::unitDescription( unit ), i /*as id*/ ); + if ( m_unit == unit ) + d->rb_menu->setItemChecked( i, true ); + } + connect( d->rb_menu, SIGNAL( activated( int ) ), SLOT( slotMenuActivated( int ) ) ); + + d->rb_menu->insertSeparator(); + d->mPageLayout=d->rb_menu->insertItem(i18n("Page Layout..."), this, SLOT(pageLayoutDia())); + d->rb_menu->insertSeparator(); + d->mRemoveTab=d->rb_menu->insertItem(i18n("Remove Tabulator"), this, SLOT(rbRemoveTab())); + d->rb_menu->setItemEnabled( d->mRemoveTab, false ); +} + +void KoRuler::uncheckMenu() +{ + for ( uint i = 0 ; i <= KoUnit::U_LASTUNIT ; ++i ) + d->rb_menu->setItemChecked( i, false ); +} + +void KoRuler::setUnit( const QString& _unit ) +{ + setUnit( KoUnit::unit( _unit ) ); +} + +void KoRuler::setUnit( KoUnit::Unit unit ) +{ + m_unit = unit; + uncheckMenu(); + d->rb_menu->setItemChecked( m_unit, true ); + update(); +} + +void KoRuler::setZoom( const double& zoom ) +{ + if(zoom==m_zoom) + return; + if(zoom < 1E-4) // Don't do 0 or negative values + return; + m_zoom=zoom; + m_1_zoom=1/m_zoom; + update(); +} + +bool KoRuler::willRemoveTab( int y ) const +{ + return (y < -50 || y > height() + 25) && d->currTab.type != T_INVALID; +} + +void KoRuler::rbRemoveTab() { + + d->tabList.remove( d->currTab ); + d->currTab.type = T_INVALID; + emit tabListChanged( d->tabList ); + update(); +} + +void KoRuler::setReadWrite(bool _readWrite) +{ + d->m_bReadWrite=_readWrite; +} + +void KoRuler::searchTab(int mx) { + + int pos; + d->currTab.type = T_INVALID; + KoTabulatorList::ConstIterator it = d->tabList.begin(); + for ( ; it != d->tabList.end() ; ++it ) { + pos = qRound(applyRtlAndZoom((*it).ptPos)) - diffx + frameStart; + if ( mx > pos - 5 && mx < pos + 5 ) { + setCursor( Qt::sizeHorCursor ); + d->action = A_TAB; + d->currTab = *it; + break; + } + } +} + +void KoRuler::drawLine(int oldX, int newX) { + + QPainter p( d->canvas ); + p.setRasterOp( Qt::NotROP ); + p.drawLine( oldX, 0, oldX, d->canvas->height() ); + if(newX!=-1) + p.drawLine( newX, 0, newX, d->canvas->height() ); + p.end(); +} + +void KoRuler::showMousePos( bool _showMPos ) +{ + showMPos = _showMPos; + hasToDelete = false; + mposX = -1; + mposY = -1; + update(); +} + +void KoRuler::setOffset( int _diffx, int _diffy ) +{ + //kdDebug() << "KoRuler::setOffset " << _diffx << "," << _diffy << endl; + diffx = _diffx; + diffy = _diffy; + update(); +} + +void KoRuler::setFrameStartEnd( int _frameStart, int _frameEnd ) +{ + if ( _frameStart != frameStart || _frameEnd != d->frameEnd || !m_bFrameStartSet ) + { + frameStart = _frameStart; + d->frameEnd = _frameEnd; + // Remember that setFrameStartEnd was called. This activates a slightly + // different mode (when moving start and end positions). + m_bFrameStartSet = true; + update(); + } +} + +void KoRuler::setRightIndent( double _right ) +{ + d->i_right = makeIntern( _right ); + update(); +} + +void KoRuler::setDirection( bool rtl ) +{ + d->rtl = rtl; + update(); +} + +void KoRuler::changeFlags(int _flags) +{ + d->flags = _flags; +} + +int KoRuler::flags() const +{ + return d->flags; +} + +bool KoRuler::doubleClickedIndent() const +{ + return d->doubleClickedIndent; +} + +double KoRuler::applyRtlAndZoom( double value ) const +{ + int frameWidth = d->frameEnd - frameStart; + return d->rtl ? ( frameWidth - zoomIt( value ) ) : zoomIt( value ); +} + +double KoRuler::unZoomItRtl( int pixValue ) const +{ + int frameWidth = d->frameEnd - frameStart; + return d->rtl ? ( unZoomIt( (double)(frameWidth - pixValue) ) ) : unZoomIt( (double)pixValue ); +} + +void KoRuler::slotMenuActivated( int i ) +{ + if ( i >= 0 && i <= KoUnit::U_LASTUNIT ) + { + KoUnit::Unit unit = static_cast<KoUnit::Unit>(i); + setUnit( unit ); + emit unitChanged( unit ); + } +} + +QSize KoRuler::minimumSizeHint() const +{ + QSize size; + QFont font = KGlobalSettings::toolBarFont(); + QFontMetrics fm( font ); + + size.setWidth( QMAX( fm.height() + 4, 20 ) ); + size.setHeight( QMAX( fm.height() + 4, 20 ) ); + + return size; +} + +QSize KoRuler::sizeHint() const +{ + return minimumSizeHint(); +} + +void KoRuler::setPageLayout( const KoPageLayout& _layout ) +{ + d->layout = _layout; + update(); +} + +#include "KoRuler.moc" diff --git a/lib/kofficeui/KoRuler.h b/lib/kofficeui/KoRuler.h new file mode 100644 index 00000000..77d169f4 --- /dev/null +++ b/lib/kofficeui/KoRuler.h @@ -0,0 +1,372 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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. +*/ + +// Description: Ruler (header) + +/******************************************************************/ + +#ifndef koRuler_h +#define koRuler_h + +#include <qframe.h> +#include <qpixmap.h> + +#include <kdemacros.h> +#include <koffice_export.h> +#include <KoGlobal.h> +#include <KoTabChooser.h> +#include <KoUnit.h> + +class KoPageLayout; +class QPainter; + +enum KoTabulators { T_LEFT = 0, T_CENTER = 1, T_RIGHT = 2, T_DEC_PNT = 3, T_INVALID = -1 }; +enum KoTabulatorFilling { TF_BLANK = 0, TF_DOTS = 1, TF_LINE = 2, TF_DASH = 3, TF_DASH_DOT = 4, TF_DASH_DOT_DOT = 5}; + +/** + * Struct: KoTabulator + * Defines the position of a tabulation (in pt), and its type + */ +struct KoTabulator { + /** + * Position of the tab in pt + */ + double ptPos; + /** + * Type of tab (left/center/right/decimalpoint) + */ + KoTabulators type; + /** + * Type of tab filling. + */ + KoTabulatorFilling filling; + /** + * Width of the tab filling line. + */ + double ptWidth; + /** + * Alignment character. + */ + QChar alignChar; + + bool operator==( const KoTabulator & t ) const { + return QABS( ptPos - t.ptPos ) < 1E-4 && type == t.type && + filling == t.filling && QABS( ptWidth - t.ptWidth ) < 1E-4; + } + bool operator!=( const KoTabulator & t ) const { + return !operator==(t); + } + // Operators used for sorting + bool operator < ( const KoTabulator & t ) const { + return ptPos < t.ptPos; + } + bool operator <= ( const KoTabulator & t ) const { + return ptPos <= t.ptPos; + } + bool operator > ( const KoTabulator & t ) const { + return ptPos > t.ptPos; + } +}; + +typedef QValueList<KoTabulator> KoTabulatorList; + +class KoRulerPrivate; + +/** + * KoRuler is the horizontal or vertical ruler, to be used around + * the drawing area of most KOffice programs. + * + * It shows the graduated ruler with numbering, in any of the base units (like mm/pt/inch), + * and supports zooming, tabulators, paragraph indents, showing the mouse position, etc. + * + * It also offers a popupmenu upon right-clicking, for changing the unit, + * the page layout, or removing a tab. + */ +class KOFFICEUI_EXPORT KoRuler : public QFrame +{ + Q_OBJECT + friend class KoRulerPrivate; // for the Action enum +public: + static const int F_TABS; + static const int F_INDENTS; + static const int F_HELPLINES; + static const int F_NORESIZE; + + /** + * Create a ruler + * TODO document params + */ + KoRuler( QWidget *_parent, QWidget *_canvas, Orientation _orientation, + const KoPageLayout& _layout, int _flags, KoUnit::Unit _unit, + KoTabChooser *_tabChooser = 0L ); + ~KoRuler(); + + /** + * Set the unit to be used. The unit is specified using text as defined in KoUnit, for + * example "mm", "pt" or "inch". + * @deprecated You should use the KoUnit::Unit variant instead. + */ + void setUnit( const QString& unit ) KDE_DEPRECATED ; + /** + * Set the unit to be used. + */ + void setUnit( KoUnit::Unit unit ); + + /** + * Set the zoom of the ruler (default value of 1.0 is 100%) + */ + void setZoom( const double& zoom=1.0 ); + /** + * @return the current zoom level + */ + const double& zoom() const { return m_zoom; } + + /** + * Set the page layout, see @ref KoPageLayout. + * This defines the size of the page and the margins, + * from which the size of the ruler is deducted. + */ + void setPageLayout( const KoPageLayout& _layout ); + + /** + * Call showMousePos(true) if the ruler should indicate the position + * of the mouse. This is usually only the case for drawing applications, + * so it is not enabled by default. + */ + void showMousePos( bool _showMPos ); + /** + * Set the position of the mouse, to update the indication in the ruler. + * This is only effective if showMousePos(true) was called previously. + * The position to give is not zoomed, it's in real pixel coordinates! + */ + void setMousePos( int mx, int my ); + + /** + * Set a global offset to the X and Y coordinates. + * Usually the main drawing area is a QScrollView, and this is called + * with contentsX() and contentsY(), each time those values change. + */ + void setOffset( int _diffx, int _diffy ); + + /** + * Set the [paragraph] left indent to the specified position (in the current unit) + */ + void setLeftIndent( double _left ) + { i_left = makeIntern( _left ); update(); } + + /** + * Set the [paragraph] first-line left indent to the specified position (in the current unit) + * This indent is cumulated with the left or right margin, depending on the [paragraph] direction. + */ + void setFirstIndent( double _first ) + { i_first = makeIntern( _first ); update(); } + + /** + * Set the [paragraph] right indent to the specified position (in the current unit) + */ + void setRightIndent( double _right ); + + /** + * Set the [paragraph] direction. By default (rtl=false), the left indent is on the + * left, and the right indent is on the right ;) + * If rtl=true, it's the opposite. + */ + void setDirection( bool rtl ); + + /** + * Set the list of tabulators to show in the ruler. + */ + void setTabList( const KoTabulatorList & tabList ); + + /** + * Set the start and the end of the current 'frame', i.e. the part + * of the page in which we are currently working. See KWord frames + * for an example where this is used. The tab positions and paragraph + * indents then become relative to the beginning of the frame, and the + * ruler goes from frameStart to frameEnd instead of using the page margins. + * @p _frameStart et @p _frameEnd are in pixel coordinates. + */ + void setFrameStartEnd( int _frameStart, int _frameEnd ); + + /** + * KoRuler is in "read write" mode by default. + * Use setReadWrite(false) to use it in read-only mode. + */ + void setReadWrite( bool _readWrite ); + + /** + * Change the flag (i.e. activate or deactivate certain features of KoRuler) + */ + void changeFlags(int _flags); + + /** + * Set the size of the grid used for tabs positioning, size in pt. + * default value is 0. 0 means no grid. + */ + void setGridSize(double newGridSize) { gridSize=newGridSize; } + + /** + * @return the current flags + */ + int flags() const; + + /** + * @return whether the current doubleClicked() signal was triggered + * by the user double-clicking on an indent (BCI). It returns false + * if the user just double-clicked on an "empty" part of the ruler. + * + * This method is strictly provided for use in a slot connected to the + * doubleClicked() signal; calling it at any other time results in + * undefined behavior. + */ + bool doubleClickedIndent() const; + + /** + * Enable or disable the "Page Layout" menu item. + */ + void setPageLayoutMenuItemEnabled(bool b); + + /** + * Reimplemented from QWidget + */ + virtual QSize minimumSizeHint() const; + + /** + * Reimplemented from QWidget + */ + virtual QSize sizeHint() const; + +signals: + void newPageLayout( const KoPageLayout & ); + void newLeftIndent( double ); + void newFirstIndent( double ); + void newRightIndent( double ); + /** Old signal, kept for compatibility. Use doubleClicked instead. */ + void openPageLayoutDia(); + /** This signal is emitted when double-clicking the ruler (or an indent) */ + void doubleClicked(); + /** This signal is emitted when double-clicking a tab */ + void doubleClicked( double ptPos ); + + void tabListChanged( const KoTabulatorList & ); + void unitChanged( KoUnit::Unit ); + + void addGuide(const QPoint &, bool, int ); + void moveGuide( const QPoint &, bool, int ); + void addHelpline(const QPoint &, bool ); + void moveHelpLines( const QPoint &, bool ); + +protected: + enum Action {A_NONE, A_BR_LEFT, A_BR_RIGHT, A_BR_TOP, A_BR_BOTTOM, + A_LEFT_INDENT, A_FIRST_INDENT, A_TAB, A_RIGHT_INDENT, + A_HELPLINES }; + + void drawContents( QPainter *_painter ) + { orientation == Qt::Horizontal ? drawHorizontal( _painter ) : drawVertical( _painter ); } + + void drawHorizontal( QPainter *_painter ); + void drawVertical( QPainter *_painter ); + void drawTabs( QPainter &_painter ); + + void mousePressEvent( QMouseEvent *e ); + void mouseReleaseEvent( QMouseEvent *e ); + void mouseMoveEvent( QMouseEvent *e ); + void mouseDoubleClickEvent( QMouseEvent* ); + void resizeEvent( QResizeEvent *e ); + void handleDoubleClick(); + + double makeIntern( double _v ); + double zoomIt(const double &value) const; + int zoomIt(const int &value) const; + unsigned int zoomIt(const unsigned int &value) const; + double unZoomIt(const double &value) const; + int unZoomIt(const int &value) const; + unsigned int unZoomIt(const unsigned int &value) const; + void setupMenu(); + void uncheckMenu(); + void searchTab(int mx); + void drawLine(int oldX, int newX); + +private: + double applyRtlAndZoom( double value ) const; + double unZoomItRtl( int pixValue ) const; + double lineDistance() const; + bool willRemoveTab( int y ) const; + + KoRulerPrivate *d; + + Qt::Orientation orientation; + int diffx, diffy; + double i_left, i_first; + QPixmap buffer; + double m_zoom, m_1_zoom; + KoUnit::Unit m_unit; + bool hasToDelete; + bool showMPos; + bool m_bFrameStartSet; + bool m_bReadWrite; + int mposX, mposY; + int frameStart; + + double gridSize; + +protected slots: + void slotMenuActivated( int i ); + void pageLayoutDia() { emit doubleClicked()/*openPageLayoutDia()*/; } + void rbRemoveTab(); + +}; + +inline double KoRuler::zoomIt(const double &value) const { + if (m_zoom==1.0) + return value; + return m_zoom*value; +} + +inline int KoRuler::zoomIt(const int &value) const { + if (m_zoom==1.0) + return value; + return qRound(m_zoom*value); +} + +inline unsigned int KoRuler::zoomIt(const unsigned int &value) const { + if (m_zoom==1.0) + return value; + return static_cast<unsigned int>(qRound(m_zoom*value)); +} + +inline double KoRuler::unZoomIt(const double &value) const { + if(m_zoom==1.0) + return value; + return value*m_1_zoom; +} + +inline int KoRuler::unZoomIt(const int &value) const { + if(m_zoom==1.0) + return value; + return qRound(value*m_1_zoom); +} + +inline unsigned int KoRuler::unZoomIt(const unsigned int &value) const { + if(m_zoom==1.0) + return value; + return static_cast<unsigned int>(qRound(value*m_1_zoom)); +} + +#endif diff --git a/lib/kofficeui/KoSelectAction.cpp b/lib/kofficeui/KoSelectAction.cpp new file mode 100644 index 00000000..68237b6a --- /dev/null +++ b/lib/kofficeui/KoSelectAction.cpp @@ -0,0 +1,193 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Peter Simonsson <psn@linux.se> + + 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 "KoSelectAction.h" + +#include <qpixmap.h> +#include <qbitmap.h> +#include <qwhatsthis.h> +#include <qmenubar.h> + +#include <kpopupmenu.h> +#include <kapplication.h> +#include <kdebug.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> +#include <kiconloader.h> +#include <klocale.h> + +class KoSelectAction::KoSelectActionPrivate +{ + public: + KoSelectActionPrivate() + { + m_popup = new KPopupMenu(0L,"KoLineStyleAction::popup"); + m_currentSelection = 0; + } + + ~KoSelectActionPrivate() + { + delete m_popup; + m_popup = 0; + } + + KPopupMenu* m_popup; + int m_currentSelection; +}; + +KoSelectAction::KoSelectAction(const QString &text, const QString& icon, + QObject* parent, const char* name) : KAction(text, icon, 0, parent, name) +{ + d = new KoSelectActionPrivate; + setShowCurrentSelection(true); + + connect(popupMenu(), SIGNAL(activated(int)), this, SLOT(execute(int))); +} + +KoSelectAction::KoSelectAction(const QString &text, const QString& icon, const QObject* receiver, + const char* slot, QObject* parent, const char* name) : KAction(text, icon, 0, parent, name) +{ + d = new KoSelectActionPrivate; + + connect(this, SIGNAL(selectionChanged(int)), receiver, slot); + connect(popupMenu(), SIGNAL(activated(int)), this, SLOT(execute(int))); +} + +KoSelectAction::~KoSelectAction() +{ + delete d; +} + +KPopupMenu* KoSelectAction::popupMenu() const +{ + return d->m_popup; +} + +void KoSelectAction::popup(const QPoint& global) +{ + popupMenu()->popup(global); +} + +int KoSelectAction::plug(QWidget* widget, int index) +{ + // This function is copied from KActionMenu::plug + 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(), popupMenu(), -1, index ); + else + id = menu->insertItem( kapp->iconLoader()->loadIcon(icon(), KIcon::Small), + text(), popupMenu(), -1, index ); + + if ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + 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(); + + if ( icon().isEmpty() && !iconSet().isNull() ) { + bar->insertButton( iconSet().pixmap(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index ); + } else { + 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, instance ); + } + + addContainer( bar, id_ ); + + if (!whatsThis().isEmpty()) + QWhatsThis::add( bar->getButton(id_), whatsThis() ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + bar->getButton(id_)->setPopup(popupMenu(), true ); + + 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; +} + +void KoSelectAction::execute(int index) +{ + setCurrentSelection(index); + emit selectionChanged(d->m_currentSelection); +} + +int KoSelectAction::currentSelection() +{ + return d->m_currentSelection; +} + +void KoSelectAction::setCurrentSelection(int index) +{ + if(popupMenu()->isCheckable()) { + popupMenu()->setItemChecked(d->m_currentSelection, false); + popupMenu()->setItemChecked(index, true); + } + + d->m_currentSelection = index; +} + +void KoSelectAction::setShowCurrentSelection(bool show) +{ + popupMenu()->setCheckable(show); +} + +#include "KoSelectAction.moc" diff --git a/lib/kofficeui/KoSelectAction.h b/lib/kofficeui/KoSelectAction.h new file mode 100644 index 00000000..6cdae7c4 --- /dev/null +++ b/lib/kofficeui/KoSelectAction.h @@ -0,0 +1,90 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Peter Simonsson <psn@linux.se> + + 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. +*/ +#ifndef KOSELECTACTION_H +#define KOSELECTACTION_H + +#include <kaction.h> +#include <koffice_export.h> +class KPopupMenu; +class QPoint; + +/** An action that provides a menu with items that can be selected. + * The main difference between this action and a KSelectAction is that + * it is plugged into a toolbar as a dropdown menu and not as a combobox. + */ +class KOFFICEUI_EXPORT KoSelectAction : public KAction +{ + Q_OBJECT + public: + /** Constructs a KoSelectAction with a text and an icon. + * @param text The text that will be displayed. + * @param icon The dynamically loaded icon that goes with this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KoSelectAction(const QString& text, const QString& icon, QObject* parent = 0, const char* name = 0); + /** Same as above, but it also connects a slot to the selectionChanged(int) signal. + * @param text The text that will be displayed. + * @param icon The dynamically loaded icon that goes with this action. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a selectionChanged(int) signal is emited. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KoSelectAction(const QString& text, const QString& icon, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0); + ~KoSelectAction(); + + /** Returns a pointer to the popup menu. */ + KPopupMenu* popupMenu() const; + /** Shows the popup menu. + * @param global Position at which the popup menu is shown. + */ + void popup(const QPoint& global); + + virtual int plug(QWidget* widget, int index = -1); + + /** Returns the index of the currently selected item. */ + virtual int currentSelection(); + + /** If the current selection selection should be shown or not in the menu */ + void setShowCurrentSelection(bool show); + + signals: + /** Emited when the selection changed */ + void selectionChanged(int); + + public slots: + /** Set which item that should be selected. + * @param index Index of item that should be selected + */ + virtual void setCurrentSelection(int index); + + protected slots: + /** Execute an item. By default it sets the item as selected and emits the selectionChanged signal. + * @param index Index of the item that should be executed. + */ + virtual void execute(int index); + + private: + class KoSelectActionPrivate; + KoSelectActionPrivate* d; +}; + +#endif diff --git a/lib/kofficeui/KoTabBar.cpp b/lib/kofficeui/KoTabBar.cpp new file mode 100644 index 00000000..d73025b4 --- /dev/null +++ b/lib/kofficeui/KoTabBar.cpp @@ -0,0 +1,913 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Ariya Hidayat <ariya@kde.org> + Copyright (C) 2003 Norbert Andres <nandres@web.de> + Copyright (C) 2002 Laurent Montel <montel@kde.org> + Copyright (C) 1999 David Faure <faure@kde.org> + Copyright (C) 1999 Boris Wedl <boris.wedl@kfunigraz.ac.at> + Copyright (C) 1998-2000 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "KoTabBar.h" + +#include <qdrawutil.h> +#include <qpainter.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qstyle.h> +#include <qtimer.h> +#include <qtoolbutton.h> +#include <qvaluevector.h> +#include <qwidget.h> + +// TODO +// improvement possibilities +// - use offscreen buffer to reduce flicker even more +// - keep track of tabs, only (re)layout when necessary +// - paint all tabs to buffer, show only by shifting +// - customizable button pixmaps +// - use QStyle to paint the tabs & buttons (is it good/possible?) + + +class KoTabBarPrivate +{ +public: + KoTabBar* tabbar; + + // scroll buttons + QToolButton* scrollFirstButton; + QToolButton* scrollLastButton; + QToolButton* scrollBackButton; + QToolButton* scrollForwardButton; + + // read-only: no mouse drag, double-click, right-click + bool readOnly; + + // if true, layout is from right to left + bool reverseLayout; + + // list of all tabs, in order of appearance + QStringList tabs; + + // array of QRect for each visible tabs + QValueVector<QRect> tabRects; + + // leftmost tab (or rightmost if reverseLayout) + int firstTab; + + // rightmost tab (or leftmost if reverseLayout) + int lastTab; + + // the active tab in the range form 1..n. + // if this value is 0, that means that no tab is active. + int activeTab; + + // unusable space on the left, taken by the scroll buttons + int offset; + + // when the user drag the tab (in order to move it) + // this is the target position, it's 0 if no tab is dragged + int targetTab; + + // wheel movement since selected tab was last changed by the + // mouse wheel + int wheelDelta; + + // true if autoscroll is active + bool autoScroll; + + // calculate the bounding rectangle for each visible tab + void layoutTabs(); + + // reposition scroll buttons + void layoutButtons(); + + // find a tab whose bounding rectangle contains the pos + // return -1 if no such tab is found + int tabAt( const QPoint& pos ); + + // draw a single tab + void drawTab( QPainter& painter, QRect& rect, const QString& text, bool active ); + + // draw a marker to indicate tab moving + void drawMoveMarker( QPainter& painter, int x, int y ); + + // update the enable/disable status of scroll buttons + void updateButtons(); + +}; + +// built-in pixmap for scroll-first button +static const char * arrow_leftmost_xpm[] = { +"10 10 2 1", +" c None", +". c #000000", +" ", +" . . ", +" . .. ", +" . ... ", +" . .... ", +" . ... ", +" . .. ", +" . . ", +" ", +" "}; + +// built-in pixmap for scroll-last button +static const char * arrow_rightmost_xpm[] = { +"10 10 2 1", +" c None", +". c #000000", +" ", +" . . ", +" .. . ", +" ... . ", +" .... . ", +" ... . ", +" .. . ", +" . . ", +" ", +" "}; + +// built-in pixmap for scroll-left button +static const char * arrow_left_xpm[] = { +"10 10 2 1", +" c None", +". c #000000", +" ", +" . ", +" .. ", +" ... ", +" .... ", +" ... ", +" .. ", +" . ", +" ", +" "}; + +// built-in pixmap for scroll-right button +static const char * arrow_right_xpm[] = { +"10 10 2 1", +" c None", +". c #000000", +" ", +" . ", +" .. ", +" ... ", +" .... ", +" ... ", +" .. ", +" . ", +" ", +" "}; + + +void KoTabBarPrivate::layoutTabs() +{ + tabRects.clear(); + + QPainter painter( tabbar ); + + QFont f = painter.font(); + f.setBold( true ); + painter.setFont( f ); + QFontMetrics fm = painter.fontMetrics(); + + if( !reverseLayout ) + { + // left to right + int x = 0; + for( unsigned c = 0; c < tabs.count(); c++ ) + { + QRect rect; + if( (int)c >= firstTab-1 ) + { + QString text = tabs[ c ]; + int tw = fm.width( text ) + 4; + rect = QRect( x, 0, tw + 20, tabbar->height() ); + x = x + tw + 20; + } + tabRects.append( rect ); + } + + lastTab = tabRects.count(); + for( unsigned i = 0; i < tabRects.count(); i++ ) + if( tabRects[i].right()-10+offset > tabbar->width() ) + { + lastTab = i; + break; + } + } + else + { + // right to left + int x = tabbar->width() - offset; + for( unsigned c = 0; c < tabs.count(); c++ ) + { + QRect rect; + if( (int)c >= firstTab-1 ) + { + QString text = tabs[ c ]; + int tw = fm.width( text ) + 4; + rect = QRect( x - tw - 20, 0, tw + 20, tabbar->height() ); + x = x - tw - 20; + } + tabRects.append( rect ); + } + + lastTab = tabRects.count(); + for( unsigned i = tabRects.count()-1; i>0; i-- ) + if( tabRects[i].left() > 0 ) + { + lastTab = i+1; + break; + } + } +} + +int KoTabBarPrivate::tabAt( const QPoint& pos ) +{ + for( unsigned i = 0; i < tabRects.count(); i++ ) + { + QRect rect = tabRects[ i ]; + if( rect.isNull() ) continue; + if( rect.contains( pos ) ) return i; + } + + return -1; // not found +} + +void KoTabBarPrivate::drawTab( QPainter& painter, QRect& rect, const QString& text, bool active ) +{ + QPointArray polygon; + + if( !reverseLayout ) + polygon.setPoints( 6, rect.x(), rect.y(), + rect.x(), rect.bottom()-3, + rect.x()+2, rect.bottom(), + rect.right()-4, rect.bottom(), + rect.right()-2, rect.bottom()-2, + rect.right()+5, rect.top() ); + else + polygon.setPoints( 6, rect.right(), rect.top(), + rect.right(), rect.bottom()-3, + rect.right()-2, rect.bottom(), + rect.x()+4, rect.bottom(), + rect.x()+2, rect.bottom()-2, + rect.x()-5, rect.top() ); + + painter.save(); + + // fill it first + QBrush bg = tabbar->colorGroup().background(); + if( active ) bg = tabbar->colorGroup().base(); + painter.setBrush( bg ); + painter.setPen( QPen( Qt::NoPen ) ); + painter.drawPolygon( polygon ); + + // draw the lines + painter.setPen( tabbar->colorGroup().dark() ); + if( !active ) + painter.drawLine( rect.x()-25, rect.y(), rect.right()+25, rect.top() ); + // Qt4: painter.setRenderHint( QPainter::Antialiasing ); + painter.drawPolyline( polygon ); + + painter.setPen( tabbar->colorGroup().buttonText() ); + QFont f = painter.font(); + if( active ) f.setBold( true ); + painter.setFont( f ); + QFontMetrics fm = painter.fontMetrics(); + int tx = rect.x() + ( rect.width() - fm.width( text ) ) / 2; + int ty = rect.y() + ( rect.height() - fm.height() ) / 2 + fm.ascent(); + painter.drawText( tx, ty, text ); + + painter.restore(); +} + +void KoTabBarPrivate::drawMoveMarker( QPainter& painter, int x, int y ) +{ + QPointArray movmark; + movmark.setPoints( 3, x, y, x + 7, y, x + 4, y + 6); + QBrush oldBrush = painter.brush(); + painter.setBrush( Qt::black ); + painter.drawPolygon(movmark); + painter.setBrush( oldBrush ); +} + +void KoTabBarPrivate::layoutButtons() +{ + int bw = tabbar->height(); + int w = tabbar->width(); + offset = bw * 4; + + if( !reverseLayout ) + { + scrollFirstButton->setGeometry( 0, 0, bw, bw ); + scrollFirstButton->setPixmap( arrow_leftmost_xpm ); + scrollBackButton->setGeometry( bw, 0, bw, bw ); + scrollBackButton->setPixmap( arrow_left_xpm ); + scrollForwardButton->setGeometry( bw*2, 0, bw, bw ); + scrollForwardButton->setPixmap( arrow_right_xpm ); + scrollLastButton->setGeometry( bw*3, 0, bw, bw ); + scrollLastButton->setPixmap( arrow_rightmost_xpm ); + } + else + { + scrollFirstButton->setGeometry( w-bw, 0, bw, bw ); + scrollFirstButton->setPixmap( arrow_rightmost_xpm ); + scrollBackButton->setGeometry( w-2*bw, 0, bw, bw ); + scrollBackButton->setPixmap( arrow_right_xpm ); + scrollForwardButton->setGeometry( w-3*bw, 0, bw, bw ); + scrollForwardButton->setPixmap( arrow_left_xpm ); + scrollLastButton->setGeometry( w-4*bw, 0, bw, bw ); + scrollLastButton->setPixmap( arrow_leftmost_xpm ); + } + } + +void KoTabBarPrivate::updateButtons() +{ + scrollFirstButton->setEnabled( tabbar->canScrollBack() ); + scrollBackButton->setEnabled( tabbar->canScrollBack() ); + scrollForwardButton->setEnabled( tabbar->canScrollForward() ); + scrollLastButton->setEnabled( tabbar->canScrollForward() ); +} + +// creates a new tabbar +KoTabBar::KoTabBar( QWidget* parent, const char* name ) + : QWidget( parent, name, Qt::WResizeNoErase | Qt::WRepaintNoErase ) +{ + d = new KoTabBarPrivate; + d->tabbar = this; + d->readOnly = false; + d->reverseLayout = false; + d->firstTab = 1; + d->lastTab = 0; + d->activeTab = 0; + d->targetTab = 0; + d->wheelDelta = 0; + d->autoScroll = false; + d->offset = 64; + + // initialize the scroll buttons + d->scrollFirstButton = new QToolButton( this ); + connect( d->scrollFirstButton, SIGNAL( clicked() ), + this, SLOT( scrollFirst() ) ); + d->scrollLastButton = new QToolButton( this ); + connect( d->scrollLastButton, SIGNAL( clicked() ), + this, SLOT( scrollLast() ) ); + d->scrollBackButton = new QToolButton( this ); + connect( d->scrollBackButton, SIGNAL( clicked() ), + this, SLOT( scrollBack() ) ); + d->scrollForwardButton = new QToolButton( this ); + connect( d->scrollForwardButton, SIGNAL( clicked() ), + this, SLOT( scrollForward() ) ); + d->layoutButtons(); + d->updateButtons(); +} + +// destroys the tabbar +KoTabBar::~KoTabBar() +{ + delete d; +} + +// adds a new visible tab +void KoTabBar::addTab( const QString& text ) +{ + d->tabs.append( text ); + + update(); +} + +// removes a tab +void KoTabBar::removeTab( const QString& text ) +{ + int i = d->tabs.findIndex( text ); + if ( i == -1 ) return; + + if ( d->activeTab == i + 1 ) + d->activeTab = 0; + + d->tabs.remove( text ); + + update(); +} + +// removes all tabs +void KoTabBar::clear() +{ + d->tabs.clear(); + d->activeTab = 0; + d->firstTab = 1; + + update(); +} + +bool KoTabBar::readOnly() const +{ + return d->readOnly; +} + +void KoTabBar::setReadOnly( bool ro ) +{ + d->readOnly = ro; +} + +bool KoTabBar::reverseLayout() const +{ + return d->reverseLayout; +} + +void KoTabBar::setReverseLayout( bool reverse ) +{ + if( reverse != d->reverseLayout ) + { + d->reverseLayout = reverse; + d->layoutTabs(); + d->layoutButtons(); + d->updateButtons(); + update(); + } +} + +void KoTabBar::setTabs( const QStringList& list ) +{ + QString left, active; + + if( d->activeTab > 0 ) + active = d->tabs[ d->activeTab-1 ]; + if( d->firstTab > 0 ) + left = d->tabs[ d->firstTab-1 ]; + + d->tabs = list; + + if( !left.isNull() ) + { + d->firstTab = d->tabs.findIndex( left ) + 1; + if( d->firstTab > (int)d->tabs.count() ) + d->firstTab = 1; + if( d->firstTab <= 0 ) + d->firstTab = 1; + } + + d->activeTab = 0; + if( !active.isNull() ) + setActiveTab( active ); + + update(); +} + +QStringList KoTabBar::tabs() const +{ + return d->tabs; +} + +unsigned KoTabBar::count() const +{ + return d->tabs.count(); +} + +bool KoTabBar::canScrollBack() const +{ + if ( d->tabs.count() == 0 ) + return false; + + return d->firstTab > 1; +} + +bool KoTabBar::canScrollForward() const +{ + if ( d->tabs.count() == 0 ) + return false; + + return d->lastTab < (int)d->tabs.count(); +} + +void KoTabBar::scrollBack() +{ + if ( !canScrollBack() ) + return; + + d->firstTab--; + if( d->firstTab < 1 ) d->firstTab = 1; + + d->layoutTabs(); + d->updateButtons(); + update(); +} + +void KoTabBar::scrollForward() +{ + if ( !canScrollForward() ) + return; + + d->firstTab ++; + if( d->firstTab > (int)d->tabs.count() ) + d->firstTab = d->tabs.count(); + + d->layoutTabs(); + d->updateButtons(); + update(); +} + +void KoTabBar::scrollFirst() +{ + if ( !canScrollBack() ) + return; + + d->firstTab = 1; + d->layoutTabs(); + d->updateButtons(); + update(); +} + +void KoTabBar::scrollLast() +{ + if ( !canScrollForward() ) + return; + + d->layoutTabs(); + + if( !d->reverseLayout ) + { + int fullWidth = d->tabRects[ d->tabRects.count()-1 ].right(); + int delta = fullWidth - width() + d->offset; + for( unsigned i = 0; i < d->tabRects.count(); i++ ) + if( d->tabRects[i].x() > delta ) + { + d->firstTab = i+1; + break; + } + } + else + { + // FIXME optimize this, perhaps without loop + for( ; d->firstTab <= (int)d->tabRects.count();) + { + int x = d->tabRects[ d->tabRects.count()-1 ].x(); + if( x > 0 ) break; + d->firstTab++; + d->layoutTabs(); + } + } + + d->layoutTabs(); + d->updateButtons(); + update(); +} + +void KoTabBar::ensureVisible( const QString& tab ) +{ + int i = d->tabs.findIndex( tab ); + if ( i == -1 ) + return; + i++; + + // already visible, then do nothing + if( ( i >= d->firstTab ) && ( i <= d->lastTab ) ) + return; + + if( i < d->firstTab ) + while( i < d->firstTab ) + scrollBack(); + + if( i > d->lastTab ) + while( i > d->lastTab ) + scrollForward(); +} + +void KoTabBar::moveTab( unsigned tab, unsigned target ) +{ + QString tabName = d->tabs[ tab ]; + QStringList::Iterator it; + + it = d->tabs.at( tab ); + d->tabs.remove( it ); + + if( target > tab ) target--; + it = d->tabs.at( target ); + if( target >= d->tabs.count() ) + it = d->tabs.end(); + d->tabs.insert( it, tabName ); + + if( d->activeTab == (int)tab+1 ) + d->activeTab = target+1; + + update(); +} + +void KoTabBar::setActiveTab( const QString& text ) +{ + int i = d->tabs.findIndex( text ); + if ( i == -1 ) + return; + + if ( i + 1 == d->activeTab ) + return; + + d->activeTab = i + 1; + d->updateButtons(); + update(); + + emit tabChanged( text ); +} + +void KoTabBar::autoScrollBack() +{ + if( !d->autoScroll ) return; + + scrollBack(); + + if( !canScrollBack() ) + d->autoScroll = false; + else + QTimer::singleShot( 400, this, SLOT( autoScrollBack() ) ); +} + +void KoTabBar::autoScrollForward() +{ + if( !d->autoScroll ) return; + + scrollForward(); + + if( !canScrollForward() ) + d->autoScroll = false; + else + QTimer::singleShot( 400, this, SLOT( autoScrollForward() ) ); +} + +void KoTabBar::paintEvent( QPaintEvent* ) +{ + if ( d->tabs.count() == 0 ) + { + erase(); + return; + } + + QPainter painter; + QPixmap pm( size() ); + pm.fill( colorGroup().background() ); + painter.begin( &pm, this ); + + painter.setPen( colorGroup().dark() ); + painter.drawLine( 0, 0, width(), 0 ); + + if( !d->reverseLayout ) + painter.translate( 5, 0 ); + + d->layoutTabs(); + d->updateButtons(); + + // draw first all non-active, visible tabs + for( int c = d->tabRects.count()-1; c>=0; c-- ) + { + QRect rect = d->tabRects[ c ]; + if( rect.isNull() ) continue; + QString text = d->tabs[ c ]; + d->drawTab( painter, rect, text, false ); + } + + // draw the active tab + if( d->activeTab > 0 ) + { + QRect rect = d->tabRects[ d->activeTab-1 ]; + if( !rect.isNull() ) + { + QString text = d->tabs[ d->activeTab-1 ]; + d->drawTab( painter, rect, text, true ); + } + } + + // draw the move marker + if( d->targetTab > 0 ) + { + int p = QMIN( d->targetTab, (int)d->tabRects.count() ); + QRect rect = d->tabRects[ p-1 ]; + if( !rect.isNull() ) + { + int x = !d->reverseLayout ? rect.x() : rect.right()-7; + if( d->targetTab > (int)d->tabRects.count() ) + x = !d->reverseLayout ? rect.right()-7 : rect.x()-3; + d->drawMoveMarker( painter, x, rect.y() ); + } + } + + painter.end(); + + if( !d->reverseLayout ) + bitBlt( this, d->offset, 0, &pm ); + else + bitBlt( this, 0, 0, &pm ); + +} + +void KoTabBar::resizeEvent( QResizeEvent* ) +{ + d->layoutButtons(); + d->updateButtons(); + update(); +} + +QSize KoTabBar::sizeHint() const +{ + return QSize( 40, style().pixelMetric( QStyle::PM_ScrollBarExtent, this ) ); +} + +void KoTabBar::renameTab( const QString& old_name, const QString& new_name ) +{ + QStringList::Iterator it = d->tabs.find( old_name ); + (*it) = new_name; + + update(); +} + +QString KoTabBar::activeTab() const +{ + if( d->activeTab == 0 ) + return QString::null; + else + return d->tabs[ d->activeTab ]; +} + +void KoTabBar::mousePressEvent( QMouseEvent* ev ) +{ + if ( d->tabs.count() == 0 ) + { + erase(); + return; + } + + d->layoutTabs(); + + QPoint pos = ev->pos(); + if( !d->reverseLayout ) pos = pos - QPoint( d->offset,0 ); + + int tab = d->tabAt( pos ) + 1; + if( ( tab > 0 ) && ( tab != d->activeTab ) ) + { + d->activeTab = tab; + update(); + + emit tabChanged( d->tabs[ d->activeTab-1] ); + + // scroll if partially visible + if( d->tabRects[ tab-1 ].right() > width() - d->offset ) + scrollForward(); + } + + if( ev->button() == RightButton ) + if( !d->readOnly ) + emit contextMenu( ev->globalPos() ); +} + +void KoTabBar::mouseReleaseEvent( QMouseEvent* ev ) +{ + if ( d->readOnly ) return; + + d->autoScroll = false; + + if ( ev->button() == LeftButton && d->targetTab != 0 ) + { + emit tabMoved( d->activeTab-1, d->targetTab-1 ); + d->targetTab = 0; + } +} + +void KoTabBar::mouseMoveEvent( QMouseEvent* ev ) +{ + if ( d->readOnly ) return; + + QPoint pos = ev->pos(); + if( !d->reverseLayout) pos = pos - QPoint( d->offset,0 ); + + // check if user drags a tab to move it + int i = d->tabAt( pos ) + 1; + if( ( i > 0 ) && ( i != d->targetTab ) ) + { + if( i == d->activeTab ) i = 0; + if( i == d->activeTab+1 ) i = 0; + + if( i != d->targetTab ) + { + d->targetTab = i; + d->autoScroll = false; + update(); + } + } + + // drag past the very latest visible tab + // e.g move a tab to the last ordering position + QRect r = d->tabRects[ d->tabRects.count()-1 ]; + bool moveToLast = false; + if( r.isValid() ) + { + if( !d->reverseLayout ) + if( pos.x() > r.right() ) + if( pos.x() < width() ) + moveToLast = true; + if( d->reverseLayout ) + if( pos.x() < r.x() ) + if( pos.x() > 0 ) + moveToLast = true; + } + if( moveToLast ) + if( d->targetTab != (int)d->tabRects.count()+1 ) + { + d->targetTab = d->tabRects.count()+1; + d->autoScroll = false; + update(); + } + + // outside far too left ? activate autoscroll... + if ( pos.x() < 0 && !d->autoScroll ) + { + d->autoScroll = true; + autoScrollBack(); + } + + // outside far too right ? activate autoscroll... + int w = width() - d->offset; + if ( pos.x() > w && !d->autoScroll ) + { + d->autoScroll = true; + autoScrollForward(); + } +} + +void KoTabBar::mouseDoubleClickEvent( QMouseEvent* ev ) +{ + int offset = d->reverseLayout ? 0 : d->offset; + if( ev->pos().x() > offset ) + if( !d->readOnly ) + emit doubleClicked(); +} + +void KoTabBar::wheelEvent( QWheelEvent * e ) +{ + if ( d->tabs.count() == 0 ) + { + erase(); + return; + } + + // Currently one wheel movement is a delta of 120. + // The 'unused' delta is stored for devices that allow + // a higher scrolling resolution. + // The delta required to move one tab is one wheel movement: + const int deltaRequired = 120; + + d->wheelDelta += e->delta(); + int tabDelta = - (d->wheelDelta / deltaRequired); + d->wheelDelta = d->wheelDelta % deltaRequired; + int numTabs = d->tabs.size(); + + if(d->activeTab + tabDelta > numTabs) + { + // Would take us past the last tab + d->activeTab = numTabs; + } + else if (d->activeTab + tabDelta < 1) + { + // Would take us before the first tab + d->activeTab = 1; + } + else + { + d->activeTab = d->activeTab + tabDelta; + } + + // Find the left and right edge of the new tab. If we're + // going forward, and the right of the new tab isn't visible + // then scroll forward. Likewise, if going back, and the + // left of the new tab isn't visible, then scroll back. + int activeTabRight = d->tabRects[ d->activeTab-1 ].right(); + int activeTabLeft = d->tabRects[ d->activeTab-1 ].left(); + if(tabDelta > 0 && activeTabRight > width() - d->offset ) + { + scrollForward(); + } + else if(tabDelta < 0 && activeTabLeft < width() - d->offset ) + { + scrollBack(); + } + + update(); + emit tabChanged( d->tabs[ d->activeTab-1] ); +} + + +#include "KoTabBar.moc" diff --git a/lib/kofficeui/KoTabBar.h b/lib/kofficeui/KoTabBar.h new file mode 100644 index 00000000..e582c3d2 --- /dev/null +++ b/lib/kofficeui/KoTabBar.h @@ -0,0 +1,275 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Ariya Hidayat <ariya@kde.org> + Copyright (C) 2003 Norbert Andres <nandres@web.de> + Copyright (C) 2002 Laurent Montel <montel@kde.org> + Copyright (C) 1999 David Faure <faure@kde.org> + Copyright (C) 1999 Boris Wedl <boris.wedl@kfunigraz.ac.at> + Copyright (C) 1998-2000 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef kotabbar_h +#define kotabbar_h + +#include <qwidget.h> +#include <qstringlist.h> +#include <koffice_export.h> +class KoTabBarPrivate; + +/** + * The KoTabBar class provides a tab bar, for use to switch active + * page/sheet in a document. + * + * The tab bar is typically used in the main view. + * It is the small widget on the bottom left corner. + * Pages/sheets are displayed as tabs, clicking on + * one of the tab will activate the corresponding sheet (this is actually + * done in main view). Current active page/sheet is marked by bold text. + * + * The tab bar supports page/sheet reorder by dragging a certain tab + * and move it to another location. The main view should handle the necessary + * action to perform the actual reorder. + * + * There are four scroll buttons available in the tab bar. They are used + * to shift the tabs in left and right direction, for example when there + * are more tabs than the space available to display all tabs. + * + * Since a page/sheet can be hidden, the tab bar only shows the visible page/sheet. + * When a hidden page or sheet is shown again, it will be on the same position as + * before it was hidden. + * + * When the document is protected, it is necessary to set the tab bar as + * read-only using setReadOnly (see also readOnly). If it is set to true, + * tabs can not be moved by dragging and context menu will not be displayed. + * + * @short A bar with tabs and scroll buttons. + */ +class KOFFICEUI_EXPORT KoTabBar : public QWidget +{ + Q_OBJECT + + Q_PROPERTY( QString activeTab READ activeTab WRITE setActiveTab ) + Q_PROPERTY( bool readOnly READ readOnly WRITE setReadOnly ) + Q_PROPERTY( QStringList tabs READ tabs WRITE setTabs ) + Q_PROPERTY( unsigned count READ count ) + +public: + + /** + * Creates a new tabbar. + */ + KoTabBar( QWidget* parent = 0, const char *name = 0 ); + + /** + * Destroy the tabbar. + */ + virtual ~KoTabBar(); + + /** + * Returns true if the tab bar is read only. + */ + bool readOnly() const; + + /** + * Returns true if tabs and scroll buttons will be laid out in a mirrored + * (right to left) fashion. + */ + bool reverseLayout() const; + + /** + * Returns all the tab as list of strings. + */ + QStringList tabs() const; + + /** + * Returns number of tabs. + * This is the same as KoTabBar::tabs().count() + */ + unsigned count() const; + + /** + * Returns the active tab. + */ + QString activeTab() const; + + /** + * Returns true if it is possible to scroll one tab back. + * + * \sa scrollBack + */ + bool canScrollBack() const; + + /** + * Returns true if it is possible to scroll one tab forward. + * + * \sa scrollForward + */ + bool canScrollForward() const; + + /** + * Ensures that specified tab is visible. + */ + void ensureVisible( const QString& tab ); + +public slots: + + /** + * Replaces all tabs with the list of strings. + */ + void setTabs( const QStringList& list ); + + /** + * Sets the tab bar to be read only. + * + * If the tab bar is read only, tab reordering is not allowed. + * This means that signal tabMoved, contextMenu and doubleClicked + * would not be emitted. + */ + void setReadOnly( bool ro ); + + /** + * If reverse is true, dialogs and scroll buttonswidgets will be laid out in a mirrored + * as if the sheet is in right to left languages (such as Arabic and Hebrew) + */ + void setReverseLayout( bool reverse ); + + /** + * Adds a tab to the tab bar. + */ + void addTab( const QString& text ); + + /** + * Removes a tab from the bar. If the tab was the active one then + * no tab will be active. + * It is recommended to call setActiveTab after a call to this function. + */ + void removeTab( const QString& text ); + + /** + * Renames a tab. + */ + void renameTab( const QString& old_name, const QString& new_name ); + + /** + * Moves a tab to another position and reorder other tabs. + * + * Example 1: if there are four tabs A - B - C - D, then + * moveTab(2,1) will yield A - C - B - D. This is because + * 2nd tab (i.e C) is moved to a position before 1th tab (i.e B). + * + * Example 2: for these tabs: X - Y - Z, moveTab(0,3) will + * move tab X after tab Z so that the result is Y - Z - X. + */ + void moveTab( unsigned tab, unsigned target ); + + /** + * Scrolls one tab back. Does nothing if the leftmost tab (rightmost tab + * when reverseLayout is true) is already the first tab. + * + * \sa canScrollBack + */ + void scrollBack(); + + /** + * Scrolls one tab forward. Does nothing if the rightmost tab (leftmost tab + * when reverseLayout is true) is already the last tab. + * + * \sa canScrollForward + */ + void scrollForward(); + + /** + * Scrolls to the first tab. Does nothing if the leftmost tab (rightmost tab + * when reverseLayout is true) is already the first tab. + * + * \sa canScrollBack + */ + void scrollFirst(); + + /** + * Scrolls to the last tab. Does nothing if the rightmost tab (leftmost tab + * when reverseLayout is true) is already the last tab. + * + * \sa canScrollForward + */ + void scrollLast(); + + /** + * Sets active tab. + */ + void setActiveTab( const QString& text ); + + /** + * Removes all tabs. + */ + void clear(); + + QSize sizeHint() const; + +signals: + + /** + * Emitted if the active tab changed. + */ + void tabChanged( const QString& _text ); + + /** + * This signal is emitted whenever a tab is dragged, moved and + * released. This means that the user wants to move a tab into + * another position (right before target). + * + * When the signal is emitted, the tabs are not reordered. + * Therefore if you just ignore this signal, than no tab reorder + * is possible. Call moveTab (from the slot connected to this signal) + * to perform the actual tab reorder. + */ + void tabMoved( unsigned tab, unsigned target ); + + /** + * This signal is emitted whenever the tab bar is right-clicked. + * Typically it is used to popup a context menu. + */ + void contextMenu( const QPoint& pos ); + + /** + * This signal is emitted whenever the tab bar is double-clicked. + */ + void doubleClicked(); + +protected slots: + void autoScrollBack(); + void autoScrollForward(); + +protected: + virtual void paintEvent ( QPaintEvent* ev ); + virtual void resizeEvent( QResizeEvent* ev ); + virtual void mousePressEvent ( QMouseEvent* ev ); + virtual void mouseReleaseEvent ( QMouseEvent* ev ); + virtual void mouseDoubleClickEvent ( QMouseEvent* ev ); + virtual void mouseMoveEvent ( QMouseEvent* ev ); + virtual void wheelEvent ( QWheelEvent * e ); + +private: + KoTabBarPrivate *d; + + // don't allow copy or assignment + KoTabBar( const KoTabBar& ); + KoTabBar& operator=( const KoTabBar& ); +}; + + +#endif // kotabbar_h diff --git a/lib/kofficeui/KoTabChooser.cpp b/lib/kofficeui/KoTabChooser.cpp new file mode 100644 index 00000000..414db6bb --- /dev/null +++ b/lib/kofficeui/KoTabChooser.cpp @@ -0,0 +1,175 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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. +*/ + +// Description: Tabulator chooser (header) + +/******************************************************************/ + +#include <KoTabChooser.h> +#include <qpainter.h> +#include <qpopupmenu.h> +#include <qcursor.h> + +#include <klocale.h> + + +class KoTabChooserPrivate { +public: + KoTabChooserPrivate() { + } + ~KoTabChooserPrivate() {} + + bool m_bReadWrite; +}; + +/******************************************************************/ +/* Class: KoTabChooser */ +/******************************************************************/ + +/*================================================================*/ +KoTabChooser::KoTabChooser( QWidget *parent, int _flags ) + : QFrame( parent, "" ) +{ + setFrameStyle( MenuBarPanel ); + flags = _flags; + d=new KoTabChooserPrivate(); + + d->m_bReadWrite=true; + + currType = 0; + + if ( flags & TAB_DEC_PNT ) currType = TAB_DEC_PNT; + if ( flags & TAB_CENTER ) currType = TAB_CENTER; + if ( flags & TAB_RIGHT ) currType = TAB_RIGHT; + if ( flags & TAB_LEFT ) currType = TAB_LEFT; + + setupMenu(); +} + +/*================================================================*/ +void KoTabChooser::mousePressEvent( QMouseEvent *e ) +{ + if ( currType == 0 ) return; + + if( !d->m_bReadWrite) + return; + + switch ( e->button() ) { + case LeftButton: case MidButton: { + switch ( currType ) { + case TAB_LEFT: { + if ( flags & TAB_CENTER ) currType = TAB_CENTER; + else if ( flags & TAB_RIGHT ) currType = TAB_RIGHT; + else if ( flags & TAB_DEC_PNT ) currType = TAB_DEC_PNT; + } break; + case TAB_RIGHT: { + if ( flags & TAB_DEC_PNT ) currType = TAB_DEC_PNT; + else if ( flags & TAB_LEFT ) currType = TAB_LEFT; + else if ( flags & TAB_CENTER ) currType = TAB_CENTER; + } break; + case TAB_CENTER: { + if ( flags & TAB_RIGHT ) currType = TAB_RIGHT; + else if ( flags & TAB_DEC_PNT ) currType = TAB_DEC_PNT; + else if ( flags & TAB_LEFT ) currType = TAB_LEFT; + } break; + case TAB_DEC_PNT: { + if ( flags & TAB_LEFT ) currType = TAB_LEFT; + else if ( flags & TAB_CENTER ) currType = TAB_CENTER; + else if ( flags & TAB_RIGHT ) currType = TAB_RIGHT; + } break; + } + repaint( true ); + } break; + case RightButton: { + QPoint pnt( QCursor::pos() ); + + rb_menu->setItemChecked( mLeft, false ); + rb_menu->setItemChecked( mCenter, false ); + rb_menu->setItemChecked( mRight, false ); + rb_menu->setItemChecked( mDecPoint, false ); + + switch ( currType ) { + case TAB_LEFT: rb_menu->setItemChecked( mLeft, true ); + break; + case TAB_CENTER: rb_menu->setItemChecked( mCenter, true ); + break; + case TAB_RIGHT: rb_menu->setItemChecked( mRight, true ); + break; + case TAB_DEC_PNT: rb_menu->setItemChecked( mDecPoint, true ); + break; + } + + rb_menu->popup( pnt ); + } break; + default: break; + } +} + +/*================================================================*/ +void KoTabChooser::drawContents( QPainter *painter ) +{ + if ( currType == 0 ) return; + + painter->setPen( QPen( black, 2, SolidLine ) ); + + switch ( currType ) { + case TAB_LEFT: { + painter->drawLine( 4, height() - 4, width() - 4, height() - 4 ); + painter->drawLine( 5, 4, 5, height() - 4 ); + } break; + case TAB_CENTER: { + painter->drawLine( 4, height() - 4, width() - 4, height() - 4 ); + painter->drawLine( width() / 2, 4, width() / 2, height() - 4 ); + } break; + case TAB_RIGHT: { + painter->drawLine( 4, height() - 4, width() - 4, height() - 4 ); + painter->drawLine( width() - 5, 4, width() - 5, height() - 4 ); + } break; + case TAB_DEC_PNT: { + painter->drawLine( 4, height() - 4, width() - 4, height() - 4 ); + painter->drawLine( width() / 2, 4, width() / 2, height() - 4 ); + painter->fillRect( width() / 2 + 2, height() - 9, 3, 3, black ); + } break; + default: break; + } +} + +/*================================================================*/ +void KoTabChooser::setupMenu() +{ + rb_menu = new QPopupMenu(); + Q_CHECK_PTR( rb_menu ); + mLeft = rb_menu->insertItem( i18n( "Tabulator &Left" ), this, SLOT( rbLeft() ) ); + mCenter = rb_menu->insertItem( i18n( "Tabulator &Center" ), this, SLOT( rbCenter() ) ); + mRight = rb_menu->insertItem( i18n( "Tabulator &Right" ), this, SLOT( rbRight() ) ); + mDecPoint = rb_menu->insertItem( i18n( "Tabulator &Decimal Point" ), this, SLOT( rbDecPoint() ) ); + rb_menu->setCheckable( false ); +} + +KoTabChooser::~KoTabChooser() { + delete rb_menu; + delete d; +} + +void KoTabChooser::setReadWrite(bool _readWrite) +{ + d->m_bReadWrite=_readWrite; +} + +#include <KoTabChooser.moc> diff --git a/lib/kofficeui/KoTabChooser.h b/lib/kofficeui/KoTabChooser.h new file mode 100644 index 00000000..7a49f495 --- /dev/null +++ b/lib/kofficeui/KoTabChooser.h @@ -0,0 +1,80 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 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 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. +*/ + +#ifndef koTabChooser_h +#define koTabChooser_h + +#include <qframe.h> +#include <koffice_export.h> +class QMouseEvent; +class QPainter; +class QPopupMenu; + +/** + * class KoTabChooser + */ + +class KoTabChooserPrivate; + +class KOFFICEUI_EXPORT KoTabChooser : public QFrame +{ + Q_OBJECT + +public: + enum { TAB_LEFT = 1, + TAB_CENTER = 2, + TAB_RIGHT = 4, + TAB_DEC_PNT = 8, + TAB_ALL = TAB_LEFT | TAB_CENTER | TAB_RIGHT | TAB_DEC_PNT }; + + KoTabChooser( QWidget *parent, int _flags ); + ~KoTabChooser(); + + int getCurrTabType() { return currType; } + + /** + * put m_bReadWrite to true as default + * and used setReadWrite(false) to make in readOnly mode + */ + void setReadWrite(bool _readWrite); + +protected: + void mousePressEvent( QMouseEvent *e ); + void drawContents( QPainter *painter ); + void setupMenu(); + + int flags; + int currType; + QPopupMenu *rb_menu; + int mLeft; + int mRight; + int mCenter; + int mDecPoint; + + KoTabChooserPrivate *d; + +protected slots: + void rbLeft() { currType = TAB_LEFT; repaint( true ); } + void rbCenter() { currType = TAB_CENTER; repaint( true ); } + void rbRight() { currType = TAB_RIGHT; repaint( true ); } + void rbDecPoint() { currType = TAB_DEC_PNT; repaint( true ); } + +}; + +#endif diff --git a/lib/kofficeui/KoTemplateChooseDia.cpp b/lib/kofficeui/KoTemplateChooseDia.cpp new file mode 100644 index 00000000..1c2fd843 --- /dev/null +++ b/lib/kofficeui/KoTemplateChooseDia.cpp @@ -0,0 +1,829 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + 2000, 2001 Werner Trobin <trobin@kde.org> + 2002, 2003 Thomas Nagy <tnagy@eleve.emn.fr> + 2004 David Faure <faure@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. + */ + +// Description: Template Choose Dialog + +/******************************************************************/ + +#include "KoTemplateChooseDia.h" + +#include <klocale.h> +#include <kdeversion.h> +#include <kfiledialog.h> +#include <kinstance.h> +#include <KoFilterManager.h> +#include <KoTemplates.h> +#include <KoDocument.h> +#include <kmainwindow.h> + +#include <kdebug.h> +#include <kpushbutton.h> +#include <kjanuswidget.h> +#include <kglobalsettings.h> +#include <ktextedit.h> +#include <kfileiconview.h> +#include <kfileitem.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <kaboutdata.h> + +#include <qapplication.h> +#include <qlayout.h> +#include <qtabwidget.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <qpoint.h> +#include <qobjectlist.h> +#include <qvgroupbox.h> +#include <qtooltip.h> + +class MyFileDialog : public KFileDialog +{ + public : + MyFileDialog( + const QString& startDir=0, + const QString& filter =0, + QWidget *parent=0, + const char *name=0, + bool modal=0) + : KFileDialog (startDir, filter, parent, name, modal), + m_slotOkCalled( false ) {} + + KURL currentURL() + { + setResult( QDialog::Accepted ); // selectedURL tests for it + return KFileDialog::selectedURL(); + } + + // Return true if the current URL exists, show msg box if not + bool checkURL() + { + bool ok = true; + KURL url = currentURL(); + if ( url.isLocalFile() ) + { + ok = QFile::exists( url.path() ); + if ( !ok ) { + // Maybe offer to create a new document with that name? (see alos KoDocument::openFile) + KMessageBox::error( this, i18n( "The file %1 does not exist." ).arg( url.path() ) ); + } + } + return ok; + } + // Called directly by pressing Return in the location combo + // (so we need to remember that it got called, to avoid calling it twice) + // Called "by hand" when clicking on our OK button + void slotOk() { + m_slotOkCalled = true; + KFileDialog::slotOk(); + } + bool slotOkCalled() const { return m_slotOkCalled; } + protected: + // Typing a file that doesn't exist closes the file dialog, we have to + // handle this case better here. + virtual void accept() { + if ( checkURL() ) + KFileDialog::accept(); + } + + virtual void reject() { + KFileDialog::reject(); + emit cancelClicked(); + } +private: + bool m_slotOkCalled; +}; + +/*================================================================*/ + +/*================================================================*/ + +class KoTemplateChooseDiaPrivate { + public: + KoTemplateChooseDiaPrivate(const QCString& templateType, KInstance* instance, + const QCString &format, + const QString &nativeName, + const QStringList& extraNativeMimeTypes, + const KoTemplateChooseDia::DialogType &dialogType) : + m_templateType(templateType), m_instance(instance), m_format(format), + m_nativeName(nativeName), m_extraNativeMimeTypes( extraNativeMimeTypes ), + m_dialogType(dialogType), tree(0), + m_nostartupdlg( false ), + m_mainwidget(0), m_nodiag( 0 ) + { + m_returnType = KoTemplateChooseDia::Empty; + } + + ~KoTemplateChooseDiaPrivate() {} + + QCString m_templateType; + KInstance* m_instance; + QCString m_format; + QString m_nativeName; + QStringList m_extraNativeMimeTypes; + + KoTemplateChooseDia::DialogType m_dialogType; + KoTemplateTree *tree; + + QString m_templateName; + QString m_fullTemplateName; + KoTemplateChooseDia::ReturnType m_returnType; + + bool m_nostartupdlg; + + // the main widget + QWidget *m_mainwidget; + + // do not show this dialog at startup + QCheckBox *m_nodiag; + + // choose a template + KJanusWidget * m_jwidget; + KFileIconView *m_recent; + QVGroupBox * boxdescription; + KTextEdit * textedit; + + // choose a file + MyFileDialog *m_filedialog; + + // for the layout + QTabWidget* tabWidget; + QWidget* newTab; + QWidget* existingTab; + QWidget* recentTab; + +}; + +/******************************************************************/ +/* Class: KoTemplateChooseDia */ +/******************************************************************/ + +/*================================================================*/ +KoTemplateChooseDia::KoTemplateChooseDia(QWidget *parent, const char *name, KInstance* instance, + const QCString &format, + const QString &nativeName, + const QStringList &extraNativeMimeTypes, + const DialogType &dialogType, + const QCString& templateType) : + KDialogBase(parent, name, true, i18n("Open Document"), KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok) +{ + d = new KoTemplateChooseDiaPrivate( + templateType, + instance, + format, + nativeName, + extraNativeMimeTypes, + dialogType); + + QPushButton* ok = actionButton( KDialogBase::Ok ); + QPushButton* cancel = actionButton( KDialogBase::Cancel ); + cancel->setAutoDefault(false); + ok->setDefault(true); + //enableButtonOK(false); + + if (!templateType.isNull() && !templateType.isEmpty() && dialogType!=NoTemplates) + d->tree = new KoTemplateTree(templateType, instance, true); + + d->m_mainwidget = makeMainWidget(); + + d->m_templateName = ""; + d->m_fullTemplateName = ""; + d->m_returnType = Cancel; + + setupDialog(); +} + +KoTemplateChooseDia::~KoTemplateChooseDia() +{ + delete d->tree; + delete d; + d=0L; +} + +// Keep in sync with KoMainWindow::chooseNewDocument +static bool cancelQuits() { + bool onlyDoc = !KoDocument::documentList() || KoDocument::documentList()->count() <= 1; + bool onlyMainWindow = !KMainWindow::memberList || KMainWindow::memberList->count() <= 1; + return onlyDoc && onlyMainWindow && kapp->instanceName() != "koshell"; // hack for koshell +} + +KoTemplateChooseDia::ReturnType KoTemplateChooseDia::choose(KInstance* instance, QString &file, + const KoTemplateChooseDia::DialogType &dialogType, + const QCString& templateType, + QWidget* parent) +{ + const QString nativeName = instance->aboutData()->programName(); + const QCString format = KoDocument::readNativeFormatMimeType( instance ); + const QStringList extraNativeMimeTypes = KoDocument::readExtraNativeMimeTypes( instance ); + // Maybe the above two can be combined into one call, for speed: + //KoDocument::getNativeMimeTypeInfo( instance, nativeName, extraNativeMimeTypes ); + return choose( instance, file, format, nativeName, extraNativeMimeTypes, + dialogType, templateType, parent ); +} + +KoTemplateChooseDia::ReturnType KoTemplateChooseDia::choose(KInstance* instance, QString &file, + const QCString &format, + const QString &nativeName, + const QStringList& extraNativeMimeTypes, + const DialogType &dialogType, + const QCString& templateType, + QWidget* parent ) +{ + KoTemplateChooseDia *dlg = new KoTemplateChooseDia( + parent, "Choose", instance, format, + nativeName, extraNativeMimeTypes, dialogType, templateType ); + + KoTemplateChooseDia::ReturnType rt = Cancel; + + if (dlg->noStartupDlg()) + { + // start with the default template + file = dlg->getFullTemplate(); + rt = dlg->getReturnType(); + } + else + { + dlg->resize( 700, 480 ); + if ( dlg->exec() == QDialog::Accepted ) + { + file = dlg->getFullTemplate(); + rt = dlg->getReturnType(); + } + } + + delete dlg; + return rt; +} + +bool KoTemplateChooseDia::noStartupDlg() const { + return d->m_nostartupdlg; +} + + +QString KoTemplateChooseDia::getTemplate() const{ + return d->m_templateName; +} + +QString KoTemplateChooseDia::getFullTemplate() const{ + return d->m_fullTemplateName; +} + +KoTemplateChooseDia::ReturnType KoTemplateChooseDia::getReturnType() const { + return d->m_returnType; +} + +KoTemplateChooseDia::DialogType KoTemplateChooseDia::getDialogType() const { + return d->m_dialogType; +} + +/*================================================================*/ +// private +void KoTemplateChooseDia::setupRecentDialog(QWidget * widgetbase, QGridLayout * layout) +{ + + d->m_recent = new KoTCDRecentFilesIconView(widgetbase, "recent files"); + // I prefer the icons to be in "most recent first" order (DF) + d->m_recent->setSorting( static_cast<QDir::SortSpec>( QDir::Time | QDir::Reversed ) ); + layout->addWidget(d->m_recent,0,0); + + QString oldGroup = d->m_instance->config()->group(); + d->m_instance->config()->setGroup( "RecentFiles" ); + + int i = 0; + QString value; + do { + QString key=QString( "File%1" ).arg( i ); + value=d->m_instance->config()->readPathEntry( key ); + if ( !value.isEmpty() ) { + // Support for kdelibs-3.5's new RecentFiles format: name[url] + QString s = value; + if ( s.endsWith("]") ) + { + int pos = s.find("["); + s = s.mid( pos + 1, s.length() - pos - 2); + } + KURL url(s); + + if(!url.isLocalFile() || QFile::exists(url.path())) { + KFileItem *item = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, url ); + d->m_recent->insertItem(item); + } + } + i++; + } while ( !value.isEmpty() || i<=10 ); + + d->m_instance->config()->setGroup( oldGroup ); + d->m_recent->showPreviews(); + + connect(d->m_recent, SIGNAL( doubleClicked ( QIconViewItem * ) ), + this, SLOT( recentSelected( QIconViewItem * ) ) ); + +} + +/*================================================================*/ +// private +void KoTemplateChooseDia::setupFileDialog(QWidget * widgetbase, QGridLayout * layout) +{ + QString dir = QString::null; + QPoint point( 0, 0 ); + + d->m_filedialog=new MyFileDialog(dir, + QString::null, + widgetbase, + "file dialog", + false); + + layout->addWidget(d->m_filedialog,0,0); + d->m_filedialog->reparent( widgetbase , point ); + //d->m_filedialog->setOperationMode( KFileDialog::Opening); + + QObjectList *l = d->m_filedialog->queryList( "QPushButton" ); + QObjectListIt childit( *l ); + QObject *obj; + while ( (obj = childit.current()) != 0 ) { + ++childit; + ((QPushButton*)obj)->hide(); + } + delete l; + + d->m_filedialog->setSizeGripEnabled ( FALSE ); + + QStringList mimeFilter = KoFilterManager::mimeFilter( d->m_format, KoFilterManager::Import ); + QStringList::Iterator mimeFilterIt = mimeFilter.at( 1 ); + for ( QStringList::ConstIterator it = d->m_extraNativeMimeTypes.begin(); + it != d->m_extraNativeMimeTypes.end(); ++it ) { + mimeFilterIt = mimeFilter.insert( mimeFilterIt, *it ); + ++mimeFilterIt; + } + d->m_filedialog->setMimeFilter( mimeFilter ); + + connect(d->m_filedialog, SIGNAL( okClicked() ), + this, SLOT ( slotOk() )); + + connect(d->m_filedialog, SIGNAL( cancelClicked() ), + this, SLOT ( slotCancel() )); + +} + +/*================================================================*/ +// private +void KoTemplateChooseDia::setupTemplateDialog(QWidget * widgetbase, QGridLayout * layout) +{ + + d->m_jwidget = new KJanusWidget( + widgetbase, + "kjanuswidget", + KJanusWidget::IconList); + layout->addWidget(d->m_jwidget,0,0); + + d->boxdescription = new QVGroupBox( + i18n("Selected Template"), + widgetbase, + "boxdescription"); + layout->addWidget(d->boxdescription, 1, 0 ); + + // config + KConfigGroup grp( d->m_instance->config(), "TemplateChooserDialog" ); + int templateNum = grp.readNumEntry( "TemplateTab", -1 ); + QString templateName = grp.readPathEntry( "TemplateName" ); + if ( templateName.isEmpty() && d->tree->defaultTemplate() ) + templateName = d->tree->defaultTemplate()->name(); //select the default template for the app + + // item which will be selected initially + QIconViewItem * itemtoselect = 0; + + // count the templates inserted + int entriesnumber = 0; + int defaultTemplateGroup = -1; + + for ( KoTemplateGroup *group = d->tree->first(); group!=0L; group=d->tree->next() ) + { + if (group->isHidden()) + continue; + + if ( d->tree->defaultGroup() == group ) + defaultTemplateGroup = entriesnumber; //select the default template group for the app + + QFrame * frame = d->m_jwidget->addPage ( + group->name(), + group->name(), + group->first()->loadPicture(d->m_instance)); + + QGridLayout * layout = new QGridLayout(frame); + KoTCDIconCanvas *canvas = new KoTCDIconCanvas( frame ); + layout->addWidget(canvas,0,0); + + canvas->setBackgroundColor( colorGroup().base() ); + canvas->setResizeMode(QIconView::Adjust); + canvas->setWordWrapIconText( true ); + canvas->show(); + + QIconViewItem * tempitem = canvas->load(group, templateName, d->m_instance); + if (tempitem) + itemtoselect = tempitem; + + canvas->sort(); + canvas->setSelectionMode(QIconView::Single); + + connect( canvas, SIGNAL( clicked ( QIconViewItem * ) ), + this, SLOT( currentChanged( QIconViewItem * ) ) ); + + connect( canvas, SIGNAL( doubleClicked( QIconViewItem * ) ), + this, SLOT( chosen(QIconViewItem *) ) ); + + entriesnumber++; + } + + d->boxdescription->setInsideMargin ( 3 ); + d->boxdescription->setInsideSpacing ( 3 ); + + d->textedit = new KTextEdit( d->boxdescription ); + d->textedit->setReadOnly(1); + d->textedit->setText(descriptionText(i18n("Empty Document"), i18n("Creates an empty document"))); + d->textedit->setLineWidth(0); + d->textedit->setMaximumHeight(50); + + // Hide the widget if there is no template available. This should never happen ;-) + if (!entriesnumber) + d->m_jwidget->hide(); + + // Set the initially shown page, possibly from the last usage of the dialog + if (entriesnumber >= templateNum && templateNum != -1 ) + d->m_jwidget->showPage(templateNum); + else if ( defaultTemplateGroup != -1) + d->m_jwidget->showPage(defaultTemplateGroup); + + + // Set the initially selected template, possibly from the last usage of the dialog + currentChanged(itemtoselect); + + // setup the checkbox + QString translatedstring = i18n("Always start %1 with the selected template").arg(d->m_nativeName); + + d->m_nodiag = new QCheckBox ( translatedstring , widgetbase); + layout->addWidget(d->m_nodiag, 2, 0); + QString startwithoutdialog = grp.readEntry( "NoStartDlg" ); + bool ischecked = startwithoutdialog == QString("yes"); + + // When not starting up, display a tri-state button telling whether + // the user actually choosed the template to start with next times (bug:77542) + if (d->m_dialogType == Everything) + { + d->m_nodiag->setChecked( ischecked ); + } + else + { + d->m_nodiag->setTristate(); + d->m_nodiag->setNoChange(); + } +} + +/*================================================================*/ +// private +void KoTemplateChooseDia::setupDialog() +{ + + QGridLayout *maingrid=new QGridLayout( d->m_mainwidget, 1, 1, 2, 6); + KConfigGroup grp( d->m_instance->config(), "TemplateChooserDialog" ); + + if (d->m_dialogType == Everything) + { + + // the user may want to start with his favorite template + if (grp.readEntry( "NoStartDlg" ) == QString("yes") ) + { + d->m_nostartupdlg = true; + d->m_returnType = Empty; + + // no default template, just start with an empty document + if (grp.readEntry("LastReturnType") == QString("Empty") ) + return; + + // start with the default template + d->m_templateName = grp.readPathEntry( "TemplateName" ); + d->m_fullTemplateName = grp.readPathEntry( "FullTemplateName" ); + + // be paranoid : invalid template means empty template + if (!QFile::exists(d->m_fullTemplateName)) + return; + + if (d->m_fullTemplateName.length() < 2) + return; + + d->m_returnType = Template; + return; + } + + if ( cancelQuits() ) + setButtonCancel( KStdGuiItem::quit() ); + + d->tabWidget = new QTabWidget( d->m_mainwidget, "tabWidget" ); + maingrid->addWidget( d->tabWidget, 0, 0 ); + + // new document + d->newTab = new QWidget( d->tabWidget, "newTab" ); + d->tabWidget->insertTab( d->newTab, i18n( "&Create Document" ) ); + QGridLayout * newTabLayout = new QGridLayout( d->newTab, 1, 1, KDialogBase::marginHint(), KDialogBase::spacingHint()); + + // existing document + d->existingTab = new QWidget( d->tabWidget, "existingTab" ); + d->tabWidget->insertTab( d->existingTab, i18n( "Open &Existing Document" ) ); + QGridLayout * existingTabLayout = new QGridLayout( d->existingTab, 1, 1, 0, KDialog::spacingHint()); + + // recent document + d->recentTab = new QWidget( d->tabWidget, "recentTab" ); + d->tabWidget->insertTab( d->recentTab, i18n( "Open &Recent Document" ) ); + QGridLayout * recentTabLayout = new QGridLayout( d->recentTab, 1, 1, KDialogBase::marginHint(), KDialog::spacingHint()); + + setupTemplateDialog(d->newTab, newTabLayout); + setupFileDialog(d->existingTab, existingTabLayout); + setupRecentDialog(d->recentTab, recentTabLayout); + + QString tabhighlighted = grp.readEntry("LastReturnType"); + if ( tabhighlighted == "Template" ) + d->tabWidget->setCurrentPage(0); // CreateDocument tab + else if (tabhighlighted == "File" ) + d->tabWidget->setCurrentPage(2); // RecentDocument tab + else + d->tabWidget->setCurrentPage(0); // Default setting: CreateDocument tab + } + else + { + + // open a file + if (d->m_dialogType == NoTemplates) + { + setupFileDialog(d->m_mainwidget, maingrid); + } + // create a new document from a template + if (d->m_dialogType == OnlyTemplates) + { + setCaption(i18n( "Create Document" )); + setupTemplateDialog(d->m_mainwidget, maingrid); + } + } +} + +/*================================================================*/ +// private SLOT +void KoTemplateChooseDia::currentChanged( QIconViewItem * item) +{ + if (item) + { + QIconView* canvas = item->iconView(); + + // set text in the textarea + d->textedit->setText( descriptionText( + item->text(), + ((KoTCDIconViewItem *) item)->getDescr() + )); + + // set the icon in the canvas selected + if (canvas) + canvas->setSelected(item,1,0); + + // register the current template + d->m_templateName = item->text(); + d->m_fullTemplateName = ((KoTCDIconViewItem *) item)->getFName(); + } +} + +/*================================================================*/ +// private SLOT +void KoTemplateChooseDia::chosen(QIconViewItem * item) +{ + // the user double clicked on a template + if (item) + { + currentChanged(item); + slotOk(); + } +} + +/* */ +// private SLOT +void KoTemplateChooseDia::recentSelected( QIconViewItem * item) +{ + if (item) + { + slotOk(); + } +} + +/*================================================================*/ +// protected SLOT +void KoTemplateChooseDia::slotOk() +{ + // Collect info from the dialog into d->m_returnType and d->m_templateName etc. + if (collectInfo()) + { + // Save it for the next time + KConfigGroup grp( d->m_instance->config(), "TemplateChooserDialog" ); + static const char* const s_returnTypes[] = { 0 /*Cancel ;)*/, "Template", "File", "Empty" }; + if ( d->m_returnType <= Empty ) + { + grp.writeEntry( "LastReturnType", QString::fromLatin1(s_returnTypes[d->m_returnType]) ); + if (d->m_returnType == Template) + { + grp.writeEntry( "TemplateTab", d->m_jwidget->activePageIndex() ); + grp.writePathEntry( "TemplateName", d->m_templateName ); + grp.writePathEntry( "FullTemplateName", d->m_fullTemplateName); + } + + if (d->m_nodiag) + { + // The checkbox m_nodiag is in tri-state mode for new documents + // fixes bug:77542 + if (d->m_nodiag->state() == QButton::On) { + grp.writeEntry( "NoStartDlg", "yes"); + } + else if (d->m_nodiag->state() == QButton::Off) { + grp.writeEntry( "NoStartDlg", "no"); + } + } + } + else + { + kdWarning(30003) << "Unsupported template chooser result: " << d->m_returnType << endl; + grp.writeEntry( "LastReturnType", QString::null ); + } + KDialogBase::slotOk(); + } +} + +/*================================================================*/ +// private +bool KoTemplateChooseDia::collectInfo() +{ + + + // to determine what tab is selected in "Everything" mode + bool newTabSelected = false; + if ( d->m_dialogType == Everything) + if ( d->tabWidget->currentPage() == d->newTab ) + newTabSelected = true; + + // is it a template or a file ? + if ( d->m_dialogType==OnlyTemplates || newTabSelected ) + { + // a template is chosen + if (d->m_templateName.length() > 0) + d->m_returnType = Template; + else + d->m_returnType=Empty; + + return true; + } + else if ( d->m_dialogType != OnlyTemplates ) + { + // a file is chosen + if (d->m_dialogType == Everything && d->tabWidget->currentPage() == d->recentTab) + { + // Recent file + KFileItem * item = d->m_recent->currentFileItem(); + if (! item) + return false; + KURL url = item->url(); + if(url.isLocalFile() && !QFile::exists(url.path())) + { + KMessageBox::error( this, i18n( "The file %1 does not exist." ).arg( url.path() ) ); + return false; + } + d->m_fullTemplateName = url.url(); + d->m_returnType = File; + } + else + { + // Existing file from file dialog + if ( !d->m_filedialog->slotOkCalled() ) + d->m_filedialog->slotOk(); + KURL url = d->m_filedialog->currentURL(); + d->m_fullTemplateName = url.url(); + d->m_returnType = File; + return d->m_filedialog->checkURL(); + } + return true; + } + + d->m_returnType=Empty; + return false; +} + +/*================================================================*/ +//private +QString KoTemplateChooseDia::descriptionText(const QString &name, const QString &description) +{ + QString descrText(i18n("Name:")); + descrText += " " + name; + descrText += "\n"; + descrText += i18n("Description:"); + if (description.isEmpty()) + descrText += " " + i18n("No description available"); + else + descrText += " " + description; + return descrText; +} + +/*================================================================*/ + +QIconViewItem * KoTCDIconCanvas::load( KoTemplateGroup *group, const QString& name, KInstance* instance ) +{ + QIconViewItem * itemtoreturn = 0; + + for (KoTemplate *t=group->first(); t!=0L; t=group->next()) { + if (t->isHidden()) + continue; + QIconViewItem *item = new KoTCDIconViewItem( + this, + t->name(), + t->loadPicture(instance), + t->description(), + t->file()); + + if (name == t->name()) + { + itemtoreturn = item; + } + + item->setKey(t->name()); + item->setDragEnabled(false); + item->setDropEnabled(false); + } + + return itemtoreturn; +} + +/*================================================================*/ + +KoTCDRecentFilesIconView::~KoTCDRecentFilesIconView() +{ + removeToolTip(); +} + +void KoTCDRecentFilesIconView::showToolTip( QIconViewItem* item ) +{ + removeToolTip(); + if ( !item ) + return; + + // Mostly duplicated from KFileIconView, because it only shows tooltips + // for truncated icon texts, and we want tooltips on all icons, + // with the full path... + // KFileIconView would need a virtual method for deciding if a tooltip should be shown, + // and another one for deciding what's the text of the tooltip... + const KFileItem *fi = ( (KFileIconViewItem*)item )->fileInfo(); + QString toolTipText = fi->url().prettyURL( 0, KURL::StripFileProtocol ); + toolTip = new QLabel( QString::fromLatin1(" %1 ").arg(toolTipText), 0, + "myToolTip", + WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM ); + toolTip->setFrameStyle( QFrame::Plain | QFrame::Box ); + toolTip->setLineWidth( 1 ); + toolTip->setAlignment( AlignLeft | AlignTop ); + toolTip->move( QCursor::pos() + QPoint( 14, 14 ) ); + toolTip->adjustSize(); + QRect screen = QApplication::desktop()->screenGeometry( + QApplication::desktop()->screenNumber(QCursor::pos())); + if (toolTip->x()+toolTip->width() > screen.right()) { + toolTip->move(toolTip->x()+screen.right()-toolTip->x()-toolTip->width(), toolTip->y()); + } + if (toolTip->y()+toolTip->height() > screen.bottom()) { + toolTip->move(toolTip->x(), screen.bottom()-toolTip->y()-toolTip->height()+toolTip->y()); + } + toolTip->setFont( QToolTip::font() ); + toolTip->setPalette( QToolTip::palette(), TRUE ); + toolTip->show(); +} + +void KoTCDRecentFilesIconView::removeToolTip() +{ + delete toolTip; + toolTip = 0; +} + +void KoTCDRecentFilesIconView::hideEvent( QHideEvent *ev ) +{ + removeToolTip(); + KFileIconView::hideEvent( ev ); +} + +#include "KoTemplateChooseDia.moc" diff --git a/lib/kofficeui/KoTemplateChooseDia.h b/lib/kofficeui/KoTemplateChooseDia.h new file mode 100644 index 00000000..41389b20 --- /dev/null +++ b/lib/kofficeui/KoTemplateChooseDia.h @@ -0,0 +1,250 @@ +/* + This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + 2000, 2001 Werner Trobin <trobin@kde.org> + 2002, 2003 Thomas Nagy <tnagy@eleve.emn.fr> + 2004 David Faure <faure@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. + */ + +#ifndef koTemplateChooseDia_h +#define koTemplateChooseDia_h + +#include <kdialogbase.h> +#include <kicondialog.h> +#include <kiconview.h> +#include <koffice_export.h> + +// KoTCD : KoTemplateChooseDia + +class KoTCDIconViewItem; +class KoTemplateTree; +class KoTemplateGroup; +class QGridLayout; + +/** + * Our reimplementation of KIconCanvas used within the template-chooser dialog. + * @internal + */ +class KoTCDIconCanvas : public KIconCanvas +{ + Q_OBJECT + public: + KoTCDIconCanvas( QWidget *parent = 0, const char *name = 0L ) + : KIconCanvas( parent, name ) {} + + bool isCurrentValid() { return currentItem(); } + QIconViewItem * load(KoTemplateGroup *group, const QString& name, KInstance* instance); + + protected: + virtual void keyPressEvent( QKeyEvent *e ) { + if ( e->key() == Key_Return || e->key() == Key_Enter ) + e->ignore(); + else + KIconCanvas::keyPressEvent( e ); + } +}; + +/// @internal +class KoTCDIconViewItem : public KIconViewItem +{ + public: + KoTCDIconViewItem(QIconView *parent=0) + : KIconViewItem ( parent ) + {} + + KoTCDIconViewItem(QIconView *parent=0, const QString &text=0, const QPixmap &icon=0, + const QString &descr=0, const QString &fullname=0) + : KIconViewItem(parent, text, icon) + { + m_descr = descr; + m_full = fullname; + } + + QString getDescr() const { return m_descr; } + QString getFName() const { return m_full; } + + private : + QString m_descr; + QString m_full; + +}; + +#include <kfileiconview.h> +#include <qlabel.h> +/** + * Our reimplementation of KFileIconView used as the "recent files" view + * within the template-chooser dialog. + * @internal + */ +class KoTCDRecentFilesIconView : public KFileIconView { + Q_OBJECT + public: + KoTCDRecentFilesIconView( QWidget* parent, const char* name ) : + KFileIconView( parent, name ), toolTip(0) + { + connect( this, SIGNAL( onItem( QIconViewItem * ) ), + SLOT( showToolTip( QIconViewItem * ) ) ); + connect( this, SIGNAL( onViewport() ), + SLOT( removeToolTip() ) ); + } + virtual ~KoTCDRecentFilesIconView(); + protected: + /** + * Reimplemented to remove an eventual tooltip + */ + virtual void hideEvent( QHideEvent * ); + + private slots: + void showToolTip( QIconViewItem* ); + void removeToolTip(); + private: + QLabel* toolTip; +}; + +class KInstance; +class KoTemplateChooseDiaPrivate; + +/** + * This class is used to show the template dialog + * on startup. Unless you need something special, you should use the static + * method choose(). + * + * @short The template choose dialog + * @author Reginald Stadlbauer <reggie@kde.org> + * @author Werner Trobin <trobin@kde.org> + */ +class KOFFICEUI_EXPORT KoTemplateChooseDia : public KDialogBase +{ + Q_OBJECT + +public: + /** + * The Dialog returns one of these values depending + * on the input of the user. + * Cancel = The user pressed 'Cancel' + * Template = The user selected a template + * File = The user has chosen a file + * Empty = The user selected "Empty document" + */ + enum ReturnType { Cancel, Template, File, Empty }; + /** + * To configure the dialog you have to use this enum. + * Everything = Show templates and the rest of the dialog + * OnlyTemplates = Show only the templates + * NoTemplates = Just guess :) + */ + enum DialogType { Everything, OnlyTemplates, NoTemplates }; + + ~KoTemplateChooseDia(); + + /** + * This is the static method you'll normally use to show the + * dialog. + * + * @param instance the KInstance of your app + * The native mimetype is retrieved from the (desktop file of) that instance. + * @param file this is the filename which is returned to your app + * More precisely, it's a url (to give to KURL) if ReturnType is File + * and it's a path (to open directly) if ReturnType is Template + * + * @param dialogType the type of the dialog + * @param templateType the template type of your application (see kword or + * kpresenter for details) + * @param parent pointer to parent widget + * @return The return type (see above) + */ + static ReturnType choose(KInstance* instance, QString &file, + const DialogType &dialogType, + const QCString& templateType, + QWidget* parent); + +private: + /// Ditto, with extraNativeMimeTypes added + static ReturnType choose(KInstance* instance, QString &file, + const QCString &format, + const QString &nativeName, + const QStringList& extraNativeMimeTypes, + const DialogType &dialogType=Everything, + const QCString& templateType="", + QWidget* parent = 0); +public: + + /** + * Method to get the current template + */ + QString getTemplate() const; + /** + * Method to get the "full" template (path+template) + */ + QString getFullTemplate() const; + /** + * The ReturnType (call this one after exec()) + */ + ReturnType getReturnType() const; + /** + * The dialogType - normally you won't need this one + */ + DialogType getDialogType() const; + +protected slots: + /** + * Activated when the Ok button has been clicked. + */ + virtual void slotOk(); + +private: + /** + * + * @param parent parent the parent of the dialog + * @param name the Qt internal name + * @param instance the KInstance of your app + * @param format is the mimetype of the app (e.g. application/x-kspread) + * @param nativeName is the name of your app (e.g KSpread) + * @param dialogType the type of the dialog + * @param templateType the template type of your application (see kword or + * kpresenter for details) + * + * @return The return type (see above) + */ + KoTemplateChooseDia(QWidget *parent, const char *name, KInstance* instance, + const QCString &format, + const QString &nativeName, + const QStringList &extraNativeMimeTypes, + const DialogType &dialogType=Everything, + const QCString& templateType=""); + +private: + KoTemplateChooseDiaPrivate *d; + + QString descriptionText(const QString &name, const QString &description); + void setupDialog(); + void setupTemplateDialog(QWidget * widgetbase, QGridLayout * layout); + void setupFileDialog(QWidget * widgetbase, QGridLayout * layout); + void setupRecentDialog(QWidget * widgetbase, QGridLayout * layout); + bool collectInfo(); + bool noStartupDlg() const; + +private slots: + + void chosen(QIconViewItem *); + void currentChanged( QIconViewItem * ); + void recentSelected( QIconViewItem * ); +}; + +#endif + diff --git a/lib/kofficeui/KoTemplateCreateDia.cpp b/lib/kofficeui/KoTemplateCreateDia.cpp new file mode 100644 index 00000000..0e89bb99 --- /dev/null +++ b/lib/kofficeui/KoTemplateCreateDia.cpp @@ -0,0 +1,497 @@ +/* + This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + 2000 Werner Trobin <trobin@kde.org> + Copyright (C) 2004 Nicolas GOUTTE <goutte@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 <KoTemplateCreateDia.h> + +#include <qfile.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qgroupbox.h> +#include <qradiobutton.h> +#include <qpushbutton.h> +#include <qheader.h> +#include <qcheckbox.h> +#include <qtooltip.h> + +#include <ktempfile.h> +#include <klineedit.h> +#include <klistview.h> +#include <klocale.h> +#include <KoTemplates.h> +#include <kicondialog.h> +#include <kinputdialog.h> +#include <kmessagebox.h> +#include <kimageio.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <kio/netaccess.h> +#include <kiconloader.h> +#include <kaboutdata.h> +#include <kconfigbase.h> +#include <kconfig.h> + +#include <stdlib.h> +#include <kinstance.h> + + +class KoTemplateCreateDiaPrivate { +public: + KoTemplateCreateDiaPrivate( QWidget* /*parent*/, KInstance * instance) + : m_instance( instance ), m_tempFile( QString::null, ".png" ) + { + m_tree=0L; + m_name=0L; + m_default=0L; + m_custom=0L; + m_select=0L; + m_preview=0L; + m_groups=0L; + m_add=0L; + m_remove=0L; + m_defaultTemplate=0L; + m_tempFile.setAutoDelete( true ); + } + ~KoTemplateCreateDiaPrivate() { + delete m_tree; + } + + KoTemplateTree *m_tree; + KLineEdit *m_name; + QRadioButton *m_default, *m_custom; + QPushButton *m_select; + QLabel *m_preview; + QString m_customFile; + QPixmap m_customPixmap; + KListView *m_groups; + QPushButton *m_add, *m_remove; + QCheckBox *m_defaultTemplate; + KInstance *m_instance; + bool m_changed; + /// Temp file for remote picture file + KTempFile m_tempFile; +}; + + +/**************************************************************************** + * + * Class: koTemplateCreateDia + * + ****************************************************************************/ + +KoTemplateCreateDia::KoTemplateCreateDia( const QCString &templateType, KInstance *instance, + const QString &file, const QPixmap &pix, QWidget *parent ) : + KDialogBase( parent, "template create dia", true, i18n( "Create Template" ), + KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ), m_file(file), m_pixmap(pix) { + + d=new KoTemplateCreateDiaPrivate( parent, instance ); + + QFrame *mainwidget=makeMainWidget(); + QHBoxLayout *mbox=new QHBoxLayout(mainwidget, 0, KDialogBase::spacingHint()); + QVBoxLayout *leftbox=new QVBoxLayout(mbox); + + QLabel *label=new QLabel(i18n("Name:"), mainwidget); + leftbox->addSpacing(label->fontMetrics().height()/2); + QHBoxLayout *namefield=new QHBoxLayout(leftbox); + namefield->addWidget(label); + d->m_name=new KLineEdit(mainwidget); + d->m_name->setFocus(); + connect(d->m_name, SIGNAL(textChanged(const QString &)), + this, SLOT(slotNameChanged(const QString &))); + namefield->addWidget(d->m_name); + + label=new QLabel(i18n("Group:"), mainwidget); + leftbox->addWidget(label); + d->m_groups=new KListView(mainwidget); + leftbox->addWidget(d->m_groups); + d->m_groups->addColumn(""); + d->m_groups->header()->hide(); + d->m_groups->setRootIsDecorated(true); + d->m_groups->setSorting(0); + + d->m_tree=new KoTemplateTree(templateType, instance, true); + fillGroupTree(); + d->m_groups->sort(); + + QHBoxLayout *bbox=new QHBoxLayout(leftbox); + d->m_add=new QPushButton(i18n("&Add Group..."), mainwidget); + connect(d->m_add, SIGNAL(clicked()), this, SLOT(slotAddGroup())); + bbox->addWidget(d->m_add); + d->m_remove=new QPushButton(i18n("&Remove"), mainwidget); + connect(d->m_remove, SIGNAL(clicked()), this, SLOT(slotRemove())); + bbox->addWidget(d->m_remove); + + QVBoxLayout *rightbox=new QVBoxLayout(mbox); + QGroupBox *pixbox=new QGroupBox(i18n("Picture"), mainwidget); + rightbox->addWidget(pixbox); + QVBoxLayout *pixlayout=new QVBoxLayout(pixbox, KDialogBase::marginHint(), + KDialogBase::spacingHint()); + pixlayout->addSpacing(pixbox->fontMetrics().height()/2); + pixlayout->addStretch(1); + d->m_default=new QRadioButton(i18n("&Default"), pixbox); + d->m_default->setChecked(true); + connect(d->m_default, SIGNAL(clicked()), this, SLOT(slotDefault())); + pixlayout->addWidget(d->m_default); + QHBoxLayout *custombox=new QHBoxLayout(pixlayout); + d->m_custom=new QRadioButton(i18n("Custom"), pixbox); + d->m_custom->setChecked(false); + connect(d->m_custom, SIGNAL(clicked()), this, SLOT(slotCustom())); + custombox->addWidget(d->m_custom); + d->m_select=new QPushButton(i18n("&Select..."), pixbox); + connect(d->m_select, SIGNAL(clicked()), this, SLOT(slotSelect())); + custombox->addWidget(d->m_select, 1); + custombox->addStretch(1); + pixlayout->addStretch(1); + label=new QLabel(i18n("Preview:"), pixbox); + pixlayout->addWidget(label); + QHBoxLayout *previewbox=new QHBoxLayout(pixlayout); + previewbox->addStretch(10); + d->m_preview=new QLabel(pixbox); // setPixmap() -> auto resize? + previewbox->addWidget(d->m_preview); + previewbox->addStretch(10); + pixlayout->addStretch(8); + + d->m_defaultTemplate = new QCheckBox( i18n("Use the new template as default"), mainwidget ); + d->m_defaultTemplate->setChecked( true ); + QToolTip::add( d->m_defaultTemplate, i18n("Use the new template every time %1 starts").arg(instance->aboutData()->programName() ) ); + rightbox->addWidget( d->m_defaultTemplate ); + + enableButtonOK(false); + d->m_changed=false; + updatePixmap(); + + connect(d->m_groups,SIGNAL( selectionChanged()),this,SLOT(slotSelectionChanged())); + + d->m_remove->setEnabled(d->m_groups->currentItem()); +} + +KoTemplateCreateDia::~KoTemplateCreateDia() { + delete d; +} + +void KoTemplateCreateDia::slotSelectionChanged() +{ + const QListViewItem* item = d->m_groups->currentItem(); + d->m_remove->setEnabled( item ); + if ( ! item ) + return; + + if ( item->depth() > 0 ) + { + d->m_name->setText( item->text( 0 ) ); + } +} + +void KoTemplateCreateDia::createTemplate( const QCString &templateType, KInstance *instance, + const QString &file, const QPixmap &pix, QWidget *parent ) { + + KoTemplateCreateDia *dia = new KoTemplateCreateDia( templateType, instance, file, pix, parent ); + dia->exec(); + delete dia; +} + +void KoTemplateCreateDia::slotOk() { + + // get the current item, if there is one... + QListViewItem *item=d->m_groups->currentItem(); + if(!item) + item=d->m_groups->firstChild(); + if(!item) { // safe :) + d->m_tree->writeTemplateTree(); + KDialogBase::slotCancel(); + return; + } + // is it a group or a template? anyway - get the group :) + if(item->depth()!=0) + item=item->parent(); + if(!item) { // *very* safe :P + d->m_tree->writeTemplateTree(); + KDialogBase::slotCancel(); + return; + } + + KoTemplateGroup *group=d->m_tree->find(item->text(0)); + if(!group) { // even safer + d->m_tree->writeTemplateTree(); + KDialogBase::slotCancel(); + return; + } + + if(d->m_name->text().isEmpty()) { + d->m_tree->writeTemplateTree(); + KDialogBase::slotCancel(); + return; + } + + // copy the tmp file and the picture the app provides + QString dir=d->m_tree->instance()->dirs()->saveLocation(d->m_tree->templateType()); + dir+=group->name(); + QString templateDir=dir+"/.source/"; + QString iconDir=dir+"/.icon/"; + + QString file=KoTemplates::stripWhiteSpace(d->m_name->text()); + QString tmpIcon=".icon/"+file; + tmpIcon+=".png"; + QString icon=iconDir+file; + icon+=".png"; + + // try to find the extension for the template file :P + const int pos = m_file.findRev( '.' ); + QString ext; + if ( pos > -1 ) + ext = m_file.mid( pos ); + else + kdWarning(30004) << "Template extension not found!" << endl; + + KURL dest; + dest.setPath(templateDir+file+ext); + if ( QFile::exists( dest.prettyURL(0, KURL::StripFileProtocol) ) ) + { + do + { + file.prepend( '_' ); + dest.setPath( templateDir + file + ext ); + tmpIcon=".icon/"+file+".png"; + icon=iconDir+file+".png"; + } + while ( KIO::NetAccess::exists( dest, true, this ) ); + } + bool ignore = false; + kdDebug(30004) << "Trying to create template: " << d->m_name->text() << "URL=" << ".source/"+file+ext << " ICON=" << tmpIcon << endl; + KoTemplate *t=new KoTemplate(d->m_name->text(), QString::null, ".source/"+file+ext, tmpIcon, "", "", false, true); + if(!group->add(t)) { + KoTemplate *existingTemplate=group->find(d->m_name->text()); + if(existingTemplate && !existingTemplate->isHidden()) { + if(KMessageBox::warningYesNo(this, i18n("Do you really want to overwrite" + " the existing '%1' template?"). + arg(existingTemplate->name()))==KMessageBox::Yes) + group->add(t, true); + else + { + delete t; + return; + } + } + else + ignore = true; + } + + if(!KStandardDirs::makeDir(templateDir) || !KStandardDirs::makeDir(iconDir)) { + d->m_tree->writeTemplateTree(); + KDialogBase::slotCancel(); + return; + } + + KURL orig; + orig.setPath( m_file ); + // don't overwrite the hidden template file with a new non-hidden one + if ( !ignore ) + { + // copy the template file + KIO::NetAccess::file_copy( orig, dest, -1, true, false, this ); + + // save the picture + if(d->m_default->isChecked() && !m_pixmap.isNull()) + m_pixmap.save(icon, "PNG"); + else if(!d->m_customPixmap.isNull()) + d->m_customPixmap.save(icon, "PNG"); + else + kdWarning(30004) << "Could not save the preview picture!" << endl; + } + + // if there's a .directory file, we copy this one, too + bool ready=false; + QStringList tmp=group->dirs(); + for(QStringList::ConstIterator it=tmp.begin(); it!=tmp.end() && !ready; ++it) { + if((*it).contains(dir)==0) { + orig.setPath( (*it)+".directory" ); + // Check if we can read the file + if( KIO::NetAccess::exists(orig, true, this) ) { + dest.setPath( dir+"/.directory" ); + // We copy the file with overwrite + KIO::NetAccess::file_copy( orig, dest, -1, true, false, this ); + ready=true; + } + } + } + + d->m_tree->writeTemplateTree(); + + if ( d->m_defaultTemplate->isChecked() ) + { + KConfigGroup grp( d->m_instance->config(), "TemplateChooserDialog" ); + grp.writeEntry( "LastReturnType", "Template" ); + grp.writePathEntry( "FullTemplateName", dir + "/" + t->file() ); + grp.writePathEntry( "AlwaysUseTemplate", dir + "/" + t->file() ); + } + KDialogBase::slotOk(); +} + +void KoTemplateCreateDia::slotDefault() { + + d->m_default->setChecked(true); + d->m_custom->setChecked(false); + updatePixmap(); +} + +void KoTemplateCreateDia::slotCustom() { + + d->m_default->setChecked(false); + d->m_custom->setChecked(true); + if(d->m_customFile.isEmpty()) + slotSelect(); + else + updatePixmap(); +} + +void KoTemplateCreateDia::slotSelect() { + + d->m_default->setChecked(false); + d->m_custom->setChecked(true); + + QString name = KIconDialog::getIcon(); + if( name.isEmpty() ) { + if(d->m_customFile.isEmpty()) { + d->m_default->setChecked(true); + d->m_custom->setChecked(false); + } + return; + } + // ### TODO: do a better remote loading without having to have d->m_tempFile + QString path = KGlobal::iconLoader()->iconPath(name, KIcon::Desktop); + d->m_customFile = path; + d->m_customPixmap=QPixmap(); + updatePixmap(); +} + +void KoTemplateCreateDia::slotNameChanged(const QString &name) { + + if( ( name.stripWhiteSpace().isEmpty() || !d->m_groups->firstChild() ) && !d->m_changed ) + enableButtonOK(false); + else + enableButtonOK(true); +} + +void KoTemplateCreateDia::slotAddGroup() { + bool ok=false; + const QString name ( KInputDialog::getText( i18n("Add Group"), i18n("Enter group name:"), QString::null, &ok, this ) ); + if(!ok) + return; + KoTemplateGroup *group=d->m_tree->find(name); + if(group && !group->isHidden()) + { + KMessageBox::information( this, i18n("This name is already used."), i18n("Add Group") ); + return; + } + QString dir=d->m_tree->instance()->dirs()->saveLocation(d->m_tree->templateType()); + dir+=name; + KoTemplateGroup *newGroup=new KoTemplateGroup(name, dir, 0, true); + d->m_tree->add(newGroup); + QListViewItem *item=new QListViewItem(d->m_groups, name); + d->m_groups->setCurrentItem(item); + d->m_groups->sort(); + d->m_name->setFocus(); + enableButtonOK(true); + d->m_changed=true; +} + +void KoTemplateCreateDia::slotRemove() { + + QListViewItem *item=d->m_groups->currentItem(); + if(!item) + return; + + QString what; + QString removed; + if (item->depth()==0) { + what = i18n("Do you really want to remove that group?"); + removed = i18n("Remove Group"); + } else { + what = i18n("Do you really want to remove that template?"); + removed = i18n("Remove Template"); + } + + if(KMessageBox::warningContinueCancel(this, what, + removed,KGuiItem(i18n("&Delete"),"editdelete"))==KMessageBox::Cancel) { + d->m_name->setFocus(); + return; + } + + if(item->depth()==0) { + KoTemplateGroup *group=d->m_tree->find(item->text(0)); + if(group) + group->setHidden(true); + } + else { + bool done=false; + for(KoTemplateGroup *g=d->m_tree->first(); g!=0L && !done; g=d->m_tree->next()) { + KoTemplate *t=g->find(item->text(0)); + if(t) { + t->setHidden(true); + done=true; + } + } + } + delete item; + item=0L; + enableButtonOK(true); + d->m_name->setFocus(); + d->m_changed=true; +} + +void KoTemplateCreateDia::updatePixmap() { + + if(d->m_default->isChecked() && !m_pixmap.isNull()) + d->m_preview->setPixmap(m_pixmap); + else if(d->m_custom->isChecked() && !d->m_customFile.isEmpty()) { + if(d->m_customPixmap.isNull()) { + kdDebug(30004) << "Trying to load picture " << d->m_customFile << endl; + // use the code in KoTemplate to load the image... hacky, I know :) + KoTemplate t("foo", "bar", QString::null, d->m_customFile); + d->m_customPixmap=t.loadPicture(d->m_tree->instance()); + } + else + kdWarning(30004) << "Trying to load picture" << endl; + + if(!d->m_customPixmap.isNull()) + d->m_preview->setPixmap(d->m_customPixmap); + else + d->m_preview->setText(i18n("Could not load picture.")); + } + else + d->m_preview->setText(i18n("No picture available.")); +} + +void KoTemplateCreateDia::fillGroupTree() { + + for(KoTemplateGroup *group=d->m_tree->first(); group!=0L; group=d->m_tree->next()) { + if(group->isHidden()) + continue; + QListViewItem *groupItem=new QListViewItem(d->m_groups, group->name()); + for(KoTemplate *t=group->first(); t!=0L; t=group->next()) { + if(t->isHidden()) + continue; + (void)new QListViewItem(groupItem, t->name()); + } + } +} + +#include <KoTemplateCreateDia.moc> diff --git a/lib/kofficeui/KoTemplateCreateDia.h b/lib/kofficeui/KoTemplateCreateDia.h new file mode 100644 index 00000000..eb703592 --- /dev/null +++ b/lib/kofficeui/KoTemplateCreateDia.h @@ -0,0 +1,75 @@ +/* + This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + 2000 Werner Trobin <trobin@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. +*/ + +#ifndef koTemplateCreateDia_h +#define koTemplateCreateDia_h + +#include <kdialogbase.h> +#include <koffice_export.h> + +class QString; +class QPixmap; +class QWidget; +class KInstance; +class KLineEdit; +class QListViewItem; +class KoTemplateCreateDiaPrivate; + +/**************************************************************************** + * + * Class: koTemplateCreateDia + * + ****************************************************************************/ + +class KOFFICEUI_EXPORT KoTemplateCreateDia : public KDialogBase +{ + Q_OBJECT + +public: + KoTemplateCreateDia( const QCString &templateType, KInstance *instance, + const QString &file, const QPixmap &pix, QWidget *parent=0L ); + ~KoTemplateCreateDia(); + + static void createTemplate( const QCString &templateType, KInstance *instance, + const QString &file, const QPixmap &pix, QWidget *parent=0L ); + +protected: + void slotOk(); + +private slots: + void slotDefault(); + void slotCustom(); + void slotSelect(); + void slotNameChanged(const QString &name); + + void slotAddGroup(); + void slotRemove(); + void slotSelectionChanged(); +private: + void updatePixmap(); + void fillGroupTree(); + + QString m_file; + QPixmap m_pixmap; + KoTemplateCreateDiaPrivate *d; +}; + +#endif diff --git a/lib/kofficeui/KoToolBox.cpp b/lib/kofficeui/KoToolBox.cpp new file mode 100644 index 00000000..60a3a2bf --- /dev/null +++ b/lib/kofficeui/KoToolBox.cpp @@ -0,0 +1,256 @@ +/* + Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.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 <qbuttongroup.h> +#include <qnamespace.h> +#include <qtoolbutton.h> +#include <qlabel.h> +#include <qtooltip.h> +#include <qlayout.h> +#include <qpixmap.h> +#include <qtoolbar.h> +#include <qdockwindow.h> + +#include <kdebug.h> +#include <kparts/event.h> +#include <klocale.h> +#include <ktoolbar.h> +#include <kiconloader.h> +#include <kseparator.h> +#include <kaction.h> +#include <kactioncollection.h> +#include <kactionclasses.h> + +#include <KoMainWindow.h> +#include "KoToolBox.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +KoToolBox::KoToolBox( KMainWindow *mainWin, const char* name, KInstance* instance, int numberOfTooltypes ) + : KToolBar( mainWin, Qt::DockLeft, false, name, true, true), m_instance(instance) +{ + setFullSize( false ); + setMargin(2); + + m_buttonGroup = new QButtonGroup( 0L ); + m_buttonGroup->setExclusive( true ); + connect( m_buttonGroup, SIGNAL( pressed( int ) ), this, SLOT( slotButtonPressed( int ) ) ); + + m_tools.setAutoDelete( true ); + // Create separate lists for the various sorts of tools + for (int i = 0; i < numberOfTooltypes ; ++i) { + ToolList * tl = new ToolList(); + m_tools.append(tl); + } +} + +KoToolBox::~KoToolBox() +{ + delete m_buttonGroup; +} + + +void KoToolBox::slotPressButton( int id ) +{ + m_buttonGroup->setButton( id ); + slotButtonPressed( id ); +} + +void KoToolBox::slotButtonPressed( int id ) +{ + if( id != m_buttonGroup->selectedId() && m_buttonGroup->selected() ) { + m_buttonGroup->selected()->setDown( false ); + } + m_idToActionMap.at(id)->activate(); + +} + +void KoToolBox::registerTool( KAction *tool, int toolType, Q_UINT32 priority ) +{ + uint prio = priority; + ToolList * tl = m_tools.at(toolType); + while( (*tl)[prio] ) prio++; + (*tl)[prio] = tool; +} + +QToolButton *KoToolBox::createButton(QWidget * parent, const char* iconName, QString tooltip) +{ + QToolButton *button = new QToolButton(parent); + + if ( iconName && *iconName ) { + QPixmap pixmap = BarIcon( iconName, m_instance ); + button->setPixmap( pixmap ); + button->setToggleButton( true ); + } + + if ( !tooltip.isEmpty() ) { + QToolTip::add( button, tooltip ); + } + return button; +} + + +void KoToolBox::setupTools() +{ + int id = 0; + // Loop through tooltypes + for (uint i = 0; i < m_tools.count(); ++i) { + ToolList * tl = m_tools.at(i); + + if (!tl) continue; + if (tl->isEmpty()) continue; + + ToolArea *tools = new ToolArea( this ); + ToolList::Iterator it; + for ( it = tl->begin(); it != tl->end(); ++it ) + { + KAction *tool = it.data(); + if(! tool) + continue; + QToolButton *bn = createButton(tools->getNextParent(), tool->icon().latin1(), tool->toolTip()); + tools->add(bn); + m_buttonGroup->insert( bn, id++ ); + m_idToActionMap.append( tool ); + } + if (i < m_tools.count() -1) addSeparator(); + m_toolBoxes.append(tools); + } + // select first (select tool) + m_buttonGroup->setButton( 0 ); + m_numberOfButtons = id; +} + + +void KoToolBox::setOrientation ( Qt::Orientation o ) +{ + if ( barPos() == Floating ) { // when floating, make it a standing toolbox. + o = o == Qt::Vertical ? Qt::Horizontal : Qt::Vertical; + } + + QDockWindow::setOrientation( o ); + + for (uint i = 0; i < m_toolBoxes.count(); ++i) { + ToolArea *t = m_toolBoxes.at(i); + t->setOrientation(o); + } +} + + +void KoToolBox::enableTools(bool enable) +{ + if (m_tools.isEmpty()) return; + if (!m_buttonGroup) return; + if (m_numberOfButtons <= 0) return; + + for (uint i = 0; i < m_tools.count(); ++i) { + ToolList * tl = m_tools.at(i); + + if (!tl) continue; + + ToolList::Iterator it; + for ( it = tl->begin(); it != tl->end(); ++it ) + if (it != 0 && it.data()) + it.data()->setEnabled(enable); + } + m_buttonGroup->setEnabled(enable); + for (Q_UINT32 i = 0; i < m_numberOfButtons; ++i) { + m_buttonGroup->find( i )->setEnabled( enable ); + } +} + +void KoToolBox::slotSetTool(const QString & toolname) +{ + for (uint i = 0; i < m_idToActionMap.count(); ++i) { + KAction * a = m_idToActionMap.at(i); + if (!a || a->name() != toolname) continue; + + m_buttonGroup->setButton(i); + return; + + } +} + + +// ---------------------------------------------------------------- +// class ToolArea + + +ToolArea::ToolArea(QWidget *parent) + : QWidget(parent), m_left(true) +{ + m_layout = new QBoxLayout(this, QBoxLayout::LeftToRight, 0, 0, 0); + QWidget *w = new QWidget(this); + m_layout->addWidget(w); + + QGridLayout *grid = new QGridLayout(w, 2, 2); + m_leftRow = new QWidget(w); + grid->addWidget(m_leftRow, 0, 0); + m_leftLayout = new QBoxLayout(m_leftRow, QBoxLayout::TopToBottom, 0, 1, 0); + + w = new QWidget(this); + m_layout->addWidget(w); + + grid = new QGridLayout(w, 2, 2); + m_rightRow = new QWidget(w); + grid->addWidget(m_rightRow, 0, 0); + m_rightLayout = new QBoxLayout(m_rightRow, QBoxLayout::TopToBottom, 0, 1, 0); +} + + +ToolArea::~ToolArea() +{ +} + + +void ToolArea::add(QWidget *button) +{ + if (m_left) + m_leftLayout->addWidget(button); + else + m_rightLayout->addWidget(button); + button->show(); + m_left = !m_left; +} + + +QWidget* ToolArea::getNextParent() +{ + if (m_left) + return m_leftRow; + return m_rightRow; +} + + +void ToolArea::setOrientation ( Qt::Orientation o ) +{ + QBoxLayout::Direction dir = (o != Qt::Horizontal + ? QBoxLayout::TopToBottom + : QBoxLayout::LeftToRight); + m_leftLayout->setDirection(dir); + m_rightLayout->setDirection(dir); + + m_layout->setDirection(o == Qt::Horizontal + ? QBoxLayout::TopToBottom + : QBoxLayout::LeftToRight); +} + + +#include "KoToolBox.moc" diff --git a/lib/kofficeui/KoToolBox.h b/lib/kofficeui/KoToolBox.h new file mode 100644 index 00000000..81e1c751 --- /dev/null +++ b/lib/kofficeui/KoToolBox.h @@ -0,0 +1,119 @@ +/* + Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.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. + */ +#ifndef _KO_TOOLBOX_H_ +#define _KO_TOOLBOX_H_ + +#include <qtoolbutton.h> +#include <qptrvector.h> +#include <qtoolbar.h> +#include <koffice_export.h> +#include <ktoolbar.h> + +class QWidget; +class KAction; +class KMainWindow; +class KDualColorButton; +class QGridLayout; +class ToolArea; + + +/** + * KActionBox is a kind of super-specialized toolbox that can order + * tools according to type and priority. + * + * This is to a large extent a port of the Karbon vtoolbox -- with + * which it should be merged one day. However, it doesn't depend on a + * tool-like class, it aggregates actions. + */ + +class KOFFICEUI_EXPORT KoToolBox : public KToolBar { + + Q_OBJECT + +public: + + KoToolBox( KMainWindow *mainWin, const char* name, KInstance* instance, int numberOfTooltypes); + virtual ~KoToolBox(); + + // Called by the toolcontroller for each tool. For every category, + // there is a separate list, and the tool is categorized correctly. + // The tool is not yet added to the widgets; call setupTools() + // to do that. We don't store the tool. + void registerTool(KAction * tool, int toolType, Q_UINT32 priority); + + // Called when all tools have been added by the tool controller + void setupTools(); + +public slots: + + virtual void setOrientation ( Orientation o ); + void slotButtonPressed( int id ); + void slotPressButton( int id ); + + // Enables or disables all buttons and the corresponding actions. + void enableTools(bool enable); + + void slotSetTool(const QString & toolname); + +private: + + QToolButton * createButton(QWidget * parent, const char* iconName, QString tooltip); + + +private: + Q_UINT32 m_numberOfButtons; + + QButtonGroup * m_buttonGroup; // The invisible group of all toolbuttons, so only one can be active at a given time + + QPtrList<ToolArea> m_toolBoxes; // For every ToolArea + + typedef QMap< int, KAction*> ToolList; // The priority ordered list of tools for a certain tooltype + + QPtrList<ToolList> m_tools; + QPtrList<KAction> m_idToActionMap; // Map the buttongroup id's to actions for easy activating. + KInstance* m_instance; +}; + + +class ToolArea : public QWidget { + +public: + ToolArea(QWidget *parent); + ~ToolArea(); + + void setOrientation ( Qt::Orientation o ); + void add(QWidget *button); + + QWidget* getNextParent(); + +private: + QPtrList<QWidget> m_children; + QBoxLayout *m_layout; + + QWidget *m_leftRow; + QBoxLayout *m_leftLayout; + + QWidget *m_rightRow; + QBoxLayout *m_rightLayout; + + bool m_left; +}; + + +#endif // _KO_TOOLBOX_H_ diff --git a/lib/kofficeui/KoTooluButton.cpp b/lib/kofficeui/KoTooluButton.cpp new file mode 100644 index 00000000..c5e893d5 --- /dev/null +++ b/lib/kofficeui/KoTooluButton.cpp @@ -0,0 +1,858 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Werner Trobin <trobin@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 <qapplication.h> +#include <qtooltip.h> +#include <qpainter.h> +#include <qdrawutil.h> +#include <qpixmap.h> +#include <qstyle.h> +#include <qpopupmenu.h> + +#include <kglobalsettings.h> +#include <ktoolbar.h> +#include <KoTooluButton.h> +#include <kcolordrag.h> +#include <klocale.h> +#include <kcolordialog.h> +#include <kdebug.h> + +namespace { + // For the KoColorPanel + const int COLS = 15; + const int TILESIZE = 16; + // For the KoToolButton + int ARROW_WIDTH = 12; +} + +KoColorPanel::KoColorPanel( QWidget* parent, const char* name ) : + QWidget( parent, name, WStaticContents | WRepaintNoErase | WResizeNoErase ) +{ + setMouseTracking( true ); + setAcceptDrops( true ); + init(); +} + +KoColorPanel::~KoColorPanel() +{ +} + +QSize KoColorPanel::sizeHint() const +{ + return minimumSizeHint(); +} + +QSize KoColorPanel::minimumSizeHint() const +{ + return QSize( COLS << 4, lines() << 4 ); +} + +QPopupMenu* KoColorPanel::createColorPopup( KoColorPanel::MenuStyle style, const QColor& defaultColor, + const QObject* receiver, const char* slot, + QWidget* parent, const char* name ) +{ + QPopupMenu* menu = new QPopupMenu( parent, name ); + KoColorPopupProxy* proxy = 0; + + if ( defaultColor.isValid() ) { + QPixmap pixmap( 12, 12 ); + QPainter p( &pixmap ); + p.fillRect( 0, 0, 12, 12, defaultColor ); + p.end(); + proxy = new KoColorPopupProxy( defaultColor, 0, menu, "color proxy" ); + connect( proxy, SIGNAL( colorSelected( const QColor& ) ), receiver, slot ); + menu->insertItem( QIconSet( pixmap ), i18n( "Default Color" ), proxy, SLOT( slotDefaultColor() ) ); + menu->insertSeparator(); + } + + KoColorPanel* panel = new KoColorPanel( menu, "default colors" ); + panel->insertDefaultColors(); + connect( panel, SIGNAL( colorSelected( const QColor& ) ), receiver, slot ); + menu->insertItem( panel ); + + if ( style == CustomColors ) { + menu->insertSeparator(); + panel = new KoColorPanel( menu, "custom panel" ); + connect( panel, SIGNAL( colorSelected( const QColor& ) ), receiver, slot ); + menu->insertItem( panel ); + if ( !proxy ) { + proxy = new KoColorPopupProxy( QColor(), panel, menu, "color proxy" ); + connect( proxy, SIGNAL( colorSelected( const QColor& ) ), receiver, slot ); + } + else + proxy->setRecentColorPanel( panel ); + menu->insertSeparator(); + menu->insertItem( i18n( "More Colors..." ), proxy, SLOT( slotMoreColors() ) ); + } + + return menu; +} + +void KoColorPanel::clear() +{ + if ( m_colorMap.isEmpty() ) + return; + + QSize area( minimumSizeHint() ); + m_colorMap.clear(); + init(); + updateGeometry(); + erase( 0, 0, area.width(), area.height() ); +} + +void KoColorPanel::insertColor( const QColor& color ) +{ + Position pos = m_nextPosition; + if ( insertColor( color, true ) ) // we want checking for external users + finalizeInsertion( pos ); +} + +void KoColorPanel::insertColor( const QColor& color, const QString& toolTip ) +{ + Position pos = m_nextPosition; + if ( insertColor( color, toolTip, true ) ) // we want checking for external users + finalizeInsertion( pos ); +} + +void KoColorPanel::insertDefaultColors() +{ + if ( m_defaultsAdded ) + return; + m_defaultsAdded = true; + + int currentRow = m_nextPosition.y; // we have to repaint this row below + + // Note: No checking for duplicates, so take care when you modify that list + insertColor(QColor( 255 , 0 , 0 ), i18n( "color", "Red" ), false); + insertColor(QColor( 255 , 165 , 0 ), i18n( "color", "Orange" ), false); + insertColor(QColor( 255 , 0 , 255 ), i18n( "color", "Magenta" ), false); + insertColor(QColor( 0 , 0 , 255 ), i18n( "color", "Blue" ), false); + insertColor(QColor( 0 , 255 , 255 ), i18n( "color", "Cyan" ), false); + insertColor(QColor( 0 , 255 , 0 ), i18n( "color", "Green" ), false); + insertColor(QColor( 255 , 255 , 0 ), i18n( "color", "Yellow" ), false); + insertColor(QColor( 165 , 42 , 42 ), i18n( "color", "Brown" ), false); + insertColor(QColor( 139 , 0 , 0 ), i18n( "color", "DarkRed" ), false); + insertColor(QColor( 255 , 140 , 0 ), i18n( "color", "DarkOrange" ), false); + insertColor(QColor( 139 , 0 , 139 ), i18n( "color", "DarkMagenta" ), false); + insertColor(QColor( 0 , 0 , 139 ), i18n( "color", "DarkBlue" ), false); + insertColor(QColor( 0 , 139 , 139 ), i18n( "color", "DarkCyan" ), false); + insertColor(QColor( 0 , 100 , 0 ), i18n( "color", "DarkGreen" ), false); + insertColor(QColor( 130 , 127 , 0 ), i18n( "color", "DarkYellow" ), false); + insertColor(QColor( 255 , 255 , 255 ), i18n( "color", "White" ), false); + // xgettext:no-c-format + insertColor(QColor( 229 , 229 , 229 ), i18n( "color", "Gray 90%" ), false); + // xgettext:no-c-format + insertColor(QColor( 204 , 204 , 204 ), i18n( "color", "Gray 80%" ), false); + // xgettext:no-c-format + insertColor(QColor( 178 , 178 , 178 ), i18n( "color", "Gray 70%" ), false); + // xgettext:no-c-format + insertColor(QColor( 153 , 153 , 153 ), i18n( "color", "Gray 60%" ), false); + // xgettext:no-c-format + insertColor(QColor( 127 , 127 , 127 ), i18n( "color", "Gray 50%" ), false); + // xgettext:no-c-format + insertColor(QColor( 102 , 102 , 102 ), i18n( "color", "Gray 40%" ), false); + // xgettext:no-c-format + insertColor(QColor( 76 , 76 , 76 ), i18n( "color", "Gray 30%" ), false); + // xgettext:no-c-format + insertColor(QColor( 51 , 51 , 51 ), i18n( "color", "Gray 20%" ), false); + // xgettext:no-c-format + insertColor(QColor( 25 , 25 , 25 ), i18n( "color", "Gray 10%" ), false); + insertColor(QColor( 0 , 0 , 0 ), i18n( "color", "Black" ), false); + insertColor(QColor( 255 , 255 , 240 ), i18n( "color", "Ivory" ), false); + insertColor(QColor( 255 , 250 , 250 ), i18n( "color", "Snow" ), false); + insertColor(QColor( 245 , 255 , 250 ), i18n( "color", "MintCream" ), false); + insertColor(QColor( 255 , 250 , 240 ), i18n( "color", "FloralWhite" ), false); + insertColor(QColor( 255 , 255 , 224 ), i18n( "color", "LightYellow" ), false); + insertColor(QColor( 240 , 255 , 255 ), i18n( "color", "Azure" ), false); + insertColor(QColor( 248 , 248 , 255 ), i18n( "color", "GhostWhite" ), false); + insertColor(QColor( 240 , 255 , 240 ), i18n( "color", "Honeydew" ), false); + insertColor(QColor( 255 , 245 , 238 ), i18n( "color", "Seashell" ), false); + insertColor(QColor( 240 , 248 , 255 ), i18n( "color", "AliceBlue" ), false); + insertColor(QColor( 255 , 248 , 220 ), i18n( "color", "Cornsilk" ), false); + insertColor(QColor( 255 , 240 , 245 ), i18n( "color", "LavenderBlush" ), false); + insertColor(QColor( 253 , 245 , 230 ), i18n( "color", "OldLace" ), false); + insertColor(QColor( 245 , 245 , 245 ), i18n( "color", "WhiteSmoke" ), false); + insertColor(QColor( 255 , 250 , 205 ), i18n( "color", "LemonChiffon" ), false); + insertColor(QColor( 224 , 255 , 255 ), i18n( "color", "LightCyan" ), false); + insertColor(QColor( 250 , 250 , 210 ), i18n( "color", "LightGoldenrodYellow" ), false); + insertColor(QColor( 250 , 240 , 230 ), i18n( "color", "Linen" ), false); + insertColor(QColor( 245 , 245 , 220 ), i18n( "color", "Beige" ), false); + insertColor(QColor( 255 , 239 , 213 ), i18n( "color", "PapayaWhip" ), false); + insertColor(QColor( 255 , 235 , 205 ), i18n( "color", "BlanchedAlmond" ), false); + insertColor(QColor( 250 , 235 , 215 ), i18n( "color", "AntiqueWhite" ), false); + insertColor(QColor( 255 , 228 , 225 ), i18n( "color", "MistyRose" ), false); + insertColor(QColor( 230 , 230 , 250 ), i18n( "color", "Lavender" ), false); + insertColor(QColor( 255 , 228 , 196 ), i18n( "color", "Bisque" ), false); + insertColor(QColor( 255 , 228 , 181 ), i18n( "color", "Moccasin" ), false); + insertColor(QColor( 255 , 222 , 173 ), i18n( "color", "NavajoWhite" ), false); + insertColor(QColor( 255 , 218 , 185 ), i18n( "color", "PeachPuff" ), false); + insertColor(QColor( 238 , 232 , 170 ), i18n( "color", "PaleGoldenrod" ), false); + insertColor(QColor( 245 , 222 , 179 ), i18n( "color", "Wheat" ), false); + insertColor(QColor( 220 , 220 , 220 ), i18n( "color", "Gainsboro" ), false); + insertColor(QColor( 240 , 230 , 140 ), i18n( "color", "Khaki" ), false); + insertColor(QColor( 175 , 238 , 238 ), i18n( "color", "PaleTurquoise" ), false); + insertColor(QColor( 255 , 192 , 203 ), i18n( "color", "Pink" ), false); + insertColor(QColor( 238 , 221 , 130 ), i18n( "color", "LightGoldenrod" ), false); + insertColor(QColor( 211 , 211 , 211 ), i18n( "color", "LightGray" ), false); + insertColor(QColor( 255 , 182 , 193 ), i18n( "color", "LightPink" ), false); + insertColor(QColor( 176 , 224 , 230 ), i18n( "color", "PowderBlue" ), false); + insertColor(QColor( 127 , 255 , 212 ), i18n( "color", "Aquamarine" ), false); + insertColor(QColor( 216 , 191 , 216 ), i18n( "color", "Thistle" ), false); + insertColor(QColor( 173 , 216 , 230 ), i18n( "color", "LightBlue" ), false); + insertColor(QColor( 152 , 251 , 152 ), i18n( "color", "PaleGreen" ), false); + insertColor(QColor( 255 , 215 , 0 ), i18n( "color", "Gold" ), false); + insertColor(QColor( 173 , 255 , 47 ), i18n( "color", "GreenYellow" ), false); + insertColor(QColor( 176 , 196 , 222 ), i18n( "color", "LightSteelBlue" ), false); + insertColor(QColor( 144 , 238 , 144 ), i18n( "color", "LightGreen" ), false); + insertColor(QColor( 221 , 160 , 221 ), i18n( "color", "Plum" ), false); + insertColor(QColor( 190 , 190 , 190 ), i18n( "color", "Gray" ), false); + insertColor(QColor( 222 , 184 , 135 ), i18n( "color", "BurlyWood" ), false); + insertColor(QColor( 135 , 206 , 250 ), i18n( "color", "LightSkyBlue" ), false); + insertColor(QColor( 255 , 160 , 122 ), i18n( "color", "LightSalmon" ), false); + insertColor(QColor( 135 , 206 , 235 ), i18n( "color", "SkyBlue" ), false); + insertColor(QColor( 210 , 180 , 140 ), i18n( "color", "Tan" ), false); + insertColor(QColor( 238 , 130 , 238 ), i18n( "color", "Violet" ), false); + insertColor(QColor( 244 , 164 , 96 ), i18n( "color", "SandyBrown" ), false); + insertColor(QColor( 233 , 150 , 122 ), i18n( "color", "DarkSalmon" ), false); + insertColor(QColor( 189 , 183 , 107 ), i18n( "color", "DarkKhaki" ), false); + insertColor(QColor( 127 , 255 , 0 ), i18n( "color", "Chartreuse" ), false); + insertColor(QColor( 169 , 169 , 169 ), i18n( "color", "DarkGray" ), false); + insertColor(QColor( 124 , 252 , 0 ), i18n( "color", "LawnGreen" ), false); + insertColor(QColor( 255 , 105 , 180 ), i18n( "color", "HotPink" ), false); + insertColor(QColor( 250 , 128 , 114 ), i18n( "color", "Salmon" ), false); + insertColor(QColor( 240 , 128 , 128 ), i18n( "color", "LightCoral" ), false); + insertColor(QColor( 64 , 224 , 208 ), i18n( "color", "Turquoise" ), false); + insertColor(QColor( 143 , 188 , 143 ), i18n( "color", "DarkSeaGreen" ), false); + insertColor(QColor( 218 , 112 , 214 ), i18n( "color", "Orchid" ), false); + insertColor(QColor( 102 , 205 , 170 ), i18n( "color", "MediumAquamarine" ), false); + insertColor(QColor( 255 , 127 , 80 ), i18n( "color", "Coral" ), false); + insertColor(QColor( 154 , 205 , 50 ), i18n( "color", "YellowGreen" ), false); + insertColor(QColor( 218 , 165 , 32 ), i18n( "color", "Goldenrod" ), false); + insertColor(QColor( 72 , 209 , 204 ), i18n( "color", "MediumTurquoise" ), false); + insertColor(QColor( 188 , 143 , 143 ), i18n( "color", "RosyBrown" ), false); + insertColor(QColor( 219 , 112 , 147 ), i18n( "color", "PaleVioletRed" ), false); + insertColor(QColor( 0 , 250 , 154 ), i18n( "color", "MediumSpringGreen" ), false); + insertColor(QColor( 255 , 99 , 71 ), i18n( "color", "Tomato" ), false); + insertColor(QColor( 0 , 255 , 127 ), i18n( "color", "SpringGreen" ), false); + insertColor(QColor( 205 , 133 , 63 ), i18n( "color", "Peru" ), false); + insertColor(QColor( 100 , 149 , 237 ), i18n( "color", "CornflowerBlue" ), false); + insertColor(QColor( 132 , 112 , 255 ), i18n( "color", "LightSlateBlue" ), false); + insertColor(QColor( 147 , 112 , 219 ), i18n( "color", "MediumPurple" ), false); + insertColor(QColor( 186 , 85 , 211 ), i18n( "color", "MediumOrchid" ), false); + insertColor(QColor( 95 , 158 , 160 ), i18n( "color", "CadetBlue" ), false); + insertColor(QColor( 0 , 206 , 209 ), i18n( "color", "DarkTurquoise" ), false); + insertColor(QColor( 0 , 191 , 255 ), i18n( "color", "DeepSkyBlue" ), false); + insertColor(QColor( 119 , 136 , 153 ), i18n( "color", "LightSlateGray" ), false); + insertColor(QColor( 184 , 134 , 11 ), i18n( "color", "DarkGoldenrod" ), false); + insertColor(QColor( 123 , 104 , 238 ), i18n( "color", "MediumSlateBlue" ), false); + insertColor(QColor( 205 , 92 , 92 ), i18n( "color", "IndianRed" ), false); + insertColor(QColor( 210 , 105 , 30 ), i18n( "color", "Chocolate" ), false); + insertColor(QColor( 60 , 179 , 113 ), i18n( "color", "MediumSeaGreen" ), false); + insertColor(QColor( 50 , 205 , 50 ), i18n( "color", "LimeGreen" ), false); + insertColor(QColor( 32 , 178 , 170 ), i18n( "color", "LightSeaGreen" ), false); + insertColor(QColor( 112 , 128 , 144 ), i18n( "color", "SlateGray" ), false); + insertColor(QColor( 30 , 144 , 255 ), i18n( "color", "DodgerBlue" ), false); + insertColor(QColor( 255 , 69 , 0 ), i18n( "color", "OrangeRed" ), false); + insertColor(QColor( 255 , 20 , 147 ), i18n( "color", "DeepPink" ), false); + insertColor(QColor( 70 , 130 , 180 ), i18n( "color", "SteelBlue" ), false); + insertColor(QColor( 106 , 90 , 205 ), i18n( "color", "SlateBlue" ), false); + insertColor(QColor( 107 , 142 , 35 ), i18n( "color", "OliveDrab" ), false); + insertColor(QColor( 65 , 105 , 225 ), i18n( "color", "RoyalBlue" ), false); + insertColor(QColor( 208 , 32 , 144 ), i18n( "color", "VioletRed" ), false); + insertColor(QColor( 153 , 50 , 204 ), i18n( "color", "DarkOrchid" ), false); + insertColor(QColor( 160 , 32 , 240 ), i18n( "color", "Purple" ), false); + insertColor(QColor( 105 , 105 , 105 ), i18n( "color", "DimGray" ), false); + insertColor(QColor( 138 , 43 , 226 ), i18n( "color", "BlueViolet" ), false); + insertColor(QColor( 160 , 82 , 45 ), i18n( "color", "Sienna" ), false); + insertColor(QColor( 199 , 21 , 133 ), i18n( "color", "MediumVioletRed" ), false); + insertColor(QColor( 176 , 48 , 96 ), i18n( "color", "Maroon" ), false); + insertColor(QColor( 46 , 139 , 87 ), i18n( "color", "SeaGreen" ), false); + insertColor(QColor( 85 , 107 , 47 ), i18n( "color", "DarkOliveGreen" ), false); + insertColor(QColor( 34 , 139 , 34 ), i18n( "color", "ForestGreen" ), false); + insertColor(QColor( 139 , 69 , 19 ), i18n( "color", "SaddleBrown" ), false); + insertColor(QColor( 148 , 0 , 211 ), i18n( "color", "DarkViolet" ), false); + insertColor(QColor( 178 , 34 , 34 ), i18n( "color", "FireBrick" ), false); + insertColor(QColor( 72 , 61 , 139 ), i18n( "color", "DarkSlateBlue" ), false); + insertColor(QColor( 47 , 79 , 79 ), i18n( "color", "DarkSlateGray" ), false); + insertColor(QColor( 25 , 25 , 112 ), i18n( "color", "MidnightBlue" ), false); + insertColor(QColor( 0 , 0 , 205 ), i18n( "color", "MediumBlue" ), false); + insertColor(QColor( 0 , 0 , 128 ), i18n( "color", "Navy" ), false); + + finalizeInsertion( m_nextPosition ); // with a no-op paint() call as we repaint anyway + updateGeometry(); + // we have to repaint the "old" current row explicitly due + // to WStaticContents + update( 0, currentRow << 4, COLS << 4, 16 ); +} + +void KoColorPanel::mousePressEvent( QMouseEvent* e ) +{ + if ( e->button() == Qt::LeftButton ) + m_pressedPos = e->pos(); +} + +void KoColorPanel::mouseReleaseEvent( QMouseEvent* ) +{ + if ( isVisible() && parentWidget() && parentWidget()->inherits( "QPopupMenu" ) ) + parentWidget()->close(); + emit colorSelected( mapToColor( m_pressedPos ) ); +} + +void KoColorPanel::mouseMoveEvent( QMouseEvent* e ) +{ + if ( e->state() & Qt::LeftButton ) { + QPoint p = m_pressedPos - e->pos(); + if ( p.manhattanLength() > QApplication::startDragDistance() ) { + QColor color( mapToColor( m_pressedPos ) ); + if ( color.isValid() ) { + KColorDrag *drag = new KColorDrag( color, this, name() ); + drag->dragCopy(); + } + } + } + else + updateFocusPosition( mapToPosition( e->pos() ) ); +} + +void KoColorPanel::paintEvent( QPaintEvent* e ) +{ + int lns = lines(); + int startRow, endRow, startCol, endCol; + paintArea( e->rect(), startRow, endRow, startCol, endCol ); + + QPainter p( this ); + + // First clear all the areas we won't paint on later (only if the widget isn't erased) + if ( !e->erased() ) { + // vertical rects + int tmp = TILESIZE * lns; + if ( startCol == 0 ) + erase( 0, 0, 2, tmp ); + if ( endCol == COLS ) + erase( width() - 2, 0, 2, tmp ); + else + erase( ( endCol << 4 ) - 2, 0, 2, tmp ); + int i = startCol == 0 ? 1 : startCol; + for ( ; i < endCol; ++i ) + erase( ( i << 4 ) - 2, 0, 4, tmp ); + + // horizontal rects + tmp = TILESIZE * COLS; + if ( startRow == 0 ) + erase( 0, 0, tmp, 2 ); + if ( endRow == lns ) + erase( 0, height() - 2, tmp, 2 ); + else + erase( 0, ( endRow << 4 ) - 2, tmp, 2 ); + i = startRow == 0 ? 1 : startRow; + for ( ; i < endRow; ++i ) + erase( 0, ( i << 4 ) - 2, tmp, 4 ); + } + + // The "active" element (if there is one) + if ( hasFocus() && m_focusPosition.x != -1 && m_focusPosition.y != -1 && + mapFromPosition( m_focusPosition ).intersects( e->rect() ) ) + style().drawPrimitive( QStyle::PE_Panel, &p, QRect( m_focusPosition.x << 4, m_focusPosition.y << 4, TILESIZE, TILESIZE ), + colorGroup(), QStyle::Style_Sunken | QStyle::Style_Enabled ); + + --lns; // Attention: We just avoid some lns - 1 statements + + // ...all color tiles + if ( !m_colorMap.isEmpty() ) { + int currentRow = startRow, currentCol = startCol; + while ( currentRow < endRow && currentCol < endCol ) { + QMap<Position, QColor>::ConstIterator it = m_colorMap.find( Position( currentCol, currentRow ) ); + if( it != m_colorMap.end() ) + p.fillRect( ( currentCol << 4 ) + 2, ( currentRow << 4 ) + 2, 12, 12, it.data() ); + + // position of the next cell + ++currentCol; + if ( currentCol == endCol ) { + ++currentRow; + currentCol = startCol; + } + } + } + + // clean up the last line (it's most likely that it's not totally filled) + if ( !e->erased() && endRow > lns ) { + int fields = m_colorMap.count() % COLS; + erase( fields << 4, lns * TILESIZE, ( COLS - fields ) << 4, 16 ); + } +} + +void KoColorPanel::keyPressEvent( QKeyEvent* e ) +{ + Position newPos( validPosition( m_focusPosition ) ); + if ( e->key() == Qt::Key_Up ) { + if ( newPos.y == 0 ) + e->ignore(); + else + --newPos.y; + } + else if ( e->key() == Qt::Key_Down ) { + if ( newPos < Position( m_colorMap.count() % COLS, lines() - 2 ) ) + ++newPos.y; + else + e->ignore(); + } + else if ( e->key() == Qt::Key_Left ) { + if ( newPos.x == 0 ) + e->ignore(); + else + --newPos.x; + } + else if ( e->key() == Qt::Key_Right ) { + if ( newPos.x < COLS - 1 && newPos < Position( m_colorMap.count() % COLS - 1, lines() - 1 ) ) + ++newPos.x; + else + e->ignore(); + } + else if ( e->key() == Qt::Key_Return ) { + if ( isVisible() && parentWidget() && parentWidget()->inherits( "QPopupMenu" ) ) + parentWidget()->close(); + emit colorSelected( mapToColor( m_focusPosition ) ); + } + updateFocusPosition( newPos ); +} + +void KoColorPanel::focusInEvent( QFocusEvent* e ) +{ + if ( !m_colorMap.isEmpty() && m_focusPosition.x == -1 && m_focusPosition.y == -1 ) { + m_focusPosition.x = 0; + m_focusPosition.y = 0; + } + QWidget::focusInEvent( e ); +} + +void KoColorPanel::dragEnterEvent( QDragEnterEvent* e ) +{ + e->accept( KColorDrag::canDecode( e ) ); +} + +void KoColorPanel::dropEvent( QDropEvent* e ) +{ + QColor color; + if ( KColorDrag::decode( e, color ) ) + insertColor( color ); +} + +void KoColorPanel::finalizeInsertion( const Position& pos ) +{ + paint( pos ); + + if ( !isFocusEnabled() ) + setFocusPolicy( QWidget::StrongFocus ); + // Did we start a new row? + if ( m_nextPosition.x == 1 ) + updateGeometry(); +} + +bool KoColorPanel::insertColor( const QColor& color, bool checking ) +{ + if ( checking && isAvailable( color ) ) + return false; + + m_colorMap.insert( m_nextPosition, color ); + + ++m_nextPosition.x; + if ( m_nextPosition.x == COLS ) { + m_nextPosition.x = 0; + ++m_nextPosition.y; + } + return true; +} + +bool KoColorPanel::insertColor( const QColor& color, const QString& toolTip, bool checking ) +{ + if ( checking && isAvailable( color ) ) + return false; + + // Remember the "old" m_nextPosition -- this is the place where the newly + // inserted color will be located + QRect rect( mapFromPosition( m_nextPosition ) ); + insertColor( color, false ); // check only once ;) + QToolTip::add( this, rect, toolTip ); + return true; +} + +bool KoColorPanel::isAvailable( const QColor& color ) +{ + // O(n) checking on insert, but this is better than O(n) checking + // on every mouse move... + QMap<Position, QColor>::ConstIterator it = m_colorMap.begin(); + QMap<Position, QColor>::ConstIterator end = m_colorMap.end(); + for ( ; it != end; ++it ) + if ( it.data() == color ) + return true; + return false; +} + +KoColorPanel::Position KoColorPanel::mapToPosition( const QPoint& point ) const +{ + return Position( point.x() >> 4, point.y() >> 4 ); +} + +QColor KoColorPanel::mapToColor( const QPoint& point ) const +{ + return mapToColor( mapToPosition( point ) ); +} + +QColor KoColorPanel::mapToColor( const KoColorPanel::Position& position ) const +{ + QMap<Position, QColor>::ConstIterator it = m_colorMap.find( position ); + if ( it != m_colorMap.end() ) + return it.data(); + return QColor(); +} + +QRect KoColorPanel::mapFromPosition( const KoColorPanel::Position& position ) const +{ + return QRect( position.x << 4, position.y << 4, TILESIZE, TILESIZE ); +} + +KoColorPanel::Position KoColorPanel::validPosition( const Position& position ) +{ + Position pos( position ); + int lns = lines() - 1; + int lastLineLen = m_colorMap.count() % COLS - 1; + + // ensure the position is within the valid grid area + // note: special handling of the last line + if ( pos.x < 0 ) + pos.x = 0; + else if ( pos.y == lns && pos.x > lastLineLen ) + pos.x = lastLineLen; + else if ( pos.x >= COLS ) + pos.x = COLS - 1; + + if ( pos.y < 0 ) + pos.y = 0; + else if ( pos.x > lastLineLen && pos.y > lns - 1 ) + pos.y = lns - 1; + else if ( pos.y > lns ) + pos.y = lns; + return pos; +} + +int KoColorPanel::lines() const +{ + if ( m_colorMap.isEmpty() ) + return 1; + return ( m_colorMap.count() - 1 ) / COLS + 1; +} + +void KoColorPanel::paintArea( const QRect& rect, int& startRow, int& endRow, int& startCol, int& endCol ) const +{ + startRow = rect.top() >> 4; + endRow = ( rect.bottom() >> 4 ) + 1; + startCol = rect.left() >> 4; + endCol = ( rect.right() >> 4 ) + 1; +} + +void KoColorPanel::updateFocusPosition( const Position& newPosition ) +{ + QPainter p( this ); + + // restore the old tile where we had the focus before + if ( m_focusPosition.x != -1 && m_focusPosition.y != -1 ) + paint( m_focusPosition ); + + m_focusPosition = newPosition; + + QMap<Position, QColor>::ConstIterator it = m_colorMap.find( m_focusPosition ); + if ( it != m_colorMap.end() ) { + // draw at the new focus position + style().drawPrimitive( QStyle::PE_Panel, &p, QRect( m_focusPosition.x << 4, m_focusPosition.y << 4, TILESIZE, TILESIZE ), + colorGroup(), QStyle::Style_Sunken | QStyle::Style_Enabled ); + p.fillRect( ( m_focusPosition.x << 4 ) + 2, ( m_focusPosition.y << 4 ) + 2, 12, 12, it.data() ); + } + +} + +void KoColorPanel::paint( const Position& position ) +{ + QMap<Position, QColor>::ConstIterator it = m_colorMap.find( position ); + if ( it == m_colorMap.end() ) + return; + + erase( mapFromPosition( position ) ); + QPainter p( this ); + p.fillRect( ( position.x << 4 ) + 2, ( position.y << 4 ) + 2, 12, 12, it.data() ); +} + +void KoColorPanel::init() +{ + setFocusPolicy( QWidget::NoFocus ); // it's empty + m_nextPosition.x = 0; + m_nextPosition.y = 0; + m_focusPosition.x = -1; + m_focusPosition.y = -1; + m_defaultsAdded = false; +} + +bool operator<( const KoColorPanel::Position& lhs, const KoColorPanel::Position& rhs ) +{ + return ( lhs.y * COLS + lhs.x ) < ( rhs.y * COLS + rhs.x ); +} + + +KoColorPopupProxy::KoColorPopupProxy( const QColor& defaultColor, KoColorPanel* recentColors, QObject* parent, const char* name ) : + QObject( parent, name ), m_defaultColor( defaultColor ), m_recentColors( recentColors ) +{ +} + +void KoColorPopupProxy::setRecentColorPanel( KoColorPanel* recentColors ) +{ + m_recentColors = recentColors; +} + +void KoColorPopupProxy::slotDefaultColor() +{ + emit colorSelected( m_defaultColor ); +} + +void KoColorPopupProxy::slotMoreColors() +{ + if ( !m_recentColors ) + return; + + QColor newColor; + QWidget* p = 0; + if ( parent() && parent()->isWidgetType() ) + p = static_cast<QWidget*>( parent() ); + + if ( KColorDialog::getColor( newColor, p ) == QDialog::Accepted ) { + m_recentColors->insertColor( newColor ); + emit colorSelected( newColor ); + } +} + + +KoToolButton::KoToolButton( const QString& icon, int id, QWidget* parent, + const char* name, const QString& txt, KInstance* _instance ) : + KToolBarButton( icon, id, parent, name, txt, _instance ), m_arrowPressed( false ) +{ + init(); +} + +KoToolButton::KoToolButton( const QPixmap& pixmap, int id, QWidget* parent, + const char* name, const QString& txt ) : + KToolBarButton( pixmap, id, parent, name, txt ), m_arrowPressed( false ) +{ + init(); +} + +KoToolButton::~KoToolButton() +{ +} + +QSize KoToolButton::sizeHint() const +{ + return minimumSizeHint(); +} + +QSize KoToolButton::minimumSizeHint() const +{ + QSize size = KToolBarButton::minimumSizeHint(); + size.setWidth( size.width() + ARROW_WIDTH ); + return size; +} + +QSize KoToolButton::minimumSize() const +{ + return minimumSizeHint(); +} + +void KoToolButton::colorSelected( const QColor& color ) +{ + kdDebug() << "selected::: " << color.name() << endl; +} + +void KoToolButton::drawButton(QPainter *_painter) +{ + QStyle::SFlags flags = QStyle::Style_Default; + QStyle::SCFlags active = QStyle::SC_None; + QStyle::SCFlags arrowActive = QStyle::SC_None; + QStyleOption opt; + QColorGroup cg( colorGroup() ); + + if ( isEnabled() ) { + flags |= QStyle::Style_Enabled; + if ( KToolBarButton::isRaised() || m_arrowPressed ) + flags |= QStyle::Style_Raised; + } + if ( isOn() ) + flags |= QStyle::Style_On; + + QStyle::SFlags arrowFlags = flags; + + if ( isDown() && !m_arrowPressed ) { + flags |= QStyle::Style_Down; + active |= QStyle::SC_ToolButton; + } + if ( m_arrowPressed ) + arrowActive |= QStyle::SC_ToolButton; + + // Draw styled toolbuttons + _painter->setClipRect( 0, 0, width() - ARROW_WIDTH, height() ); + style().drawComplexControl( QStyle::CC_ToolButton, _painter, this, QRect( 0, 0, width() - ARROW_WIDTH, height() ), cg, + flags, QStyle::SC_ToolButton, active, opt ); + _painter->setClipRect( width() - ARROW_WIDTH, 0, ARROW_WIDTH, height() ); + style().drawComplexControl( QStyle::CC_ToolButton, _painter, this, QRect( width(), 0, ARROW_WIDTH, height() ), cg, + arrowFlags, QStyle::SC_ToolButton, arrowActive, opt ); + _painter->setClipping( false ); + + // ...and the arrow indicating the popup + style().drawPrimitive( QStyle::PE_ArrowDown, _painter, QRect( width() - ARROW_WIDTH - 1, 0, ARROW_WIDTH, height() ), + cg, flags, opt ); + + if ( KToolBarButton::isRaised() || m_arrowPressed ) + qDrawShadeLine( _painter, width() - ARROW_WIDTH - 1, 0, width() - ARROW_WIDTH - 1, height() - 1, colorGroup(), true ); + + int dx, dy; + QFont tmp_font( KGlobalSettings::toolBarFont() ); + QFontMetrics fm( tmp_font ); + QRect textRect; + int textFlags = 0; + + if ( static_cast<KToolBar::IconText>( iconTextMode() ) == KToolBar::IconOnly ) { // icon only + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? ( KToolBarButton::isActive() ? QIconSet::Active : QIconSet::Normal ) : + QIconSet::Disabled, isOn() ? QIconSet::On : QIconSet::Off ); + if ( !pixmap.isNull() ) { + dx = ( width() - ARROW_WIDTH - pixmap.width() ) / 2; + dy = ( height() - pixmap.height() ) / 2; + buttonShift( dx, dy ); + _painter->drawPixmap( dx, dy, pixmap ); + } + } + else if ( static_cast<KToolBar::IconText>( iconTextMode() ) == KToolBar::IconTextRight ) { // icon and text (if any) + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? ( KToolBarButton::isActive() ? QIconSet::Active : QIconSet::Normal ) : + QIconSet::Disabled, isOn() ? QIconSet::On : QIconSet::Off ); + if( !pixmap.isNull()) { + dx = 4; + dy = ( height() - pixmap.height() ) / 2; + buttonShift( 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; + buttonShift( dx, dy ); + textRect = QRect( dx, dy, width() - dx, height() ); + } + } + else if ( static_cast<KToolBar::IconText>( iconTextMode() ) == KToolBar::TextOnly ) { + if ( !textLabel().isNull() ) { + textFlags = AlignTop | AlignLeft; + dx = ( width() - ARROW_WIDTH - fm.width( textLabel() ) ) / 2; + dy = ( height() - fm.lineSpacing() ) / 2; + buttonShift( dx, dy ); + textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() ); + } + } + else if ( static_cast<KToolBar::IconText>( iconTextMode() ) == KToolBar::IconTextBottom ) { + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? ( KToolBarButton::isActive() ? QIconSet::Active : QIconSet::Normal ) : + QIconSet::Disabled, isOn() ? QIconSet::On : QIconSet::Off ); + if( !pixmap.isNull()) { + dx = ( width() - ARROW_WIDTH - pixmap.width() ) / 2; + dy = ( height() - fm.lineSpacing() - pixmap.height() ) / 2; + buttonShift( dx, dy ); + _painter->drawPixmap( dx, dy, pixmap ); + } + + if ( !textLabel().isNull() ) { + textFlags = AlignBottom | AlignHCenter; + dx = ( width() - ARROW_WIDTH - fm.width( textLabel() ) ) / 2; + dy = height() - fm.lineSpacing() - 4; + buttonShift( 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( KToolBarButton::isRaised() ) + _painter->setPen( KGlobalSettings::toolBarHighlightColor() ); + else + _painter->setPen( colorGroup().buttonText() ); + _painter->drawText( textRect, textFlags, textLabel() ); + } +} + +bool KoToolButton::eventFilter( QObject* o, QEvent* e ) +{ + if ( o == m_popup ) { + if ( e->type() == QEvent::MouseButtonPress ) + if ( hitArrow( mapFromGlobal( static_cast<QMouseEvent*>( e )->globalPos() ) ) ) { + kdDebug() << "KoToolButton::eventFilter-------------->" << endl; + m_popup->close(); + m_arrowPressed = false; + return true; + } + return false; + } + + if ( e->type() == QEvent::MouseButtonPress ) { + m_arrowPressed = hitArrow( static_cast<QMouseEvent*>( e )->pos() ); + if ( m_arrowPressed ) + m_popup->popup( mapToGlobal( QPoint( 0, height() ) ) ); + } + else if ( e->type() == QEvent::MouseButtonRelease ) + m_arrowPressed = false; + return KToolBarButton::eventFilter( o, e ); +} + +void KoToolButton::init() +{ + m_popup = KoColorPanel::createColorPopup( KoColorPanel::CustomColors, Qt::yellow, this, + SLOT( colorSelected( const QColor& ) ), + this, "no-name" ); + // We are interested in the mouse clicks on the arrow button + m_popup->installEventFilter( this ); + + ARROW_WIDTH = style().pixelMetric(QStyle::PM_MenuButtonIndicator) + 4; + kdDebug() << "##################### Arrow: " << ARROW_WIDTH << endl; +} + +void KoToolButton::buttonShift( int& dx, int& dy ) +{ + if ( isDown() && !m_arrowPressed ) { + dx += style().pixelMetric( QStyle::PM_ButtonShiftHorizontal ); + dy += style().pixelMetric( QStyle::PM_ButtonShiftVertical ); + } +} + +bool KoToolButton::hitArrow( const QPoint& pos ) +{ + return QRect( width() - ARROW_WIDTH, 0, ARROW_WIDTH, height() ).contains( pos ); +} + +#include <KoTooluButton.moc> diff --git a/lib/kofficeui/KoTooluButton.h b/lib/kofficeui/KoTooluButton.h new file mode 100644 index 00000000..b933eeee --- /dev/null +++ b/lib/kofficeui/KoTooluButton.h @@ -0,0 +1,183 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Werner Trobin <trobin@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. +*/ + +#ifndef _kotoolbutton_h_ +#define _kotoolbutton_h_ + +#include <ktoolbarbutton.h> +#include <qmap.h> +#include <qpoint.h> + +class QPopupMenu; + +class KoColorPanel : public QWidget +{ + Q_OBJECT +public: + KoColorPanel( QWidget* parent = 0, const char* name = 0 ); + virtual ~KoColorPanel(); + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + + enum MenuStyle { Plain, CustomColors }; + static QPopupMenu* createColorPopup( MenuStyle style, const QColor& defaultColor, + const QObject* receiver, const char* slot, + QWidget* parent, const char* name ); + +public slots: + void clear(); + void insertColor( const QColor& color ); + void insertColor( const QColor& color, const QString& toolTip ); + void insertDefaultColors(); + +signals: + void colorSelected( const QColor& color ); + +protected: + virtual void mousePressEvent( QMouseEvent* e ); + virtual void mouseReleaseEvent( QMouseEvent* e ); + virtual void mouseMoveEvent( QMouseEvent* e ); + virtual void paintEvent( QPaintEvent* e ); + virtual void keyPressEvent( QKeyEvent* e ); + virtual void focusInEvent( QFocusEvent* e ); + virtual void dragEnterEvent( QDragEnterEvent* e ); + virtual void dropEvent( QDropEvent* e ); + +private: + // The position of the 16x16 tiles in "tile steps" + struct Position { + Position() : x( -1 ), y( -1 ) {} + Position( short x_, short y_ ) : x( x_ ), y( y_ ) {} + + short x; + short y; + }; + friend bool operator<( const KoColorPanel::Position& lhs, const KoColorPanel::Position& rhs ); + + void finalizeInsertion( const Position& pos ); + bool insertColor( const QColor& color, bool checking ); + bool insertColor( const QColor& color, const QString& toolTip, bool checking ); + bool isAvailable( const QColor& color ); + + Position mapToPosition( const QPoint& point ) const; + QColor mapToColor( const QPoint& point ) const; + QColor mapToColor( const Position& position ) const; + QRect mapFromPosition( const Position& position ) const; + Position validPosition( const Position& position ); + + int lines() const; + void paintArea( const QRect& rect, int& startRow, int& endRow, int& startCol, int& endCol ) const; + void updateFocusPosition( const Position& newPosition ); + void paint( const Position& position ); + void init(); + + Position m_nextPosition, m_focusPosition; + QMap<Position, QColor> m_colorMap; + QPoint m_pressedPos; + bool m_defaultsAdded; +}; + +// Needed for the use of KoColorPanel::Position in QMap +bool operator<( const KoColorPanel::Position& lhs, const KoColorPanel::Position& rhs ); + + +// A tiny class needed to emit the correct signal when the default +// color item in the color-panel popup is activated. Additionally +// it's used to provide the color select dialog and manages the recent +// colors... hacky +class KoColorPopupProxy : public QObject +{ + Q_OBJECT +public: + KoColorPopupProxy( const QColor& defaultColor, KoColorPanel* recentColors, QObject* parent, const char* name ); + virtual ~KoColorPopupProxy() {} + + void setRecentColorPanel( KoColorPanel* recentColors ); + +public slots: + void slotDefaultColor(); + void slotMoreColors(); + +signals: + void colorSelected( const QColor& color ); + +private: + QColor m_defaultColor; + KoColorPanel* m_recentColors; +}; + + +// Parts of the code are from KToolBarButton +class KoToolButton : public KToolBarButton +{ + 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) + */ + KoToolButton( const QString& icon, int id, QWidget* parent, + const char* name = 0L, const QString& txt = QString::null, + 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) + */ + KoToolButton( const QPixmap& pixmap, int id, QWidget* parent, + const char* name = 0L, const QString& txt = QString::null ); + + virtual ~KoToolButton(); + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + virtual QSize minimumSize() const; + +public slots: + void colorSelected( const QColor& color ); + +protected: + virtual void drawButton(QPainter *p); + virtual bool eventFilter( QObject* o, QEvent* e ); + +private: + void init(); + void buttonShift( int& dx, int& dy ); + bool hitArrow( const QPoint& pos ); + + QPopupMenu* m_popup; + bool m_arrowPressed; +}; + +#endif // _kotoolbutton_h_ diff --git a/lib/kofficeui/KoUnitWidgets.cpp b/lib/kofficeui/KoUnitWidgets.cpp new file mode 100644 index 00000000..00899882 --- /dev/null +++ b/lib/kofficeui/KoUnitWidgets.cpp @@ -0,0 +1,455 @@ +/* This file is part of the KDE project + Copyright (C) 2002, Rob Buis(buis@kde.org) + Copyright (C) 2004, Nicolas GOUTTE <goutte@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 "KoUnitWidgets.h" +#include "KoUnitWidgets.moc" +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <qpushbutton.h> +#include <qlayout.h> + + +// ---------------------------------------------------------------- +// Support classes + + +KoUnitDoubleValidator::KoUnitDoubleValidator( KoUnitDoubleBase *base, QObject *parent, const char *name ) +: KDoubleValidator( parent, name ), m_base( base ) +{ +} + +QValidator::State +KoUnitDoubleValidator::validate( QString &s, int &pos ) const +{ + + kdDebug(30004) << "KoUnitDoubleValidator::validate : " << s << " at " << pos << endl; + QValidator::State result = Acceptable; + + QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end + const int res = regexp.search( s ); + + if ( res == -1 ) + { + // Nothing like an unit? The user is probably editing the unit + kdDebug(30004) << "Intermediate (no unit)" << endl; + return Intermediate; + } + + // ### TODO: are all the QString::stripWhiteSpace really necessary? + const QString number ( s.left( res ).stripWhiteSpace() ); + const QString unitName ( regexp.cap( 1 ).stripWhiteSpace().lower() ); + + kdDebug(30004) << "Split:" << number << ":" << unitName << ":" << endl; + + bool ok = false; + const double value = m_base->toDouble( number, &ok ); + double newVal = 0.0; + if( ok ) + { + KoUnit::Unit unit = KoUnit::unit( unitName, &ok ); + if ( ok ) + newVal = KoUnit::fromUserValue( value, unit ); + else + { + // Probably the user is trying to edit the unit + kdDebug(30004) << "Intermediate (unknown unit)" << endl; + return Intermediate; + } + } + else + { + kdWarning(30004) << "Not a number: " << number << endl; + return Invalid; + } + + newVal = KoUnit::ptToUnit( newVal, m_base->m_unit ); + + s = m_base->getVisibleText( newVal ); + + return result; +} + + +QString KoUnitDoubleBase::getVisibleText( double value ) const +{ + const QString num ( QString( "%1%2").arg( KGlobal::locale()->formatNumber( value, m_precision ), KoUnit::unitName( m_unit ) ) ); + kdDebug(30004) << "getVisibleText: " << QString::number( value, 'f', 12 ) << " => " << num << endl; + return num; +} + +double KoUnitDoubleBase::toDouble( const QString& str, bool* ok ) const +{ + QString str2( str ); + /* KLocale::readNumber wants the thousand separator exactly at 1000. + But when editing, it might be anywhere. So we need to remove it. */ + const QString sep( KGlobal::locale()->thousandsSeparator() ); + if ( !sep.isEmpty() ) + str2.remove( sep ); + str2.remove( KoUnit::unitName( m_unit ) ); + const double dbl = KGlobal::locale()->readNumber( str2, ok ); + if ( ok ) + kdDebug(30004) << "toDouble:" << str << ": => :" << str2 << ": => " << QString::number( dbl, 'f', 12 ) << endl; + else + kdWarning(30004) << "toDouble error:" << str << ": => :" << str2 << ":" << endl; + return dbl; +} + + +// ---------------------------------------------------------------- +// Widget classes + + +KoUnitDoubleSpinBox::KoUnitDoubleSpinBox( QWidget *parent, const char *name ) + : KDoubleSpinBox( parent, name ), KoUnitDoubleBase( KoUnit::U_PT, 2 ) + , m_lowerInPoints( -9999 ) + , m_upperInPoints( 9999 ) + , m_stepInPoints( 1 ) +{ + KDoubleSpinBox::setPrecision( 2 ); + m_validator = new KoUnitDoubleValidator( this, this ); + QSpinBox::setValidator( m_validator ); + setAcceptLocalizedNumbers( true ); + setUnit( KoUnit::U_PT ); + + connect(this, SIGNAL(valueChanged( double )), SLOT(privateValueChanged())); +} + + +KoUnitDoubleSpinBox::KoUnitDoubleSpinBox( QWidget *parent, + double lower, double upper, + double step, + double value, + KoUnit::Unit unit, + unsigned int precision, + const char *name ) + : KDoubleSpinBox( lower, upper, step, value, precision, parent, name ), + KoUnitDoubleBase( unit, precision ), + m_lowerInPoints( lower ), m_upperInPoints( upper ), m_stepInPoints( step ) +{ + m_unit = KoUnit::U_PT; + m_validator = new KoUnitDoubleValidator( this, this ); + QSpinBox::setValidator( m_validator ); + setAcceptLocalizedNumbers( true ); + setUnit( unit ); + changeValue( value ); + setLineStep( 0.5 ); + + connect(this, SIGNAL(valueChanged( double )), SLOT(privateValueChanged())); +} + +void +KoUnitDoubleSpinBox::changeValue( double val ) +{ + KDoubleSpinBox::setValue( KoUnit::toUserValue( val, m_unit ) ); + // TODO: emit valueChanged ONLY if the value was out-of-bounds + // This will allow the 'user' dialog to set a dirty bool and ensure + // a proper value is getting saved. +} + +void KoUnitDoubleSpinBox::privateValueChanged() { + emit valueChangedPt( value () ); +} + +void +KoUnitDoubleSpinBox::setUnit( KoUnit::Unit unit ) +{ + double oldvalue = KoUnit::fromUserValue( KDoubleSpinBox::value(), m_unit ); + KDoubleSpinBox::setMinValue( KoUnit::toUserValue( m_lowerInPoints, unit ) ); + KDoubleSpinBox::setMaxValue( KoUnit::toUserValue( m_upperInPoints, unit ) ); + KDoubleSpinBox::setLineStep( KoUnit::toUserValue( m_stepInPoints, unit ) ); + KDoubleSpinBox::setValue( KoUnit::ptToUnit( oldvalue, unit ) ); + m_unit = unit; + setSuffix( KoUnit::unitName( unit ).prepend( ' ' ) ); +} + +double KoUnitDoubleSpinBox::value( void ) const +{ + return KoUnit::fromUserValue( KDoubleSpinBox::value(), m_unit ); +} + +void KoUnitDoubleSpinBox::setMinValue( double min ) +{ + m_lowerInPoints = min; + KDoubleSpinBox::setMinValue( KoUnit::toUserValue( m_lowerInPoints, m_unit ) ); +} + +void KoUnitDoubleSpinBox::setMaxValue( double max ) +{ + m_upperInPoints = max; + KDoubleSpinBox::setMaxValue( KoUnit::toUserValue( m_upperInPoints, m_unit ) ); +} + +void KoUnitDoubleSpinBox::setLineStep( double step ) +{ + m_stepInPoints = KoUnit::toUserValue(step, KoUnit::U_PT ); + KDoubleSpinBox::setLineStep( step ); +} + +void KoUnitDoubleSpinBox::setLineStepPt( double step ) +{ + m_stepInPoints = step; + KDoubleSpinBox::setLineStep( KoUnit::toUserValue( m_stepInPoints, m_unit ) ); +} + +void KoUnitDoubleSpinBox::setMinMaxStep( double min, double max, double step ) +{ + setMinValue( min ); + setMaxValue( max ); + setLineStepPt( step ); +} + +// ---------------------------------------------------------------- + + +KoUnitDoubleLineEdit::KoUnitDoubleLineEdit( QWidget *parent, const char *name ) + : KLineEdit( parent, name ), KoUnitDoubleBase( KoUnit::U_PT, 2 ), m_value( 0.0 ), m_lower( 0.0 ), m_upper( 9999.99 ), + m_lowerInPoints( 0.0 ), m_upperInPoints( 9999.99 ) +{ + setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + setValidator( m_validator ); + setUnit( KoUnit::U_PT ); + changeValue( KoUnit::ptToUnit( 0.0, KoUnit::U_PT ) ); +} + +KoUnitDoubleLineEdit::KoUnitDoubleLineEdit( QWidget *parent, double lower, double upper, double value, KoUnit::Unit unit, + unsigned int precision, const char *name ) + : KLineEdit( parent, name ), KoUnitDoubleBase( unit, precision ), m_value( value ), m_lower( lower ), m_upper( upper ), + m_lowerInPoints( lower ), m_upperInPoints( upper ) +{ + setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + setValidator( m_validator ); + setUnit( unit ); + changeValue( KoUnit::ptToUnit( value, unit ) ); +} + +void +KoUnitDoubleLineEdit::changeValue( double value ) +{ + m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value ); + setText( getVisibleText( m_value ) ); +} + +void +KoUnitDoubleLineEdit::setUnit( KoUnit::Unit unit ) +{ + KoUnit::Unit old = m_unit; + m_unit = unit; + m_lower = KoUnit::ptToUnit( m_lowerInPoints, unit ); + m_upper = KoUnit::ptToUnit( m_upperInPoints, unit ); + changeValue( KoUnit::ptToUnit( KoUnit::fromUserValue( m_value, old ), unit ) ); +} + +bool +KoUnitDoubleLineEdit::eventFilter( QObject* o, QEvent* ev ) +{ +#if 0 + if( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Leave || ev->type() == QEvent::Hide ) + { + bool ok; + double value = toDouble( text(), &ok ); + changeValue( value ); + return false; + } + else +#endif + return QLineEdit::eventFilter( o, ev ); +} + +double KoUnitDoubleLineEdit::value( void ) const +{ + return KoUnit::fromUserValue( m_value, m_unit ); +} + + +// ---------------------------------------------------------------- + + +KoUnitDoubleComboBox::KoUnitDoubleComboBox( QWidget *parent, const char *name ) + : KComboBox( true, parent, name ), KoUnitDoubleBase( KoUnit::U_PT, 2 ), m_value( 0.0 ), m_lower( 0.0 ), m_upper( 9999.99 ), m_lowerInPoints( 0.0 ), m_upperInPoints( 9999.99 ) +{ + lineEdit()->setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + lineEdit()->setValidator( m_validator ); + setUnit( KoUnit::U_PT ); + changeValue( KoUnit::ptToUnit( 0.0, KoUnit::U_PT ) ); + connect( this, SIGNAL( activated( int ) ), this, SLOT( slotActivated( int ) ) ); +} + +KoUnitDoubleComboBox::KoUnitDoubleComboBox( QWidget *parent, double lower, double upper, double value, KoUnit::Unit unit, + unsigned int precision, const char *name ) + : KComboBox( true, parent, name ), KoUnitDoubleBase( unit, precision ), m_value( value ), m_lower( lower ), m_upper( upper ), + m_lowerInPoints( lower ), m_upperInPoints( upper ) +{ + lineEdit()->setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + lineEdit()->setValidator( m_validator ); + setUnit( unit ); + changeValue( KoUnit::ptToUnit( value, unit ) ); + connect( this, SIGNAL( activated( int ) ), this, SLOT( slotActivated( int ) ) ); +} + +void +KoUnitDoubleComboBox::changeValue( double value ) +{ + QString oldLabel = lineEdit()->text(); + updateValue( value ); + if( lineEdit()->text() != oldLabel ) + emit valueChanged( m_value ); +} + +void +KoUnitDoubleComboBox::updateValue( double value ) +{ + m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value ); + lineEdit()->setText( getVisibleText( m_value ) ); +} + +void +KoUnitDoubleComboBox::insertItem( double value, int index ) +{ + KComboBox::insertItem( getVisibleText( value ), index ); +} + +void +KoUnitDoubleComboBox::slotActivated( int index ) +{ + double oldvalue = m_value; + bool ok; + double value = toDouble( text( index ), &ok ); + m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value ); + if( m_value != oldvalue ) + emit valueChanged( m_value ); +} + +void +KoUnitDoubleComboBox::setUnit( KoUnit::Unit unit ) +{ + KoUnit::Unit old = m_unit; + m_unit = unit; + m_lower = KoUnit::ptToUnit( m_lowerInPoints, unit ); + m_upper = KoUnit::ptToUnit( m_upperInPoints, unit ); + changeValue( KoUnit::ptToUnit( KoUnit::fromUserValue( m_value, old ), unit ) ); +} + +bool +KoUnitDoubleComboBox::eventFilter( QObject* o, QEvent* ev ) +{ +#if 0 + if( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Leave || ev->type() == QEvent::Hide ) + { + bool ok; + double value = toDouble( lineEdit()->text(), &ok ); + changeValue( value ); + return false; + } + else +#endif + return QComboBox::eventFilter( o, ev ); +} + +double KoUnitDoubleComboBox::value( void ) const +{ + return KoUnit::fromUserValue( m_value, m_unit ); +} + + +// ---------------------------------------------------------------- + + +KoUnitDoubleSpinComboBox::KoUnitDoubleSpinComboBox( QWidget *parent, const char *name ) + : QWidget( parent ), m_step( 1.0 ) +{ + QGridLayout *layout = new QGridLayout( this, 2, 3 ); + //layout->setMargin( 2 ); + QPushButton *up = new QPushButton( "+", this ); + //up->setFlat( true ); + up->setMaximumHeight( 15 ); + up->setMaximumWidth( 15 ); + layout->addWidget( up, 0, 0 ); + connect( up, SIGNAL( clicked() ), this, SLOT( slotUpClicked() ) ); + + QPushButton *down = new QPushButton( "-", this ); + down->setMaximumHeight( 15 ); + down->setMaximumWidth( 15 ); + layout->addWidget( down, 1, 0 ); + connect( down, SIGNAL( clicked() ), this, SLOT( slotDownClicked() ) ); + + m_combo = new KoUnitDoubleComboBox( this, KoUnit::ptToUnit( 0.0, KoUnit::U_PT ), KoUnit::ptToUnit( 9999.99, KoUnit::U_PT ), 0.0, KoUnit::U_PT, 2, name ); + connect( m_combo, SIGNAL( valueChanged( double ) ), this, SIGNAL( valueChanged( double ) ) ); + layout->addMultiCellWidget( m_combo, 0, 1, 2, 2 ); +} + +KoUnitDoubleSpinComboBox::KoUnitDoubleSpinComboBox( QWidget *parent, double lower, double upper, double step, double value, + KoUnit::Unit unit, unsigned int precision, const char *name ) + : QWidget( parent ), m_step( step )//, m_lowerInPoints( lower ), m_upperInPoints( upper ) +{ + QGridLayout *layout = new QGridLayout( this, 2, 3 ); + //layout->setMargin( 2 ); + QPushButton *up = new QPushButton( "+", this ); + //up->setFlat( true ); + up->setMaximumHeight( 15 ); + up->setMaximumWidth( 15 ); + layout->addWidget( up, 0, 0 ); + connect( up, SIGNAL( clicked() ), this, SLOT( slotUpClicked() ) ); + + QPushButton *down = new QPushButton( "-", this ); + down->setMaximumHeight( 15 ); + down->setMaximumWidth( 15 ); + layout->addWidget( down, 1, 0 ); + connect( down, SIGNAL( clicked() ), this, SLOT( slotDownClicked() ) ); + + m_combo = new KoUnitDoubleComboBox( this, KoUnit::ptToUnit( lower, unit ), KoUnit::ptToUnit( upper, unit ), value, unit, precision, name ); + connect( m_combo, SIGNAL( valueChanged( double ) ), this, SIGNAL( valueChanged( double ) ) ); + layout->addMultiCellWidget( m_combo, 0, 1, 2, 2 ); +} + +void +KoUnitDoubleSpinComboBox::slotUpClicked() +{ + m_combo->changeValue( m_combo->value() + m_step ); +} + +void +KoUnitDoubleSpinComboBox::slotDownClicked() +{ + m_combo->changeValue( m_combo->value() - m_step ); +} + +void +KoUnitDoubleSpinComboBox::insertItem( double value, int index ) +{ + m_combo->insertItem( value, index ); +} + +void +KoUnitDoubleSpinComboBox::updateValue( double value ) +{ + m_combo->updateValue( value ); +} + +double +KoUnitDoubleSpinComboBox::value() const +{ + return m_combo->value(); +} + diff --git a/lib/kofficeui/KoUnitWidgets.h b/lib/kofficeui/KoUnitWidgets.h new file mode 100644 index 00000000..957b1b36 --- /dev/null +++ b/lib/kofficeui/KoUnitWidgets.h @@ -0,0 +1,246 @@ +/* This file is part of the KDE project + Copyright (C) 2002, Rob Buis(buis@kde.org) + Copyright (C) 2004, Nicolas GOUTTE <goutte@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. +*/ + +#ifndef __KOUNITWIDGETS_H__ +#define __KOUNITWIDGETS_H__ + +#include <knuminput.h> +#include <knumvalidator.h> +#include <klineedit.h> +#include <kcombobox.h> +#include <KoUnit.h> +#include <koffice_export.h> + + +// ---------------------------------------------------------------- +// Support classes + + +class KoUnitDoubleBase; + +// ### TODO: put it out of the public header file (if possible) +/** + * Validator for the unit widget classes + * \internal + * \since 1.4 (change of behavior) + */ +class KOFFICEUI_EXPORT KoUnitDoubleValidator : public KDoubleValidator +{ +public: + KoUnitDoubleValidator( KoUnitDoubleBase *base, QObject *parent, const char *name = 0 ); + + virtual QValidator::State validate( QString &, int & ) const; + +private: + KoUnitDoubleBase *m_base; +}; + + +/** + * Base for the unit widgets + * \since 1.4 (change of behavior) + */ +class KOFFICEUI_EXPORT KoUnitDoubleBase +{ +public: + KoUnitDoubleBase( KoUnit::Unit unit, unsigned int precision ) : m_unit( unit ), m_precision( precision ) {} + virtual ~KoUnitDoubleBase() {} + + virtual void changeValue( double ) = 0; + virtual void setUnit( KoUnit::Unit = KoUnit::U_PT ) = 0; + + void setValueInUnit( double value, KoUnit::Unit unit ) + { + changeValue( KoUnit::ptToUnit( KoUnit::fromUserValue( value, unit ), m_unit ) ); + } + + void setPrecision( unsigned int precision ) { m_precision = precision; }; + +protected: + friend class KoUnitDoubleValidator; + /** + * Transform the double in a nice text, using locale symbols + * @param value the number as double + * @return the resulting string + */ + QString getVisibleText( double value ) const; + /** + * Transfrom a string into a double, while taking care of locale specific symbols. + * @param str the string to transform into a number + * @param ok true, if the conversion was succesful + * @return the value as double + */ + double toDouble( const QString& str, bool* ok ) const; + +protected: + KoUnitDoubleValidator *m_validator; + KoUnit::Unit m_unit; + unsigned int m_precision; +}; + + +// ---------------------------------------------------------------- +// Widget classes + + +/** + * Spin box for double precision numbers with unit display + * \since 1.4 (change of behavior) + */ +class KOFFICEUI_EXPORT KoUnitDoubleSpinBox : public KDoubleSpinBox, public KoUnitDoubleBase +{ + Q_OBJECT +public: + KoUnitDoubleSpinBox( QWidget *parent = 0L, const char *name = 0L ); + // lower, upper, step and value are in pt + KoUnitDoubleSpinBox( 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 ); + // added so the class can be used in .ui files(by Tymoteusz Majewski, maju7@o2.pl) + virtual void changeValue( double ); + virtual void setUnit( KoUnit::Unit = KoUnit::U_PT ); + + /// @return the current value, converted in points + double value( void ) const; + + /// Set minimum value in points. + void setMinValue(double min); + + /// Set maximum value in points. + void setMaxValue(double max); + + /// Set step size in the current unit. + void setLineStep(double step); + + /// Set step size in points. + void setLineStepPt(double step); + + /// Set minimum, maximum value and the step size (all in points) (by Tymoteusz Majewski, maju7@o2.pl) + void setMinMaxStep( double min, double max, double step ); + +signals: + /// emitted like valueChanged in the parent, but this one emits the point value + void valueChangedPt( double ); + + +private: + double m_lowerInPoints; ///< lowest value in points + double m_upperInPoints; ///< highest value in points + double m_stepInPoints; ///< step in points + +private slots: + // exists to do emits for valueChangedPt + void privateValueChanged(); +}; + + +/** + * Line edit for double precision numbers with unit display + * \since 1.4 (change of behavior) + */ +class KOFFICEUI_EXPORT KoUnitDoubleLineEdit : public KLineEdit, public KoUnitDoubleBase +{ + Q_OBJECT +public: + KoUnitDoubleLineEdit( QWidget *parent = 0L, const char *name = 0L ); + KoUnitDoubleLineEdit( QWidget *parent, double lower, double upper, double value = 0.0, KoUnit::Unit unit = KoUnit::U_PT, unsigned int precision = 2, const char *name = 0 ); + + virtual void changeValue( double ); + virtual void setUnit( KoUnit::Unit = KoUnit::U_PT ); + + /// @return the current value, converted in points + double value( void ) const; + +protected: + bool eventFilter( QObject* obj, QEvent* ev ); + +private: + double m_value; + double m_lower; + double m_upper; + double m_lowerInPoints; ///< lowest value in points + double m_upperInPoints; ///< highest value in points +}; + +/** + * Combo box for double precision numbers with unit display + * \since 1.4 (change of behavior) + */ +class KOFFICEUI_EXPORT KoUnitDoubleComboBox : public KComboBox, public KoUnitDoubleBase +{ + Q_OBJECT +public: + KoUnitDoubleComboBox( QWidget *parent = 0L, const char *name = 0L ); + KoUnitDoubleComboBox( QWidget *parent, double lower, double upper, double value = 0.0, KoUnit::Unit unit = KoUnit::U_PT, unsigned int precision = 2, const char *name = 0 ); + + virtual void changeValue( double ); + void updateValue( double ); + virtual void setUnit( KoUnit::Unit = KoUnit::U_PT ); + + /// @return the current value, converted in points + double value( void ) const; + void insertItem( double, int index = -1 ); + +protected: + bool eventFilter( QObject* obj, QEvent* ev ); + +signals: + void valueChanged(double); + +private slots: + void slotActivated( int ); + +protected: + double m_value; + double m_lower; + double m_upper; + double m_lowerInPoints; ///< lowest value in points + double m_upperInPoints; ///< highest value in points +}; + +/** + * Combo box (with spin control) for double precision numbers with unit display + * \since 1.4 (change of behavior) + */ +class KOFFICEUI_EXPORT KoUnitDoubleSpinComboBox : public QWidget +{ + Q_OBJECT +public: + KoUnitDoubleSpinComboBox( QWidget *parent = 0L, const char *name = 0L ); + KoUnitDoubleSpinComboBox( 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 ); + + void insertItem( double, int index = -1 ); + void updateValue( double ); + /// @return the current value, converted in points + double value( void ) const; + +signals: + void valueChanged(double); + +private slots: + void slotUpClicked(); + void slotDownClicked(); + +private: + KoUnitDoubleComboBox *m_combo; + double m_step; +}; + +#endif + diff --git a/lib/kofficeui/KoZoomAction.cpp b/lib/kofficeui/KoZoomAction.cpp new file mode 100644 index 00000000..5f53f007 --- /dev/null +++ b/lib/kofficeui/KoZoomAction.cpp @@ -0,0 +1,115 @@ +/* This file is part of the KDE libraries + Copyright (C) 2004 Ariya Hidayat <ariya@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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <KoZoomAction.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qregexp.h> +#include <qvaluelist.h> + +#include <klocale.h> + +KoZoomAction::KoZoomAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, QObject* parent, const char* name ): + KSelectAction( text, pix, cut, parent, name ) +{ + init(); +} + +KoZoomAction::KoZoomAction( const QString& text, const QString& pix, + const KShortcut& cut, QObject* parent, const char* name ): + KSelectAction( text, pix, cut, parent, name ) +{ + init(); + +} + +void KoZoomAction::setZoom( const QString& text ) +{ + bool ok = false; + QString t = text; + int zoom = t.remove( '%' ).toInt( &ok ); + + // where we'll store sorted new zoom values + QValueList<int> list; + if( zoom > 10 ) list.append( zoom ); + + // "Captured" non-empty sequence of digits + QRegExp regexp("(\\d+)"); + + const QStringList itemsList( items() ); + for( QStringList::ConstIterator it = itemsList.begin(); it != itemsList.end(); ++it ) + { + regexp.search( *it ); + const int val=regexp.cap(1).toInt( &ok ); + + //zoom : limit inferior=10 + if( ok && val>9 && list.contains( val )==0 ) + list.append( val ); + } + + qHeapSort( list ); + + // update items with new sorted zoom values + QStringList values; + for (QValueList<int>::Iterator it = list.begin(); it != list.end(); ++it ) + values.append( i18n("%1%").arg(*it) ); + setItems( values ); + + QString zoomStr = i18n("%1%").arg( zoom ); + setCurrentItem( values.findIndex( zoomStr ) ); +} + +void KoZoomAction::setZoom( int zoom ) +{ + setZoom( QString::number( zoom ) ); +} + +void KoZoomAction::activated( const QString& text ) +{ + setZoom( text ); + emit zoomChanged( text ); +} + +void KoZoomAction::init() +{ + setEditable( true ); + + QStringList values; + values << i18n("%1%").arg("33"); + values << i18n("%1%").arg("50"); + values << i18n("%1%").arg("75"); + values << i18n("%1%").arg("100"); + values << i18n("%1%").arg("125"); + values << i18n("%1%").arg("150"); + values << i18n("%1%").arg("200"); + values << i18n("%1%").arg("250"); + values << i18n("%1%").arg("350"); + values << i18n("%1%").arg("400"); + values << i18n("%1%").arg("450"); + values << i18n("%1%").arg("500"); + setItems( values ); + + setCurrentItem( values.findIndex( i18n("%1%").arg( 100 ) ) ); + + connect( this, SIGNAL( activated( const QString& ) ), + SLOT( activated( const QString& ) ) ); +} + +#include "KoZoomAction.moc" diff --git a/lib/kofficeui/KoZoomAction.h b/lib/kofficeui/KoZoomAction.h new file mode 100644 index 00000000..326e4f04 --- /dev/null +++ b/lib/kofficeui/KoZoomAction.h @@ -0,0 +1,82 @@ +/* This file is part of the KDE libraries + Copyright (C) 2004 Ariya Hidayat <ariya@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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef kozoomaction_h +#define kozoomaction_h + +#include <kaction.h> +#include <koffice_export.h> +/** + * Class KoZoomAction implements an action to provide zoom values. + * In a toolbar, KoZoomAction will show a dropdown list, also with + * the possibility for the user to enter arbritrary zoom value + * (must be an integer). The values shown on the list are alwalys + * sorted. + */ +class KOFFICEUI_EXPORT KoZoomAction : public KSelectAction +{ +Q_OBJECT + +public: + + /** + * Creates a new zoom action. + */ + KoZoomAction( const QString& text, const QIconSet& pix, + const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * Creates a new zoom action. + */ + KoZoomAction( const QString& text, const QString& pix, + const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + +public slots: + + /** + * Sets the zoom. If it's not yet on the list of zoom values, it will be inserted + * into the list at proper place so that the the values remain sorted. + */ + void setZoom( const QString& zoom ); + + /** + * Sets the zoom. If it's not yet on the list of zoom values, it will be inserted + * into the list at proper place so that the the values remain sorted. + */ + void setZoom( int zoom ); + +protected slots: + + void activated( const QString& text ); + +signals: + + /** + * Signal zoomChanged is triggered when user changes the zoom value, either by + * choosing it from the list or by entering new value. + */ + void zoomChanged( const QString& zoom ); + +protected: + + void init(); + +}; + + +#endif // kozoomaction_h diff --git a/lib/kofficeui/KoZoomHandler.cpp b/lib/kofficeui/KoZoomHandler.cpp new file mode 100644 index 00000000..2bb202e9 --- /dev/null +++ b/lib/kofficeui/KoZoomHandler.cpp @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + Copyright (C) 2001-2005 David Faure <faure@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 "KoZoomHandler.h" +#include <kdebug.h> +#include <KoUnit.h> // for POINT_TO_INCH +#include <KoGlobal.h> + +KoZoomHandler::KoZoomHandler() +{ + // Note that this calls the method below, not the derived one + setZoomAndResolution( 100, KoGlobal::dpiX(), KoGlobal::dpiY() ); +} + +void KoZoomHandler::setZoomAndResolution( int zoom, int dpiX, int dpiY ) +{ + // m_resolution[XY] is in pixel per pt + m_resolutionX = POINT_TO_INCH( static_cast<double>(dpiX) ); + m_resolutionY = POINT_TO_INCH( static_cast<double>(dpiY) ); + setZoom( zoom ); + /*kdDebug(32500) << "KoZoomHandler::setZoomAndResolution " << zoom << " " << dpiX << "," << dpiY + << " m_resolutionX=" << m_resolutionX + << " m_zoomedResolutionX=" << m_zoomedResolutionX + << " m_resolutionY=" << m_resolutionY + << " m_zoomedResolutionY=" << m_zoomedResolutionY << endl;*/ +} + +void KoZoomHandler::setResolution( double resolutionX, double resolutionY ) +{ + m_zoom = 100; + m_resolutionX = resolutionX; + m_resolutionY = resolutionY; + m_zoomedResolutionX = resolutionX; + m_zoomedResolutionY = resolutionY; +} + +void KoZoomHandler::setZoomedResolution( double zoomedResolutionX, double zoomedResolutionY ) +{ + // m_zoom doesn't matter, it's only used in setZoom() to calculated the zoomed resolutions + // Here we know them. The whole point of this method is to allow a different zoom factor + // for X and for Y, as can be useful for e.g. fullscreen kpresenter presentations. + m_zoomedResolutionX = zoomedResolutionX; + m_zoomedResolutionY = zoomedResolutionY; +} + +void KoZoomHandler::setZoom( int zoom ) +{ + m_zoom = zoom; + if( m_zoom == 100 ) { + m_zoomedResolutionX = m_resolutionX; + m_zoomedResolutionY = m_resolutionY; + } else { + m_zoomedResolutionX = static_cast<double>(m_zoom) * m_resolutionX / 100.0; + m_zoomedResolutionY = static_cast<double>(m_zoom) * m_resolutionY / 100.0; + } +} diff --git a/lib/kofficeui/KoZoomHandler.h b/lib/kofficeui/KoZoomHandler.h new file mode 100644 index 00000000..903d2e11 --- /dev/null +++ b/lib/kofficeui/KoZoomHandler.h @@ -0,0 +1,163 @@ +/* This file is part of the KDE project + Copyright (C) 2001-2005 David Faure <faure@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. +*/ + +#ifndef kozoomhandler_h +#define kozoomhandler_h + +#include <KoRect.h> +#include <koffice_export.h> +#include <KoZoomMode.h> + +/** + * This class handles the zooming and DPI stuff (conversions between pt values and pixels). + * An instance of KoZoomHandler operates at a given zoom (see setZoomAndResolution() and setZoom()) + * so there is usually one instance of KoZoomHandler per view. + */ +class KOFFICEUI_EXPORT KoZoomHandler +{ +public: + KoZoomHandler(); + virtual ~KoZoomHandler() {} + + /** + * Change the zoom factor to @p z (e.g. 150 for 150%) + * and/or change the resolution, given in DPI. + * This is done on startup, when zooming, and when printing. + * The same call combines both so that all the updating done behind + * the scenes is done only once, even if both zoom and DPI must be changed. + */ + virtual void setZoomAndResolution( int zoom, int dpiX, int dpiY ); + + /** + * @return the conversion factor between pt and pixel, that + * takes care of the zoom and the DPI setting. + * Use zoomIt(pt) instead, though. + */ + double zoomedResolutionX() const { return m_zoomedResolutionX; } + double zoomedResolutionY() const { return m_zoomedResolutionY; } + + double resolutionX() const { return m_resolutionX; } + double resolutionY() const { return m_resolutionY; } + + /** + * Zoom factor for X. Equivalent to zoomedResolutionX()/resolutionX() + */ + double zoomFactorX() const { return m_zoomedResolutionX / m_resolutionX; } + /** + * Zoom factor for Y. Equivalent to zoomedResolutionY()/resolutionY() + */ + double zoomFactorY() const { return m_zoomedResolutionY / m_resolutionY; } + + + /** + * Set a resolution for X and Y, when no zoom applies (e.g. when painting an + * embedded document. This will set the zoom to 100, and it will set + * zoomedResolution[XY] to the resolution[XY] parameters + * Helper method, equivalent to setZoomAndResolution(100,...). + */ + void setResolution( double resolutionX, double resolutionY ); + + /** + * Set the zoomed resolution for X and Y. + * Compared to the setZoom... methods, this allows to set a different + * zoom factor for X and for Y. + */ + virtual void setZoomedResolution( double zoomedResolutionX, double zoomedResolutionY ); + + /** + * Change the zoom level, keeping the resolution unchanged. + * @param zoom the zoom factor (e.g. 100 for 100%) + */ + void setZoom( int zoom ); + /** + * Change the zoom mode + * @param zoomMode the zoom mode. + */ + void setZoomMode( KoZoomMode::Mode zoomMode ) { m_zoomMode = zoomMode; } + /** + * @return the global zoom factor (e.g. 100 for 100%). + * Only use this to display to the user, don't use in calculations + */ + int zoom() const { return m_zoom; } + /** + * @return the global zoom mode (e.g. KoZoomMode::ZOOM_WIDTH). + * use this to determine how to zoom + */ + KoZoomMode::Mode zoomMode() const { return m_zoomMode; } + + // Input: pt. Output: pixels. Resolution and zoom are applied. + int zoomItX( double z ) const { + return qRound( m_zoomedResolutionX * z ); + } + int zoomItY( double z ) const { + return qRound( m_zoomedResolutionY * z ); + } + + QPoint zoomPoint( const KoPoint & p ) const { + return QPoint( zoomItX( p.x() ), zoomItY( p.y() ) ); + } + QRect zoomRect( const KoRect & r ) const { + QRect _r; + _r.setCoords( zoomItX( r.left() ), zoomItY( r.top() ), + zoomItX( r.right() ), zoomItY( r.bottom() ) ); + return _r; + } + /** + * Returns the size in pixels for a input size in points. + * + * This function can return a size with 1 pixel to less, depending + * on the reference point and the width and/or the zoom level. + * It's save to use if the starting point is (0/0). + * You can use it if you don't know the starting point yet + * (like when inserting a picture), but then please take + * care of it afterwards, when you know the reference point. + */ + QSize zoomSize( const KoSize & s ) const { + return QSize( zoomItX( s.width() ), zoomItY( s.height() ) ); + } + + // Input: pixels. Output: pt. + double unzoomItX( int x ) const { + return static_cast<double>( x ) / m_zoomedResolutionX; + } + double unzoomItY( int y ) const { + return static_cast<double>( y ) / m_zoomedResolutionY; + } + KoPoint unzoomPoint( const QPoint & p ) const { + return KoPoint( unzoomItX( p.x() ), unzoomItY( p.y() ) ); + } + KoRect unzoomRect( const QRect & r ) const { + KoRect _r; + _r.setCoords( unzoomItX( r.left() ), unzoomItY( r.top() ), + unzoomItX( r.right() ), unzoomItY( r.bottom() ) ); + return _r; + } + + +protected: + int m_zoom; + KoZoomMode::Mode m_zoomMode; + + double m_resolutionX; + double m_resolutionY; + double m_zoomedResolutionX; + double m_zoomedResolutionY; +}; + +#endif diff --git a/lib/kofficeui/KoZoomMode.cpp b/lib/kofficeui/KoZoomMode.cpp new file mode 100644 index 00000000..4df4a7fa --- /dev/null +++ b/lib/kofficeui/KoZoomMode.cpp @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Johannes Schaub <litb_devel@web.de> + + 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 "KoZoomMode.h" +#include <klocale.h> + +const char* KoZoomMode::modes[] = +{ + I18N_NOOP("Fit to Width"), + I18N_NOOP("Fit to Page"), + I18N_NOOP("%1%") +}; + +QString KoZoomMode::toString(Mode mode) +{ + return i18n(modes[mode]); +} + +KoZoomMode::Mode KoZoomMode::toMode(const QString& mode) +{ + if(mode == i18n(modes[ZOOM_WIDTH])) + return ZOOM_WIDTH; + else + if(mode == i18n(modes[ZOOM_PAGE])) + return ZOOM_PAGE; + else + return ZOOM_CONSTANT; + // we return ZOOM_CONSTANT else because then we can pass '10%' or '15%' + // or whatever, it's automatically converted. ZOOM_CONSTANT is + // changable, whereas all other zoom modes (non-constants) are normal + // text like "Fit to xxx". they let the view grow/shrink according + // to windowsize, hence the term 'non-constant' +} diff --git a/lib/kofficeui/KoZoomMode.h b/lib/kofficeui/KoZoomMode.h new file mode 100644 index 00000000..3e012f28 --- /dev/null +++ b/lib/kofficeui/KoZoomMode.h @@ -0,0 +1,54 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Johannes Schaub <litb_devel@web.de> + + 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. +*/ + +#ifndef _KOZOOMMODE_H_ +#define _KOZOOMMODE_H_ + +#include <qstring.h> +#include "koffice_export.h" + +/** + * The ZoomMode container + */ +class KOFFICEUI_EXPORT KoZoomMode +{ +public: + enum Mode + { + ZOOM_WIDTH = 0, ///< zoom pagewidth + ZOOM_PAGE = 1, ///< zoom to pagesize + ZOOM_CONSTANT = 2 ///< zoom x % + }; + + /// \param mode the mode name + /// \return the to Mode converted QString \c mode + static Mode toMode(const QString& mode); + + /// \return the to QString converted and translated Mode \c mode + static QString toString(Mode mode); + + /// \param mode the mode name + /// \return true if \c mode isn't dependent on windowsize + static bool isConstant(const QString& mode) + { return toMode(mode) == ZOOM_CONSTANT; } +private: + static const char * modes[]; +}; + +#endif diff --git a/lib/kofficeui/Kolinestyleaction.cpp b/lib/kofficeui/Kolinestyleaction.cpp new file mode 100644 index 00000000..da3415c7 --- /dev/null +++ b/lib/kofficeui/Kolinestyleaction.cpp @@ -0,0 +1,88 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Peter Simonsson <psn@linux.se> + + 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 "Kolinestyleaction.h" + +#include <qpainter.h> +#include <qpixmap.h> +#include <qbitmap.h> + +#include <kpopupmenu.h> +#include <kdebug.h> +#include <klocale.h> + +class KoLineStyleAction::KoLineStyleActionPrivate +{ + public: + KoLineStyleActionPrivate() + { + m_currentStyle = Qt::SolidLine; + } + + ~KoLineStyleActionPrivate() + { + } + + int m_currentStyle; +}; + +KoLineStyleAction::KoLineStyleAction(const QString &text, const QString& icon, + QObject* parent, const char* name) : KoSelectAction(text, icon, parent, name) +{ + d = new KoLineStyleActionPrivate; + + createMenu(); +} + +KoLineStyleAction::KoLineStyleAction(const QString &text, const QString& icon, const QObject* receiver, + const char* slot, QObject* parent, const char* name) : KoSelectAction(text, icon, receiver, slot, parent, name) +{ + d = new KoLineStyleActionPrivate; + + createMenu(); +} + +KoLineStyleAction::~KoLineStyleAction() +{ + delete d; +} + +void KoLineStyleAction::createMenu() +{ + KPopupMenu* popup = popupMenu(); + QBitmap mask; + QPixmap pix(70, 21); + QPainter p(&pix, popup); + int cindex = 0; + QPen pen; + pen.setWidth(2); + popup->insertItem(i18n("None"),cindex++); + + for(int i = 1; i < 6; i++) { + pix.fill(white); + pen.setStyle(static_cast<Qt::PenStyle>(i)); + p.setPen(pen); + p.drawLine(0, 10, pix.width(), 10); + mask = pix; + pix.setMask(mask); + popup->insertItem(pix,cindex++); + } +} + +#include "Kolinestyleaction.moc" diff --git a/lib/kofficeui/Kolinestyleaction.h b/lib/kofficeui/Kolinestyleaction.h new file mode 100644 index 00000000..ff8086f8 --- /dev/null +++ b/lib/kofficeui/Kolinestyleaction.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Peter Simonsson <psn@linux.se> + + 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. +*/ + +#ifndef KOLINESTYLEACTION_H +#define KOLINESTYLEACTION_H + +#include "KoSelectAction.h" +#include <koffice_export.h> +/** A line style selection action */ +class KOFFICEUI_EXPORT KoLineStyleAction : public KoSelectAction +{ + Q_OBJECT + public: + /** Constructs a KoLineStyleAction with a text and an icon. + * @param text The text that will be displayed. + * @param icon The dynamically loaded icon that goes with this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KoLineStyleAction(const QString& text, const QString& icon, QObject* parent = 0, const char* name = 0); + /** Same as above, but it also connects a slot to the selectionChanged(int) signal. + * @param text The text that will be displayed. + * @param icon The dynamically loaded icon that goes with this action. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a selectionChanged(int) signal is emited. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KoLineStyleAction(const QString& text, const QString& icon, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0); + ~KoLineStyleAction(); + + protected: + /** Draws and adds each item of the menu. */ + void createMenu(); + + private: + class KoLineStyleActionPrivate; + KoLineStyleActionPrivate* d; +}; + +#endif diff --git a/lib/kofficeui/Kolinewidthaction.cpp b/lib/kofficeui/Kolinewidthaction.cpp new file mode 100644 index 00000000..611481cb --- /dev/null +++ b/lib/kofficeui/Kolinewidthaction.cpp @@ -0,0 +1,200 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Peter Simonsson <psn@linux.se> + + 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 "Kolinewidthaction.h" + +#include <qpainter.h> +#include <qpixmap.h> +#include <qbitmap.h> +#include <qwhatsthis.h> +#include <qmenubar.h> +#include <qlayout.h> +#include <qlabel.h> + +#include <kpopupmenu.h> +#include <kapplication.h> +#include <kdebug.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> +#include <kiconloader.h> +#include <klocale.h> + +#include <KoUnitWidgets.h> +#include <KoGlobal.h> + +class KoLineWidthAction::KoLineWidthActionPrivate +{ + public: + KoLineWidthActionPrivate() + { + m_currentWidth = 1.0; + m_unit = KoUnit::U_PT; + } + + ~KoLineWidthActionPrivate() + { + } + + double m_currentWidth; + KoUnit::Unit m_unit; +}; + +KoLineWidthAction::KoLineWidthAction(const QString &text, const QString& icon, + QObject* parent, const char* name) : KoSelectAction(text, icon, parent, name) +{ + d = new KoLineWidthActionPrivate; + + createMenu(); +} + +KoLineWidthAction::KoLineWidthAction(const QString &text, const QString& icon, const QObject* receiver, + const char* slot, QObject* parent, const char* name) : KoSelectAction(text, icon, parent, name) +{ + d = new KoLineWidthActionPrivate; + + createMenu(); + + connect(this, SIGNAL(lineWidthChanged(double)), receiver, slot); +} + +KoLineWidthAction::~KoLineWidthAction() +{ + delete d; +} + +void KoLineWidthAction::createMenu() +{ + KPopupMenu* popup = popupMenu(); + QBitmap mask; + QPixmap pix(70, 21); + QPainter p(&pix, popup); + int cindex = 0; + QPen pen; + + for(int i = 1; i <= 10; i++) { + pix.fill(white); + pen.setWidth(qRound(i * POINT_TO_INCH(static_cast<double>(KoGlobal::dpiY())))); + p.setPen(pen); + p.drawLine(0, 10, pix.width(), 10); + mask = pix; + pix.setMask(mask); + popup->insertItem(pix,cindex++); + } + + popup->insertSeparator(cindex++); + popup->insertItem(i18n("&Custom..."), cindex++); +} + +void KoLineWidthAction::execute(int index) +{ + bool ok = false; + + if((index >= 0) && (index < 10)) { + d->m_currentWidth = (double) index + 1.0; + ok = true; + } if(index == 11) { // Custom width dialog... + KoLineWidthChooser dlg(qApp->activeWindow()); + dlg.setUnit(d->m_unit); + dlg.setWidth(d->m_currentWidth); + + if(dlg.exec()) { + d->m_currentWidth = dlg.width(); + ok = true; + } + } + + if(ok) { + setCurrentSelection(index); + emit lineWidthChanged(d->m_currentWidth); + } +} + +double KoLineWidthAction::currentWidth() const +{ + return d->m_currentWidth; +} + +void KoLineWidthAction::setCurrentWidth(double width) +{ + d->m_currentWidth = width; + + // Check if it is a standard width... + for(int i = 1; i <= 10; i++) { + if(KoUnit::toPoint(width) == (double) i) { + setCurrentSelection(i - 1); + return; + } + } + + //Custom width... + setCurrentSelection(11); +} + +void KoLineWidthAction::setUnit(KoUnit::Unit unit) +{ + d->m_unit = unit; +} + +////////////////////////////////////////////////// +// +// KoLineWidthChooser +// + +class KoLineWidthChooser::KoLineWidthChooserPrivate +{ + public: + KoUnitDoubleSpinBox* m_lineWidthUSBox; +}; + +KoLineWidthChooser::KoLineWidthChooser(QWidget* parent, const char* name) + : KDialogBase(parent, name, true, i18n("Custom Line Width"), Ok|Cancel, Ok) +{ + d = new KoLineWidthChooserPrivate; + + // Create the ui + QWidget* mainWidget = new QWidget(this); + setMainWidget(mainWidget); + QGridLayout* gl = new QGridLayout(mainWidget, 1, 2, KDialog::marginHint(), KDialog::spacingHint()); + QLabel* textLbl = new QLabel(i18n("Line width:"), mainWidget); + d->m_lineWidthUSBox = new KoUnitDoubleSpinBox(mainWidget, 0.0, 1000.0, 0.1, 1.0, KoUnit::U_PT, 2); + gl->addWidget(textLbl, 0, 0); + gl->addWidget(d->m_lineWidthUSBox, 0, 1); +} + +KoLineWidthChooser::~KoLineWidthChooser() +{ + delete d; +} + +double KoLineWidthChooser::width() const +{ + return d->m_lineWidthUSBox->value(); +} + +void KoLineWidthChooser::setUnit(KoUnit::Unit unit) +{ + d->m_lineWidthUSBox->setUnit(unit); +} + +void KoLineWidthChooser::setWidth(double width) +{ + d->m_lineWidthUSBox->changeValue(width); +} + +#include "Kolinewidthaction.moc" diff --git a/lib/kofficeui/Kolinewidthaction.h b/lib/kofficeui/Kolinewidthaction.h new file mode 100644 index 00000000..fe03de72 --- /dev/null +++ b/lib/kofficeui/Kolinewidthaction.h @@ -0,0 +1,112 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Peter Simonsson <psn@linux.se> + + 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. +*/ + +#ifndef KOLINEWIDTHACTION_H +#define KOLINEWIDTHACTION_H + +#include <kdialogbase.h> + +#include <KoUnit.h> +#include <KoSelectAction.h> +#include <koffice_export.h> + +/** A line width selection action */ +class KOFFICEUI_EXPORT KoLineWidthAction : public KoSelectAction +{ + Q_OBJECT + public: + /** Constructs a KoLineWidthAction with a text and an icon. + * @param text The text that will be displayed. + * @param icon The dynamically loaded icon that goes with this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KoLineWidthAction(const QString& text, const QString& icon, QObject* parent = 0, const char* name = 0); + /** Same as above, but it also connects a slot to the selectionChanged(int) signal. + * @param text The text that will be displayed. + * @param icon The dynamically loaded icon that goes with this action. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a lineWidthChanged(double) signal is emited. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KoLineWidthAction(const QString& text, const QString& icon, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0); + ~KoLineWidthAction(); + + /** Returns the currently selected line width */ + double currentWidth() const; + + signals: + /** Emited when a new line width have been selected */ + void lineWidthChanged(double); + + public slots: + /** Set the current width. + * @param width The new width. + */ + void setCurrentWidth(double width); + /** Set which unit to use in the custom width dialog. + * @param unit The unit to use. + */ + void setUnit(KoUnit::Unit unit); + + protected slots: + /** Reimplemented from KoSelectAction. + * Emits lineWidthChanged(double) when a new width is selected. + * @param index Index of the selected item + */ + void execute(int index); + + protected: + /** Draws and adds each item of the menu. */ + void createMenu(); + + private: + class KoLineWidthActionPrivate; + KoLineWidthActionPrivate* d; +}; + +/** This class provides a dialog for setting a custom line width. */ +class KoLineWidthChooser : public KDialogBase +{ + Q_OBJECT + public: + KoLineWidthChooser(QWidget* parent = 0, const char* name = 0); + ~KoLineWidthChooser(); + + /** Returns the selected line width in points. */ + double width() const; + + public slots: + /** Set unit to use when showing the width. + * @param unit Unit to use. + */ + void setUnit(KoUnit::Unit unit); + /** Set line width. + * @param width Line width in points. + */ + void setWidth(double width); + + private: + class KoLineWidthChooserPrivate; + KoLineWidthChooserPrivate* d; +}; + +#endif diff --git a/lib/kofficeui/Makefile.am b/lib/kofficeui/Makefile.am new file mode 100644 index 00000000..133673f2 --- /dev/null +++ b/lib/kofficeui/Makefile.am @@ -0,0 +1,61 @@ +###### General stuff + +KDE_CXXFLAGS = $(USE_RTTI) -DMAKE_KOFFICEUI_LIB +INCLUDES = $(KSTORE_INCLUDES) $(KOFFICECORE_INCLUDES) $(all_includes) + +####### Files + +SUBDIRS = . tests pics + +lib_LTLIBRARIES = libkofficeui.la + +libkofficeui_la_SOURCES = \ + KoPageLayoutDia.cpp KoZoomAction.cpp KoTabBar.cpp \ + KoPartSelectDia.cpp KoPartSelectAction.cpp \ + KoRuler.cpp KoTemplateChooseDia.cpp KoTabChooser.cpp \ + KoKoolBar.cpp KoTemplateCreateDia.cpp KoContextCelp.cpp\ + kcoloractions.cpp \ + KoPictureFilePreview.cpp KoUnitWidgets.cpp \ + tkaction.cpp tkcoloractions.cpp tkcombobox.cpp tktoolbarbutton.cpp \ + KoCharSelectDia.cpp KoInsertLink.cpp KoEditPath.cpp KoCommandHistory.cpp \ + KoSelectAction.cpp Kolinewidthaction.cpp Kolinestyleaction.cpp \ + KoTooluButton.cpp \ + KoBrush.cpp KoImageResource.cpp KoToolBox.cpp KoZoomHandler.cpp \ + KoGuideLineDia.cpp KoGuides.cpp \ + KoGeneralPropertyUi.ui KoPageLayoutColumns.cpp KoPageLayoutColumnsBase.ui KoPageLayoutSize.cpp \ + KoPageLayoutHeaderBase.ui KoPageLayoutHeader.cpp KoPen.cpp KoZoomMode.cpp + +libkofficeui_la_LDFLAGS = -version-info 3:0:0 -no-undefined $(all_libraries) +libkofficeui_la_LIBADD = $(LIB_KOFFICECORE) + +include_HEADERS = \ + KoPageLayoutDia.h KoZoomAction.h KoTabBar.h \ + KoPartSelectDia.h KoPartSelectAction.h \ + KoRuler.h KoTemplateChooseDia.h KoTabChooser.h \ + KoKoolBar.h KoTemplateCreateDia.h KoContextCelp.h \ + kcoloractions.h \ + KoPictureFilePreview.h KoUnitWidgets.h \ + tkaction.h tkcoloractions.h tktoolbarbutton.h tkcombobox.h \ + KoCharSelectDia.h KoInsertLink.h KoTooluButton.h KoEditPath.h \ + KoCommandHistory.h KoImageResource.h \ + KoSelectAction.h Kolinewidthaction.h Kolinestyleaction.h \ + KoZoomHandler.h KoGuideLineDia.h KoGuides.h \ + KoPageLayoutHeader.h KoPageLayoutSize.h KoGeneralPropertyUi.h KoPageLayoutColumns.h \ + KoBrush.h KoPen.h KoZoomMode.h + + +# FIXME: Disabled for now as it breaks the installation process if +# KOffice is not installed in $KDEDIR +# +#AM_CXXFLAGS = -DQT_PLUGIN +#kde_widget_LTLIBRARIES = kofficewidgets.la +#kofficewidgets_la_LDFLAGS = $(KDE_PLUGIN) -module $(all_libraries) +#kofficewidgets_la_LIBADD = $(LIB_KIO) libkofficeui.la +#kofficewidgets_la_SOURCES = kofficewidgets.cpp + +#kofficewidgets.cpp: $(srcdir)/koffice.widgets +# $(MAKEKDEWIDGETS) -o kofficewidgets.cpp $(srcdir)/koffice.widgets + +#CLEANFILES = kofficewidgets.cpp + +METASOURCES = AUTO diff --git a/lib/kofficeui/kcoloractions.cpp b/lib/kofficeui/kcoloractions.cpp new file mode 100644 index 00000000..a2d707d4 --- /dev/null +++ b/lib/kofficeui/kcoloractions.cpp @@ -0,0 +1,348 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2002 Werner Trobin <trobin@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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <kcoloractions.h> + +#include <qpopupmenu.h> +#include <qwhatsthis.h> +#include <qtooltip.h> + +#include <kapplication.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> +#include <kdebug.h> + +KColorAction::KColorAction( const QString& text, int accel, + QObject* parent, const char* name ) + : KAction( text, accel, parent, name ) +{ + typ = TextColor; + init(); +} + +KColorAction::KColorAction( const QString& text, int accel, + QObject* receiver, const char* slot, QObject* parent, + const char* name ) + : KAction( text, accel, receiver, slot, parent, name ) +{ + typ = TextColor; + init(); +} + +KColorAction::KColorAction( const QString& text, Type type, int accel, + QObject* parent, const char* name ) + : KAction( text, accel, parent, name ) +{ + typ = type; + init(); +} + +KColorAction::KColorAction( const QString& text, Type type, int accel, + QObject* receiver, const char* slot, QObject* parent, + const char* name ) + : KAction( text, accel, receiver, slot, parent, name ) +{ + typ = type; + init(); +} + +KColorAction::KColorAction( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + typ = TextColor; + init(); +} + +void KColorAction::setColor( const QColor &c ) +{ + if ( c == col ) + return; + + col = c; + createPixmap(); +} + +QColor KColorAction::color() const +{ + return col; +} + +void KColorAction::setType( Type t ) +{ + if ( t == typ ) + return; + + typ = t; + createPixmap(); +} + +KColorAction::Type KColorAction::type() const +{ + return typ; +} + +void KColorAction::init() +{ + col = Qt::black; + createPixmap(); +} + +void KColorAction::createPixmap() +{ + int r, g, b; + QCString pix; + QCString line; + + col.rgb( &r, &g, &b ); + + pix = "/* XPM */\n"; + + pix += "static char * text_xpm[] = {\n"; + + switch ( typ ) { + case TextColor: { + pix += "\"20 20 11 1\",\n"; + pix += "\"h c #c0c000\",\n"; + pix += "\"g c #808000\",\n"; + pix += "\"f c #c0c0ff\",\n"; + pix += "\"a c #000000\",\n"; + pix += "\"d c #ff8000\",\n"; + pix += "\". c none\",\n"; + pix += "\"e c #0000c0\",\n"; + pix += "\"i c #ffff00\",\n"; + line.sprintf( "\"# c #%02X%02X%02X \",\n", r, g, b ); + pix += line.copy(); + pix += "\"b c #c00000\",\n"; + pix += "\"c c #ff0000\",\n"; + pix += "\"....................\",\n"; + pix += "\"....................\",\n"; + pix += "\"....................\",\n"; + pix += "\"........#...........\",\n"; + pix += "\"........#a..........\",\n"; + pix += "\".......###..........\",\n"; + pix += "\".......###a.........\",\n"; + pix += "\"......##aa#.........\",\n"; + pix += "\"......##a.#a........\",\n"; + pix += "\".....##a...#........\",\n"; + pix += "\".....#######a.......\",\n"; + pix += "\"....##aaaaaa#.......\",\n"; + pix += "\"....##a.....aaaaaaaa\",\n"; + pix += "\"...####....#abbccdda\",\n"; + pix += "\"....aaaa....abbccdda\",\n"; + pix += "\"............aee##ffa\",\n"; + pix += "\"............aee##ffa\",\n"; + pix += "\"............agghhiia\",\n"; + pix += "\"............agghhiia\",\n"; + pix += "\"............aaaaaaaa\"};\n"; + } break; + case FrameColor: { + pix += "\" 20 20 3 1 \",\n"; + + pix += "\" c none \",\n"; + pix += "\"+ c white \",\n"; + line.sprintf( "\". c #%02X%02X%02X \",\n", r, g, b ); + pix += line.copy(); + + pix += "\" \",\n"; + pix += "\" \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ...++++++++++... \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ................ \",\n"; + pix += "\" \",\n"; + pix += "\" \";\n"; + } break; + case BackgroundColor: { + pix += "\" 20 20 3 1 \",\n"; + + pix += "\" c none \",\n"; + pix += "\". c red \",\n"; + line.sprintf( "\"+ c #%02X%02X%02X \",\n", r, g, b ); + pix += line.copy(); + + pix += "\" \",\n"; + pix += "\" \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ..++++++++++++.. \",\n"; + pix += "\" ................ \",\n"; + pix += "\" ................ \",\n"; + pix += "\" \",\n"; + pix += "\" \";\n"; + } break; + } + + QPixmap pixmap( pix ); + setIconSet( QIconSet( pixmap ) ); +} + + +KSelectColorAction::KSelectColorAction( const QString& text, Type type, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) : + KAction( text, KShortcut(), receiver, slot, parent, name ), m_type( type ), + m_color( Qt::black ) +{ +} + +KSelectColorAction::~KSelectColorAction() +{ +} + +int KSelectColorAction::plug( QWidget* w, int index ) +{ + if (w == 0) { + kdWarning() << "KSelectColorAction::plug called with 0 argument\n"; + return -1; + } + if (kapp && !kapp->authorizeKAction(name())) + return -1; + + if ( w->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( w ); + int id; + + if ( hasIcon() ) + { + /* ###### CHECK: We're not allowed to specify the instance in iconSet() + KInstance *instance; + if ( parentCollection() ) + instance = parentCollection()->instance(); + else + instance = KGlobal::instance(); + */ + id = menu->insertItem( iconSet( KIcon::Small, 0 ), text(), this,//dsweet + SLOT( slotActivated() ), 0, -1, index ); + } + else + id = menu->insertItem( text(), this, SLOT( slotActivated() ), //dsweet + 0, -1, index ); + + 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 ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + if ( !whatsThis().isEmpty() ) + menu->setWhatsThis( id, whatsThisWithIcon() ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( parentCollection() ) + parentCollection()->connectHighlight( menu, this ); + + return containerCount() - 1; + } + else if ( w->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( w ); + + int id_ = getToolButtonID(); + KInstance *instance; + if ( parentCollection() ) + instance = parentCollection()->instance(); + else + instance = KGlobal::instance(); + + if ( icon().isEmpty() ) // old code using QIconSet directly + { + bar->insertButton( iconSet( KIcon::Small ).pixmap(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + isEnabled(), plainText(), index ); + } + else + bar->insertButton( icon(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + isEnabled(), plainText(), index, instance ); + + bar->getButton( id_ )->setName( QCString("toolbutton_")+name() ); + + if ( !whatsThis().isEmpty() ) + QWhatsThis::add( bar->getButton(id_), whatsThisWithIcon() ); + + if ( !toolTip().isEmpty() ) + QToolTip::add( bar->getButton(id_), toolTip() ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( parentCollection() ) + parentCollection()->connectHighlight( bar, this ); + + return containerCount() - 1; + } + + return -1; +} + +QColor KSelectColorAction::color() const +{ + return m_color; +} + +KSelectColorAction::Type KSelectColorAction::type() const +{ + return m_type; +} + +void KSelectColorAction::setColor( const QColor &/*c*/ ) +{ +} + +void KSelectColorAction::setType( Type /*t*/ ) +{ +} + +QString KSelectColorAction::whatsThisWithIcon() const +{ + QString text = whatsThis(); + if (!icon().isEmpty()) + return QString::fromLatin1("<img source=\"small|%1\"> %2").arg(icon()).arg(text); + return text; +} + +#include <kcoloractions.moc> diff --git a/lib/kofficeui/kcoloractions.h b/lib/kofficeui/kcoloractions.h new file mode 100644 index 00000000..b20be747 --- /dev/null +++ b/lib/kofficeui/kcoloractions.h @@ -0,0 +1,101 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2002 Werner Trobin <trobin@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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef kcoloractions_h +#define kcoloractions_h + +#include <kaction.h> + +/** + * An action whose pixmap is automatically generated from a color. + * It knows three types of pixmaps: text color, frame color and background color + */ +class KColorAction : public KAction +{ + Q_OBJECT + +public: + enum Type { + TextColor, + FrameColor, + BackgroundColor + }; + + // Create default (text) color action + KColorAction( const QString& text, int accel = 0, QObject* parent = 0, const char* name = 0 ); + KColorAction( const QString& text, int accel, + QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + KColorAction( QObject* parent = 0, const char* name = 0 ); + + // Create a color action of a given type + KColorAction( const QString& text, Type type, int accel = 0, + QObject* parent = 0, const char* name = 0 ); + KColorAction( const QString& text, Type type, int accel, + QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + virtual void setColor( const QColor &c ); + QColor color() const; + + virtual void setType( Type type ); + Type type() const; + +private: + void init(); + void createPixmap(); + + QColor col; + Type typ; +}; + + +class KSelectColorAction : public KAction +{ + Q_OBJECT +public: + enum Type { + TextColor, + LineColor, + FillColor + }; + + KSelectColorAction( const QString& text, Type type, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + virtual ~KSelectColorAction(); + + virtual int plug( QWidget* w, int index = -1 ); + + QColor color() const; + Type type() const; + +public slots: + virtual void setColor( const QColor &c ); + virtual void setType( Type t ); + +signals: + void colorSelected( const QColor& color ); + +private: + QString whatsThisWithIcon() const; // duplicated, as it's private in kaction + + Type m_type; + QColor m_color; +}; + +#endif diff --git a/lib/kofficeui/koffice.widgets b/lib/kofficeui/koffice.widgets new file mode 100644 index 00000000..9a3f0ba1 --- /dev/null +++ b/lib/kofficeui/koffice.widgets @@ -0,0 +1,32 @@ +[Global] +PluginName=KOfficeWidgets + +[KoBuggyUnitDoubleSpinBox] +ToolTip=KOffice Spin box for double precision numbers with unit display +WhatsThis=KOffice Spin box for double precision numbers with unit display +IncludeFile=koUnitWidgets.h +Group=Input (KOffice) + +[KoUnitDoubleSpinBox2] +ToolTip=KOffice Spin box for double precision numbers with unit display +WhatsThis=KOffice Spin box for double precision numbers with unit display +IncludeFile=koUnitWidgets.h +Group=Input (KOffice) + +[KoUnitDoubleLineEdit] +ToolTip=KOffice Line edit for double precision numbers with unit display +WhatsThis=KOffice Line edit for double precision numbers with unit display +IncludeFile=koUnitWidgets.h +Group=Input (KOffice) + +[KoUnitDoubleComboBox] +ToolTip=KOffice Combo box for double precision numbers with unit display +WhatsThis=KOffice Combo box for double precision numbers with unit display +IncludeFile=koUnitWidgets.h +Group=Input (KOffice) + +[KoUnitDoubleSpinComboBox] +ToolTip=KOffice Combo box (with spin control) for double precision numbers with unit display +WhatsThis=KOffice Combo box (with spin control) for double precision numbers with unit display +IncludeFile=koUnitWidgets.h +Group=Input (KOffice) diff --git a/lib/kofficeui/pics/Makefile.am b/lib/kofficeui/pics/Makefile.am new file mode 100644 index 00000000..a7f2e664 --- /dev/null +++ b/lib/kofficeui/pics/Makefile.am @@ -0,0 +1,12 @@ + +picsdir = $(kde_datadir)/koffice/pics +pics_DATA = koRulerFirst.png koRulerLeft.png koffice-logo.png \ + koKoolBarDown.png koKoolBarUp.png \ + koPortrait.png koLandscape.png + +kofficewidgetsdata_DATA = kounitdoublecombobox.png kounitdoublelineedit.png \ + kounitdoublespinbox2.png kounitdoublespincombobox.png + +kofficewidgetsdatadir = $(kde_datadir)/kofficewidgets/pics + +EXTRA_DIST = $(kofficewidgetsdata_DATA) diff --git a/lib/kofficeui/pics/koKoolBarDown.png b/lib/kofficeui/pics/koKoolBarDown.png Binary files differnew file mode 100644 index 00000000..621e4afd --- /dev/null +++ b/lib/kofficeui/pics/koKoolBarDown.png diff --git a/lib/kofficeui/pics/koKoolBarUp.png b/lib/kofficeui/pics/koKoolBarUp.png Binary files differnew file mode 100644 index 00000000..513f6a1d --- /dev/null +++ b/lib/kofficeui/pics/koKoolBarUp.png diff --git a/lib/kofficeui/pics/koLandscape.png b/lib/kofficeui/pics/koLandscape.png Binary files differnew file mode 100644 index 00000000..63daed42 --- /dev/null +++ b/lib/kofficeui/pics/koLandscape.png diff --git a/lib/kofficeui/pics/koPortrait.png b/lib/kofficeui/pics/koPortrait.png Binary files differnew file mode 100644 index 00000000..b0e28bdb --- /dev/null +++ b/lib/kofficeui/pics/koPortrait.png diff --git a/lib/kofficeui/pics/koRulerFirst.png b/lib/kofficeui/pics/koRulerFirst.png Binary files differnew file mode 100644 index 00000000..bc9957cf --- /dev/null +++ b/lib/kofficeui/pics/koRulerFirst.png diff --git a/lib/kofficeui/pics/koRulerLeft.png b/lib/kofficeui/pics/koRulerLeft.png Binary files differnew file mode 100644 index 00000000..0b117a04 --- /dev/null +++ b/lib/kofficeui/pics/koRulerLeft.png diff --git a/lib/kofficeui/pics/koffice-logo.png b/lib/kofficeui/pics/koffice-logo.png Binary files differnew file mode 100644 index 00000000..fd8e3a86 --- /dev/null +++ b/lib/kofficeui/pics/koffice-logo.png diff --git a/lib/kofficeui/pics/kounitdoublecombobox.png b/lib/kofficeui/pics/kounitdoublecombobox.png Binary files differnew file mode 100644 index 00000000..79efbbfa --- /dev/null +++ b/lib/kofficeui/pics/kounitdoublecombobox.png diff --git a/lib/kofficeui/pics/kounitdoublelineedit.png b/lib/kofficeui/pics/kounitdoublelineedit.png Binary files differnew file mode 100644 index 00000000..a3bce54a --- /dev/null +++ b/lib/kofficeui/pics/kounitdoublelineedit.png diff --git a/lib/kofficeui/pics/kounitdoublespinbox2.png b/lib/kofficeui/pics/kounitdoublespinbox2.png Binary files differnew file mode 100644 index 00000000..e1da718c --- /dev/null +++ b/lib/kofficeui/pics/kounitdoublespinbox2.png diff --git a/lib/kofficeui/pics/kounitdoublespincombobox.png b/lib/kofficeui/pics/kounitdoublespincombobox.png Binary files differnew file mode 100644 index 00000000..79efbbfa --- /dev/null +++ b/lib/kofficeui/pics/kounitdoublespincombobox.png diff --git a/lib/kofficeui/tests/Makefile.am b/lib/kofficeui/tests/Makefile.am new file mode 100644 index 00000000..2aa13645 --- /dev/null +++ b/lib/kofficeui/tests/Makefile.am @@ -0,0 +1,15 @@ +####### General stuff + +INCLUDES= -I$(srcdir)/.. $(KOFFICECORE_INCLUDES) $(all_includes) + +####### Files + +METASOURCES = AUTO + +check_PROGRAMS = # coloraction_test + +TESTS = + +#coloraction_test_SOURCES = coloraction_test.cpp +#coloraction_test_LDADD = ../libkofficeui.la + diff --git a/lib/kofficeui/tests/coloraction_test.cpp b/lib/kofficeui/tests/coloraction_test.cpp new file mode 100644 index 00000000..538f9707 --- /dev/null +++ b/lib/kofficeui/tests/coloraction_test.cpp @@ -0,0 +1,112 @@ +/* This file is part of the KDE project + Copyright (C) 1999 by Dirk A. Mueller <dmuell@gmx.net> + Copyright (C) 2002 Werner Trobin <trobin@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 <qlayout.h> +#include <qvgroupbox.h> +#include <qpopupmenu.h> +#include <qmenubar.h> + +#include <kdebug.h> +#include <ktoolbar.h> +#include <kiconloader.h> +#include <kapplication.h> +#include <KoTooluButton.h> +#include <coloraction_test.h> + +#include <stdlib.h> +#include <time.h> + + +TopLevel::TopLevel( QWidget* parent, const char* name) : QMainWindow( parent, name ) +{ + setCaption( QString::fromLatin1( "KColorAction test application" ) ); + + QWidget *w = new QWidget( this ); + setCentralWidget( w ); + + QBoxLayout* l = new QHBoxLayout( w, KDialog::marginHint(), KDialog::spacingHint() ); + QGroupBox* b1 = new QVGroupBox( QString::fromLatin1( "KoColorPanel 1" ), w ); + panel = new KoColorPanel( b1, "panel1" ); + connect( panel, SIGNAL( colorSelected( const QColor& ) ), SLOT( slotColorSelected( const QColor& ) ) ); + //panel->insertDefaultColors(); + l->addWidget( b1 ); + + b1 = new QVGroupBox( QString::fromLatin1( "KoColorPanel 2" ), w ); + + ( void ) new KoColorPanel( b1, "panel2" ); + l->addWidget( b1 ); + + QPopupMenu* file = new QPopupMenu( this ); + menuBar()->insertItem( "&File", file ); + + file->insertItem( "Custom + Default", KoColorPanel::createColorPopup( KoColorPanel::CustomColors, Qt::red, this, + SLOT( slotColorSelected( const QColor& ) ), file, "blah" ) ); + file->insertItem( "Custom", KoColorPanel::createColorPopup( KoColorPanel::CustomColors, QColor(), this, + SLOT( slotColorSelected( const QColor& ) ), file, "blah" ) ); + file->insertItem( "Plain + Default", KoColorPanel::createColorPopup( KoColorPanel::Plain, Qt::green, this, + SLOT( slotColorSelected( const QColor& ) ), file, "blah" ) ); + file->insertItem( "Plain", KoColorPanel::createColorPopup( KoColorPanel::Plain, QColor(), this, + SLOT( slotColorSelected( const QColor& ) ), file, "blah" ) ); + file->insertSeparator(); + file->insertItem( "Default Colors", this, SLOT( defaultColors() ), CTRL+Key_D ); + file->insertItem( "Insert Random Color", this, SLOT( insertRandomColor() ), CTRL+Key_R ); + file->insertSeparator(); + file->insertItem( "Clear", this, SLOT( clearColors() ), CTRL+Key_C ); + file->insertSeparator(); + file->insertItem( "&Quit", qApp, SLOT( closeAllWindows() ), CTRL+Key_Q ); + + KToolBar* toolBar = new KToolBar( this ); + addDockWindow( toolBar ); + ( void ) new KoToolButton( "color_fill", 1, toolBar, "funky button", "Fill Color" ); +} + +void TopLevel::insertRandomColor() +{ + panel->insertColor( qRgb( rand() % 256, rand() % 256, rand() % 256 ) ); +} + +void TopLevel::defaultColors() +{ + panel->insertDefaultColors(); +} + +void TopLevel::clearColors() +{ + panel->clear(); +} + +void TopLevel::slotColorSelected( const QColor& color ) +{ + kdDebug() << "#### selected: " << color.name() << endl; +} + + +int main( int argc, char ** argv ) +{ + srand( time( 0 ) ); + + KApplication a( argc, argv, "KColorAction Test" ); + TopLevel *toplevel = new TopLevel( 0, "coloractiontest" ); + a.setMainWidget( toplevel ); + toplevel->show(); + return a.exec(); +} + +#include <coloraction_test.moc> diff --git a/lib/kofficeui/tests/coloraction_test.h b/lib/kofficeui/tests/coloraction_test.h new file mode 100644 index 00000000..d29f9c5a --- /dev/null +++ b/lib/kofficeui/tests/coloraction_test.h @@ -0,0 +1,44 @@ +/* This file is part of the KDE project + Copyright (C) 1999 by Dirk A. Mueller <dmuell@gmx.net> + Copyright (C) 2002 Werner Trobin <trobin@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. +*/ + +#ifndef _COLORACTIONTEST_H +#define _COLORACTIONTEST_H + +#include <qmainwindow.h> + +class KoColorPanel; + +class TopLevel : public QMainWindow +{ + Q_OBJECT +public: + TopLevel( QWidget* parent = 0, const char* name = 0 ); + +public slots: + void insertRandomColor(); + void defaultColors(); + void clearColors(); + void slotColorSelected( const QColor& color ); + +private: + KoColorPanel* panel; +}; + +#endif // _COLORACTIONTEST_H diff --git a/lib/kofficeui/tkaction.cpp b/lib/kofficeui/tkaction.cpp new file mode 100644 index 00000000..f627df56 --- /dev/null +++ b/lib/kofficeui/tkaction.cpp @@ -0,0 +1,300 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include "tkaction.h" +#include "tktoolbarbutton.h" +#include "tkcombobox.h" + +#include <qlabel.h> +#include <qlayout.h> + +#include <ktoolbar.h> +#include <kiconloader.h> + +#define SET_FOR_ALL_CONTAINER(WIDGET_TYPE,METHOD_NAME,VALUE) \ + for( int id = 0; id < containerCount(); ++id ) { \ + QWidget* w = container(id); \ + if ( w->inherits("KToolBar") ) { \ + QWidget* r = static_cast<KToolBar*>(w)->getWidget(itemId(id)); \ + if (qstrcmp(r->name(),"KTToolBarLayout")==0) \ + r = (QWidget*)r->child("widget"); \ + if ( r && r->inherits(#WIDGET_TYPE) ) { \ + WIDGET_TYPE* b = static_cast<WIDGET_TYPE*>(r); \ + b->METHOD_NAME(VALUE); \ + } \ + } \ + } + +TKAction::TKAction(QObject* parent, const char* name) +: KAction( "", 0, parent, name ) +{ + m_imode = TK::IconOnly; +} + +TKAction::~TKAction() +{ +} + +int TKAction::plug(QWidget* widget, int index) +{ + if ( widget->inherits("KToolBar") ) { + KToolBar* bar = static_cast<KToolBar*>(widget); + int id_ = KAction::getToolButtonID(); + KInstance *instance; + + if ( parentCollection() ) + instance = parentCollection()->instance(); + else + instance = KGlobal::instance(); + + TKToolBarButton* b = new TKToolBarButton(icon(),plainText(),bar,name(),instance); + // we don't need clicked() and buttonClicked(), do we? + // connect(b,SIGNAL(clicked()),SLOT(slotActivated())); + b->setIconMode(m_imode); + initToolBarButton(b); + + bar->insertWidget( id_, 100, b, index ); + addContainer(bar,id_); + connect( bar, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + + return containerCount() - 1; + } + return KAction::plug(widget,index); +} + +void TKAction::initToolBarButton(TKToolBarButton* button) +{ + connect(button,SIGNAL(buttonClicked()),SLOT(slotActivated())); +} + +TK::IconMode TKAction::iconMode() +{ + return m_imode; +} + +void TKAction::setIconMode(TK::IconMode mode) +{ + m_imode = mode; + SET_FOR_ALL_CONTAINER(TKToolBarButton,setIconMode,mode) +} + +void TKAction::setText(const QString& text) +{ + KAction::setText(text); + updateLayout(); +} + +void TKAction::setIcon(const QString& icon) +{ + KAction::setIcon(icon); + updateLayout(); +} + +void TKAction::updateLayout() +{ + int len = containerCount(); + for( int id = 0; id < len; ++id ) { + QWidget* w = container( id ); + if (w->inherits("KToolBar")) { + QWidget* r = static_cast<KToolBar*>(w)->getWidget(itemId(id)); + if (qstrcmp(r->name(),"KTToolBarLayout")==0) { + updateLayout(r); + } + } + } +} + +QWidget* TKAction::createLayout(QWidget* parent, QWidget* children) +{ + QWidget* base = new QWidget(parent,"KTToolBarLayout"); + QLabel* textLabel = new QLabel(base,"text"); + textLabel->setMinimumHeight(1); + QLabel* pixLabel = new QLabel(base,"pixmap"); + children->reparent(base,QPoint(0,0)); + children->setName("widget"); + QHBoxLayout* layout = new QHBoxLayout(base,0,3); + layout->setResizeMode(QLayout::Minimum); + layout->addWidget(textLabel); + layout->addWidget(pixLabel); + layout->addWidget(children,1); + + updateLayout(base); + return base; +} + +void TKAction::updateLayout(QWidget* base) +{ + QLabel* textLabel = (QLabel*)base->child("text"); + QLabel* pixLabel = (QLabel*)base->child("pixmap"); + QWidget* w = (QWidget*)base->child("widget"); + + if (!textLabel || !pixLabel || !w) + return; + + if (!text().isEmpty() && m_imode != TK::IconOnly ) { + textLabel->setText(text()); + textLabel->show(); + } else + textLabel->hide(); + + QPixmap pix; + if (hasIcon()) + pix = iconSet(KIcon::Small).pixmap(); + + if (!icon().isEmpty()) + pix = BarIcon(icon()); + + if (!pix.isNull() && m_imode != TK::TextOnly) { + pixLabel->setPixmap(pix); + pixLabel->show(); + } else + pixLabel->hide(); + + base->setFixedWidth( w->sizeHint().width() + + (textLabel->isVisible() ? textLabel->sizeHint().width():0) + + (pixLabel->isVisible() ? pixLabel->sizeHint().width():0) ); +} +/******************************************************************************/ +TKBaseSelectAction::TKBaseSelectAction( QObject* parent, const char* name ) +: TKAction(parent,name) +{ + m_current = 0; + m_editable = false; +} + +TKBaseSelectAction::~TKBaseSelectAction() +{ +} + +int TKBaseSelectAction::plug(QWidget* widget, int index) +{ + if ( widget->inherits("KToolBar") ) + { + KToolBar* bar = static_cast<KToolBar*>( widget ); + int id_ = KAction::getToolButtonID(); + + TKComboBox* cb = new TKComboBox(m_editable,bar); + initComboBox(cb); + cb->setMinimumWidth( cb->sizeHint().width() ); + QWidget* base = createLayout(bar,cb); + + bar->insertWidget( id_, 100, base, index ); + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + setCurrentItem(currentItem()); + + return containerCount() - 1; + } + return -1; +} + +int TKBaseSelectAction::currentItem() +{ + return m_current; +} + +void TKBaseSelectAction::initComboBox(TKComboBox* cb) +{ + connect(cb,SIGNAL(activated(int)),SLOT(slotActivated(int))); +} + +void TKBaseSelectAction::setEditable(bool editable) +{ + m_editable = editable; + SET_FOR_ALL_CONTAINER(TKComboBox,setEditable,editable) +} + +bool TKBaseSelectAction::isEditable() +{ + return m_editable; +} + +void TKBaseSelectAction::setCurrentItem(int index) +{ + m_current = index; + SET_FOR_ALL_CONTAINER(TKComboBox,setCurrentItem,index) +} + +void TKBaseSelectAction::slotActivated(int id) +{ + if ( m_current == id ) + return; + + m_current = id; + setCurrentItem(id); + activate(id); +} + +void TKBaseSelectAction::activate(int id) +{ + emit activated(id); +} +/******************************************************************************/ +TKSelectAction::TKSelectAction( QObject* parent, const char* name ) +: TKBaseSelectAction(parent,name) +{ +} + +TKSelectAction::~TKSelectAction() +{ +} + +void TKSelectAction::initComboBox(TKComboBox* cb) +{ + TKBaseSelectAction::initComboBox(cb); + connect(cb,SIGNAL(activated(const QString&)),SLOT(slotActivated(const QString&))); + cb->insertStringList(items()); +} + +void TKSelectAction::slotActivated(const QString& text) +{ + emit activated(text); +} + +void TKSelectAction::setItems(const QStringList& lst ) +{ + m_list = lst; + m_current = -1; + + SET_FOR_ALL_CONTAINER(TKComboBox,clear, ) + SET_FOR_ALL_CONTAINER(TKComboBox,insertStringList,lst) + + // Disable if empty and not editable + setEnabled ( lst.count() > 0 || m_editable ); +} + +QStringList TKSelectAction::items() const +{ + return m_list; +} + +void TKSelectAction::clear() +{ + SET_FOR_ALL_CONTAINER(TKComboBox,clear, ) +} + +void TKSelectAction::setEditText(const QString& text) +{ + SET_FOR_ALL_CONTAINER(TKComboBox,setEditText,text) +} + +#undef SET_FOR_ALL_CONTAINER +#include "tkaction.moc" diff --git a/lib/kofficeui/tkaction.h b/lib/kofficeui/tkaction.h new file mode 100644 index 00000000..648ffc90 --- /dev/null +++ b/lib/kofficeui/tkaction.h @@ -0,0 +1,123 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef TKACTION_H +#define TKACTION_H + +#include <kaction.h> +#include <qstringlist.h> +#include <koffice_export.h> +namespace TK { + enum IconMode { IconOnly, IconAndText, TextOnly }; +} + +class TKToolBarButton; +class TKComboBox; + +class KOFFICEUI_EXPORT TKAction : public KAction +{ Q_OBJECT +public: + TKAction(QObject* parent, const char* name); + ~TKAction(); + + virtual int plug(QWidget* widget, int index = -1); + + TK::IconMode iconMode(); + +protected: + virtual void initToolBarButton(TKToolBarButton*); + + QWidget* createLayout(QWidget* parent, QWidget* children); + void updateLayout(); + virtual void updateLayout(QWidget*); + +public slots: + virtual void setIconMode(TK::IconMode); + void setText(const QString&); + void setIcon(const QString&); + +private: + TK::IconMode m_imode; + class TKActionPrivate; + TKActionPrivate *d; +}; +/******************************************************************************/ +class KOFFICEUI_EXPORT TKBaseSelectAction : public TKAction +{ Q_OBJECT +friend class TKSelectAction; +public: + TKBaseSelectAction(QObject* parent, const char* name); + ~TKBaseSelectAction(); + + virtual int plug(QWidget* widget, int index = -1); + + int currentItem(); + bool isEditable(); + + void activate(int); + +protected: + virtual void initComboBox(TKComboBox*); + +public slots: + virtual void setCurrentItem(int index); + virtual void setEditable(bool); + +protected slots: + virtual void slotActivated(int); + +signals: + void activated(int); + +private: + int m_current; + bool m_editable; + class TKBaseSelectActionPrivate; + TKBaseSelectActionPrivate *d; +}; +/******************************************************************************/ +class KOFFICEUI_EXPORT TKSelectAction : public TKBaseSelectAction +{ Q_OBJECT +public: + TKSelectAction(QObject* parent, const char* name); + ~TKSelectAction(); + + QStringList items() const; + +public slots: + virtual void setItems(const QStringList& ); + virtual void setEditText(const QString&); + virtual void clear(); + +protected: + virtual void initComboBox(TKComboBox*); + +protected slots: + void slotActivated(const QString&); + +signals: + void activated(const QString&); + +private: + QStringList m_list; + class TKSelectActionPrivate; + TKSelectActionPrivate *d; +}; +/******************************************************************************/ +#endif diff --git a/lib/kofficeui/tkcoloractions.cpp b/lib/kofficeui/tkcoloractions.cpp new file mode 100644 index 00000000..40859916 --- /dev/null +++ b/lib/kofficeui/tkcoloractions.cpp @@ -0,0 +1,621 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include "tkcoloractions.h" +#include "tktoolbarbutton.h" + +#include <qlayout.h> +#include <kcolordialog.h> +#include <ktoolbar.h> +#include <qpainter.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <klocale.h> +#include <kdebug.h> +#include <qapplication.h> + +TKColorPopupMenu::TKColorPopupMenu( QWidget* parent, const char* name ) +: KPopupMenu(parent,name) +{ +} + +TKColorPopupMenu::~TKColorPopupMenu() +{ +} + +void TKColorPopupMenu::updateItemSize() +{ + styleChange(style()); +} +/****************************************************************************************/ +class TKSelectColorActionPrivate +{ +public: + TKSelectColorActionPrivate() + { + } + bool defaultColorMenu; + QColor defaultColor; +}; + + +TKSelectColorAction::TKSelectColorAction( const QString& text, Type type, QObject* parent, const char* name, bool menuDefaultColor ) +: TKAction(parent,name) +{ + d=new TKSelectColorActionPrivate(); + d->defaultColorMenu=menuDefaultColor; + d->defaultColor=QColor(); + setText(text); + m_type = type; + init(); +} + +TKSelectColorAction::TKSelectColorAction( const QString& text, Type type, + QObject* receiver, const char* slot, + QObject* parent, const char* name, bool menuDefaultColor) +: TKAction(parent,name) +{ + d=new TKSelectColorActionPrivate(); + d->defaultColorMenu=menuDefaultColor; + d->defaultColor=QColor(); + setText(text); + m_type = type; + connect( this, SIGNAL( activated() ), receiver, slot ); + init(); +} + +void TKSelectColorAction::init() +{ + m_pStandardColor = new TKColorPanel(); + m_pRecentColor = new TKColorPanel(); + + connect(m_pStandardColor,SIGNAL(colorSelected(const QColor&)),SLOT(panelColorSelected(const QColor&))); + connect(m_pStandardColor,SIGNAL(reject()),SLOT(panelReject())); + connect(m_pRecentColor,SIGNAL(colorSelected(const QColor&)),SLOT(panelColorSelected(const QColor&))); + connect(m_pRecentColor,SIGNAL(reject()),SLOT(panelReject())); + + m_pRecentColor->clear(); + + m_pMenu = new TKColorPopupMenu(); + m_pMenu->insertItem(m_pStandardColor); + m_pMenu->insertSeparator(); + m_pMenu->insertItem(m_pRecentColor); + m_pMenu->insertSeparator(); + + switch (m_type) { + case TextColor: + m_pMenu->insertItem(i18n("More Text Colors..."),this,SLOT(selectColorDialog())); + setCurrentColor(black); + setIcon("textcolor"); + break; + case LineColor: + m_pMenu->insertItem(i18n("More Line Colors..."),this,SLOT(selectColorDialog())); + setCurrentColor(black); + setIcon("color_line"); + break; + case FillColor: + m_pMenu->insertItem(i18n("More Fill Colors..."),this,SLOT(selectColorDialog())); + setCurrentColor(white); + setIcon("color_fill"); + break; + case Color: + break; + } + if(d->defaultColorMenu) + { + m_pMenu->insertSeparator(); + m_pMenu->insertItem(i18n("Default Color"),this,SLOT(defaultColor())); + } + + connect(m_pStandardColor,SIGNAL(sizeChanged()),m_pMenu,SLOT(updateItemSize())); + connect(m_pRecentColor,SIGNAL(sizeChanged()),m_pMenu,SLOT(updateItemSize())); +} + +TKSelectColorAction::~TKSelectColorAction() +{ + delete m_pMenu; + delete d; +} + +void TKSelectColorAction::initToolBarButton(TKToolBarButton* b) +{ + QWhatsThis::add( b, whatsThis() ); + TKAction::initToolBarButton(b); + b->setDelayedPopup( popupMenu() ); + updatePixmap(b); + updatePixmap(); +} + +void TKSelectColorAction::defaultColor() +{ + m_pCurrentColor = d->defaultColor; + emit activated(); +} + +void TKSelectColorAction::setDefaultColor(const QColor &_col) +{ + d->defaultColor=_col; +} + +void TKSelectColorAction::updatePixmap() +{ + for( int id = 0; id < containerCount(); ++id ) { + QWidget* w = container(id); + if ( w->inherits("KToolBar") ) { + QWidget* r = static_cast<KToolBar*>(w)->getWidget(itemId(id)); + if ( r->inherits("TKToolBarButton") ) { + updatePixmap(static_cast<TKToolBarButton*>(r)); + } + } + else if(w->inherits("QPopupMenu") ) { + QPixmap pix =iconSet(KIcon::Small).pixmap(QIconSet::Automatic,QIconSet::Active); + if ( pix.isNull() ) + return; + QPainter p(&pix); + switch (m_type) { + case TextColor: + p.fillRect(QRect(0,12,16,5), m_pCurrentColor); + break; + case LineColor: + p.fillRect(QRect(0,13,16,5), m_pCurrentColor); + p.fillRect(QRect(3,12,1,1), m_pCurrentColor); + break; + case FillColor: + p.fillRect(QRect(0,13,16,5), m_pCurrentColor); + p.fillRect(QRect(1,10,5,3), m_pCurrentColor); + break; + case Color: + break; + } + p.end(); + setIconSet( pix ); + } + } +} + +void TKSelectColorAction::updatePixmap(TKToolBarButton* b) +{ + if (!b) + return; + // Not much point in painting with an invalid color + if (!m_pCurrentColor.isValid()) + return; + QPixmap pix =b->getActivePixmap(); + QPainter p(&pix); + switch (m_type) { + case TextColor: + p.fillRect(QRect(0,12,16,5), m_pCurrentColor); + break; + case LineColor: + p.fillRect(QRect(0,13,16,5), m_pCurrentColor); + p.fillRect(QRect(3,12,1,1), m_pCurrentColor); + break; + case FillColor: + p.fillRect(QRect(0,13,16,5), m_pCurrentColor); + p.fillRect(QRect(1,10,5,3), m_pCurrentColor); + break; + case Color: + break; + } + p.end(); + b->setPixmap(pix); +} + +void TKSelectColorAction::setCurrentColor( const QColor& color ) +{ + if ( color == m_pCurrentColor ) + return; + m_pCurrentColor = color; + setActiveColor( color ); + m_pRecentColor->setActiveColor(color ); + updatePixmap(); +} + +void TKSelectColorAction::setActiveColor( const QColor& color ) +{ + m_pStandardColor->setActiveColor(color); +} + +void TKSelectColorAction::selectColorDialog() +{ + QColor c = color(); + + if ( d->defaultColorMenu ) + { + if ( KColorDialog::getColor(c,d->defaultColor, qApp->activeWindow()) == QDialog::Accepted ) + { + setCurrentColor(c); + m_pRecentColor->insertColor(m_pCurrentColor); + activate(); + } + + } + else + { + if ( KColorDialog::getColor(c, qApp->activeWindow()) == QDialog::Accepted ) + { + setCurrentColor(c); + m_pRecentColor->insertColor(m_pCurrentColor); + activate(); + } + } +} + +// Called when activating the menu item +void TKSelectColorAction::slotActivated() +{ + //kdDebug() << "TKSelectColorAction::slotActivated" << endl; + selectColorDialog(); +} + +void TKSelectColorAction::activate() +{ + emit colorSelected(m_pCurrentColor); + emit activated(); +} + +void TKSelectColorAction::panelColorSelected( const QColor& color ) +{ + m_pMenu->hide(); + setCurrentColor(color); + + activate(); +} + +void TKSelectColorAction::panelReject() +{ + m_pMenu->hide(); +} + +class TKColorPanel::TKColorPanelPrivate +{ +public: + TKColorPanelPrivate() + { + panelCreated = false; + } + + bool panelCreated; +}; + +/****************************************************************************************/ +TKColorPanel::TKColorPanel( QWidget* parent, const char* name ) +: QWidget(parent,name) +{ + d = new TKColorPanel::TKColorPanelPrivate(); + m_activeColor = black; + + //m_iX = 0; // happens in setNumCols() -> resetGrid() + //m_iY = 0; // anyway, so... + + m_pLayout = 0L; + setNumCols(15); +} + +void TKColorPanel::setNumCols( int col ) +{ + m_iWidth = col; + resetGrid(); + + QDictIterator<TKColorPanelButton> it(m_pColorDict); + while ( it.current() ) { + addToGrid(it.current()); + ++it; + } +} + +TKColorPanel::~TKColorPanel() +{ + delete d; +} + +void TKColorPanel::resetGrid() +{ + m_iX = 0; + m_iY = 0; + + delete m_pLayout; + m_pLayout = new QGridLayout(this,0,m_iWidth+1,0,0); + + emit sizeChanged(); +} + +void TKColorPanel::clear() +{ + m_pColorDict.setAutoDelete(true); + m_pColorDict.clear(); + m_pColorDict.setAutoDelete(false); + d->panelCreated = true; // we don't want to create the default + // panel anymore now (b/c of recent colors) + resetGrid(); +} + +void TKColorPanel::insertColor( const QColor& color, const QString& text ) +{ + if (m_pColorDict[color.name()]) + return; + + insertColor(color); + QToolTip::add(m_pColorDict[color.name()],text); +} + +void TKColorPanel::insertColor( const QColor& color ) +{ + if (m_pColorDict[color.name()]) + return; + + m_pLayout->setMargin(3); + TKColorPanelButton* f = new TKColorPanelButton(color,this); + m_pColorDict.insert(color.name(),f); + if ( m_activeColor == color ) + f->setActive(true); + + connect(f,SIGNAL(selected(const QColor&)),SLOT(selected(const QColor&))); + + addToGrid(f); +} + +void TKColorPanel::addToGrid( TKColorPanelButton* f ) +{ + m_pLayout->addWidget(f,m_iY,m_iX); + f->show(); // yeehaaaw! ugly hack (Werner) + m_iX++; + if ( m_iX == m_iWidth ) { + m_iX = 0; + m_iY++; + } + emit sizeChanged(); +} + +void TKColorPanel::setActiveColor( const QColor& color ) +{ + TKColorPanelButton* b = m_pColorDict[m_activeColor.name()]; + if (b) + b->setActive(false); + + m_activeColor = color; + + b = m_pColorDict[m_activeColor.name()]; + if (b) + b->setActive(true); +} + +void TKColorPanel::mouseReleaseEvent( QMouseEvent* ) +{ + reject(); +} + +void TKColorPanel::showEvent( QShowEvent *e ) +{ + if ( !d->panelCreated ) + fillPanel(); + QWidget::showEvent(e); +} + +void TKColorPanel::selected( const QColor& color ) +{ + emit colorSelected(color); +} + +void TKColorPanel::fillPanel() +{ + d->panelCreated = true; + blockSignals(true); // don't emit sizeChanged() all the time + + // ### TODO: names without space (e.g. red) are lower case in rgb.txt + insertColor(QColor( 255, 0, 0 ), i18n( "color", "Red")); + insertColor(QColor( 255, 165, 0 ), i18n( "color", "Orange")); + insertColor(QColor( 255, 0, 255 ), i18n( "color", "Magenta")); + insertColor(QColor( 0, 0, 255 ), i18n( "color", "Blue")); + insertColor(QColor( 0, 255, 255 ), i18n( "color", "Cyan")); + insertColor(QColor( 0, 255, 0 ), i18n( "color", "Green")); + insertColor(QColor( 255, 255, 0 ), i18n( "color", "Yellow")); + insertColor(QColor( 165, 42, 42 ), i18n( "color", "Brown")); + insertColor(QColor( 139, 0, 0 ), i18n( "color", "DarkRed")); + insertColor(QColor( 255, 140, 0 ), i18n( "color", "DarkOrange")); + insertColor(QColor( 139, 0, 139 ), i18n( "color", "DarkMagenta")); + insertColor(QColor( 0, 0, 139 ), i18n( "color", "DarkBlue")); + insertColor(QColor( 0, 139, 139 ), i18n( "color", "DarkCyan")); + insertColor(QColor( 0, 100, 0 ), i18n( "color", "DarkGreen")); + insertColor(QColor( 130, 127, 0 ), i18n( "color", "DarkYellow")); // ### not in rgb.txt + + insertColor(QColor( 255, 255, 255 ), i18n( "color", "White")); + insertColor(QColor( 229, 229, 229 ), i18n( "color", "Gray 90%")); // ### not in rgb.txt + insertColor(QColor( 204, 204, 204 ), i18n( "color", "Gray 80%")); // ### not in rgb.txt + insertColor(QColor( 178, 178, 178 ), i18n( "color", "Gray 70%")); // ### not in rgb.txt + insertColor(QColor( 153, 153, 153 ), i18n( "color", "Gray 60%")); // ### not in rgb.txt + insertColor(QColor( 127, 127, 127 ), i18n( "color", "Gray 50%")); // ### not in rgb.txt + insertColor(QColor( 102, 102, 102 ), i18n( "color", "Gray 40%")); // ### not in rgb.txt + insertColor(QColor( 76, 76, 76 ), i18n( "color", "Gray 30%")); // ### not in rgb.txt + insertColor(QColor( 51, 51, 51 ), i18n( "color", "Gray 20%")); // ### not in rgb.txt + insertColor(QColor( 25, 25, 25 ), i18n( "color", "Gray 10%")); // ### not in rgb.txt + insertColor(QColor( 0, 0, 0 ), i18n( "color", "Black")); + + insertColor(QColor( 255, 255, 240 ), i18n( "color", "Ivory")); + insertColor(QColor( 255, 250, 250 ), i18n( "color", "Snow")); + insertColor(QColor( 245, 255, 250 ), i18n( "color", "MintCream")); + insertColor(QColor( 255, 250, 240 ), i18n( "color", "FloralWhite")); + insertColor(QColor( 255, 255, 224 ), i18n( "color", "LightYellow")); + insertColor(QColor( 240, 255, 255 ), i18n( "color", "Azure")); + insertColor(QColor( 248, 248, 255 ), i18n( "color", "GhostWhite")); + insertColor(QColor( 240, 255, 240 ), i18n( "color", "Honeydew")); + insertColor(QColor( 255, 245, 238 ), i18n( "color", "Seashell")); + insertColor(QColor( 240, 248, 255 ), i18n( "color", "AliceBlue")); + insertColor(QColor( 255, 248, 220 ), i18n( "color", "Cornsilk")); + insertColor(QColor( 255, 240, 245 ), i18n( "color", "LavenderBlush")); + insertColor(QColor( 253, 245, 230 ), i18n( "color", "OldLace")); + insertColor(QColor( 245, 245, 245 ), i18n( "color", "WhiteSmoke")); + insertColor(QColor( 255, 250, 205 ), i18n( "color", "LemonChiffon")); + insertColor(QColor( 224, 255, 255 ), i18n( "color", "LightCyan")); + insertColor(QColor( 250, 250, 210 ), i18n( "color", "LightGoldenrodYellow")); + insertColor(QColor( 250, 240, 230 ), i18n( "color", "Linen")); + insertColor(QColor( 245, 245, 220 ), i18n( "color", "Beige")); + insertColor(QColor( 255, 239, 213 ), i18n( "color", "PapayaWhip")); + insertColor(QColor( 255, 235, 205 ), i18n( "color", "BlanchedAlmond")); + insertColor(QColor( 250, 235, 215 ), i18n( "color", "AntiqueWhite")); + insertColor(QColor( 255, 228, 225 ), i18n( "color", "MistyRose")); + insertColor(QColor( 230, 230, 250 ), i18n( "color", "Lavender")); + insertColor(QColor( 255, 228, 196 ), i18n( "color", "Bisque")); + insertColor(QColor( 255, 228, 181 ), i18n( "color", "Moccasin")); + insertColor(QColor( 255, 222, 173 ), i18n( "color", "NavajoWhite")); + insertColor(QColor( 255, 218, 185 ), i18n( "color", "PeachPuff")); + insertColor(QColor( 238, 232, 170 ), i18n( "color", "PaleGoldenrod")); + insertColor(QColor( 245, 222, 179 ), i18n( "color", "Wheat")); + insertColor(QColor( 220, 220, 220 ), i18n( "color", "Gainsboro")); + insertColor(QColor( 240, 230, 140 ), i18n( "color", "Khaki")); + insertColor(QColor( 175, 238, 238 ), i18n( "color", "PaleTurquoise")); + insertColor(QColor( 255, 192, 203 ), i18n( "color", "Pink")); + insertColor(QColor( 238, 221, 130 ), i18n( "color", "LightGoldenrod")); + insertColor(QColor( 211, 211, 211 ), i18n( "color", "LightGray")); + insertColor(QColor( 255, 182, 193 ), i18n( "color", "LightPink")); + insertColor(QColor( 176, 224, 230 ), i18n( "color", "PowderBlue")); + insertColor(QColor( 127, 255, 212 ), i18n( "color", "Aquamarine")); + insertColor(QColor( 216, 191, 216 ), i18n( "color", "Thistle")); + insertColor(QColor( 173, 216, 230 ), i18n( "color", "LightBlue")); + insertColor(QColor( 152, 251, 152 ), i18n( "color", "PaleGreen")); + insertColor(QColor( 255, 215, 0 ), i18n( "color", "Gold")); + insertColor(QColor( 173, 255, 47 ), i18n( "color", "GreenYellow")); + insertColor(QColor( 176, 196, 222 ), i18n( "color", "LightSteelBlue")); + insertColor(QColor( 144, 238, 144 ), i18n( "color", "LightGreen")); + insertColor(QColor( 221, 160, 221 ), i18n( "color", "Plum")); + insertColor(QColor( 190, 190, 190 ), i18n( "color", "Gray")); + insertColor(QColor( 222, 184, 135 ), i18n( "color", "BurlyWood")); + insertColor(QColor( 135, 206, 250 ), i18n( "color", "LightSkyblue")); + insertColor(QColor( 255, 160, 122 ), i18n( "color", "LightSalmon")); + insertColor(QColor( 135, 206, 235 ), i18n( "color", "SkyBlue")); + insertColor(QColor( 210, 180, 140 ), i18n( "color", "Tan")); + insertColor(QColor( 238, 130, 238 ), i18n( "color", "Violet")); + insertColor(QColor( 244, 164, 96 ), i18n( "color", "SandyBrown")); + insertColor(QColor( 233, 150, 122 ), i18n( "color", "DarkSalmon")); + insertColor(QColor( 189, 183, 107 ), i18n( "color", "DarkKhaki")); + insertColor(QColor( 127, 255, 0 ), i18n( "color", "Chartreuse")); + insertColor(QColor( 169, 169, 169 ), i18n( "color", "DarkGray")); + insertColor(QColor( 124, 252, 0 ), i18n( "color", "LawnGreen")); + insertColor(QColor( 255, 105, 180 ), i18n( "color", "HotPink")); + insertColor(QColor( 250, 128, 114 ), i18n( "color", "Salmon")); + insertColor(QColor( 240, 128, 128 ), i18n( "color", "LightCoral")); + insertColor(QColor( 64, 224, 208 ), i18n( "color", "Turquoise")); + insertColor(QColor( 143, 188, 143 ), i18n( "color", "DarkSeagreen")); + insertColor(QColor( 218, 112, 214 ), i18n( "color", "Orchid")); + insertColor(QColor( 102, 205, 170 ), i18n( "color", "MediumAquamarine")); + insertColor(QColor( 255, 127, 80 ), i18n( "color", "Coral")); + insertColor(QColor( 154, 205, 50 ), i18n( "color", "YellowGreen")); + insertColor(QColor( 218, 165, 32 ), i18n( "color", "Goldenrod")); + insertColor(QColor( 72, 209, 204 ), i18n( "color", "MediumTurquoise")); + insertColor(QColor( 188, 143, 143 ), i18n( "color", "RosyBrown")); + insertColor(QColor( 219, 112, 147 ), i18n( "color", "PaleVioletRed")); + insertColor(QColor( 0, 250, 154 ), i18n( "color", "MediumSpringGreen")); + insertColor(QColor( 255, 99, 71 ), i18n( "color", "Tomato")); + insertColor(QColor( 0, 255, 127 ), i18n( "color", "SpringGreen")); + insertColor(QColor( 205, 133, 63 ), i18n( "color", "Peru")); + insertColor(QColor( 100, 149, 237 ), i18n( "color", "CornflowerBlue")); + insertColor(QColor( 132, 112, 255 ), i18n( "color", "LightSlateBlue")); + insertColor(QColor( 147, 112, 219 ), i18n( "color", "MediumPurple")); + insertColor(QColor( 186, 85, 211 ), i18n( "color", "MediumOrchid")); + insertColor(QColor( 95, 158, 160 ), i18n( "color", "CadetBlue")); + insertColor(QColor( 0, 206, 209 ), i18n( "color", "DarkTurquoise")); + insertColor(QColor( 0, 191, 255 ), i18n( "color", "DeepSkyblue")); + insertColor(QColor( 119, 136, 153 ), i18n( "color", "LightSlateGray")); + insertColor(QColor( 184, 134, 11 ), i18n( "color", "DarkGoldenrod")); + insertColor(QColor( 123, 104, 238 ), i18n( "color", "MediumSlateBlue")); + insertColor(QColor( 205, 92, 92 ), i18n( "color", "IndianRed")); + insertColor(QColor( 210, 105, 30 ), i18n( "color", "Chocolate")); + insertColor(QColor( 60, 179, 113 ), i18n( "color", "MediumSeaGreen")); + insertColor(QColor( 50, 205, 50 ), i18n( "color", "LimeGreen")); + insertColor(QColor( 32, 178, 170 ), i18n( "color", "LightSeaGreen")); + insertColor(QColor( 112, 128, 144 ), i18n( "color", "SlateGray")); + insertColor(QColor( 30, 144, 255 ), i18n( "color", "DodgerBlue")); + insertColor(QColor( 255, 69, 0 ), i18n( "color", "OrangeRed")); + insertColor(QColor( 255, 20, 147 ), i18n( "color", "DeepPink")); + insertColor(QColor( 70, 130, 180 ), i18n( "color", "SteelBlue")); + insertColor(QColor( 106, 90, 205 ), i18n( "color", "SlateBlue")); + insertColor(QColor( 107, 142, 35 ), i18n( "color", "OliveDrab")); + insertColor(QColor( 65, 105, 225 ), i18n( "color", "RoyalBlue")); + insertColor(QColor( 208, 32, 144 ), i18n( "color", "VioletRed")); + insertColor(QColor( 153, 50, 204 ), i18n( "color", "DarkOrchid")); + insertColor(QColor( 160, 32, 240 ), i18n( "color", "Purple")); + insertColor(QColor( 105, 105, 105 ), i18n( "color", "DimGray")); + insertColor(QColor( 138, 43, 226 ), i18n( "color", "BlueViolet")); + insertColor(QColor( 160, 82, 45 ), i18n( "color", "Sienna")); + insertColor(QColor( 199, 21, 133 ), i18n( "color", "MediumVioletRed")); + insertColor(QColor( 176, 48, 96 ), i18n( "color", "Maroon")); + insertColor(QColor( 46, 139, 87 ), i18n( "color", "SeaGreen")); + insertColor(QColor( 85, 107, 47 ), i18n( "color", "DarkOliveGreen")); + insertColor(QColor( 34, 139, 34 ), i18n( "color", "ForestGreen")); + insertColor(QColor( 139, 69, 19 ), i18n( "color", "SaddleBrown")); + insertColor(QColor( 148, 0, 211 ), i18n( "color", "DarkViolet")); + insertColor(QColor( 178, 34, 34 ), i18n( "color", "FireBrick")); + insertColor(QColor( 72, 61, 139 ), i18n( "color", "DarkSlateBlue")); + insertColor(QColor( 47, 79, 79 ), i18n( "color", "DarkSlateGray")); + insertColor(QColor( 25, 25, 112 ), i18n( "color", "MidnightBlue")); + insertColor(QColor( 0, 0, 205 ), i18n( "color", "MediumBlue")); + insertColor(QColor( 0, 0, 128 ), i18n( "color", "Navy")); + + blockSignals(false); // Signals allowed again + emit sizeChanged(); // one call should be enough ;) +} + +/****************************************************************************************/ +TKColorPanelButton::TKColorPanelButton( const QColor& color, QWidget* parent, const char* name ) +: QFrame(parent,name), m_Color(color), m_bActive(false) +{ + setFixedSize(16,16); + setFrameStyle( NoFrame ); +} + +TKColorPanelButton::~TKColorPanelButton() +{ +} + +void TKColorPanelButton::enterEvent( QEvent* ) +{ + if (!m_bActive) + setFrameStyle( Panel | Sunken ); +} + +void TKColorPanelButton::leaveEvent( QEvent* ) +{ + if (!m_bActive) + setFrameStyle( NoFrame ); +} + +void TKColorPanelButton::paintEvent( QPaintEvent* ev ) +{ + QFrame::paintEvent(ev); + + QPainter p(this,this); + p.fillRect(2,2,12,12,m_Color); + p.setPen(gray); + p.drawRect(2,2,12,12); + p.end(); +} + +void TKColorPanelButton::setActive( bool f ) +{ + m_bActive = f; + setFrameStyle( m_bActive ? Panel | Sunken : NoFrame ); +} + +void TKColorPanelButton::mouseReleaseEvent( QMouseEvent* ) +{ + emit selected(m_Color); +} +#include "tkcoloractions.moc" diff --git a/lib/kofficeui/tkcoloractions.h b/lib/kofficeui/tkcoloractions.h new file mode 100644 index 00000000..0d8179a1 --- /dev/null +++ b/lib/kofficeui/tkcoloractions.h @@ -0,0 +1,169 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef TKCOLORACTION_H +#define TKCOLORACTION_H + +#include "tkaction.h" +#include <koffice_export.h> +#include <kpopupmenu.h> +#include <qdict.h> + +class QGridLayout; +class TKColorPanel; +class TKSelectColorActionPrivate; + +class TKColorPopupMenu : public KPopupMenu +{ Q_OBJECT +public: + TKColorPopupMenu( QWidget* parent = 0, const char* name = 0 ); + ~TKColorPopupMenu(); + +public slots: + void updateItemSize(); +}; +/****************************************************************************************/ +class KOFFICEUI_EXPORT TKSelectColorAction : public TKAction +{ Q_OBJECT +public: + enum Type { + TextColor, + LineColor, + FillColor, + Color + }; + + TKSelectColorAction( const QString& text, Type type, QObject* parent, const char* name, bool menuDefaultColor=false); + TKSelectColorAction( const QString& text, Type type, + QObject* receiver, const char* slot, + QObject* parent, const char* name,bool menuDefaultColor=false ); + + virtual ~TKSelectColorAction(); + + QColor color() const { return m_pCurrentColor; } + + KPopupMenu* popupMenu() const { return m_pMenu; } + void setDefaultColor(const QColor &_col); + + +public slots: + void setCurrentColor( const QColor& ); + void setActiveColor( const QColor& ); + virtual void activate(); + +signals: + void colorSelected( const QColor& ); + +protected slots: + void selectColorDialog(); + void panelColorSelected( const QColor& ); + void panelReject(); + virtual void slotActivated(); + void defaultColor(); + +protected: + void init(); + virtual void initToolBarButton(TKToolBarButton*); + void updatePixmap(); + void updatePixmap(TKToolBarButton*); + +protected: + TKColorPopupMenu* m_pMenu; + TKColorPanel* m_pStandardColor; + TKColorPanel* m_pRecentColor; + int m_type; + + QColor m_pCurrentColor; + +private: + TKSelectColorActionPrivate *d; +}; +/****************************************************************************************/ +class TKColorPanelButton : public QFrame +{ Q_OBJECT +public: + TKColorPanelButton( const QColor&, QWidget* parent, const char* name = 0 ); + ~TKColorPanelButton(); + + void setActive( bool ); + + QColor panelColor() const { return m_Color; } + +signals: + void selected( const QColor& ); + +protected: + virtual void paintEvent( QPaintEvent* ); + virtual void enterEvent( QEvent* ); + virtual void leaveEvent( QEvent* ); + virtual void mouseReleaseEvent( QMouseEvent* ); + + QColor m_Color; + bool m_bActive; + +private: + class TKColorPanelButtonPrivate; + TKColorPanelButtonPrivate *d; +}; +/****************************************************************************************/ +class TKColorPanel : public QWidget +{ Q_OBJECT + +public: + TKColorPanel( QWidget* parent = 0L, const char* name = 0 ); + ~TKColorPanel(); + + void setActiveColor( const QColor& ); + void setNumCols( int col ); + void clear(); + +public slots: + void insertColor( const QColor& ); + void insertColor( const QColor&, const QString& ); + void selected( const QColor& ); + +signals: + void colorSelected( const QColor& ); + void reject(); + void sizeChanged(); + +protected: + void addToGrid( TKColorPanelButton* ); + void resetGrid(); + + virtual void mouseReleaseEvent( QMouseEvent* ); + virtual void showEvent( QShowEvent *e ); + + QGridLayout* m_pLayout; + int m_iWidth; + int m_iX; + int m_iY; + + QColor m_activeColor; + QDict<TKColorPanelButton> m_pColorDict; + +private: + void fillPanel(); + + class TKColorPanelPrivate; + TKColorPanelPrivate *d; +}; + +#endif diff --git a/lib/kofficeui/tkcombobox.cpp b/lib/kofficeui/tkcombobox.cpp new file mode 100644 index 00000000..525afb44 --- /dev/null +++ b/lib/kofficeui/tkcombobox.cpp @@ -0,0 +1,123 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include "tkcombobox.h" + +#include <qlistbox.h> +#include <qpainter.h> +#include <qstyle.h> +#include <qdrawutil.h> + +#include <kapplication.h> + +TKComboBox::TKComboBox(QWidget* parent, const char* name) +: QComboBox(false,parent,name) +{ +} + + +TKComboBox::TKComboBox( bool isEditable, QWidget* parent, const char* name ) +: QComboBox(isEditable,parent,name) +{ +} + +TKComboBox::~TKComboBox() +{ +} + +void TKComboBox::paintEvent(QPaintEvent*) +{ + QRect r; + if (editable()){ +#ifdef __GNUC__ +#warning "Left out for now, lacking a style expert (Werner)" +#endif + //r = QRect( style().comboButtonRect( 0, 0, width(), height() ) ); + r = QRect(4, 2, width()-height()-2, height()-4); + } else { + r = QRect(4, 2, width()-height()-2, height()-4); + } + int by = 2; + int bx = r.x() + r.width(); + int bw = width() - bx - 2; + int bh = height()-4; + + QPainter p( this ); + const QColorGroup& g = colorGroup(); + + QRect fr(2,2,width()-4,height()-4); + + if ( hasFocus()) { + p.fillRect( fr, g.brush( QColorGroup::Highlight ) ); + } else { + p.fillRect( fr, g.brush( QColorGroup::Base ) ); + } + + QRect r1(1,1,width()-1,height()-1); + qDrawShadePanel( &p, r1, g, true, 1 ); + + static const char* arrow_down[] = { + "7 7 2 1", + "X c Gray0", + " c None", + "XXXXXXX", + "XXXXXXX", + " ", + "XXXXXXX", + " XXXXX ", + " XXX ", + " X "}; + + QPixmap pixmap(arrow_down); + + + style().drawControl( QStyle::CE_PushButton, &p, this, QRect( bx, by, bw, bh ), colorGroup() ); + style().drawItem( &p, QRect( bx, by, bw, bh), AlignCenter, colorGroup(), isEnabled(), &pixmap, QString::null ); + + if ( hasFocus()) { + style().drawPrimitive( QStyle::PE_FocusRect, &p, fr, g ); + } + + if (!editable()) { + p.setClipRect(r); + p.setPen( g.text() ); + p.setBackgroundColor( g.background() ); + + if ( listBox()->item(currentItem()) ) { + QListBoxItem * item = listBox()->item(currentItem()); + const QPixmap *pix = item->pixmap(); + QString text = item->text(); + int x = r.x(); + if ( pix ) { + p.drawPixmap( x, r.y() + ( r.height() - pix->height() ) / 2 +1, *pix ); + x += pix->width()+3; + } + if (!text.isEmpty()) + p.drawText( x, r.y(), r.width()-x, r.height(), AlignLeft|AlignVCenter|SingleLine, text ); + } + } + p.end(); +} + +void TKComboBox::activate() +{ + emit activated(currentItem()); +} + +#include "tkcombobox.moc" diff --git a/lib/kofficeui/tkcombobox.h b/lib/kofficeui/tkcombobox.h new file mode 100644 index 00000000..8b036dd6 --- /dev/null +++ b/lib/kofficeui/tkcombobox.h @@ -0,0 +1,41 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef TKCOMBOBOX_H +#define TKCOMBOBOX_H + +#include <qcombobox.h> +class TKComboBox : public QComboBox +{ Q_OBJECT +public: + TKComboBox(QWidget* parent=0, const char* name=0); + TKComboBox(bool isEditable, QWidget* parent=0, const char* name=0); + ~TKComboBox(); + + void activate(); + +protected: + void paintEvent(QPaintEvent*); + +private: + class TKComboBoxPrivate; + TKComboBoxPrivate *d; +}; + +#endif diff --git a/lib/kofficeui/tktoolbarbutton.cpp b/lib/kofficeui/tktoolbarbutton.cpp new file mode 100644 index 00000000..b6baba1a --- /dev/null +++ b/lib/kofficeui/tktoolbarbutton.cpp @@ -0,0 +1,532 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include <tktoolbarbutton.h> + +#include <qtimer.h> +#include <qtooltip.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qdrawutil.h> +#include <qstyle.h> + +#include <kdeversion.h> +#include <kapplication.h> +#include <kiconeffect.h> +#include <kiconloader.h> +#include <kglobalsettings.h> + +// Delay in ms before delayed popup pops up +#define POPUP_DELAY 500 + +class TKToolBarButton::TKToolBarButtonPrivate +{ +public: + TKToolBarButtonPrivate() + { + m_iconMode = TK::IconOnly; + m_isPopup = false; + m_isToggle = false; + m_isOn = false; + m_isRaised = false; + m_autoRaised = true; + ignoreNextMousePress = false; + + m_text = QString::null; + m_iconName = QString::null; + m_arrowPressed = false; + m_delayTimer = 0L; + m_popup = 0L; + + m_disabledIconName = QString::null; + m_defaultIconName = QString::null; + + m_instance = KGlobal::instance(); + } + + ~TKToolBarButtonPrivate() + { + delete m_delayTimer; + m_delayTimer = 0; + } + + bool m_isPopup; + bool m_isToggle; + bool m_isOn; + bool m_isRaised; + bool m_autoRaised; + bool m_arrowPressed; + bool ignoreNextMousePress; + + QString m_text; + QString m_iconName; + QString m_disabledIconName; + QString m_defaultIconName; + + TK::IconMode m_iconMode; + + QTimer *m_delayTimer; + QPopupMenu *m_popup; + + KInstance *m_instance; +}; + +TKToolBarButton::TKToolBarButton( const QString& icon, const QString& txt, + QWidget* parent, const char* name, + KInstance *instance ) +: QToolButton(parent,name) +{ + d = new TKToolBarButtonPrivate; + d->m_text = txt; + d->m_instance = instance; + + setFocusPolicy( NoFocus ); + + connect(this, SIGNAL(clicked()), SLOT(slotClicked()) ); + connect(this, SIGNAL(pressed()), SLOT(slotPressed()) ); + connect(this, SIGNAL(released()), SLOT(slotReleased()) ); + + installEventFilter(this); + + setIcon(icon); + modeChange(); +} + +TKToolBarButton::TKToolBarButton( const QPixmap& pixmap, const QString& txt, QWidget* parent, const char* name ) +: QToolButton(parent,name ) +{ + d = new TKToolBarButtonPrivate; + d->m_text = txt; + + setFocusPolicy( NoFocus ); + + connect(this, SIGNAL(clicked()), SLOT(slotClicked()) ); + connect(this, SIGNAL(pressed()), SLOT(slotPressed()) ); + connect(this, SIGNAL(released()), SLOT(slotReleased()) ); + + installEventFilter(this); + + setPixmap(pixmap); + modeChange(); +} + +TKToolBarButton::~TKToolBarButton() +{ + delete d; +} + +QString TKToolBarButton::text() +{ + return d->m_text; +} + +void TKToolBarButton::modeChange() +{ + QToolTip::add(this,d->m_text); + + int border = 3; + int w = 2*border; + int h = 2*border; + + if (pixmap()) { + w += pixmap()->width(); + h = QMAX(h,pixmap()->height()+2*border); + if (d->m_iconMode == TK::IconAndText && !d->m_text.isEmpty()) + w += border; + } + + if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty()) + { + QFont tmp_font = KGlobalSettings::toolBarFont(); + QFontMetrics fm(tmp_font); + + h = QMAX(h,fm.lineSpacing()+2*border); + w += fm.width(d->m_text); + } + + if (d->m_popup && !d->m_isToggle) + w += 11; + + QSize size(w,h); + setMinimumSize(size); + + updateGeometry(); +} + +void TKToolBarButton::setEnabled( bool enabled ) +{ + if (isEnabled()==enabled) + return; + + QToolButton::setPixmap( (enabled ? defaultPixmap : disabledPixmap) ); + QToolButton::setEnabled( enabled ); +} + +void TKToolBarButton::setText( const QString& text) +{ + d->m_text = text; + repaint(false); +} + +void TKToolBarButton::setIcon( const QString& icon ) +{ + d->m_iconName = icon; + int iconSize = 16; + + setPixmap( BarIcon(icon, iconSize, KIcon::ActiveState, d->m_instance), false ); + setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) ); + setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) ); +} + +void TKToolBarButton::setDisabledIcon( const QString &icon ) +{ + d->m_disabledIconName = icon; + int iconSize = 16; + setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) ); +} + +void TKToolBarButton::setDefaultIcon( const QString &icon ) +{ + d->m_defaultIconName = icon; + int iconSize = 16; + setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) ); +} + +QPixmap TKToolBarButton::getActivePixmap() const +{ + return activePixmap; +} + +void TKToolBarButton::setPixmap( const QPixmap &pixmap ) +{ + setPixmap( pixmap, true ); +} + +void TKToolBarButton::setPixmap( const QPixmap &pixmap, bool generate ) +{ + activePixmap = pixmap; + + if ( generate ) + { + makeDefaultPixmap(); + makeDisabledPixmap(); + } + else + { + if (defaultPixmap.isNull()) + defaultPixmap = activePixmap; + if (disabledPixmap.isNull()) + disabledPixmap = activePixmap; + } + + QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap ); +} + +void TKToolBarButton::setDefaultPixmap( const QPixmap &pixmap ) +{ + defaultPixmap = pixmap; + QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap ); +} + +void TKToolBarButton::setDisabledPixmap( const QPixmap &pixmap ) +{ + disabledPixmap = pixmap; + QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap ); +} + +void TKToolBarButton::setPopup(QPopupMenu *p) +{ + d->m_popup = p; + d->m_popup->setFont(KGlobalSettings::toolBarFont()); + p->installEventFilter(this); + + modeChange(); +} + +QPopupMenu *TKToolBarButton::popup() +{ + return d->m_popup; +} + +void TKToolBarButton::setDelayedPopup (QPopupMenu *p, bool toggle ) +{ + d->m_isPopup = true; + setToggle(toggle); + + if (!d->m_delayTimer) { + d->m_delayTimer = new QTimer(this); + connect(d->m_delayTimer, SIGNAL(timeout()), this, SLOT(slotDelayTimeout())); + } + + setPopup(p); +} + +void TKToolBarButton::setRaised(bool f) +{ + d->m_isRaised = f; + repaint(false); +} + +void TKToolBarButton::setAutoRaised(bool f) +{ + d->m_autoRaised = f; +} + +void TKToolBarButton::leaveEvent(QEvent *) +{ + if (!d->m_isToggle && !(d->m_popup && d->m_popup->isVisible()) ) { + QToolButton::setPixmap(isEnabled() ? defaultPixmap : disabledPixmap); + if (d->m_autoRaised) + setRaised(false); + } +} + +void TKToolBarButton::enterEvent(QEvent *) +{ + if (!d->m_isToggle) { + if (isEnabled()) { + QToolButton::setPixmap(activePixmap); + if (d->m_autoRaised) + setRaised(true); + } else { + QToolButton::setPixmap(disabledPixmap); + } + repaint(false); + } +} + +bool TKToolBarButton::eventFilter(QObject *o, QEvent *ev) +{ + if ( o == this ) + if (ev->type() == QEvent::MouseButtonPress && d->m_popup && d->m_isPopup ) { + if (!d->m_isToggle) { + d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) ); + } else { + d->m_delayTimer->start(POPUP_DELAY); + } + } + + if ( o == d->m_popup) { + switch (ev->type()) + { + case QEvent::Show: + on(true); + return false; + case QEvent::Hide: + on(false); + setDown(false); + if ( !geometry().contains(parentWidget()->mapFromGlobal(QCursor::pos())) ) + leaveEvent(0L); + return false; + break; + case QEvent::MouseButtonPress: { + d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) ); + d->ignoreNextMousePress = d->m_arrowPressed; + break; + } + default: + break; + } + } + return false; +} + +void TKToolBarButton::drawButton( QPainter* p ) +{ +#define DRAW_PIXMAP_AND_TEXT \ + int x = 3;\ + if (pixmap()) {\ + style().drawItem( p, QRect( x, 0, pixmap()->width(), height() ), AlignCenter, colorGroup(), isEnabled(), pixmap(), QString::null );\ + if (d->m_iconMode==TK::IconAndText && !d->m_text.isEmpty()) {\ + x += pixmap()->width() + 3;\ + }\ + }\ + if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty()) {\ + QFontMetrics fm(KGlobalSettings::toolBarFont());\ + style().drawItem( p, QRect( x, 0, fm.width(d->m_text), height() ), AlignCenter, colorGroup(), isEnabled(), 0, d->m_text );\ + } + + const char* arrow[] = { + "7 4 2 1", + "# c Black", + ". c None", + "#######", + ".#####.", + "..###..", + "...#..."}; + QPixmap arrow_pix(arrow); + bool f = d->m_isOn || isDown(); + + if (d->m_popup && !d->m_isToggle) + { + if (d->m_isPopup) + { + QStyle::SFlags flags = QStyle::Style_Default; + if (isEnabled()) flags |= QStyle::Style_Enabled; + if (isOn()) flags |= QStyle::Style_On; + if (d->m_isRaised) flags |= QStyle::Style_Raised; + if (hasFocus()) flags |= QStyle::Style_HasFocus; + + style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( 0, 0, width()-12, height() ), colorGroup(), flags, QStyle::SC_ToolButton ); + style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( width()-13, 0, 13, height() ), colorGroup(), flags, QStyle::SC_ToolButton ); + style().drawItem( p, QRect( width()-13, 0, 13, height() ), AlignCenter, colorGroup(), isEnabled(), &arrow_pix, QString::null ); + if ( d->m_isRaised ) + qDrawShadeLine( p, width()-12, 0, width()-12, height(), colorGroup(), true ); + DRAW_PIXMAP_AND_TEXT + } else { + style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f ); + DRAW_PIXMAP_AND_TEXT + int z = f ? 1:0; + p->drawPixmap(width()-11+z,(height()-4)/2+z ,arrow_pix); + } + } else { + style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f ); + DRAW_PIXMAP_AND_TEXT + } +} + +void TKToolBarButton::paletteChange(const QPalette &) +{ + makeDisabledPixmap(); + if ( !isEnabled() ) + QToolButton::setPixmap( disabledPixmap ); + else + QToolButton::setPixmap( defaultPixmap ); + repaint(false); +} + +void TKToolBarButton::makeDefaultPixmap() +{ + if (activePixmap.isNull()) + return; + + KIconEffect effect; + defaultPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DefaultState); +} + +void TKToolBarButton::makeDisabledPixmap() +{ + if (activePixmap.isNull()) + return; + + KIconEffect effect; + disabledPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DisabledState); +} + +QSize TKToolBarButton::sizeHint() const +{ + return minimumSize(); +} + +QSize TKToolBarButton::minimumSizeHint() const +{ + return minimumSize(); +} + +void TKToolBarButton::showMenu() +{ + QPoint p ( mapToGlobal( QPoint( 0, 0 ) ) ); + const int deskHeight = KGlobalSettings::desktopGeometry(this).height(); + if ( p.y() + height() + d->m_popup->height() > deskHeight ) + p.setY( p.y() - d->m_popup->height() ); + else + p.setY( p.y() + height( )); + + d->m_popup->popup(p); +} + +void TKToolBarButton::slotDelayTimeout() +{ + d->m_delayTimer->stop(); + showMenu(); +} + +void TKToolBarButton::slotClicked() +{ + if ( d->ignoreNextMousePress ) { + d->ignoreNextMousePress=false; + return; + } + + if (d->m_popup && !d->m_isPopup) + showMenu(); + else + emit buttonClicked(); +} + +void TKToolBarButton::slotPressed() +{ + if ( d->ignoreNextMousePress ) + return; + + if (d->m_popup) { + if (!d->m_isPopup || d->m_isPopup && d->m_arrowPressed) + showMenu(); + } + else + emit buttonPressed(); + + d->ignoreNextMousePress = false; +} + +void TKToolBarButton::slotReleased() +{ + if (d->m_popup && d->m_isPopup) + d->m_delayTimer->stop(); + + emit buttonReleased(); +} + +void TKToolBarButton::slotToggled() +{ + emit buttonToggled(); +} + +void TKToolBarButton::on(bool flag) +{ + d->m_isOn = flag; + repaint(); +} + +void TKToolBarButton::toggle() +{ + on(!d->m_isOn); +} + +void TKToolBarButton::setToggle(bool flag) +{ + d->m_isToggle = flag; + if (flag == true) + connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); + else + disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); + + modeChange(); + repaint(); +} + +void TKToolBarButton::setIconMode( TK::IconMode m ) +{ + d->m_iconMode = m; + modeChange(); + repaint(); +} + +#include <tktoolbarbutton.moc> diff --git a/lib/kofficeui/tktoolbarbutton.h b/lib/kofficeui/tktoolbarbutton.h new file mode 100644 index 00000000..a4724672 --- /dev/null +++ b/lib/kofficeui/tktoolbarbutton.h @@ -0,0 +1,227 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000 theKompany.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef TKTOOLBARBUTTON_H +#define TKTOOLBARBUTTON_H + +#include <tkaction.h> + +#include <qpixmap.h> +#include <qtoolbutton.h> +#include <kglobal.h> + +class KToolBar; +class KInstance; +class QPopupMenu; +class QPainter; + +class TKToolBarButton : public QToolButton +{ Q_OBJECT +public: + TKToolBarButton(const QString& icon, const QString& txt, + QWidget* parent = 0, const char *name=0L, + KInstance *_instance = KGlobal::instance()); + + TKToolBarButton(const QPixmap&, const QString&, QWidget* parent=0, const char* name=0); + ~TKToolBarButton(); + + void setIconMode(TK::IconMode); + void setRaised(bool); + void setAutoRaised(bool); + + /** + * Enable/Disable this button + * + * @param enable Defaults to true + */ + void setEnabled(bool enable = true); + + /** + * 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 + */ + virtual void setPixmap(const QPixmap &pixmap); + + /** + * Set the pixmap directly for this button. This pixmap should be + * the active one.. however, the disabled and default pixmaps will + * only be constructed if @ref #generate is true. In any event, + * don't use this function unless you are positive that you don't + * want to use @ref setIcon. + * + * @param pixmap The active pixmap + * @param generate If true, then the other pixmaps will be + * automatically generated using configurable effects + */ + virtual void setPixmap(const QPixmap &pixmap, bool generate); + + /** + * 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 + */ + virtual void setDefaultPixmap(const QPixmap& pixmap); + + /** + * Force the button to use this pixmap when disabled one rather then + * generating it using effects. + * + * @param pixmap The pixmap to use when disabled + */ + virtual void setDisabledPixmap(const QPixmap& pixmap); + + /** + * 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); + QString text(); + + /** + * Set the icon for this button. This icon should be the active + * one... the dimmed and disabled icons are constructed based on + * this one. The actual pixmap will be loaded internally. This + * function is preferred over @ref setPixmap + * + * @param icon The name of the active pixmap + */ + virtual void setIcon(const QString &icon); + + /** + * 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 + */ + virtual void setDefaultIcon(const QString& icon); + + /** + * Force the button to use this icon when disabled one rather then + * generating it using effects. + * + * @param icon The icon to use when disabled + */ + virtual void setDisabledIcon(const QString& icon); + + /** + * 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(); + + /** + * 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); + + /** + * 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. You can also make the poup-menu + * "sticky", i.e. visible until a selection is made or the mouse is + * clikced elsewhere, by simply setting the second argument to true. + * This "sticky" button feature allows you to make a selection without + * having to press and hold down the mouse while making a selection. + * + * @param p the new popup menu + * @param toggle if true, makes the button "sticky" (toggled) + */ + void setDelayedPopup(QPopupMenu *p, bool toggle = false); + + QPixmap getActivePixmap() const; + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + +signals: + void buttonClicked(); + void buttonPressed(); + void buttonReleased(); + void buttonToggled(); + +public slots: + void modeChange(); + +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(); + + void makeDefaultPixmap(); + void makeDisabledPixmap(); + bool arrowPressed( const QPoint& pos ) { + int x = pos.x(); + int y = pos.y(); + return (x > width() - 12 && x <= width() && y > 0 && y < height()); + } + +private: + QPixmap defaultPixmap; + QPixmap activePixmap; + QPixmap disabledPixmap; + virtual void setIcon(const QPixmap &p) { QButton::setIcon(p); } + class TKToolBarButtonPrivate; + TKToolBarButtonPrivate *d; + + +protected slots: + void slotClicked(); + void slotPressed(); + void slotReleased(); + void slotToggled(); + void slotDelayTimeout(); +}; + +#endif |