You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6168 lines
173 KiB
6168 lines
173 KiB
/* This file is part of the KDE project
|
|
|
|
Copyright 2006 Robert Knight <robertknight@gmail.com>
|
|
Copyright 2006 Inge Wallin <inge@lysator.liu.se>
|
|
Copyright 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
|
|
Copyright 1999-2002,2004 Laurent Montel <montel@kde.org>
|
|
Copyright 2002-2005 Ariya Hidayat <ariya@kde.org>
|
|
Copyright 1999-2004 David Faure <faure@kde.org>
|
|
Copyright 2004-2005 Meni Livne <livne@kde.org>
|
|
Copyright 2001-2003 Philipp Mueller <philipp.mueller@gmx.de>
|
|
Copyright 2002-2003 Norbert Andres <nandres@web.de>
|
|
Copyright 2003 Hamish Rodda <rodda@kde.org>
|
|
Copyright 2003 Joseph Wenninger <jowenn@kde.org>
|
|
Copyright 2003 Lukas Tinkl <lukas@kde.org>
|
|
Copyright 2000-2002 Werner Trobin <trobin@kde.org>
|
|
Copyright 2002 Harri Porten <porten@kde.org>
|
|
Copyright 2002 John Dailey <dailey@vt.edu>
|
|
Copyright 2002 Daniel Naber <daniel.naber@t-online.de>
|
|
Copyright 1999-2000 Torben Weis <weis@kde.org>
|
|
Copyright 1999-2000 Stephan Kulow <coolo@kde.org>
|
|
Copyright 2000 Bernd Wuebben <wuebben@kde.org>
|
|
Copyright 2000 Wilco Greven <greven@kde.org>
|
|
Copyright 2000 Simon Hausmann <hausmann@kde.org
|
|
Copyright 1999 Michael Reiher <michael.reiher.gmx.de>
|
|
Copyright 1999 Boris Wedl <boris.wedl@kfunigraz.ac.at>
|
|
Copyright 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 <assert.h>
|
|
#include <float.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <tqapplication.h>
|
|
#include <tqbuffer.h>
|
|
#include <tqclipboard.h>
|
|
#include <tqdrawutil.h>
|
|
#include <tqlabel.h>
|
|
#include <tqpoint.h>
|
|
#include <tqscrollbar.h>
|
|
#include <tqtimer.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqwidgetlist.h>
|
|
|
|
#include <kcursor.h>
|
|
#include <kdebug.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdemultipledrag.h>
|
|
#include <krun.h>
|
|
#include <kmimetype.h>
|
|
#include <ksharedptr.h>
|
|
#include <kwordwrap.h>
|
|
|
|
#include <KoOasisStore.h>
|
|
#include <KoSpeaker.h>
|
|
#include <KoStore.h>
|
|
#include <KoStoreDrag.h>
|
|
#include <KoXmlWriter.h>
|
|
#include <KoDocumentChild.h>
|
|
#include <KoRect.h>
|
|
|
|
#include "commands.h"
|
|
#include "kspread_doc.h"
|
|
#include "kspread_editors.h"
|
|
#include "kspread_global.h"
|
|
#include "kspread_locale.h"
|
|
#include "kspread_map.h"
|
|
#include "kspread_sheet.h"
|
|
#include "kspread_undo.h"
|
|
#include "kspread_util.h"
|
|
#include "kspread_view.h"
|
|
#include "selection.h"
|
|
|
|
#include "kspread_canvas.h"
|
|
|
|
// TODO Stefan: undefine/remove, if non-contiguous selections don't work
|
|
// properly or if we are sure, that they do. ;-)
|
|
#define NONCONTIGUOUSSELECTION
|
|
|
|
#define MIN_SIZE 10
|
|
|
|
using namespace KSpread;
|
|
|
|
class Canvas::Private
|
|
{
|
|
public:
|
|
ComboboxLocationEditWidget *posWidget;
|
|
KSpread::EditWidget *editWidget;
|
|
KSpread::CellEditor *cellEditor;
|
|
|
|
View *view;
|
|
TQTimer* scrollTimer;
|
|
|
|
// Non visible range left from current screen
|
|
// Example: If the first visible column is 'E', then xOffset stores
|
|
// the width of the invisible columns 'A' to 'D'.
|
|
double xOffset;
|
|
|
|
// Non visible range on top of the current screen
|
|
// Example: If the first visible row is '5', then yOffset stores
|
|
// the height of the invisible rows '1' to '4'.
|
|
double yOffset;
|
|
|
|
// Used to draw the grey grid that is usually only visible on the
|
|
// screen, but not by printing on paper.
|
|
TQPen defaultGridPen;
|
|
|
|
// see setLastEditorWithFocus, lastEditorWithFocus
|
|
Canvas::EditorType focusEditorType;
|
|
|
|
TQLabel *validationInfo;
|
|
|
|
// true if the user is to choose a cell.
|
|
bool chooseCell;
|
|
|
|
// True when the mouse button is pressed
|
|
bool mousePressed;
|
|
|
|
// If the user is dragging around with the mouse then this tells us what he is doing.
|
|
// The user may want to mark cells or he started in the lower right corner
|
|
// of the marker which is something special. The values for the 2 above
|
|
// methods are called 'Mark' and 'ResizeCell' or 'AutoFill' depending
|
|
// on the mouse button used. By default this variable holds
|
|
// the value 'NoAction'.
|
|
Canvas::MouseActions mouseAction;
|
|
|
|
// If we use the lower right corner of the marker to start autofilling, then this
|
|
// rectangle conatins all cells that were already marker when the user started
|
|
// to mark the rectangle which he wants to become autofilled.
|
|
TQRect autoFillSource;
|
|
|
|
// Start coordinates for drag and drop
|
|
TQPoint dragStart;
|
|
bool dragging;
|
|
|
|
// Used to indicate whether the user started drawing a rubber band rectangle
|
|
bool rubberBandStarted;
|
|
TQPoint rubberBandStart;
|
|
TQPoint rubberBandEnd;
|
|
|
|
// If the mouse is over some anchor ( in the sense of HTML anchors )
|
|
TQString anchor;
|
|
|
|
bool mouseSelectedObject;
|
|
bool drawContour;
|
|
ModifyType modType;
|
|
/**
|
|
* Saves the last mouse position during mouse move events.
|
|
*/
|
|
TQPoint m_savedMousePos;
|
|
|
|
//---- stuff needed for resizing ----
|
|
/// object which gets resized
|
|
EmbeddedObject *m_resizeObject;
|
|
/// ratio of the object ( width / height )
|
|
double m_ratio;
|
|
bool m_isResizing;
|
|
/// The last position of the mouse during moving
|
|
KoPoint m_origMousePos;
|
|
|
|
//---- stuff needed for moving ----
|
|
bool m_isMoving;
|
|
KoPoint m_moveStartPoint;
|
|
|
|
/// size of the object at when resizing is started
|
|
KoRect m_rectBeforeResize;
|
|
/// Start position for move with mouse
|
|
KoPoint m_moveStartPosMouse;
|
|
|
|
/// object which is selected and should be shown above all the other objects
|
|
EmbeddedObject * m_objectDisplayAbove;
|
|
|
|
// bool mouseOverHighlightRangeSizeGrip;
|
|
|
|
// The row and column of 1) the last cell under mouse pointer, 2) the last focused cell, and
|
|
// the last spoken cell.
|
|
int prevSpokenPointerRow;
|
|
int prevSpokenPointerCol;
|
|
int prevSpokenFocusRow;
|
|
int prevSpokenFocusCol;
|
|
int prevSpokenRow;
|
|
int prevSpokenCol;
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************
|
|
*
|
|
* Canvas
|
|
*
|
|
****************************************************************/
|
|
|
|
Canvas::Canvas (View *_view)
|
|
: TQWidget( _view, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase )
|
|
{
|
|
d = new Private;
|
|
|
|
d->cellEditor = 0;
|
|
d->chooseCell = false;
|
|
d->validationInfo = 0L;
|
|
|
|
TQWidget::setFocusPolicy( TQWidget::StrongFocus );
|
|
|
|
d->dragStart = TQPoint( -1, -1 );
|
|
d->dragging = false;
|
|
|
|
|
|
d->defaultGridPen.setColor( lightGray );
|
|
d->defaultGridPen.setWidth( 1 );
|
|
d->defaultGridPen.setStyle( Qt::SolidLine );
|
|
|
|
d->xOffset = 0.0;
|
|
d->yOffset = 0.0;
|
|
d->view = _view;
|
|
// m_eAction = DefaultAction;
|
|
d->mouseAction = NoAction;
|
|
d->rubberBandStarted = false;
|
|
// m_bEditDirtyFlag = false;
|
|
|
|
//Now built afterwards(David)
|
|
//d->editWidget = d->view->editWidget();
|
|
d->posWidget = d->view->posWidget();
|
|
|
|
setBackgroundMode( PaletteBase );
|
|
|
|
setMouseTracking( true );
|
|
d->mousePressed = false;
|
|
d->mouseSelectedObject = false;
|
|
d->drawContour = false;
|
|
d->modType = MT_NONE;
|
|
|
|
d->m_resizeObject = 0L;
|
|
d->m_ratio = 0.0;
|
|
d->m_isMoving = false;
|
|
d->m_objectDisplayAbove = 0;
|
|
d->m_isResizing = false;
|
|
|
|
d->prevSpokenPointerRow = -1;
|
|
d->prevSpokenPointerCol = -1;
|
|
d->prevSpokenFocusRow = -1;
|
|
d->prevSpokenFocusCol = -1;
|
|
d->prevSpokenRow = -1;
|
|
d->prevSpokenCol = -1;
|
|
|
|
d->scrollTimer = new TQTimer( this );
|
|
connect (d->scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) );
|
|
|
|
if( d->view)
|
|
{
|
|
connect( d->view, TQT_SIGNAL( autoScroll( const TQPoint & )), this, TQT_SLOT( slotAutoScroll( const TQPoint &)));
|
|
}
|
|
if (kospeaker)
|
|
{
|
|
connect (kospeaker, TQT_SIGNAL(customSpeakWidget(TQWidget*, const TQPoint&, uint)),
|
|
this, TQT_SLOT(speakCell(TQWidget*, const TQPoint&, uint)));
|
|
}
|
|
|
|
setFocus();
|
|
installEventFilter( this );
|
|
(void)new ToolTip( this );
|
|
setAcceptDrops( true );
|
|
setInputMethodEnabled( true ); // ensure using the InputMethod
|
|
|
|
setWFlags(TQt::WNoAutoErase);
|
|
}
|
|
|
|
Canvas::~Canvas()
|
|
{
|
|
delete d->scrollTimer;
|
|
delete d->validationInfo;
|
|
delete d;
|
|
}
|
|
|
|
KSpread::View* Canvas::view() const
|
|
{
|
|
return d->view;
|
|
}
|
|
|
|
Doc* Canvas::doc() const
|
|
{
|
|
return d->view->doc();
|
|
}
|
|
|
|
void Canvas::setEditWidget( KSpread::EditWidget * ew )
|
|
{
|
|
d->editWidget = ew;
|
|
}
|
|
|
|
KSpread::EditWidget* Canvas::editWidget() const
|
|
{
|
|
return d->editWidget;
|
|
}
|
|
|
|
CellEditor* Canvas::editor() const
|
|
{
|
|
return d->cellEditor;
|
|
}
|
|
|
|
double Canvas::xOffset() const
|
|
{
|
|
return d->xOffset;
|
|
}
|
|
|
|
double Canvas::yOffset() const
|
|
{
|
|
return d->yOffset;
|
|
}
|
|
|
|
void Canvas::setXOffset( double _xOffset )
|
|
{
|
|
d->xOffset = _xOffset;
|
|
}
|
|
|
|
void Canvas::setYOffset( double _yOffset )
|
|
{
|
|
d->yOffset = _yOffset;
|
|
}
|
|
|
|
const TQPen& Canvas::defaultGridPen() const
|
|
{
|
|
return d->defaultGridPen;
|
|
}
|
|
|
|
void Canvas::setLastEditorWithFocus( Canvas::EditorType type )
|
|
{
|
|
d->focusEditorType = type;
|
|
}
|
|
|
|
Canvas::EditorType Canvas::lastEditorWithFocus() const
|
|
{
|
|
return d->focusEditorType;
|
|
}
|
|
|
|
|
|
bool Canvas::eventFilter( TQObject *o, TQEvent *e )
|
|
{
|
|
/* this canvas event filter acts on events sent to the line edit as well
|
|
as events to this filter itself.
|
|
*/
|
|
if ( !o || !e )
|
|
return true;
|
|
switch ( e->type() )
|
|
{
|
|
case TQEvent::KeyPress:
|
|
{
|
|
TQKeyEvent * keyev = TQT_TQKEYEVENT(e);
|
|
if ((keyev->key()==Key_Tab) || (keyev->key()==Key_Backtab))
|
|
{
|
|
keyPressEvent ( keyev );
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
case TQEvent::IMStart:
|
|
case TQEvent::IMCompose:
|
|
case TQEvent::IMEnd:
|
|
{
|
|
TQIMEvent * imev = static_cast<TQIMEvent *>(e);
|
|
processIMEvent( imev );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Canvas::focusNextPrevChild( bool )
|
|
{
|
|
return true; // Don't allow to go out of the canvas widget by pressing "Tab"
|
|
}
|
|
|
|
Selection* Canvas::selectionInfo() const
|
|
{
|
|
return d->view->selectionInfo();
|
|
}
|
|
|
|
Selection* Canvas::choice() const
|
|
{
|
|
return d->view->choice();
|
|
}
|
|
|
|
TQRect Canvas::selection() const
|
|
{
|
|
return d->view->selectionInfo()->selection();
|
|
}
|
|
|
|
TQPoint Canvas::marker() const
|
|
{
|
|
return d->view->selectionInfo()->marker();
|
|
}
|
|
|
|
int Canvas::markerColumn() const
|
|
{
|
|
return d->view->selectionInfo()->marker().x();
|
|
}
|
|
|
|
int Canvas::markerRow() const
|
|
{
|
|
return d->view->selectionInfo()->marker().y();
|
|
}
|
|
|
|
double Canvas::zoom() const
|
|
{
|
|
return d->view->zoom();
|
|
}
|
|
|
|
void Canvas::setChooseMode(bool state)
|
|
{
|
|
d->chooseCell = state;
|
|
}
|
|
|
|
bool Canvas::chooseMode() const
|
|
{
|
|
return d->chooseCell;
|
|
}
|
|
|
|
void Canvas::startChoose()
|
|
{
|
|
if ( d->chooseCell )
|
|
return;
|
|
|
|
choice()->clear();
|
|
choice()->setSheet(activeSheet());
|
|
|
|
// It is important to enable this AFTER we set the rect!
|
|
d->chooseCell = true;
|
|
}
|
|
|
|
void Canvas::startChoose( const TQRect& rect )
|
|
{
|
|
if (d->chooseCell)
|
|
return;
|
|
|
|
choice()->setSheet(activeSheet());
|
|
choice()->initialize(rect);
|
|
|
|
// It is important to enable this AFTER we set the rect!
|
|
d->chooseCell = true;
|
|
}
|
|
|
|
void Canvas::endChoose()
|
|
{
|
|
// While entering a formula the choose mode is turned on and off.
|
|
// Clear the choice even if we are not in choose mode. Otherwise,
|
|
// cell references will stay highlighted.
|
|
if (!choice()->isEmpty())
|
|
{
|
|
choice()->clear();
|
|
update();
|
|
}
|
|
|
|
if ( !d->chooseCell )
|
|
return;
|
|
|
|
d->chooseCell = false;
|
|
|
|
Sheet *sheet = choice()->sheet();
|
|
if (sheet)
|
|
{
|
|
d->view->setActiveSheet(sheet);
|
|
}
|
|
}
|
|
|
|
HBorder* Canvas::hBorderWidget() const
|
|
{
|
|
return d->view->hBorderWidget();
|
|
}
|
|
|
|
VBorder* Canvas::vBorderWidget() const
|
|
{
|
|
return d->view->vBorderWidget();
|
|
}
|
|
|
|
TQScrollBar* Canvas::horzScrollBar() const
|
|
{
|
|
return d->view->horzScrollBar();
|
|
}
|
|
|
|
TQScrollBar* Canvas::vertScrollBar() const
|
|
{
|
|
return d->view->vertScrollBar();
|
|
}
|
|
|
|
Sheet* Canvas::findSheet( const TQString& _name ) const
|
|
{
|
|
return d->view->doc()->map()->findSheet( _name );
|
|
}
|
|
|
|
Sheet* Canvas::activeSheet() const
|
|
{
|
|
return d->view->activeSheet();
|
|
}
|
|
|
|
void Canvas::validateSelection()
|
|
{
|
|
Sheet* sheet = activeSheet();
|
|
if (!sheet)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( selectionInfo()->isSingular() )
|
|
{
|
|
int col = selectionInfo()->marker().x();
|
|
int row = selectionInfo()->marker().y();
|
|
Cell * cell = sheet->cellAt( col,row );
|
|
if ( cell && cell->getValidity(0) && cell->getValidity()->displayValidationInformation)
|
|
{
|
|
TQString title = cell->getValidity(0)->titleInfo;
|
|
TQString message = cell->getValidity(0)->messageInfo;
|
|
if ( title.isEmpty() && message.isEmpty() )
|
|
return;
|
|
|
|
if ( !d->validationInfo )
|
|
d->validationInfo = new TQLabel( this );
|
|
kdDebug()<<" display info validation\n";
|
|
double u = cell->dblWidth( col );
|
|
double v = cell->dblHeight( row );
|
|
double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset();
|
|
double ypos = sheet->dblRowPos( markerRow() ) - yOffset();
|
|
// Special treatment for obscured cells.
|
|
if ( cell->isObscured() && cell->isPartOfMerged() )
|
|
{
|
|
cell = cell->obscuringCells().first();
|
|
int moveX = cell->column();
|
|
int moveY = cell->row();
|
|
|
|
// Use the obscuring cells dimensions
|
|
u = cell->dblWidth( moveX );
|
|
v = cell->dblHeight( moveY );
|
|
xpos = sheet->dblColumnPos( moveX );
|
|
ypos = sheet->dblRowPos( moveY );
|
|
}
|
|
//d->validationInfo->setGeometry( 3, y + 3, len + 2, hei + 2 );
|
|
d->validationInfo->setAlignment( TQt::AlignVCenter );
|
|
TQPainter painter;
|
|
painter.begin( this );
|
|
int len = 0;
|
|
int hei = 0;
|
|
TQString resultText;
|
|
if ( !title.isEmpty() )
|
|
{
|
|
len = painter.fontMetrics().width( title );
|
|
hei = painter.fontMetrics().height();
|
|
resultText = title + "\n";
|
|
}
|
|
if ( !message.isEmpty() )
|
|
{
|
|
int i = 0;
|
|
int pos = 0;
|
|
TQString t;
|
|
do
|
|
{
|
|
i = message.find( "\n", pos );
|
|
if ( i == -1 )
|
|
t = message.mid( pos, message.length() - pos );
|
|
else
|
|
{
|
|
t = message.mid( pos, i - pos );
|
|
pos = i + 1;
|
|
}
|
|
hei += painter.fontMetrics().height();
|
|
len = TQMAX( len, painter.fontMetrics().width( t ) );
|
|
}
|
|
while ( i != -1 );
|
|
resultText += message;
|
|
}
|
|
painter.end();
|
|
d->validationInfo->setText( resultText );
|
|
|
|
KoRect unzoomedMarker( xpos - xOffset()+u,
|
|
ypos - yOffset()+v,
|
|
len,
|
|
hei );
|
|
TQRect marker( d->view->doc()->zoomRect( unzoomedMarker ) );
|
|
|
|
d->validationInfo->setGeometry( marker );
|
|
d->validationInfo->show();
|
|
}
|
|
else
|
|
{
|
|
delete d->validationInfo;
|
|
d->validationInfo = 0L;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete d->validationInfo;
|
|
d->validationInfo = 0L;
|
|
}
|
|
}
|
|
|
|
|
|
void Canvas::scrollToCell(TQPoint location) const
|
|
{
|
|
Sheet* sheet = activeSheet();
|
|
if (sheet == NULL)
|
|
return;
|
|
|
|
if (d->view->isLoading())
|
|
return;
|
|
|
|
// kdDebug(36001) << "------------------------------------------------" << endl;
|
|
// kdDebug(36001) << "scrollToCell(): at location [" << location.x() << ","
|
|
// << location.y() << "]" << endl;
|
|
|
|
/* we don't need this cell ptr, but this call is necessary to update the
|
|
scroll bar correctly. I don't like having that as part of the cellAt function
|
|
but I suppose that's ok for now.
|
|
*/
|
|
Cell* cell = sheet->cellAt(location.x(), location.y(), true);
|
|
Q_UNUSED(cell);
|
|
|
|
double unzoomedWidth = d->view->doc()->unzoomItX( width() );
|
|
double unzoomedHeight = d->view->doc()->unzoomItY( height() );
|
|
|
|
//kdDebug(36001) << "Unzoomed view size: [" << unzoomedWidth << ","
|
|
// << unzoomedHeight << "]" << endl;
|
|
|
|
// xpos is the position of the cell in the current window in unzoomed
|
|
// document coordinates.
|
|
double xpos;
|
|
if ( sheet->layoutDirection()==Sheet::LeftToRight )
|
|
xpos = sheet->dblColumnPos( location.x() ) - xOffset();
|
|
else
|
|
xpos = unzoomedWidth - sheet->dblColumnPos( location.x() ) + xOffset();
|
|
double ypos = sheet->dblRowPos( location.y() ) - yOffset();
|
|
|
|
//kdDebug(36001) << "Position: [" << xpos << "," << ypos << "]" << endl;
|
|
|
|
double minY = 40.0;
|
|
double maxY = unzoomedHeight - 40.0;
|
|
//kdDebug(36001) << "Canvas::scrollToCell : height=" << height() << endl;
|
|
//kdDebug(36001) << "Canvas::scrollToCell : width=" << width() << endl;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft ) {
|
|
// Right to left sheet.
|
|
|
|
double minX = unzoomedWidth - 100.0; // less than that, we scroll
|
|
double maxX = 100.0; // more than that, we scroll
|
|
|
|
// kdDebug() << "rtl2: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << ", Offset: " << xOffset() << endl;
|
|
|
|
// Do we need to scroll left?
|
|
if ( xpos > minX )
|
|
horzScrollBar()->setValue( horzScrollBar()->maxValue() -
|
|
d->view->doc()->zoomItX( xOffset() - xpos + minX ) );
|
|
|
|
// Do we need to scroll right?
|
|
else if ( xpos < maxX )
|
|
{
|
|
double horzScrollBarValue = xOffset() - xpos + maxX;
|
|
double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth;
|
|
|
|
//We don't want to display any area > KS_colMax widths
|
|
if ( horzScrollBarValue > horzScrollBarValueMax )
|
|
horzScrollBarValue = horzScrollBarValueMax;
|
|
|
|
horzScrollBar()->setValue( horzScrollBar()->maxValue() -
|
|
d->view->doc()->zoomItX( horzScrollBarValue ) );
|
|
}
|
|
}
|
|
else {
|
|
// Left to right sheet.
|
|
|
|
double minX = 100.0; // less than that, we scroll
|
|
double maxX = unzoomedWidth - 100.0; // more than that, we scroll
|
|
|
|
// kdDebug() << "ltr: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << endl;
|
|
|
|
// Do we need to scroll left?
|
|
if ( xpos < minX )
|
|
horzScrollBar()->setValue( d->view->doc()->zoomItX( xOffset() + xpos - minX ) );
|
|
|
|
// Do we need to scroll right?
|
|
else if ( xpos > maxX )
|
|
{
|
|
double horzScrollBarValue = xOffset() + xpos - maxX;
|
|
double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth;
|
|
|
|
//We don't want to display any area > KS_colMax widths
|
|
if ( horzScrollBarValue > horzScrollBarValueMax )
|
|
horzScrollBarValue = horzScrollBarValueMax;
|
|
|
|
horzScrollBar()->setValue( d->view->doc()->zoomItX( horzScrollBarValue ) );
|
|
}
|
|
}
|
|
// kdDebug() << "ltr: YPos: " << ypos << ", min: " << minY << ", maxY: " << maxY << endl;
|
|
|
|
// do we need to scroll up
|
|
if ( ypos < minY )
|
|
vertScrollBar()->setValue( d->view->doc()->zoomItY( yOffset() + ypos - minY ) );
|
|
|
|
// do we need to scroll down
|
|
else if ( ypos > maxY )
|
|
{
|
|
double vertScrollBarValue = yOffset() + ypos - maxY;
|
|
double vertScrollBarValueMax = sheet->sizeMaxY() - unzoomedHeight;
|
|
|
|
//We don't want to display any area > KS_rowMax heights
|
|
if ( vertScrollBarValue > vertScrollBarValueMax )
|
|
vertScrollBarValue = vertScrollBarValueMax;
|
|
|
|
vertScrollBar()->setValue( d->view->doc()->zoomItY( vertScrollBarValue ) );
|
|
}
|
|
}
|
|
|
|
void Canvas::slotScrollHorz( int _value )
|
|
{
|
|
Sheet * sheet = activeSheet();
|
|
|
|
if ( sheet == 0L )
|
|
return;
|
|
|
|
kdDebug(36001) << "slotScrollHorz: value = " << _value << endl;
|
|
//kdDebug(36001) << kdBacktrace() << endl;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
_value = horzScrollBar()->maxValue() - _value;
|
|
|
|
double unzoomedValue = d->view->doc()->unzoomItX( _value );
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
|
|
d->view->doc()->emitBeginOperation(false);
|
|
|
|
if ( unzoomedValue < 0.0 ) {
|
|
kdDebug (36001)
|
|
<< "Canvas::slotScrollHorz: value out of range (unzoomedValue: "
|
|
<< unzoomedValue << ")" << endl;
|
|
unzoomedValue = 0.0;
|
|
}
|
|
|
|
double xpos = sheet->dblColumnPos( TQMIN( KS_colMax, d->view->activeSheet()->maxColumn()+10 ) ) - d->xOffset;
|
|
if ( unzoomedValue > ( xpos + d->xOffset ) )
|
|
unzoomedValue = xpos + d->xOffset;
|
|
|
|
sheet->enableScrollBarUpdates( false );
|
|
|
|
// Relative movement
|
|
int dx = d->view->doc()->zoomItX( d->xOffset - unzoomedValue );
|
|
|
|
|
|
/* what cells will need painted now? */
|
|
TQRect area = visibleCells();
|
|
double tmp;
|
|
if (dx > 0)
|
|
{
|
|
area.setRight( area.left() );
|
|
area.setLeft( sheet->leftColumn( unzoomedValue, tmp ) );
|
|
}
|
|
else
|
|
{
|
|
area.setLeft( area.right() );
|
|
area.setRight( sheet->rightColumn( dwidth + unzoomedValue ) );
|
|
}
|
|
|
|
sheet->setRegionPaintDirty(area);
|
|
|
|
// New absolute position
|
|
kdDebug(36001) << "slotScrollHorz(): XOffset before setting: "
|
|
<< d->xOffset << endl;
|
|
d->xOffset = unzoomedValue;
|
|
kdDebug(36001) << "slotScrollHorz(): XOffset after setting: "
|
|
<< d->xOffset << endl;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
dx = -dx;
|
|
|
|
scroll( dx, 0 );
|
|
|
|
hBorderWidget()->scroll( dx, 0 );
|
|
|
|
sheet->enableScrollBarUpdates( true );
|
|
|
|
d->view->doc()->emitEndOperation( sheet->visibleRect( this ) );
|
|
}
|
|
|
|
void Canvas::slotScrollVert( int _value )
|
|
{
|
|
if ( activeSheet() == 0L )
|
|
return;
|
|
|
|
d->view->doc()->emitBeginOperation(false);
|
|
double unzoomedValue = d->view->doc()->unzoomItY( _value );
|
|
|
|
if ( unzoomedValue < 0 )
|
|
{
|
|
unzoomedValue = 0;
|
|
kdDebug (36001) << "Canvas::slotScrollVert: value out of range (unzoomedValue: " <<
|
|
unzoomedValue << ")" << endl;
|
|
}
|
|
|
|
double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, d->view->activeSheet()->maxRow()+10 ) );
|
|
if ( unzoomedValue > ypos )
|
|
unzoomedValue = ypos;
|
|
|
|
activeSheet()->enableScrollBarUpdates( false );
|
|
|
|
// Relative movement
|
|
int dy = d->view->doc()->zoomItY( d->yOffset - unzoomedValue );
|
|
|
|
|
|
/* what cells will need painted now? */
|
|
TQRect area = visibleCells();
|
|
double tmp;
|
|
if (dy > 0)
|
|
{
|
|
area.setBottom(area.top());
|
|
area.setTop(activeSheet()->topRow(unzoomedValue, tmp));
|
|
}
|
|
else
|
|
{
|
|
area.setTop(area.bottom());
|
|
area.setBottom(activeSheet()->bottomRow(d->view->doc()->unzoomItY(height()) +
|
|
unzoomedValue));
|
|
}
|
|
|
|
activeSheet()->setRegionPaintDirty( area );
|
|
|
|
// New absolute position
|
|
d->yOffset = unzoomedValue;
|
|
scroll( 0, dy );
|
|
vBorderWidget()->scroll( 0, dy );
|
|
|
|
activeSheet()->enableScrollBarUpdates( true );
|
|
|
|
d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) );
|
|
}
|
|
|
|
void Canvas::slotMaxColumn( int _max_column )
|
|
{
|
|
int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value();
|
|
double xpos = activeSheet()->dblColumnPos( TQMIN( KS_colMax, _max_column + 10 ) ) - xOffset();
|
|
double unzoomWidth = d->view->doc()->unzoomItX( width() );
|
|
|
|
//Don't go beyond the maximum column range (KS_colMax)
|
|
double sizeMaxX = activeSheet()->sizeMaxX();
|
|
if ( xpos > sizeMaxX - xOffset() - unzoomWidth )
|
|
xpos = sizeMaxX - xOffset() - unzoomWidth;
|
|
|
|
horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( xpos + xOffset() ) );
|
|
|
|
if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
|
|
horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue );
|
|
}
|
|
|
|
void Canvas::slotMaxRow( int _max_row )
|
|
{
|
|
double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, _max_row + 10 ) ) - yOffset();
|
|
double unzoomHeight = d->view->doc()->unzoomItY( height() );
|
|
|
|
//Don't go beyond the maximum row range (KS_rowMax)
|
|
double sizeMaxY = activeSheet()->sizeMaxY();
|
|
if ( ypos > sizeMaxY - yOffset() - unzoomHeight )
|
|
ypos = sizeMaxY - yOffset() - unzoomHeight;
|
|
|
|
vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( ypos + yOffset() ) );
|
|
}
|
|
|
|
void Canvas::mouseMoveEvent( TQMouseEvent * _ev )
|
|
{
|
|
// Dont allow modifications if document is readonly. Selecting is no modification
|
|
if ( (!d->view->koDocument()->isReadWrite()) && (d->mouseAction!=Mark))
|
|
return;
|
|
|
|
if ( d->mousePressed && d->modType != MT_NONE )
|
|
{
|
|
KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) );
|
|
docPoint += KoPoint( xOffset(), yOffset() );
|
|
|
|
if ( d->modType == MT_MOVE )
|
|
{
|
|
if ( !d->m_isMoving )
|
|
{
|
|
d->m_moveStartPoint = objectRect( false ).topLeft();
|
|
d->m_isMoving = true;
|
|
}
|
|
moveObjectsByMouse( docPoint, _ev->state() & AltButton || _ev->state() & ControlButton );
|
|
}
|
|
else if ( d->m_resizeObject )
|
|
{
|
|
if ( !d->m_isResizing )
|
|
d->m_isResizing = true;
|
|
|
|
bool keepRatio = d->m_resizeObject->isKeepRatio();
|
|
if ( _ev->state() & AltButton )
|
|
{
|
|
keepRatio = true;
|
|
}
|
|
docPoint = KoPoint( doc()->unzoomPoint( _ev->pos() ) );
|
|
resizeObject( d->modType, docPoint, keepRatio );
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/*if ( d->mousePressed && d->m_resizeObject && d->modType != MT_NONE )
|
|
{
|
|
if ( !d->m_isMoving )
|
|
{
|
|
d->m_isMoving = true;
|
|
update();
|
|
}
|
|
else
|
|
update( d->m_boundingRealRect );
|
|
|
|
|
|
TQRect drawingRect;
|
|
|
|
if ( d->modType == MT_MOVE )
|
|
{
|
|
drawingRect = TQRect( _ev->pos() - d->m_origPos, d->m_origSize );
|
|
d->m_boundingRealRect = drawingRect;
|
|
}
|
|
else
|
|
{
|
|
drawingRect = doc()->zoomRect( calculateNewGeometry(d->modType, _ev->pos().x(), _ev->pos().y() ) );
|
|
drawingRect.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ) , (int)( -yOffset() * doc()->zoomedResolutionY() ) );
|
|
}
|
|
|
|
// Autoscrolling
|
|
if ( ( d->modType == MT_MOVE && drawingRect.top() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().y() < 0 ) )
|
|
{
|
|
vertScrollBar()->setValue ((int) ( vertScrollBar()->value() -
|
|
autoScrollAccelerationY( - drawingRect.top() ) ) );
|
|
}
|
|
else if ( ( d->modType == MT_MOVE && drawingRect.bottom() > height() ) || ( d->modType != MT_MOVE && _ev->pos().y() > height() ) )
|
|
{
|
|
vertScrollBar()->setValue ((int) ( vertScrollBar()->value() +
|
|
autoScrollAccelerationY ( drawingRect.bottom() - height() ) ) );
|
|
}
|
|
if ( ( d->modType == MT_MOVE && drawingRect.left() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().x() < 0 ) )
|
|
{
|
|
horzScrollBar()->setValue ((int) ( horzScrollBar()->value() -
|
|
autoScrollAccelerationX( - drawingRect.left() ) ) );
|
|
}
|
|
else if ( ( d->modType == MT_MOVE && drawingRect.right() > width() ) || ( d->modType != MT_MOVE && _ev->pos().x() > width() ) )
|
|
{
|
|
horzScrollBar()->setValue ((int) (horzScrollBar()->value() +
|
|
autoScrollAccelerationX( drawingRect.right() - width() ) ) );
|
|
}
|
|
|
|
if ( drawingRect.left() < 0 )
|
|
{
|
|
drawingRect.setRight( drawingRect.right() -drawingRect.left() );
|
|
drawingRect.setLeft( 0 );
|
|
}
|
|
if ( drawingRect.top() < 0 )
|
|
{
|
|
drawingRect.setBottom( drawingRect.bottom() -drawingRect.top() );
|
|
drawingRect.setTop( 0 );
|
|
}
|
|
|
|
d->m_boundingRealRect = drawingRect; //redraw this area next time the mouse has been moved
|
|
|
|
//update( d->m_boundingRealRect );
|
|
TQPainter p(this);
|
|
p.setRasterOp( NotROP );
|
|
p.setPen( TQPen( black, 0, DotLine ) );
|
|
p.drawRect( drawingRect );
|
|
p.end();
|
|
return;
|
|
}*/
|
|
|
|
if ( d->dragging )
|
|
{
|
|
return;
|
|
}
|
|
if ( d->dragStart.x() != -1 )
|
|
{
|
|
TQPoint p ( (int) _ev->pos().x() + (int) xOffset(),
|
|
(int) _ev->pos().y() + (int) yOffset() );
|
|
|
|
if ( ( d->dragStart - p ).manhattanLength() > 4 )
|
|
{
|
|
d->dragging = true;
|
|
startTheDrag();
|
|
d->dragStart.setX( -1 );
|
|
}
|
|
d->dragging = false;
|
|
return;
|
|
}
|
|
|
|
// Get info about where the event occurred - this is duplicated
|
|
// in ::mousePressEvent, needs to be separated into one function
|
|
Sheet *sheet = activeSheet();
|
|
if ( !sheet )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( d->mouseSelectedObject )
|
|
{
|
|
EmbeddedObject *obj = 0;
|
|
TQPoint p ( (int) _ev->x(),
|
|
(int) _ev->y() );
|
|
if ( ( obj = getObject( p, activeSheet() ) ) && obj->isSelected() )
|
|
{
|
|
KoRect const bound = obj->geometry();
|
|
TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(),
|
|
bound.width(),
|
|
bound.height() ) );
|
|
zoomedBound.moveBy( (int)(-xOffset() * doc()->zoomedResolutionX() ), (int)(-yOffset() * doc()->zoomedResolutionY() ));
|
|
setCursor( obj->getCursor( p, d->modType, zoomedBound ) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
double ev_PosX;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
}
|
|
else
|
|
{
|
|
ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
}
|
|
double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
|
|
|
|
// In which cell did the user click ?
|
|
double xpos;
|
|
double ypos;
|
|
int col = sheet->leftColumn( ev_PosX, xpos );
|
|
int row = sheet->topRow( ev_PosY, ypos );
|
|
|
|
// you cannot move marker when col > KS_colMax or row > KS_rowMax
|
|
if ( col > KS_colMax || row > KS_rowMax )
|
|
{
|
|
kdDebug(36001) << "Canvas::mouseMoveEvent: col or row is out of range: "
|
|
<< "col: " << col << " row: " << row << endl;
|
|
return;
|
|
}
|
|
|
|
|
|
//*** Highlighted Range Resize Handling ***
|
|
if (d->mouseAction == ResizeSelection)
|
|
{
|
|
choice()->update(TQPoint(col,row));
|
|
return;
|
|
}
|
|
|
|
//Check to see if the mouse is over a highlight range size grip and if it is, change the cursor
|
|
//shape to a resize arrow
|
|
if (highlightRangeSizeGripAt(ev_PosX,ev_PosY))
|
|
{
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
setCursor( sizeBDiagCursor );
|
|
else
|
|
setCursor( sizeFDiagCursor );
|
|
return;
|
|
}
|
|
|
|
TQRect rct( (d->chooseCell ? choice() : selectionInfo())->lastRange() );
|
|
|
|
TQRect r1;
|
|
TQRect r2;
|
|
|
|
double lx = sheet->dblColumnPos( rct.left() );
|
|
double rx = sheet->dblColumnPos( rct.right() + 1 );
|
|
double ty = sheet->dblRowPos( rct.top() );
|
|
double by = sheet->dblRowPos( rct.bottom() + 1 );
|
|
|
|
r1.setLeft( (int) (lx - 1) );
|
|
r1.setTop( (int) (ty - 1) );
|
|
r1.setRight( (int) (rx + 1) );
|
|
r1.setBottom( (int) (by + 1) );
|
|
|
|
r2.setLeft( (int) (lx + 1) );
|
|
r2.setTop( (int) (ty + 1) );
|
|
r2.setRight( (int) (rx - 1) );
|
|
r2.setBottom( (int) (by - 1) );
|
|
|
|
// Test whether the mouse is over some anchor
|
|
{
|
|
Cell *cell = sheet->visibleCellAt( col, row );
|
|
TQString anchor;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
anchor = cell->testAnchor( d->view->doc()->zoomItX( cell->dblWidth() - ev_PosX + xpos ),
|
|
d->view->doc()->zoomItY( ev_PosY - ypos ) );
|
|
}
|
|
else
|
|
{
|
|
anchor = cell->testAnchor( d->view->doc()->zoomItX( ev_PosX - xpos ),
|
|
d->view->doc()->zoomItY( ev_PosY - ypos ) );
|
|
}
|
|
if ( !anchor.isEmpty() && anchor != d->anchor )
|
|
{
|
|
setCursor( KCursor::handCursor() );
|
|
}
|
|
|
|
d->anchor = anchor;
|
|
}
|
|
|
|
// Test wether mouse is over the selection handle
|
|
TQRect selectionHandle = d->view->selectionInfo()->selectionHandleArea();
|
|
if ( selectionHandle.contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ),
|
|
d->view->doc()->zoomItY( ev_PosY ) ) ) )
|
|
{
|
|
//If the cursor is over the handle, than it might be already on the next cell.
|
|
//Recalculate the cell!
|
|
col = sheet->leftColumn( ev_PosX - d->view->doc()->unzoomItX( 2 ), xpos );
|
|
row = sheet->topRow( ev_PosY - d->view->doc()->unzoomItY( 2 ), ypos );
|
|
|
|
if ( !sheet->isProtected() )
|
|
{
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
setCursor( sizeBDiagCursor );
|
|
else
|
|
setCursor( sizeFDiagCursor );
|
|
}
|
|
}
|
|
else if ( !d->anchor.isEmpty() )
|
|
{
|
|
if ( !sheet->isProtected() )
|
|
setCursor( KCursor::handCursor() );
|
|
}
|
|
else if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) )
|
|
&& !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) )
|
|
{
|
|
setCursor( KCursor::handCursor() );
|
|
}
|
|
else if ( d->chooseCell )
|
|
{
|
|
//Visual cue to indicate that the user can drag-select the choice selection
|
|
setCursor( KCursor::crossCursor() );
|
|
}
|
|
else
|
|
{
|
|
//Nothing special is happening, use a normal arrow cursor
|
|
setCursor( arrowCursor );
|
|
}
|
|
|
|
// No marking, selecting etc. in progess? Then quit here.
|
|
if ( d->mouseAction == NoAction )
|
|
return;
|
|
|
|
// Set the new extent of the selection
|
|
(d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row));
|
|
}
|
|
|
|
void Canvas::mouseReleaseEvent( TQMouseEvent* /*_ev*/)
|
|
{
|
|
if ( d->scrollTimer->isActive() )
|
|
d->scrollTimer->stop();
|
|
|
|
d->mousePressed = false;
|
|
d->view->disableAutoScroll();
|
|
|
|
if ( d->modType != MT_NONE /*&& d->m_resizeObject && d->m_resizeObject->isSelected() */)
|
|
{
|
|
switch ( d->modType )
|
|
{
|
|
case MT_MOVE:
|
|
{
|
|
KoPoint move( objectRect( false ).topLeft() - d->m_moveStartPosMouse );
|
|
if ( move != KoPoint( 0, 0 ) )
|
|
{
|
|
KCommand *cmd= activeSheet()->moveObject( view(), move.x(), move.y() );
|
|
if(cmd)
|
|
doc()->addCommand( cmd );
|
|
} else
|
|
{
|
|
repaint();
|
|
}
|
|
d->m_isMoving = false;
|
|
break;
|
|
}
|
|
case MT_RESIZE_UP: case MT_RESIZE_LF: case MT_RESIZE_RT: case MT_RESIZE_LU: case MT_RESIZE_LD: case MT_RESIZE_RU: case MT_RESIZE_RD:
|
|
finishResizeObject( i18n("Resize Object") );
|
|
break;
|
|
case MT_RESIZE_DN:
|
|
finishResizeObject( i18n("Resize Object"), false );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
Sheet *sheet = activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
Selection* selectionInfo = d->view->selectionInfo();
|
|
TQRect s( selectionInfo->lastRange() );
|
|
|
|
// The user started the drag in the lower right corner of the marker ?
|
|
if ( d->mouseAction == ResizeCell && !sheet->isProtected() )
|
|
{
|
|
sheet->mergeCells(selectionInfo->lastRange());
|
|
d->view->updateEditWidget();
|
|
}
|
|
else if ( d->mouseAction == AutoFill && !sheet->isProtected() )
|
|
{
|
|
TQRect dest = s;
|
|
sheet->autofill( d->autoFillSource, dest );
|
|
|
|
d->view->updateEditWidget();
|
|
}
|
|
// The user started the drag in the middle of a cell ?
|
|
else if ( d->mouseAction == Mark && !d->chooseCell )
|
|
{
|
|
d->view->updateEditWidget();
|
|
}
|
|
|
|
d->mouseAction = NoAction;
|
|
d->dragging = false;
|
|
d->dragStart.setX( -1 );
|
|
}
|
|
|
|
void Canvas::processClickSelectionHandle( TQMouseEvent *event )
|
|
{
|
|
// Auto fill ? That is done using the left mouse button.
|
|
if ( event->button() == Qt::LeftButton )
|
|
{
|
|
d->mouseAction = AutoFill;
|
|
d->autoFillSource = selectionInfo()->lastRange();
|
|
}
|
|
// Resize a cell (done with the right mouse button) ?
|
|
// But for that to work there must not be a selection.
|
|
else if ( event->button() == Qt::MidButton && selectionInfo()->isSingular())
|
|
{
|
|
d->mouseAction = ResizeCell;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void Canvas::processLeftClickAnchor()
|
|
{
|
|
bool isRefLink = localReferenceAnchor( d->anchor );
|
|
bool isLocalLink = (d->anchor.find("file:") == 0);
|
|
if ( !isRefLink )
|
|
{
|
|
TQString type=KMimeType::findByURL(d->anchor, 0, isLocalLink)->name();
|
|
|
|
if ( KRun::isExecutableFile( d->anchor , type ) )
|
|
{
|
|
//TQString question = i18n("Do you want to open this link to '%1'?\n").arg(d->anchor);
|
|
|
|
//question += i18n("Note that opening a link to a local file may "
|
|
// "compromise your system's security.");
|
|
|
|
TQString question = i18n("This link points to the program or script '%1'.\n"
|
|
"Malicious programs can harm your computer. Are you sure that you want to run this program?").arg(d->anchor);
|
|
// this will also start local programs, so adding a "don't warn again"
|
|
// checkbox will probably be too dangerous
|
|
int choice = KMessageBox::warningYesNo(this, question, i18n("Open Link?"));
|
|
if ( choice != KMessageBox::Yes )
|
|
{
|
|
return;
|
|
//(void) new KRun( d->anchor );
|
|
}
|
|
}
|
|
|
|
new KRun(d->anchor);
|
|
}
|
|
else
|
|
{
|
|
selectionInfo()->initialize(Region(d->view, d->anchor));
|
|
}
|
|
}
|
|
|
|
bool Canvas::highlightRangeSizeGripAt(double x, double y)
|
|
{
|
|
if (!d->chooseCell)
|
|
return 0;
|
|
|
|
Region::ConstIterator end = choice()->constEnd();
|
|
for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it)
|
|
{
|
|
// TODO Stefan: adapt to Selection::selectionHandleArea
|
|
KoRect visibleRect;
|
|
sheetAreaToRect((*it)->rect().normalize(), visibleRect);
|
|
|
|
TQPoint bottomRight((int) visibleRect.right(), (int) visibleRect.bottom());
|
|
TQRect handle( ( (int) bottomRight.x() - 6 ),
|
|
( (int) bottomRight.y() - 6 ),
|
|
( 6 ),
|
|
( 6 ) );
|
|
|
|
if (handle.contains(TQPoint((int) x,(int) y)))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void Canvas::mousePressEvent( TQMouseEvent * _ev )
|
|
{
|
|
if ( _ev->button() == Qt::LeftButton )
|
|
{
|
|
d->mousePressed = true;
|
|
d->view->enableAutoScroll();
|
|
}
|
|
|
|
if ( activeSheet() && _ev->button() == Qt::LeftButton)
|
|
{
|
|
d->m_moveStartPosMouse = objectRect( false ).topLeft();
|
|
EmbeddedObject *obj = getObject( _ev->pos(), activeSheet() );
|
|
|
|
if ( obj )
|
|
{
|
|
// use ctrl + Button to select / deselect object
|
|
if ( _ev->state() & ControlButton && obj->isSelected() )
|
|
deselectObject( obj );
|
|
else if ( _ev->state() & ControlButton )
|
|
{
|
|
if ( d->modType == MT_NONE)
|
|
return;
|
|
|
|
selectObject( obj );
|
|
raiseObject( obj );
|
|
d->m_moveStartPosMouse = objectRect( false ).topLeft();
|
|
}
|
|
else
|
|
{
|
|
if ( d->modType != MT_MOVE || !obj->isSelected() )
|
|
deselectAllObjects();
|
|
|
|
selectObject( obj );
|
|
|
|
raiseObject( obj );
|
|
d->m_moveStartPosMouse = objectRect( false ).topLeft();
|
|
}
|
|
|
|
// start resizing
|
|
if ( d->modType != MT_MOVE && d->modType != MT_NONE && !obj->isProtect() )
|
|
{
|
|
deselectAllObjects();
|
|
selectObject( obj );
|
|
raiseObject( obj );
|
|
|
|
d->m_resizeObject = obj;
|
|
|
|
d->m_ratio = static_cast<double>( obj->geometry().width() ) /
|
|
static_cast<double>( obj->geometry().height() );
|
|
d->m_rectBeforeResize = obj->geometry();
|
|
}
|
|
|
|
KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) );
|
|
docPoint += KoPoint( xOffset(), yOffset() );
|
|
d->m_origMousePos = docPoint;
|
|
d->m_moveStartPosMouse = objectRect( false ).topLeft();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
d->modType = MT_NONE;
|
|
if ( !( _ev->state() & ShiftButton ) && !( _ev->state() & ControlButton ) )
|
|
deselectAllObjects();
|
|
}
|
|
}
|
|
|
|
// Get info about where the event occurred - this is duplicated
|
|
// in ::mouseMoveEvent, needs to be separated into one function
|
|
Sheet *sheet = activeSheet();
|
|
if ( !sheet )
|
|
{
|
|
return;
|
|
}
|
|
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
double ev_PosX;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
}
|
|
else
|
|
{
|
|
ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
}
|
|
double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
|
|
|
|
// In which cell did the user click ?
|
|
double xpos;
|
|
double ypos;
|
|
int col = sheet->leftColumn( ev_PosX, xpos );
|
|
int row = sheet->topRow( ev_PosY, ypos );
|
|
// you cannot move marker when col > KS_colMax or row > KS_rowMax
|
|
if ( col > KS_colMax || row > KS_rowMax )
|
|
{
|
|
kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: "
|
|
<< "col: " << col << " row: " << row << endl;
|
|
return;
|
|
}
|
|
|
|
// you cannot move marker when col > KS_colMax or row > KS_rowMax
|
|
if ( col > KS_colMax || row > KS_rowMax )
|
|
{
|
|
kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: "
|
|
<< "col: " << col << " row: " << row << endl;
|
|
return;
|
|
}
|
|
|
|
if (d->chooseCell && highlightRangeSizeGripAt(ev_PosX,ev_PosY))
|
|
{
|
|
choice()->setActiveElement(TQPoint(col,row));
|
|
d->mouseAction = ResizeSelection;
|
|
return;
|
|
}
|
|
|
|
// We were editing a cell -> save value and get out of editing mode
|
|
if ( d->cellEditor && !d->chooseCell )
|
|
{
|
|
deleteEditor( true ); // save changes
|
|
}
|
|
|
|
d->scrollTimer->start( 50 );
|
|
|
|
// Did we click in the lower right corner of the marker/marked-area ?
|
|
if ( selectionInfo()->selectionHandleArea().contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ),
|
|
d->view->doc()->zoomItY( ev_PosY ) ) ) )
|
|
{
|
|
processClickSelectionHandle( _ev );
|
|
return;
|
|
}
|
|
|
|
|
|
// TODO Stefan: adapt to non-cont. selection
|
|
{
|
|
// start drag ?
|
|
TQRect rct( selectionInfo()->lastRange() );
|
|
|
|
TQRect r1;
|
|
TQRect r2;
|
|
{
|
|
double lx = sheet->dblColumnPos( rct.left() );
|
|
double rx = sheet->dblColumnPos( rct.right() + 1 );
|
|
double ty = sheet->dblRowPos( rct.top() );
|
|
double by = sheet->dblRowPos( rct.bottom() + 1 );
|
|
|
|
r1.setLeft( (int) (lx - 1) );
|
|
r1.setTop( (int) (ty - 1) );
|
|
r1.setRight( (int) (rx + 1) );
|
|
r1.setBottom( (int) (by + 1) );
|
|
|
|
r2.setLeft( (int) (lx + 1) );
|
|
r2.setTop( (int) (ty + 1) );
|
|
r2.setRight( (int) (rx - 1) );
|
|
r2.setBottom( (int) (by - 1) );
|
|
}
|
|
|
|
d->dragStart.setX( -1 );
|
|
|
|
if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) )
|
|
&& !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) )
|
|
{
|
|
d->dragStart.setX( (int) ev_PosX );
|
|
d->dragStart.setY( (int) ev_PosY );
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
// kdDebug() << "Clicked in cell " << col << ", " << row << endl;
|
|
|
|
// Extending an existing selection with the shift button ?
|
|
if ((_ev->state() & ShiftButton) &&
|
|
d->view->koDocument()->isReadWrite() &&
|
|
!selectionInfo()->isColumnOrRowSelected())
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row));
|
|
return;
|
|
}
|
|
|
|
|
|
// Go to the upper left corner of the obscuring object if cells are merged
|
|
Cell *cell = sheet->cellAt( col, row );
|
|
if (cell->isPartOfMerged())
|
|
{
|
|
cell = cell->obscuringCells().first();
|
|
col = cell->column();
|
|
row = cell->row();
|
|
}
|
|
|
|
switch (_ev->button())
|
|
{
|
|
case Qt::LeftButton:
|
|
if (!d->anchor.isEmpty())
|
|
{
|
|
// Hyperlink pressed
|
|
processLeftClickAnchor();
|
|
}
|
|
#ifdef NONCONTIGUOUSSELECTION
|
|
else if ( _ev->state() & ControlButton )
|
|
{
|
|
if (d->chooseCell)
|
|
{
|
|
#if 0 // TODO Stefan: remove for NCS of choices
|
|
// Start a marking action
|
|
d->mouseAction = Mark;
|
|
// extend the existing selection
|
|
choice()->extend(TQPoint(col,row), activeSheet());
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// Start a marking action
|
|
d->mouseAction = Mark;
|
|
// extend the existing selection
|
|
selectionInfo()->extend(TQPoint(col,row), activeSheet());
|
|
}
|
|
// TODO Stefan: simplification, if NCS of choices is working
|
|
/* (d->chooseCell ? choice() : selectionInfo())->extend(TQPoint(col,row), activeSheet());*/
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
// Start a marking action
|
|
d->mouseAction = Mark;
|
|
// reinitialize the selection
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet());
|
|
}
|
|
break;
|
|
case Qt::MidButton:
|
|
// Paste operation with the middle button?
|
|
if ( d->view->koDocument()->isReadWrite() && !sheet->isProtected() )
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize( TQPoint( col, row ), activeSheet() );
|
|
sheet->paste(selectionInfo()->lastRange(), true, Paste::Normal,
|
|
Paste::OverWrite, false, 0, false, TQClipboard::Selection);
|
|
sheet->setRegionPaintDirty(*selectionInfo());
|
|
}
|
|
break;
|
|
case Qt::RightButton:
|
|
if (!selectionInfo()->contains( TQPoint( col, row ) ))
|
|
{
|
|
// No selection or the mouse press was outside of an existing selection?
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet());
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
scrollToCell(selectionInfo()->marker());
|
|
if ( !d->chooseCell )
|
|
{
|
|
d->view->updateEditWidgetOnPress();
|
|
}
|
|
updatePosWidget();
|
|
|
|
// Context menu?
|
|
if ( _ev->button() == Qt::RightButton )
|
|
{
|
|
// TODO: Handle anchor // TODO Stefan: ???
|
|
TQPoint p = mapToGlobal( _ev->pos() );
|
|
d->view->openPopupMenu( p );
|
|
}
|
|
}
|
|
|
|
void Canvas::startTheDrag()
|
|
{
|
|
Sheet * sheet = activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
// right area for start dragging
|
|
TextDrag * d = new TextDrag( this );
|
|
setCursor( KCursor::handCursor() );
|
|
|
|
TQDomDocument doc = sheet->saveCellRegion(*selectionInfo());
|
|
|
|
// Save to buffer
|
|
TQBuffer buffer;
|
|
buffer.open( IO_WriteOnly );
|
|
TQTextStream str( &buffer );
|
|
str.setEncoding( TQTextStream::UnicodeUTF8 );
|
|
str << doc;
|
|
buffer.close();
|
|
|
|
d->setPlain( sheet->copyAsText( selectionInfo() ) );
|
|
d->setKSpread( buffer.buffer() );
|
|
|
|
d->dragCopy();
|
|
setCursor( KCursor::arrowCursor() );
|
|
}
|
|
|
|
void Canvas::mouseDoubleClickEvent( TQMouseEvent* _ev)
|
|
{
|
|
|
|
EmbeddedObject *obj;
|
|
if ( ( obj = getObject( _ev->pos(), activeSheet() ) ) )
|
|
{
|
|
switch ( obj->getType() )
|
|
{
|
|
case OBJECT_KOFFICE_PART: case OBJECT_CHART:
|
|
{
|
|
dynamic_cast<EmbeddedKOfficeObject*>(obj)->activate( view(), this );
|
|
return;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
view()->extraProperties();
|
|
return;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( d->view->koDocument()->isReadWrite() && activeSheet() )
|
|
createEditor(true);
|
|
}
|
|
|
|
void Canvas::wheelEvent( TQWheelEvent* _ev )
|
|
{
|
|
if ( _ev->orientation() == Qt::Vertical )
|
|
{
|
|
if ( vertScrollBar() )
|
|
TQApplication::sendEvent( vertScrollBar(), _ev );
|
|
}
|
|
else if ( horzScrollBar() )
|
|
{
|
|
TQApplication::sendEvent( horzScrollBar(), _ev );
|
|
}
|
|
}
|
|
|
|
void Canvas::paintEvent( TQPaintEvent* _ev )
|
|
{
|
|
if ( d->view->doc()->isLoading() )
|
|
return;
|
|
|
|
Sheet* sheet = activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
// ElapsedTime et( "Canvas::paintEvent" );
|
|
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
KoRect rect = d->view->doc()->unzoomRect( _ev->rect() & TQWidget::rect() );
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
rect.moveBy( -xOffset(), yOffset() );
|
|
else
|
|
rect.moveBy( xOffset(), yOffset() );
|
|
|
|
KoPoint tl = rect.topLeft();
|
|
KoPoint br = rect.bottomRight();
|
|
|
|
double tmp;
|
|
int left_col;
|
|
int right_col;
|
|
//Philipp: I don't know why we need the +1, but otherwise we don't get it correctly
|
|
//Testcase: Move a dialog slowly up left. Sometimes the top/left most points are not painted
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
right_col = sheet->leftColumn( dwidth - tl.x(), tmp );
|
|
left_col = sheet->rightColumn( dwidth - br.x() + 1.0 );
|
|
}
|
|
else
|
|
{
|
|
left_col = sheet->leftColumn( tl.x(), tmp );
|
|
right_col = sheet->rightColumn( br.x() + 1.0 );
|
|
}
|
|
int top_row = sheet->topRow( tl.y(), tmp );
|
|
int bottom_row = sheet->bottomRow( br.y() + 1.0 );
|
|
|
|
TQRect vr( TQPoint(left_col, top_row),
|
|
TQPoint(right_col, bottom_row) );
|
|
d->view->doc()->emitBeginOperation( false );
|
|
sheet->setRegionPaintDirty( vr );
|
|
d->view->doc()->emitEndOperation( vr );
|
|
}
|
|
|
|
void Canvas::focusInEvent( TQFocusEvent* )
|
|
{
|
|
if ( !d->cellEditor )
|
|
return;
|
|
|
|
//kdDebug(36001) << "d->chooseCell : " << ( d->chooseCell ? "true" : "false" ) << endl;
|
|
// If we are in editing mode, we redirect the
|
|
// focus to the CellEditor or EditWidget
|
|
// And we know which, using lastEditorWithFocus.
|
|
// This screws up <Tab> though (David)
|
|
if ( lastEditorWithFocus() == EditWidget )
|
|
{
|
|
d->editWidget->setFocus();
|
|
//kdDebug(36001) << "Focus to EditWidget" << endl;
|
|
return;
|
|
}
|
|
|
|
//kdDebug(36001) << "Redirecting focus to editor" << endl;
|
|
d->cellEditor->setFocus();
|
|
}
|
|
|
|
void Canvas::focusOutEvent( TQFocusEvent* )
|
|
{
|
|
if ( d->scrollTimer->isActive() )
|
|
d->scrollTimer->stop();
|
|
d->mousePressed = false;
|
|
d->view->disableAutoScroll();
|
|
}
|
|
|
|
void Canvas::dragMoveEvent( TQDragMoveEvent * _ev )
|
|
{
|
|
Sheet * sheet = activeSheet();
|
|
if ( !sheet )
|
|
{
|
|
_ev->ignore();
|
|
return;
|
|
}
|
|
|
|
_ev->accept( TextDrag::canDecode( _ev ) );
|
|
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() );
|
|
double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() );
|
|
double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this );
|
|
double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this );
|
|
|
|
TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3);
|
|
|
|
double ev_PosX;
|
|
if (sheet->layoutDirection()==Sheet::RightToLeft)
|
|
ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
else
|
|
ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
|
|
double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
|
|
|
|
if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) )
|
|
_ev->ignore( r1 );
|
|
}
|
|
|
|
void Canvas::dragLeaveEvent( TQDragLeaveEvent * )
|
|
{
|
|
if ( d->scrollTimer->isActive() )
|
|
d->scrollTimer->stop();
|
|
}
|
|
|
|
void Canvas::dropEvent( TQDropEvent * _ev )
|
|
{
|
|
d->dragging = false;
|
|
if ( d->scrollTimer->isActive() )
|
|
d->scrollTimer->stop();
|
|
Sheet * sheet = activeSheet();
|
|
if ( !sheet || sheet->isProtected() )
|
|
{
|
|
_ev->ignore();
|
|
return;
|
|
}
|
|
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() );
|
|
double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() );
|
|
double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this );
|
|
double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this );
|
|
|
|
TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3);
|
|
|
|
double ev_PosX;
|
|
if (sheet->layoutDirection()==Sheet::RightToLeft)
|
|
ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
else
|
|
ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
|
|
|
|
double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
|
|
|
|
if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) )
|
|
{
|
|
_ev->ignore( );
|
|
return;
|
|
}
|
|
else
|
|
_ev->accept( );
|
|
|
|
double tmp;
|
|
int col = sheet->leftColumn( ev_PosX, tmp );
|
|
int row = sheet->topRow( ev_PosY, tmp );
|
|
|
|
if ( !TextDrag::canDecode( _ev ) )
|
|
{
|
|
_ev->ignore();
|
|
return;
|
|
}
|
|
|
|
TQByteArray b;
|
|
|
|
bool makeUndo = true;
|
|
|
|
if ( _ev->provides( TextDrag::selectionMimeType() ) )
|
|
{
|
|
if ( TextDrag::target() == _ev->source() )
|
|
{
|
|
if ( !d->view->doc()->undoLocked() )
|
|
{
|
|
UndoDragDrop * undo
|
|
= new UndoDragDrop(d->view->doc(), sheet, *selectionInfo(),
|
|
TQRect(col, row,
|
|
selectionInfo()->boundingRect().width(),
|
|
selectionInfo()->boundingRect().height()));
|
|
d->view->doc()->addCommand( undo );
|
|
makeUndo = false;
|
|
}
|
|
sheet->deleteSelection( selectionInfo(), false );
|
|
}
|
|
|
|
|
|
b = _ev->encodedData( TextDrag::selectionMimeType() );
|
|
sheet->paste( b, TQRect( col, row, 1, 1 ), makeUndo );
|
|
|
|
if ( _ev->source() == this )
|
|
_ev->acceptAction();
|
|
_ev->accept();
|
|
}
|
|
else
|
|
{
|
|
TQString text;
|
|
if ( !TQTextDrag::decode( _ev, text ) )
|
|
{
|
|
_ev->ignore();
|
|
return;
|
|
}
|
|
// if ( TextDrag::target() == _ev->source() )
|
|
// sheet->deleteSelection( selectionInfo() );
|
|
|
|
sheet->pasteTextPlain( text, TQRect( col, row, 1, 1 ) );
|
|
_ev->accept();
|
|
if ( _ev->source() == this )
|
|
_ev->acceptAction();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Canvas::resizeEvent( TQResizeEvent* _ev )
|
|
{
|
|
if (!activeSheet())
|
|
return;
|
|
|
|
|
|
double ev_Width = d->view->doc()->unzoomItX( _ev->size().width() );
|
|
double ev_Height = d->view->doc()->unzoomItY( _ev->size().height() );
|
|
|
|
// workaround to allow horizontal resizing and zoom changing when sheet
|
|
// direction and interface direction don't match (e.g. an RTL sheet on an
|
|
// LTR interface)
|
|
if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() )
|
|
{
|
|
int dx = _ev->size().width() - _ev->oldSize().width();
|
|
scroll(dx, 0);
|
|
}
|
|
else if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() )
|
|
{
|
|
int dx = _ev->size().width() - _ev->oldSize().width();
|
|
scroll(-dx, 0);
|
|
}
|
|
|
|
// If we rise horizontally, then check if we are still within the valid area (KS_colMax)
|
|
if ( _ev->size().width() > _ev->oldSize().width() )
|
|
{
|
|
int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value();
|
|
|
|
if ( ( xOffset() + ev_Width ) >
|
|
d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) )
|
|
{
|
|
horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) );
|
|
if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
|
|
horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue );
|
|
}
|
|
}
|
|
// If we lower vertically, then check if the range should represent the maximum range
|
|
else if ( _ev->size().width() < _ev->oldSize().width() )
|
|
{
|
|
int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value();
|
|
|
|
if ( horzScrollBar()->maxValue() ==
|
|
int( d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) - ev_Width ) )
|
|
{
|
|
horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) );
|
|
if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
|
|
horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue );
|
|
}
|
|
}
|
|
|
|
// If we rise vertically, then check if we are still within the valid area (KS_rowMax)
|
|
if ( _ev->size().height() > _ev->oldSize().height() )
|
|
{
|
|
if ( ( yOffset() + ev_Height ) >
|
|
d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) )
|
|
{
|
|
vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) );
|
|
}
|
|
}
|
|
// If we lower vertically, then check if the range should represent the maximum range
|
|
else if ( _ev->size().height() < _ev->oldSize().height() )
|
|
{
|
|
if ( vertScrollBar()->maxValue() ==
|
|
int( d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) - ev_Height ) )
|
|
{
|
|
vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
TQPoint Canvas::cursorPos()
|
|
{
|
|
TQPoint cursor;
|
|
if (d->chooseCell && !choice()->isEmpty())
|
|
cursor = choice()->cursor();
|
|
else
|
|
cursor = selectionInfo()->cursor();
|
|
|
|
return cursor;
|
|
}
|
|
|
|
TQRect Canvas::moveDirection( KSpread::MoveTo direction, bool extendSelection )
|
|
{
|
|
kdDebug(36001) << "Canvas::moveDirection" << endl;
|
|
|
|
TQPoint destination;
|
|
TQPoint cursor = cursorPos();
|
|
|
|
TQPoint cellCorner = cursor;
|
|
Cell* cell = activeSheet()->cellAt(cursor.x(), cursor.y());
|
|
|
|
/* cell is either the same as the marker, or the cell that is forced obscuring
|
|
the marker cell
|
|
*/
|
|
if (cell->isPartOfMerged())
|
|
{
|
|
cell = cell->obscuringCells().first();
|
|
cellCorner = TQPoint(cell->column(), cell->row());
|
|
}
|
|
|
|
/* how many cells must we move to get to the next cell? */
|
|
int offset = 0;
|
|
RowFormat *rl = NULL;
|
|
ColumnFormat *cl = NULL;
|
|
switch (direction)
|
|
/* for each case, figure out how far away the next cell is and then keep
|
|
going one row/col at a time after that until a visible row/col is found
|
|
|
|
NEVER use cell->column() or cell->row() -- it might be a default cell
|
|
*/
|
|
{
|
|
case KSpread::Bottom:
|
|
offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1;
|
|
rl = activeSheet()->rowFormat( cursor.y() + offset );
|
|
while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide())
|
|
{
|
|
offset++;
|
|
rl = activeSheet()->rowFormat( cursor.y() + offset );
|
|
}
|
|
|
|
destination = TQPoint(cursor.x(), TQMIN(cursor.y() + offset, KS_rowMax));
|
|
break;
|
|
case KSpread::Top:
|
|
offset = (cellCorner.y() - cursor.y()) - 1;
|
|
rl = activeSheet()->rowFormat( cursor.y() + offset );
|
|
while ( ((cursor.y() + offset) >= 1) && rl->isHide())
|
|
{
|
|
offset--;
|
|
rl = activeSheet()->rowFormat( cursor.y() + offset );
|
|
}
|
|
destination = TQPoint(cursor.x(), TQMAX(cursor.y() + offset, 1));
|
|
break;
|
|
case KSpread::Left:
|
|
offset = (cellCorner.x() - cursor.x()) - 1;
|
|
cl = activeSheet()->columnFormat( cursor.x() + offset );
|
|
while ( ((cursor.x() + offset) >= 1) && cl->isHide())
|
|
{
|
|
offset--;
|
|
cl = activeSheet()->columnFormat( cursor.x() + offset );
|
|
}
|
|
destination = TQPoint(TQMAX(cursor.x() + offset, 1), cursor.y());
|
|
break;
|
|
case KSpread::Right:
|
|
offset = cell->mergedXCells() - (cursor.x() - cellCorner.x()) + 1;
|
|
cl = activeSheet()->columnFormat( cursor.x() + offset );
|
|
while ( ((cursor.x() + offset) <= KS_colMax) && cl->isHide())
|
|
{
|
|
offset++;
|
|
cl = activeSheet()->columnFormat( cursor.x() + offset );
|
|
}
|
|
destination = TQPoint(TQMIN(cursor.x() + offset, KS_colMax), cursor.y());
|
|
break;
|
|
case KSpread::BottomFirst:
|
|
offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1;
|
|
rl = activeSheet()->rowFormat( cursor.y() + offset );
|
|
while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide())
|
|
{
|
|
++offset;
|
|
rl = activeSheet()->rowFormat( cursor.y() + offset );
|
|
}
|
|
|
|
destination = TQPoint( 1, TQMIN( cursor.y() + offset, KS_rowMax ) );
|
|
break;
|
|
}
|
|
|
|
if (extendSelection)
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->update(destination);
|
|
}
|
|
else
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
|
|
}
|
|
d->view->updateEditWidget();
|
|
|
|
return TQRect( cursor, destination );
|
|
}
|
|
|
|
void Canvas::processEnterKey(TQKeyEvent* event)
|
|
{
|
|
// array is true, if ctrl+alt are pressed
|
|
bool array = (event->state() & TQt::AltButton) &&
|
|
(event->state() & TQt::ControlButton);
|
|
|
|
/* save changes to the current editor */
|
|
if (!d->chooseCell)
|
|
{
|
|
deleteEditor(true, array);
|
|
}
|
|
|
|
/* use the configuration setting to see which direction we're supposed to move
|
|
when enter is pressed.
|
|
*/
|
|
KSpread::MoveTo direction = d->view->doc()->getMoveToValue();
|
|
|
|
//if shift Button clicked inverse move direction
|
|
if (event->state() & TQt::ShiftButton)
|
|
{
|
|
switch( direction )
|
|
{
|
|
case KSpread::Bottom:
|
|
direction = KSpread::Top;
|
|
break;
|
|
case KSpread::Top:
|
|
direction = KSpread::Bottom;
|
|
break;
|
|
case KSpread::Left:
|
|
direction = KSpread::Right;
|
|
break;
|
|
case KSpread::Right:
|
|
direction = KSpread::Left;
|
|
break;
|
|
case KSpread::BottomFirst:
|
|
direction = KSpread::BottomFirst;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* never extend a selection with the enter key -- the shift key reverses
|
|
direction, not extends the selection
|
|
*/
|
|
TQRect r( moveDirection( direction, false ) );
|
|
d->view->doc()->emitEndOperation( r );
|
|
}
|
|
|
|
void Canvas::processArrowKey( TQKeyEvent *event)
|
|
{
|
|
/* NOTE: hitting the tab key also calls this function. Don't forget
|
|
to account for it
|
|
*/
|
|
|
|
/* save changes to the current editor */
|
|
if (!d->chooseCell)
|
|
{
|
|
deleteEditor( true );
|
|
}
|
|
|
|
KSpread::MoveTo direction = KSpread::Bottom;
|
|
bool makingSelection = event->state() & ShiftButton;
|
|
|
|
switch (event->key())
|
|
{
|
|
case Key_Down:
|
|
direction = KSpread::Bottom;
|
|
break;
|
|
case Key_Up:
|
|
direction = KSpread::Top;
|
|
break;
|
|
case Key_Left:
|
|
if (activeSheet()->layoutDirection()==Sheet::RightToLeft)
|
|
direction = KSpread::Right;
|
|
else
|
|
direction = KSpread::Left;
|
|
break;
|
|
case Key_Right:
|
|
if (activeSheet()->layoutDirection()==Sheet::RightToLeft)
|
|
direction = KSpread::Left;
|
|
else
|
|
direction = KSpread::Right;
|
|
break;
|
|
case Key_Tab:
|
|
direction = KSpread::Right;
|
|
break;
|
|
case Key_Backtab:
|
|
//Shift+Tab moves to the left
|
|
direction = KSpread::Left;
|
|
makingSelection = false;
|
|
break;
|
|
default:
|
|
Q_ASSERT(false);
|
|
break;
|
|
}
|
|
|
|
TQRect r( moveDirection( direction, makingSelection ) );
|
|
d->view->doc()->emitEndOperation( r );
|
|
}
|
|
|
|
void Canvas::processEscapeKey(TQKeyEvent * event)
|
|
{
|
|
if ( d->cellEditor )
|
|
deleteEditor( false );
|
|
|
|
if ( view()->isInsertingObject() )
|
|
{
|
|
view()->resetInsertHandle();
|
|
setCursor( arrowCursor );
|
|
return;
|
|
}
|
|
|
|
event->accept(); // ?
|
|
TQPoint cursor = cursorPos();
|
|
|
|
d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
|
|
|
|
if ( d->mousePressed /*&& toolEditMode == TEM_MOUSE */)
|
|
{
|
|
switch (d->modType)
|
|
{
|
|
case MT_RESIZE_UP:
|
|
case MT_RESIZE_DN:
|
|
case MT_RESIZE_LF:
|
|
case MT_RESIZE_RT:
|
|
case MT_RESIZE_LU:
|
|
case MT_RESIZE_LD:
|
|
case MT_RESIZE_RU:
|
|
case MT_RESIZE_RD:
|
|
{
|
|
TQRect oldBoundingRect = doc()->zoomRect( d->m_resizeObject->geometry()/*getRepaintRect()*/);
|
|
d->m_resizeObject->setGeometry( d->m_rectBeforeResize );
|
|
oldBoundingRect.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) ,
|
|
(int)( -yOffset() * doc()->zoomedResolutionY()) );
|
|
|
|
activeSheet()->setRegionPaintDirty( oldBoundingRect );
|
|
repaint( oldBoundingRect );
|
|
repaintObject( d->m_resizeObject );
|
|
d->m_ratio = 0.0;
|
|
d->m_resizeObject = 0;
|
|
d->m_isResizing = false;
|
|
view()->disableAutoScroll();
|
|
d->mousePressed = false;
|
|
d->modType = MT_NONE;
|
|
break;
|
|
}
|
|
case MT_MOVE:
|
|
{
|
|
if ( d->m_isMoving )
|
|
{
|
|
KoPoint move( d->m_moveStartPoint - objectRect( false ).topLeft() );
|
|
activeSheet()->moveObject( view(), move, false );
|
|
view()->disableAutoScroll();
|
|
d->mousePressed = false;
|
|
d->modType = MT_NONE;
|
|
d->m_isMoving = false;
|
|
update();
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Canvas::processHomeKey(TQKeyEvent* event)
|
|
{
|
|
bool makingSelection = event->state() & ShiftButton;
|
|
Sheet* sheet = activeSheet();
|
|
|
|
if ( d->cellEditor )
|
|
// We are in edit mode -> go beginning of line
|
|
{
|
|
TQApplication::sendEvent( d->editWidget, event );
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
TQPoint destination;
|
|
/* start at the first used cell in the row and cycle through the right until
|
|
we find a cell that has some output text. But don't look past the current
|
|
marker.
|
|
The end result we want is to move to the left to the first cell with text,
|
|
or just to the first column if there is no more text to the left.
|
|
|
|
But why? In excel, home key sends you to the first column always.
|
|
We might want to change to that behavior.
|
|
*/
|
|
|
|
if (event->state() & ControlButton)
|
|
{
|
|
/* ctrl + Home will always just send us to location (1,1) */
|
|
destination = TQPoint( 1, 1 );
|
|
}
|
|
else
|
|
{
|
|
TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
|
|
|
|
Cell * cell = sheet->getFirstCellRow(marker.y());
|
|
while (cell != NULL && cell->column() < marker.x() && cell->isEmpty())
|
|
{
|
|
cell = sheet->getNextCellRight(cell->column(), cell->row());
|
|
}
|
|
|
|
int col = ( cell ? cell->column() : 1 );
|
|
if ( col == marker.x())
|
|
col = 1;
|
|
destination = TQPoint(col, marker.y());
|
|
}
|
|
|
|
if ( selectionInfo()->marker() == destination )
|
|
{
|
|
d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
|
|
return false;
|
|
}
|
|
|
|
if (makingSelection)
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->update(destination);
|
|
}
|
|
else
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Canvas::processEndKey( TQKeyEvent *event )
|
|
{
|
|
bool makingSelection = event->state() & ShiftButton;
|
|
Sheet* sheet = activeSheet();
|
|
Cell* cell = NULL;
|
|
TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
|
|
|
|
// move to the last used cell in the row
|
|
// We are in edit mode -> go beginning of line
|
|
if ( d->cellEditor )
|
|
{
|
|
TQApplication::sendEvent( d->editWidget, event );
|
|
d->view->doc()->emitEndOperation( TQRect( marker, marker ) );
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
int col = 1;
|
|
|
|
cell = sheet->getLastCellRow(marker.y());
|
|
while (cell != NULL && cell->column() > markerColumn() && cell->isEmpty())
|
|
{
|
|
cell = sheet->getNextCellLeft(cell->column(), cell->row());
|
|
}
|
|
|
|
col = (cell == NULL) ? KS_colMax : cell->column();
|
|
|
|
TQPoint destination( col, marker.y() );
|
|
if ( destination == marker )
|
|
{
|
|
d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
|
|
return false;
|
|
}
|
|
|
|
if (makingSelection)
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->update(destination);
|
|
}
|
|
else
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Canvas::processPriorKey(TQKeyEvent *event)
|
|
{
|
|
bool makingSelection = event->state() & ShiftButton;
|
|
if (!d->chooseCell)
|
|
{
|
|
deleteEditor( true );
|
|
}
|
|
|
|
TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
|
|
|
|
TQPoint destination(marker.x(), TQMAX(1, marker.y() - 10));
|
|
if ( destination == marker )
|
|
{
|
|
d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
|
|
return false;
|
|
}
|
|
|
|
if (makingSelection)
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->update(destination);
|
|
}
|
|
else
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Canvas::processNextKey(TQKeyEvent *event)
|
|
{
|
|
bool makingSelection = event->state() & ShiftButton;
|
|
|
|
if (!d->chooseCell)
|
|
{
|
|
deleteEditor( true /*save changes*/ );
|
|
}
|
|
|
|
TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
|
|
TQPoint destination(marker.x(), TQMAX(1, marker.y() + 10));
|
|
|
|
if ( marker == destination )
|
|
{
|
|
d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
|
|
return false;
|
|
}
|
|
|
|
if (makingSelection)
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->update(destination);
|
|
}
|
|
else
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Canvas::processDeleteKey(TQKeyEvent* /* event */)
|
|
{
|
|
if ( isObjectSelected() )
|
|
{
|
|
d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) );
|
|
d->view->deleteSelectedObjects();
|
|
return;
|
|
}
|
|
|
|
activeSheet()->clearTextSelection( selectionInfo() );
|
|
d->editWidget->setText( "" );
|
|
|
|
TQPoint cursor = cursorPos();
|
|
|
|
d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
|
|
return;
|
|
}
|
|
|
|
void Canvas::processF2Key(TQKeyEvent* /* event */)
|
|
{
|
|
d->editWidget->setFocus();
|
|
if ( d->cellEditor )
|
|
d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() - 1 );
|
|
d->editWidget->cursorForward( false );
|
|
|
|
|
|
TQPoint cursor = cursorPos();
|
|
|
|
d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
|
|
return;
|
|
}
|
|
|
|
void Canvas::processF4Key(TQKeyEvent* event)
|
|
{
|
|
/* passes F4 to the editor (if any), which will process it
|
|
*/
|
|
if ( d->cellEditor )
|
|
{
|
|
d->cellEditor->handleKeyPressEvent( event );
|
|
// d->editWidget->setFocus();
|
|
d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() );
|
|
}
|
|
TQPoint cursor = cursorPos();
|
|
|
|
d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
|
|
return;
|
|
}
|
|
|
|
void Canvas::processOtherKey(TQKeyEvent *event)
|
|
{
|
|
// No null character ...
|
|
if ( event->text().isEmpty() || !d->view->koDocument()->isReadWrite()
|
|
|| !activeSheet() || activeSheet()->isProtected() )
|
|
{
|
|
event->accept();
|
|
}
|
|
else
|
|
{
|
|
if ( !d->cellEditor && !d->chooseCell )
|
|
{
|
|
// Switch to editing mode
|
|
createEditor( CellEditor );
|
|
d->cellEditor->handleKeyPressEvent( event );
|
|
}
|
|
else if ( d->cellEditor )
|
|
d->cellEditor->handleKeyPressEvent( event );
|
|
}
|
|
|
|
TQPoint cursor = cursorPos();
|
|
|
|
d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
|
|
|
|
return;
|
|
}
|
|
|
|
bool Canvas::processControlArrowKey( TQKeyEvent *event )
|
|
{
|
|
bool makingSelection = event->state() & ShiftButton;
|
|
|
|
Sheet* sheet = activeSheet();
|
|
Cell* cell = NULL;
|
|
Cell* lastCell;
|
|
TQPoint destination;
|
|
bool searchThroughEmpty = true;
|
|
int row;
|
|
int col;
|
|
|
|
TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
|
|
|
|
/* here, we want to move to the first or last cell in the given direction that is
|
|
actually being used. Ignore empty cells and cells on hidden rows/columns */
|
|
switch ( event->key() )
|
|
{
|
|
//Ctrl+Key_Up
|
|
case Key_Up:
|
|
|
|
cell = sheet->cellAt( marker.x(), marker.y() );
|
|
if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != 1))
|
|
{
|
|
lastCell = cell;
|
|
row = marker.y()-1;
|
|
cell = sheet->cellAt(cell->column(), row);
|
|
while ((cell != NULL) && (row > 0) && (!cell->isEmpty()) )
|
|
{
|
|
if (!(sheet->rowFormat(cell->row())->isHide()))
|
|
{
|
|
lastCell = cell;
|
|
searchThroughEmpty = false;
|
|
}
|
|
row--;
|
|
if ( row > 0 )
|
|
cell = sheet->cellAt(cell->column(), row);
|
|
}
|
|
cell = lastCell;
|
|
}
|
|
if (searchThroughEmpty)
|
|
{
|
|
cell = sheet->getNextCellUp(marker.x(), marker.y());
|
|
|
|
while ((cell != NULL) &&
|
|
(cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide())))
|
|
{
|
|
cell = sheet->getNextCellUp(cell->column(), cell->row());
|
|
}
|
|
}
|
|
|
|
if (cell == NULL)
|
|
row = 1;
|
|
else
|
|
row = cell->row();
|
|
|
|
while ( sheet->rowFormat(row)->isHide() )
|
|
{
|
|
row++;
|
|
}
|
|
|
|
destination.setX(marker.x());
|
|
destination.setY(row);
|
|
break;
|
|
|
|
//Ctrl+Key_Down
|
|
case Key_Down:
|
|
|
|
cell = sheet->cellAt( marker.x(), marker.y() );
|
|
if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != KS_rowMax))
|
|
{
|
|
lastCell = cell;
|
|
row = marker.y()+1;
|
|
cell = sheet->cellAt(cell->column(), row);
|
|
while ((cell != NULL) && (row < KS_rowMax) && (!cell->isEmpty()) )
|
|
{
|
|
if (!(sheet->rowFormat(cell->row())->isHide()))
|
|
{
|
|
lastCell = cell;
|
|
searchThroughEmpty = false;
|
|
}
|
|
row++;
|
|
cell = sheet->cellAt(cell->column(), row);
|
|
}
|
|
cell = lastCell;
|
|
}
|
|
if (searchThroughEmpty)
|
|
{
|
|
cell = sheet->getNextCellDown(marker.x(), marker.y());
|
|
|
|
while ((cell != NULL) &&
|
|
(cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide())))
|
|
{
|
|
cell = sheet->getNextCellDown(cell->column(), cell->row());
|
|
}
|
|
}
|
|
|
|
if (cell == NULL)
|
|
row = marker.y();
|
|
else
|
|
row = cell->row();
|
|
|
|
while ( sheet->rowFormat(row)->isHide() )
|
|
{
|
|
row--;
|
|
}
|
|
|
|
destination.setX(marker.x());
|
|
destination.setY(row);
|
|
break;
|
|
|
|
//Ctrl+Key_Left
|
|
case Key_Left:
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
cell = sheet->cellAt( marker.x(), marker.y() );
|
|
if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax))
|
|
{
|
|
lastCell = cell;
|
|
col = marker.x()+1;
|
|
cell = sheet->cellAt(col, cell->row());
|
|
while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) )
|
|
{
|
|
if (!(sheet->columnFormat(cell->column())->isHide()))
|
|
{
|
|
lastCell = cell;
|
|
searchThroughEmpty = false;
|
|
}
|
|
col++;
|
|
cell = sheet->cellAt(col, cell->row());
|
|
}
|
|
cell = lastCell;
|
|
}
|
|
if (searchThroughEmpty)
|
|
{
|
|
cell = sheet->getNextCellRight(marker.x(), marker.y());
|
|
|
|
while ((cell != NULL) &&
|
|
(cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
|
|
{
|
|
cell = sheet->getNextCellRight(cell->column(), cell->row());
|
|
}
|
|
}
|
|
|
|
if (cell == NULL)
|
|
col = marker.x();
|
|
else
|
|
col = cell->column();
|
|
|
|
while ( sheet->columnFormat(col)->isHide() )
|
|
{
|
|
col--;
|
|
}
|
|
|
|
destination.setX(col);
|
|
destination.setY(marker.y());
|
|
}
|
|
else
|
|
{
|
|
cell = sheet->cellAt( marker.x(), marker.y() );
|
|
if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1))
|
|
{
|
|
lastCell = cell;
|
|
col = marker.x()-1;
|
|
cell = sheet->cellAt(col, cell->row());
|
|
while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) )
|
|
{
|
|
if (!(sheet->columnFormat(cell->column())->isHide()))
|
|
{
|
|
lastCell = cell;
|
|
searchThroughEmpty = false;
|
|
}
|
|
col--;
|
|
if ( col > 0 )
|
|
cell = sheet->cellAt(col, cell->row());
|
|
}
|
|
cell = lastCell;
|
|
}
|
|
if (searchThroughEmpty)
|
|
{
|
|
cell = sheet->getNextCellLeft(marker.x(), marker.y());
|
|
|
|
while ((cell != NULL) &&
|
|
(cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
|
|
{
|
|
cell = sheet->getNextCellLeft(cell->column(), cell->row());
|
|
}
|
|
}
|
|
|
|
if (cell == NULL)
|
|
col = 1;
|
|
else
|
|
col = cell->column();
|
|
|
|
while ( sheet->columnFormat(col)->isHide() )
|
|
{
|
|
col++;
|
|
}
|
|
|
|
destination.setX(col);
|
|
destination.setY(marker.y());
|
|
}
|
|
break;
|
|
|
|
//Ctrl+Key_Right
|
|
case Key_Right:
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
cell = sheet->cellAt( marker.x(), marker.y() );
|
|
if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1))
|
|
{
|
|
lastCell = cell;
|
|
col = marker.x()-1;
|
|
cell = sheet->cellAt(col, cell->row());
|
|
while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) )
|
|
{
|
|
if (!(sheet->columnFormat(cell->column())->isHide()))
|
|
{
|
|
lastCell = cell;
|
|
searchThroughEmpty = false;
|
|
}
|
|
col--;
|
|
if ( col > 0 )
|
|
cell = sheet->cellAt(col, cell->row());
|
|
}
|
|
cell = lastCell;
|
|
}
|
|
if (searchThroughEmpty)
|
|
{
|
|
cell = sheet->getNextCellLeft(marker.x(), marker.y());
|
|
|
|
while ((cell != NULL) &&
|
|
(cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
|
|
{
|
|
cell = sheet->getNextCellLeft(cell->column(), cell->row());
|
|
}
|
|
}
|
|
|
|
if (cell == NULL)
|
|
col = 1;
|
|
else
|
|
col = cell->column();
|
|
|
|
while ( sheet->columnFormat(col)->isHide() )
|
|
{
|
|
col++;
|
|
}
|
|
|
|
destination.setX(col);
|
|
destination.setY(marker.y());
|
|
}
|
|
else
|
|
{
|
|
cell = sheet->cellAt( marker.x(), marker.y() );
|
|
if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax))
|
|
{
|
|
lastCell = cell;
|
|
col = marker.x()+1;
|
|
cell = sheet->cellAt(col, cell->row());
|
|
while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) )
|
|
{
|
|
if (!(sheet->columnFormat(cell->column())->isHide()))
|
|
{
|
|
lastCell = cell;
|
|
searchThroughEmpty = false;
|
|
}
|
|
col++;
|
|
cell = sheet->cellAt(col, cell->row());
|
|
}
|
|
cell = lastCell;
|
|
}
|
|
if (searchThroughEmpty)
|
|
{
|
|
cell = sheet->getNextCellRight(marker.x(), marker.y());
|
|
|
|
while ((cell != NULL) &&
|
|
(cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
|
|
{
|
|
cell = sheet->getNextCellRight(cell->column(), cell->row());
|
|
}
|
|
}
|
|
|
|
if (cell == NULL)
|
|
col = marker.x();
|
|
else
|
|
col = cell->column();
|
|
|
|
while ( sheet->columnFormat(col)->isHide() )
|
|
{
|
|
col--;
|
|
}
|
|
|
|
destination.setX(col);
|
|
destination.setY(marker.y());
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
if ( marker == destination )
|
|
{
|
|
d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
|
|
return false;
|
|
}
|
|
|
|
if (makingSelection)
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->update(destination);
|
|
}
|
|
else
|
|
{
|
|
(d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
void Canvas::keyPressEvent ( TQKeyEvent * _ev )
|
|
{
|
|
Sheet * sheet = activeSheet();
|
|
|
|
if ( !sheet || formatKeyPress( _ev ))
|
|
return;
|
|
|
|
// Dont handle the remaining special keys.
|
|
if ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) &&
|
|
(_ev->key() != Key_Down) &&
|
|
(_ev->key() != Key_Up) &&
|
|
(_ev->key() != Key_Right) &&
|
|
(_ev->key() != Key_Left) &&
|
|
(_ev->key() != Key_Home) &&
|
|
(_ev->key() != Key_Enter) &&
|
|
(_ev->key() != Key_Return) &&
|
|
(_ev->key() != TDEGlobalSettings::contextMenuKey()))
|
|
{
|
|
TQWidget::keyPressEvent( _ev );
|
|
return;
|
|
}
|
|
|
|
// Always accept so that events are not
|
|
// passed to the parent.
|
|
_ev->accept();
|
|
|
|
d->view->doc()->emitBeginOperation(false);
|
|
if ( _ev->key() == TDEGlobalSettings::contextMenuKey() ) {
|
|
int row = markerRow();
|
|
int col = markerColumn();
|
|
KoPoint kop(sheet->columnPos(col, this), sheet->rowPos(row, this));
|
|
TQPoint p = d->view->doc()->zoomPoint(kop);
|
|
p = mapToGlobal(p);
|
|
d->view->openPopupMenu( p );
|
|
}
|
|
switch( _ev->key() )
|
|
{
|
|
case Key_Return:
|
|
case Key_Enter:
|
|
processEnterKey( _ev );
|
|
return;
|
|
break;
|
|
case Key_Down:
|
|
case Key_Up:
|
|
case Key_Left:
|
|
case Key_Right:
|
|
case Key_Tab: /* a tab behaves just like a right/left arrow */
|
|
case Key_Backtab: /* and so does Shift+Tab */
|
|
if (_ev->state() & ControlButton)
|
|
{
|
|
if ( !processControlArrowKey( _ev ) )
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
processArrowKey( _ev );
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case Key_Escape:
|
|
processEscapeKey( _ev );
|
|
return;
|
|
break;
|
|
|
|
case Key_Home:
|
|
if ( !processHomeKey( _ev ) )
|
|
return;
|
|
break;
|
|
|
|
case Key_End:
|
|
if ( !processEndKey( _ev ) )
|
|
return;
|
|
break;
|
|
|
|
case Key_Prior: /* Page Up */
|
|
if ( !processPriorKey( _ev ) )
|
|
return;
|
|
break;
|
|
|
|
case Key_Next: /* Page Down */
|
|
if ( !processNextKey( _ev ) )
|
|
return;
|
|
break;
|
|
|
|
case Key_Delete:
|
|
processDeleteKey( _ev );
|
|
return;
|
|
break;
|
|
|
|
case Key_F2:
|
|
processF2Key( _ev );
|
|
return;
|
|
break;
|
|
|
|
case Key_F4:
|
|
processF4Key( _ev );
|
|
return;
|
|
break;
|
|
|
|
default:
|
|
processOtherKey( _ev );
|
|
return;
|
|
break;
|
|
}
|
|
|
|
//most process*Key methods call emitEndOperation, this only gets called in some situations
|
|
// (after some move operations)
|
|
d->view->doc()->emitEndOperation( sheet->visibleRect( this ) );
|
|
return;
|
|
}
|
|
|
|
void Canvas::processIMEvent( TQIMEvent * event )
|
|
{
|
|
d->view->doc()->emitBeginOperation( false );
|
|
if ( !d->cellEditor && !d->chooseCell )
|
|
{
|
|
// Switch to editing mode
|
|
createEditor( CellEditor );
|
|
d->cellEditor->handleIMEvent( event );
|
|
}
|
|
|
|
TQPoint cursor;
|
|
|
|
if ( d->chooseCell )
|
|
{
|
|
cursor = choice()->cursor();
|
|
/* if the cursor is unset, pretend we're starting at the regular cursor */
|
|
if (cursor.x() == 0 || cursor.y() == 0)
|
|
cursor = choice()->cursor();
|
|
}
|
|
else
|
|
cursor = selectionInfo()->cursor();
|
|
|
|
d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
|
|
}
|
|
|
|
bool Canvas::formatKeyPress( TQKeyEvent * _ev )
|
|
{
|
|
if (!(_ev->state() & ControlButton ))
|
|
return false;
|
|
|
|
int key = _ev->key();
|
|
if ( key != Key_Exclam && key != Key_At && key != Key_Ampersand
|
|
&& key != Key_Dollar && key != Key_Percent && key != Key_AsciiCircum
|
|
&& key != Key_NumberSign )
|
|
return false;
|
|
|
|
Cell * cell = 0L;
|
|
Sheet * sheet = activeSheet();
|
|
|
|
d->view->doc()->emitBeginOperation(false);
|
|
|
|
if ( !d->view->doc()->undoLocked() )
|
|
{
|
|
TQString dummy;
|
|
UndoCellFormat * undo = new UndoCellFormat( d->view->doc(), sheet, *selectionInfo(), dummy );
|
|
d->view->doc()->addCommand( undo );
|
|
}
|
|
|
|
Region::ConstIterator end(selectionInfo()->constEnd());
|
|
for (Region::ConstIterator it = selectionInfo()->constBegin(); it != end; ++it)
|
|
{
|
|
TQRect rect = (*it)->rect().normalize();
|
|
|
|
int right = rect.right();
|
|
int bottom = rect.bottom();
|
|
|
|
if ( util_isRowSelected(rect) )
|
|
{
|
|
for ( int r = rect.top(); r <= bottom; ++r )
|
|
{
|
|
cell = sheet->getFirstCellRow( r );
|
|
while ( cell )
|
|
{
|
|
if ( cell->isPartOfMerged() )
|
|
{
|
|
cell = sheet->getNextCellRight( cell->column(), r );
|
|
continue;
|
|
}
|
|
|
|
formatCellByKey (cell, _ev->key(), rect);
|
|
|
|
cell = sheet->getNextCellRight( cell->column(), r );
|
|
} // while (cell)
|
|
RowFormat * rw = sheet->nonDefaultRowFormat( r );
|
|
TQPen pen;
|
|
switch ( _ev->key() )
|
|
{
|
|
case Key_Exclam:
|
|
rw->setFormatType (Number_format);
|
|
rw->setPrecision( 2 );
|
|
break;
|
|
|
|
case Key_Dollar:
|
|
rw->setFormatType (Money_format);
|
|
rw->setPrecision( d->view->doc()->locale()->fracDigits() );
|
|
break;
|
|
|
|
case Key_Percent:
|
|
rw->setFormatType (Percentage_format);
|
|
break;
|
|
|
|
case Key_At:
|
|
rw->setFormatType( SecondeTime_format );
|
|
break;
|
|
|
|
case Key_NumberSign:
|
|
rw->setFormatType( ShortDate_format );
|
|
break;
|
|
|
|
case Key_AsciiCircum:
|
|
rw->setFormatType( Scientific_format );
|
|
break;
|
|
|
|
case Key_Ampersand:
|
|
if ( r == rect.top() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
rw->setTopBorderPen( pen );
|
|
}
|
|
if ( r == rect.bottom() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
rw->setBottomBorderPen( pen );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
d->view->doc()->emitEndOperation( rect );
|
|
return false;
|
|
}
|
|
sheet->emit_updateRow( rw, r );
|
|
}
|
|
|
|
d->view->doc()->emitEndOperation( rect );
|
|
return true;
|
|
}
|
|
|
|
if ( util_isColumnSelected(rect) )
|
|
{
|
|
for ( int c = rect.left(); c <= right; ++c )
|
|
{
|
|
cell = sheet->getFirstCellColumn( c );
|
|
while ( cell )
|
|
{
|
|
if ( cell->isPartOfMerged() )
|
|
{
|
|
cell = sheet->getNextCellDown( c, cell->row() );
|
|
continue;
|
|
}
|
|
|
|
formatCellByKey (cell, _ev->key(), rect);
|
|
|
|
cell = sheet->getNextCellDown( c, cell->row() );
|
|
}
|
|
|
|
ColumnFormat * cw = sheet->nonDefaultColumnFormat( c );
|
|
TQPen pen;
|
|
switch ( _ev->key() )
|
|
{
|
|
case Key_Exclam:
|
|
cw->setFormatType( Number_format );
|
|
cw->setPrecision( 2 );
|
|
break;
|
|
|
|
case Key_Dollar:
|
|
cw->setFormatType( Money_format );
|
|
cw->setPrecision( d->view->doc()->locale()->fracDigits() );
|
|
break;
|
|
|
|
case Key_Percent:
|
|
cw->setFormatType( Percentage_format );
|
|
break;
|
|
|
|
case Key_At:
|
|
cw->setFormatType( SecondeTime_format );
|
|
break;
|
|
|
|
case Key_NumberSign:
|
|
cw->setFormatType( ShortDate_format );
|
|
break;
|
|
|
|
case Key_AsciiCircum:
|
|
cw->setFormatType( Scientific_format );
|
|
break;
|
|
|
|
case Key_Ampersand:
|
|
if ( c == rect.left() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
cw->setLeftBorderPen( pen );
|
|
}
|
|
if ( c == rect.right() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
cw->setRightBorderPen( pen );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
d->view->doc()->emitEndOperation( rect );
|
|
return false;
|
|
}
|
|
sheet->emit_updateColumn( cw, c );
|
|
}
|
|
d->view->doc()->emitEndOperation( rect );
|
|
return true;
|
|
}
|
|
|
|
for ( int row = rect.top(); row <= bottom; ++row )
|
|
{
|
|
for ( int col = rect.left(); col <= right; ++ col )
|
|
{
|
|
cell = sheet->nonDefaultCell( col, row );
|
|
|
|
if ( cell->isPartOfMerged() )
|
|
continue;
|
|
|
|
formatCellByKey (cell, _ev->key(), rect);
|
|
} // for left .. right
|
|
} // for top .. bottom
|
|
|
|
}
|
|
_ev->accept();
|
|
|
|
d->view->doc()->emitEndOperation( *selectionInfo() );
|
|
return true;
|
|
}
|
|
|
|
bool Canvas::formatCellByKey (Cell *cell, int key, const TQRect &rect)
|
|
{
|
|
TQPen pen;
|
|
switch (key)
|
|
{
|
|
case Key_Exclam:
|
|
cell->convertToDouble ();
|
|
cell->format()->setFormatType (Number_format);
|
|
cell->format()->setPrecision( 2 );
|
|
break;
|
|
|
|
case Key_Dollar:
|
|
cell->convertToMoney ();
|
|
break;
|
|
|
|
case Key_Percent:
|
|
cell->convertToPercent ();
|
|
break;
|
|
|
|
case Key_At:
|
|
cell->convertToTime ();
|
|
break;
|
|
|
|
case Key_NumberSign:
|
|
cell->convertToDate ();
|
|
break;
|
|
|
|
case Key_AsciiCircum:
|
|
cell->format()->setFormatType (Scientific_format);
|
|
cell->convertToDouble ();
|
|
break;
|
|
|
|
case Key_Ampersand:
|
|
if ( cell->row() == rect.top() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
cell->setTopBorderPen( pen );
|
|
}
|
|
if ( cell->row() == rect.bottom() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
cell->setBottomBorderPen( pen );
|
|
}
|
|
if ( cell->column() == rect.left() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
cell->setLeftBorderPen( pen );
|
|
}
|
|
if ( cell->column() == rect.right() )
|
|
{
|
|
pen = TQPen( d->view->borderColor(), 1, SolidLine);
|
|
cell->setRightBorderPen( pen );
|
|
}
|
|
break;
|
|
} // switch
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void Canvas::slotAutoScroll(const TQPoint &scrollDistance)
|
|
{
|
|
TQPoint d = scrollDistance;
|
|
horzScrollBar()->setValue( horzScrollBar()->value() + d.x() );
|
|
vertScrollBar()->setValue( vertScrollBar()->value() + d.y() );
|
|
}
|
|
|
|
void Canvas::doAutoScroll()
|
|
{
|
|
if ( !d->mousePressed )
|
|
{
|
|
d->scrollTimer->stop();
|
|
return;
|
|
}
|
|
bool select = false;
|
|
TQPoint pos = mapFromGlobal( TQCursor::pos() );
|
|
|
|
//Provide progressive scrolling depending on the mouse position
|
|
if ( pos.y() < 0 )
|
|
{
|
|
vertScrollBar()->setValue ((int) (vertScrollBar()->value() -
|
|
autoScrollAccelerationY( - pos.y())));
|
|
select = true;
|
|
}
|
|
else if ( pos.y() > height() )
|
|
{
|
|
vertScrollBar()->setValue ((int) (vertScrollBar()->value() +
|
|
autoScrollAccelerationY (pos.y() - height())));
|
|
select = true;
|
|
}
|
|
|
|
if ( pos.x() < 0 )
|
|
{
|
|
horzScrollBar()->setValue ((int) (horzScrollBar()->value() -
|
|
autoScrollAccelerationX( - pos.x() )));
|
|
select = true;
|
|
}
|
|
else if ( pos.x() > width() )
|
|
{
|
|
horzScrollBar()->setValue ((int) (horzScrollBar()->value() +
|
|
autoScrollAccelerationX( pos.x() - width())));
|
|
select = true;
|
|
}
|
|
|
|
if ( select )
|
|
{
|
|
TQMouseEvent * event = new TQMouseEvent(TQEvent::MouseMove, pos, 0, 0);
|
|
mouseMoveEvent( event );
|
|
delete event;
|
|
}
|
|
|
|
//Restart timer
|
|
d->scrollTimer->start( 50 );
|
|
}
|
|
|
|
void Canvas::speakCell(TQWidget* w, const TQPoint& p, uint flags)
|
|
{
|
|
Q_UNUSED(flags);
|
|
if (w != this) return;
|
|
Sheet* sheet = activeSheet();
|
|
if (!sheet) return;
|
|
int row = -1;
|
|
int col = -1;
|
|
if (p == TQPoint()) {
|
|
row = markerRow();
|
|
col = markerColumn();
|
|
if (row == d->prevSpokenFocusRow && col == d->prevSpokenFocusCol) return;
|
|
d->prevSpokenFocusRow = row;
|
|
d->prevSpokenFocusCol = col;
|
|
} else {
|
|
TQPoint wp = w->mapFromGlobal(p);
|
|
double tmp;
|
|
double posX;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
posX = dwidth - d->view->doc()->unzoomItX( wp.x() );
|
|
}
|
|
else
|
|
posX = d->view->doc()->unzoomItX( wp.x() );
|
|
|
|
double posY = d->view->doc()->unzoomItY( wp.y() );
|
|
col = sheet->leftColumn( (posX + xOffset()), tmp );
|
|
row = sheet->topRow( (posY + yOffset()), tmp );
|
|
if (row == d->prevSpokenPointerRow && col == d->prevSpokenPointerCol) return;
|
|
d->prevSpokenPointerRow = row;
|
|
d->prevSpokenPointerCol = col;
|
|
}
|
|
if (row == d->prevSpokenRow && col == d->prevSpokenCol) return;
|
|
d->prevSpokenRow = row;
|
|
d->prevSpokenCol = col;
|
|
// kdDebug() << "Canvas::speakCell: row = " << row << " col = " << col << endl;
|
|
if (row >=0 && col >= 0) {
|
|
Cell* cell = sheet->cellAt( col, row );
|
|
if (!cell) return;
|
|
TQString text = cell->strOutText();
|
|
if (!text.isEmpty()) {
|
|
text.prepend(i18n("Spreadsheet cell", "Cell ") + cell->name() + " ");
|
|
if (cell->isFormula()) {
|
|
TQString f = cell->text();
|
|
// Try to format the formula so synth can more clearly speak it.
|
|
TQString f2;
|
|
for (uint i = 0; i < f.length(); i++) f2 += f[i] + " ";
|
|
f2.replace("(", i18n("character (", "left paren"));
|
|
f2.replace(")", i18n("character )", "right paren"));
|
|
f2.replace(":", i18n("character :", "colon"));
|
|
f2.replace(";", i18n("character ;", "semicolon"));
|
|
f2.replace("=", i18n("character =", "equals"));
|
|
f2.replace(".", i18n("character .", "point"));
|
|
f2.replace(",", i18n("character ,", "comma"));
|
|
f2.replace(" . . ", i18n("characters ..", " dot dot "));
|
|
text.append(i18n("Spreadsheet formula", " Formula ") + f2);
|
|
}
|
|
// kdDebug() << "Canvas::speakCell: text = " << text << endl;
|
|
kospeaker->sayWidget(text);
|
|
}
|
|
}
|
|
}
|
|
|
|
double Canvas::autoScrollAccelerationX( int offset )
|
|
{
|
|
switch( static_cast<int>( offset / 20 ) )
|
|
{
|
|
case 0: return 5.0;
|
|
case 1: return 20.0;
|
|
case 2: return d->view->doc()->unzoomItX( width() );
|
|
case 3: return d->view->doc()->unzoomItX( width() );
|
|
default: return d->view->doc()->unzoomItX( (int) (width() * 5.0) );
|
|
}
|
|
}
|
|
|
|
double Canvas::autoScrollAccelerationY( int offset )
|
|
{
|
|
switch( static_cast<int>( offset / 20 ) )
|
|
{
|
|
case 0: return 5.0;
|
|
case 1: return 20.0;
|
|
case 2: return d->view->doc()->unzoomItY( height() );
|
|
case 3: return d->view->doc()->unzoomItY( height() );
|
|
default: return d->view->doc()->unzoomItY( (int) (height() * 5.0) );
|
|
}
|
|
}
|
|
|
|
|
|
KSpread::EmbeddedObject *Canvas::getObject( const TQPoint &pos, Sheet *_sheet )
|
|
{
|
|
TQPoint const p ( (int) pos.x() ,
|
|
(int) pos.y() );
|
|
|
|
TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
|
|
for( ; itObject.current(); ++itObject )
|
|
{
|
|
if ( itObject.current()->sheet() == _sheet )
|
|
{
|
|
KoRect const bound = ( itObject.current() )->geometry();
|
|
TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(),
|
|
bound.width(),
|
|
bound.height() ) );
|
|
zoomedBound.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ), (int)( -yOffset() * doc()->zoomedResolutionY() ) );
|
|
if ( zoomedBound.contains( p ) )
|
|
return itObject.current();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void Canvas::selectObject( EmbeddedObject *obj )
|
|
{
|
|
if ( obj->sheet() != activeSheet() || obj->isSelected() )
|
|
return;
|
|
obj->setSelected( true );
|
|
repaintObject( obj );
|
|
|
|
d->mouseSelectedObject = true;
|
|
emit objectSelectedChanged();
|
|
deleteEditor( true );
|
|
}
|
|
|
|
void Canvas::deselectObject( EmbeddedObject *obj )
|
|
{
|
|
if ( obj->sheet() != activeSheet() || !obj->isSelected() )
|
|
return;
|
|
obj->setSelected( false );
|
|
repaintObject( obj );
|
|
|
|
d->mouseSelectedObject = false;
|
|
emit objectSelectedChanged();
|
|
}
|
|
|
|
void Canvas::selectAllObjects()
|
|
{
|
|
TQPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
|
|
for ( ; it.current() ; ++it )
|
|
{
|
|
if ( it.current()->sheet() == activeSheet() )
|
|
it.current()->setSelected( true );
|
|
}
|
|
|
|
d->mouseSelectedObject = true;
|
|
// emit objectSelectedChanged();
|
|
}
|
|
|
|
void Canvas::deselectAllObjects()
|
|
{
|
|
if( activeSheet()->numSelected() == 0 )
|
|
return;
|
|
|
|
//lowerObject();
|
|
|
|
TQPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
|
|
for ( ; it.current() ; ++it )
|
|
deselectObject( it.current() );
|
|
|
|
d->mouseSelectedObject = false;
|
|
// emit objectSelectedChanged();
|
|
}
|
|
|
|
|
|
|
|
void Canvas::setMouseSelectedObject(bool b)
|
|
{
|
|
d->mouseSelectedObject = b;
|
|
emit objectSelectedChanged();
|
|
}
|
|
|
|
bool Canvas::isObjectSelected()
|
|
{
|
|
return d->mouseSelectedObject;
|
|
}
|
|
|
|
|
|
void Canvas::moveObjectsByMouse( KoPoint &pos, bool keepXorYunchanged )
|
|
{
|
|
KoRect rect( objectRect( false ) );
|
|
KoPoint move( 0, 0 );
|
|
double diffx = pos.x() - d->m_origMousePos.x();
|
|
double diffy = pos.y() - d->m_origMousePos.y();
|
|
|
|
move = KoPoint( diffx, diffy );
|
|
d->m_origMousePos = pos;
|
|
|
|
// unwind last snapping
|
|
KoRect movedRect( rect );
|
|
movedRect.moveBy( diffx, diffy );
|
|
|
|
// don't move object off canvas
|
|
KoPoint diffDueToBorders(0,0);
|
|
// KoRect pageRect( m_activePage->getPageRect() );
|
|
if ( rect.left() + move.x() < 0/*pageRect.left()*/ )
|
|
diffDueToBorders.setX( -rect.left() - move.x() );
|
|
// else if ( rect.right() + move.x() > pageRect.right() )
|
|
// diffDueToBorders.setX( pageRect.right() - (rect.right() + move.x()) );
|
|
|
|
|
|
//kdDebug() << "rect.top() + move.y():" << rect.top() + move.y()<< endl;
|
|
if ( rect.top() + move.y() < 0 )
|
|
diffDueToBorders.setY( -rect.top() - move.y() );
|
|
// else if ( rect.bottom() + move.y() > pageRect.bottom() )
|
|
// diffDueToBorders.setY( pageRect.bottom() - (rect.bottom() + move.y()) );
|
|
|
|
// m_moveSnapDiff += diffDueToBorders;
|
|
move += diffDueToBorders;
|
|
|
|
// movedRect.moveBy( m_moveSnapDiff.x(), m_moveSnapDiff.y() );
|
|
if ( keepXorYunchanged )
|
|
{
|
|
KoPoint diff( d->m_moveStartPosMouse - movedRect.topLeft() );
|
|
if ( fabs( diff.x() ) > fabs( diff.y() ) )
|
|
{
|
|
// m_moveSnapDiff.setY( /*m_moveSnapDiff.y() + */m_moveStartPosMouse.y() - movedRect.y() );
|
|
movedRect.moveTopLeft( KoPoint( movedRect.x(), d->m_moveStartPosMouse.y() ) );
|
|
move.setY( movedRect.y() - rect.y() );
|
|
}
|
|
else
|
|
{
|
|
// m_moveSnapDiff.setX( /*m_moveSnapDiff.x() + */m_moveStartPosMouse.x() - movedRect.x() );
|
|
movedRect.moveTopLeft( KoPoint( d->m_moveStartPosMouse.x(), movedRect.y() ) );
|
|
move.setX( movedRect.x() - rect.x() );
|
|
}
|
|
}
|
|
|
|
if ( move != KoPoint( 0, 0 ) )
|
|
{
|
|
//kdDebug(33001) << "moveObjectsByMouse move = " << move << endl;
|
|
activeSheet()->moveObject( view(), move, false );
|
|
}
|
|
}
|
|
|
|
|
|
void Canvas::resizeObject( ModifyType _modType, const KoPoint & point, bool keepRatio )
|
|
{
|
|
EmbeddedObject *obj = d->m_resizeObject;
|
|
|
|
KoRect objRect = obj->geometry();
|
|
objRect.moveBy( -xOffset(), -yOffset() );
|
|
TQRect oldBoundingRect( doc()->zoomRect( objRect ) );
|
|
|
|
bool left = false;
|
|
bool right = false;
|
|
bool top = false;
|
|
bool bottom = false;
|
|
if ( _modType == MT_RESIZE_UP || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_RU )
|
|
{
|
|
top = true;
|
|
// snapStatus |= KoGuides::SNAP_HORIZ;
|
|
}
|
|
if ( _modType == MT_RESIZE_DN || _modType == MT_RESIZE_LD || _modType == MT_RESIZE_RD )
|
|
{
|
|
bottom = true;
|
|
// snapStatus |= KoGuides::SNAP_HORIZ;
|
|
}
|
|
if ( _modType == MT_RESIZE_LF || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_LD )
|
|
{
|
|
left = true;
|
|
// snapStatus |= KoGuides::SNAP_VERT;
|
|
}
|
|
if ( _modType == MT_RESIZE_RT || _modType == MT_RESIZE_RU || _modType == MT_RESIZE_RD )
|
|
{
|
|
right = true;
|
|
// snapStatus |= KoGuides::SNAP_VERT;
|
|
}
|
|
|
|
double newLeft = objRect.left();
|
|
double newRight = objRect.right();
|
|
double newTop = objRect.top();
|
|
double newBottom = objRect.bottom();
|
|
if ( top )
|
|
{
|
|
if ( point.y() < objRect.bottom() - MIN_SIZE )
|
|
{
|
|
newTop = point.y();
|
|
}
|
|
else
|
|
{
|
|
newTop = objRect.bottom() - MIN_SIZE;
|
|
}
|
|
}
|
|
if ( bottom )
|
|
{
|
|
if ( point.y() > objRect.top() + MIN_SIZE )
|
|
{
|
|
newBottom = point.y();
|
|
}
|
|
else
|
|
{
|
|
newBottom = objRect.top() + MIN_SIZE;
|
|
}
|
|
}
|
|
if ( left )
|
|
{
|
|
if ( point.x() < objRect.right() - MIN_SIZE )
|
|
{
|
|
newLeft = point.x();
|
|
}
|
|
else
|
|
{
|
|
newLeft = objRect.right() - MIN_SIZE;
|
|
}
|
|
}
|
|
if ( right )
|
|
{
|
|
if ( point.x() > objRect.left() + MIN_SIZE )
|
|
{
|
|
newRight = point.x();
|
|
}
|
|
else
|
|
{
|
|
newRight = objRect.left() + MIN_SIZE;
|
|
}
|
|
}
|
|
|
|
double width = newRight - newLeft;
|
|
double height = newBottom - newTop;
|
|
|
|
if ( keepRatio && d->m_ratio != 0 )
|
|
{
|
|
if ( ( top || bottom ) && ( right || left ) )
|
|
{
|
|
if ( height * height * d->m_ratio > width * width / d->m_ratio )
|
|
{
|
|
width = height * d->m_ratio;
|
|
}
|
|
else
|
|
{
|
|
height = width / d->m_ratio;
|
|
}
|
|
}
|
|
else if ( top || bottom )
|
|
{
|
|
width = height * d->m_ratio;
|
|
}
|
|
else
|
|
{
|
|
height = width / d->m_ratio;
|
|
}
|
|
|
|
if ( top )
|
|
{
|
|
newTop = objRect.bottom() - height;
|
|
}
|
|
else
|
|
{
|
|
newBottom = objRect.top() + height;
|
|
}
|
|
if ( left )
|
|
{
|
|
newLeft = objRect.right() - width;
|
|
}
|
|
else
|
|
{
|
|
newRight = objRect.right() + width;
|
|
}
|
|
}
|
|
|
|
if ( newLeft != objRect.left() || newRight != objRect.right() || newTop != objRect.top() || newBottom != objRect.bottom() )
|
|
{
|
|
// resizeBy and moveBy have to been used to make it work with rotated objects
|
|
obj->resizeBy( width - objRect.width(), height - objRect.height() );
|
|
|
|
if ( objRect.left() != newLeft || objRect.top() != newTop )
|
|
{
|
|
obj->moveBy( KoPoint( newLeft - objRect.left(), newTop - objRect.top() ) );
|
|
}
|
|
|
|
// if ( doc()->showGuideLines() && !m_disableSnapping )
|
|
// {
|
|
// KoRect rect( obj->getRealRect() );
|
|
// KoPoint sp( rect.topLeft() );
|
|
// if ( right )
|
|
// {
|
|
// sp.setX( rect.right() );
|
|
// }
|
|
// if ( bottom )
|
|
// {
|
|
// sp.setY( rect.bottom() );
|
|
// }
|
|
// m_gl.repaintSnapping( sp, snapStatus );
|
|
// }
|
|
|
|
repaint( oldBoundingRect );
|
|
repaintObject( obj );
|
|
emit objectSizeChanged();
|
|
}
|
|
}
|
|
|
|
|
|
void Canvas::finishResizeObject( const TQString &/*name*/, bool /*layout*/ )
|
|
{
|
|
if ( d->m_resizeObject )
|
|
{
|
|
KoPoint move = KoPoint( d->m_resizeObject->geometry().x() - d->m_rectBeforeResize.x(),
|
|
d->m_resizeObject->geometry().y() - d->m_rectBeforeResize.y() );
|
|
KoSize size = KoSize( d->m_resizeObject->geometry().width() - d->m_rectBeforeResize.width(),
|
|
d->m_resizeObject->geometry().height() - d->m_rectBeforeResize.height() );
|
|
|
|
if ( ( d->m_resizeObject->geometry() ) != d->m_rectBeforeResize )
|
|
{
|
|
ChangeObjectGeometryCommand *resizeCmd = new ChangeObjectGeometryCommand( d->m_resizeObject, move, size );
|
|
// the command is not executed as the object is allready resized.
|
|
doc()->addCommand( resizeCmd );
|
|
}
|
|
|
|
// if ( layout )
|
|
// doc()->layout( m_resizeObject );
|
|
|
|
d->m_ratio = 0.0;
|
|
d->m_isResizing = false;
|
|
repaintObject( d->m_resizeObject );
|
|
d->m_resizeObject = NULL;
|
|
}
|
|
}
|
|
|
|
void Canvas::raiseObject( EmbeddedObject *object )
|
|
{
|
|
if ( doc()->embeddedObjects().count() <= 1 )
|
|
return;
|
|
|
|
if ( d->m_objectDisplayAbove == 0 )
|
|
{
|
|
if ( activeSheet()->numSelected() == 1 )
|
|
{
|
|
d->m_objectDisplayAbove = object;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Canvas::lowerObject()
|
|
{
|
|
d->m_objectDisplayAbove = 0;
|
|
}
|
|
|
|
void Canvas::displayObjectList( TQPtrList<EmbeddedObject> &list )
|
|
{
|
|
list = doc()->embeddedObjects();
|
|
list.setAutoDelete( false );
|
|
|
|
if ( d->m_objectDisplayAbove )
|
|
{
|
|
// it can happen that the object is no longer there e.g. when
|
|
// the insert of the object is undone
|
|
int pos = doc()->embeddedObjects().findRef( d->m_objectDisplayAbove );
|
|
if ( pos != -1 && d->m_objectDisplayAbove->isSelected() )
|
|
{
|
|
list.take( pos );
|
|
list.append( d->m_objectDisplayAbove );
|
|
}
|
|
else
|
|
{
|
|
//tz not possible due to const. should const be removed?
|
|
//m_objectDisplayAbove = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
KoRect Canvas::objectRect( bool all ) const
|
|
{
|
|
return activeSheet()->getRealRect( all );
|
|
}
|
|
|
|
void Canvas::deleteEditor (bool saveChanges, bool array)
|
|
{
|
|
if ( !d->cellEditor )
|
|
return;
|
|
|
|
|
|
//There may be highlighted areas on the sheet which will need to be erased
|
|
setSelectionChangePaintDirty( activeSheet() , *choice() );
|
|
|
|
d->editWidget->setEditMode( false );
|
|
|
|
TQString t = d->cellEditor->text();
|
|
// Delete the cell editor first and after that update the document.
|
|
// That means we get a synchronous repaint after the cell editor
|
|
// widget is gone. Otherwise we may get painting errors.
|
|
delete d->cellEditor;
|
|
d->cellEditor = 0;
|
|
|
|
if ( saveChanges )
|
|
{
|
|
if ( t.at(0)=='=' )
|
|
{
|
|
//a formula
|
|
int openParenthese = t.contains('(' );
|
|
int closeParenthese = t.contains(')' );
|
|
int diff = TQABS( openParenthese - closeParenthese );
|
|
if ( openParenthese > closeParenthese )
|
|
{
|
|
for (int i=0; i < diff;i++)
|
|
{
|
|
t=t+')';
|
|
}
|
|
}
|
|
}
|
|
d->view->setText (t, array);
|
|
}
|
|
else
|
|
{
|
|
d->view->updateEditWidget();
|
|
}
|
|
|
|
setFocus();
|
|
}
|
|
|
|
|
|
void Canvas::createEditor(bool captureArrowKeys)
|
|
{
|
|
if (!activeSheet())
|
|
return;
|
|
|
|
Cell * cell = activeSheet()->nonDefaultCell( markerColumn(), markerRow(), false );
|
|
|
|
if ( !createEditor( CellEditor , true , captureArrowKeys ) )
|
|
return;
|
|
if ( cell )
|
|
d->cellEditor->setText( cell->text() );
|
|
}
|
|
|
|
bool Canvas::createEditor( EditorType ed, bool addFocus, bool captureArrowKeys )
|
|
{
|
|
Sheet * sheet = activeSheet();
|
|
|
|
// Set the starting sheet of the choice.
|
|
choice()->setSheet( activeSheet() );
|
|
|
|
if ( !d->cellEditor )
|
|
{
|
|
Cell * cell = sheet->nonDefaultCell( marker().x(), marker().y(), false );
|
|
|
|
if ( sheet->isProtected() && !cell->format()->notProtected( marker().x(), marker().y() ) )
|
|
return false;
|
|
|
|
if ( ed == CellEditor )
|
|
{
|
|
d->editWidget->setEditMode( true );
|
|
d->cellEditor = new KSpread::CellEditor( cell, this, captureArrowKeys );
|
|
}
|
|
|
|
double w, h;
|
|
double min_w = cell->dblWidth( markerColumn() );
|
|
double min_h = cell->dblHeight( markerRow() );
|
|
if ( cell->isDefault() )
|
|
{
|
|
w = min_w;
|
|
h = min_h;
|
|
//kdDebug(36001) << "DEFAULT" << endl;
|
|
}
|
|
else
|
|
{
|
|
w = cell->extraWidth();
|
|
h = cell->extraHeight();
|
|
//kdDebug(36001) << "HEIGHT=" << min_h << " EXTRA=" << h << endl;
|
|
}
|
|
|
|
double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset();
|
|
|
|
Sheet::LayoutDirection sheetDir = sheet->layoutDirection();
|
|
bool rtlText = cell->strOutText().isRightToLeft();
|
|
|
|
// if sheet and cell direction don't match, then the editor's location
|
|
// needs to be shifted backwards so that it's right above the cell's text
|
|
if ( w > 0 && ( ( sheetDir == Sheet::RightToLeft && !rtlText ) ||
|
|
( sheetDir == Sheet::LeftToRight && rtlText ) ) )
|
|
xpos -= w - min_w;
|
|
|
|
// paint editor above correct cell if sheet direction is RTL
|
|
if ( sheetDir == Sheet::RightToLeft )
|
|
{
|
|
double dwidth = d->view->doc()->unzoomItX( width() );
|
|
double w2 = TQMAX( w, min_w );
|
|
xpos = dwidth - w2 - xpos;
|
|
}
|
|
|
|
double ypos = sheet->dblRowPos( markerRow() ) - yOffset();
|
|
TQPalette p = d->cellEditor->palette();
|
|
TQColorGroup g( p.active() );
|
|
|
|
TQColor color = cell->format()->textColor( markerColumn(), markerRow() );
|
|
if ( !color.isValid() )
|
|
color = TQApplication::palette().active().text();
|
|
g.setColor( TQColorGroup::Text, color);
|
|
|
|
color = cell->bgColor( markerColumn(), markerRow() );
|
|
if ( !color.isValid() )
|
|
color = g.base();
|
|
g.setColor( TQColorGroup::Background, color );
|
|
|
|
d->cellEditor->setPalette( TQPalette( g, p.disabled(), g ) );
|
|
TQFont tmpFont = cell->format()->textFont( markerColumn(), markerRow() );
|
|
tmpFont.setPointSizeFloat( 0.01 * d->view->doc()->zoom() * tmpFont.pointSizeFloat() );
|
|
d->cellEditor->setFont( tmpFont );
|
|
|
|
KoRect rect( xpos, ypos, w, h ); //needed to circumvent rounding issue with height/width
|
|
|
|
|
|
TQRect zoomedRect=d->view->doc()->zoomRect( rect );
|
|
/*zoomedRect.setLeft(zoomedRect.left()-2);
|
|
zoomedRect.setRight(zoomedRect.right()+4);
|
|
zoomedRect.setTop(zoomedRect.top()-1);
|
|
zoomedRect.setBottom(zoomedRect.bottom()+2);*/
|
|
|
|
d->cellEditor->setGeometry( zoomedRect );
|
|
d->cellEditor->setMinimumSize( TQSize( d->view->doc()->zoomItX( min_w ), d->view->doc()->zoomItY( min_h ) ) );
|
|
d->cellEditor->show();
|
|
//kdDebug(36001) << "FOCUS1" << endl;
|
|
//Laurent 2001-12-05
|
|
//Don't add focus when we create a new editor and
|
|
//we select text in edit widget otherwise we don't delete
|
|
//selected text.
|
|
// startChoose();
|
|
|
|
if ( addFocus )
|
|
d->cellEditor->setFocus();
|
|
|
|
setSelectionChangePaintDirty(sheet, *selectionInfo());
|
|
paintUpdates();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Canvas::repaintObject( EmbeddedObject *obj )
|
|
{
|
|
//Calculate where the object appears on the canvas widget and then repaint that part of the widget
|
|
TQRect canvasRelativeGeometry = doc()->zoomRect( obj->geometry() );
|
|
canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) ,
|
|
(int)( -yOffset() * doc()->zoomedResolutionY()) );
|
|
|
|
update( canvasRelativeGeometry );
|
|
|
|
/* if ( !obj->isSelected() )
|
|
{
|
|
KoRect g = obj->geometry();
|
|
g.moveBy( -xOffset(), -yOffset() );
|
|
TQRect geometry( doc()->zoomRect( g ) );
|
|
|
|
update( geometry );
|
|
}
|
|
else
|
|
{
|
|
TQPainter p(this);
|
|
p.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() );
|
|
obj->draw(&p); //this goes faster than calling repaint
|
|
p.end();
|
|
}*/
|
|
}
|
|
|
|
void Canvas::copyOasisObjects()
|
|
{
|
|
// We'll create a store (ZIP format) in memory
|
|
TQBuffer buffer;
|
|
TQCString mimeType = "application/vnd.oasis.opendocument.spreadsheet";
|
|
KoStore* store = KoStore::createStore( TQT_TQIODEVICE(&buffer), KoStore::Write, mimeType );
|
|
Q_ASSERT( store );
|
|
Q_ASSERT( !store->bad() );
|
|
KoOasisStore oasisStore( store );
|
|
|
|
KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
|
|
|
|
TQString plainText;
|
|
KoPicture picture;
|
|
if ( !doc()->saveOasisHelper( store, manifestWriter, Doc::SaveSelected, &plainText, &picture )
|
|
|| !oasisStore.closeManifestWriter() )
|
|
{
|
|
delete store;
|
|
return;
|
|
}
|
|
delete store;
|
|
|
|
KMultipleDrag* multiDrag = new KMultipleDrag();
|
|
if ( !plainText.isEmpty() )
|
|
multiDrag->addDragObject( new TQTextDrag( plainText, 0 ) );
|
|
if ( !picture.isNull() )
|
|
multiDrag->addDragObject( picture.dragObject( 0 ) );
|
|
KoStoreDrag* storeDrag = new KoStoreDrag( mimeType, 0 );
|
|
kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl;
|
|
storeDrag->setEncodedData( buffer.buffer() );
|
|
multiDrag->addDragObject( storeDrag );
|
|
|
|
//save the objects as pictures too so that other programs can access them
|
|
TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
|
|
itObject.toFirst();
|
|
if ( itObject.current() )
|
|
{
|
|
KoRect kr = objectRect(false);
|
|
TQRect r( kr.toTQRect() );
|
|
TQPixmap pixmap( r.width(), r.height() );
|
|
pixmap.fill( "white" );
|
|
TQPainter p(&pixmap);
|
|
for( ; itObject.current(); ++itObject )
|
|
{
|
|
if ( itObject.current()->isSelected() )
|
|
p.drawPixmap( itObject.current()->geometry().toTQRect().left() - r.left(), itObject.current()->geometry().toTQRect().top() - r.top(), itObject.current()->toPixmap( 1.0 , 1.0 ) );
|
|
}
|
|
p.end();
|
|
if (!pixmap.isNull())
|
|
{
|
|
TQImageDrag *imagedrag = new TQImageDrag( pixmap.convertToImage() );
|
|
multiDrag->addDragObject( imagedrag );
|
|
}
|
|
}
|
|
|
|
TQDragObject *dragObject = multiDrag;
|
|
TQApplication::clipboard()->setData( dragObject, TQClipboard::Clipboard );
|
|
}
|
|
|
|
void Canvas::closeEditor()
|
|
{
|
|
if ( d->chooseCell )
|
|
return;
|
|
|
|
if ( d->cellEditor )
|
|
{
|
|
deleteEditor( true ); // save changes
|
|
}
|
|
}
|
|
|
|
void Canvas::updateEditor()
|
|
{
|
|
if (!d->chooseCell)
|
|
return;
|
|
|
|
Sheet* sheet = activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
if (d->cellEditor)
|
|
{
|
|
if (choice()->sheet() != sheet)
|
|
{
|
|
d->cellEditor->hide();
|
|
}
|
|
else
|
|
{
|
|
d->cellEditor->show();
|
|
}
|
|
d->cellEditor->updateChoice();
|
|
}
|
|
}
|
|
|
|
void Canvas::setSelectionChangePaintDirty(Sheet* sheet, const Region& region)
|
|
{
|
|
sheet->setRegionPaintDirty(region); // TODO should the paintDirtyList be in Canvas?
|
|
}
|
|
|
|
|
|
void Canvas::updatePosWidget()
|
|
{
|
|
TQString buffer;
|
|
// No selection, or only one cell merged selected
|
|
if ( selectionInfo()->isSingular() )
|
|
{
|
|
if (activeSheet()->getLcMode())
|
|
{
|
|
buffer = "L" + TQString::number( markerRow() ) +
|
|
"C" + TQString::number( markerColumn() );
|
|
}
|
|
else
|
|
{
|
|
buffer = Cell::columnName( markerColumn() ) +
|
|
TQString::number( markerRow() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (activeSheet()->getLcMode())
|
|
{
|
|
buffer = TQString::number( (selectionInfo()->lastRange().bottom()-selectionInfo()->lastRange().top()+1) )+"Lx";
|
|
if ( util_isRowSelected( selectionInfo()->lastRange() ) )
|
|
buffer+=TQString::number((KS_colMax-selectionInfo()->lastRange().left()+1))+"C";
|
|
else
|
|
buffer+=TQString::number((selectionInfo()->lastRange().right()-selectionInfo()->lastRange().left()+1))+"C";
|
|
}
|
|
else
|
|
{
|
|
//encodeColumnLabelText return @@@@ when column >KS_colMax
|
|
//=> it's not a good display
|
|
//=> for the moment I display pos of marker
|
|
buffer=Cell::columnName( selectionInfo()->lastRange().left() ) +
|
|
TQString::number(selectionInfo()->lastRange().top()) + ":" +
|
|
Cell::columnName( TQMIN( KS_colMax, selectionInfo()->lastRange().right() ) ) +
|
|
TQString::number(selectionInfo()->lastRange().bottom());
|
|
//buffer=activeSheet()->columnLabel( m_iMarkerColumn );
|
|
//buffer+=tmp.setNum(m_iMarkerRow);
|
|
}
|
|
}
|
|
|
|
if (buffer != d->posWidget->lineEdit()->text())
|
|
d->posWidget->lineEdit()->setText(buffer);
|
|
}
|
|
|
|
void Canvas::equalizeRow()
|
|
{
|
|
TQRect s( selection() );
|
|
RowFormat *rl = d->view->activeSheet()->rowFormat(s.top());
|
|
int size=rl->height(this);
|
|
if ( s.top() == s.bottom() )
|
|
return;
|
|
for(int i=s.top()+1;i<=s.bottom();i++)
|
|
{
|
|
Sheet *sheet = activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
size=TQMAX(d->view->activeSheet()->rowFormat(i)->height(this),size);
|
|
}
|
|
d->view->vBorderWidget()->equalizeRow(size);
|
|
}
|
|
|
|
void Canvas::equalizeColumn()
|
|
{
|
|
TQRect s( selection() );
|
|
ColumnFormat *cl = d->view->activeSheet()->columnFormat(s.left());
|
|
int size=cl->width(this);
|
|
if ( s.left() == s.right() )
|
|
return;
|
|
|
|
for(int i=s.left()+1;i<=s.right();i++)
|
|
{
|
|
size=TQMAX(d->view->activeSheet()->columnFormat(i)->width(this),size);
|
|
}
|
|
d->view->hBorderWidget()->equalizeColumn(size);
|
|
}
|
|
|
|
TQRect Canvas::cellsInArea( const TQRect area ) const
|
|
{
|
|
KoRect unzoomedRect = d->view->doc()->unzoomRect( area );
|
|
|
|
unzoomedRect.moveBy( (int)xOffset(), (int)yOffset() );
|
|
|
|
double tmp;
|
|
int left_col = activeSheet()->leftColumn( unzoomedRect.left(), tmp );
|
|
int right_col = activeSheet()->rightColumn( unzoomedRect.right() );
|
|
int top_row = activeSheet()->topRow( unzoomedRect.top(), tmp );
|
|
int bottom_row = activeSheet()->bottomRow( unzoomedRect.bottom() );
|
|
|
|
return TQRect( left_col, top_row,
|
|
right_col - left_col + 1, bottom_row - top_row + 1 );
|
|
}
|
|
|
|
TQRect Canvas::visibleCells() const
|
|
{
|
|
return cellsInArea( TQRect(0,0,width(),height()) );
|
|
|
|
}
|
|
|
|
|
|
//---------------------------------------------
|
|
//
|
|
// Drawing Engine
|
|
//
|
|
//---------------------------------------------
|
|
|
|
void Canvas::paintUpdates()
|
|
{
|
|
if (activeSheet() == NULL)
|
|
return;
|
|
|
|
TQPainter painter(this);
|
|
|
|
//Save clip region
|
|
TQRegion rgnComplete( painter.clipRegion() );
|
|
TQWMatrix matrix;
|
|
if ( d->view )
|
|
{
|
|
matrix = d->view->matrix();
|
|
}
|
|
else
|
|
{
|
|
matrix = painter.worldMatrix();
|
|
}
|
|
|
|
|
|
paintChildren( painter, matrix );
|
|
|
|
painter.save();
|
|
clipoutChildren( painter );
|
|
|
|
KoRect unzoomedRect = d->view->doc()->unzoomRect( TQRect( 0, 0, width(), height() ) );
|
|
// unzoomedRect.moveBy( xOffset(), yOffset() );
|
|
|
|
|
|
/* paint any visible cell that has the paintDirty flag */
|
|
TQRect range = visibleCells();
|
|
Cell* cell = NULL;
|
|
|
|
double topPos = activeSheet()->dblRowPos(range.top());
|
|
double leftPos = activeSheet()->dblColumnPos(range.left());
|
|
|
|
KoPoint dblCorner( leftPos - xOffset(), topPos - yOffset() );
|
|
|
|
int x;
|
|
int y;
|
|
|
|
int right = range.right();
|
|
int bottom = range.bottom();
|
|
Sheet * sheet = activeSheet();
|
|
|
|
#if 0
|
|
kdDebug(36001)
|
|
<< "================================================================"
|
|
<< endl;
|
|
kdDebug(36001) << "painting dirty cells " << endl;
|
|
#endif
|
|
|
|
TQValueList<TQPoint> mergedCellsPainted;
|
|
for ( x = range.left(); x <= right; ++x )
|
|
{
|
|
for ( y = range.top(); y <= bottom; ++y )
|
|
{
|
|
if ( sheet->cellIsPaintDirty( TQPoint( x, y ) ) )
|
|
{
|
|
cell = sheet->cellAt( x, y );
|
|
|
|
// recalc and relayout only for non default cells
|
|
if (!cell->isDefault())
|
|
{
|
|
if (cell->calcDirtyFlag()) cell->calc();
|
|
if (cell->layoutDirtyFlag()) cell->makeLayout( painter, x, y );
|
|
}
|
|
|
|
/* bool paintBordersBottom = false;
|
|
bool paintBordersRight = false;
|
|
bool paintBordersLeft = false;
|
|
bool paintBordersTop = false; */
|
|
|
|
int paintBorder=Cell::Border_None;
|
|
|
|
TQPen bottomPen( cell->effBottomBorderPen( x, y ) );
|
|
TQPen rightPen( cell->effRightBorderPen( x, y ) );
|
|
TQPen leftPen( cell->effLeftBorderPen( x, y ) );
|
|
TQPen topPen( cell->effTopBorderPen( x, y ) );
|
|
|
|
// paint right border
|
|
// - if rightmost cell
|
|
// - if the pen is more "worth" than the left border pen of the cell
|
|
// on the left
|
|
if ( x >= KS_colMax )
|
|
{
|
|
paintBorder |= Cell::Border_Right;
|
|
}
|
|
else
|
|
{
|
|
paintBorder |= Cell::Border_Right;
|
|
if ( cell->effRightBorderValue( x, y ) <
|
|
sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) )
|
|
rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y );
|
|
}
|
|
|
|
// similiar for other borders...
|
|
// bottom border:
|
|
if ( y >= KS_rowMax )
|
|
{
|
|
paintBorder |= Cell::Border_Bottom;
|
|
}
|
|
else
|
|
{
|
|
paintBorder |= Cell::Border_Bottom;
|
|
if ( cell->effBottomBorderValue( x, y ) <
|
|
sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1 ) )
|
|
bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 );
|
|
}
|
|
|
|
// left border:
|
|
if ( x == 1 )
|
|
{
|
|
paintBorder |= Cell::Border_Left;
|
|
}
|
|
else
|
|
{
|
|
paintBorder |= Cell::Border_Left;
|
|
if ( cell->effLeftBorderValue( x, y ) <
|
|
sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) )
|
|
leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y );
|
|
}
|
|
|
|
// top border:
|
|
if ( y == 1 )
|
|
{
|
|
paintBorder |= Cell::Border_Top;
|
|
}
|
|
else
|
|
{
|
|
paintBorder |= Cell::Border_Top;
|
|
if ( cell->effTopBorderValue( x, y ) <
|
|
sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) )
|
|
topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 );
|
|
}
|
|
|
|
cell->paintCell( unzoomedRect, painter, d->view, dblCorner,
|
|
TQPoint( x, y), paintBorder,
|
|
rightPen,bottomPen,leftPen,topPen,
|
|
mergedCellsPainted);
|
|
}
|
|
dblCorner.setY( dblCorner.y() + sheet->rowFormat( y )->dblHeight( ) );
|
|
}
|
|
dblCorner.setY( topPos - yOffset() );
|
|
dblCorner.setX( dblCorner.x() + sheet->columnFormat( x )->dblWidth( ) );
|
|
}
|
|
|
|
/* now paint the selection */
|
|
//Nb. No longer necessary to paint choose selection here as the cell reference highlight
|
|
//stuff takes care of this anyway
|
|
|
|
paintHighlightedRanges(painter, unzoomedRect);
|
|
paintNormalMarker(painter, unzoomedRect);
|
|
|
|
//restore clip region with children area
|
|
painter.restore();
|
|
//painter.setClipRegion( rgnComplete );
|
|
}
|
|
|
|
|
|
|
|
void Canvas::clipoutChildren( TQPainter& painter ) const
|
|
{
|
|
TQRegion rgn = painter.clipRegion();
|
|
if ( rgn.isEmpty() )
|
|
rgn = TQRegion( TQRect( 0, 0, width(), height() ) );
|
|
|
|
const double horizontalOffset = -xOffset() * doc()->zoomedResolutionX();
|
|
const double verticalOffset = -yOffset() * doc()->zoomedResolutionY();
|
|
|
|
TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
|
|
for( ; itObject.current(); ++itObject )
|
|
{
|
|
if ( ( itObject.current() )->sheet() == activeSheet() )
|
|
{
|
|
TQRect childGeometry = doc()->zoomRect( itObject.current()->geometry());
|
|
|
|
//The clipping region is given in device coordinates
|
|
//so subtract the current offset (scroll position) of the canvas
|
|
childGeometry.moveBy( (int)horizontalOffset , (int)verticalOffset );
|
|
|
|
if (painter.window().intersects(childGeometry))
|
|
rgn -= childGeometry;
|
|
|
|
//painter.fillRect( doc()->zoomRect( itObject.current()->geometry() ), TQColor("red" ) );
|
|
}
|
|
}
|
|
|
|
painter.setClipRegion( rgn );
|
|
}
|
|
|
|
TQRect Canvas::painterWindowGeometry( const TQPainter& painter ) const
|
|
{
|
|
TQRect zoomedWindowGeometry = painter.window();
|
|
|
|
zoomedWindowGeometry.moveBy( (int)( xOffset() * doc()->zoomedResolutionX() ) , (int)( yOffset() * doc()->zoomedResolutionY() ) );
|
|
|
|
return zoomedWindowGeometry;
|
|
}
|
|
|
|
void Canvas::paintChildren( TQPainter& painter, TQWMatrix& /*matrix*/ )
|
|
{
|
|
TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
|
|
itObject.toFirst();
|
|
if ( !itObject.current() )
|
|
return;
|
|
|
|
painter.save();
|
|
painter.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() );
|
|
|
|
const TQRect zoomedWindowGeometry = painterWindowGeometry( painter );
|
|
const Sheet* sheet = activeSheet();
|
|
|
|
for( ; itObject.current(); ++itObject )
|
|
{
|
|
TQRect const zoomedObjectGeometry = doc()->zoomRect( itObject.current()->geometry() );
|
|
if ( ( itObject.current() )->sheet() == activeSheet() &&
|
|
zoomedWindowGeometry.intersects( zoomedObjectGeometry ) )
|
|
{
|
|
//To prevent unnecessary redrawing of the embedded object, we only repaint
|
|
//if one or more of the cells underneath the object has been marked as 'dirty'.
|
|
|
|
TQRect canvasRelativeGeometry = zoomedObjectGeometry;
|
|
canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) ,
|
|
(int)( -yOffset() * doc()->zoomedResolutionY()) );
|
|
|
|
const TQRect cellsUnderObject=cellsInArea( canvasRelativeGeometry );
|
|
bool redraw=false;
|
|
|
|
for (int x=cellsUnderObject.left();x<=cellsUnderObject.right();x++)
|
|
{
|
|
for (int y=cellsUnderObject.top();y<=cellsUnderObject.bottom();y++)
|
|
if ( sheet->cellIsPaintDirty( TQPoint(x,y) ) )
|
|
{
|
|
redraw=true;
|
|
break;
|
|
}
|
|
if (redraw)
|
|
break;
|
|
}
|
|
|
|
if ( redraw )
|
|
itObject.current()->draw( &painter );
|
|
}
|
|
}
|
|
painter.restore();
|
|
}
|
|
|
|
void Canvas::paintHighlightedRanges(TQPainter& painter, const KoRect& /*viewRect*/)
|
|
{
|
|
TQValueList<TQColor> colors = choice()->colors();
|
|
TQBrush nullBrush;
|
|
int index = 0;
|
|
Region::ConstIterator end(choice()->constEnd());
|
|
for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it)
|
|
{
|
|
//Only paint ranges or cells on the current sheet
|
|
if ((*it)->sheet() != activeSheet())
|
|
{
|
|
index++;
|
|
continue;
|
|
}
|
|
|
|
TQRect region = (*it)->rect().normalize();
|
|
|
|
//double positions[4];
|
|
//bool paintSides[4];
|
|
KoRect unzoomedRect;
|
|
|
|
sheetAreaToVisibleRect(region,unzoomedRect);
|
|
//Convert region from sheet coordinates to canvas coordinates for use with the painter
|
|
//retrieveMarkerInfo(region,viewRect,positions,paintSides);
|
|
|
|
TQPen highlightPen( colors[(index) % colors.size()] ); // (*it)->color() );
|
|
painter.setPen(highlightPen);
|
|
|
|
//Adjust the canvas coordinate - rect to take account of zoom level
|
|
|
|
TQRect zoomedRect;
|
|
|
|
zoomedRect.setCoords ( d->view->doc()->zoomItX(unzoomedRect.left()),
|
|
d->view->doc()->zoomItY(unzoomedRect.top()),
|
|
d->view->doc()->zoomItX(unzoomedRect.right()),
|
|
d->view->doc()->zoomItY(unzoomedRect.bottom()) );
|
|
|
|
//Now adjust the highlight rectangle is slightly inside the cell borders (this means that multiple highlighted cells
|
|
//look nicer together as the borders do not clash)
|
|
|
|
zoomedRect.setLeft(zoomedRect.left()+1);
|
|
zoomedRect.setTop(zoomedRect.top()+1);
|
|
zoomedRect.setRight(zoomedRect.right()-1);
|
|
zoomedRect.setBottom(zoomedRect.bottom()-1);
|
|
|
|
painter.setBrush(nullBrush);
|
|
painter.drawRect(zoomedRect);
|
|
|
|
//Now draw the size grip (the little rectangle on the bottom right-hand corner of the range which the user can
|
|
//click and drag to resize the region)
|
|
|
|
|
|
TQBrush sizeGripBrush( colors[(index) % colors.size()] ); // (*it)->color());
|
|
TQPen sizeGripPen(TQt::white);
|
|
|
|
painter.setPen(sizeGripPen);
|
|
painter.setBrush(sizeGripBrush);
|
|
|
|
painter.drawRect(zoomedRect.right()-3,zoomedRect.bottom()-3,6,6);
|
|
index++;
|
|
}
|
|
}
|
|
|
|
void Canvas::paintNormalMarker(TQPainter& painter, const KoRect &viewRect)
|
|
{
|
|
//Only the active element (the one with the anchor) will be drawn with a border
|
|
|
|
if( d->chooseCell )
|
|
return;
|
|
|
|
if (d->cellEditor)
|
|
return;
|
|
|
|
Region::ConstIterator end(selectionInfo()->constEnd());
|
|
for (Region::ConstIterator it(selectionInfo()->constBegin()); it != end; ++it)
|
|
{
|
|
TQRect range = (*it)->rect().normalize();
|
|
|
|
double positions[4];
|
|
bool paintSides[4];
|
|
|
|
bool current = TQRect(selectionInfo()->anchor(), selectionInfo()->marker()).normalize() == range;
|
|
TQPen pen( TQt::black, 2 );
|
|
painter.setPen( pen );
|
|
|
|
retrieveMarkerInfo( selectionInfo()->extendToMergedAreas(range), viewRect, positions, paintSides );
|
|
|
|
double left = positions[0];
|
|
double top = positions[1];
|
|
double right = positions[2];
|
|
double bottom = positions[3];
|
|
|
|
bool paintLeft = paintSides[0];
|
|
bool paintTop = paintSides[1];
|
|
bool paintRight = paintSides[2];
|
|
bool paintBottom = paintSides[3];
|
|
|
|
/* the extra '-1's thrown in here account for the thickness of the pen.
|
|
want to look like this: not this:
|
|
* * * * * * * * * *
|
|
* * * *
|
|
* * * *
|
|
*/
|
|
int l = 1;
|
|
|
|
if ( paintTop )
|
|
{
|
|
painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( top ),
|
|
d->view->doc()->zoomItX( right ) + l, d->view->doc()->zoomItY( top ) );
|
|
}
|
|
if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
if ( paintRight )
|
|
{
|
|
painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ),
|
|
d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) );
|
|
}
|
|
if ( paintLeft && paintBottom && current )
|
|
{
|
|
/* then the 'handle' in the bottom left corner is visible. */
|
|
painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ),
|
|
d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) - 3 );
|
|
painter.drawLine( d->view->doc()->zoomItX( left ) + 4, d->view->doc()->zoomItY( bottom ),
|
|
d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) );
|
|
painter.fillRect( d->view->doc()->zoomItX( left ) - 2, d->view->doc()->zoomItY( bottom ) -2, 5, 5,
|
|
painter.pen().color() );
|
|
}
|
|
else
|
|
{
|
|
if ( paintLeft )
|
|
{
|
|
painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ),
|
|
d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) );
|
|
}
|
|
if ( paintBottom )
|
|
{
|
|
painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ),
|
|
d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ));
|
|
}
|
|
}
|
|
}
|
|
else // activeSheet()->layoutDirection()==Sheet::LeftToRight
|
|
{
|
|
if ( paintLeft )
|
|
{
|
|
painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ),
|
|
d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) );
|
|
}
|
|
if ( paintRight && paintBottom && current )
|
|
{
|
|
/* then the 'handle' in the bottom right corner is visible. */
|
|
painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ),
|
|
d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) - 3 );
|
|
painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ),
|
|
d->view->doc()->zoomItX( right ) - 3, d->view->doc()->zoomItY( bottom ) );
|
|
painter.fillRect( d->view->doc()->zoomItX( right ) - 2, d->view->doc()->zoomItY( bottom ) - 2, 5, 5,
|
|
painter.pen().color() );
|
|
}
|
|
else
|
|
{
|
|
if ( paintRight )
|
|
{
|
|
painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ),
|
|
d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) );
|
|
}
|
|
if ( paintBottom )
|
|
{
|
|
painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ),
|
|
d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Canvas::sheetAreaToRect(const TQRect& sheetArea, KoRect& rect)
|
|
{
|
|
Sheet* sheet=activeSheet();
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
rect.setLeft(sheet->dblColumnPos( sheetArea.right()+1 ) );
|
|
rect.setRight(sheet->dblColumnPos( sheetArea.left() ));
|
|
}
|
|
else
|
|
{
|
|
rect.setLeft(sheet->dblColumnPos( sheetArea.left() ));
|
|
rect.setRight(sheet->dblColumnPos( sheetArea.right()+1 ));
|
|
}
|
|
|
|
rect.setTop(sheet->dblRowPos(sheetArea.top()));
|
|
rect.setBottom(sheet->dblRowPos(sheetArea.bottom()+1));
|
|
|
|
}
|
|
|
|
void Canvas::sheetAreaToVisibleRect( const TQRect& sheetArea,
|
|
KoRect& visibleRect )
|
|
{
|
|
Sheet* sheet=activeSheet();
|
|
|
|
if (!sheet)
|
|
return;
|
|
|
|
double dwidth=d->view->doc()->unzoomItX(width());
|
|
double xpos;
|
|
double x;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
xpos = dwidth - sheet->dblColumnPos( sheetArea.right() ) + xOffset();
|
|
x = dwidth - sheet->dblColumnPos( sheetArea.left() ) + xOffset();
|
|
}
|
|
else
|
|
{
|
|
xpos = sheet->dblColumnPos( sheetArea.left() ) - xOffset();
|
|
x = sheet->dblColumnPos( sheetArea.right() ) - xOffset();
|
|
}
|
|
|
|
double ypos = sheet->dblRowPos(sheetArea.top())-yOffset();
|
|
|
|
const ColumnFormat *columnFormat = sheet->columnFormat( sheetArea.right() );
|
|
double tw = columnFormat->dblWidth( );
|
|
double w = x - xpos + tw;
|
|
|
|
double y = sheet->dblRowPos( sheetArea.bottom() ) - yOffset();
|
|
const RowFormat* rowFormat = sheet->rowFormat( sheetArea.bottom() );
|
|
double th = rowFormat->dblHeight( );
|
|
double h = ( y - ypos ) + th;
|
|
|
|
/* left, top, right, bottom */
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
visibleRect.setLeft(xpos - tw );
|
|
visibleRect.setRight(xpos - tw + w );
|
|
}
|
|
else
|
|
{
|
|
visibleRect.setLeft(xpos );
|
|
visibleRect.setRight(xpos + w );
|
|
}
|
|
visibleRect.setTop(ypos);
|
|
visibleRect.setBottom(ypos + h);
|
|
}
|
|
|
|
void Canvas::retrieveMarkerInfo( const TQRect &marker,
|
|
const KoRect &viewRect,
|
|
double positions[],
|
|
bool paintSides[] )
|
|
{
|
|
|
|
Sheet* sheet=activeSheet();
|
|
|
|
if (!sheet) return;
|
|
|
|
KoRect visibleRect;
|
|
sheetAreaToVisibleRect(marker,visibleRect);
|
|
|
|
|
|
/* Sheet * sheet = activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
double dWidth = d->view->doc()->unzoomItX( width() );
|
|
|
|
double xpos;
|
|
double x;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
xpos = dWidth - sheet->dblColumnPos( marker.right() ) + xOffset();
|
|
x = dWidth - sheet->dblColumnPos( marker.left() ) + xOffset();
|
|
}
|
|
else
|
|
{
|
|
xpos = sheet->dblColumnPos( marker.left() ) - xOffset();
|
|
x = sheet->dblColumnPos( marker.right() ) - xOffset();
|
|
}
|
|
double ypos = sheet->dblRowPos( marker.top() ) - yOffset();
|
|
|
|
const ColumnFormat *columnFormat = sheet->columnFormat( marker.right() );
|
|
double tw = columnFormat->dblWidth( );
|
|
double w = x - xpos + tw;
|
|
|
|
double y = sheet->dblRowPos( marker.bottom() ) - yOffset();
|
|
const RowFormat* rowFormat = sheet->rowFormat( marker.bottom() );
|
|
double th = rowFormat->dblHeight( );
|
|
double h = ( y - ypos ) + th;
|
|
|
|
//left, top, right, bottom
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
positions[0] = xpos - tw;
|
|
positions[2] = xpos - tw + w;
|
|
}
|
|
else
|
|
{
|
|
positions[0] = xpos;
|
|
positions[2] = xpos + w;
|
|
}
|
|
positions[1] = ypos;
|
|
positions[3] = ypos + h;*/
|
|
|
|
/* these vars are used for clarity, the array for simpler function arguments */
|
|
double left = visibleRect.left();
|
|
double top = visibleRect.top();
|
|
double right = visibleRect.right();
|
|
double bottom = visibleRect.bottom();
|
|
|
|
/* left, top, right, bottom */
|
|
paintSides[0] = (viewRect.left() <= left) && (left <= viewRect.right()) &&
|
|
(bottom >= viewRect.top()) && (top <= viewRect.bottom());
|
|
paintSides[1] = (viewRect.top() <= top) && (top <= viewRect.bottom())
|
|
&& (right >= viewRect.left()) && (left <= viewRect.right());
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
paintSides[2] = (viewRect.left() <= right ) &&
|
|
(right - 1 <= viewRect.right()) &&
|
|
(bottom >= viewRect.top()) && (top <= viewRect.bottom());
|
|
else
|
|
paintSides[2] = (viewRect.left() <= right ) &&
|
|
(right <= viewRect.right()) &&
|
|
(bottom >= viewRect.top()) && (top <= viewRect.bottom());
|
|
paintSides[3] = (viewRect.top() <= bottom) && (bottom <= viewRect.bottom())
|
|
&& (right >= viewRect.left()) && (left <= viewRect.right());
|
|
|
|
positions[0] = TQMAX( left, viewRect.left() );
|
|
positions[1] = TQMAX( top, viewRect.top() );
|
|
positions[2] = TQMIN( right, viewRect.right() );
|
|
positions[3] = TQMIN( bottom, viewRect.bottom() );
|
|
}
|
|
|
|
|
|
/****************************************************************
|
|
*
|
|
* VBorder
|
|
*
|
|
****************************************************************/
|
|
|
|
VBorder::VBorder( TQWidget *_parent, Canvas *_canvas, View *_view)
|
|
: TQWidget( _parent, "", /*WNorthWestGravity*/WStaticContents | WResizeNoErase | WRepaintNoErase )
|
|
{
|
|
m_pView = _view;
|
|
m_pCanvas = _canvas;
|
|
m_lSize = 0L;
|
|
|
|
setBackgroundMode( PaletteButton );
|
|
setMouseTracking( true );
|
|
m_bResize = false;
|
|
m_bSelection = false;
|
|
m_iSelectionAnchor=1;
|
|
m_bMousePressed = false;
|
|
|
|
m_scrollTimer = new TQTimer( this );
|
|
connect (m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) );
|
|
}
|
|
|
|
|
|
VBorder::~VBorder()
|
|
{
|
|
delete m_scrollTimer;
|
|
}
|
|
|
|
TQSize VBorder::sizeHint() const
|
|
{
|
|
return TQSize( 40, 10 );
|
|
}
|
|
|
|
|
|
void VBorder::mousePressEvent( TQMouseEvent * _ev )
|
|
{
|
|
if ( !m_pView->koDocument()->isReadWrite() )
|
|
return;
|
|
|
|
if ( _ev->button() == Qt::LeftButton )
|
|
m_bMousePressed = true;
|
|
|
|
const Sheet *sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset();
|
|
double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() );
|
|
m_bResize = false;
|
|
m_bSelection = false;
|
|
|
|
// We were editing a cell -> save value and get out of editing mode
|
|
if ( m_pCanvas->editor() )
|
|
{
|
|
m_pCanvas->deleteEditor( true ); // save changes
|
|
}
|
|
|
|
m_scrollTimer->start( 50 );
|
|
|
|
// Find the first visible row and the y position of this row.
|
|
double y;
|
|
int row = sheet->topRow( m_pCanvas->yOffset(), y );
|
|
|
|
// Did the user click between two rows?
|
|
while ( y < ( dHeight + m_pCanvas->yOffset() ) && ( !m_bResize ) )
|
|
{
|
|
double h = sheet->rowFormat( row )->dblHeight();
|
|
row++;
|
|
if ( row > KS_rowMax )
|
|
row = KS_rowMax;
|
|
if ( ( ev_PosY >= y + h - 2 ) &&
|
|
( ev_PosY <= y + h + 1 ) &&
|
|
!( sheet->rowFormat( row )->isHide() && row == 1 ) )
|
|
m_bResize = true;
|
|
y += h;
|
|
}
|
|
|
|
//if row is hide and it's the first row
|
|
//you mustn't resize it.
|
|
double tmp2;
|
|
int tmpRow = sheet->topRow( ev_PosY - 1, tmp2 );
|
|
if ( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 )
|
|
m_bResize = false;
|
|
|
|
// So he clicked between two rows ?
|
|
if ( m_bResize )
|
|
{
|
|
// Determine row to resize
|
|
double tmp;
|
|
m_iResizedRow = sheet->topRow( ev_PosY - 1, tmp );
|
|
if ( !sheet->isProtected() )
|
|
paintSizeIndicator( _ev->pos().y(), true );
|
|
}
|
|
else
|
|
{
|
|
m_bSelection = true;
|
|
|
|
double tmp;
|
|
int hit_row = sheet->topRow( ev_PosY, tmp );
|
|
if ( hit_row > KS_rowMax )
|
|
return;
|
|
|
|
m_iSelectionAnchor = hit_row;
|
|
|
|
if ( !m_pView->selectionInfo()->contains( TQPoint(1, hit_row) ) ||
|
|
!( _ev->button() == Qt::RightButton ) ||
|
|
!m_pView->selectionInfo()->isRowSelected() )
|
|
{
|
|
TQPoint newMarker( 1, hit_row );
|
|
TQPoint newAnchor( KS_colMax, hit_row );
|
|
#ifdef NONCONTIGUOUSSELECTION
|
|
if (_ev->state() == ControlButton)
|
|
{
|
|
m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker));
|
|
}
|
|
else
|
|
#endif
|
|
if (_ev->state() == ShiftButton)
|
|
{
|
|
m_pView->selectionInfo()->update(newMarker);
|
|
}
|
|
else
|
|
{
|
|
m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker));
|
|
}
|
|
}
|
|
|
|
if ( _ev->button() == Qt::RightButton )
|
|
{
|
|
TQPoint p = mapToGlobal( _ev->pos() );
|
|
m_pView->popupRowMenu( p );
|
|
m_bSelection = false;
|
|
}
|
|
m_pView->updateEditWidget();
|
|
}
|
|
}
|
|
|
|
void VBorder::mouseReleaseEvent( TQMouseEvent * _ev )
|
|
{
|
|
if ( m_scrollTimer->isActive() )
|
|
m_scrollTimer->stop();
|
|
|
|
m_bMousePressed = false;
|
|
|
|
if ( !m_pView->koDocument()->isReadWrite() )
|
|
return;
|
|
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset();
|
|
|
|
if ( m_bResize )
|
|
{
|
|
// Remove size indicator painted by paintSizeIndicator
|
|
TQPainter painter;
|
|
painter.begin( m_pCanvas );
|
|
painter.setRasterOp( NotROP );
|
|
painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos );
|
|
painter.end();
|
|
|
|
int start = m_iResizedRow;
|
|
int end = m_iResizedRow;
|
|
TQRect rect;
|
|
rect.setCoords( 1, m_iResizedRow, KS_colMax, m_iResizedRow );
|
|
if ( m_pView->selectionInfo()->isRowSelected() )
|
|
{
|
|
if ( m_pView->selectionInfo()->contains( TQPoint( 1, m_iResizedRow ) ) )
|
|
{
|
|
start = m_pView->selectionInfo()->lastRange().top();
|
|
end = m_pView->selectionInfo()->lastRange().bottom();
|
|
rect = m_pView->selectionInfo()->lastRange();
|
|
}
|
|
}
|
|
|
|
double height = 0.0;
|
|
double y = sheet->dblRowPos( m_iResizedRow );
|
|
if ( ev_PosY - y <= 0.0 )
|
|
height = 0.0;
|
|
else
|
|
height = ev_PosY - y;
|
|
|
|
if ( !sheet->isProtected() )
|
|
{
|
|
if ( !m_pCanvas->d->view->doc()->undoLocked() )
|
|
{
|
|
//just resize
|
|
if ( height != 0.0 )
|
|
{
|
|
// TODO Stefan: replace this
|
|
UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect );
|
|
m_pCanvas->d->view->doc()->addCommand( undo );
|
|
}
|
|
}
|
|
|
|
for( int i = start; i <= end; i++ )
|
|
{
|
|
RowFormat *rl = sheet->nonDefaultRowFormat( i );
|
|
if ( height != 0.0 )
|
|
{
|
|
if ( !rl->isHide() )
|
|
rl->setDblHeight( height );
|
|
}
|
|
else
|
|
{
|
|
sheet->hideRow(*m_pView->selectionInfo());
|
|
}
|
|
}
|
|
|
|
delete m_lSize;
|
|
m_lSize = 0;
|
|
}
|
|
}
|
|
else if ( m_bSelection )
|
|
{
|
|
TQRect rect = m_pView->selectionInfo()->lastRange();
|
|
|
|
// TODO: please don't remove. Right now it's useless, but it's for a future feature
|
|
// Norbert
|
|
bool m_frozen = false;
|
|
if ( m_frozen )
|
|
{
|
|
kdDebug(36001) << "selected: T " << rect.top() << " B " << rect.bottom() << endl;
|
|
|
|
int i;
|
|
RowFormat * row;
|
|
TQValueList<int>hiddenRows;
|
|
|
|
for ( i = rect.top(); i <= rect.bottom(); ++i )
|
|
{
|
|
row = m_pView->activeSheet()->rowFormat( i );
|
|
if ( row->isHide() )
|
|
{
|
|
hiddenRows.append(i);
|
|
}
|
|
}
|
|
|
|
if ( hiddenRows.count() > 0 )
|
|
m_pView->activeSheet()->showRow(*m_pView->selectionInfo());
|
|
}
|
|
}
|
|
|
|
m_bSelection = false;
|
|
m_bResize = false;
|
|
}
|
|
|
|
void VBorder::equalizeRow( double resize )
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
Q_ASSERT( sheet );
|
|
|
|
TQRect selection( m_pView->selectionInfo()->selection() );
|
|
if ( !m_pCanvas->d->view->doc()->undoLocked() )
|
|
{
|
|
UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection );
|
|
m_pCanvas->d->view->doc()->addCommand( undo );
|
|
}
|
|
RowFormat *rl;
|
|
for ( int i = selection.top(); i <= selection.bottom(); i++ )
|
|
{
|
|
rl = sheet->nonDefaultRowFormat( i );
|
|
resize = TQMAX( 2.0, resize);
|
|
rl->setDblHeight( resize );
|
|
}
|
|
}
|
|
|
|
void VBorder::mouseDoubleClickEvent(TQMouseEvent*)
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() )
|
|
return;
|
|
|
|
sheet->adjustRow(*m_pCanvas->selectionInfo());
|
|
}
|
|
|
|
|
|
void VBorder::mouseMoveEvent( TQMouseEvent * _ev )
|
|
{
|
|
if ( !m_pView->koDocument()->isReadWrite() )
|
|
return;
|
|
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
|
|
if (!sheet)
|
|
return;
|
|
|
|
double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset();
|
|
double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() );
|
|
|
|
// The button is pressed and we are resizing ?
|
|
if ( m_bResize )
|
|
{
|
|
if ( !sheet->isProtected() )
|
|
paintSizeIndicator( _ev->pos().y(), false );
|
|
}
|
|
// The button is pressed and we are selecting ?
|
|
else if ( m_bSelection )
|
|
{
|
|
double y;
|
|
int row = sheet->topRow( ev_PosY, y );
|
|
if ( row > KS_rowMax )
|
|
return;
|
|
|
|
TQPoint newAnchor = m_pView->selectionInfo()->anchor();
|
|
TQPoint newMarker = m_pView->selectionInfo()->marker();
|
|
newMarker.setY( row );
|
|
newAnchor.setY( m_iSelectionAnchor );
|
|
m_pView->selectionInfo()->update(newMarker);
|
|
|
|
if ( _ev->pos().y() < 0 )
|
|
m_pCanvas->vertScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItY( ev_PosY ) );
|
|
else if ( _ev->pos().y() > m_pCanvas->height() )
|
|
{
|
|
if ( row < KS_rowMax )
|
|
{
|
|
RowFormat *rl = sheet->rowFormat( row + 1 );
|
|
y = sheet->dblRowPos( row + 1 );
|
|
m_pCanvas->vertScrollBar()->setValue ((int) (m_pCanvas->d->view->doc()->zoomItY
|
|
(ev_PosY + rl->dblHeight()) - dHeight));
|
|
}
|
|
}
|
|
}
|
|
// No button is pressed and the mouse is just moved
|
|
else
|
|
{
|
|
|
|
//What is the internal size of 1 pixel
|
|
const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItY( 1 );
|
|
double y;
|
|
int tmpRow = sheet->topRow( m_pCanvas->yOffset(), y );
|
|
|
|
while ( y < m_pCanvas->d->view->doc()->unzoomItY( height() ) + m_pCanvas->yOffset() )
|
|
{
|
|
double h = sheet->rowFormat( tmpRow )->dblHeight();
|
|
//if col is hide and it's the first column
|
|
//you mustn't resize it.
|
|
if ( ev_PosY >= y + h - 2 * unzoomedPixel &&
|
|
ev_PosY <= y + h + unzoomedPixel &&
|
|
!( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 ) )
|
|
{
|
|
setCursor( splitVCursor );
|
|
return;
|
|
}
|
|
y += h;
|
|
tmpRow++;
|
|
}
|
|
setCursor( arrowCursor );
|
|
}
|
|
}
|
|
|
|
void VBorder::doAutoScroll()
|
|
{
|
|
if ( !m_bMousePressed )
|
|
{
|
|
m_scrollTimer->stop();
|
|
return;
|
|
}
|
|
|
|
TQPoint pos( mapFromGlobal( TQCursor::pos() ) );
|
|
|
|
if ( pos.y() < 0 || pos.y() > height() )
|
|
{
|
|
TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 );
|
|
mouseMoveEvent( event );
|
|
delete event;
|
|
}
|
|
|
|
//Restart timer
|
|
m_scrollTimer->start( 50 );
|
|
}
|
|
|
|
void VBorder::wheelEvent( TQWheelEvent* _ev )
|
|
{
|
|
if ( m_pCanvas->vertScrollBar() )
|
|
TQApplication::sendEvent( m_pCanvas->vertScrollBar(), _ev );
|
|
}
|
|
|
|
|
|
void VBorder::paintSizeIndicator( int mouseY, bool firstTime )
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
TQPainter painter;
|
|
painter.begin( m_pCanvas );
|
|
painter.setRasterOp( NotROP );
|
|
|
|
if ( !firstTime )
|
|
painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos );
|
|
|
|
m_iResizePos = mouseY;
|
|
|
|
// Dont make the row have a height < 2 pixel.
|
|
int y = m_pCanvas->d->view->doc()->zoomItY( sheet->dblRowPos( m_iResizedRow ) - m_pCanvas->yOffset() );
|
|
if ( m_iResizePos < y + 2 )
|
|
m_iResizePos = y;
|
|
|
|
painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos );
|
|
|
|
painter.end();
|
|
|
|
TQString tmpSize;
|
|
if ( m_iResizePos != y )
|
|
tmpSize = i18n("Height: %1 %2").arg( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItY( m_iResizePos - y ),
|
|
m_pView->doc()->unit() ) )
|
|
.arg( m_pView->doc()->unitName() );
|
|
else
|
|
tmpSize = i18n( "Hide Row" );
|
|
|
|
painter.begin( this );
|
|
int len = painter.fontMetrics().width( tmpSize );
|
|
int hei = painter.fontMetrics().height();
|
|
painter.end();
|
|
|
|
if ( !m_lSize )
|
|
{
|
|
m_lSize = new TQLabel( m_pCanvas );
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
m_lSize->setGeometry( m_pCanvas->width() - len - 5,
|
|
y + 3, len + 2, hei + 2 );
|
|
else
|
|
m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 );
|
|
|
|
m_lSize->setAlignment( TQt::AlignVCenter );
|
|
m_lSize->setText( tmpSize );
|
|
m_lSize->setPalette( TQToolTip::palette() );
|
|
m_lSize->show();
|
|
}
|
|
else
|
|
{
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
m_lSize->setGeometry( m_pCanvas->width() - len - 5,
|
|
y + 3, len + 2, hei + 2 );
|
|
else
|
|
m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 );
|
|
|
|
m_lSize->setText( tmpSize );
|
|
}
|
|
}
|
|
|
|
void VBorder::updateRows( int from, int to )
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
int y0 = sheet->rowPos( from, m_pCanvas );
|
|
int y1 = sheet->rowPos( to+1, m_pCanvas );
|
|
update( 0, y0, width(), y1-y0 );
|
|
}
|
|
|
|
void VBorder::paintEvent( TQPaintEvent* _ev )
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
TQPainter painter( this );
|
|
TQColor highlightColor = View::highlightColor();
|
|
TQPen pen( TQt::black, 1 );
|
|
painter.setPen( pen );
|
|
// painter.setBackgroundColor( colorGroup().base() );
|
|
|
|
// painter.eraseRect( _ev->rect() );
|
|
|
|
//TQFontMetrics fm = painter.fontMetrics();
|
|
// Matthias Elter: This causes a SEGFAULT in ~TQPainter!
|
|
// Only god and the trolls know why ;-)
|
|
// bah...took me quite some time to track this one down...
|
|
|
|
painter.setClipRect( _ev->rect() );
|
|
|
|
double yPos;
|
|
//Get the top row and the current y-position
|
|
int y = sheet->topRow( (m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().y() ) + m_pCanvas->yOffset()), yPos );
|
|
//Align to the offset
|
|
yPos = yPos - m_pCanvas->yOffset();
|
|
int width = m_pCanvas->d->view->doc()->zoomItX( YBORDER_WIDTH );
|
|
|
|
TQFont normalFont = painter.font();
|
|
if ( m_pCanvas->d->view->doc()->zoom() < 100 )
|
|
{
|
|
normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() *
|
|
normalFont.pointSizeFloat() );
|
|
}
|
|
TQFont boldFont = normalFont;
|
|
boldFont.setBold( true );
|
|
|
|
//Loop through the rows, until we are out of range
|
|
while ( yPos <= m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().bottom() ) )
|
|
{
|
|
bool selected = (m_pView->selectionInfo()->isRowSelected(y));
|
|
bool highlighted = (!selected && m_pView->selectionInfo()->isRowAffected(y));
|
|
|
|
const RowFormat *row_lay = sheet->rowFormat( y );
|
|
int zoomedYPos = m_pCanvas->d->view->doc()->zoomItY( yPos );
|
|
int height = m_pCanvas->d->view->doc()->zoomItY( yPos + row_lay->dblHeight() ) - zoomedYPos;
|
|
|
|
if ( selected )
|
|
{
|
|
TQBrush fillSelected( highlightColor );
|
|
qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150),
|
|
1, &fillSelected );
|
|
}
|
|
else if ( highlighted )
|
|
{
|
|
TQBrush fillHighlighted( highlightColor );
|
|
qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150),
|
|
1, &fillHighlighted );
|
|
}
|
|
else
|
|
{
|
|
TQColor c = colorGroup().background();
|
|
TQBrush fill( c );
|
|
qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, c.dark(150),
|
|
1, &fill );
|
|
}
|
|
|
|
TQString rowText = TQString::number( y );
|
|
|
|
// Reset painter
|
|
painter.setFont( normalFont );
|
|
painter.setPen( colorGroup().text() );
|
|
|
|
if ( selected )
|
|
painter.setPen( colorGroup().highlightedText() );
|
|
else if ( highlighted )
|
|
painter.setFont( boldFont );
|
|
|
|
int len = painter.fontMetrics().width( rowText );
|
|
if (!row_lay->isHide())
|
|
painter.drawText( ( width-len )/2, zoomedYPos +
|
|
( height + painter.fontMetrics().ascent() -
|
|
painter.fontMetrics().descent() ) / 2, rowText );
|
|
|
|
yPos += row_lay->dblHeight();
|
|
y++;
|
|
}
|
|
}
|
|
|
|
|
|
void VBorder::focusOutEvent( TQFocusEvent* )
|
|
{
|
|
if ( m_scrollTimer->isActive() )
|
|
m_scrollTimer->stop();
|
|
m_bMousePressed = false;
|
|
}
|
|
|
|
|
|
/****************************************************************
|
|
*
|
|
* HBorder
|
|
*
|
|
****************************************************************/
|
|
|
|
HBorder::HBorder( TQWidget *_parent, Canvas *_canvas,View *_view )
|
|
: TQWidget( _parent, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase )
|
|
{
|
|
m_pView = _view;
|
|
m_pCanvas = _canvas;
|
|
m_lSize = 0L;
|
|
setBackgroundMode( PaletteButton );
|
|
setMouseTracking( true );
|
|
m_bResize = false;
|
|
m_bSelection = false;
|
|
m_iSelectionAnchor=1;
|
|
m_bMousePressed = false;
|
|
|
|
m_scrollTimer = new TQTimer( this );
|
|
connect( m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( doAutoScroll() ) );
|
|
}
|
|
|
|
|
|
HBorder::~HBorder()
|
|
{
|
|
delete m_scrollTimer;
|
|
}
|
|
|
|
TQSize HBorder::sizeHint() const
|
|
{
|
|
return TQSize( 40, 10 );
|
|
}
|
|
|
|
void HBorder::mousePressEvent( TQMouseEvent * _ev )
|
|
{
|
|
if (!m_pView->koDocument()->isReadWrite())
|
|
return;
|
|
|
|
if ( _ev->button() == Qt::LeftButton )
|
|
m_bMousePressed = true;
|
|
|
|
const Sheet *sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
// We were editing a cell -> save value and get out of editing mode
|
|
if ( m_pCanvas->editor() )
|
|
{
|
|
m_pCanvas->deleteEditor( true ); // save changes
|
|
}
|
|
|
|
m_scrollTimer->start( 50 );
|
|
|
|
double ev_PosX;
|
|
double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() );
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
|
|
else
|
|
ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
|
|
m_bResize = false;
|
|
m_bSelection = false;
|
|
|
|
// Find the first visible column and the x position of this column.
|
|
double x;
|
|
|
|
const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 );
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x );
|
|
|
|
kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", COL: " << tmpCol << endl;
|
|
while ( ev_PosX > x && ( !m_bResize ) )
|
|
{
|
|
double w = sheet->columnFormat( tmpCol )->dblWidth();
|
|
|
|
kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", w: " << w << ", COL: " << tmpCol << endl;
|
|
|
|
++tmpCol;
|
|
if ( tmpCol > KS_colMax )
|
|
tmpCol = KS_colMax;
|
|
//if col is hide and it's the first column
|
|
//you mustn't resize it.
|
|
|
|
if ( ev_PosX >= x + w - unzoomedPixel &&
|
|
ev_PosX <= x + w + unzoomedPixel &&
|
|
!( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) )
|
|
{
|
|
m_bResize = true;
|
|
}
|
|
x += w;
|
|
}
|
|
|
|
//if col is hide and it's the first column
|
|
//you mustn't resize it.
|
|
double tmp2;
|
|
tmpCol = sheet->leftColumn( dWidth - ev_PosX + 1, tmp2 );
|
|
if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 )
|
|
{
|
|
kdDebug() << "No resize: " << tmpCol << ", " << sheet->columnFormat( tmpCol )->isHide() << endl;
|
|
m_bResize = false;
|
|
}
|
|
|
|
kdDebug() << "Resize: " << m_bResize << endl;
|
|
}
|
|
else
|
|
{
|
|
int col = sheet->leftColumn( m_pCanvas->xOffset(), x );
|
|
|
|
// Did the user click between two columns?
|
|
while ( x < ( dWidth + m_pCanvas->xOffset() ) && ( !m_bResize ) )
|
|
{
|
|
double w = sheet->columnFormat( col )->dblWidth();
|
|
col++;
|
|
if ( col > KS_colMax )
|
|
col = KS_colMax;
|
|
if ( ( ev_PosX >= x + w - unzoomedPixel ) &&
|
|
( ev_PosX <= x + w + unzoomedPixel ) &&
|
|
!( sheet->columnFormat( col )->isHide() && col == 1 ) )
|
|
m_bResize = true;
|
|
x += w;
|
|
}
|
|
|
|
//if col is hide and it's the first column
|
|
//you mustn't resize it.
|
|
double tmp2;
|
|
int tmpCol = sheet->leftColumn( ev_PosX - 1, tmp2 );
|
|
if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 )
|
|
m_bResize = false;
|
|
}
|
|
|
|
// So he clicked between two rows ?
|
|
if ( m_bResize )
|
|
{
|
|
// Determine the column to resize
|
|
double tmp;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp );
|
|
// kdDebug() << "RColumn: " << m_iResizedColumn << ", PosX: " << ev_PosX << endl;
|
|
|
|
if ( !sheet->isProtected() )
|
|
paintSizeIndicator( _ev->pos().x(), true );
|
|
}
|
|
else
|
|
{
|
|
m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp );
|
|
|
|
if ( !sheet->isProtected() )
|
|
paintSizeIndicator( _ev->pos().x(), true );
|
|
}
|
|
|
|
// kdDebug() << "Column: " << m_iResizedColumn << endl;
|
|
}
|
|
else
|
|
{
|
|
m_bSelection = true;
|
|
|
|
double tmp;
|
|
int hit_col = sheet->leftColumn( ev_PosX, tmp );
|
|
if ( hit_col > KS_colMax )
|
|
return;
|
|
|
|
m_iSelectionAnchor = hit_col;
|
|
|
|
if ( !m_pView->selectionInfo()->contains( TQPoint( hit_col, 1 ) ) ||
|
|
!( _ev->button() == Qt::RightButton ) ||
|
|
!m_pView->selectionInfo()->isColumnSelected() )
|
|
{
|
|
TQPoint newMarker( hit_col, 1 );
|
|
TQPoint newAnchor( hit_col, KS_rowMax );
|
|
#ifdef NONCONTIGUOUSSELECTION
|
|
if (_ev->state() == ControlButton)
|
|
{
|
|
m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker));
|
|
}
|
|
else
|
|
#endif
|
|
if (_ev->state() == ShiftButton)
|
|
{
|
|
m_pView->selectionInfo()->update(newMarker);
|
|
}
|
|
else
|
|
{
|
|
m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker));
|
|
}
|
|
}
|
|
|
|
if ( _ev->button() == Qt::RightButton )
|
|
{
|
|
TQPoint p = mapToGlobal( _ev->pos() );
|
|
m_pView->popupColumnMenu( p );
|
|
m_bSelection = false;
|
|
}
|
|
m_pView->updateEditWidget();
|
|
}
|
|
}
|
|
|
|
void HBorder::mouseReleaseEvent( TQMouseEvent * _ev )
|
|
{
|
|
if ( m_scrollTimer->isActive() )
|
|
m_scrollTimer->stop();
|
|
|
|
m_bMousePressed = false;
|
|
|
|
if ( !m_pView->koDocument()->isReadWrite() )
|
|
return;
|
|
|
|
Sheet * sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
if ( m_bResize )
|
|
{
|
|
double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() );
|
|
double ev_PosX;
|
|
|
|
// Remove size indicator painted by paintSizeIndicator
|
|
TQPainter painter;
|
|
painter.begin( m_pCanvas );
|
|
painter.setRasterOp( NotROP );
|
|
painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() );
|
|
painter.end();
|
|
|
|
int start = m_iResizedColumn;
|
|
int end = m_iResizedColumn;
|
|
TQRect rect;
|
|
rect.setCoords( m_iResizedColumn, 1, m_iResizedColumn, KS_rowMax );
|
|
if ( m_pView->selectionInfo()->isColumnSelected() )
|
|
{
|
|
if ( m_pView->selectionInfo()->contains( TQPoint( m_iResizedColumn, 1 ) ) )
|
|
{
|
|
start = m_pView->selectionInfo()->lastRange().left();
|
|
end = m_pView->selectionInfo()->lastRange().right();
|
|
rect = m_pView->selectionInfo()->lastRange();
|
|
}
|
|
}
|
|
|
|
double width = 0.0;
|
|
double x;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
|
|
else
|
|
ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
|
|
|
|
x = sheet->dblColumnPos( m_iResizedColumn );
|
|
|
|
if ( ev_PosX - x <= 0.0 )
|
|
width = 0.0;
|
|
else
|
|
width = ev_PosX - x;
|
|
|
|
if ( !sheet->isProtected() )
|
|
{
|
|
if ( !m_pCanvas->d->view->doc()->undoLocked() )
|
|
{
|
|
//just resize
|
|
if ( width != 0.0 )
|
|
{
|
|
// TODO Stefan: replace this
|
|
UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect );
|
|
m_pCanvas->d->view->doc()->addCommand( undo );
|
|
}
|
|
}
|
|
|
|
for( int i = start; i <= end; i++ )
|
|
{
|
|
ColumnFormat *cl = sheet->nonDefaultColumnFormat( i );
|
|
if ( width != 0.0 )
|
|
{
|
|
if ( !cl->isHide() )
|
|
cl->setDblWidth( width );
|
|
}
|
|
else
|
|
{
|
|
sheet->hideColumn(*m_pView->selectionInfo());
|
|
}
|
|
}
|
|
|
|
delete m_lSize;
|
|
m_lSize = 0;
|
|
}
|
|
}
|
|
else if ( m_bSelection )
|
|
{
|
|
TQRect rect = m_pView->selectionInfo()->lastRange();
|
|
|
|
// TODO: please don't remove. Right now it's useless, but it's for a future feature
|
|
// Norbert
|
|
bool m_frozen = false;
|
|
if ( m_frozen )
|
|
{
|
|
kdDebug(36001) << "selected: L " << rect.left() << " R " << rect.right() << endl;
|
|
|
|
int i;
|
|
ColumnFormat * col;
|
|
TQValueList<int>hiddenCols;
|
|
|
|
for ( i = rect.left(); i <= rect.right(); ++i )
|
|
{
|
|
col = m_pView->activeSheet()->columnFormat( i );
|
|
if ( col->isHide() )
|
|
{
|
|
hiddenCols.append(i);
|
|
}
|
|
}
|
|
|
|
if ( hiddenCols.count() > 0 )
|
|
m_pView->activeSheet()->showColumn(*m_pView->selectionInfo());
|
|
}
|
|
}
|
|
|
|
m_bSelection = false;
|
|
m_bResize = false;
|
|
}
|
|
|
|
void HBorder::equalizeColumn( double resize )
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
Q_ASSERT( sheet );
|
|
|
|
TQRect selection( m_pView->selectionInfo()->selection() );
|
|
if ( !m_pCanvas->d->view->doc()->undoLocked() )
|
|
{
|
|
UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection );
|
|
m_pCanvas->d->view->doc()->addCommand( undo );
|
|
}
|
|
ColumnFormat *cl;
|
|
for ( int i = selection.left(); i <= selection.right(); i++ )
|
|
{
|
|
cl = sheet->nonDefaultColumnFormat( i );
|
|
resize = TQMAX( 2.0, resize );
|
|
cl->setDblWidth( resize );
|
|
}
|
|
|
|
}
|
|
|
|
void HBorder::mouseDoubleClickEvent(TQMouseEvent*)
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() )
|
|
return;
|
|
|
|
sheet->adjustColumn(*m_pCanvas->selectionInfo());
|
|
}
|
|
|
|
void HBorder::mouseMoveEvent( TQMouseEvent * _ev )
|
|
{
|
|
if ( !m_pView->koDocument()->isReadWrite() )
|
|
return;
|
|
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
|
|
if (!sheet)
|
|
return;
|
|
|
|
double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() );
|
|
double ev_PosX;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
|
|
else
|
|
ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
|
|
|
|
// The button is pressed and we are resizing ?
|
|
if ( m_bResize )
|
|
{
|
|
if ( !sheet->isProtected() )
|
|
paintSizeIndicator( _ev->pos().x(), false );
|
|
}
|
|
// The button is pressed and we are selecting ?
|
|
else if ( m_bSelection )
|
|
{
|
|
double x;
|
|
int col = sheet->leftColumn( ev_PosX, x );
|
|
|
|
if ( col > KS_colMax )
|
|
return;
|
|
|
|
TQPoint newMarker = m_pView->selectionInfo()->marker();
|
|
TQPoint newAnchor = m_pView->selectionInfo()->anchor();
|
|
newMarker.setX( col );
|
|
newAnchor.setX( m_iSelectionAnchor );
|
|
m_pView->selectionInfo()->update(newMarker);
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
if ( _ev->pos().x() < width() - m_pCanvas->width() )
|
|
{
|
|
ColumnFormat *cl = sheet->columnFormat( col + 1 );
|
|
x = sheet->dblColumnPos( col + 1 );
|
|
m_pCanvas->horzScrollBar()->setValue ( m_pCanvas->horzScrollBar()->maxValue() - (int)
|
|
(m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - m_pCanvas->d->view->doc()->unzoomItX( m_pCanvas->width() )));
|
|
}
|
|
else if ( _ev->pos().x() > width() )
|
|
m_pCanvas->horzScrollBar()->setValue( m_pCanvas->horzScrollBar()->maxValue() - m_pCanvas->d->view->doc()->zoomItX( ev_PosX - dWidth + m_pCanvas->d->view->doc()->unzoomItX( m_pCanvas->width() ) ) );
|
|
}
|
|
else
|
|
{
|
|
if ( _ev->pos().x() < 0 )
|
|
m_pCanvas->horzScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItX( ev_PosX ) );
|
|
else if ( _ev->pos().x() > m_pCanvas->width() )
|
|
{
|
|
if ( col < KS_colMax )
|
|
{
|
|
ColumnFormat *cl = sheet->columnFormat( col + 1 );
|
|
x = sheet->dblColumnPos( col + 1 );
|
|
m_pCanvas->horzScrollBar()->setValue ((int)
|
|
(m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - dWidth));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
// No button is pressed and the mouse is just moved
|
|
else
|
|
{
|
|
//What is the internal size of 1 pixel
|
|
const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 );
|
|
double x;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x );
|
|
|
|
while ( ev_PosX > x )
|
|
{
|
|
double w = sheet->columnFormat( tmpCol )->dblWidth();
|
|
++tmpCol;
|
|
|
|
//if col is hide and it's the first column
|
|
//you mustn't resize it.
|
|
if ( ev_PosX >= x + w - unzoomedPixel &&
|
|
ev_PosX <= x + w + unzoomedPixel &&
|
|
!( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 ) )
|
|
{
|
|
setCursor( splitHCursor );
|
|
return;
|
|
}
|
|
x += w;
|
|
}
|
|
setCursor( arrowCursor );
|
|
}
|
|
else
|
|
{
|
|
int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x );
|
|
|
|
while ( x < m_pCanvas->d->view->doc()->unzoomItY( width() ) + m_pCanvas->xOffset() )
|
|
{
|
|
double w = sheet->columnFormat( tmpCol )->dblWidth();
|
|
//if col is hide and it's the first column
|
|
//you mustn't resize it.
|
|
if ( ev_PosX >= x + w - unzoomedPixel &&
|
|
ev_PosX <= x + w + unzoomedPixel &&
|
|
!( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) )
|
|
{
|
|
setCursor( splitHCursor );
|
|
return;
|
|
}
|
|
x += w;
|
|
tmpCol++;
|
|
}
|
|
setCursor( arrowCursor );
|
|
}
|
|
}
|
|
}
|
|
|
|
void HBorder::doAutoScroll()
|
|
{
|
|
if ( !m_bMousePressed )
|
|
{
|
|
m_scrollTimer->stop();
|
|
return;
|
|
}
|
|
|
|
TQPoint pos( mapFromGlobal( TQCursor::pos() ) );
|
|
|
|
if ( pos.x() < 0 || pos.x() > width() )
|
|
{
|
|
TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 );
|
|
mouseMoveEvent( event );
|
|
delete event;
|
|
}
|
|
|
|
//Restart timer
|
|
m_scrollTimer->start( 50 );
|
|
}
|
|
|
|
void HBorder::wheelEvent( TQWheelEvent* _ev )
|
|
{
|
|
if ( m_pCanvas->horzScrollBar() )
|
|
TQApplication::sendEvent( m_pCanvas->horzScrollBar(), _ev );
|
|
}
|
|
|
|
void HBorder::resizeEvent( TQResizeEvent* _ev )
|
|
{
|
|
// workaround to allow horizontal resizing and zoom changing when sheet
|
|
// direction and interface direction don't match (e.g. an RTL sheet on an
|
|
// LTR interface)
|
|
if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() )
|
|
{
|
|
int dx = _ev->size().width() - _ev->oldSize().width();
|
|
scroll(dx, 0);
|
|
}
|
|
else if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() )
|
|
{
|
|
int dx = _ev->size().width() - _ev->oldSize().width();
|
|
scroll(-dx, 0);
|
|
}
|
|
}
|
|
|
|
void HBorder::paintSizeIndicator( int mouseX, bool firstTime )
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if (!sheet)
|
|
return;
|
|
|
|
TQPainter painter;
|
|
painter.begin( m_pCanvas );
|
|
painter.setRasterOp( NotROP );
|
|
|
|
if ( !firstTime )
|
|
painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() );
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
m_iResizePos = mouseX + m_pCanvas->width() - width();
|
|
else
|
|
m_iResizePos = mouseX;
|
|
|
|
// Dont make the column have a width < 2 pixels.
|
|
int x = m_pCanvas->d->view->doc()->zoomItX( sheet->dblColumnPos( m_iResizedColumn ) - m_pCanvas->xOffset() );
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
x = m_pCanvas->width() - x;
|
|
|
|
if ( m_iResizePos > x - 2 )
|
|
m_iResizePos = x;
|
|
}
|
|
else
|
|
{
|
|
if ( m_iResizePos < x + 2 )
|
|
m_iResizePos = x;
|
|
}
|
|
|
|
painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() );
|
|
|
|
painter.end();
|
|
|
|
TQString tmpSize;
|
|
if ( m_iResizePos != x )
|
|
tmpSize = i18n("Width: %1 %2")
|
|
.arg( TDEGlobal::locale()->formatNumber( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItX( (sheet->layoutDirection()==Sheet::RightToLeft) ? x - m_iResizePos : m_iResizePos - x ),
|
|
m_pView->doc()->unit() )))
|
|
.arg( m_pView->doc()->unitName() );
|
|
else
|
|
tmpSize = i18n( "Hide Column" );
|
|
|
|
painter.begin( this );
|
|
int len = painter.fontMetrics().width( tmpSize );
|
|
int hei = painter.fontMetrics().height();
|
|
painter.end();
|
|
|
|
if ( !m_lSize )
|
|
{
|
|
m_lSize = new TQLabel( m_pCanvas );
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 );
|
|
else
|
|
m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 );
|
|
|
|
m_lSize->setAlignment( TQt::AlignVCenter );
|
|
m_lSize->setText( tmpSize );
|
|
m_lSize->setPalette( TQToolTip::palette() );
|
|
m_lSize->show();
|
|
}
|
|
else
|
|
{
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 );
|
|
else
|
|
m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 );
|
|
|
|
m_lSize->setText( tmpSize );
|
|
}
|
|
}
|
|
|
|
void HBorder::updateColumns( int from, int to )
|
|
{
|
|
Sheet *sheet = m_pCanvas->activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
int x0 = sheet->columnPos( from, m_pCanvas );
|
|
int x1 = sheet->columnPos( to+1, m_pCanvas );
|
|
update( x0, 0, x1-x0, height() );
|
|
}
|
|
|
|
void HBorder::paintEvent( TQPaintEvent* _ev )
|
|
{
|
|
Sheet * sheet = m_pCanvas->activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
TQColor highlightColor = View::highlightColor();
|
|
TQPainter painter( this );
|
|
TQPen pen( TQt::black, 1 );
|
|
painter.setPen( pen );
|
|
painter.setBackgroundColor( white );
|
|
|
|
painter.setClipRect( _ev->rect() );
|
|
|
|
// painter.eraseRect( _ev->rect() );
|
|
|
|
//TQFontMetrics fm = painter.fontMetrics();
|
|
// Matthias Elter: This causes a SEGFAULT in ~TQPainter!
|
|
// Only god and the trolls know why ;-)
|
|
// bah...took me quite some time to track this one down...
|
|
|
|
double xPos;
|
|
int x;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
//Get the left column and the current x-position
|
|
x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( width() ) - m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos );
|
|
//Align to the offset
|
|
xPos = m_pCanvas->d->view->doc()->unzoomItX( width() ) - xPos + m_pCanvas->xOffset();
|
|
}
|
|
else
|
|
{
|
|
//Get the left column and the current x-position
|
|
x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos );
|
|
//Align to the offset
|
|
xPos = xPos - m_pCanvas->xOffset();
|
|
}
|
|
|
|
int height = m_pCanvas->d->view->doc()->zoomItY( TQFont(painter.font()).pointSizeFloat() + 5 );
|
|
|
|
TQFont normalFont = painter.font();
|
|
if ( m_pCanvas->d->view->doc()->zoom() < 100 )
|
|
{
|
|
normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() *
|
|
normalFont.pointSizeFloat() );
|
|
}
|
|
TQFont boldFont = normalFont;
|
|
boldFont.setBold( true );
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
if ( x > KS_colMax )
|
|
x = KS_colMax;
|
|
|
|
xPos -= sheet->columnFormat( x )->dblWidth();
|
|
|
|
//Loop through the columns, until we are out of range
|
|
while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) )
|
|
{
|
|
bool selected = (m_pView->selectionInfo()->isColumnSelected(x));
|
|
bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x));
|
|
|
|
const ColumnFormat * col_lay = sheet->columnFormat( x );
|
|
int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos );
|
|
int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos;
|
|
|
|
if ( selected )
|
|
{
|
|
TQBrush fillSelected( highlightColor );
|
|
qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150),
|
|
1, &fillSelected );
|
|
}
|
|
else if ( highlighted )
|
|
{
|
|
TQBrush fillHighlighted( highlightColor );
|
|
qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150),
|
|
1, &fillHighlighted );
|
|
}
|
|
else
|
|
{
|
|
TQColor c = colorGroup().background();
|
|
TQBrush fill( c );
|
|
qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150),
|
|
1, &fill );
|
|
}
|
|
|
|
// Reset painter
|
|
painter.setFont( normalFont );
|
|
painter.setPen( colorGroup().text() );
|
|
|
|
if ( selected )
|
|
painter.setPen( colorGroup().highlightedText() );
|
|
else if ( highlighted )
|
|
painter.setFont( boldFont );
|
|
if ( !m_pView->activeSheet()->getShowColumnNumber() )
|
|
{
|
|
TQString colText = Cell::columnName( x );
|
|
int len = painter.fontMetrics().width( colText );
|
|
if ( !col_lay->isHide() )
|
|
painter.drawText( zoomedXPos + ( width - len ) / 2,
|
|
( height + painter.fontMetrics().ascent() -
|
|
painter.fontMetrics().descent() ) / 2, colText );
|
|
}
|
|
else
|
|
{
|
|
TQString tmp;
|
|
int len = painter.fontMetrics().width( tmp.setNum(x) );
|
|
if (!col_lay->isHide())
|
|
painter.drawText( zoomedXPos + ( width - len ) / 2,
|
|
( height + painter.fontMetrics().ascent() -
|
|
painter.fontMetrics().descent() ) / 2,
|
|
tmp.setNum(x) );
|
|
}
|
|
xPos += col_lay->dblWidth();
|
|
--x;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Loop through the columns, until we are out of range
|
|
while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) )
|
|
{
|
|
bool selected = (m_pView->selectionInfo()->isColumnSelected(x));
|
|
bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x));
|
|
|
|
const ColumnFormat *col_lay = sheet->columnFormat( x );
|
|
int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos );
|
|
int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos;
|
|
|
|
if ( selected )
|
|
{
|
|
TQBrush fillSelected( highlightColor );
|
|
qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(),
|
|
1, &fillSelected );
|
|
}
|
|
else if ( highlighted )
|
|
{
|
|
TQBrush fillHighlighted( highlightColor );
|
|
qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(),
|
|
1, &fillHighlighted );
|
|
}
|
|
else
|
|
{
|
|
TQColor c = colorGroup().background();
|
|
TQBrush fill( c );
|
|
qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150),
|
|
1, &fill );
|
|
}
|
|
|
|
// Reset painter
|
|
painter.setFont( normalFont );
|
|
painter.setPen( colorGroup().text() );
|
|
|
|
if ( selected )
|
|
painter.setPen( colorGroup().highlightedText() );
|
|
else if ( highlighted )
|
|
painter.setFont( boldFont );
|
|
if ( !m_pView->activeSheet()->getShowColumnNumber() )
|
|
{
|
|
TQString colText = Cell::columnName( x );
|
|
int len = painter.fontMetrics().width( colText );
|
|
if (!col_lay->isHide())
|
|
painter.drawText( zoomedXPos + ( width - len ) / 2,
|
|
( height + painter.fontMetrics().ascent() -
|
|
painter.fontMetrics().descent() ) / 2, colText );
|
|
}
|
|
else
|
|
{
|
|
TQString tmp;
|
|
int len = painter.fontMetrics().width( tmp.setNum(x) );
|
|
if (!col_lay->isHide())
|
|
painter.drawText( zoomedXPos + ( width - len ) / 2,
|
|
( height + painter.fontMetrics().ascent() -
|
|
painter.fontMetrics().descent() ) / 2,
|
|
tmp.setNum(x) );
|
|
}
|
|
xPos += col_lay->dblWidth();
|
|
++x;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HBorder::focusOutEvent( TQFocusEvent* )
|
|
{
|
|
if ( m_scrollTimer->isActive() )
|
|
m_scrollTimer->stop();
|
|
m_bMousePressed = false;
|
|
}
|
|
|
|
/****************************************************************
|
|
*
|
|
* ToolTip
|
|
*
|
|
****************************************************************/
|
|
|
|
ToolTip::ToolTip( Canvas* canvas )
|
|
: TQToolTip( canvas ), m_canvas( canvas )
|
|
{
|
|
}
|
|
|
|
// find the label for the tip
|
|
// this is a hack of course, because it's not available from TQToolTip
|
|
TQLabel *tip_findLabel()
|
|
{
|
|
TQWidgetList *list = TQApplication::allWidgets();
|
|
TQWidgetListIt it( *list );
|
|
TQWidget * w;
|
|
while ( (w=it.current()) != 0 )
|
|
{
|
|
if(w->isA("TQTipLabel"))
|
|
return static_cast<TQLabel*>(w);
|
|
++it;
|
|
}
|
|
delete list;
|
|
return 0;
|
|
}
|
|
|
|
void ToolTip::maybeTip( const TQPoint& p )
|
|
{
|
|
Sheet *sheet = m_canvas->activeSheet();
|
|
if ( !sheet )
|
|
return;
|
|
|
|
// Over which cell is the mouse ?
|
|
double ypos, xpos;
|
|
double dwidth = m_canvas->doc()->unzoomItX( m_canvas->width() );
|
|
int col;
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
col = sheet->leftColumn( (dwidth - m_canvas->doc()->unzoomItX( p.x() ) +
|
|
m_canvas->xOffset()), xpos );
|
|
else
|
|
col = sheet->leftColumn( (m_canvas->doc()->unzoomItX( p.x() ) +
|
|
m_canvas->xOffset()), xpos );
|
|
|
|
|
|
int row = sheet->topRow( (m_canvas->doc()->unzoomItY( p.y() ) +
|
|
m_canvas->yOffset()), ypos );
|
|
|
|
const Cell* cell = sheet->visibleCellAt( col, row );
|
|
if ( !cell )
|
|
return;
|
|
|
|
#if 0
|
|
// Quick cut
|
|
if( cell->strOutText().isEmpty() )
|
|
return;
|
|
#endif
|
|
// displayed tool tip, which has the following priorities:
|
|
// - cell content if the cell dimension is too small
|
|
// - cell comment
|
|
// - hyperlink
|
|
TQString tipText;
|
|
TQString comment = cell->format()->comment( col, row );
|
|
|
|
// If cell is too small, show the content
|
|
if ( cell->testFlag( Cell::Flag_CellTooShortX ) ||
|
|
cell->testFlag( Cell::Flag_CellTooShortY ) )
|
|
{
|
|
tipText = cell->strOutText();
|
|
}
|
|
|
|
// Show hyperlink, if any
|
|
if ( tipText.isEmpty() )
|
|
{
|
|
tipText = cell->link();
|
|
}
|
|
|
|
// Nothing to display, bail out
|
|
if ( tipText.isEmpty() && comment.isEmpty() )
|
|
return;
|
|
|
|
// Cut if the tip is ridiculously long
|
|
const unsigned maxLen = 256;
|
|
if ( tipText.length() > maxLen )
|
|
tipText = tipText.left(maxLen).append("...");
|
|
|
|
// Determine position and width of the current cell.
|
|
double u = cell->dblWidth( col );
|
|
double v = cell->dblHeight( row );
|
|
|
|
// Special treatment for obscured cells.
|
|
if ( cell->isObscured() && cell->isPartOfMerged() )
|
|
{
|
|
cell = cell->obscuringCells().first();
|
|
const int moveX = cell->column();
|
|
const int moveY = cell->row();
|
|
|
|
// Use the obscuring cells dimensions
|
|
u = cell->dblWidth( moveX );
|
|
v = cell->dblHeight( moveY );
|
|
xpos = sheet->dblColumnPos( moveX );
|
|
ypos = sheet->dblRowPos( moveY );
|
|
}
|
|
|
|
// Get the cell dimensions
|
|
TQRect marker;
|
|
bool insideMarker = false;
|
|
|
|
if ( sheet->layoutDirection()==Sheet::RightToLeft )
|
|
{
|
|
KoRect unzoomedMarker( dwidth - u - xpos + m_canvas->xOffset(),
|
|
ypos - m_canvas->yOffset(),
|
|
u,
|
|
v );
|
|
|
|
marker = m_canvas->doc()->zoomRect( unzoomedMarker );
|
|
insideMarker = marker.contains( p );
|
|
}
|
|
else
|
|
{
|
|
KoRect unzoomedMarker( xpos - m_canvas->xOffset(),
|
|
ypos - m_canvas->yOffset(),
|
|
u,
|
|
v );
|
|
|
|
marker = m_canvas->doc()->zoomRect( unzoomedMarker );
|
|
insideMarker = marker.contains( p );
|
|
}
|
|
|
|
// No use if mouse is somewhere else
|
|
if ( !insideMarker )
|
|
return;
|
|
|
|
// Find the tipLabel
|
|
// NOTE: if we failed, check again when the tip is shown already
|
|
TQLabel* tipLabel = tip_findLabel();
|
|
|
|
// Ensure that it is plain text
|
|
// Not funny if (intentional or not) <a> appears as hyperlink
|
|
if ( tipLabel )
|
|
tipLabel->setTextFormat( TQt::PlainText );
|
|
|
|
TQFontMetrics fm = tipLabel ? tipLabel->fontMetrics() : m_canvas->fontMetrics();
|
|
const TQRect r( 0, 0, 200, -1 );
|
|
// Wrap the text if too long
|
|
if ( tipText.length() > 16 )
|
|
{
|
|
KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, tipText );
|
|
tipText = wrap->wrappedString();
|
|
delete wrap;
|
|
}
|
|
// Wrap the comment if too long
|
|
if ( comment.length() > 16 )
|
|
{
|
|
KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, comment );
|
|
comment = wrap->wrappedString();
|
|
delete wrap;
|
|
}
|
|
|
|
// Show comment, if any
|
|
if ( tipText.isEmpty() )
|
|
{
|
|
tipText = comment;
|
|
}
|
|
else if ( !comment.isEmpty() )
|
|
{
|
|
//Add 2 extra lines and a text, when both should be in the tooltip
|
|
if ( !comment.isEmpty() )
|
|
comment = "\n\n" + i18n("Comment:") + "\n" + comment;
|
|
|
|
tipText += comment;
|
|
}
|
|
|
|
// Now we shows the tip
|
|
tip( marker, tipText );
|
|
|
|
// Here we try to find the tip label again
|
|
// Reason: the previous tip_findLabel might fail if no tip has ever shown yet
|
|
if ( !tipLabel )
|
|
{
|
|
tipLabel = tip_findLabel();
|
|
if( tipLabel )
|
|
tipLabel->setTextFormat( TQt::PlainText );
|
|
}
|
|
|
|
}
|
|
|
|
#include "kspread_canvas.moc"
|