kspread

kspread_canvas.cpp
1/* This file is part of the KDE project
2
3 Copyright 2006 Robert Knight <robertknight@gmail.com>
4 Copyright 2006 Inge Wallin <inge@lysator.liu.se>
5 Copyright 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
6 Copyright 1999-2002,2004 Laurent Montel <montel@kde.org>
7 Copyright 2002-2005 Ariya Hidayat <ariya@kde.org>
8 Copyright 1999-2004 David Faure <faure@kde.org>
9 Copyright 2004-2005 Meni Livne <livne@kde.org>
10 Copyright 2001-2003 Philipp Mueller <philipp.mueller@gmx.de>
11 Copyright 2002-2003 Norbert Andres <nandres@web.de>
12 Copyright 2003 Hamish Rodda <rodda@kde.org>
13 Copyright 2003 Joseph Wenninger <jowenn@kde.org>
14 Copyright 2003 Lukas Tinkl <lukas@kde.org>
15 Copyright 2000-2002 Werner Trobin <trobin@kde.org>
16 Copyright 2002 Harri Porten <porten@kde.org>
17 Copyright 2002 John Dailey <dailey@vt.edu>
18 Copyright 2002 Daniel Naber <daniel.naber@t-online.de>
19 Copyright 1999-2000 Torben Weis <weis@kde.org>
20 Copyright 1999-2000 Stephan Kulow <coolo@kde.org>
21 Copyright 2000 Bernd Wuebben <wuebben@kde.org>
22 Copyright 2000 Wilco Greven <greven@kde.org>
23 Copyright 2000 Simon Hausmann <hausmann@kde.org
24 Copyright 1999 Michael Reiher <michael.reiher.gmx.de>
25 Copyright 1999 Boris Wedl <boris.wedl@kfunigraz.ac.at>
26 Copyright 1999 Reginald Stadlbauer <reggie@kde.org>
27
28 This library is free software; you can redistribute it and/or
29 modify it under the terms of the GNU Library General Public
30 License as published by the Free Software Foundation; either
31 version 2 of the License, or (at your option) any later version.
32
33 This library is distributed in the hope that it will be useful,
34 but WITHOUT ANY WARRANTY; without even the implied warranty of
35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 Library General Public License for more details.
37
38 You should have received a copy of the GNU Library General Public License
39 along with this library; see the file COPYING.LIB. If not, write to
40 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
41 * Boston, MA 02110-1301, USA.
42*/
43
44#include <assert.h>
45#include <float.h>
46#include <stdlib.h>
47
48#include <tqapplication.h>
49#include <tqbuffer.h>
50#include <tqclipboard.h>
51#include <tqdrawutil.h>
52#include <tqlabel.h>
53#include <tqpoint.h>
54#include <tqscrollbar.h>
55#include <tqtimer.h>
56#include <tqtooltip.h>
57#include <tqwidgetlist.h>
58
59#include <kcursor.h>
60#include <kdebug.h>
61#include <tdemessagebox.h>
62#include <tdemultipledrag.h>
63#include <krun.h>
64#include <kmimetype.h>
65#include <ksharedptr.h>
66#include <kwordwrap.h>
67
68#include <KoOasisStore.h>
69#include <KoSpeaker.h>
70#include <KoStore.h>
71#include <KoStoreDrag.h>
72#include <KoXmlWriter.h>
73#include <KoDocumentChild.h>
74#include <KoRect.h>
75
76#include "commands.h"
77#include "kspread_doc.h"
78#include "kspread_editors.h"
79#include "kspread_global.h"
80#include "kspread_locale.h"
81#include "kspread_map.h"
82#include "kspread_sheet.h"
83#include "kspread_undo.h"
84#include "kspread_util.h"
85#include "kspread_view.h"
86#include "selection.h"
87
88#include "kspread_canvas.h"
89
90// TODO Stefan: undefine/remove, if non-contiguous selections don't work
91// properly or if we are sure, that they do. ;-)
92#define NONCONTIGUOUSSELECTION
93
94#define MIN_SIZE 10
95
96using namespace KSpread;
97
98class Canvas::Private
99{
100 public:
102 KSpread::EditWidget *editWidget;
103 KSpread::CellEditor *cellEditor;
104
105 View *view;
106 TQTimer* scrollTimer;
107
108 // Non visible range left from current screen
109 // Example: If the first visible column is 'E', then xOffset stores
110 // the width of the invisible columns 'A' to 'D'.
111 double xOffset;
112
113 // Non visible range on top of the current screen
114 // Example: If the first visible row is '5', then yOffset stores
115 // the height of the invisible rows '1' to '4'.
116 double yOffset;
117
118 // Used to draw the grey grid that is usually only visible on the
119 // screen, but not by printing on paper.
120 TQPen defaultGridPen;
121
122 // see setLastEditorWithFocus, lastEditorWithFocus
123 Canvas::EditorType focusEditorType;
124
125 TQLabel *validationInfo;
126
127 // true if the user is to choose a cell.
128 bool chooseCell;
129
130 // True when the mouse button is pressed
131 bool mousePressed;
132
133 // If the user is dragging around with the mouse then this tells us what he is doing.
134 // The user may want to mark cells or he started in the lower right corner
135 // of the marker which is something special. The values for the 2 above
136 // methods are called 'Mark' and 'ResizeCell' or 'AutoFill' depending
137 // on the mouse button used. By default this variable holds
138 // the value 'NoAction'.
139 Canvas::MouseActions mouseAction;
140
141 // If we use the lower right corner of the marker to start autofilling, then this
142 // rectangle conatins all cells that were already marker when the user started
143 // to mark the rectangle which he wants to become autofilled.
144 TQRect autoFillSource;
145
146 // Start coordinates for drag and drop
147 TQPoint dragStart;
148 bool dragging;
149
150 // Used to indicate whether the user started drawing a rubber band rectangle
151 bool rubberBandStarted;
152 TQPoint rubberBandStart;
153 TQPoint rubberBandEnd;
154
155 // If the mouse is over some anchor ( in the sense of HTML anchors )
156 TQString anchor;
157
158 bool mouseSelectedObject;
159 bool drawContour;
160 ModifyType modType;
164 TQPoint m_savedMousePos;
165
166 //---- stuff needed for resizing ----
168 EmbeddedObject *m_resizeObject;
170 double m_ratio;
171 bool m_isResizing;
173 KoPoint m_origMousePos;
174
175 //---- stuff needed for moving ----
176 bool m_isMoving;
177 KoPoint m_moveStartPoint;
178
180 KoRect m_rectBeforeResize;
182 KoPoint m_moveStartPosMouse;
183
185 EmbeddedObject * m_objectDisplayAbove;
186
187 // bool mouseOverHighlightRangeSizeGrip;
188
189 // The row and column of 1) the last cell under mouse pointer, 2) the last focused cell, and
190 // the last spoken cell.
191 int prevSpokenPointerRow;
192 int prevSpokenPointerCol;
193 int prevSpokenFocusRow;
194 int prevSpokenFocusCol;
195 int prevSpokenRow;
196 int prevSpokenCol;
197};
198
199
200
201/****************************************************************
202 *
203 * Canvas
204 *
205 ****************************************************************/
206
207Canvas::Canvas (View *_view)
208 : TQWidget( _view, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase )
209{
210 d = new Private;
211
212 d->cellEditor = 0;
213 d->chooseCell = false;
214 d->validationInfo = 0L;
215
216 TQWidget::setFocusPolicy( TQWidget::StrongFocus );
217
218 d->dragStart = TQPoint( -1, -1 );
219 d->dragging = false;
220
221
222 d->defaultGridPen.setColor( lightGray );
223 d->defaultGridPen.setWidth( 1 );
224 d->defaultGridPen.setStyle( TQt::SolidLine );
225
226 d->xOffset = 0.0;
227 d->yOffset = 0.0;
228 d->view = _view;
229 // m_eAction = DefaultAction;
230 d->mouseAction = NoAction;
231 d->rubberBandStarted = false;
232 // m_bEditDirtyFlag = false;
233
234 //Now built afterwards(David)
235 //d->editWidget = d->view->editWidget();
236 d->posWidget = d->view->posWidget();
237
238 setBackgroundMode( PaletteBase );
239
240 setMouseTracking( true );
241 d->mousePressed = false;
242 d->mouseSelectedObject = false;
243 d->drawContour = false;
244 d->modType = MT_NONE;
245
246 d->m_resizeObject = 0L;
247 d->m_ratio = 0.0;
248 d->m_isMoving = false;
249 d->m_objectDisplayAbove = 0;
250 d->m_isResizing = false;
251
252 d->prevSpokenPointerRow = -1;
253 d->prevSpokenPointerCol = -1;
254 d->prevSpokenFocusRow = -1;
255 d->prevSpokenFocusCol = -1;
256 d->prevSpokenRow = -1;
257 d->prevSpokenCol = -1;
258
259 d->scrollTimer = new TQTimer( this );
260 connect (d->scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( doAutoScroll() ) );
261
262 if( d->view)
263 {
264 connect( d->view, TQ_SIGNAL( autoScroll( const TQPoint & )), this, TQ_SLOT( slotAutoScroll( const TQPoint &)));
265 }
266 if (kospeaker)
267 {
268 connect (kospeaker, TQ_SIGNAL(customSpeakWidget(TQWidget*, const TQPoint&, uint)),
269 this, TQ_SLOT(speakCell(TQWidget*, const TQPoint&, uint)));
270 }
271
272 setFocus();
273 installEventFilter( this );
274 (void)new ToolTip( this );
275 setAcceptDrops( true );
276 setInputMethodEnabled( true ); // ensure using the InputMethod
277
278 setWFlags(TQt::WNoAutoErase);
279}
280
281Canvas::~Canvas()
282{
283 delete d->scrollTimer;
284 delete d->validationInfo;
285 delete d;
286}
287
288KSpread::View* Canvas::view() const
289{
290 return d->view;
291}
292
293Doc* Canvas::doc() const
294{
295 return d->view->doc();
296}
297
298void Canvas::setEditWidget( KSpread::EditWidget * ew )
299{
300 d->editWidget = ew;
301}
302
303KSpread::EditWidget* Canvas::editWidget() const
304{
305 return d->editWidget;
306}
307
308CellEditor* Canvas::editor() const
309{
310 return d->cellEditor;
311}
312
313double Canvas::xOffset() const
314{
315 return d->xOffset;
316}
317
318double Canvas::yOffset() const
319{
320 return d->yOffset;
321}
322
323void Canvas::setXOffset( double _xOffset )
324{
325 d->xOffset = _xOffset;
326}
327
328void Canvas::setYOffset( double _yOffset )
329{
330 d->yOffset = _yOffset;
331}
332
333const TQPen& Canvas::defaultGridPen() const
334{
335 return d->defaultGridPen;
336}
337
338void Canvas::setLastEditorWithFocus( Canvas::EditorType type )
339{
340 d->focusEditorType = type;
341}
342
343Canvas::EditorType Canvas::lastEditorWithFocus() const
344{
345 return d->focusEditorType;
346}
347
348
349bool Canvas::eventFilter( TQObject *o, TQEvent *e )
350{
351 /* this canvas event filter acts on events sent to the line edit as well
352 as events to this filter itself.
353 */
354 if ( !o || !e )
355 return true;
356 switch ( e->type() )
357 {
358 case TQEvent::KeyPress:
359 {
360 TQKeyEvent * keyev = static_cast<TQKeyEvent*>(e);
361 if ((keyev->key()==Key_Tab) || (keyev->key()==Key_Backtab))
362 {
363 keyPressEvent ( keyev );
364 return true;
365 }
366 break;
367 }
368 case TQEvent::IMStart:
369 case TQEvent::IMCompose:
370 case TQEvent::IMEnd:
371 {
372 TQIMEvent * imev = static_cast<TQIMEvent *>(e);
373 processIMEvent( imev );
374 break;
375 }
376 default:
377 break;
378 }
379 return false;
380}
381
382bool Canvas::focusNextPrevChild( bool )
383{
384 return true; // Don't allow to go out of the canvas widget by pressing "Tab"
385}
386
387Selection* Canvas::selectionInfo() const
388{
389 return d->view->selectionInfo();
390}
391
392Selection* Canvas::choice() const
393{
394 return d->view->choice();
395}
396
397TQRect Canvas::selection() const
398{
399 return d->view->selectionInfo()->selection();
400}
401
402TQPoint Canvas::marker() const
403{
404 return d->view->selectionInfo()->marker();
405}
406
408{
409 return d->view->selectionInfo()->marker().x();
410}
411
413{
414 return d->view->selectionInfo()->marker().y();
415}
416
417double Canvas::zoom() const
418{
419 return d->view->zoom();
420}
421
422void Canvas::setChooseMode(bool state)
423{
424 d->chooseCell = state;
425}
426
428{
429 return d->chooseCell;
430}
431
433{
434 if ( d->chooseCell )
435 return;
436
437 choice()->clear();
438 choice()->setSheet(activeSheet());
439
440 // It is important to enable this AFTER we set the rect!
441 d->chooseCell = true;
442}
443
444void Canvas::startChoose( const TQRect& rect )
445{
446 if (d->chooseCell)
447 return;
448
449 choice()->setSheet(activeSheet());
450 choice()->initialize(rect);
451
452 // It is important to enable this AFTER we set the rect!
453 d->chooseCell = true;
454}
455
457{
458 // While entering a formula the choose mode is turned on and off.
459 // Clear the choice even if we are not in choose mode. Otherwise,
460 // cell references will stay highlighted.
461 if (!choice()->isEmpty())
462 {
463 choice()->clear();
464 update();
465 }
466
467 if ( !d->chooseCell )
468 return;
469
470 d->chooseCell = false;
471
472 Sheet *sheet = choice()->sheet();
473 if (sheet)
474 {
475 d->view->setActiveSheet(sheet);
476 }
477}
478
479HBorder* Canvas::hBorderWidget() const
480{
481 return d->view->hBorderWidget();
482}
483
484VBorder* Canvas::vBorderWidget() const
485{
486 return d->view->vBorderWidget();
487}
488
489TQScrollBar* Canvas::horzScrollBar() const
490{
491 return d->view->horzScrollBar();
492}
493
494TQScrollBar* Canvas::vertScrollBar() const
495{
496 return d->view->vertScrollBar();
497}
498
499Sheet* Canvas::findSheet( const TQString& _name ) const
500{
501 return d->view->doc()->map()->findSheet( _name );
502}
503
505{
506 return d->view->activeSheet();
507}
508
510{
511 Sheet* sheet = activeSheet();
512 if (!sheet)
513 {
514 return;
515 }
516
517 if ( selectionInfo()->isSingular() )
518 {
519 int col = selectionInfo()->marker().x();
520 int row = selectionInfo()->marker().y();
521 Cell * cell = sheet->cellAt( col,row );
522 if ( cell && cell->getValidity(0) && cell->getValidity()->displayValidationInformation)
523 {
524 TQString title = cell->getValidity(0)->titleInfo;
525 TQString message = cell->getValidity(0)->messageInfo;
526 if ( title.isEmpty() && message.isEmpty() )
527 return;
528
529 if ( !d->validationInfo )
530 d->validationInfo = new TQLabel( this );
531 kdDebug()<<" display info validation\n";
532 double u = cell->dblWidth( col );
533 double v = cell->dblHeight( row );
534 double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset();
535 double ypos = sheet->dblRowPos( markerRow() ) - yOffset();
536 // Special treatment for obscured cells.
537 if ( cell->isObscured() && cell->isPartOfMerged() )
538 {
539 cell = cell->obscuringCells().first();
540 int moveX = cell->column();
541 int moveY = cell->row();
542
543 // Use the obscuring cells dimensions
544 u = cell->dblWidth( moveX );
545 v = cell->dblHeight( moveY );
546 xpos = sheet->dblColumnPos( moveX );
547 ypos = sheet->dblRowPos( moveY );
548 }
549 //d->validationInfo->setGeometry( 3, y + 3, len + 2, hei + 2 );
550 d->validationInfo->setAlignment( TQt::AlignVCenter );
551 TQPainter painter;
552 painter.begin( this );
553 int len = 0;
554 int hei = 0;
555 TQString resultText;
556 if ( !title.isEmpty() )
557 {
558 len = painter.fontMetrics().width( title );
559 hei = painter.fontMetrics().height();
560 resultText = title + "\n";
561 }
562 if ( !message.isEmpty() )
563 {
564 int i = 0;
565 int pos = 0;
566 TQString t;
567 do
568 {
569 i = message.find( "\n", pos );
570 if ( i == -1 )
571 t = message.mid( pos, message.length() - pos );
572 else
573 {
574 t = message.mid( pos, i - pos );
575 pos = i + 1;
576 }
577 hei += painter.fontMetrics().height();
578 len = TQMAX( len, painter.fontMetrics().width( t ) );
579 }
580 while ( i != -1 );
581 resultText += message;
582 }
583 painter.end();
584 d->validationInfo->setText( resultText );
585
586 KoRect unzoomedMarker( xpos - xOffset()+u,
587 ypos - yOffset()+v,
588 len,
589 hei );
590 TQRect marker( d->view->doc()->zoomRect( unzoomedMarker ) );
591
592 d->validationInfo->setGeometry( marker );
593 d->validationInfo->show();
594 }
595 else
596 {
597 delete d->validationInfo;
598 d->validationInfo = 0L;
599 }
600 }
601 else
602 {
603 delete d->validationInfo;
604 d->validationInfo = 0L;
605 }
606}
607
608
609void Canvas::scrollToCell(TQPoint location) const
610{
611 Sheet* sheet = activeSheet();
612 if (sheet == NULL)
613 return;
614
615 if (d->view->isLoading())
616 return;
617
618 // kdDebug(36001) << "------------------------------------------------" << endl;
619 // kdDebug(36001) << "scrollToCell(): at location [" << location.x() << ","
620 // << location.y() << "]" << endl;
621
622 /* we don't need this cell ptr, but this call is necessary to update the
623 scroll bar correctly. I don't like having that as part of the cellAt function
624 but I suppose that's ok for now.
625 */
626 Cell* cell = sheet->cellAt(location.x(), location.y(), true);
627 Q_UNUSED(cell);
628
629 double unzoomedWidth = d->view->doc()->unzoomItX( width() );
630 double unzoomedHeight = d->view->doc()->unzoomItY( height() );
631
632 //kdDebug(36001) << "Unzoomed view size: [" << unzoomedWidth << ","
633 // << unzoomedHeight << "]" << endl;
634
635 // xpos is the position of the cell in the current window in unzoomed
636 // document coordinates.
637 double xpos;
638 if ( sheet->layoutDirection()==Sheet::LeftToRight )
639 xpos = sheet->dblColumnPos( location.x() ) - xOffset();
640 else
641 xpos = unzoomedWidth - sheet->dblColumnPos( location.x() ) + xOffset();
642 double ypos = sheet->dblRowPos( location.y() ) - yOffset();
643
644 //kdDebug(36001) << "Position: [" << xpos << "," << ypos << "]" << endl;
645
646 double minY = 40.0;
647 double maxY = unzoomedHeight - 40.0;
648 //kdDebug(36001) << "Canvas::scrollToCell : height=" << height() << endl;
649 //kdDebug(36001) << "Canvas::scrollToCell : width=" << width() << endl;
650
651 if ( sheet->layoutDirection()==Sheet::RightToLeft ) {
652 // Right to left sheet.
653
654 double minX = unzoomedWidth - 100.0; // less than that, we scroll
655 double maxX = 100.0; // more than that, we scroll
656
657 // kdDebug() << "rtl2: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << ", Offset: " << xOffset() << endl;
658
659 // Do we need to scroll left?
660 if ( xpos > minX )
661 horzScrollBar()->setValue( horzScrollBar()->maxValue() -
662 d->view->doc()->zoomItX( xOffset() - xpos + minX ) );
663
664 // Do we need to scroll right?
665 else if ( xpos < maxX )
666 {
667 double horzScrollBarValue = xOffset() - xpos + maxX;
668 double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth;
669
670 //We don't want to display any area > KS_colMax widths
671 if ( horzScrollBarValue > horzScrollBarValueMax )
672 horzScrollBarValue = horzScrollBarValueMax;
673
674 horzScrollBar()->setValue( horzScrollBar()->maxValue() -
675 d->view->doc()->zoomItX( horzScrollBarValue ) );
676 }
677 }
678 else {
679 // Left to right sheet.
680
681 double minX = 100.0; // less than that, we scroll
682 double maxX = unzoomedWidth - 100.0; // more than that, we scroll
683
684 // kdDebug() << "ltr: XPos: " << xpos << ", min: " << minX << ", maxX: " << maxX << endl;
685
686 // Do we need to scroll left?
687 if ( xpos < minX )
688 horzScrollBar()->setValue( d->view->doc()->zoomItX( xOffset() + xpos - minX ) );
689
690 // Do we need to scroll right?
691 else if ( xpos > maxX )
692 {
693 double horzScrollBarValue = xOffset() + xpos - maxX;
694 double horzScrollBarValueMax = sheet->sizeMaxX() - unzoomedWidth;
695
696 //We don't want to display any area > KS_colMax widths
697 if ( horzScrollBarValue > horzScrollBarValueMax )
698 horzScrollBarValue = horzScrollBarValueMax;
699
700 horzScrollBar()->setValue( d->view->doc()->zoomItX( horzScrollBarValue ) );
701 }
702 }
703// kdDebug() << "ltr: YPos: " << ypos << ", min: " << minY << ", maxY: " << maxY << endl;
704
705 // do we need to scroll up
706 if ( ypos < minY )
707 vertScrollBar()->setValue( d->view->doc()->zoomItY( yOffset() + ypos - minY ) );
708
709 // do we need to scroll down
710 else if ( ypos > maxY )
711 {
712 double vertScrollBarValue = yOffset() + ypos - maxY;
713 double vertScrollBarValueMax = sheet->sizeMaxY() - unzoomedHeight;
714
715 //We don't want to display any area > KS_rowMax heights
716 if ( vertScrollBarValue > vertScrollBarValueMax )
717 vertScrollBarValue = vertScrollBarValueMax;
718
719 vertScrollBar()->setValue( d->view->doc()->zoomItY( vertScrollBarValue ) );
720 }
721}
722
723void Canvas::slotScrollHorz( int _value )
724{
725 Sheet * sheet = activeSheet();
726
727 if ( sheet == 0L )
728 return;
729
730 kdDebug(36001) << "slotScrollHorz: value = " << _value << endl;
731 //kdDebug(36001) << kdBacktrace() << endl;
732
733 if ( sheet->layoutDirection()==Sheet::RightToLeft )
734 _value = horzScrollBar()->maxValue() - _value;
735
736 double unzoomedValue = d->view->doc()->unzoomItX( _value );
737 double dwidth = d->view->doc()->unzoomItX( width() );
738
739 d->view->doc()->emitBeginOperation(false);
740
741 if ( unzoomedValue < 0.0 ) {
742 kdDebug (36001)
743 << "Canvas::slotScrollHorz: value out of range (unzoomedValue: "
744 << unzoomedValue << ")" << endl;
745 unzoomedValue = 0.0;
746 }
747
748 double xpos = sheet->dblColumnPos( TQMIN( KS_colMax, d->view->activeSheet()->maxColumn()+10 ) ) - d->xOffset;
749 if ( unzoomedValue > ( xpos + d->xOffset ) )
750 unzoomedValue = xpos + d->xOffset;
751
752 sheet->enableScrollBarUpdates( false );
753
754 // Relative movement
755 int dx = d->view->doc()->zoomItX( d->xOffset - unzoomedValue );
756
757
758 /* what cells will need painted now? */
759 TQRect area = visibleCells();
760 double tmp;
761 if (dx > 0)
762 {
763 area.setRight( area.left() );
764 area.setLeft( sheet->leftColumn( unzoomedValue, tmp ) );
765 }
766 else
767 {
768 area.setLeft( area.right() );
769 area.setRight( sheet->rightColumn( dwidth + unzoomedValue ) );
770 }
771
772 sheet->setRegionPaintDirty(area);
773
774 // New absolute position
775 kdDebug(36001) << "slotScrollHorz(): XOffset before setting: "
776 << d->xOffset << endl;
777 d->xOffset = unzoomedValue;
778 kdDebug(36001) << "slotScrollHorz(): XOffset after setting: "
779 << d->xOffset << endl;
780
781 if ( sheet->layoutDirection()==Sheet::RightToLeft )
782 dx = -dx;
783
784 scroll( dx, 0 );
785
786 hBorderWidget()->scroll( dx, 0 );
787
788 sheet->enableScrollBarUpdates( true );
789
790 d->view->doc()->emitEndOperation( sheet->visibleRect( this ) );
791}
792
793void Canvas::slotScrollVert( int _value )
794{
795 if ( activeSheet() == 0L )
796 return;
797
798 d->view->doc()->emitBeginOperation(false);
799 double unzoomedValue = d->view->doc()->unzoomItY( _value );
800
801 if ( unzoomedValue < 0 )
802 {
803 unzoomedValue = 0;
804 kdDebug (36001) << "Canvas::slotScrollVert: value out of range (unzoomedValue: " <<
805 unzoomedValue << ")" << endl;
806 }
807
808 double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, d->view->activeSheet()->maxRow()+10 ) );
809 if ( unzoomedValue > ypos )
810 unzoomedValue = ypos;
811
812 activeSheet()->enableScrollBarUpdates( false );
813
814 // Relative movement
815 int dy = d->view->doc()->zoomItY( d->yOffset - unzoomedValue );
816
817
818 /* what cells will need painted now? */
819 TQRect area = visibleCells();
820 double tmp;
821 if (dy > 0)
822 {
823 area.setBottom(area.top());
824 area.setTop(activeSheet()->topRow(unzoomedValue, tmp));
825 }
826 else
827 {
828 area.setTop(area.bottom());
829 area.setBottom(activeSheet()->bottomRow(d->view->doc()->unzoomItY(height()) +
830 unzoomedValue));
831 }
832
833 activeSheet()->setRegionPaintDirty( area );
834
835 // New absolute position
836 d->yOffset = unzoomedValue;
837 scroll( 0, dy );
838 vBorderWidget()->scroll( 0, dy );
839
840 activeSheet()->enableScrollBarUpdates( true );
841
842 d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) );
843}
844
845void Canvas::slotMaxColumn( int _max_column )
846{
847 int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value();
848 double xpos = activeSheet()->dblColumnPos( TQMIN( KS_colMax, _max_column + 10 ) ) - xOffset();
849 double unzoomWidth = d->view->doc()->unzoomItX( width() );
850
851 //Don't go beyond the maximum column range (KS_colMax)
852 double sizeMaxX = activeSheet()->sizeMaxX();
853 if ( xpos > sizeMaxX - xOffset() - unzoomWidth )
854 xpos = sizeMaxX - xOffset() - unzoomWidth;
855
856 horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( xpos + xOffset() ) );
857
858 if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
859 horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue );
860}
861
862void Canvas::slotMaxRow( int _max_row )
863{
864 double ypos = activeSheet()->dblRowPos( TQMIN( KS_rowMax, _max_row + 10 ) ) - yOffset();
865 double unzoomHeight = d->view->doc()->unzoomItY( height() );
866
867 //Don't go beyond the maximum row range (KS_rowMax)
868 double sizeMaxY = activeSheet()->sizeMaxY();
869 if ( ypos > sizeMaxY - yOffset() - unzoomHeight )
870 ypos = sizeMaxY - yOffset() - unzoomHeight;
871
872 vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( ypos + yOffset() ) );
873}
874
875void Canvas::mouseMoveEvent( TQMouseEvent * _ev )
876{
877 // Dont allow modifications if document is readonly. Selecting is no modification
878 if ( (!d->view->koDocument()->isReadWrite()) && (d->mouseAction!=Mark))
879 return;
880
881 if ( d->mousePressed && d->modType != MT_NONE )
882 {
883 KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) );
884 docPoint += KoPoint( xOffset(), yOffset() );
885
886 if ( d->modType == MT_MOVE )
887 {
888 if ( !d->m_isMoving )
889 {
890 d->m_moveStartPoint = objectRect( false ).topLeft();
891 d->m_isMoving = true;
892 }
893 moveObjectsByMouse( docPoint, _ev->state() & AltButton || _ev->state() & ControlButton );
894 }
895 else if ( d->m_resizeObject )
896 {
897 if ( !d->m_isResizing )
898 d->m_isResizing = true;
899
900 bool keepRatio = d->m_resizeObject->isKeepRatio();
901 if ( _ev->state() & AltButton )
902 {
903 keepRatio = true;
904 }
905 docPoint = KoPoint( doc()->unzoomPoint( _ev->pos() ) );
906 resizeObject( d->modType, docPoint, keepRatio );
907 }
908 return;
909 }
910
911
912 /*if ( d->mousePressed && d->m_resizeObject && d->modType != MT_NONE )
913 {
914 if ( !d->m_isMoving )
915 {
916 d->m_isMoving = true;
917 update();
918 }
919 else
920 update( d->m_boundingRealRect );
921
922
923 TQRect drawingRect;
924
925 if ( d->modType == MT_MOVE )
926 {
927 drawingRect = TQRect( _ev->pos() - d->m_origPos, d->m_origSize );
928 d->m_boundingRealRect = drawingRect;
929 }
930 else
931 {
932 drawingRect = doc()->zoomRect( calculateNewGeometry(d->modType, _ev->pos().x(), _ev->pos().y() ) );
933 drawingRect.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ) , (int)( -yOffset() * doc()->zoomedResolutionY() ) );
934 }
935
936 // Autoscrolling
937 if ( ( d->modType == MT_MOVE && drawingRect.top() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().y() < 0 ) )
938 {
939 vertScrollBar()->setValue ((int) ( vertScrollBar()->value() -
940 autoScrollAccelerationY( - drawingRect.top() ) ) );
941 }
942 else if ( ( d->modType == MT_MOVE && drawingRect.bottom() > height() ) || ( d->modType != MT_MOVE && _ev->pos().y() > height() ) )
943 {
944 vertScrollBar()->setValue ((int) ( vertScrollBar()->value() +
945 autoScrollAccelerationY ( drawingRect.bottom() - height() ) ) );
946 }
947 if ( ( d->modType == MT_MOVE && drawingRect.left() < 0 ) || ( d->modType != MT_MOVE && _ev->pos().x() < 0 ) )
948 {
949 horzScrollBar()->setValue ((int) ( horzScrollBar()->value() -
950 autoScrollAccelerationX( - drawingRect.left() ) ) );
951 }
952 else if ( ( d->modType == MT_MOVE && drawingRect.right() > width() ) || ( d->modType != MT_MOVE && _ev->pos().x() > width() ) )
953 {
954 horzScrollBar()->setValue ((int) (horzScrollBar()->value() +
955 autoScrollAccelerationX( drawingRect.right() - width() ) ) );
956 }
957
958 if ( drawingRect.left() < 0 )
959 {
960 drawingRect.setRight( drawingRect.right() -drawingRect.left() );
961 drawingRect.setLeft( 0 );
962 }
963 if ( drawingRect.top() < 0 )
964 {
965 drawingRect.setBottom( drawingRect.bottom() -drawingRect.top() );
966 drawingRect.setTop( 0 );
967 }
968
969 d->m_boundingRealRect = drawingRect; //redraw this area next time the mouse has been moved
970
971 //update( d->m_boundingRealRect );
972 TQPainter p(this);
973 p.setRasterOp( NotROP );
974 p.setPen( TQPen( black, 0, DotLine ) );
975 p.drawRect( drawingRect );
976 p.end();
977 return;
978}*/
979
980 if ( d->dragging )
981 {
982 return;
983 }
984 if ( d->dragStart.x() != -1 )
985 {
986 TQPoint p ( (int) _ev->pos().x() + (int) xOffset(),
987 (int) _ev->pos().y() + (int) yOffset() );
988
989 if ( ( d->dragStart - p ).manhattanLength() > 4 )
990 {
991 d->dragging = true;
992 startTheDrag();
993 d->dragStart.setX( -1 );
994 }
995 d->dragging = false;
996 return;
997 }
998
999 // Get info about where the event occurred - this is duplicated
1000 // in ::mousePressEvent, needs to be separated into one function
1001 Sheet *sheet = activeSheet();
1002 if ( !sheet )
1003 {
1004 return;
1005 }
1006
1007 if ( d->mouseSelectedObject )
1008 {
1009 EmbeddedObject *obj = 0;
1010 TQPoint p ( (int) _ev->x(),
1011 (int) _ev->y() );
1012 if ( ( obj = getObject( p, activeSheet() ) ) && obj->isSelected() )
1013 {
1014 KoRect const bound = obj->geometry();
1015 TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(),
1016 bound.width(),
1017 bound.height() ) );
1018 zoomedBound.moveBy( (int)(-xOffset() * doc()->zoomedResolutionX() ), (int)(-yOffset() * doc()->zoomedResolutionY() ));
1019 setCursor( obj->getCursor( p, d->modType, zoomedBound ) );
1020 return;
1021 }
1022 }
1023
1024 double dwidth = d->view->doc()->unzoomItX( width() );
1025 double ev_PosX;
1026 if ( sheet->layoutDirection()==Sheet::RightToLeft )
1027 {
1028 ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1029 }
1030 else
1031 {
1032 ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1033 }
1034 double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
1035
1036 // In which cell did the user click ?
1037 double xpos;
1038 double ypos;
1039 int col = sheet->leftColumn( ev_PosX, xpos );
1040 int row = sheet->topRow( ev_PosY, ypos );
1041
1042 // you cannot move marker when col > KS_colMax or row > KS_rowMax
1043 if ( col > KS_colMax || row > KS_rowMax )
1044 {
1045 kdDebug(36001) << "Canvas::mouseMoveEvent: col or row is out of range: "
1046 << "col: " << col << " row: " << row << endl;
1047 return;
1048 }
1049
1050
1051 //*** Highlighted Range Resize Handling ***
1052 if (d->mouseAction == ResizeSelection)
1053 {
1054 choice()->update(TQPoint(col,row));
1055 return;
1056 }
1057
1058 //Check to see if the mouse is over a highlight range size grip and if it is, change the cursor
1059 //shape to a resize arrow
1060 if (highlightRangeSizeGripAt(ev_PosX,ev_PosY))
1061 {
1062 if ( sheet->layoutDirection()==Sheet::RightToLeft )
1063 setCursor( sizeBDiagCursor );
1064 else
1065 setCursor( sizeFDiagCursor );
1066 return;
1067 }
1068
1069 TQRect rct( (d->chooseCell ? choice() : selectionInfo())->lastRange() );
1070
1071 TQRect r1;
1072 TQRect r2;
1073
1074 double lx = sheet->dblColumnPos( rct.left() );
1075 double rx = sheet->dblColumnPos( rct.right() + 1 );
1076 double ty = sheet->dblRowPos( rct.top() );
1077 double by = sheet->dblRowPos( rct.bottom() + 1 );
1078
1079 r1.setLeft( (int) (lx - 1) );
1080 r1.setTop( (int) (ty - 1) );
1081 r1.setRight( (int) (rx + 1) );
1082 r1.setBottom( (int) (by + 1) );
1083
1084 r2.setLeft( (int) (lx + 1) );
1085 r2.setTop( (int) (ty + 1) );
1086 r2.setRight( (int) (rx - 1) );
1087 r2.setBottom( (int) (by - 1) );
1088
1089 // Test whether the mouse is over some anchor
1090 {
1091 Cell *cell = sheet->visibleCellAt( col, row );
1092 TQString anchor;
1093 if ( sheet->layoutDirection()==Sheet::RightToLeft )
1094 {
1095 anchor = cell->testAnchor( d->view->doc()->zoomItX( cell->dblWidth() - ev_PosX + xpos ),
1096 d->view->doc()->zoomItY( ev_PosY - ypos ) );
1097 }
1098 else
1099 {
1100 anchor = cell->testAnchor( d->view->doc()->zoomItX( ev_PosX - xpos ),
1101 d->view->doc()->zoomItY( ev_PosY - ypos ) );
1102 }
1103 if ( !anchor.isEmpty() && anchor != d->anchor )
1104 {
1105 setCursor( KCursor::handCursor() );
1106 }
1107
1108 d->anchor = anchor;
1109 }
1110
1111 // Test wether mouse is over the selection handle
1112 TQRect selectionHandle = d->view->selectionInfo()->selectionHandleArea();
1113 if ( selectionHandle.contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ),
1114 d->view->doc()->zoomItY( ev_PosY ) ) ) )
1115 {
1116 //If the cursor is over the handle, than it might be already on the next cell.
1117 //Recalculate the cell!
1118 col = sheet->leftColumn( ev_PosX - d->view->doc()->unzoomItX( 2 ), xpos );
1119 row = sheet->topRow( ev_PosY - d->view->doc()->unzoomItY( 2 ), ypos );
1120
1121 if ( !sheet->isProtected() )
1122 {
1123 if ( sheet->layoutDirection()==Sheet::RightToLeft )
1124 setCursor( sizeBDiagCursor );
1125 else
1126 setCursor( sizeFDiagCursor );
1127 }
1128 }
1129 else if ( !d->anchor.isEmpty() )
1130 {
1131 if ( !sheet->isProtected() )
1132 setCursor( KCursor::handCursor() );
1133 }
1134 else if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) )
1135 && !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) )
1136 {
1137 setCursor( KCursor::handCursor() );
1138 }
1139 else if ( d->chooseCell )
1140 {
1141 //Visual cue to indicate that the user can drag-select the choice selection
1142 setCursor( KCursor::crossCursor() );
1143 }
1144 else
1145 {
1146 //Nothing special is happening, use a normal arrow cursor
1147 setCursor( arrowCursor );
1148 }
1149
1150 // No marking, selecting etc. in progess? Then quit here.
1151 if ( d->mouseAction == NoAction )
1152 return;
1153
1154 // Set the new extent of the selection
1155 (d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row));
1156}
1157
1158void Canvas::mouseReleaseEvent( TQMouseEvent* /*_ev*/)
1159{
1160 if ( d->scrollTimer->isActive() )
1161 d->scrollTimer->stop();
1162
1163 d->mousePressed = false;
1164 d->view->disableAutoScroll();
1165
1166 if ( d->modType != MT_NONE /*&& d->m_resizeObject && d->m_resizeObject->isSelected() */)
1167 {
1168 switch ( d->modType )
1169 {
1170 case MT_MOVE:
1171 {
1172 KoPoint move( objectRect( false ).topLeft() - d->m_moveStartPosMouse );
1173 if ( move != KoPoint( 0, 0 ) )
1174 {
1175 KCommand *cmd= activeSheet()->moveObject( view(), move.x(), move.y() );
1176 if(cmd)
1177 doc()->addCommand( cmd );
1178 } else
1179 {
1180 repaint();
1181 }
1182 d->m_isMoving = false;
1183 break;
1184 }
1185 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:
1186 finishResizeObject( i18n("Resize Object") );
1187 break;
1188 case MT_RESIZE_DN:
1189 finishResizeObject( i18n("Resize Object"), false );
1190 break;
1191 default:
1192 break;
1193 }
1194 return;
1195 }
1196
1197 Sheet *sheet = activeSheet();
1198 if ( !sheet )
1199 return;
1200
1201 Selection* selectionInfo = d->view->selectionInfo();
1202 TQRect s( selectionInfo->lastRange() );
1203
1204 // The user started the drag in the lower right corner of the marker ?
1205 if ( d->mouseAction == ResizeCell && !sheet->isProtected() )
1206 {
1207 sheet->mergeCells(selectionInfo->lastRange());
1208 d->view->updateEditWidget();
1209 }
1210 else if ( d->mouseAction == AutoFill && !sheet->isProtected() )
1211 {
1212 TQRect dest = s;
1213 sheet->autofill( d->autoFillSource, dest );
1214
1215 d->view->updateEditWidget();
1216 }
1217 // The user started the drag in the middle of a cell ?
1218 else if ( d->mouseAction == Mark && !d->chooseCell )
1219 {
1220 d->view->updateEditWidget();
1221 }
1222
1223 d->mouseAction = NoAction;
1224 d->dragging = false;
1225 d->dragStart.setX( -1 );
1226}
1227
1228void Canvas::processClickSelectionHandle( TQMouseEvent *event )
1229{
1230 // Auto fill ? That is done using the left mouse button.
1231 if ( event->button() == TQt::LeftButton )
1232 {
1233 d->mouseAction = AutoFill;
1234 d->autoFillSource = selectionInfo()->lastRange();
1235 }
1236 // Resize a cell (done with the right mouse button) ?
1237 // But for that to work there must not be a selection.
1238 else if ( event->button() == TQt::MidButton && selectionInfo()->isSingular())
1239 {
1240 d->mouseAction = ResizeCell;
1241 }
1242
1243 return;
1244}
1245
1246void Canvas::processLeftClickAnchor()
1247{
1248 bool isRefLink = localReferenceAnchor( d->anchor );
1249 bool isLocalLink = (d->anchor.find("file:") == 0);
1250 if ( !isRefLink )
1251 {
1252 TQString type=KMimeType::findByURL(d->anchor, 0, isLocalLink)->name();
1253
1254 if ( KRun::isExecutableFile( d->anchor , type ) )
1255 {
1256 //TQString question = i18n("Do you want to open this link to '%1'?\n").arg(d->anchor);
1257
1258 //question += i18n("Note that opening a link to a local file may "
1259 // "compromise your system's security.");
1260
1261 TQString question = i18n("This link points to the program or script '%1'.\n"
1262 "Malicious programs can harm your computer. Are you sure that you want to run this program?").arg(d->anchor);
1263 // this will also start local programs, so adding a "don't warn again"
1264 // checkbox will probably be too dangerous
1265 int choice = KMessageBox::warningYesNo(this, question, i18n("Open Link?"));
1266 if ( choice != KMessageBox::Yes )
1267 {
1268 return;
1269 //(void) new KRun( d->anchor );
1270 }
1271 }
1272
1273 new KRun(d->anchor);
1274 }
1275 else
1276 {
1277 selectionInfo()->initialize(Region(d->view, d->anchor));
1278 }
1279}
1280
1281bool Canvas::highlightRangeSizeGripAt(double x, double y)
1282{
1283 if (!d->chooseCell)
1284 return 0;
1285
1286 Region::ConstIterator end = choice()->constEnd();
1287 for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it)
1288 {
1289 // TODO Stefan: adapt to Selection::selectionHandleArea
1290 KoRect visibleRect;
1291 sheetAreaToRect((*it)->rect().normalize(), visibleRect);
1292
1293 TQPoint bottomRight((int) visibleRect.right(), (int) visibleRect.bottom());
1294 TQRect handle( ( (int) bottomRight.x() - 6 ),
1295 ( (int) bottomRight.y() - 6 ),
1296 ( 6 ),
1297 ( 6 ) );
1298
1299 if (handle.contains(TQPoint((int) x,(int) y)))
1300 {
1301 return true;
1302 }
1303 }
1304
1305 return false;
1306}
1307
1308void Canvas::mousePressEvent( TQMouseEvent * _ev )
1309{
1310 if ( _ev->button() == TQt::LeftButton )
1311 {
1312 d->mousePressed = true;
1313 d->view->enableAutoScroll();
1314 }
1315
1316 if ( activeSheet() && _ev->button() == TQt::LeftButton)
1317 {
1318 d->m_moveStartPosMouse = objectRect( false ).topLeft();
1319 EmbeddedObject *obj = getObject( _ev->pos(), activeSheet() );
1320
1321 if ( obj )
1322 {
1323 // use ctrl + Button to select / deselect object
1324 if ( _ev->state() & ControlButton && obj->isSelected() )
1325 deselectObject( obj );
1326 else if ( _ev->state() & ControlButton )
1327 {
1328 if ( d->modType == MT_NONE)
1329 return;
1330
1331 selectObject( obj );
1332 raiseObject( obj );
1333 d->m_moveStartPosMouse = objectRect( false ).topLeft();
1334 }
1335 else
1336 {
1337 if ( d->modType != MT_MOVE || !obj->isSelected() )
1338 deselectAllObjects();
1339
1340 selectObject( obj );
1341
1342 raiseObject( obj );
1343 d->m_moveStartPosMouse = objectRect( false ).topLeft();
1344 }
1345
1346 // start resizing
1347 if ( d->modType != MT_MOVE && d->modType != MT_NONE && !obj->isProtect() )
1348 {
1349 deselectAllObjects();
1350 selectObject( obj );
1351 raiseObject( obj );
1352
1353 d->m_resizeObject = obj;
1354
1355 d->m_ratio = static_cast<double>( obj->geometry().width() ) /
1356 static_cast<double>( obj->geometry().height() );
1357 d->m_rectBeforeResize = obj->geometry();
1358 }
1359
1360 KoPoint docPoint ( doc()->unzoomPoint( _ev->pos() ) );
1361 docPoint += KoPoint( xOffset(), yOffset() );
1362 d->m_origMousePos = docPoint;
1363 d->m_moveStartPosMouse = objectRect( false ).topLeft();
1364 return;
1365 }
1366 else
1367 {
1368 d->modType = MT_NONE;
1369 if ( !( _ev->state() & ShiftButton ) && !( _ev->state() & ControlButton ) )
1370 deselectAllObjects();
1371 }
1372 }
1373
1374 // Get info about where the event occurred - this is duplicated
1375 // in ::mouseMoveEvent, needs to be separated into one function
1376 Sheet *sheet = activeSheet();
1377 if ( !sheet )
1378 {
1379 return;
1380 }
1381
1382 double dwidth = d->view->doc()->unzoomItX( width() );
1383 double ev_PosX;
1384 if ( sheet->layoutDirection()==Sheet::RightToLeft )
1385 {
1386 ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1387 }
1388 else
1389 {
1390 ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1391 }
1392 double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
1393
1394 // In which cell did the user click ?
1395 double xpos;
1396 double ypos;
1397 int col = sheet->leftColumn( ev_PosX, xpos );
1398 int row = sheet->topRow( ev_PosY, ypos );
1399 // you cannot move marker when col > KS_colMax or row > KS_rowMax
1400 if ( col > KS_colMax || row > KS_rowMax )
1401 {
1402 kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: "
1403 << "col: " << col << " row: " << row << endl;
1404 return;
1405 }
1406
1407 // you cannot move marker when col > KS_colMax or row > KS_rowMax
1408 if ( col > KS_colMax || row > KS_rowMax )
1409 {
1410 kdDebug(36001) << "Canvas::mousePressEvent: col or row is out of range: "
1411 << "col: " << col << " row: " << row << endl;
1412 return;
1413 }
1414
1415 if (d->chooseCell && highlightRangeSizeGripAt(ev_PosX,ev_PosY))
1416 {
1417 choice()->setActiveElement(TQPoint(col,row));
1418 d->mouseAction = ResizeSelection;
1419 return;
1420 }
1421
1422 // We were editing a cell -> save value and get out of editing mode
1423 if ( d->cellEditor && !d->chooseCell )
1424 {
1425 deleteEditor( true ); // save changes
1426 }
1427
1428 d->scrollTimer->start( 50 );
1429
1430 // Did we click in the lower right corner of the marker/marked-area ?
1431 if ( selectionInfo()->selectionHandleArea().contains( TQPoint( d->view->doc()->zoomItX( ev_PosX ),
1432 d->view->doc()->zoomItY( ev_PosY ) ) ) )
1433 {
1434 processClickSelectionHandle( _ev );
1435 return;
1436 }
1437
1438
1439 // TODO Stefan: adapt to non-cont. selection
1440 {
1441 // start drag ?
1442 TQRect rct( selectionInfo()->lastRange() );
1443
1444 TQRect r1;
1445 TQRect r2;
1446 {
1447 double lx = sheet->dblColumnPos( rct.left() );
1448 double rx = sheet->dblColumnPos( rct.right() + 1 );
1449 double ty = sheet->dblRowPos( rct.top() );
1450 double by = sheet->dblRowPos( rct.bottom() + 1 );
1451
1452 r1.setLeft( (int) (lx - 1) );
1453 r1.setTop( (int) (ty - 1) );
1454 r1.setRight( (int) (rx + 1) );
1455 r1.setBottom( (int) (by + 1) );
1456
1457 r2.setLeft( (int) (lx + 1) );
1458 r2.setTop( (int) (ty + 1) );
1459 r2.setRight( (int) (rx - 1) );
1460 r2.setBottom( (int) (by - 1) );
1461 }
1462
1463 d->dragStart.setX( -1 );
1464
1465 if ( r1.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) )
1466 && !r2.contains( TQPoint( (int) ev_PosX, (int) ev_PosY ) ) )
1467 {
1468 d->dragStart.setX( (int) ev_PosX );
1469 d->dragStart.setY( (int) ev_PosY );
1470
1471 return;
1472 }
1473 }
1474
1475 // kdDebug() << "Clicked in cell " << col << ", " << row << endl;
1476
1477 // Extending an existing selection with the shift button ?
1478 if ((_ev->state() & ShiftButton) &&
1479 d->view->koDocument()->isReadWrite() &&
1480 !selectionInfo()->isColumnOrRowSelected())
1481 {
1482 (d->chooseCell ? choice() : selectionInfo())->update(TQPoint(col,row));
1483 return;
1484 }
1485
1486
1487 // Go to the upper left corner of the obscuring object if cells are merged
1488 Cell *cell = sheet->cellAt( col, row );
1489 if (cell->isPartOfMerged())
1490 {
1491 cell = cell->obscuringCells().first();
1492 col = cell->column();
1493 row = cell->row();
1494 }
1495
1496 switch (_ev->button())
1497 {
1498 case TQt::LeftButton:
1499 if (!d->anchor.isEmpty())
1500 {
1501 // Hyperlink pressed
1502 processLeftClickAnchor();
1503 }
1504#ifdef NONCONTIGUOUSSELECTION
1505 else if ( _ev->state() & ControlButton )
1506 {
1507 if (d->chooseCell)
1508 {
1509#if 0 // TODO Stefan: remove for NCS of choices
1510 // Start a marking action
1511 d->mouseAction = Mark;
1512 // extend the existing selection
1513 choice()->extend(TQPoint(col,row), activeSheet());
1514#endif
1515 }
1516 else
1517 {
1518 // Start a marking action
1519 d->mouseAction = Mark;
1520 // extend the existing selection
1521 selectionInfo()->extend(TQPoint(col,row), activeSheet());
1522 }
1523// TODO Stefan: simplification, if NCS of choices is working
1524/* (d->chooseCell ? choice() : selectionInfo())->extend(TQPoint(col,row), activeSheet());*/
1525 }
1526#endif
1527 else
1528 {
1529 // Start a marking action
1530 d->mouseAction = Mark;
1531 // reinitialize the selection
1532 (d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet());
1533 }
1534 break;
1535 case TQt::MidButton:
1536 // Paste operation with the middle button?
1537 if ( d->view->koDocument()->isReadWrite() && !sheet->isProtected() )
1538 {
1539 (d->chooseCell ? choice() : selectionInfo())->initialize( TQPoint( col, row ), activeSheet() );
1540 sheet->paste(selectionInfo()->lastRange(), true, Paste::Normal,
1541 Paste::OverWrite, false, 0, false, TQClipboard::Selection);
1542 sheet->setRegionPaintDirty(*selectionInfo());
1543 }
1544 break;
1545 case TQt::RightButton:
1546 if (!selectionInfo()->contains( TQPoint( col, row ) ))
1547 {
1548 // No selection or the mouse press was outside of an existing selection?
1549 (d->chooseCell ? choice() : selectionInfo())->initialize(TQPoint(col,row), activeSheet());
1550 }
1551 break;
1552 default:
1553 break;
1554 }
1555
1557 if ( !d->chooseCell )
1558 {
1559 d->view->updateEditWidgetOnPress();
1560 }
1562
1563 // Context menu?
1564 if ( _ev->button() == TQt::RightButton )
1565 {
1566 // TODO: Handle anchor // TODO Stefan: ???
1567 TQPoint p = mapToGlobal( _ev->pos() );
1568 d->view->openPopupMenu( p );
1569 }
1570}
1571
1572void Canvas::startTheDrag()
1573{
1574 Sheet * sheet = activeSheet();
1575 if ( !sheet )
1576 return;
1577
1578 // right area for start dragging
1579 TextDrag * d = new TextDrag( this );
1580 setCursor( KCursor::handCursor() );
1581
1582 TQDomDocument doc = sheet->saveCellRegion(*selectionInfo());
1583
1584 // Save to buffer
1585 TQBuffer buffer;
1586 buffer.open( IO_WriteOnly );
1587 TQTextStream str( &buffer );
1588 str.setEncoding( TQTextStream::UnicodeUTF8 );
1589 str << doc;
1590 buffer.close();
1591
1592 d->setPlain( sheet->copyAsText( selectionInfo() ) );
1593 d->setKSpread( buffer.buffer() );
1594
1595 d->dragCopy();
1596 setCursor( KCursor::arrowCursor() );
1597}
1598
1599void Canvas::mouseDoubleClickEvent( TQMouseEvent* _ev)
1600{
1601
1602 EmbeddedObject *obj;
1603 if ( ( obj = getObject( _ev->pos(), activeSheet() ) ) )
1604 {
1605 switch ( obj->getType() )
1606 {
1607 case OBJECT_KOFFICE_PART: case OBJECT_CHART:
1608 {
1609 dynamic_cast<EmbeddedKOfficeObject*>(obj)->activate( view(), this );
1610 return;
1611 break;
1612 }
1613 default:
1614 {
1615 view()->extraProperties();
1616 return;
1617 break;
1618 }
1619 }
1620 }
1621
1622 if ( d->view->koDocument()->isReadWrite() && activeSheet() )
1623 createEditor(true);
1624}
1625
1626void Canvas::wheelEvent( TQWheelEvent* _ev )
1627{
1628 if ( _ev->orientation() == TQt::Vertical )
1629 {
1630 if ( vertScrollBar() )
1631 TQApplication::sendEvent( vertScrollBar(), _ev );
1632 }
1633 else if ( horzScrollBar() )
1634 {
1635 TQApplication::sendEvent( horzScrollBar(), _ev );
1636 }
1637}
1638
1639void Canvas::paintEvent( TQPaintEvent* _ev )
1640{
1641 if ( d->view->doc()->isLoading() )
1642 return;
1643
1644 Sheet* sheet = activeSheet();
1645 if ( !sheet )
1646 return;
1647
1648 // ElapsedTime et( "Canvas::paintEvent" );
1649
1650 double dwidth = d->view->doc()->unzoomItX( width() );
1651 KoRect rect = d->view->doc()->unzoomRect( _ev->rect() & TQWidget::rect() );
1652 if ( sheet->layoutDirection()==Sheet::RightToLeft )
1653 rect.moveBy( -xOffset(), yOffset() );
1654 else
1655 rect.moveBy( xOffset(), yOffset() );
1656
1657 KoPoint tl = rect.topLeft();
1658 KoPoint br = rect.bottomRight();
1659
1660 double tmp;
1661 int left_col;
1662 int right_col;
1663 //Philipp: I don't know why we need the +1, but otherwise we don't get it correctly
1664 //Testcase: Move a dialog slowly up left. Sometimes the top/left most points are not painted
1665 if ( sheet->layoutDirection()==Sheet::RightToLeft )
1666 {
1667 right_col = sheet->leftColumn( dwidth - tl.x(), tmp );
1668 left_col = sheet->rightColumn( dwidth - br.x() + 1.0 );
1669 }
1670 else
1671 {
1672 left_col = sheet->leftColumn( tl.x(), tmp );
1673 right_col = sheet->rightColumn( br.x() + 1.0 );
1674 }
1675 int top_row = sheet->topRow( tl.y(), tmp );
1676 int bottom_row = sheet->bottomRow( br.y() + 1.0 );
1677
1678 TQRect vr( TQPoint(left_col, top_row),
1679 TQPoint(right_col, bottom_row) );
1680 d->view->doc()->emitBeginOperation( false );
1681 sheet->setRegionPaintDirty( vr );
1682 d->view->doc()->emitEndOperation( vr );
1683}
1684
1685void Canvas::focusInEvent( TQFocusEvent* )
1686{
1687 if ( !d->cellEditor )
1688 return;
1689
1690 //kdDebug(36001) << "d->chooseCell : " << ( d->chooseCell ? "true" : "false" ) << endl;
1691 // If we are in editing mode, we redirect the
1692 // focus to the CellEditor or EditWidget
1693 // And we know which, using lastEditorWithFocus.
1694 // This screws up <Tab> though (David)
1695 if ( lastEditorWithFocus() == EditWidget )
1696 {
1697 d->editWidget->setFocus();
1698 //kdDebug(36001) << "Focus to EditWidget" << endl;
1699 return;
1700 }
1701
1702 //kdDebug(36001) << "Redirecting focus to editor" << endl;
1703 d->cellEditor->setFocus();
1704}
1705
1706void Canvas::focusOutEvent( TQFocusEvent* )
1707{
1708 if ( d->scrollTimer->isActive() )
1709 d->scrollTimer->stop();
1710 d->mousePressed = false;
1711 d->view->disableAutoScroll();
1712}
1713
1714void Canvas::dragMoveEvent( TQDragMoveEvent * _ev )
1715{
1716 Sheet * sheet = activeSheet();
1717 if ( !sheet )
1718 {
1719 _ev->ignore();
1720 return;
1721 }
1722
1723 _ev->accept( TextDrag::canDecode( _ev ) );
1724
1725 double dwidth = d->view->doc()->unzoomItX( width() );
1726 double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() );
1727 double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() );
1728 double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this );
1729 double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this );
1730
1731 TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3);
1732
1733 double ev_PosX;
1734 if (sheet->layoutDirection()==Sheet::RightToLeft)
1735 ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1736 else
1737 ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1738
1739 double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
1740
1741 if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) )
1742 _ev->ignore( r1 );
1743}
1744
1745void Canvas::dragLeaveEvent( TQDragLeaveEvent * )
1746{
1747 if ( d->scrollTimer->isActive() )
1748 d->scrollTimer->stop();
1749}
1750
1751void Canvas::dropEvent( TQDropEvent * _ev )
1752{
1753 d->dragging = false;
1754 if ( d->scrollTimer->isActive() )
1755 d->scrollTimer->stop();
1756 Sheet * sheet = activeSheet();
1757 if ( !sheet || sheet->isProtected() )
1758 {
1759 _ev->ignore();
1760 return;
1761 }
1762
1763 double dwidth = d->view->doc()->unzoomItX( width() );
1764 double xpos = sheet->dblColumnPos( selectionInfo()->lastRange().left() );
1765 double ypos = sheet->dblRowPos( selectionInfo()->lastRange().top() );
1766 double width = sheet->columnFormat( selectionInfo()->lastRange().left() )->dblWidth( this );
1767 double height = sheet->rowFormat( selectionInfo()->lastRange().top() )->dblHeight( this );
1768
1769 TQRect r1 ((int) xpos - 1, (int) ypos - 1, (int) width + 3, (int) height + 3);
1770
1771 double ev_PosX;
1772 if (sheet->layoutDirection()==Sheet::RightToLeft)
1773 ev_PosX = dwidth - d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1774 else
1775 ev_PosX = d->view->doc()->unzoomItX( _ev->pos().x() ) + xOffset();
1776
1777 double ev_PosY = d->view->doc()->unzoomItY( _ev->pos().y() ) + yOffset();
1778
1779 if ( r1.contains( TQPoint ((int) ev_PosX, (int) ev_PosY) ) )
1780 {
1781 _ev->ignore( );
1782 return;
1783 }
1784 else
1785 _ev->accept( );
1786
1787 double tmp;
1788 int col = sheet->leftColumn( ev_PosX, tmp );
1789 int row = sheet->topRow( ev_PosY, tmp );
1790
1791 if ( !TextDrag::canDecode( _ev ) )
1792 {
1793 _ev->ignore();
1794 return;
1795 }
1796
1797 TQByteArray b;
1798
1799 bool makeUndo = true;
1800
1801 if ( _ev->provides( TextDrag::selectionMimeType() ) )
1802 {
1803 if ( TextDrag::target() == _ev->source() )
1804 {
1805 if ( !d->view->doc()->undoLocked() )
1806 {
1807 UndoDragDrop * undo
1808 = new UndoDragDrop(d->view->doc(), sheet, *selectionInfo(),
1809 TQRect(col, row,
1810 selectionInfo()->boundingRect().width(),
1811 selectionInfo()->boundingRect().height()));
1812 d->view->doc()->addCommand( undo );
1813 makeUndo = false;
1814 }
1815 sheet->deleteSelection( selectionInfo(), false );
1816 }
1817
1818
1819 b = _ev->encodedData( TextDrag::selectionMimeType() );
1820 sheet->paste( b, TQRect( col, row, 1, 1 ), makeUndo );
1821
1822 if ( _ev->source() == this )
1823 _ev->acceptAction();
1824 _ev->accept();
1825 }
1826 else
1827 {
1828 TQString text;
1829 if ( !TQTextDrag::decode( _ev, text ) )
1830 {
1831 _ev->ignore();
1832 return;
1833 }
1834 // if ( TextDrag::target() == _ev->source() )
1835 // sheet->deleteSelection( selectionInfo() );
1836
1837 sheet->pasteTextPlain( text, TQRect( col, row, 1, 1 ) );
1838 _ev->accept();
1839 if ( _ev->source() == this )
1840 _ev->acceptAction();
1841
1842 return;
1843 }
1844}
1845
1846void Canvas::resizeEvent( TQResizeEvent* _ev )
1847{
1848 if (!activeSheet())
1849 return;
1850
1851
1852 double ev_Width = d->view->doc()->unzoomItX( _ev->size().width() );
1853 double ev_Height = d->view->doc()->unzoomItY( _ev->size().height() );
1854
1855 // workaround to allow horizontal resizing and zoom changing when sheet
1856 // direction and interface direction don't match (e.g. an RTL sheet on an
1857 // LTR interface)
1858 if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() )
1859 {
1860 int dx = _ev->size().width() - _ev->oldSize().width();
1861 scroll(dx, 0);
1862 }
1863 else if ( activeSheet() && activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() )
1864 {
1865 int dx = _ev->size().width() - _ev->oldSize().width();
1866 scroll(-dx, 0);
1867 }
1868
1869 // If we rise horizontally, then check if we are still within the valid area (KS_colMax)
1870 if ( _ev->size().width() > _ev->oldSize().width() )
1871 {
1872 int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value();
1873
1874 if ( ( xOffset() + ev_Width ) >
1875 d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) )
1876 {
1877 horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) );
1878 if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
1879 horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue );
1880 }
1881 }
1882 // If we lower vertically, then check if the range should represent the maximum range
1883 else if ( _ev->size().width() < _ev->oldSize().width() )
1884 {
1885 int oldValue = horzScrollBar()->maxValue() - horzScrollBar()->value();
1886
1887 if ( horzScrollBar()->maxValue() ==
1888 int( d->view->doc()->zoomItX( activeSheet()->sizeMaxX() ) - ev_Width ) )
1889 {
1890 horzScrollBar()->setRange( 0, d->view->doc()->zoomItX( activeSheet()->sizeMaxX() - ev_Width ) );
1891 if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
1892 horzScrollBar()->setValue( horzScrollBar()->maxValue() - oldValue );
1893 }
1894 }
1895
1896 // If we rise vertically, then check if we are still within the valid area (KS_rowMax)
1897 if ( _ev->size().height() > _ev->oldSize().height() )
1898 {
1899 if ( ( yOffset() + ev_Height ) >
1900 d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) )
1901 {
1902 vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) );
1903 }
1904 }
1905 // If we lower vertically, then check if the range should represent the maximum range
1906 else if ( _ev->size().height() < _ev->oldSize().height() )
1907 {
1908 if ( vertScrollBar()->maxValue() ==
1909 int( d->view->doc()->zoomItY( activeSheet()->sizeMaxY() ) - ev_Height ) )
1910 {
1911 vertScrollBar()->setRange( 0, d->view->doc()->zoomItY( activeSheet()->sizeMaxY() - ev_Height ) );
1912 }
1913 }
1914}
1915
1916TQPoint Canvas::cursorPos()
1917{
1918 TQPoint cursor;
1919 if (d->chooseCell && !choice()->isEmpty())
1920 cursor = choice()->cursor();
1921 else
1922 cursor = selectionInfo()->cursor();
1923
1924 return cursor;
1925}
1926
1927TQRect Canvas::moveDirection( KSpread::MoveTo direction, bool extendSelection )
1928{
1929 kdDebug(36001) << "Canvas::moveDirection" << endl;
1930
1931 TQPoint destination;
1932 TQPoint cursor = cursorPos();
1933
1934 TQPoint cellCorner = cursor;
1935 Cell* cell = activeSheet()->cellAt(cursor.x(), cursor.y());
1936
1937 /* cell is either the same as the marker, or the cell that is forced obscuring
1938 the marker cell
1939 */
1940 if (cell->isPartOfMerged())
1941 {
1942 cell = cell->obscuringCells().first();
1943 cellCorner = TQPoint(cell->column(), cell->row());
1944 }
1945
1946 /* how many cells must we move to get to the next cell? */
1947 int offset = 0;
1948 RowFormat *rl = NULL;
1949 ColumnFormat *cl = NULL;
1950 switch (direction)
1951 /* for each case, figure out how far away the next cell is and then keep
1952 going one row/col at a time after that until a visible row/col is found
1953
1954 NEVER use cell->column() or cell->row() -- it might be a default cell
1955 */
1956 {
1957 case KSpread::Bottom:
1958 offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1;
1959 rl = activeSheet()->rowFormat( cursor.y() + offset );
1960 while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide())
1961 {
1962 offset++;
1963 rl = activeSheet()->rowFormat( cursor.y() + offset );
1964 }
1965
1966 destination = TQPoint(cursor.x(), TQMIN(cursor.y() + offset, KS_rowMax));
1967 break;
1968 case KSpread::Top:
1969 offset = (cellCorner.y() - cursor.y()) - 1;
1970 rl = activeSheet()->rowFormat( cursor.y() + offset );
1971 while ( ((cursor.y() + offset) >= 1) && rl->isHide())
1972 {
1973 offset--;
1974 rl = activeSheet()->rowFormat( cursor.y() + offset );
1975 }
1976 destination = TQPoint(cursor.x(), TQMAX(cursor.y() + offset, 1));
1977 break;
1978 case KSpread::Left:
1979 offset = (cellCorner.x() - cursor.x()) - 1;
1980 cl = activeSheet()->columnFormat( cursor.x() + offset );
1981 while ( ((cursor.x() + offset) >= 1) && cl->isHide())
1982 {
1983 offset--;
1984 cl = activeSheet()->columnFormat( cursor.x() + offset );
1985 }
1986 destination = TQPoint(TQMAX(cursor.x() + offset, 1), cursor.y());
1987 break;
1988 case KSpread::Right:
1989 offset = cell->mergedXCells() - (cursor.x() - cellCorner.x()) + 1;
1990 cl = activeSheet()->columnFormat( cursor.x() + offset );
1991 while ( ((cursor.x() + offset) <= KS_colMax) && cl->isHide())
1992 {
1993 offset++;
1994 cl = activeSheet()->columnFormat( cursor.x() + offset );
1995 }
1996 destination = TQPoint(TQMIN(cursor.x() + offset, KS_colMax), cursor.y());
1997 break;
1998 case KSpread::BottomFirst:
1999 offset = cell->mergedYCells() - (cursor.y() - cellCorner.y()) + 1;
2000 rl = activeSheet()->rowFormat( cursor.y() + offset );
2001 while ( ((cursor.y() + offset) <= KS_rowMax) && rl->isHide())
2002 {
2003 ++offset;
2004 rl = activeSheet()->rowFormat( cursor.y() + offset );
2005 }
2006
2007 destination = TQPoint( 1, TQMIN( cursor.y() + offset, KS_rowMax ) );
2008 break;
2009 }
2010
2011 if (extendSelection)
2012 {
2013 (d->chooseCell ? choice() : selectionInfo())->update(destination);
2014 }
2015 else
2016 {
2017 (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
2018 }
2019 d->view->updateEditWidget();
2020
2021 return TQRect( cursor, destination );
2022}
2023
2024void Canvas::processEnterKey(TQKeyEvent* event)
2025{
2026 // array is true, if ctrl+alt are pressed
2027 bool array = (event->state() & TQt::AltButton) &&
2028 (event->state() & TQt::ControlButton);
2029
2030 /* save changes to the current editor */
2031 if (!d->chooseCell)
2032 {
2033 deleteEditor(true, array);
2034 }
2035
2036 /* use the configuration setting to see which direction we're supposed to move
2037 when enter is pressed.
2038 */
2039 KSpread::MoveTo direction = d->view->doc()->getMoveToValue();
2040
2041 //if shift Button clicked inverse move direction
2042 if (event->state() & TQt::ShiftButton)
2043 {
2044 switch( direction )
2045 {
2046 case KSpread::Bottom:
2047 direction = KSpread::Top;
2048 break;
2049 case KSpread::Top:
2050 direction = KSpread::Bottom;
2051 break;
2052 case KSpread::Left:
2053 direction = KSpread::Right;
2054 break;
2055 case KSpread::Right:
2056 direction = KSpread::Left;
2057 break;
2058 case KSpread::BottomFirst:
2059 direction = KSpread::BottomFirst;
2060 break;
2061 }
2062 }
2063
2064 /* never extend a selection with the enter key -- the shift key reverses
2065 direction, not extends the selection
2066 */
2067 TQRect r( moveDirection( direction, false ) );
2068 d->view->doc()->emitEndOperation( r );
2069}
2070
2071void Canvas::processArrowKey( TQKeyEvent *event)
2072{
2073 /* NOTE: hitting the tab key also calls this function. Don't forget
2074 to account for it
2075 */
2076
2077 /* save changes to the current editor */
2078 if (!d->chooseCell)
2079 {
2080 deleteEditor( true );
2081 }
2082
2083 KSpread::MoveTo direction = KSpread::Bottom;
2084 bool makingSelection = event->state() & ShiftButton;
2085
2086 switch (event->key())
2087 {
2088 case Key_Down:
2089 direction = KSpread::Bottom;
2090 break;
2091 case Key_Up:
2092 direction = KSpread::Top;
2093 break;
2094 case Key_Left:
2095 if (activeSheet()->layoutDirection()==Sheet::RightToLeft)
2096 direction = KSpread::Right;
2097 else
2098 direction = KSpread::Left;
2099 break;
2100 case Key_Right:
2101 if (activeSheet()->layoutDirection()==Sheet::RightToLeft)
2102 direction = KSpread::Left;
2103 else
2104 direction = KSpread::Right;
2105 break;
2106 case Key_Tab:
2107 direction = KSpread::Right;
2108 break;
2109 case Key_Backtab:
2110 //Shift+Tab moves to the left
2111 direction = KSpread::Left;
2112 makingSelection = false;
2113 break;
2114 default:
2115 Q_ASSERT(false);
2116 break;
2117 }
2118
2119 TQRect r( moveDirection( direction, makingSelection ) );
2120 d->view->doc()->emitEndOperation( r );
2121}
2122
2123void Canvas::processEscapeKey(TQKeyEvent * event)
2124{
2125 if ( d->cellEditor )
2126 deleteEditor( false );
2127
2128 if ( view()->isInsertingObject() )
2129 {
2130 view()->resetInsertHandle();
2131 setCursor( arrowCursor );
2132 return;
2133 }
2134
2135 event->accept(); // ?
2136 TQPoint cursor = cursorPos();
2137
2138 d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
2139
2140 if ( d->mousePressed /*&& toolEditMode == TEM_MOUSE */)
2141 {
2142 switch (d->modType)
2143 {
2144 case MT_RESIZE_UP:
2145 case MT_RESIZE_DN:
2146 case MT_RESIZE_LF:
2147 case MT_RESIZE_RT:
2148 case MT_RESIZE_LU:
2149 case MT_RESIZE_LD:
2150 case MT_RESIZE_RU:
2151 case MT_RESIZE_RD:
2152 {
2153 TQRect oldBoundingRect = doc()->zoomRect( d->m_resizeObject->geometry()/*getRepaintRect()*/);
2154 d->m_resizeObject->setGeometry( d->m_rectBeforeResize );
2155 oldBoundingRect.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) ,
2156 (int)( -yOffset() * doc()->zoomedResolutionY()) );
2157
2158 activeSheet()->setRegionPaintDirty( oldBoundingRect );
2159 repaint( oldBoundingRect );
2160 repaintObject( d->m_resizeObject );
2161 d->m_ratio = 0.0;
2162 d->m_resizeObject = 0;
2163 d->m_isResizing = false;
2164 view()->disableAutoScroll();
2165 d->mousePressed = false;
2166 d->modType = MT_NONE;
2167 break;
2168 }
2169 case MT_MOVE:
2170 {
2171 if ( d->m_isMoving )
2172 {
2173 KoPoint move( d->m_moveStartPoint - objectRect( false ).topLeft() );
2174 activeSheet()->moveObject( view(), move, false );
2175 view()->disableAutoScroll();
2176 d->mousePressed = false;
2177 d->modType = MT_NONE;
2178 d->m_isMoving = false;
2179 update();
2180 }
2181 break;
2182 }
2183 default:
2184 break;
2185 }
2186 }
2187}
2188
2189bool Canvas::processHomeKey(TQKeyEvent* event)
2190{
2191 bool makingSelection = event->state() & ShiftButton;
2192 Sheet* sheet = activeSheet();
2193
2194 if ( d->cellEditor )
2195 // We are in edit mode -> go beginning of line
2196 {
2197 TQApplication::sendEvent( d->editWidget, event );
2198 return false;
2199 }
2200 else
2201 {
2202 TQPoint destination;
2203 /* start at the first used cell in the row and cycle through the right until
2204 we find a cell that has some output text. But don't look past the current
2205 marker.
2206 The end result we want is to move to the left to the first cell with text,
2207 or just to the first column if there is no more text to the left.
2208
2209 But why? In excel, home key sends you to the first column always.
2210 We might want to change to that behavior.
2211 */
2212
2213 if (event->state() & ControlButton)
2214 {
2215 /* ctrl + Home will always just send us to location (1,1) */
2216 destination = TQPoint( 1, 1 );
2217 }
2218 else
2219 {
2220 TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
2221
2222 Cell * cell = sheet->getFirstCellRow(marker.y());
2223 while (cell != NULL && cell->column() < marker.x() && cell->isEmpty())
2224 {
2225 cell = sheet->getNextCellRight(cell->column(), cell->row());
2226 }
2227
2228 int col = ( cell ? cell->column() : 1 );
2229 if ( col == marker.x())
2230 col = 1;
2231 destination = TQPoint(col, marker.y());
2232 }
2233
2234 if ( selectionInfo()->marker() == destination )
2235 {
2236 d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
2237 return false;
2238 }
2239
2240 if (makingSelection)
2241 {
2242 (d->chooseCell ? choice() : selectionInfo())->update(destination);
2243 }
2244 else
2245 {
2246 (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
2247 }
2248 }
2249 return true;
2250}
2251
2252bool Canvas::processEndKey( TQKeyEvent *event )
2253{
2254 bool makingSelection = event->state() & ShiftButton;
2255 Sheet* sheet = activeSheet();
2256 Cell* cell = NULL;
2257 TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
2258
2259 // move to the last used cell in the row
2260 // We are in edit mode -> go beginning of line
2261 if ( d->cellEditor )
2262 {
2263 TQApplication::sendEvent( d->editWidget, event );
2264 d->view->doc()->emitEndOperation( TQRect( marker, marker ) );
2265 return false;
2266 }
2267 else
2268 {
2269 int col = 1;
2270
2271 cell = sheet->getLastCellRow(marker.y());
2272 while (cell != NULL && cell->column() > markerColumn() && cell->isEmpty())
2273 {
2274 cell = sheet->getNextCellLeft(cell->column(), cell->row());
2275 }
2276
2277 col = (cell == NULL) ? KS_colMax : cell->column();
2278
2279 TQPoint destination( col, marker.y() );
2280 if ( destination == marker )
2281 {
2282 d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
2283 return false;
2284 }
2285
2286 if (makingSelection)
2287 {
2288 (d->chooseCell ? choice() : selectionInfo())->update(destination);
2289 }
2290 else
2291 {
2292 (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
2293 }
2294 }
2295 return true;
2296}
2297
2298bool Canvas::processPriorKey(TQKeyEvent *event)
2299{
2300 bool makingSelection = event->state() & ShiftButton;
2301 if (!d->chooseCell)
2302 {
2303 deleteEditor( true );
2304 }
2305
2306 TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
2307
2308 TQPoint destination(marker.x(), TQMAX(1, marker.y() - 10));
2309 if ( destination == marker )
2310 {
2311 d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
2312 return false;
2313 }
2314
2315 if (makingSelection)
2316 {
2317 (d->chooseCell ? choice() : selectionInfo())->update(destination);
2318 }
2319 else
2320 {
2321 (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
2322 }
2323 return true;
2324}
2325
2326bool Canvas::processNextKey(TQKeyEvent *event)
2327{
2328 bool makingSelection = event->state() & ShiftButton;
2329
2330 if (!d->chooseCell)
2331 {
2332 deleteEditor( true /*save changes*/ );
2333 }
2334
2335 TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
2336 TQPoint destination(marker.x(), TQMAX(1, marker.y() + 10));
2337
2338 if ( marker == destination )
2339 {
2340 d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
2341 return false;
2342 }
2343
2344 if (makingSelection)
2345 {
2346 (d->chooseCell ? choice() : selectionInfo())->update(destination);
2347 }
2348 else
2349 {
2350 (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
2351 }
2352 return true;
2353}
2354
2355void Canvas::processDeleteKey(TQKeyEvent* /* event */)
2356{
2357 if ( isObjectSelected() )
2358 {
2359 d->view->doc()->emitEndOperation( activeSheet()->visibleRect( this ) );
2360 d->view->deleteSelectedObjects();
2361 return;
2362 }
2363
2364 activeSheet()->clearTextSelection( selectionInfo() );
2365 d->editWidget->setText( "" );
2366
2367 TQPoint cursor = cursorPos();
2368
2369 d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
2370 return;
2371}
2372
2373void Canvas::processF2Key(TQKeyEvent* /* event */)
2374{
2375 d->editWidget->setFocus();
2376 if ( d->cellEditor )
2377 d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() - 1 );
2378 d->editWidget->cursorForward( false );
2379
2380
2381 TQPoint cursor = cursorPos();
2382
2383 d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
2384 return;
2385}
2386
2387void Canvas::processF4Key(TQKeyEvent* event)
2388{
2389 /* passes F4 to the editor (if any), which will process it
2390 */
2391 if ( d->cellEditor )
2392 {
2393 d->cellEditor->handleKeyPressEvent( event );
2394// d->editWidget->setFocus();
2395 d->editWidget->setCursorPosition( d->cellEditor->cursorPosition() );
2396 }
2397 TQPoint cursor = cursorPos();
2398
2399 d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
2400 return;
2401}
2402
2403void Canvas::processOtherKey(TQKeyEvent *event)
2404{
2405 // No null character ...
2406 if ( event->text().isEmpty() || !d->view->koDocument()->isReadWrite()
2407 || !activeSheet() || activeSheet()->isProtected() )
2408 {
2409 event->accept();
2410 }
2411 else
2412 {
2413 if ( !d->cellEditor && !d->chooseCell )
2414 {
2415 // Switch to editing mode
2417 d->cellEditor->handleKeyPressEvent( event );
2418 }
2419 else if ( d->cellEditor )
2420 d->cellEditor->handleKeyPressEvent( event );
2421 }
2422
2423 TQPoint cursor = cursorPos();
2424
2425 d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
2426
2427 return;
2428}
2429
2430bool Canvas::processControlArrowKey( TQKeyEvent *event )
2431{
2432 bool makingSelection = event->state() & ShiftButton;
2433
2434 Sheet* sheet = activeSheet();
2435 Cell* cell = NULL;
2436 Cell* lastCell;
2437 TQPoint destination;
2438 bool searchThroughEmpty = true;
2439 int row;
2440 int col;
2441
2442 TQPoint marker = d->chooseCell ? choice()->marker() : selectionInfo()->marker();
2443
2444 /* here, we want to move to the first or last cell in the given direction that is
2445 actually being used. Ignore empty cells and cells on hidden rows/columns */
2446 switch ( event->key() )
2447 {
2448 //Ctrl+Key_Up
2449 case Key_Up:
2450
2451 cell = sheet->cellAt( marker.x(), marker.y() );
2452 if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != 1))
2453 {
2454 lastCell = cell;
2455 row = marker.y()-1;
2456 cell = sheet->cellAt(cell->column(), row);
2457 while ((cell != NULL) && (row > 0) && (!cell->isEmpty()) )
2458 {
2459 if (!(sheet->rowFormat(cell->row())->isHide()))
2460 {
2461 lastCell = cell;
2462 searchThroughEmpty = false;
2463 }
2464 row--;
2465 if ( row > 0 )
2466 cell = sheet->cellAt(cell->column(), row);
2467 }
2468 cell = lastCell;
2469 }
2470 if (searchThroughEmpty)
2471 {
2472 cell = sheet->getNextCellUp(marker.x(), marker.y());
2473
2474 while ((cell != NULL) &&
2475 (cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide())))
2476 {
2477 cell = sheet->getNextCellUp(cell->column(), cell->row());
2478 }
2479 }
2480
2481 if (cell == NULL)
2482 row = 1;
2483 else
2484 row = cell->row();
2485
2486 while ( sheet->rowFormat(row)->isHide() )
2487 {
2488 row++;
2489 }
2490
2491 destination.setX(marker.x());
2492 destination.setY(row);
2493 break;
2494
2495 //Ctrl+Key_Down
2496 case Key_Down:
2497
2498 cell = sheet->cellAt( marker.x(), marker.y() );
2499 if ( (cell != NULL) && (!cell->isEmpty()) && (marker.y() != KS_rowMax))
2500 {
2501 lastCell = cell;
2502 row = marker.y()+1;
2503 cell = sheet->cellAt(cell->column(), row);
2504 while ((cell != NULL) && (row < KS_rowMax) && (!cell->isEmpty()) )
2505 {
2506 if (!(sheet->rowFormat(cell->row())->isHide()))
2507 {
2508 lastCell = cell;
2509 searchThroughEmpty = false;
2510 }
2511 row++;
2512 cell = sheet->cellAt(cell->column(), row);
2513 }
2514 cell = lastCell;
2515 }
2516 if (searchThroughEmpty)
2517 {
2518 cell = sheet->getNextCellDown(marker.x(), marker.y());
2519
2520 while ((cell != NULL) &&
2521 (cell->isEmpty() || (sheet->rowFormat(cell->row())->isHide())))
2522 {
2523 cell = sheet->getNextCellDown(cell->column(), cell->row());
2524 }
2525 }
2526
2527 if (cell == NULL)
2528 row = marker.y();
2529 else
2530 row = cell->row();
2531
2532 while ( sheet->rowFormat(row)->isHide() )
2533 {
2534 row--;
2535 }
2536
2537 destination.setX(marker.x());
2538 destination.setY(row);
2539 break;
2540
2541 //Ctrl+Key_Left
2542 case Key_Left:
2543
2544 if ( sheet->layoutDirection()==Sheet::RightToLeft )
2545 {
2546 cell = sheet->cellAt( marker.x(), marker.y() );
2547 if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax))
2548 {
2549 lastCell = cell;
2550 col = marker.x()+1;
2551 cell = sheet->cellAt(col, cell->row());
2552 while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) )
2553 {
2554 if (!(sheet->columnFormat(cell->column())->isHide()))
2555 {
2556 lastCell = cell;
2557 searchThroughEmpty = false;
2558 }
2559 col++;
2560 cell = sheet->cellAt(col, cell->row());
2561 }
2562 cell = lastCell;
2563 }
2564 if (searchThroughEmpty)
2565 {
2566 cell = sheet->getNextCellRight(marker.x(), marker.y());
2567
2568 while ((cell != NULL) &&
2569 (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
2570 {
2571 cell = sheet->getNextCellRight(cell->column(), cell->row());
2572 }
2573 }
2574
2575 if (cell == NULL)
2576 col = marker.x();
2577 else
2578 col = cell->column();
2579
2580 while ( sheet->columnFormat(col)->isHide() )
2581 {
2582 col--;
2583 }
2584
2585 destination.setX(col);
2586 destination.setY(marker.y());
2587 }
2588 else
2589 {
2590 cell = sheet->cellAt( marker.x(), marker.y() );
2591 if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1))
2592 {
2593 lastCell = cell;
2594 col = marker.x()-1;
2595 cell = sheet->cellAt(col, cell->row());
2596 while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) )
2597 {
2598 if (!(sheet->columnFormat(cell->column())->isHide()))
2599 {
2600 lastCell = cell;
2601 searchThroughEmpty = false;
2602 }
2603 col--;
2604 if ( col > 0 )
2605 cell = sheet->cellAt(col, cell->row());
2606 }
2607 cell = lastCell;
2608 }
2609 if (searchThroughEmpty)
2610 {
2611 cell = sheet->getNextCellLeft(marker.x(), marker.y());
2612
2613 while ((cell != NULL) &&
2614 (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
2615 {
2616 cell = sheet->getNextCellLeft(cell->column(), cell->row());
2617 }
2618 }
2619
2620 if (cell == NULL)
2621 col = 1;
2622 else
2623 col = cell->column();
2624
2625 while ( sheet->columnFormat(col)->isHide() )
2626 {
2627 col++;
2628 }
2629
2630 destination.setX(col);
2631 destination.setY(marker.y());
2632 }
2633 break;
2634
2635 //Ctrl+Key_Right
2636 case Key_Right:
2637
2638 if ( sheet->layoutDirection()==Sheet::RightToLeft )
2639 {
2640 cell = sheet->cellAt( marker.x(), marker.y() );
2641 if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != 1))
2642 {
2643 lastCell = cell;
2644 col = marker.x()-1;
2645 cell = sheet->cellAt(col, cell->row());
2646 while ((cell != NULL) && (col > 0) && (!cell->isEmpty()) )
2647 {
2648 if (!(sheet->columnFormat(cell->column())->isHide()))
2649 {
2650 lastCell = cell;
2651 searchThroughEmpty = false;
2652 }
2653 col--;
2654 if ( col > 0 )
2655 cell = sheet->cellAt(col, cell->row());
2656 }
2657 cell = lastCell;
2658 }
2659 if (searchThroughEmpty)
2660 {
2661 cell = sheet->getNextCellLeft(marker.x(), marker.y());
2662
2663 while ((cell != NULL) &&
2664 (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
2665 {
2666 cell = sheet->getNextCellLeft(cell->column(), cell->row());
2667 }
2668 }
2669
2670 if (cell == NULL)
2671 col = 1;
2672 else
2673 col = cell->column();
2674
2675 while ( sheet->columnFormat(col)->isHide() )
2676 {
2677 col++;
2678 }
2679
2680 destination.setX(col);
2681 destination.setY(marker.y());
2682 }
2683 else
2684 {
2685 cell = sheet->cellAt( marker.x(), marker.y() );
2686 if ( (cell != NULL) && (!cell->isEmpty()) && (marker.x() != KS_colMax))
2687 {
2688 lastCell = cell;
2689 col = marker.x()+1;
2690 cell = sheet->cellAt(col, cell->row());
2691 while ((cell != NULL) && (col < KS_colMax) && (!cell->isEmpty()) )
2692 {
2693 if (!(sheet->columnFormat(cell->column())->isHide()))
2694 {
2695 lastCell = cell;
2696 searchThroughEmpty = false;
2697 }
2698 col++;
2699 cell = sheet->cellAt(col, cell->row());
2700 }
2701 cell = lastCell;
2702 }
2703 if (searchThroughEmpty)
2704 {
2705 cell = sheet->getNextCellRight(marker.x(), marker.y());
2706
2707 while ((cell != NULL) &&
2708 (cell->isEmpty() || (sheet->columnFormat(cell->column())->isHide())))
2709 {
2710 cell = sheet->getNextCellRight(cell->column(), cell->row());
2711 }
2712 }
2713
2714 if (cell == NULL)
2715 col = marker.x();
2716 else
2717 col = cell->column();
2718
2719 while ( sheet->columnFormat(col)->isHide() )
2720 {
2721 col--;
2722 }
2723
2724 destination.setX(col);
2725 destination.setY(marker.y());
2726 }
2727 break;
2728
2729 }
2730
2731 if ( marker == destination )
2732 {
2733 d->view->doc()->emitEndOperation( TQRect( destination, destination ) );
2734 return false;
2735 }
2736
2737 if (makingSelection)
2738 {
2739 (d->chooseCell ? choice() : selectionInfo())->update(destination);
2740 }
2741 else
2742 {
2743 (d->chooseCell ? choice() : selectionInfo())->initialize(destination, activeSheet());
2744 }
2745 return true;
2746}
2747
2748
2749void Canvas::keyPressEvent ( TQKeyEvent * _ev )
2750{
2751 Sheet * sheet = activeSheet();
2752
2753 if ( !sheet || formatKeyPress( _ev ))
2754 return;
2755
2756 // Dont handle the remaining special keys.
2757 if ( _ev->state() & ( TQt::AltButton | TQt::ControlButton ) &&
2758 (_ev->key() != Key_Down) &&
2759 (_ev->key() != Key_Up) &&
2760 (_ev->key() != Key_Right) &&
2761 (_ev->key() != Key_Left) &&
2762 (_ev->key() != Key_Home) &&
2763 (_ev->key() != Key_Enter) &&
2764 (_ev->key() != Key_Return) &&
2765 (_ev->key() != TDEGlobalSettings::contextMenuKey()))
2766 {
2767 TQWidget::keyPressEvent( _ev );
2768 return;
2769 }
2770
2771 // Always accept so that events are not
2772 // passed to the parent.
2773 _ev->accept();
2774
2775 d->view->doc()->emitBeginOperation(false);
2776 if ( _ev->key() == TDEGlobalSettings::contextMenuKey() ) {
2777 int row = markerRow();
2778 int col = markerColumn();
2779 KoPoint kop(sheet->columnPos(col, this), sheet->rowPos(row, this));
2780 TQPoint p = d->view->doc()->zoomPoint(kop);
2781 p = mapToGlobal(p);
2782 d->view->openPopupMenu( p );
2783 }
2784 switch( _ev->key() )
2785 {
2786 case Key_Return:
2787 case Key_Enter:
2788 processEnterKey( _ev );
2789 return;
2790 break;
2791 case Key_Down:
2792 case Key_Up:
2793 case Key_Left:
2794 case Key_Right:
2795 case Key_Tab: /* a tab behaves just like a right/left arrow */
2796 case Key_Backtab: /* and so does Shift+Tab */
2797 if (_ev->state() & ControlButton)
2798 {
2799 if ( !processControlArrowKey( _ev ) )
2800 return;
2801 }
2802 else
2803 {
2804 processArrowKey( _ev );
2805 return;
2806 }
2807 break;
2808
2809 case Key_Escape:
2810 processEscapeKey( _ev );
2811 return;
2812 break;
2813
2814 case Key_Home:
2815 if ( !processHomeKey( _ev ) )
2816 return;
2817 break;
2818
2819 case Key_End:
2820 if ( !processEndKey( _ev ) )
2821 return;
2822 break;
2823
2824 case Key_Prior: /* Page Up */
2825 if ( !processPriorKey( _ev ) )
2826 return;
2827 break;
2828
2829 case Key_Next: /* Page Down */
2830 if ( !processNextKey( _ev ) )
2831 return;
2832 break;
2833
2834 case Key_Delete:
2835 processDeleteKey( _ev );
2836 return;
2837 break;
2838
2839 case Key_F2:
2840 processF2Key( _ev );
2841 return;
2842 break;
2843
2844 case Key_F4:
2845 processF4Key( _ev );
2846 return;
2847 break;
2848
2849 default:
2850 processOtherKey( _ev );
2851 return;
2852 break;
2853 }
2854
2855 //most process*Key methods call emitEndOperation, this only gets called in some situations
2856 // (after some move operations)
2857 d->view->doc()->emitEndOperation( sheet->visibleRect( this ) );
2858 return;
2859}
2860
2861void Canvas::processIMEvent( TQIMEvent * event )
2862{
2863 d->view->doc()->emitBeginOperation( false );
2864 if ( !d->cellEditor && !d->chooseCell )
2865 {
2866 // Switch to editing mode
2868 d->cellEditor->handleIMEvent( event );
2869 }
2870
2871 TQPoint cursor;
2872
2873 if ( d->chooseCell )
2874 {
2875 cursor = choice()->cursor();
2876 /* if the cursor is unset, pretend we're starting at the regular cursor */
2877 if (cursor.x() == 0 || cursor.y() == 0)
2878 cursor = choice()->cursor();
2879 }
2880 else
2881 cursor = selectionInfo()->cursor();
2882
2883 d->view->doc()->emitEndOperation( TQRect( cursor, cursor ) );
2884}
2885
2886bool Canvas::formatKeyPress( TQKeyEvent * _ev )
2887{
2888 if (!(_ev->state() & ControlButton ))
2889 return false;
2890
2891 int key = _ev->key();
2892 if ( key != Key_Exclam && key != Key_At && key != Key_Ampersand
2893 && key != Key_Dollar && key != Key_Percent && key != Key_AsciiCircum
2894 && key != Key_NumberSign )
2895 return false;
2896
2897 Cell * cell = 0L;
2898 Sheet * sheet = activeSheet();
2899
2900 d->view->doc()->emitBeginOperation(false);
2901
2902 if ( !d->view->doc()->undoLocked() )
2903 {
2904 TQString dummy;
2905 UndoCellFormat * undo = new UndoCellFormat( d->view->doc(), sheet, *selectionInfo(), dummy );
2906 d->view->doc()->addCommand( undo );
2907 }
2908
2909 Region::ConstIterator end(selectionInfo()->constEnd());
2910 for (Region::ConstIterator it = selectionInfo()->constBegin(); it != end; ++it)
2911 {
2912 TQRect rect = (*it)->rect().normalize();
2913
2914 int right = rect.right();
2915 int bottom = rect.bottom();
2916
2917 if ( util_isRowSelected(rect) )
2918 {
2919 for ( int r = rect.top(); r <= bottom; ++r )
2920 {
2921 cell = sheet->getFirstCellRow( r );
2922 while ( cell )
2923 {
2924 if ( cell->isPartOfMerged() )
2925 {
2926 cell = sheet->getNextCellRight( cell->column(), r );
2927 continue;
2928 }
2929
2930 formatCellByKey (cell, _ev->key(), rect);
2931
2932 cell = sheet->getNextCellRight( cell->column(), r );
2933 } // while (cell)
2934 RowFormat * rw = sheet->nonDefaultRowFormat( r );
2935 TQPen pen;
2936 switch ( _ev->key() )
2937 {
2938 case Key_Exclam:
2939 rw->setFormatType (Number_format);
2940 rw->setPrecision( 2 );
2941 break;
2942
2943 case Key_Dollar:
2944 rw->setFormatType (Money_format);
2945 rw->setPrecision( d->view->doc()->locale()->fracDigits() );
2946 break;
2947
2948 case Key_Percent:
2949 rw->setFormatType (Percentage_format);
2950 break;
2951
2952 case Key_At:
2953 rw->setFormatType( SecondeTime_format );
2954 break;
2955
2956 case Key_NumberSign:
2957 rw->setFormatType( ShortDate_format );
2958 break;
2959
2960 case Key_AsciiCircum:
2961 rw->setFormatType( Scientific_format );
2962 break;
2963
2964 case Key_Ampersand:
2965 if ( r == rect.top() )
2966 {
2967 pen = TQPen( d->view->borderColor(), 1, SolidLine);
2968 rw->setTopBorderPen( pen );
2969 }
2970 if ( r == rect.bottom() )
2971 {
2972 pen = TQPen( d->view->borderColor(), 1, SolidLine);
2973 rw->setBottomBorderPen( pen );
2974 }
2975 break;
2976
2977 default:
2978 d->view->doc()->emitEndOperation( rect );
2979 return false;
2980 }
2981 sheet->emit_updateRow( rw, r );
2982 }
2983
2984 d->view->doc()->emitEndOperation( rect );
2985 return true;
2986 }
2987
2988 if ( util_isColumnSelected(rect) )
2989 {
2990 for ( int c = rect.left(); c <= right; ++c )
2991 {
2992 cell = sheet->getFirstCellColumn( c );
2993 while ( cell )
2994 {
2995 if ( cell->isPartOfMerged() )
2996 {
2997 cell = sheet->getNextCellDown( c, cell->row() );
2998 continue;
2999 }
3000
3001 formatCellByKey (cell, _ev->key(), rect);
3002
3003 cell = sheet->getNextCellDown( c, cell->row() );
3004 }
3005
3006 ColumnFormat * cw = sheet->nonDefaultColumnFormat( c );
3007 TQPen pen;
3008 switch ( _ev->key() )
3009 {
3010 case Key_Exclam:
3011 cw->setFormatType( Number_format );
3012 cw->setPrecision( 2 );
3013 break;
3014
3015 case Key_Dollar:
3016 cw->setFormatType( Money_format );
3017 cw->setPrecision( d->view->doc()->locale()->fracDigits() );
3018 break;
3019
3020 case Key_Percent:
3021 cw->setFormatType( Percentage_format );
3022 break;
3023
3024 case Key_At:
3025 cw->setFormatType( SecondeTime_format );
3026 break;
3027
3028 case Key_NumberSign:
3029 cw->setFormatType( ShortDate_format );
3030 break;
3031
3032 case Key_AsciiCircum:
3033 cw->setFormatType( Scientific_format );
3034 break;
3035
3036 case Key_Ampersand:
3037 if ( c == rect.left() )
3038 {
3039 pen = TQPen( d->view->borderColor(), 1, SolidLine);
3040 cw->setLeftBorderPen( pen );
3041 }
3042 if ( c == rect.right() )
3043 {
3044 pen = TQPen( d->view->borderColor(), 1, SolidLine);
3045 cw->setRightBorderPen( pen );
3046 }
3047 break;
3048
3049 default:
3050 d->view->doc()->emitEndOperation( rect );
3051 return false;
3052 }
3053 sheet->emit_updateColumn( cw, c );
3054 }
3055 d->view->doc()->emitEndOperation( rect );
3056 return true;
3057 }
3058
3059 for ( int row = rect.top(); row <= bottom; ++row )
3060 {
3061 for ( int col = rect.left(); col <= right; ++ col )
3062 {
3063 cell = sheet->nonDefaultCell( col, row );
3064
3065 if ( cell->isPartOfMerged() )
3066 continue;
3067
3068 formatCellByKey (cell, _ev->key(), rect);
3069 } // for left .. right
3070 } // for top .. bottom
3071
3072 }
3073 _ev->accept();
3074
3075 d->view->doc()->emitEndOperation( *selectionInfo() );
3076 return true;
3077}
3078
3079bool Canvas::formatCellByKey (Cell *cell, int key, const TQRect &rect)
3080{
3081 TQPen pen;
3082 switch (key)
3083 {
3084 case Key_Exclam:
3085 cell->convertToDouble ();
3086 cell->format()->setFormatType (Number_format);
3087 cell->format()->setPrecision( 2 );
3088 break;
3089
3090 case Key_Dollar:
3091 cell->convertToMoney ();
3092 break;
3093
3094 case Key_Percent:
3095 cell->convertToPercent ();
3096 break;
3097
3098 case Key_At:
3099 cell->convertToTime ();
3100 break;
3101
3102 case Key_NumberSign:
3103 cell->convertToDate ();
3104 break;
3105
3106 case Key_AsciiCircum:
3107 cell->format()->setFormatType (Scientific_format);
3108 cell->convertToDouble ();
3109 break;
3110
3111 case Key_Ampersand:
3112 if ( cell->row() == rect.top() )
3113 {
3114 pen = TQPen( d->view->borderColor(), 1, SolidLine);
3115 cell->setTopBorderPen( pen );
3116 }
3117 if ( cell->row() == rect.bottom() )
3118 {
3119 pen = TQPen( d->view->borderColor(), 1, SolidLine);
3120 cell->setBottomBorderPen( pen );
3121 }
3122 if ( cell->column() == rect.left() )
3123 {
3124 pen = TQPen( d->view->borderColor(), 1, SolidLine);
3125 cell->setLeftBorderPen( pen );
3126 }
3127 if ( cell->column() == rect.right() )
3128 {
3129 pen = TQPen( d->view->borderColor(), 1, SolidLine);
3130 cell->setRightBorderPen( pen );
3131 }
3132 break;
3133 } // switch
3134
3135 return true;
3136}
3137
3138
3139void Canvas::slotAutoScroll(const TQPoint &scrollDistance)
3140{
3141 TQPoint d = scrollDistance;
3142 horzScrollBar()->setValue( horzScrollBar()->value() + d.x() );
3143 vertScrollBar()->setValue( vertScrollBar()->value() + d.y() );
3144}
3145
3146void Canvas::doAutoScroll()
3147{
3148 if ( !d->mousePressed )
3149 {
3150 d->scrollTimer->stop();
3151 return;
3152 }
3153 bool select = false;
3154 TQPoint pos = mapFromGlobal( TQCursor::pos() );
3155
3156 //Provide progressive scrolling depending on the mouse position
3157 if ( pos.y() < 0 )
3158 {
3159 vertScrollBar()->setValue ((int) (vertScrollBar()->value() -
3160 autoScrollAccelerationY( - pos.y())));
3161 select = true;
3162 }
3163 else if ( pos.y() > height() )
3164 {
3165 vertScrollBar()->setValue ((int) (vertScrollBar()->value() +
3166 autoScrollAccelerationY (pos.y() - height())));
3167 select = true;
3168 }
3169
3170 if ( pos.x() < 0 )
3171 {
3172 horzScrollBar()->setValue ((int) (horzScrollBar()->value() -
3173 autoScrollAccelerationX( - pos.x() )));
3174 select = true;
3175 }
3176 else if ( pos.x() > width() )
3177 {
3178 horzScrollBar()->setValue ((int) (horzScrollBar()->value() +
3179 autoScrollAccelerationX( pos.x() - width())));
3180 select = true;
3181 }
3182
3183 if ( select )
3184 {
3185 TQMouseEvent * event = new TQMouseEvent(TQEvent::MouseMove, pos, 0, 0);
3186 mouseMoveEvent( event );
3187 delete event;
3188 }
3189
3190 //Restart timer
3191 d->scrollTimer->start( 50 );
3192}
3193
3194void Canvas::speakCell(TQWidget* w, const TQPoint& p, uint flags)
3195{
3196 Q_UNUSED(flags);
3197 if (w != this) return;
3198 Sheet* sheet = activeSheet();
3199 if (!sheet) return;
3200 int row = -1;
3201 int col = -1;
3202 if (p == TQPoint()) {
3203 row = markerRow();
3204 col = markerColumn();
3205 if (row == d->prevSpokenFocusRow && col == d->prevSpokenFocusCol) return;
3206 d->prevSpokenFocusRow = row;
3207 d->prevSpokenFocusCol = col;
3208 } else {
3209 TQPoint wp = w->mapFromGlobal(p);
3210 double tmp;
3211 double posX;
3212 if ( sheet->layoutDirection()==Sheet::RightToLeft )
3213 {
3214 double dwidth = d->view->doc()->unzoomItX( width() );
3215 posX = dwidth - d->view->doc()->unzoomItX( wp.x() );
3216 }
3217 else
3218 posX = d->view->doc()->unzoomItX( wp.x() );
3219
3220 double posY = d->view->doc()->unzoomItY( wp.y() );
3221 col = sheet->leftColumn( (posX + xOffset()), tmp );
3222 row = sheet->topRow( (posY + yOffset()), tmp );
3223 if (row == d->prevSpokenPointerRow && col == d->prevSpokenPointerCol) return;
3224 d->prevSpokenPointerRow = row;
3225 d->prevSpokenPointerCol = col;
3226 }
3227 if (row == d->prevSpokenRow && col == d->prevSpokenCol) return;
3228 d->prevSpokenRow = row;
3229 d->prevSpokenCol = col;
3230 // kdDebug() << "Canvas::speakCell: row = " << row << " col = " << col << endl;
3231 if (row >=0 && col >= 0) {
3232 Cell* cell = sheet->cellAt( col, row );
3233 if (!cell) return;
3234 TQString text = cell->strOutText();
3235 if (!text.isEmpty()) {
3236 text.prepend(i18n("Spreadsheet cell", "Cell ") + cell->name() + " ");
3237 if (cell->isFormula()) {
3238 TQString f = cell->text();
3239 // Try to format the formula so synth can more clearly speak it.
3240 TQString f2;
3241 for (uint i = 0; i < f.length(); i++) f2 += f[i] + " ";
3242 f2.replace("(", i18n("character (", "left paren"));
3243 f2.replace(")", i18n("character )", "right paren"));
3244 f2.replace(":", i18n("character :", "colon"));
3245 f2.replace(";", i18n("character ;", "semicolon"));
3246 f2.replace("=", i18n("character =", "equals"));
3247 f2.replace(".", i18n("character .", "point"));
3248 f2.replace(",", i18n("character ,", "comma"));
3249 f2.replace(" . . ", i18n("characters ..", " dot dot "));
3250 text.append(i18n("Spreadsheet formula", " Formula ") + f2);
3251 }
3252 // kdDebug() << "Canvas::speakCell: text = " << text << endl;
3253 kospeaker->sayWidget(text);
3254 }
3255 }
3256}
3257
3259{
3260 switch( static_cast<int>( offset / 20 ) )
3261 {
3262 case 0: return 5.0;
3263 case 1: return 20.0;
3264 case 2: return d->view->doc()->unzoomItX( width() );
3265 case 3: return d->view->doc()->unzoomItX( width() );
3266 default: return d->view->doc()->unzoomItX( (int) (width() * 5.0) );
3267 }
3268}
3269
3271{
3272 switch( static_cast<int>( offset / 20 ) )
3273 {
3274 case 0: return 5.0;
3275 case 1: return 20.0;
3276 case 2: return d->view->doc()->unzoomItY( height() );
3277 case 3: return d->view->doc()->unzoomItY( height() );
3278 default: return d->view->doc()->unzoomItY( (int) (height() * 5.0) );
3279 }
3280}
3281
3282
3283KSpread::EmbeddedObject *Canvas::getObject( const TQPoint &pos, Sheet *_sheet )
3284{
3285 TQPoint const p ( (int) pos.x() ,
3286 (int) pos.y() );
3287
3288 TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
3289 for( ; itObject.current(); ++itObject )
3290 {
3291 if ( itObject.current()->sheet() == _sheet )
3292 {
3293 KoRect const bound = ( itObject.current() )->geometry();
3294 TQRect zoomedBound = doc()->zoomRect( KoRect(bound.left(), bound.top(),
3295 bound.width(),
3296 bound.height() ) );
3297 zoomedBound.moveBy( (int)( -xOffset() * doc()->zoomedResolutionX() ), (int)( -yOffset() * doc()->zoomedResolutionY() ) );
3298 if ( zoomedBound.contains( p ) )
3299 return itObject.current();
3300 }
3301 }
3302 return 0;
3303}
3304
3305void Canvas::selectObject( EmbeddedObject *obj )
3306{
3307 if ( obj->sheet() != activeSheet() || obj->isSelected() )
3308 return;
3309 obj->setSelected( true );
3310 repaintObject( obj );
3311
3312 d->mouseSelectedObject = true;
3313 emit objectSelectedChanged();
3314 deleteEditor( true );
3315}
3316
3317void Canvas::deselectObject( EmbeddedObject *obj )
3318{
3319 if ( obj->sheet() != activeSheet() || !obj->isSelected() )
3320 return;
3321 obj->setSelected( false );
3322 repaintObject( obj );
3323
3324 d->mouseSelectedObject = false;
3325 emit objectSelectedChanged();
3326}
3327
3328void Canvas::selectAllObjects()
3329{
3330 TQPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
3331 for ( ; it.current() ; ++it )
3332 {
3333 if ( it.current()->sheet() == activeSheet() )
3334 it.current()->setSelected( true );
3335 }
3336
3337 d->mouseSelectedObject = true;
3338// emit objectSelectedChanged();
3339}
3340
3341void Canvas::deselectAllObjects()
3342{
3343 if( activeSheet()->numSelected() == 0 )
3344 return;
3345
3346 //lowerObject();
3347
3348 TQPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
3349 for ( ; it.current() ; ++it )
3350 deselectObject( it.current() );
3351
3352 d->mouseSelectedObject = false;
3353// emit objectSelectedChanged();
3354}
3355
3356
3357
3358void Canvas::setMouseSelectedObject(bool b)
3359{
3360 d->mouseSelectedObject = b;
3361 emit objectSelectedChanged();
3362}
3363
3364bool Canvas::isObjectSelected()
3365{
3366 return d->mouseSelectedObject;
3367}
3368
3369
3370void Canvas::moveObjectsByMouse( KoPoint &pos, bool keepXorYunchanged )
3371{
3372 KoRect rect( objectRect( false ) );
3373 KoPoint move( 0, 0 );
3374 double diffx = pos.x() - d->m_origMousePos.x();
3375 double diffy = pos.y() - d->m_origMousePos.y();
3376
3377 move = KoPoint( diffx, diffy );
3378 d->m_origMousePos = pos;
3379
3380 // unwind last snapping
3381 KoRect movedRect( rect );
3382 movedRect.moveBy( diffx, diffy );
3383
3384 // don't move object off canvas
3385 KoPoint diffDueToBorders(0,0);
3386// KoRect pageRect( m_activePage->getPageRect() );
3387 if ( rect.left() + move.x() < 0/*pageRect.left()*/ )
3388 diffDueToBorders.setX( -rect.left() - move.x() );
3389// else if ( rect.right() + move.x() > pageRect.right() )
3390// diffDueToBorders.setX( pageRect.right() - (rect.right() + move.x()) );
3391
3392
3393 //kdDebug() << "rect.top() + move.y():" << rect.top() + move.y()<< endl;
3394 if ( rect.top() + move.y() < 0 )
3395 diffDueToBorders.setY( -rect.top() - move.y() );
3396// else if ( rect.bottom() + move.y() > pageRect.bottom() )
3397// diffDueToBorders.setY( pageRect.bottom() - (rect.bottom() + move.y()) );
3398
3399// m_moveSnapDiff += diffDueToBorders;
3400 move += diffDueToBorders;
3401
3402// movedRect.moveBy( m_moveSnapDiff.x(), m_moveSnapDiff.y() );
3403 if ( keepXorYunchanged )
3404 {
3405 KoPoint diff( d->m_moveStartPosMouse - movedRect.topLeft() );
3406 if ( fabs( diff.x() ) > fabs( diff.y() ) )
3407 {
3408// m_moveSnapDiff.setY( /*m_moveSnapDiff.y() + */m_moveStartPosMouse.y() - movedRect.y() );
3409 movedRect.moveTopLeft( KoPoint( movedRect.x(), d->m_moveStartPosMouse.y() ) );
3410 move.setY( movedRect.y() - rect.y() );
3411 }
3412 else
3413 {
3414// m_moveSnapDiff.setX( /*m_moveSnapDiff.x() + */m_moveStartPosMouse.x() - movedRect.x() );
3415 movedRect.moveTopLeft( KoPoint( d->m_moveStartPosMouse.x(), movedRect.y() ) );
3416 move.setX( movedRect.x() - rect.x() );
3417 }
3418 }
3419
3420 if ( move != KoPoint( 0, 0 ) )
3421 {
3422 //kdDebug(33001) << "moveObjectsByMouse move = " << move << endl;
3423 activeSheet()->moveObject( view(), move, false );
3424 }
3425}
3426
3427
3428void Canvas::resizeObject( ModifyType _modType, const KoPoint & point, bool keepRatio )
3429{
3430 EmbeddedObject *obj = d->m_resizeObject;
3431
3432 KoRect objRect = obj->geometry();
3433 objRect.moveBy( -xOffset(), -yOffset() );
3434 TQRect oldBoundingRect( doc()->zoomRect( objRect ) );
3435
3436 bool left = false;
3437 bool right = false;
3438 bool top = false;
3439 bool bottom = false;
3440 if ( _modType == MT_RESIZE_UP || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_RU )
3441 {
3442 top = true;
3443// snapStatus |= KoGuides::SNAP_HORIZ;
3444 }
3445 if ( _modType == MT_RESIZE_DN || _modType == MT_RESIZE_LD || _modType == MT_RESIZE_RD )
3446 {
3447 bottom = true;
3448// snapStatus |= KoGuides::SNAP_HORIZ;
3449 }
3450 if ( _modType == MT_RESIZE_LF || _modType == MT_RESIZE_LU || _modType == MT_RESIZE_LD )
3451 {
3452 left = true;
3453// snapStatus |= KoGuides::SNAP_VERT;
3454 }
3455 if ( _modType == MT_RESIZE_RT || _modType == MT_RESIZE_RU || _modType == MT_RESIZE_RD )
3456 {
3457 right = true;
3458// snapStatus |= KoGuides::SNAP_VERT;
3459 }
3460
3461 double newLeft = objRect.left();
3462 double newRight = objRect.right();
3463 double newTop = objRect.top();
3464 double newBottom = objRect.bottom();
3465 if ( top )
3466 {
3467 if ( point.y() < objRect.bottom() - MIN_SIZE )
3468 {
3469 newTop = point.y();
3470 }
3471 else
3472 {
3473 newTop = objRect.bottom() - MIN_SIZE;
3474 }
3475 }
3476 if ( bottom )
3477 {
3478 if ( point.y() > objRect.top() + MIN_SIZE )
3479 {
3480 newBottom = point.y();
3481 }
3482 else
3483 {
3484 newBottom = objRect.top() + MIN_SIZE;
3485 }
3486 }
3487 if ( left )
3488 {
3489 if ( point.x() < objRect.right() - MIN_SIZE )
3490 {
3491 newLeft = point.x();
3492 }
3493 else
3494 {
3495 newLeft = objRect.right() - MIN_SIZE;
3496 }
3497 }
3498 if ( right )
3499 {
3500 if ( point.x() > objRect.left() + MIN_SIZE )
3501 {
3502 newRight = point.x();
3503 }
3504 else
3505 {
3506 newRight = objRect.left() + MIN_SIZE;
3507 }
3508 }
3509
3510 double width = newRight - newLeft;
3511 double height = newBottom - newTop;
3512
3513 if ( keepRatio && d->m_ratio != 0 )
3514 {
3515 if ( ( top || bottom ) && ( right || left ) )
3516 {
3517 if ( height * height * d->m_ratio > width * width / d->m_ratio )
3518 {
3519 width = height * d->m_ratio;
3520 }
3521 else
3522 {
3523 height = width / d->m_ratio;
3524 }
3525 }
3526 else if ( top || bottom )
3527 {
3528 width = height * d->m_ratio;
3529 }
3530 else
3531 {
3532 height = width / d->m_ratio;
3533 }
3534
3535 if ( top )
3536 {
3537 newTop = objRect.bottom() - height;
3538 }
3539 else
3540 {
3541 newBottom = objRect.top() + height;
3542 }
3543 if ( left )
3544 {
3545 newLeft = objRect.right() - width;
3546 }
3547 else
3548 {
3549 newRight = objRect.right() + width;
3550 }
3551 }
3552
3553 if ( newLeft != objRect.left() || newRight != objRect.right() || newTop != objRect.top() || newBottom != objRect.bottom() )
3554 {
3555 // resizeBy and moveBy have to been used to make it work with rotated objects
3556 obj->resizeBy( width - objRect.width(), height - objRect.height() );
3557
3558 if ( objRect.left() != newLeft || objRect.top() != newTop )
3559 {
3560 obj->moveBy( KoPoint( newLeft - objRect.left(), newTop - objRect.top() ) );
3561 }
3562
3563// if ( doc()->showGuideLines() && !m_disableSnapping )
3564// {
3565// KoRect rect( obj->getRealRect() );
3566// KoPoint sp( rect.topLeft() );
3567// if ( right )
3568// {
3569// sp.setX( rect.right() );
3570// }
3571// if ( bottom )
3572// {
3573// sp.setY( rect.bottom() );
3574// }
3575// m_gl.repaintSnapping( sp, snapStatus );
3576// }
3577
3578 repaint( oldBoundingRect );
3579 repaintObject( obj );
3580 emit objectSizeChanged();
3581 }
3582}
3583
3584
3585void Canvas::finishResizeObject( const TQString &/*name*/, bool /*layout*/ )
3586{
3587 if ( d->m_resizeObject )
3588 {
3589 KoPoint move = KoPoint( d->m_resizeObject->geometry().x() - d->m_rectBeforeResize.x(),
3590 d->m_resizeObject->geometry().y() - d->m_rectBeforeResize.y() );
3591 KoSize size = KoSize( d->m_resizeObject->geometry().width() - d->m_rectBeforeResize.width(),
3592 d->m_resizeObject->geometry().height() - d->m_rectBeforeResize.height() );
3593
3594 if ( ( d->m_resizeObject->geometry() ) != d->m_rectBeforeResize )
3595 {
3596 ChangeObjectGeometryCommand *resizeCmd = new ChangeObjectGeometryCommand( d->m_resizeObject, move, size );
3597 // the command is not executed as the object is allready resized.
3598 doc()->addCommand( resizeCmd );
3599 }
3600
3601// if ( layout )
3602// doc()->layout( m_resizeObject );
3603
3604 d->m_ratio = 0.0;
3605 d->m_isResizing = false;
3606 repaintObject( d->m_resizeObject );
3607 d->m_resizeObject = NULL;
3608 }
3609}
3610
3612{
3613 if ( doc()->embeddedObjects().count() <= 1 )
3614 return;
3615
3616 if ( d->m_objectDisplayAbove == 0 )
3617 {
3618 if ( activeSheet()->numSelected() == 1 )
3619 {
3620 d->m_objectDisplayAbove = object;
3621 }
3622 }
3623}
3624
3626{
3627 d->m_objectDisplayAbove = 0;
3628}
3629
3630void Canvas::displayObjectList( TQPtrList<EmbeddedObject> &list )
3631{
3632 list = doc()->embeddedObjects();
3633 list.setAutoDelete( false );
3634
3635 if ( d->m_objectDisplayAbove )
3636 {
3637 // it can happen that the object is no longer there e.g. when
3638 // the insert of the object is undone
3639 int pos = doc()->embeddedObjects().findRef( d->m_objectDisplayAbove );
3640 if ( pos != -1 && d->m_objectDisplayAbove->isSelected() )
3641 {
3642 list.take( pos );
3643 list.append( d->m_objectDisplayAbove );
3644 }
3645 else
3646 {
3647 //tz not possible due to const. should const be removed?
3648 //m_objectDisplayAbove = 0;
3649 }
3650 }
3651}
3652
3653
3654KoRect Canvas::objectRect( bool all ) const
3655{
3656 return activeSheet()->getRealRect( all );
3657}
3658
3659void Canvas::deleteEditor (bool saveChanges, bool array)
3660{
3661 if ( !d->cellEditor )
3662 return;
3663
3664
3665 //There may be highlighted areas on the sheet which will need to be erased
3666 setSelectionChangePaintDirty( activeSheet() , *choice() );
3667
3668 d->editWidget->setEditMode( false );
3669
3670 TQString t = d->cellEditor->text();
3671 // Delete the cell editor first and after that update the document.
3672 // That means we get a synchronous repaint after the cell editor
3673 // widget is gone. Otherwise we may get painting errors.
3674 delete d->cellEditor;
3675 d->cellEditor = 0;
3676
3677 if ( saveChanges )
3678 {
3679 if ( t.at(0)=='=' )
3680 {
3681 //a formula
3682 int openParenthese = t.contains('(' );
3683 int closeParenthese = t.contains(')' );
3684 int diff = TQABS( openParenthese - closeParenthese );
3685 if ( openParenthese > closeParenthese )
3686 {
3687 for (int i=0; i < diff;i++)
3688 {
3689 t=t+')';
3690 }
3691 }
3692 }
3693 d->view->setText (t, array);
3694 }
3695 else
3696 {
3697 d->view->updateEditWidget();
3698 }
3699
3700 setFocus();
3701}
3702
3703
3704void Canvas::createEditor(bool captureArrowKeys)
3705{
3706 if (!activeSheet())
3707 return;
3708
3709 Cell * cell = activeSheet()->nonDefaultCell( markerColumn(), markerRow(), false );
3710
3711 if ( !createEditor( CellEditor , true , captureArrowKeys ) )
3712 return;
3713 if ( cell )
3714 d->cellEditor->setText( cell->text() );
3715}
3716
3717bool Canvas::createEditor( EditorType ed, bool addFocus, bool captureArrowKeys )
3718{
3719 Sheet * sheet = activeSheet();
3720
3721 // Set the starting sheet of the choice.
3722 choice()->setSheet( activeSheet() );
3723
3724 if ( !d->cellEditor )
3725 {
3726 Cell * cell = sheet->nonDefaultCell( marker().x(), marker().y(), false );
3727
3728 if ( sheet->isProtected() && !cell->format()->notProtected( marker().x(), marker().y() ) )
3729 return false;
3730
3731 if ( ed == CellEditor )
3732 {
3733 d->editWidget->setEditMode( true );
3734 d->cellEditor = new KSpread::CellEditor( cell, this, captureArrowKeys );
3735 }
3736
3737 double w, h;
3738 double min_w = cell->dblWidth( markerColumn() );
3739 double min_h = cell->dblHeight( markerRow() );
3740 if ( cell->isDefault() )
3741 {
3742 w = min_w;
3743 h = min_h;
3744 //kdDebug(36001) << "DEFAULT" << endl;
3745 }
3746 else
3747 {
3748 w = cell->extraWidth();
3749 h = cell->extraHeight();
3750 //kdDebug(36001) << "HEIGHT=" << min_h << " EXTRA=" << h << endl;
3751 }
3752
3753 double xpos = sheet->dblColumnPos( markerColumn() ) - xOffset();
3754
3755 Sheet::LayoutDirection sheetDir = sheet->layoutDirection();
3756 bool rtlText = cell->strOutText().isRightToLeft();
3757
3758 // if sheet and cell direction don't match, then the editor's location
3759 // needs to be shifted backwards so that it's right above the cell's text
3760 if ( w > 0 && ( ( sheetDir == Sheet::RightToLeft && !rtlText ) ||
3761 ( sheetDir == Sheet::LeftToRight && rtlText ) ) )
3762 xpos -= w - min_w;
3763
3764 // paint editor above correct cell if sheet direction is RTL
3765 if ( sheetDir == Sheet::RightToLeft )
3766 {
3767 double dwidth = d->view->doc()->unzoomItX( width() );
3768 double w2 = TQMAX( w, min_w );
3769 xpos = dwidth - w2 - xpos;
3770 }
3771
3772 double ypos = sheet->dblRowPos( markerRow() ) - yOffset();
3773 TQPalette p = d->cellEditor->palette();
3774 TQColorGroup g( p.active() );
3775
3776 TQColor color = cell->format()->textColor( markerColumn(), markerRow() );
3777 if ( !color.isValid() )
3778 color = TQApplication::palette().active().text();
3779 g.setColor( TQColorGroup::Text, color);
3780
3781 color = cell->bgColor( markerColumn(), markerRow() );
3782 if ( !color.isValid() )
3783 color = g.base();
3784 g.setColor( TQColorGroup::Background, color );
3785
3786 d->cellEditor->setPalette( TQPalette( g, p.disabled(), g ) );
3787 TQFont tmpFont = cell->format()->textFont( markerColumn(), markerRow() );
3788 tmpFont.setPointSizeFloat( 0.01 * d->view->doc()->zoom() * tmpFont.pointSizeFloat() );
3789 d->cellEditor->setFont( tmpFont );
3790
3791 KoRect rect( xpos, ypos, w, h ); //needed to circumvent rounding issue with height/width
3792
3793
3794 TQRect zoomedRect=d->view->doc()->zoomRect( rect );
3795 /*zoomedRect.setLeft(zoomedRect.left()-2);
3796 zoomedRect.setRight(zoomedRect.right()+4);
3797 zoomedRect.setTop(zoomedRect.top()-1);
3798 zoomedRect.setBottom(zoomedRect.bottom()+2);*/
3799
3800 d->cellEditor->setGeometry( zoomedRect );
3801 d->cellEditor->setMinimumSize( TQSize( d->view->doc()->zoomItX( min_w ), d->view->doc()->zoomItY( min_h ) ) );
3802 d->cellEditor->show();
3803 //kdDebug(36001) << "FOCUS1" << endl;
3804 //Laurent 2001-12-05
3805 //Don't add focus when we create a new editor and
3806 //we select text in edit widget otherwise we don't delete
3807 //selected text.
3808 // startChoose();
3809
3810 if ( addFocus )
3811 d->cellEditor->setFocus();
3812
3813 setSelectionChangePaintDirty(sheet, *selectionInfo());
3814 paintUpdates();
3815 }
3816
3817 return true;
3818}
3819
3820void Canvas::repaintObject( EmbeddedObject *obj )
3821{
3822 //Calculate where the object appears on the canvas widget and then repaint that part of the widget
3823 TQRect canvasRelativeGeometry = doc()->zoomRect( obj->geometry() );
3824 canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) ,
3825 (int)( -yOffset() * doc()->zoomedResolutionY()) );
3826
3827 update( canvasRelativeGeometry );
3828
3829 /* if ( !obj->isSelected() )
3830 {
3831 KoRect g = obj->geometry();
3832 g.moveBy( -xOffset(), -yOffset() );
3833 TQRect geometry( doc()->zoomRect( g ) );
3834
3835 update( geometry );
3836 }
3837 else
3838 {
3839 TQPainter p(this);
3840 p.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() );
3841 obj->draw(&p); //this goes faster than calling repaint
3842 p.end();
3843 }*/
3844}
3845
3847{
3848 // We'll create a store (ZIP format) in memory
3849 TQBuffer buffer;
3850 TQCString mimeType = "application/vnd.oasis.opendocument.spreadsheet";
3851 KoStore* store = KoStore::createStore( &buffer, KoStore::Write, mimeType );
3852 Q_ASSERT( store );
3853 Q_ASSERT( !store->bad() );
3854 KoOasisStore oasisStore( store );
3855
3856 KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
3857
3858 TQString plainText;
3859 KoPicture picture;
3860 if ( !doc()->saveOasisHelper( store, manifestWriter, Doc::SaveSelected, &plainText, &picture )
3861 || !oasisStore.closeManifestWriter() )
3862 {
3863 delete store;
3864 return;
3865 }
3866 delete store;
3867
3868 KMultipleDrag* multiDrag = new KMultipleDrag();
3869 if ( !plainText.isEmpty() )
3870 multiDrag->addDragObject( new TQTextDrag( plainText, 0 ) );
3871 if ( !picture.isNull() )
3872 multiDrag->addDragObject( picture.dragObject( 0 ) );
3873 KoStoreDrag* storeDrag = new KoStoreDrag( mimeType, 0 );
3874 kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl;
3875 storeDrag->setEncodedData( buffer.buffer() );
3876 multiDrag->addDragObject( storeDrag );
3877
3878 //save the objects as pictures too so that other programs can access them
3879 TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
3880 itObject.toFirst();
3881 if ( itObject.current() )
3882 {
3883 KoRect kr = objectRect(false);
3884 TQRect r( kr.toTQRect() );
3885 TQPixmap pixmap( r.width(), r.height() );
3886 pixmap.fill( "white" );
3887 TQPainter p(&pixmap);
3888 for( ; itObject.current(); ++itObject )
3889 {
3890 if ( itObject.current()->isSelected() )
3891 p.drawPixmap( itObject.current()->geometry().toTQRect().left() - r.left(), itObject.current()->geometry().toTQRect().top() - r.top(), itObject.current()->toPixmap( 1.0 , 1.0 ) );
3892 }
3893 p.end();
3894 if (!pixmap.isNull())
3895 {
3896 TQImageDrag *imagedrag = new TQImageDrag( pixmap.convertToImage() );
3897 multiDrag->addDragObject( imagedrag );
3898 }
3899 }
3900
3901 TQDragObject *dragObject = multiDrag;
3902 TQApplication::clipboard()->setData( dragObject, TQClipboard::Clipboard );
3903}
3904
3906{
3907 if ( d->chooseCell )
3908 return;
3909
3910 if ( d->cellEditor )
3911 {
3912 deleteEditor( true ); // save changes
3913 }
3914}
3915
3916void Canvas::updateEditor()
3917{
3918 if (!d->chooseCell)
3919 return;
3920
3921 Sheet* sheet = activeSheet();
3922 if (!sheet)
3923 return;
3924
3925 if (d->cellEditor)
3926 {
3927 if (choice()->sheet() != sheet)
3928 {
3929 d->cellEditor->hide();
3930 }
3931 else
3932 {
3933 d->cellEditor->show();
3934 }
3935 d->cellEditor->updateChoice();
3936 }
3937}
3938
3939void Canvas::setSelectionChangePaintDirty(Sheet* sheet, const Region& region)
3940{
3941 sheet->setRegionPaintDirty(region); // TODO should the paintDirtyList be in Canvas?
3942}
3943
3944
3946{
3947 TQString buffer;
3948 // No selection, or only one cell merged selected
3949 if ( selectionInfo()->isSingular() )
3950 {
3951 if (activeSheet()->getLcMode())
3952 {
3953 buffer = "L" + TQString::number( markerRow() ) +
3954 "C" + TQString::number( markerColumn() );
3955 }
3956 else
3957 {
3958 buffer = Cell::columnName( markerColumn() ) +
3959 TQString::number( markerRow() );
3960 }
3961 }
3962 else
3963 {
3964 if (activeSheet()->getLcMode())
3965 {
3966 buffer = TQString::number( (selectionInfo()->lastRange().bottom()-selectionInfo()->lastRange().top()+1) )+"Lx";
3967 if ( util_isRowSelected( selectionInfo()->lastRange() ) )
3968 buffer+=TQString::number((KS_colMax-selectionInfo()->lastRange().left()+1))+"C";
3969 else
3970 buffer+=TQString::number((selectionInfo()->lastRange().right()-selectionInfo()->lastRange().left()+1))+"C";
3971 }
3972 else
3973 {
3974 //encodeColumnLabelText return @@@@ when column >KS_colMax
3975 //=> it's not a good display
3976 //=> for the moment I display pos of marker
3977 buffer=Cell::columnName( selectionInfo()->lastRange().left() ) +
3978 TQString::number(selectionInfo()->lastRange().top()) + ":" +
3979 Cell::columnName( TQMIN( KS_colMax, selectionInfo()->lastRange().right() ) ) +
3980 TQString::number(selectionInfo()->lastRange().bottom());
3981 //buffer=activeSheet()->columnLabel( m_iMarkerColumn );
3982 //buffer+=tmp.setNum(m_iMarkerRow);
3983 }
3984 }
3985
3986 if (buffer != d->posWidget->lineEdit()->text())
3987 d->posWidget->lineEdit()->setText(buffer);
3988}
3989
3990void Canvas::equalizeRow()
3991{
3992 TQRect s( selection() );
3993 RowFormat *rl = d->view->activeSheet()->rowFormat(s.top());
3994 int size=rl->height(this);
3995 if ( s.top() == s.bottom() )
3996 return;
3997 for(int i=s.top()+1;i<=s.bottom();i++)
3998 {
3999 Sheet *sheet = activeSheet();
4000 if ( !sheet )
4001 return;
4002 size=TQMAX(d->view->activeSheet()->rowFormat(i)->height(this),size);
4003 }
4004 d->view->vBorderWidget()->equalizeRow(size);
4005}
4006
4007void Canvas::equalizeColumn()
4008{
4009 TQRect s( selection() );
4010 ColumnFormat *cl = d->view->activeSheet()->columnFormat(s.left());
4011 int size=cl->width(this);
4012 if ( s.left() == s.right() )
4013 return;
4014
4015 for(int i=s.left()+1;i<=s.right();i++)
4016 {
4017 size=TQMAX(d->view->activeSheet()->columnFormat(i)->width(this),size);
4018 }
4019 d->view->hBorderWidget()->equalizeColumn(size);
4020}
4021
4022TQRect Canvas::cellsInArea( const TQRect area ) const
4023{
4024 KoRect unzoomedRect = d->view->doc()->unzoomRect( area );
4025
4026 unzoomedRect.moveBy( (int)xOffset(), (int)yOffset() );
4027
4028 double tmp;
4029 int left_col = activeSheet()->leftColumn( unzoomedRect.left(), tmp );
4030 int right_col = activeSheet()->rightColumn( unzoomedRect.right() );
4031 int top_row = activeSheet()->topRow( unzoomedRect.top(), tmp );
4032 int bottom_row = activeSheet()->bottomRow( unzoomedRect.bottom() );
4033
4034 return TQRect( left_col, top_row,
4035 right_col - left_col + 1, bottom_row - top_row + 1 );
4036}
4037
4039{
4040 return cellsInArea( TQRect(0,0,width(),height()) );
4041
4042}
4043
4044
4045//---------------------------------------------
4046//
4047// Drawing Engine
4048//
4049//---------------------------------------------
4050
4052{
4053 if (activeSheet() == NULL)
4054 return;
4055
4056 TQPainter painter(this);
4057
4058 //Save clip region
4059 TQRegion rgnComplete( painter.clipRegion() );
4060 TQWMatrix matrix;
4061 if ( d->view )
4062 {
4063 matrix = d->view->matrix();
4064 }
4065 else
4066 {
4067 matrix = painter.worldMatrix();
4068 }
4069
4070
4071 paintChildren( painter, matrix );
4072
4073 painter.save();
4074 clipoutChildren( painter );
4075
4076 KoRect unzoomedRect = d->view->doc()->unzoomRect( TQRect( 0, 0, width(), height() ) );
4077 // unzoomedRect.moveBy( xOffset(), yOffset() );
4078
4079
4080 /* paint any visible cell that has the paintDirty flag */
4081 TQRect range = visibleCells();
4082 Cell* cell = NULL;
4083
4084 double topPos = activeSheet()->dblRowPos(range.top());
4085 double leftPos = activeSheet()->dblColumnPos(range.left());
4086
4087 KoPoint dblCorner( leftPos - xOffset(), topPos - yOffset() );
4088
4089 int x;
4090 int y;
4091
4092 int right = range.right();
4093 int bottom = range.bottom();
4094 Sheet * sheet = activeSheet();
4095
4096#if 0
4097 kdDebug(36001)
4098 << "================================================================"
4099 << endl;
4100 kdDebug(36001) << "painting dirty cells " << endl;
4101#endif
4102
4103 TQValueList<TQPoint> mergedCellsPainted;
4104 for ( x = range.left(); x <= right; ++x )
4105 {
4106 for ( y = range.top(); y <= bottom; ++y )
4107 {
4108 if ( sheet->cellIsPaintDirty( TQPoint( x, y ) ) )
4109 {
4110 cell = sheet->cellAt( x, y );
4111
4112 // recalc and relayout only for non default cells
4113 if (!cell->isDefault())
4114 {
4115 if (cell->calcDirtyFlag()) cell->calc();
4116 if (cell->layoutDirtyFlag()) cell->makeLayout( painter, x, y );
4117 }
4118
4119 /* bool paintBordersBottom = false;
4120 bool paintBordersRight = false;
4121 bool paintBordersLeft = false;
4122 bool paintBordersTop = false; */
4123
4124 int paintBorder=Cell::Border_None;
4125
4126 TQPen bottomPen( cell->effBottomBorderPen( x, y ) );
4127 TQPen rightPen( cell->effRightBorderPen( x, y ) );
4128 TQPen leftPen( cell->effLeftBorderPen( x, y ) );
4129 TQPen topPen( cell->effTopBorderPen( x, y ) );
4130
4131 // paint right border
4132 // - if rightmost cell
4133 // - if the pen is more "worth" than the left border pen of the cell
4134 // on the left
4135 if ( x >= KS_colMax )
4136 {
4137 paintBorder |= Cell::Border_Right;
4138 }
4139 else
4140 {
4141 paintBorder |= Cell::Border_Right;
4142 if ( cell->effRightBorderValue( x, y ) <
4143 sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) )
4144 rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y );
4145 }
4146
4147 // similiar for other borders...
4148 // bottom border:
4149 if ( y >= KS_rowMax )
4150 {
4151 paintBorder |= Cell::Border_Bottom;
4152 }
4153 else
4154 {
4155 paintBorder |= Cell::Border_Bottom;
4156 if ( cell->effBottomBorderValue( x, y ) <
4157 sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1 ) )
4158 bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 );
4159 }
4160
4161 // left border:
4162 if ( x == 1 )
4163 {
4164 paintBorder |= Cell::Border_Left;
4165 }
4166 else
4167 {
4168 paintBorder |= Cell::Border_Left;
4169 if ( cell->effLeftBorderValue( x, y ) <
4170 sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) )
4171 leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y );
4172 }
4173
4174 // top border:
4175 if ( y == 1 )
4176 {
4177 paintBorder |= Cell::Border_Top;
4178 }
4179 else
4180 {
4181 paintBorder |= Cell::Border_Top;
4182 if ( cell->effTopBorderValue( x, y ) <
4183 sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) )
4184 topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 );
4185 }
4186
4187 cell->paintCell( unzoomedRect, painter, d->view, dblCorner,
4188 TQPoint( x, y), paintBorder,
4189 rightPen,bottomPen,leftPen,topPen,
4190 mergedCellsPainted);
4191 }
4192 dblCorner.setY( dblCorner.y() + sheet->rowFormat( y )->dblHeight( ) );
4193 }
4194 dblCorner.setY( topPos - yOffset() );
4195 dblCorner.setX( dblCorner.x() + sheet->columnFormat( x )->dblWidth( ) );
4196 }
4197
4198 /* now paint the selection */
4199 //Nb. No longer necessary to paint choose selection here as the cell reference highlight
4200 //stuff takes care of this anyway
4201
4202 paintHighlightedRanges(painter, unzoomedRect);
4203 paintNormalMarker(painter, unzoomedRect);
4204
4205 //restore clip region with children area
4206 painter.restore();
4207 //painter.setClipRegion( rgnComplete );
4208}
4209
4210
4211
4212void Canvas::clipoutChildren( TQPainter& painter ) const
4213{
4214 TQRegion rgn = painter.clipRegion();
4215 if ( rgn.isEmpty() )
4216 rgn = TQRegion( TQRect( 0, 0, width(), height() ) );
4217
4218 const double horizontalOffset = -xOffset() * doc()->zoomedResolutionX();
4219 const double verticalOffset = -yOffset() * doc()->zoomedResolutionY();
4220
4221 TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
4222 for( ; itObject.current(); ++itObject )
4223 {
4224 if ( ( itObject.current() )->sheet() == activeSheet() )
4225 {
4226 TQRect childGeometry = doc()->zoomRect( itObject.current()->geometry());
4227
4228 //The clipping region is given in device coordinates
4229 //so subtract the current offset (scroll position) of the canvas
4230 childGeometry.moveBy( (int)horizontalOffset , (int)verticalOffset );
4231
4232 if (painter.window().intersects(childGeometry))
4233 rgn -= childGeometry;
4234
4235 //painter.fillRect( doc()->zoomRect( itObject.current()->geometry() ), TQColor("red" ) );
4236 }
4237 }
4238
4239 painter.setClipRegion( rgn );
4240}
4241
4242TQRect Canvas::painterWindowGeometry( const TQPainter& painter ) const
4243{
4244 TQRect zoomedWindowGeometry = painter.window();
4245
4246 zoomedWindowGeometry.moveBy( (int)( xOffset() * doc()->zoomedResolutionX() ) , (int)( yOffset() * doc()->zoomedResolutionY() ) );
4247
4248 return zoomedWindowGeometry;
4249}
4250
4251void Canvas::paintChildren( TQPainter& painter, TQWMatrix& /*matrix*/ )
4252{
4253 TQPtrListIterator<EmbeddedObject> itObject( doc()->embeddedObjects() );
4254 itObject.toFirst();
4255 if ( !itObject.current() )
4256 return;
4257
4258 painter.save();
4259 painter.translate( -xOffset() * doc()->zoomedResolutionX() , -yOffset() * doc()->zoomedResolutionY() );
4260
4261 const TQRect zoomedWindowGeometry = painterWindowGeometry( painter );
4262 const Sheet* sheet = activeSheet();
4263
4264 for( ; itObject.current(); ++itObject )
4265 {
4266 TQRect const zoomedObjectGeometry = doc()->zoomRect( itObject.current()->geometry() );
4267 if ( ( itObject.current() )->sheet() == activeSheet() &&
4268 zoomedWindowGeometry.intersects( zoomedObjectGeometry ) )
4269 {
4270 //To prevent unnecessary redrawing of the embedded object, we only repaint
4271 //if one or more of the cells underneath the object has been marked as 'dirty'.
4272
4273 TQRect canvasRelativeGeometry = zoomedObjectGeometry;
4274 canvasRelativeGeometry.moveBy( (int)( -xOffset()*doc()->zoomedResolutionX() ) ,
4275 (int)( -yOffset() * doc()->zoomedResolutionY()) );
4276
4277 const TQRect cellsUnderObject=cellsInArea( canvasRelativeGeometry );
4278 bool redraw=false;
4279
4280 for (int x=cellsUnderObject.left();x<=cellsUnderObject.right();x++)
4281 {
4282 for (int y=cellsUnderObject.top();y<=cellsUnderObject.bottom();y++)
4283 if ( sheet->cellIsPaintDirty( TQPoint(x,y) ) )
4284 {
4285 redraw=true;
4286 break;
4287 }
4288 if (redraw)
4289 break;
4290 }
4291
4292 if ( redraw )
4293 itObject.current()->draw( &painter );
4294 }
4295 }
4296 painter.restore();
4297}
4298
4299void Canvas::paintHighlightedRanges(TQPainter& painter, const KoRect& /*viewRect*/)
4300{
4301 TQValueList<TQColor> colors = choice()->colors();
4302 TQBrush nullBrush;
4303 int index = 0;
4304 Region::ConstIterator end(choice()->constEnd());
4305 for (Region::ConstIterator it = choice()->constBegin(); it != end; ++it)
4306 {
4307 //Only paint ranges or cells on the current sheet
4308 if ((*it)->sheet() != activeSheet())
4309 {
4310 index++;
4311 continue;
4312 }
4313
4314 TQRect region = (*it)->rect().normalize();
4315
4316 //double positions[4];
4317 //bool paintSides[4];
4318 KoRect unzoomedRect;
4319
4320 sheetAreaToVisibleRect(region,unzoomedRect);
4321 //Convert region from sheet coordinates to canvas coordinates for use with the painter
4322 //retrieveMarkerInfo(region,viewRect,positions,paintSides);
4323
4324 TQPen highlightPen( colors[(index) % colors.size()] ); // (*it)->color() );
4325 painter.setPen(highlightPen);
4326
4327 //Adjust the canvas coordinate - rect to take account of zoom level
4328
4329 TQRect zoomedRect;
4330
4331 zoomedRect.setCoords ( d->view->doc()->zoomItX(unzoomedRect.left()),
4332 d->view->doc()->zoomItY(unzoomedRect.top()),
4333 d->view->doc()->zoomItX(unzoomedRect.right()),
4334 d->view->doc()->zoomItY(unzoomedRect.bottom()) );
4335
4336 //Now adjust the highlight rectangle is slightly inside the cell borders (this means that multiple highlighted cells
4337 //look nicer together as the borders do not clash)
4338
4339 zoomedRect.setLeft(zoomedRect.left()+1);
4340 zoomedRect.setTop(zoomedRect.top()+1);
4341 zoomedRect.setRight(zoomedRect.right()-1);
4342 zoomedRect.setBottom(zoomedRect.bottom()-1);
4343
4344 painter.setBrush(nullBrush);
4345 painter.drawRect(zoomedRect);
4346
4347 //Now draw the size grip (the little rectangle on the bottom right-hand corner of the range which the user can
4348 //click and drag to resize the region)
4349
4350
4351 TQBrush sizeGripBrush( colors[(index) % colors.size()] ); // (*it)->color());
4352 TQPen sizeGripPen(TQt::white);
4353
4354 painter.setPen(sizeGripPen);
4355 painter.setBrush(sizeGripBrush);
4356
4357 painter.drawRect(zoomedRect.right()-3,zoomedRect.bottom()-3,6,6);
4358 index++;
4359 }
4360}
4361
4362void Canvas::paintNormalMarker(TQPainter& painter, const KoRect &viewRect)
4363{
4364 //Only the active element (the one with the anchor) will be drawn with a border
4365
4366 if( d->chooseCell )
4367 return;
4368
4369 if (d->cellEditor)
4370 return;
4371
4372 Region::ConstIterator end(selectionInfo()->constEnd());
4373 for (Region::ConstIterator it(selectionInfo()->constBegin()); it != end; ++it)
4374 {
4375 TQRect range = (*it)->rect().normalize();
4376
4377 double positions[4];
4378 bool paintSides[4];
4379
4380 bool current = TQRect(selectionInfo()->anchor(), selectionInfo()->marker()).normalize() == range;
4381 TQPen pen( TQt::black, 2 );
4382 painter.setPen( pen );
4383
4384 retrieveMarkerInfo( selectionInfo()->extendToMergedAreas(range), viewRect, positions, paintSides );
4385
4386 double left = positions[0];
4387 double top = positions[1];
4388 double right = positions[2];
4389 double bottom = positions[3];
4390
4391 bool paintLeft = paintSides[0];
4392 bool paintTop = paintSides[1];
4393 bool paintRight = paintSides[2];
4394 bool paintBottom = paintSides[3];
4395
4396 /* the extra '-1's thrown in here account for the thickness of the pen.
4397 want to look like this: not this:
4398 * * * * * * * * * *
4399 * * * *
4400 * * * *
4401 */
4402 int l = 1;
4403
4404 if ( paintTop )
4405 {
4406 painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( top ),
4407 d->view->doc()->zoomItX( right ) + l, d->view->doc()->zoomItY( top ) );
4408 }
4409 if ( activeSheet()->layoutDirection()==Sheet::RightToLeft )
4410 {
4411 if ( paintRight )
4412 {
4413 painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ),
4414 d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) );
4415 }
4416 if ( paintLeft && paintBottom && current )
4417 {
4418 /* then the 'handle' in the bottom left corner is visible. */
4419 painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ),
4420 d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) - 3 );
4421 painter.drawLine( d->view->doc()->zoomItX( left ) + 4, d->view->doc()->zoomItY( bottom ),
4422 d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) );
4423 painter.fillRect( d->view->doc()->zoomItX( left ) - 2, d->view->doc()->zoomItY( bottom ) -2, 5, 5,
4424 painter.pen().color() );
4425 }
4426 else
4427 {
4428 if ( paintLeft )
4429 {
4430 painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ),
4431 d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) );
4432 }
4433 if ( paintBottom )
4434 {
4435 painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ),
4436 d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ));
4437 }
4438 }
4439 }
4440 else // activeSheet()->layoutDirection()==Sheet::LeftToRight
4441 {
4442 if ( paintLeft )
4443 {
4444 painter.drawLine( d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( top ),
4445 d->view->doc()->zoomItX( left ), d->view->doc()->zoomItY( bottom ) );
4446 }
4447 if ( paintRight && paintBottom && current )
4448 {
4449 /* then the 'handle' in the bottom right corner is visible. */
4450 painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ),
4451 d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) - 3 );
4452 painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ),
4453 d->view->doc()->zoomItX( right ) - 3, d->view->doc()->zoomItY( bottom ) );
4454 painter.fillRect( d->view->doc()->zoomItX( right ) - 2, d->view->doc()->zoomItY( bottom ) - 2, 5, 5,
4455 painter.pen().color() );
4456 }
4457 else
4458 {
4459 if ( paintRight )
4460 {
4461 painter.drawLine( d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( top ),
4462 d->view->doc()->zoomItX( right ), d->view->doc()->zoomItY( bottom ) );
4463 }
4464 if ( paintBottom )
4465 {
4466 painter.drawLine( d->view->doc()->zoomItX( left ) - l, d->view->doc()->zoomItY( bottom ),
4467 d->view->doc()->zoomItX( right ) + l + 1, d->view->doc()->zoomItY( bottom ) );
4468 }
4469 }
4470 }
4471 }
4472}
4473
4474void Canvas::sheetAreaToRect(const TQRect& sheetArea, KoRect& rect)
4475{
4476 Sheet* sheet=activeSheet();
4477
4478 if ( sheet->layoutDirection()==Sheet::RightToLeft )
4479 {
4480 rect.setLeft(sheet->dblColumnPos( sheetArea.right()+1 ) );
4481 rect.setRight(sheet->dblColumnPos( sheetArea.left() ));
4482 }
4483 else
4484 {
4485 rect.setLeft(sheet->dblColumnPos( sheetArea.left() ));
4486 rect.setRight(sheet->dblColumnPos( sheetArea.right()+1 ));
4487 }
4488
4489 rect.setTop(sheet->dblRowPos(sheetArea.top()));
4490 rect.setBottom(sheet->dblRowPos(sheetArea.bottom()+1));
4491
4492}
4493
4494void Canvas::sheetAreaToVisibleRect( const TQRect& sheetArea,
4495 KoRect& visibleRect )
4496{
4497 Sheet* sheet=activeSheet();
4498
4499 if (!sheet)
4500 return;
4501
4502 double dwidth=d->view->doc()->unzoomItX(width());
4503 double xpos;
4504 double x;
4505
4506 if ( sheet->layoutDirection()==Sheet::RightToLeft )
4507 {
4508 xpos = dwidth - sheet->dblColumnPos( sheetArea.right() ) + xOffset();
4509 x = dwidth - sheet->dblColumnPos( sheetArea.left() ) + xOffset();
4510 }
4511 else
4512 {
4513 xpos = sheet->dblColumnPos( sheetArea.left() ) - xOffset();
4514 x = sheet->dblColumnPos( sheetArea.right() ) - xOffset();
4515 }
4516
4517 double ypos = sheet->dblRowPos(sheetArea.top())-yOffset();
4518
4519 const ColumnFormat *columnFormat = sheet->columnFormat( sheetArea.right() );
4520 double tw = columnFormat->dblWidth( );
4521 double w = x - xpos + tw;
4522
4523 double y = sheet->dblRowPos( sheetArea.bottom() ) - yOffset();
4524 const RowFormat* rowFormat = sheet->rowFormat( sheetArea.bottom() );
4525 double th = rowFormat->dblHeight( );
4526 double h = ( y - ypos ) + th;
4527
4528 /* left, top, right, bottom */
4529 if ( sheet->layoutDirection()==Sheet::RightToLeft )
4530 {
4531 visibleRect.setLeft(xpos - tw );
4532 visibleRect.setRight(xpos - tw + w );
4533 }
4534 else
4535 {
4536 visibleRect.setLeft(xpos );
4537 visibleRect.setRight(xpos + w );
4538 }
4539 visibleRect.setTop(ypos);
4540 visibleRect.setBottom(ypos + h);
4541}
4542
4543void Canvas::retrieveMarkerInfo( const TQRect &marker,
4544 const KoRect &viewRect,
4545 double positions[],
4546 bool paintSides[] )
4547{
4548
4549 Sheet* sheet=activeSheet();
4550
4551 if (!sheet) return;
4552
4553 KoRect visibleRect;
4554 sheetAreaToVisibleRect(marker,visibleRect);
4555
4556
4557 /* Sheet * sheet = activeSheet();
4558 if ( !sheet )
4559 return;
4560
4561 double dWidth = d->view->doc()->unzoomItX( width() );
4562
4563 double xpos;
4564 double x;
4565 if ( sheet->layoutDirection()==Sheet::RightToLeft )
4566 {
4567 xpos = dWidth - sheet->dblColumnPos( marker.right() ) + xOffset();
4568 x = dWidth - sheet->dblColumnPos( marker.left() ) + xOffset();
4569 }
4570 else
4571 {
4572 xpos = sheet->dblColumnPos( marker.left() ) - xOffset();
4573 x = sheet->dblColumnPos( marker.right() ) - xOffset();
4574 }
4575 double ypos = sheet->dblRowPos( marker.top() ) - yOffset();
4576
4577 const ColumnFormat *columnFormat = sheet->columnFormat( marker.right() );
4578 double tw = columnFormat->dblWidth( );
4579 double w = x - xpos + tw;
4580
4581 double y = sheet->dblRowPos( marker.bottom() ) - yOffset();
4582 const RowFormat* rowFormat = sheet->rowFormat( marker.bottom() );
4583 double th = rowFormat->dblHeight( );
4584 double h = ( y - ypos ) + th;
4585
4586 //left, top, right, bottom
4587 if ( sheet->layoutDirection()==Sheet::RightToLeft )
4588 {
4589 positions[0] = xpos - tw;
4590 positions[2] = xpos - tw + w;
4591 }
4592 else
4593 {
4594 positions[0] = xpos;
4595 positions[2] = xpos + w;
4596 }
4597 positions[1] = ypos;
4598 positions[3] = ypos + h;*/
4599
4600 /* these vars are used for clarity, the array for simpler function arguments */
4601 double left = visibleRect.left();
4602 double top = visibleRect.top();
4603 double right = visibleRect.right();
4604 double bottom = visibleRect.bottom();
4605
4606 /* left, top, right, bottom */
4607 paintSides[0] = (viewRect.left() <= left) && (left <= viewRect.right()) &&
4608 (bottom >= viewRect.top()) && (top <= viewRect.bottom());
4609 paintSides[1] = (viewRect.top() <= top) && (top <= viewRect.bottom())
4610 && (right >= viewRect.left()) && (left <= viewRect.right());
4611 if ( sheet->layoutDirection()==Sheet::RightToLeft )
4612 paintSides[2] = (viewRect.left() <= right ) &&
4613 (right - 1 <= viewRect.right()) &&
4614 (bottom >= viewRect.top()) && (top <= viewRect.bottom());
4615 else
4616 paintSides[2] = (viewRect.left() <= right ) &&
4617 (right <= viewRect.right()) &&
4618 (bottom >= viewRect.top()) && (top <= viewRect.bottom());
4619 paintSides[3] = (viewRect.top() <= bottom) && (bottom <= viewRect.bottom())
4620 && (right >= viewRect.left()) && (left <= viewRect.right());
4621
4622 positions[0] = TQMAX( left, viewRect.left() );
4623 positions[1] = TQMAX( top, viewRect.top() );
4624 positions[2] = TQMIN( right, viewRect.right() );
4625 positions[3] = TQMIN( bottom, viewRect.bottom() );
4626}
4627
4628
4629/****************************************************************
4630 *
4631 * VBorder
4632 *
4633 ****************************************************************/
4634
4635VBorder::VBorder( TQWidget *_parent, Canvas *_canvas, View *_view)
4636 : TQWidget( _parent, "", /*WNorthWestGravity*/WStaticContents | WResizeNoErase | WRepaintNoErase )
4637{
4638 m_pView = _view;
4639 m_pCanvas = _canvas;
4640 m_lSize = 0L;
4641
4642 setBackgroundMode( PaletteButton );
4643 setMouseTracking( true );
4644 m_bResize = false;
4645 m_bSelection = false;
4646 m_iSelectionAnchor=1;
4647 m_bMousePressed = false;
4648
4649 m_scrollTimer = new TQTimer( this );
4650 connect (m_scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( doAutoScroll() ) );
4651}
4652
4653
4654VBorder::~VBorder()
4655{
4656 delete m_scrollTimer;
4657}
4658
4659TQSize VBorder::sizeHint() const
4660{
4661 return TQSize( 40, 10 );
4662}
4663
4664
4665void VBorder::mousePressEvent( TQMouseEvent * _ev )
4666{
4667 if ( !m_pView->koDocument()->isReadWrite() )
4668 return;
4669
4670 if ( _ev->button() == TQt::LeftButton )
4671 m_bMousePressed = true;
4672
4673 const Sheet *sheet = m_pCanvas->activeSheet();
4674 if (!sheet)
4675 return;
4676
4677 double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset();
4678 double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() );
4679 m_bResize = false;
4680 m_bSelection = false;
4681
4682 // We were editing a cell -> save value and get out of editing mode
4683 if ( m_pCanvas->editor() )
4684 {
4685 m_pCanvas->deleteEditor( true ); // save changes
4686 }
4687
4688 m_scrollTimer->start( 50 );
4689
4690 // Find the first visible row and the y position of this row.
4691 double y;
4692 int row = sheet->topRow( m_pCanvas->yOffset(), y );
4693
4694 // Did the user click between two rows?
4695 while ( y < ( dHeight + m_pCanvas->yOffset() ) && ( !m_bResize ) )
4696 {
4697 double h = sheet->rowFormat( row )->dblHeight();
4698 row++;
4699 if ( row > KS_rowMax )
4700 row = KS_rowMax;
4701 if ( ( ev_PosY >= y + h - 2 ) &&
4702 ( ev_PosY <= y + h + 1 ) &&
4703 !( sheet->rowFormat( row )->isHide() && row == 1 ) )
4704 m_bResize = true;
4705 y += h;
4706 }
4707
4708 //if row is hide and it's the first row
4709 //you mustn't resize it.
4710 double tmp2;
4711 int tmpRow = sheet->topRow( ev_PosY - 1, tmp2 );
4712 if ( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 )
4713 m_bResize = false;
4714
4715 // So he clicked between two rows ?
4716 if ( m_bResize )
4717 {
4718 // Determine row to resize
4719 double tmp;
4720 m_iResizedRow = sheet->topRow( ev_PosY - 1, tmp );
4721 if ( !sheet->isProtected() )
4722 paintSizeIndicator( _ev->pos().y(), true );
4723 }
4724 else
4725 {
4726 m_bSelection = true;
4727
4728 double tmp;
4729 int hit_row = sheet->topRow( ev_PosY, tmp );
4730 if ( hit_row > KS_rowMax )
4731 return;
4732
4733 m_iSelectionAnchor = hit_row;
4734
4735 if ( !m_pView->selectionInfo()->contains( TQPoint(1, hit_row) ) ||
4736 !( _ev->button() == TQt::RightButton ) ||
4737 !m_pView->selectionInfo()->isRowSelected() )
4738 {
4739 TQPoint newMarker( 1, hit_row );
4740 TQPoint newAnchor( KS_colMax, hit_row );
4741#ifdef NONCONTIGUOUSSELECTION
4742 if (_ev->state() == ControlButton)
4743 {
4744 m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker));
4745 }
4746 else
4747#endif
4748 if (_ev->state() == ShiftButton)
4749 {
4750 m_pView->selectionInfo()->update(newMarker);
4751 }
4752 else
4753 {
4754 m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker));
4755 }
4756 }
4757
4758 if ( _ev->button() == TQt::RightButton )
4759 {
4760 TQPoint p = mapToGlobal( _ev->pos() );
4761 m_pView->popupRowMenu( p );
4762 m_bSelection = false;
4763 }
4764 m_pView->updateEditWidget();
4765 }
4766}
4767
4768void VBorder::mouseReleaseEvent( TQMouseEvent * _ev )
4769{
4770 if ( m_scrollTimer->isActive() )
4771 m_scrollTimer->stop();
4772
4773 m_bMousePressed = false;
4774
4775 if ( !m_pView->koDocument()->isReadWrite() )
4776 return;
4777
4778 Sheet *sheet = m_pCanvas->activeSheet();
4779 if (!sheet)
4780 return;
4781
4782 double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset();
4783
4784 if ( m_bResize )
4785 {
4786 // Remove size indicator painted by paintSizeIndicator
4787 TQPainter painter;
4788 painter.begin( m_pCanvas );
4789 painter.setRasterOp( NotROP );
4790 painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos );
4791 painter.end();
4792
4793 int start = m_iResizedRow;
4794 int end = m_iResizedRow;
4795 TQRect rect;
4796 rect.setCoords( 1, m_iResizedRow, KS_colMax, m_iResizedRow );
4797 if ( m_pView->selectionInfo()->isRowSelected() )
4798 {
4799 if ( m_pView->selectionInfo()->contains( TQPoint( 1, m_iResizedRow ) ) )
4800 {
4801 start = m_pView->selectionInfo()->lastRange().top();
4802 end = m_pView->selectionInfo()->lastRange().bottom();
4803 rect = m_pView->selectionInfo()->lastRange();
4804 }
4805 }
4806
4807 double height = 0.0;
4808 double y = sheet->dblRowPos( m_iResizedRow );
4809 if ( ev_PosY - y <= 0.0 )
4810 height = 0.0;
4811 else
4812 height = ev_PosY - y;
4813
4814 if ( !sheet->isProtected() )
4815 {
4816 if ( !m_pCanvas->d->view->doc()->undoLocked() )
4817 {
4818 //just resize
4819 if ( height != 0.0 )
4820 {
4821 // TODO Stefan: replace this
4822 UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect );
4823 m_pCanvas->d->view->doc()->addCommand( undo );
4824 }
4825 }
4826
4827 for( int i = start; i <= end; i++ )
4828 {
4829 RowFormat *rl = sheet->nonDefaultRowFormat( i );
4830 if ( height != 0.0 )
4831 {
4832 if ( !rl->isHide() )
4833 rl->setDblHeight( height );
4834 }
4835 else
4836 {
4837 sheet->hideRow(*m_pView->selectionInfo());
4838 }
4839 }
4840
4841 delete m_lSize;
4842 m_lSize = 0;
4843 }
4844 }
4845 else if ( m_bSelection )
4846 {
4847 TQRect rect = m_pView->selectionInfo()->lastRange();
4848
4849 // TODO: please don't remove. Right now it's useless, but it's for a future feature
4850 // Norbert
4851 bool m_frozen = false;
4852 if ( m_frozen )
4853 {
4854 kdDebug(36001) << "selected: T " << rect.top() << " B " << rect.bottom() << endl;
4855
4856 int i;
4857 RowFormat * row;
4858 TQValueList<int>hiddenRows;
4859
4860 for ( i = rect.top(); i <= rect.bottom(); ++i )
4861 {
4862 row = m_pView->activeSheet()->rowFormat( i );
4863 if ( row->isHide() )
4864 {
4865 hiddenRows.append(i);
4866 }
4867 }
4868
4869 if ( hiddenRows.count() > 0 )
4870 m_pView->activeSheet()->showRow(*m_pView->selectionInfo());
4871 }
4872 }
4873
4874 m_bSelection = false;
4875 m_bResize = false;
4876}
4877
4878void VBorder::equalizeRow( double resize )
4879{
4880 Sheet *sheet = m_pCanvas->activeSheet();
4881 Q_ASSERT( sheet );
4882
4883 TQRect selection( m_pView->selectionInfo()->selection() );
4884 if ( !m_pCanvas->d->view->doc()->undoLocked() )
4885 {
4886 UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection );
4887 m_pCanvas->d->view->doc()->addCommand( undo );
4888 }
4889 RowFormat *rl;
4890 for ( int i = selection.top(); i <= selection.bottom(); i++ )
4891 {
4892 rl = sheet->nonDefaultRowFormat( i );
4893 resize = TQMAX( 2.0, resize);
4894 rl->setDblHeight( resize );
4895 }
4896}
4897
4898void VBorder::mouseDoubleClickEvent(TQMouseEvent*)
4899{
4900 Sheet *sheet = m_pCanvas->activeSheet();
4901 if (!sheet)
4902 return;
4903
4904 if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() )
4905 return;
4906
4907 sheet->adjustRow(*m_pCanvas->selectionInfo());
4908}
4909
4910
4911void VBorder::mouseMoveEvent( TQMouseEvent * _ev )
4912{
4913 if ( !m_pView->koDocument()->isReadWrite() )
4914 return;
4915
4916 Sheet *sheet = m_pCanvas->activeSheet();
4917
4918 if (!sheet)
4919 return;
4920
4921 double ev_PosY = m_pCanvas->d->view->doc()->unzoomItY( _ev->pos().y() ) + m_pCanvas->yOffset();
4922 double dHeight = m_pCanvas->d->view->doc()->unzoomItY( height() );
4923
4924 // The button is pressed and we are resizing ?
4925 if ( m_bResize )
4926 {
4927 if ( !sheet->isProtected() )
4928 paintSizeIndicator( _ev->pos().y(), false );
4929 }
4930 // The button is pressed and we are selecting ?
4931 else if ( m_bSelection )
4932 {
4933 double y;
4934 int row = sheet->topRow( ev_PosY, y );
4935 if ( row > KS_rowMax )
4936 return;
4937
4938 TQPoint newAnchor = m_pView->selectionInfo()->anchor();
4939 TQPoint newMarker = m_pView->selectionInfo()->marker();
4940 newMarker.setY( row );
4941 newAnchor.setY( m_iSelectionAnchor );
4942 m_pView->selectionInfo()->update(newMarker);
4943
4944 if ( _ev->pos().y() < 0 )
4945 m_pCanvas->vertScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItY( ev_PosY ) );
4946 else if ( _ev->pos().y() > m_pCanvas->height() )
4947 {
4948 if ( row < KS_rowMax )
4949 {
4950 RowFormat *rl = sheet->rowFormat( row + 1 );
4951 y = sheet->dblRowPos( row + 1 );
4952 m_pCanvas->vertScrollBar()->setValue ((int) (m_pCanvas->d->view->doc()->zoomItY
4953 (ev_PosY + rl->dblHeight()) - dHeight));
4954 }
4955 }
4956 }
4957 // No button is pressed and the mouse is just moved
4958 else
4959 {
4960
4961 //What is the internal size of 1 pixel
4962 const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItY( 1 );
4963 double y;
4964 int tmpRow = sheet->topRow( m_pCanvas->yOffset(), y );
4965
4966 while ( y < m_pCanvas->d->view->doc()->unzoomItY( height() ) + m_pCanvas->yOffset() )
4967 {
4968 double h = sheet->rowFormat( tmpRow )->dblHeight();
4969 //if col is hide and it's the first column
4970 //you mustn't resize it.
4971 if ( ev_PosY >= y + h - 2 * unzoomedPixel &&
4972 ev_PosY <= y + h + unzoomedPixel &&
4973 !( sheet->rowFormat( tmpRow )->isHide() && tmpRow == 1 ) )
4974 {
4975 setCursor( splitVCursor );
4976 return;
4977 }
4978 y += h;
4979 tmpRow++;
4980 }
4981 setCursor( arrowCursor );
4982 }
4983}
4984
4985void VBorder::doAutoScroll()
4986{
4987 if ( !m_bMousePressed )
4988 {
4989 m_scrollTimer->stop();
4990 return;
4991 }
4992
4993 TQPoint pos( mapFromGlobal( TQCursor::pos() ) );
4994
4995 if ( pos.y() < 0 || pos.y() > height() )
4996 {
4997 TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 );
4998 mouseMoveEvent( event );
4999 delete event;
5000 }
5001
5002 //Restart timer
5003 m_scrollTimer->start( 50 );
5004}
5005
5006void VBorder::wheelEvent( TQWheelEvent* _ev )
5007{
5008 if ( m_pCanvas->vertScrollBar() )
5009 TQApplication::sendEvent( m_pCanvas->vertScrollBar(), _ev );
5010}
5011
5012
5013void VBorder::paintSizeIndicator( int mouseY, bool firstTime )
5014{
5015 Sheet *sheet = m_pCanvas->activeSheet();
5016 if (!sheet)
5017 return;
5018
5019 TQPainter painter;
5020 painter.begin( m_pCanvas );
5021 painter.setRasterOp( NotROP );
5022
5023 if ( !firstTime )
5024 painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos );
5025
5026 m_iResizePos = mouseY;
5027
5028 // Dont make the row have a height < 2 pixel.
5029 int y = m_pCanvas->d->view->doc()->zoomItY( sheet->dblRowPos( m_iResizedRow ) - m_pCanvas->yOffset() );
5030 if ( m_iResizePos < y + 2 )
5031 m_iResizePos = y;
5032
5033 painter.drawLine( 0, m_iResizePos, m_pCanvas->width(), m_iResizePos );
5034
5035 painter.end();
5036
5037 TQString tmpSize;
5038 if ( m_iResizePos != y )
5039 tmpSize = i18n("Height: %1 %2").arg( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItY( m_iResizePos - y ),
5040 m_pView->doc()->unit() ) )
5041 .arg( m_pView->doc()->unitName() );
5042 else
5043 tmpSize = i18n( "Hide Row" );
5044
5045 painter.begin( this );
5046 int len = painter.fontMetrics().width( tmpSize );
5047 int hei = painter.fontMetrics().height();
5048 painter.end();
5049
5050 if ( !m_lSize )
5051 {
5052 m_lSize = new TQLabel( m_pCanvas );
5053
5054 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5055 m_lSize->setGeometry( m_pCanvas->width() - len - 5,
5056 y + 3, len + 2, hei + 2 );
5057 else
5058 m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 );
5059
5060 m_lSize->setAlignment( TQt::AlignVCenter );
5061 m_lSize->setText( tmpSize );
5062 m_lSize->setPalette( TQToolTip::palette() );
5063 m_lSize->show();
5064 }
5065 else
5066 {
5067 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5068 m_lSize->setGeometry( m_pCanvas->width() - len - 5,
5069 y + 3, len + 2, hei + 2 );
5070 else
5071 m_lSize->setGeometry( 3, y + 3, len + 2,hei + 2 );
5072
5073 m_lSize->setText( tmpSize );
5074 }
5075}
5076
5077void VBorder::updateRows( int from, int to )
5078{
5079 Sheet *sheet = m_pCanvas->activeSheet();
5080 if ( !sheet )
5081 return;
5082
5083 int y0 = sheet->rowPos( from, m_pCanvas );
5084 int y1 = sheet->rowPos( to+1, m_pCanvas );
5085 update( 0, y0, width(), y1-y0 );
5086}
5087
5088void VBorder::paintEvent( TQPaintEvent* _ev )
5089{
5090 Sheet *sheet = m_pCanvas->activeSheet();
5091 if ( !sheet )
5092 return;
5093
5094 TQPainter painter( this );
5095 TQColor highlightColor = View::highlightColor();
5096 TQPen pen( TQt::black, 1 );
5097 painter.setPen( pen );
5098 // painter.setBackgroundColor( colorGroup().base() );
5099
5100 // painter.eraseRect( _ev->rect() );
5101
5102 //TQFontMetrics fm = painter.fontMetrics();
5103 // Matthias Elter: This causes a SEGFAULT in ~TQPainter!
5104 // Only god and the trolls know why ;-)
5105 // bah...took me quite some time to track this one down...
5106
5107 painter.setClipRect( _ev->rect() );
5108
5109 double yPos;
5110 //Get the top row and the current y-position
5111 int y = sheet->topRow( (m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().y() ) + m_pCanvas->yOffset()), yPos );
5112 //Align to the offset
5113 yPos = yPos - m_pCanvas->yOffset();
5114 int width = m_pCanvas->d->view->doc()->zoomItX( YBORDER_WIDTH );
5115
5116 TQFont normalFont = painter.font();
5117 if ( m_pCanvas->d->view->doc()->zoom() < 100 )
5118 {
5119 normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() *
5120 normalFont.pointSizeFloat() );
5121 }
5122 TQFont boldFont = normalFont;
5123 boldFont.setBold( true );
5124
5125 //Loop through the rows, until we are out of range
5126 while ( yPos <= m_pCanvas->d->view->doc()->unzoomItY( _ev->rect().bottom() ) )
5127 {
5128 bool selected = (m_pView->selectionInfo()->isRowSelected(y));
5129 bool highlighted = (!selected && m_pView->selectionInfo()->isRowAffected(y));
5130
5131 const RowFormat *row_lay = sheet->rowFormat( y );
5132 int zoomedYPos = m_pCanvas->d->view->doc()->zoomItY( yPos );
5133 int height = m_pCanvas->d->view->doc()->zoomItY( yPos + row_lay->dblHeight() ) - zoomedYPos;
5134
5135 if ( selected )
5136 {
5137 TQBrush fillSelected( highlightColor );
5138 qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150),
5139 1, &fillSelected );
5140 }
5141 else if ( highlighted )
5142 {
5143 TQBrush fillHighlighted( highlightColor );
5144 qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, highlightColor.dark(150),
5145 1, &fillHighlighted );
5146 }
5147 else
5148 {
5149 TQColor c = colorGroup().background();
5150 TQBrush fill( c );
5151 qDrawPlainRect ( &painter, 0, zoomedYPos, width, height+1, c.dark(150),
5152 1, &fill );
5153 }
5154
5155 TQString rowText = TQString::number( y );
5156
5157 // Reset painter
5158 painter.setFont( normalFont );
5159 painter.setPen( colorGroup().text() );
5160
5161 if ( selected )
5162 painter.setPen( colorGroup().highlightedText() );
5163 else if ( highlighted )
5164 painter.setFont( boldFont );
5165
5166 int len = painter.fontMetrics().width( rowText );
5167 if (!row_lay->isHide())
5168 painter.drawText( ( width-len )/2, zoomedYPos +
5169 ( height + painter.fontMetrics().ascent() -
5170 painter.fontMetrics().descent() ) / 2, rowText );
5171
5172 yPos += row_lay->dblHeight();
5173 y++;
5174 }
5175}
5176
5177
5178void VBorder::focusOutEvent( TQFocusEvent* )
5179{
5180 if ( m_scrollTimer->isActive() )
5181 m_scrollTimer->stop();
5182 m_bMousePressed = false;
5183}
5184
5185
5186/****************************************************************
5187 *
5188 * HBorder
5189 *
5190 ****************************************************************/
5191
5192HBorder::HBorder( TQWidget *_parent, Canvas *_canvas,View *_view )
5193 : TQWidget( _parent, "", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase )
5194{
5195 m_pView = _view;
5196 m_pCanvas = _canvas;
5197 m_lSize = 0L;
5198 setBackgroundMode( PaletteButton );
5199 setMouseTracking( true );
5200 m_bResize = false;
5201 m_bSelection = false;
5202 m_iSelectionAnchor=1;
5203 m_bMousePressed = false;
5204
5205 m_scrollTimer = new TQTimer( this );
5206 connect( m_scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( doAutoScroll() ) );
5207}
5208
5209
5210HBorder::~HBorder()
5211{
5212 delete m_scrollTimer;
5213}
5214
5215TQSize HBorder::sizeHint() const
5216{
5217 return TQSize( 40, 10 );
5218}
5219
5220void HBorder::mousePressEvent( TQMouseEvent * _ev )
5221{
5222 if (!m_pView->koDocument()->isReadWrite())
5223 return;
5224
5225 if ( _ev->button() == TQt::LeftButton )
5226 m_bMousePressed = true;
5227
5228 const Sheet *sheet = m_pCanvas->activeSheet();
5229 if (!sheet)
5230 return;
5231
5232 // We were editing a cell -> save value and get out of editing mode
5233 if ( m_pCanvas->editor() )
5234 {
5235 m_pCanvas->deleteEditor( true ); // save changes
5236 }
5237
5238 m_scrollTimer->start( 50 );
5239
5240 double ev_PosX;
5241 double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() );
5242 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5243 ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
5244 else
5245 ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
5246 m_bResize = false;
5247 m_bSelection = false;
5248
5249 // Find the first visible column and the x position of this column.
5250 double x;
5251
5252 const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 );
5253 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5254 {
5255 int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x );
5256
5257 kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", COL: " << tmpCol << endl;
5258 while ( ev_PosX > x && ( !m_bResize ) )
5259 {
5260 double w = sheet->columnFormat( tmpCol )->dblWidth();
5261
5262 kdDebug() << "evPos: " << ev_PosX << ", x: " << x << ", w: " << w << ", COL: " << tmpCol << endl;
5263
5264 ++tmpCol;
5265 if ( tmpCol > KS_colMax )
5266 tmpCol = KS_colMax;
5267 //if col is hide and it's the first column
5268 //you mustn't resize it.
5269
5270 if ( ev_PosX >= x + w - unzoomedPixel &&
5271 ev_PosX <= x + w + unzoomedPixel &&
5272 !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) )
5273 {
5274 m_bResize = true;
5275 }
5276 x += w;
5277 }
5278
5279 //if col is hide and it's the first column
5280 //you mustn't resize it.
5281 double tmp2;
5282 tmpCol = sheet->leftColumn( dWidth - ev_PosX + 1, tmp2 );
5283 if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 )
5284 {
5285 kdDebug() << "No resize: " << tmpCol << ", " << sheet->columnFormat( tmpCol )->isHide() << endl;
5286 m_bResize = false;
5287 }
5288
5289 kdDebug() << "Resize: " << m_bResize << endl;
5290 }
5291 else
5292 {
5293 int col = sheet->leftColumn( m_pCanvas->xOffset(), x );
5294
5295 // Did the user click between two columns?
5296 while ( x < ( dWidth + m_pCanvas->xOffset() ) && ( !m_bResize ) )
5297 {
5298 double w = sheet->columnFormat( col )->dblWidth();
5299 col++;
5300 if ( col > KS_colMax )
5301 col = KS_colMax;
5302 if ( ( ev_PosX >= x + w - unzoomedPixel ) &&
5303 ( ev_PosX <= x + w + unzoomedPixel ) &&
5304 !( sheet->columnFormat( col )->isHide() && col == 1 ) )
5305 m_bResize = true;
5306 x += w;
5307 }
5308
5309 //if col is hide and it's the first column
5310 //you mustn't resize it.
5311 double tmp2;
5312 int tmpCol = sheet->leftColumn( ev_PosX - 1, tmp2 );
5313 if ( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 )
5314 m_bResize = false;
5315 }
5316
5317 // So he clicked between two rows ?
5318 if ( m_bResize )
5319 {
5320 // Determine the column to resize
5321 double tmp;
5322 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5323 {
5324 m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp );
5325 // kdDebug() << "RColumn: " << m_iResizedColumn << ", PosX: " << ev_PosX << endl;
5326
5327 if ( !sheet->isProtected() )
5328 paintSizeIndicator( _ev->pos().x(), true );
5329 }
5330 else
5331 {
5332 m_iResizedColumn = sheet->leftColumn( ev_PosX - 1, tmp );
5333
5334 if ( !sheet->isProtected() )
5335 paintSizeIndicator( _ev->pos().x(), true );
5336 }
5337
5338 // kdDebug() << "Column: " << m_iResizedColumn << endl;
5339 }
5340 else
5341 {
5342 m_bSelection = true;
5343
5344 double tmp;
5345 int hit_col = sheet->leftColumn( ev_PosX, tmp );
5346 if ( hit_col > KS_colMax )
5347 return;
5348
5349 m_iSelectionAnchor = hit_col;
5350
5351 if ( !m_pView->selectionInfo()->contains( TQPoint( hit_col, 1 ) ) ||
5352 !( _ev->button() == TQt::RightButton ) ||
5353 !m_pView->selectionInfo()->isColumnSelected() )
5354 {
5355 TQPoint newMarker( hit_col, 1 );
5356 TQPoint newAnchor( hit_col, KS_rowMax );
5357#ifdef NONCONTIGUOUSSELECTION
5358 if (_ev->state() == ControlButton)
5359 {
5360 m_pView->selectionInfo()->extend(TQRect(newAnchor, newMarker));
5361 }
5362 else
5363#endif
5364 if (_ev->state() == ShiftButton)
5365 {
5366 m_pView->selectionInfo()->update(newMarker);
5367 }
5368 else
5369 {
5370 m_pView->selectionInfo()->initialize(TQRect(newAnchor, newMarker));
5371 }
5372 }
5373
5374 if ( _ev->button() == TQt::RightButton )
5375 {
5376 TQPoint p = mapToGlobal( _ev->pos() );
5377 m_pView->popupColumnMenu( p );
5378 m_bSelection = false;
5379 }
5380 m_pView->updateEditWidget();
5381 }
5382}
5383
5384void HBorder::mouseReleaseEvent( TQMouseEvent * _ev )
5385{
5386 if ( m_scrollTimer->isActive() )
5387 m_scrollTimer->stop();
5388
5389 m_bMousePressed = false;
5390
5391 if ( !m_pView->koDocument()->isReadWrite() )
5392 return;
5393
5394 Sheet * sheet = m_pCanvas->activeSheet();
5395 if (!sheet)
5396 return;
5397
5398 if ( m_bResize )
5399 {
5400 double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() );
5401 double ev_PosX;
5402
5403 // Remove size indicator painted by paintSizeIndicator
5404 TQPainter painter;
5405 painter.begin( m_pCanvas );
5406 painter.setRasterOp( NotROP );
5407 painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() );
5408 painter.end();
5409
5410 int start = m_iResizedColumn;
5411 int end = m_iResizedColumn;
5412 TQRect rect;
5413 rect.setCoords( m_iResizedColumn, 1, m_iResizedColumn, KS_rowMax );
5414 if ( m_pView->selectionInfo()->isColumnSelected() )
5415 {
5416 if ( m_pView->selectionInfo()->contains( TQPoint( m_iResizedColumn, 1 ) ) )
5417 {
5418 start = m_pView->selectionInfo()->lastRange().left();
5419 end = m_pView->selectionInfo()->lastRange().right();
5420 rect = m_pView->selectionInfo()->lastRange();
5421 }
5422 }
5423
5424 double width = 0.0;
5425 double x;
5426
5427 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5428 ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
5429 else
5430 ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
5431
5432 x = sheet->dblColumnPos( m_iResizedColumn );
5433
5434 if ( ev_PosX - x <= 0.0 )
5435 width = 0.0;
5436 else
5437 width = ev_PosX - x;
5438
5439 if ( !sheet->isProtected() )
5440 {
5441 if ( !m_pCanvas->d->view->doc()->undoLocked() )
5442 {
5443 //just resize
5444 if ( width != 0.0 )
5445 {
5446 // TODO Stefan: replace this
5447 UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), rect );
5448 m_pCanvas->d->view->doc()->addCommand( undo );
5449 }
5450 }
5451
5452 for( int i = start; i <= end; i++ )
5453 {
5454 ColumnFormat *cl = sheet->nonDefaultColumnFormat( i );
5455 if ( width != 0.0 )
5456 {
5457 if ( !cl->isHide() )
5458 cl->setDblWidth( width );
5459 }
5460 else
5461 {
5462 sheet->hideColumn(*m_pView->selectionInfo());
5463 }
5464 }
5465
5466 delete m_lSize;
5467 m_lSize = 0;
5468 }
5469 }
5470 else if ( m_bSelection )
5471 {
5472 TQRect rect = m_pView->selectionInfo()->lastRange();
5473
5474 // TODO: please don't remove. Right now it's useless, but it's for a future feature
5475 // Norbert
5476 bool m_frozen = false;
5477 if ( m_frozen )
5478 {
5479 kdDebug(36001) << "selected: L " << rect.left() << " R " << rect.right() << endl;
5480
5481 int i;
5482 ColumnFormat * col;
5483 TQValueList<int>hiddenCols;
5484
5485 for ( i = rect.left(); i <= rect.right(); ++i )
5486 {
5487 col = m_pView->activeSheet()->columnFormat( i );
5488 if ( col->isHide() )
5489 {
5490 hiddenCols.append(i);
5491 }
5492 }
5493
5494 if ( hiddenCols.count() > 0 )
5495 m_pView->activeSheet()->showColumn(*m_pView->selectionInfo());
5496 }
5497 }
5498
5499 m_bSelection = false;
5500 m_bResize = false;
5501}
5502
5503void HBorder::equalizeColumn( double resize )
5504{
5505 Sheet *sheet = m_pCanvas->activeSheet();
5506 Q_ASSERT( sheet );
5507
5508 TQRect selection( m_pView->selectionInfo()->selection() );
5509 if ( !m_pCanvas->d->view->doc()->undoLocked() )
5510 {
5511 UndoResizeColRow *undo = new UndoResizeColRow( m_pCanvas->d->view->doc(), m_pCanvas->activeSheet(), selection );
5512 m_pCanvas->d->view->doc()->addCommand( undo );
5513 }
5514 ColumnFormat *cl;
5515 for ( int i = selection.left(); i <= selection.right(); i++ )
5516 {
5517 cl = sheet->nonDefaultColumnFormat( i );
5518 resize = TQMAX( 2.0, resize );
5519 cl->setDblWidth( resize );
5520 }
5521
5522}
5523
5524void HBorder::mouseDoubleClickEvent(TQMouseEvent*)
5525{
5526 Sheet *sheet = m_pCanvas->activeSheet();
5527 if (!sheet)
5528 return;
5529
5530 if ( !m_pView->koDocument()->isReadWrite() || sheet->isProtected() )
5531 return;
5532
5533 sheet->adjustColumn(*m_pCanvas->selectionInfo());
5534}
5535
5536void HBorder::mouseMoveEvent( TQMouseEvent * _ev )
5537{
5538 if ( !m_pView->koDocument()->isReadWrite() )
5539 return;
5540
5541 Sheet *sheet = m_pCanvas->activeSheet();
5542
5543 if (!sheet)
5544 return;
5545
5546 double dWidth = m_pCanvas->d->view->doc()->unzoomItX( width() );
5547 double ev_PosX;
5548 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5549 ev_PosX = dWidth - m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
5550 else
5551 ev_PosX = m_pCanvas->d->view->doc()->unzoomItX( _ev->pos().x() ) + m_pCanvas->xOffset();
5552
5553 // The button is pressed and we are resizing ?
5554 if ( m_bResize )
5555 {
5556 if ( !sheet->isProtected() )
5557 paintSizeIndicator( _ev->pos().x(), false );
5558 }
5559 // The button is pressed and we are selecting ?
5560 else if ( m_bSelection )
5561 {
5562 double x;
5563 int col = sheet->leftColumn( ev_PosX, x );
5564
5565 if ( col > KS_colMax )
5566 return;
5567
5568 TQPoint newMarker = m_pView->selectionInfo()->marker();
5569 TQPoint newAnchor = m_pView->selectionInfo()->anchor();
5570 newMarker.setX( col );
5571 newAnchor.setX( m_iSelectionAnchor );
5572 m_pView->selectionInfo()->update(newMarker);
5573
5574 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5575 {
5576 if ( _ev->pos().x() < width() - m_pCanvas->width() )
5577 {
5578 ColumnFormat *cl = sheet->columnFormat( col + 1 );
5579 x = sheet->dblColumnPos( col + 1 );
5580 m_pCanvas->horzScrollBar()->setValue ( m_pCanvas->horzScrollBar()->maxValue() - (int)
5581 (m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - m_pCanvas->d->view->doc()->unzoomItX( m_pCanvas->width() )));
5582 }
5583 else if ( _ev->pos().x() > width() )
5584 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() ) ) );
5585 }
5586 else
5587 {
5588 if ( _ev->pos().x() < 0 )
5589 m_pCanvas->horzScrollBar()->setValue( m_pCanvas->d->view->doc()->zoomItX( ev_PosX ) );
5590 else if ( _ev->pos().x() > m_pCanvas->width() )
5591 {
5592 if ( col < KS_colMax )
5593 {
5594 ColumnFormat *cl = sheet->columnFormat( col + 1 );
5595 x = sheet->dblColumnPos( col + 1 );
5596 m_pCanvas->horzScrollBar()->setValue ((int)
5597 (m_pCanvas->d->view->doc()->zoomItX (ev_PosX + cl->dblWidth()) - dWidth));
5598 }
5599 }
5600 }
5601
5602 }
5603 // No button is pressed and the mouse is just moved
5604 else
5605 {
5606 //What is the internal size of 1 pixel
5607 const double unzoomedPixel = m_pCanvas->d->view->doc()->unzoomItX( 1 );
5608 double x;
5609
5610 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5611 {
5612 int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x );
5613
5614 while ( ev_PosX > x )
5615 {
5616 double w = sheet->columnFormat( tmpCol )->dblWidth();
5617 ++tmpCol;
5618
5619 //if col is hide and it's the first column
5620 //you mustn't resize it.
5621 if ( ev_PosX >= x + w - unzoomedPixel &&
5622 ev_PosX <= x + w + unzoomedPixel &&
5623 !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 0 ) )
5624 {
5625 setCursor( splitHCursor );
5626 return;
5627 }
5628 x += w;
5629 }
5630 setCursor( arrowCursor );
5631 }
5632 else
5633 {
5634 int tmpCol = sheet->leftColumn( m_pCanvas->xOffset(), x );
5635
5636 while ( x < m_pCanvas->d->view->doc()->unzoomItY( width() ) + m_pCanvas->xOffset() )
5637 {
5638 double w = sheet->columnFormat( tmpCol )->dblWidth();
5639 //if col is hide and it's the first column
5640 //you mustn't resize it.
5641 if ( ev_PosX >= x + w - unzoomedPixel &&
5642 ev_PosX <= x + w + unzoomedPixel &&
5643 !( sheet->columnFormat( tmpCol )->isHide() && tmpCol == 1 ) )
5644 {
5645 setCursor( splitHCursor );
5646 return;
5647 }
5648 x += w;
5649 tmpCol++;
5650 }
5651 setCursor( arrowCursor );
5652 }
5653 }
5654}
5655
5656void HBorder::doAutoScroll()
5657{
5658 if ( !m_bMousePressed )
5659 {
5660 m_scrollTimer->stop();
5661 return;
5662 }
5663
5664 TQPoint pos( mapFromGlobal( TQCursor::pos() ) );
5665
5666 if ( pos.x() < 0 || pos.x() > width() )
5667 {
5668 TQMouseEvent * event = new TQMouseEvent( TQEvent::MouseMove, pos, 0, 0 );
5669 mouseMoveEvent( event );
5670 delete event;
5671 }
5672
5673 //Restart timer
5674 m_scrollTimer->start( 50 );
5675}
5676
5677void HBorder::wheelEvent( TQWheelEvent* _ev )
5678{
5679 if ( m_pCanvas->horzScrollBar() )
5680 TQApplication::sendEvent( m_pCanvas->horzScrollBar(), _ev );
5681}
5682
5683void HBorder::resizeEvent( TQResizeEvent* _ev )
5684{
5685 // workaround to allow horizontal resizing and zoom changing when sheet
5686 // direction and interface direction don't match (e.g. an RTL sheet on an
5687 // LTR interface)
5688 if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::RightToLeft && !TQApplication::reverseLayout() )
5689 {
5690 int dx = _ev->size().width() - _ev->oldSize().width();
5691 scroll(dx, 0);
5692 }
5693 else if ( m_pCanvas->activeSheet() && m_pCanvas->activeSheet()->layoutDirection()==Sheet::LeftToRight && TQApplication::reverseLayout() )
5694 {
5695 int dx = _ev->size().width() - _ev->oldSize().width();
5696 scroll(-dx, 0);
5697 }
5698}
5699
5700void HBorder::paintSizeIndicator( int mouseX, bool firstTime )
5701{
5702 Sheet *sheet = m_pCanvas->activeSheet();
5703 if (!sheet)
5704 return;
5705
5706 TQPainter painter;
5707 painter.begin( m_pCanvas );
5708 painter.setRasterOp( NotROP );
5709
5710 if ( !firstTime )
5711 painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() );
5712
5713 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5714 m_iResizePos = mouseX + m_pCanvas->width() - width();
5715 else
5716 m_iResizePos = mouseX;
5717
5718 // Dont make the column have a width < 2 pixels.
5719 int x = m_pCanvas->d->view->doc()->zoomItX( sheet->dblColumnPos( m_iResizedColumn ) - m_pCanvas->xOffset() );
5720
5721 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5722 {
5723 x = m_pCanvas->width() - x;
5724
5725 if ( m_iResizePos > x - 2 )
5726 m_iResizePos = x;
5727 }
5728 else
5729 {
5730 if ( m_iResizePos < x + 2 )
5731 m_iResizePos = x;
5732 }
5733
5734 painter.drawLine( m_iResizePos, 0, m_iResizePos, m_pCanvas->height() );
5735
5736 painter.end();
5737
5738 TQString tmpSize;
5739 if ( m_iResizePos != x )
5740 tmpSize = i18n("Width: %1 %2")
5741 .arg( TDEGlobal::locale()->formatNumber( KoUnit::toUserValue( m_pCanvas->doc()->unzoomItX( (sheet->layoutDirection()==Sheet::RightToLeft) ? x - m_iResizePos : m_iResizePos - x ),
5742 m_pView->doc()->unit() )))
5743 .arg( m_pView->doc()->unitName() );
5744 else
5745 tmpSize = i18n( "Hide Column" );
5746
5747 painter.begin( this );
5748 int len = painter.fontMetrics().width( tmpSize );
5749 int hei = painter.fontMetrics().height();
5750 painter.end();
5751
5752 if ( !m_lSize )
5753 {
5754 m_lSize = new TQLabel( m_pCanvas );
5755
5756 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5757 m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 );
5758 else
5759 m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 );
5760
5761 m_lSize->setAlignment( TQt::AlignVCenter );
5762 m_lSize->setText( tmpSize );
5763 m_lSize->setPalette( TQToolTip::palette() );
5764 m_lSize->show();
5765 }
5766 else
5767 {
5768 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5769 m_lSize->setGeometry( x - len - 5, 3, len + 2, hei + 2 );
5770 else
5771 m_lSize->setGeometry( x + 3, 3, len + 2, hei + 2 );
5772
5773 m_lSize->setText( tmpSize );
5774 }
5775}
5776
5777void HBorder::updateColumns( int from, int to )
5778{
5779 Sheet *sheet = m_pCanvas->activeSheet();
5780 if ( !sheet )
5781 return;
5782
5783 int x0 = sheet->columnPos( from, m_pCanvas );
5784 int x1 = sheet->columnPos( to+1, m_pCanvas );
5785 update( x0, 0, x1-x0, height() );
5786}
5787
5788void HBorder::paintEvent( TQPaintEvent* _ev )
5789{
5790 Sheet * sheet = m_pCanvas->activeSheet();
5791 if ( !sheet )
5792 return;
5793
5794 TQColor highlightColor = View::highlightColor();
5795 TQPainter painter( this );
5796 TQPen pen( TQt::black, 1 );
5797 painter.setPen( pen );
5798 painter.setBackgroundColor( white );
5799
5800 painter.setClipRect( _ev->rect() );
5801
5802 // painter.eraseRect( _ev->rect() );
5803
5804 //TQFontMetrics fm = painter.fontMetrics();
5805 // Matthias Elter: This causes a SEGFAULT in ~TQPainter!
5806 // Only god and the trolls know why ;-)
5807 // bah...took me quite some time to track this one down...
5808
5809 double xPos;
5810 int x;
5811
5812 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5813 {
5814 //Get the left column and the current x-position
5815 x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( width() ) - m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos );
5816 //Align to the offset
5817 xPos = m_pCanvas->d->view->doc()->unzoomItX( width() ) - xPos + m_pCanvas->xOffset();
5818 }
5819 else
5820 {
5821 //Get the left column and the current x-position
5822 x = sheet->leftColumn( int( m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().x() ) + m_pCanvas->xOffset() ), xPos );
5823 //Align to the offset
5824 xPos = xPos - m_pCanvas->xOffset();
5825 }
5826
5827 int height = m_pCanvas->d->view->doc()->zoomItY( TQFont(painter.font()).pointSizeFloat() + 5 );
5828
5829 TQFont normalFont = painter.font();
5830 if ( m_pCanvas->d->view->doc()->zoom() < 100 )
5831 {
5832 normalFont.setPointSizeFloat( 0.01 * m_pCanvas->d->view->doc()->zoom() *
5833 normalFont.pointSizeFloat() );
5834 }
5835 TQFont boldFont = normalFont;
5836 boldFont.setBold( true );
5837
5838 if ( sheet->layoutDirection()==Sheet::RightToLeft )
5839 {
5840 if ( x > KS_colMax )
5841 x = KS_colMax;
5842
5843 xPos -= sheet->columnFormat( x )->dblWidth();
5844
5845 //Loop through the columns, until we are out of range
5846 while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) )
5847 {
5848 bool selected = (m_pView->selectionInfo()->isColumnSelected(x));
5849 bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x));
5850
5851 const ColumnFormat * col_lay = sheet->columnFormat( x );
5852 int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos );
5853 int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos;
5854
5855 if ( selected )
5856 {
5857 TQBrush fillSelected( highlightColor );
5858 qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150),
5859 1, &fillSelected );
5860 }
5861 else if ( highlighted )
5862 {
5863 TQBrush fillHighlighted( highlightColor );
5864 qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(150),
5865 1, &fillHighlighted );
5866 }
5867 else
5868 {
5869 TQColor c = colorGroup().background();
5870 TQBrush fill( c );
5871 qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150),
5872 1, &fill );
5873 }
5874
5875 // Reset painter
5876 painter.setFont( normalFont );
5877 painter.setPen( colorGroup().text() );
5878
5879 if ( selected )
5880 painter.setPen( colorGroup().highlightedText() );
5881 else if ( highlighted )
5882 painter.setFont( boldFont );
5883 if ( !m_pView->activeSheet()->getShowColumnNumber() )
5884 {
5885 TQString colText = Cell::columnName( x );
5886 int len = painter.fontMetrics().width( colText );
5887 if ( !col_lay->isHide() )
5888 painter.drawText( zoomedXPos + ( width - len ) / 2,
5889 ( height + painter.fontMetrics().ascent() -
5890 painter.fontMetrics().descent() ) / 2, colText );
5891 }
5892 else
5893 {
5894 TQString tmp;
5895 int len = painter.fontMetrics().width( tmp.setNum(x) );
5896 if (!col_lay->isHide())
5897 painter.drawText( zoomedXPos + ( width - len ) / 2,
5898 ( height + painter.fontMetrics().ascent() -
5899 painter.fontMetrics().descent() ) / 2,
5900 tmp.setNum(x) );
5901 }
5902 xPos += col_lay->dblWidth();
5903 --x;
5904 }
5905 }
5906 else
5907 {
5908 //Loop through the columns, until we are out of range
5909 while ( xPos <= m_pCanvas->d->view->doc()->unzoomItX( _ev->rect().right() ) )
5910 {
5911 bool selected = (m_pView->selectionInfo()->isColumnSelected(x));
5912 bool highlighted = (!selected && m_pView->selectionInfo()->isColumnAffected(x));
5913
5914 const ColumnFormat *col_lay = sheet->columnFormat( x );
5915 int zoomedXPos = m_pCanvas->d->view->doc()->zoomItX( xPos );
5916 int width = m_pCanvas->d->view->doc()->zoomItX( xPos + col_lay->dblWidth() ) - zoomedXPos;
5917
5918 if ( selected )
5919 {
5920 TQBrush fillSelected( highlightColor );
5921 qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(),
5922 1, &fillSelected );
5923 }
5924 else if ( highlighted )
5925 {
5926 TQBrush fillHighlighted( highlightColor );
5927 qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, highlightColor.dark(),
5928 1, &fillHighlighted );
5929 }
5930 else
5931 {
5932 TQColor c = colorGroup().background();
5933 TQBrush fill( c );
5934 qDrawPlainRect ( &painter, zoomedXPos, 0, width+1, height, c.dark(150),
5935 1, &fill );
5936 }
5937
5938 // Reset painter
5939 painter.setFont( normalFont );
5940 painter.setPen( colorGroup().text() );
5941
5942 if ( selected )
5943 painter.setPen( colorGroup().highlightedText() );
5944 else if ( highlighted )
5945 painter.setFont( boldFont );
5946 if ( !m_pView->activeSheet()->getShowColumnNumber() )
5947 {
5948 TQString colText = Cell::columnName( x );
5949 int len = painter.fontMetrics().width( colText );
5950 if (!col_lay->isHide())
5951 painter.drawText( zoomedXPos + ( width - len ) / 2,
5952 ( height + painter.fontMetrics().ascent() -
5953 painter.fontMetrics().descent() ) / 2, colText );
5954 }
5955 else
5956 {
5957 TQString tmp;
5958 int len = painter.fontMetrics().width( tmp.setNum(x) );
5959 if (!col_lay->isHide())
5960 painter.drawText( zoomedXPos + ( width - len ) / 2,
5961 ( height + painter.fontMetrics().ascent() -
5962 painter.fontMetrics().descent() ) / 2,
5963 tmp.setNum(x) );
5964 }
5965 xPos += col_lay->dblWidth();
5966 ++x;
5967 }
5968 }
5969}
5970
5971
5972void HBorder::focusOutEvent( TQFocusEvent* )
5973{
5974 if ( m_scrollTimer->isActive() )
5975 m_scrollTimer->stop();
5976 m_bMousePressed = false;
5977}
5978
5979/****************************************************************
5980 *
5981 * ToolTip
5982 *
5983 ****************************************************************/
5984
5985ToolTip::ToolTip( Canvas* canvas )
5986 : TQToolTip( canvas ), m_canvas( canvas )
5987{
5988}
5989
5990// find the label for the tip
5991// this is a hack of course, because it's not available from TQToolTip
5992TQLabel *tip_findLabel()
5993{
5994 TQWidgetList *list = TQApplication::allWidgets();
5995 TQWidgetListIt it( *list );
5996 TQWidget * w;
5997 while ( (w=it.current()) != 0 )
5998 {
5999 if(w->isA("TQTipLabel"))
6000 return static_cast<TQLabel*>(w);
6001 ++it;
6002 }
6003 delete list;
6004 return 0;
6005}
6006
6007void ToolTip::maybeTip( const TQPoint& p )
6008{
6009 Sheet *sheet = m_canvas->activeSheet();
6010 if ( !sheet )
6011 return;
6012
6013 // Over which cell is the mouse ?
6014 double ypos, xpos;
6015 double dwidth = m_canvas->doc()->unzoomItX( m_canvas->width() );
6016 int col;
6017 if ( sheet->layoutDirection()==Sheet::RightToLeft )
6018 col = sheet->leftColumn( (dwidth - m_canvas->doc()->unzoomItX( p.x() ) +
6019 m_canvas->xOffset()), xpos );
6020 else
6021 col = sheet->leftColumn( (m_canvas->doc()->unzoomItX( p.x() ) +
6022 m_canvas->xOffset()), xpos );
6023
6024
6025 int row = sheet->topRow( (m_canvas->doc()->unzoomItY( p.y() ) +
6026 m_canvas->yOffset()), ypos );
6027
6028 const Cell* cell = sheet->visibleCellAt( col, row );
6029 if ( !cell )
6030 return;
6031
6032#if 0
6033 // Quick cut
6034 if( cell->strOutText().isEmpty() )
6035 return;
6036#endif
6037 // displayed tool tip, which has the following priorities:
6038 // - cell content if the cell dimension is too small
6039 // - cell comment
6040 // - hyperlink
6041 TQString tipText;
6042 TQString comment = cell->format()->comment( col, row );
6043
6044 // If cell is too small, show the content
6045 if ( cell->testFlag( Cell::Flag_CellTooShortX ) ||
6046 cell->testFlag( Cell::Flag_CellTooShortY ) )
6047 {
6048 tipText = cell->strOutText();
6049 }
6050
6051 // Show hyperlink, if any
6052 if ( tipText.isEmpty() )
6053 {
6054 tipText = cell->link();
6055 }
6056
6057 // Nothing to display, bail out
6058 if ( tipText.isEmpty() && comment.isEmpty() )
6059 return;
6060
6061 // Cut if the tip is ridiculously long
6062 const unsigned maxLen = 256;
6063 if ( tipText.length() > maxLen )
6064 tipText = tipText.left(maxLen).append("...");
6065
6066 // Determine position and width of the current cell.
6067 double u = cell->dblWidth( col );
6068 double v = cell->dblHeight( row );
6069
6070 // Special treatment for obscured cells.
6071 if ( cell->isObscured() && cell->isPartOfMerged() )
6072 {
6073 cell = cell->obscuringCells().first();
6074 const int moveX = cell->column();
6075 const int moveY = cell->row();
6076
6077 // Use the obscuring cells dimensions
6078 u = cell->dblWidth( moveX );
6079 v = cell->dblHeight( moveY );
6080 xpos = sheet->dblColumnPos( moveX );
6081 ypos = sheet->dblRowPos( moveY );
6082 }
6083
6084 // Get the cell dimensions
6085 TQRect marker;
6086 bool insideMarker = false;
6087
6088 if ( sheet->layoutDirection()==Sheet::RightToLeft )
6089 {
6090 KoRect unzoomedMarker( dwidth - u - xpos + m_canvas->xOffset(),
6091 ypos - m_canvas->yOffset(),
6092 u,
6093 v );
6094
6095 marker = m_canvas->doc()->zoomRect( unzoomedMarker );
6096 insideMarker = marker.contains( p );
6097 }
6098 else
6099 {
6100 KoRect unzoomedMarker( xpos - m_canvas->xOffset(),
6101 ypos - m_canvas->yOffset(),
6102 u,
6103 v );
6104
6105 marker = m_canvas->doc()->zoomRect( unzoomedMarker );
6106 insideMarker = marker.contains( p );
6107 }
6108
6109 // No use if mouse is somewhere else
6110 if ( !insideMarker )
6111 return;
6112
6113 // Find the tipLabel
6114 // NOTE: if we failed, check again when the tip is shown already
6115 TQLabel* tipLabel = tip_findLabel();
6116
6117 // Ensure that it is plain text
6118 // Not funny if (intentional or not) <a> appears as hyperlink
6119 if ( tipLabel )
6120 tipLabel->setTextFormat( TQt::PlainText );
6121
6122 TQFontMetrics fm = tipLabel ? tipLabel->fontMetrics() : m_canvas->fontMetrics();
6123 const TQRect r( 0, 0, 200, -1 );
6124 // Wrap the text if too long
6125 if ( tipText.length() > 16 )
6126 {
6127 KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, tipText );
6128 tipText = wrap->wrappedString();
6129 delete wrap;
6130 }
6131 // Wrap the comment if too long
6132 if ( comment.length() > 16 )
6133 {
6134 KWordWrap* wrap = KWordWrap::formatText( fm, r, 0, comment );
6135 comment = wrap->wrappedString();
6136 delete wrap;
6137 }
6138
6139 // Show comment, if any
6140 if ( tipText.isEmpty() )
6141 {
6142 tipText = comment;
6143 }
6144 else if ( !comment.isEmpty() )
6145 {
6146 //Add 2 extra lines and a text, when both should be in the tooltip
6147 if ( !comment.isEmpty() )
6148 comment = "\n\n" + i18n("Comment:") + "\n" + comment;
6149
6150 tipText += comment;
6151 }
6152
6153 // Now we shows the tip
6154 tip( marker, tipText );
6155
6156 // Here we try to find the tip label again
6157 // Reason: the previous tip_findLabel might fail if no tip has ever shown yet
6158 if ( !tipLabel )
6159 {
6160 tipLabel = tip_findLabel();
6161 if( tipLabel )
6162 tipLabel->setTextFormat( TQt::PlainText );
6163 }
6164
6165}
6166
6167#include "kspread_canvas.moc"
The canvas builds a part of the GUI of KSpread.
int markerRow() const
convenience function.
TQPoint marker() const
convenience function.
TQRect visibleCells() const
bool highlightRangeSizeGripAt(double x, double y)
Checks to see if there is a size grip for a highlight range at a given position.
void moveObjectsByMouse(KoPoint &pos, bool keepXorYunchanged)
Move object by mouse.
void closeEditor()
Close the cell editor and saves changes.
double autoScrollAccelerationY(int offset)
Depending on the offset in "zoomed" screen pixels for the vertical direction, the function returns th...
void scrollToCell(TQPoint location) const
Makes sure a cell is visible onscreen by scrolling up/down and left/right.
void validateSelection()
Validates the selected cell.
void deleteEditor(bool saveChanges, bool array=false)
Deletes the current cell editor.
void lowerObject()
Don't display an object above the others.
void displayObjectList(TQPtrList< EmbeddedObject > &list)
Get the list of objects in the order they should be displayed.
const TQPen & defaultGridPen() const
void finishResizeObject(const TQString &name, bool layout=true)
create KPrResizeCmd
void setXOffset(double _xOffset)
Sets the width of the columns before the current screen.
void setChooseMode(bool state)
Switches the choose mode on and off.
void resizeObject(ModifyType _modType, const KoPoint &point, bool keepRatio)
resize the m_resizeObject
int markerColumn() const
convenience function.
TQRect selection() const
double yOffset() const
void paintUpdates()
Paint all visible cells that have a paint dirty flag set.
void raiseObject(EmbeddedObject *object)
Display object above the other objects in editiong mode.
void endChoose()
Switches to selection mode.
MouseActions
The current action associated with the mouse.
@ ResizeCell
Merging cell.
@ NoAction
No mouse action (default)
@ ResizeSelection
Resizing the selection.
@ AutoFill
Autofilling.
@ Mark
Marking action.
void startChoose()
Switches to choose mode and sets the initial selection to the position returned by marker().
void createEditor(bool captureArrowKeys=false)
Chooses the correct EditorType by looking at the current cells value.
Selection * choice() const
void setYOffset(double _yOffset)
Sets the height of the rows before the current screen.
bool chooseMode() const
double zoom() const
convenience function
Selection * selectionInfo() const
Sheet * findSheet(const TQString &_name) const
convenience function
void copyOasisObjects()
This is intended to copy the selected objects to the clipboard so that they can be pasted into other ...
void updatePosWidget()
Updates the position widget.
void setLastEditorWithFocus(EditorType type)
Called from EditWidget and CellEditor if they loose the focus because the user started a "choose sele...
Sheet * activeSheet() const
double xOffset() const
double autoScrollAccelerationX(int offset)
Depending on the offset in "zoomed" screen pixels for the horizontal direction, the function returns ...
class CellEditor
For every cell in the spread sheet there is a Cell object.
double dblHeight(int _row=-1, const Canvas *_canvas=0L) const
const TQPen & effBottomBorderPen(int col, int row) const
TQString link() const
Returns the link associated with cell.
bool calc(bool delay=true)
Starts calculating.
TQString text() const
Return the text the user entered.
TQString name() const
Returns the name of the cell.
int row() const
Returns the cell's row.
void setRightBorderPen(const TQPen &p)
void convertToDate()
converts content to date format
TQValueList< Cell * > obscuringCells() const
bool isObscured() const
int column() const
Returns the cell's column.
bool calcDirtyFlag()
Checks the calcDirtyFlag.
void paintCell(const KoRect &rect, TQPainter &painter, View *view, const KoPoint &coordinate, const TQPoint &cellRef, int paintBorder, TQPen &rightPen, TQPen &bottomPen, TQPen &leftPen, TQPen &topPen, TQValueList< TQPoint > &mergedCellsPainted, bool drawCursor=true)
Paints the cell.
bool isEmpty() const
Returns true if this cell has no content, i.e no text and no formula.
uint effRightBorderValue(int col, int row) const
const TQPen & effTopBorderPen(int col, int row) const
int mergedXCells() const
void setTopBorderPen(const TQPen &p)
const TQPen & effRightBorderPen(int col, int row) const
void convertToPercent()
converts content to percentageformat
bool isFormula() const
Returns true if this cell holds a formula.
uint effLeftBorderValue(int col, int row) const
uint effTopBorderValue(int col, int row) const
void convertToMoney()
converts content to money format
const TQPen & effLeftBorderPen(int col, int row) const
Format * format() const
Returns the format object of this cell.
void setBottomBorderPen(const TQPen &p)
void convertToTime()
converts content to time format
void makeLayout(TQPainter &_painter, int _col, int _row)
Calculates the layout of the cell, i,e, determines what should be shown for this cell,...
double dblWidth(int _col=-1, const Canvas *_canvas=0L) const
uint effBottomBorderValue(int col, int row) const
void convertToDouble()
converts content to double format
TQString columnName() const
Returns the column name of the cell.
bool isDefault() const
Returns true if this is a default cell (with row and column equal to zero).
const TQColor & bgColor(int col, int row) const
bool isPartOfMerged() const
If this cell is part of a merged cell, then the marker may never reside on this cell.
int mergedYCells() const
void setLeftBorderPen(const TQPen &p)
ComboboxLocationEditWidget.
This class holds the data that makes up a spreadsheet.
Definition kspread_doc.h:98
void addCommand(KCommand *command)
Adds a command to the command history.
TQString unitName() const
Returns the name of the unit used to display margins.
The widget that appears above the sheet and allows to edit the cells content.
Holds an embedded koffice object.
Contains basic information for every object.
The one for all class for points and ranges.
Definition region.h:44
This is a class for handling clipboard data.
Tooltip, which displays the comment and cell content, when it's too short.
void maybeTip(const TQPoint &p)
The View class displays a KSpread document.
ComboboxLocationEditWidget * posWidget() const
Returns the location widget.
static TQColor highlightColor()
Returns the default color for highlighting cells and column / row headers.
void resetInsertHandle()
Resets the internal handle pointer, called from InsertHandler destructor.
void updateEditWidget()
Fills the EditWidget with the current cells content.
@ OverWrite
Overwrite.
@ Normal
Everything.
The KSpread namespace.
Definition commands.h:39