KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6168 lines
173KB

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