00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "Canvas.h"
00046 #include "Canvas_p.h"
00047
00048
00049 #include <assert.h>
00050 #include <float.h>
00051 #include <stdlib.h>
00052
00053
00054 #include <QApplication>
00055 #include <QBuffer>
00056 #include <QByteArray>
00057 #include <QClipboard>
00058 #include <QDragLeaveEvent>
00059 #include <QDragMoveEvent>
00060 #include <QDropEvent>
00061 #include <QEvent>
00062 #include <QFocusEvent>
00063 #include <QKeyEvent>
00064 #include <QLabel>
00065 #include <QList>
00066 #include <QMenu>
00067 #include <QMouseEvent>
00068 #include <QPainter>
00069 #include <QPaintEvent>
00070 #include <QPixmap>
00071 #include <QPoint>
00072 #include <QScrollBar>
00073 #include <QTextStream>
00074 #include <QToolTip>
00075 #include <QWidget>
00076
00077
00078 #include <kcursor.h>
00079 #include <kdebug.h>
00080 #include <kmessagebox.h>
00081 #include <krun.h>
00082 #include <kmimetype.h>
00083 #include <ksharedptr.h>
00084 #include <kwordwrap.h>
00085 #include <kxmlguifactory.h>
00086
00087
00088 #include <KoCanvasController.h>
00089 #include <KoShapeManager.h>
00090 #include <KoStore.h>
00091 #include <KoToolManager.h>
00092 #include <KoToolProxy.h>
00093 #include <KoXmlWriter.h>
00094 #include <KoZoomHandler.h>
00095
00096
00097 #include "CellStorage.h"
00098 #include "CellView.h"
00099 #include "Doc.h"
00100 #include "Editors.h"
00101 #include "Global.h"
00102 #include "Headers.h"
00103 #include "Localization.h"
00104 #include "Map.h"
00105 #include "RowColumnFormat.h"
00106 #include "Selection.h"
00107 #include "Sheet.h"
00108 #include "SheetView.h"
00109 #include "Util.h"
00110 #include "Validity.h"
00111 #include "View.h"
00112
00113
00114 #include "commands/DeleteCommand.h"
00115 #include "commands/StyleCommand.h"
00116 #include "commands/Undo.h"
00117
00118 #define MIN_SIZE 10
00119
00120 using namespace KSpread;
00121
00122
00123
00124
00125
00126
00127
00128 Canvas::Canvas(View *view)
00129 : QWidget( view )
00130 , KoCanvasBase(0)
00131 , d( new Private )
00132 {
00133 setAttribute( Qt::WA_OpaquePaintEvent );
00134 setAttribute( Qt::WA_StaticContents );
00135 setBackgroundRole(QPalette::Base);
00136
00137 d->validationInfo = 0;
00138
00139 QWidget::setFocusPolicy( Qt::StrongFocus );
00140
00141 d->offset = QPointF( 0.0, 0.0 );
00142
00143 d->view = view;
00144
00145 setMouseTracking( true );
00146 d->mousePressed = false;
00147 d->dragging = false;
00148
00149 connect( d->view, SIGNAL( autoScroll( const QPoint & )),
00150 this, SLOT( slotAutoScroll( const QPoint &)));
00151
00152 installEventFilter( this );
00153 setAcceptDrops( true );
00154 setAttribute(Qt::WA_InputMethodEnabled, true);
00155
00156
00157 d->shapeManager = new KoShapeManager( this );
00158 d->toolProxy = new KoToolProxy( this );
00159 }
00160
00161 Canvas::~Canvas()
00162 {
00163 delete d->shapeManager;
00164 delete d->toolProxy;
00165 delete d->validationInfo;
00166 delete d;
00167 }
00168
00169 View* Canvas::view() const
00170 {
00171 return d->view;
00172 }
00173
00174 Doc* Canvas::doc() const
00175 {
00176 return d->view->doc();
00177 }
00178
00179 void Canvas::gridSize( qreal* horizontal, qreal* vertical ) const
00180 {
00181 *horizontal = doc()->map()->defaultColumnFormat()->width();
00182 *vertical = doc()->map()->defaultRowFormat()->height();
00183 }
00184
00185 bool Canvas::snapToGrid() const
00186 {
00187 return false;
00188 }
00189
00190 void Canvas::addCommand( QUndoCommand* command )
00191 {
00192 doc()->addCommand( command );
00193 }
00194
00195 KoShapeManager* Canvas::shapeManager() const
00196 {
00197 return d->shapeManager;
00198 }
00199
00200 void Canvas::updateCanvas( const QRectF& rc )
00201 {
00202 QRect clipRect( viewConverter()->documentToView( rc.translated( -offset() ) ).toRect() );
00203 clipRect.adjust( -2, -2, 2, 2 );
00204 update( clipRect );
00205 }
00206
00207 const KoViewConverter* Canvas::viewConverter() const
00208 {
00209 return view()->zoomHandler();
00210 }
00211
00212 KoUnit Canvas::unit() const
00213 {
00214 return doc()->unit();
00215 }
00216
00217 KoToolProxy* Canvas::toolProxy() const
00218 {
00219 return d->toolProxy;
00220 }
00221
00222 QPointF Canvas::offset() const
00223 {
00224 return d->offset;
00225 }
00226
00227 double Canvas::xOffset() const
00228 {
00229 return d->offset.x();
00230 }
00231
00232 double Canvas::yOffset() const
00233 {
00234 return d->offset.y();
00235 }
00236
00237 bool Canvas::eventFilter( QObject *o, QEvent *e )
00238 {
00239
00240
00241
00242 if ( !o || !e )
00243 return true;
00244 switch ( e->type() )
00245 {
00246 case QEvent::KeyPress:
00247 {
00248 QKeyEvent * keyev = static_cast<QKeyEvent *>(e);
00249 if ((keyev->key()==Qt::Key_Tab) || (keyev->key()==Qt::Key_Backtab))
00250 {
00251 keyPressEvent ( keyev );
00252 return true;
00253 }
00254 break;
00255 }
00256 case QEvent::InputMethod:
00257 {
00258
00259
00260
00261 }
00262 case QEvent::ToolTip:
00263 {
00264 QHelpEvent* helpEvent = static_cast<QHelpEvent*>( e );
00265 showToolTip( helpEvent->pos() );
00266 }
00267 default:
00268 break;
00269 }
00270 return false;
00271 }
00272
00273 Selection* Canvas::selection() const
00274 {
00275 return d->view->selection();
00276 }
00277
00278 ColumnHeader* Canvas::columnHeader() const
00279 {
00280 return d->view->columnHeader();
00281 }
00282
00283 RowHeader* Canvas::rowHeader() const
00284 {
00285 return d->view->rowHeader();
00286 }
00287
00288 QScrollBar* Canvas::horzScrollBar() const
00289 {
00290 return d->view->horzScrollBar();
00291 }
00292
00293 QScrollBar* Canvas::vertScrollBar() const
00294 {
00295 return d->view->vertScrollBar();
00296 }
00297
00298 Sheet* Canvas::activeSheet() const
00299 {
00300 return d->view->activeSheet();
00301 }
00302
00303 void Canvas::validateSelection()
00304 {
00305 register Sheet * const sheet = activeSheet();
00306 if (!sheet)
00307 return;
00308
00309 if ( selection()->isSingular() )
00310 {
00311 int col = selection()->marker().x();
00312 int row = selection()->marker().y();
00313 Cell cell( sheet, col,row );
00314 Validity validity = cell.validity();
00315 if ( validity.displayValidationInformation() )
00316 {
00317 QString title = validity.titleInfo();
00318 QString message = validity.messageInfo();
00319 if ( title.isEmpty() && message.isEmpty() )
00320 return;
00321
00322 if ( !d->validationInfo )
00323 d->validationInfo = new QLabel( this );
00324 kDebug(36001)<<" display info validation";
00325 double u = cell.width();
00326 double v = cell.height();
00327 double xpos = sheet->columnPosition( selection()->marker().x() ) - xOffset();
00328 double ypos = sheet->rowPosition( selection()->marker().y() ) - yOffset();
00329
00330 if ( cell.isPartOfMerged() )
00331 {
00332 cell = cell.masterCell();
00333 int moveX = cell.column();
00334 int moveY = cell.row();
00335
00336
00337 u = cell.width();
00338 v = cell.height();
00339 xpos = sheet->columnPosition( moveX );
00340 ypos = sheet->rowPosition( moveY );
00341 }
00342
00343 d->validationInfo->setAlignment( Qt::AlignVCenter );
00344 QPainter painter;
00345 painter.begin( this );
00346 int len = 0;
00347 int hei = 0;
00348 QString resultText;
00349 if ( !title.isEmpty() )
00350 {
00351 len = painter.fontMetrics().width( title );
00352 hei = painter.fontMetrics().height();
00353 resultText = title + '\n';
00354 }
00355 if ( !message.isEmpty() )
00356 {
00357 int i = 0;
00358 int pos = 0;
00359 QString t;
00360 do
00361 {
00362 i = message.indexOf( "\n", pos );
00363 if ( i == -1 )
00364 t = message.mid( pos, message.length() - pos );
00365 else
00366 {
00367 t = message.mid( pos, i - pos );
00368 pos = i + 1;
00369 }
00370 hei += painter.fontMetrics().height();
00371 len = qMax( len, painter.fontMetrics().width( t ) );
00372 }
00373 while ( i != -1 );
00374 resultText += message;
00375 }
00376 painter.end();
00377 d->validationInfo->setText( resultText );
00378
00379 QRectF unzoomedMarker( xpos - xOffset()+u,
00380 ypos - yOffset()+v,
00381 len,
00382 hei );
00383 QRectF marker( viewConverter()->documentToView( unzoomedMarker ) );
00384
00385 d->validationInfo->setGeometry( marker.toRect() );
00386 d->validationInfo->show();
00387 }
00388 else
00389 {
00390 delete d->validationInfo;
00391 d->validationInfo = 0;
00392 }
00393 }
00394 else
00395 {
00396 delete d->validationInfo;
00397 d->validationInfo = 0;
00398 }
00399 }
00400
00401
00402 void Canvas::scrollToCell(const QPoint& location) const
00403 {
00404 register Sheet * const sheet = activeSheet();
00405 if (!sheet)
00406 return;
00407 if (d->view->isLoading())
00408 return;
00409
00410
00411 view()->sheetView(sheet)->updateAccessedCellRange(location);
00412
00413
00414 const Cell cell = Cell(sheet, location).masterCell();
00415 const double xpos = sheet->columnPosition(cell.cellPosition().x());
00416 const double ypos = sheet->rowPosition(cell.cellPosition().y());
00417 const double width = sheet->map()->defaultColumnFormat()->width();
00418 const double height = sheet->map()->defaultRowFormat()->height();
00419 QRectF rect(xpos, ypos, cell.width(), cell.height());
00420 rect.adjust(-width-2, -height-2, width+2, height+2);
00421 rect = rect & QRectF(QPointF(0.0, 0.0), sheet->documentSize());
00422
00423 d->view->canvasController()->ensureVisible(rect, true);
00424 }
00425
00426 void Canvas::setDocumentOffset( const QPoint& offset )
00427 {
00428 const QPoint delta = offset - viewConverter()->documentToView( d->offset ).toPoint();
00429 d->offset = viewConverter()->viewToDocument( offset );
00430
00431 columnHeader()->scroll(delta.x(), 0);
00432 rowHeader()->scroll(0, delta.y());
00433 }
00434
00435 void Canvas::setDocumentSize( const QSizeF& size )
00436 {
00437 const QSize s = viewConverter()->documentToView( size ).toSize();
00438 emit documentSizeChanged( s );
00439 }
00440
00441 #if 0
00442 void Canvas::slotScrollHorz( int _value )
00443 {
00444 register Sheet * const sheet = activeSheet();
00445 if (!sheet)
00446 return;
00447
00448 kDebug(36005) <<"slotScrollHorz: value =" << _value;
00449
00450
00451 if ( sheet->layoutDirection() == Qt::RightToLeft )
00452 _value = horzScrollBar()->maximum() - _value;
00453
00454 if ( _value < 0 ) {
00455 kDebug (36001)
00456 << "Canvas::slotScrollHorz: value out of range (_value: "
00457 << _value << ')' << endl;
00458 _value = 0;
00459 }
00460
00461 double xpos = sheet->columnPosition( qMin( KS_colMax, sheet->maxColumn()+10 ) ) - d->xOffset;
00462 if ( _value > ( xpos + d->xOffset ) )
00463 _value = (int) ( xpos + d->xOffset );
00464
00465
00466
00467 int dx = qRound( viewConverter()->documentToViewX( d->xOffset - _value ) );
00468
00469
00470
00471 d->xOffset -= viewConverter()->viewToDocumentX( dx );
00472 if ( d->xOffset < 0.05 )
00473 d->xOffset = 0.0;
00474
00475
00476 if ( sheet->layoutDirection() == Qt::RightToLeft )
00477 dx = -dx;
00478 scroll( dx, 0 );
00479 columnHeader()->scroll( dx, 0 );
00480 }
00481
00482 void Canvas::slotScrollVert( int _value )
00483 {
00484 register Sheet * const sheet = activeSheet();
00485 if (!sheet)
00486 return;
00487
00488 if ( _value < 0 )
00489 {
00490 _value = 0;
00491 kDebug (36001) <<"Canvas::slotScrollVert: value out of range (_value:" <<
00492 _value << ')' << endl;
00493 }
00494
00495 double ypos = sheet->rowPosition( qMin( KS_rowMax, sheet->maxRow()+10 ) );
00496 if ( _value > ypos )
00497 _value = (int) ypos;
00498
00499
00500
00501 int dy = qRound( viewConverter()->documentToViewY( d->yOffset - _value ) );
00502 scroll( 0, dy );
00503 rowHeader()->scroll( 0, dy );
00504
00505
00506
00507 d->yOffset -= viewConverter()->viewToDocumentY( dy );
00508 if ( d->yOffset < 0.05 )
00509 d->yOffset = 0.0;
00510 }
00511
00512 void Canvas::slotMaxColumn( int _max_column )
00513 {
00514 register Sheet * const sheet = activeSheet();
00515 if (!sheet)
00516 return;
00517
00518 int oldValue = horzScrollBar()->maximum() - horzScrollBar()->value();
00519 double xpos = sheet->columnPosition( qMin( KS_colMax, _max_column + 10 ) ) - xOffset();
00520 double unzoomWidth = viewConverter()->viewToDocumentX( width() );
00521
00522
00523 double sizeMaxX = sheet->documentSize().width();
00524 if ( xpos > sizeMaxX - xOffset() - unzoomWidth )
00525 xpos = sizeMaxX - xOffset() - unzoomWidth;
00526
00527 horzScrollBar()->setRange( 0, (int) ( xpos + xOffset() ) );
00528
00529 if ( sheet->layoutDirection() == Qt::RightToLeft )
00530 horzScrollBar()->setValue( horzScrollBar()->maximum() - oldValue );
00531 }
00532
00533 void Canvas::slotMaxRow( int _max_row )
00534 {
00535 register Sheet * const sheet = activeSheet();
00536 if (!sheet)
00537 return;
00538
00539 double ypos = sheet->rowPosition( qMin( KS_rowMax, _max_row + 10 ) ) - yOffset();
00540 double unzoomHeight = viewConverter()->viewToDocumentY( height() );
00541
00542
00543 double sizeMaxY = sheet->documentSize().height();
00544 if ( ypos > sizeMaxY - yOffset() - unzoomHeight )
00545 ypos = sizeMaxY - yOffset() - unzoomHeight;
00546
00547 vertScrollBar()->setRange( 0, (int) ( ypos + yOffset() ) );
00548 }
00549 #endif
00550
00551 void Canvas::mousePressEvent( QMouseEvent* event )
00552 {
00553
00554 d->toolProxy->mousePressEvent( event, viewConverter()->viewToDocument( event->pos() ) + offset() );
00555
00556 if (!event->isAccepted() && event->button() == Qt::RightButton)
00557 {
00558 d->view->unplugActionList("toolproxy_action_list");
00559 d->view->plugActionList("toolproxy_action_list", toolProxy()->popupActionList());
00560 QMenu* menu = dynamic_cast<QMenu*>(d->view->factory()->container("default_canvas_popup", d->view));
00561
00562 if (menu && menu->actions().count() > 1) {
00563 menu->exec(event->globalPos());
00564 }
00565 event->setAccepted(true);
00566 }
00567 }
00568
00569 void Canvas::mouseReleaseEvent( QMouseEvent* event )
00570 {
00571
00572 d->toolProxy->mouseReleaseEvent( event, viewConverter()->viewToDocument( event->pos() ) + offset() );
00573 }
00574
00575 void Canvas::mouseMoveEvent( QMouseEvent* event )
00576 {
00577
00578 d->toolProxy->mouseMoveEvent( event, viewConverter()->viewToDocument( event->pos() ) + offset() );
00579 }
00580
00581 void Canvas::mouseDoubleClickEvent( QMouseEvent* event )
00582 {
00583
00584 d->toolProxy->mouseDoubleClickEvent( event, viewConverter()->viewToDocument( event->pos() ) + offset() );
00585 }
00586
00587 void Canvas::keyPressEvent ( QKeyEvent* event )
00588 {
00589
00590 d->toolProxy->keyPressEvent( event );
00591 }
00592
00593 void Canvas::tabletEvent(QTabletEvent *e)
00594 {
00595
00596 d->toolProxy->tabletEvent(e, viewConverter()->viewToDocument(e->pos() + offset()));
00597 }
00598
00599 QVariant Canvas::inputMethodQuery(Qt::InputMethodQuery query) const
00600 {
00601
00602 return d->toolProxy->inputMethodQuery(query, *(viewConverter()));
00603 }
00604
00605 void Canvas::inputMethodEvent(QInputMethodEvent *event)
00606 {
00607
00608 d->toolProxy->inputMethodEvent(event);
00609 }
00610
00611 bool Canvas::highlightRangeSizeGripAt(double x, double y)
00612 {
00613 if ( !selection()->referenceSelectionMode() )
00614 return false;
00615
00616 Region::ConstIterator end = selection()->constEnd();
00617 for (Region::ConstIterator it = selection()->constBegin(); it != end; ++it)
00618 {
00619
00620 QRectF visibleRect = activeSheet()->cellCoordinatesToDocument( (*it)->rect() );
00621
00622 QPoint bottomRight((int) visibleRect.right(), (int) visibleRect.bottom());
00623 QRect handle( ( (int) bottomRight.x() - 6 ),
00624 ( (int) bottomRight.y() - 6 ),
00625 ( 6 ),
00626 ( 6 ) );
00627
00628 if (handle.contains(QPoint((int) x,(int) y)))
00629 {
00630 return true;
00631 }
00632 }
00633
00634 return false;
00635 }
00636
00637 void Canvas::startTheDrag()
00638 {
00639 register Sheet * const sheet = activeSheet();
00640 if (!sheet)
00641 return;
00642
00643
00644 setCursor( Qt::PointingHandCursor );
00645
00646 QDomDocument doc = sheet->saveCellRegion(*selection(), true);
00647
00648
00649 QBuffer buffer;
00650 buffer.open( QIODevice::WriteOnly );
00651 QTextStream str( &buffer );
00652 str.setCodec( "UTF-8" );
00653 str << doc;
00654 buffer.close();
00655
00656 QMimeData* mimeData = new QMimeData();
00657 mimeData->setText( sheet->copyAsText( selection() ) );
00658 mimeData->setData( "application/x-kspread-snippet", buffer.buffer() );
00659
00660 QDrag *drag = new QDrag(this);
00661 drag->setMimeData( mimeData );
00662 drag->start();
00663
00664 setCursor( Qt::ArrowCursor );
00665 }
00666
00667 void Canvas::paintEvent( QPaintEvent* event )
00668 {
00669 if ( d->view->doc()->isLoading() || d->view->isLoading() )
00670 return;
00671
00672 register Sheet * const sheet = activeSheet();
00673 if (!sheet)
00674 return;
00675
00676 ElapsedTime et( "Painting cells", ElapsedTime::PrintOnlyTime );
00677
00678 QPainter painter(this);
00679 const QPointF offset = viewConverter()->documentToView(this->offset());
00680 painter.translate(-offset);
00681 painter.setClipRegion(event->region().translated(offset.x(), offset.y()));
00682 painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing );
00683 painter.save();
00684
00685 qreal zoomX, zoomY;
00686 viewConverter()->zoom(&zoomX, &zoomY);
00687 painter.scale(zoomX, zoomY);
00688
00689
00690 const QRectF paintRect = viewConverter()->viewToDocument(rect()).translated(this->offset());
00691 painter.fillRect(paintRect, painter.background());
00692
00693
00694 const QRect visibleRect = visibleCells();
00695 const QPointF topLeft(sheet->columnPosition(visibleRect.left()), sheet->rowPosition(visibleRect.top()));
00696 view()->sheetView( sheet )->setPaintCellRange( visibleRect );
00697 view()->sheetView( sheet )->paintCells( this, painter, paintRect, topLeft );
00698
00699
00700 painter.restore();
00701 d->shapeManager->paint( painter, *viewConverter(), false );
00702 painter.setRenderHint( QPainter::Antialiasing, false );
00703 d->toolProxy->paint( painter, *viewConverter() );
00704
00705 event->accept();
00706 }
00707
00708 void Canvas::focusInEvent( QFocusEvent* )
00709 {
00710
00711
00712
00713 selection()->emitRequestFocusEditor();
00714 }
00715
00716 void Canvas::focusOutEvent( QFocusEvent* )
00717 {
00718 d->mousePressed = false;
00719 d->view->disableAutoScroll();
00720 }
00721
00722 void Canvas::dragEnterEvent( QDragEnterEvent* event )
00723 {
00724 const QMimeData* mimeData = event->mimeData();
00725 if ( mimeData->hasText() ||
00726 mimeData->hasFormat( "application/x-kspread-snippet" ) )
00727 {
00728 event->acceptProposedAction();
00729 }
00730 }
00731
00732 void Canvas::dragMoveEvent( QDragMoveEvent* event )
00733 {
00734 register Sheet * const sheet = activeSheet();
00735 if (!sheet)
00736 {
00737 event->ignore();
00738 return;
00739 }
00740
00741 const QMimeData* mimeData = event->mimeData();
00742 if ( mimeData->hasText() || mimeData->hasFormat( "application/x-kspread-snippet" ) )
00743 {
00744 event->acceptProposedAction();
00745 }
00746 else
00747 {
00748 event->ignore();
00749 return;
00750 }
00751 #if 0 // TODO Stefan: implement drag marking rectangle
00752 QRect dragMarkingRect;
00753 if ( mimeData->hasFormat( "application/x-kspread-snippet" ) )
00754 {
00755 if ( event->source() == this )
00756 {
00757 kDebug(36005) <<"source == this";
00758 dragMarkingRect = selection()->boundingRect();
00759 }
00760 else
00761 {
00762 kDebug(36005) <<"source != this";
00763 QByteArray data = mimeData->data( "application/x-kspread-snippet" );
00764 QString errorMsg;
00765 int errorLine;
00766 int errorColumn;
00767 QDomDocument doc;
00768 if ( !doc.setContent( data, false, &errorMsg, &errorLine, &errorColumn ) )
00769 {
00770
00771 kDebug(36005) <<"Canvas::daragMoveEvent: an error occurred" << endl
00772 << "line: " << errorLine << " col: " << errorColumn
00773 << ' ' << errorMsg << endl;
00774 dragMarkingRect = QRect(1,1,1,1);
00775 }
00776 else
00777 {
00778 QDomElement root = doc.documentElement();
00779 dragMarkingRect = QRect(1,1,
00780 root.attribute( "columns" ).toInt(),
00781 root.attribute( "rows" ).toInt());
00782 }
00783 }
00784 }
00785 else
00786 {
00787 kDebug(36005) <<"has text";
00788 dragMarkingRect = QRect(1,1,1,1);
00789 }
00790 #endif
00791 const QPoint dragAnchor = selection()->boundingRect().topLeft();
00792 double xpos = sheet->columnPosition( dragAnchor.x() );
00793 double ypos = sheet->rowPosition( dragAnchor.y() );
00794 double width = sheet->columnFormat( dragAnchor.x() )->width();
00795 double height = sheet->rowFormat( dragAnchor.y() )->height();
00796
00797
00798 const QRectF noGoArea( xpos - 1, ypos - 1, width + 3, height + 3 );
00799
00800
00801 double eventPosX;
00802 if (sheet->layoutDirection() == Qt::RightToLeft)
00803 {
00804 eventPosX = this->width() - viewConverter()->viewToDocumentX( event->pos().x() ) + xOffset();
00805 }
00806 else
00807 {
00808 eventPosX = viewConverter()->viewToDocumentX( event->pos().x() ) + xOffset();
00809 }
00810 double eventPosY = viewConverter()->viewToDocumentY( event->pos().y() ) + yOffset();
00811
00812 if ( noGoArea.contains( QPointF( eventPosX, eventPosY ) ) )
00813 {
00814 event->ignore( noGoArea.toRect() );
00815 return;
00816 }
00817
00818 #if 0 // TODO Stefan: implement drag marking rectangle
00819
00820 double tmp;
00821 const int col = sheet->leftColumn( eventPosX, tmp );
00822 const int row = sheet->topRow( eventPosY, tmp );
00823 dragMarkingRect.moveTo( QPoint( col, row ) );
00824 kDebug(36005) <<"MARKING RECT =" << dragMarkingRect;
00825 #endif
00826 }
00827
00828 void Canvas::dragLeaveEvent( QDragLeaveEvent * )
00829 {
00830 }
00831
00832 void Canvas::dropEvent( QDropEvent * _ev )
00833 {
00834 d->dragging = false;
00835 d->view->disableAutoScroll();
00836 register Sheet * const sheet = activeSheet();
00837 if ( !sheet || sheet->isProtected() )
00838 {
00839 _ev->ignore();
00840 return;
00841 }
00842
00843 double xpos = sheet->columnPosition( selection()->lastRange().left() );
00844 double ypos = sheet->rowPosition( selection()->lastRange().top() );
00845 double width = sheet->columnFormat( selection()->lastRange().left() )->width();
00846 double height = sheet->rowFormat( selection()->lastRange().top() )->height();
00847
00848 const QRectF noGoArea( xpos - 1, ypos - 1, width + 3, height + 3 );
00849
00850 double ev_PosX;
00851 if ( sheet->layoutDirection() == Qt::RightToLeft )
00852 ev_PosX = this->width() - viewConverter()->viewToDocumentX( _ev->pos().x() ) + xOffset();
00853 else
00854 ev_PosX = viewConverter()->viewToDocumentX( _ev->pos().x() ) + xOffset();
00855
00856 double ev_PosY = viewConverter()->viewToDocumentY( _ev->pos().y() ) + yOffset();
00857
00858 if ( noGoArea.contains( QPointF( ev_PosX, ev_PosY ) ) )
00859 {
00860 _ev->ignore();
00861 return;
00862 }
00863 else
00864 _ev->setAccepted(true);
00865
00866 double tmp;
00867 int col = sheet->leftColumn( ev_PosX, tmp );
00868 int row = sheet->topRow( ev_PosY, tmp );
00869
00870 const QMimeData* mimeData = _ev->mimeData();
00871 if ( !mimeData->hasText() && !mimeData->hasFormat( "application/x-kspread-snippet" ) )
00872 {
00873 _ev->ignore();
00874 return;
00875 }
00876
00877 QByteArray b;
00878
00879 bool makeUndo = true;
00880
00881 if ( mimeData->hasFormat( "application/x-kspread-snippet" ) )
00882 {
00883 if ( _ev->source() == this )
00884 {
00885 UndoDragDrop * undo
00886 = new UndoDragDrop(sheet, *selection(),
00887 Region(QRect(col, row,
00888 selection()->boundingRect().width(),
00889 selection()->boundingRect().height())),
00890 selection());
00891 d->view->doc()->addCommand( undo );
00892 makeUndo = false;
00893
00894 DeleteCommand* command = new DeleteCommand();
00895 command->setSheet( activeSheet() );
00896 command->add( *selection() );
00897 command->setRegisterUndo( false );
00898 command->execute();
00899 }
00900
00901
00902 b = mimeData->data( "application/x-kspread-snippet" );
00903 sheet->paste( b, QRect( col, row, 1, 1 ), makeUndo );
00904
00905
00906 selection()->initialize( QRect( col, row,
00907 selection()->boundingRect().width(),
00908 selection()->boundingRect().height() ), sheet);
00909
00910 _ev->setAccepted(true);
00911 }
00912 else
00913 {
00914 QString text = mimeData->text();
00915 sheet->pasteTextPlain( text, QRect( col, row, 1, 1 ) );
00916 _ev->setAccepted(true);
00917 return;
00918 }
00919 }
00920
00921 void Canvas::slotAutoScroll(const QPoint &scrollDistance)
00922 {
00923
00924
00925
00926
00927 if (!d->mousePressed)
00928 return;
00929 d->view->canvasController()->scrollContentsBy(scrollDistance.x(), scrollDistance.y());
00930 }
00931
00932 QRect Canvas::viewToCellCoordinates( const QRectF& viewRect ) const
00933 {
00934 register Sheet * const sheet = activeSheet();
00935 if (!sheet)
00936 return QRect();
00937
00938 const QRectF rect = d->view->zoomHandler()->viewToDocument( viewRect ).translated( offset() );
00939
00940 double tmp;
00941 const int left = sheet->leftColumn( rect.left(), tmp );
00942 const int right = sheet->rightColumn( rect.right() );
00943 const int top = sheet->topRow( rect.top(), tmp );
00944 const int bottom = sheet->bottomRow( rect.bottom() );
00945
00946 return QRect( left, top, right - left + 1, bottom - top + 1 );
00947 }
00948
00949 QRect Canvas::visibleCells() const
00950 {
00951 return viewToCellCoordinates( rect() );
00952 }
00953
00954
00955
00956
00957
00958
00959
00960 QRectF Canvas::cellCoordinatesToView( const QRect& cellRange ) const
00961 {
00962 register Sheet * const sheet = activeSheet();
00963 if (!sheet)
00964 return QRectF();
00965
00966 QRectF rect = sheet->cellCoordinatesToDocument( cellRange );
00967
00968 rect.translate( -xOffset(), -yOffset() );
00969
00970 rect = d->view->zoomHandler()->documentToView( rect );
00971
00972 if ( sheet->layoutDirection() == Qt::RightToLeft )
00973 {
00974 const double left = rect.left();
00975 const double right = rect.right();
00976 rect.setLeft( width() - right );
00977 rect.setRight( width() - left );
00978 }
00979 return rect;
00980 }
00981
00982 void Canvas::showToolTip( const QPoint& p )
00983 {
00984 register Sheet * const sheet = activeSheet();
00985 if (!sheet)
00986 return;
00987
00988
00989 double ypos, xpos;
00990 double dwidth = d->view->zoomHandler()->viewToDocumentX( width() );
00991 int col;
00992 if ( sheet->layoutDirection() == Qt::RightToLeft )
00993 col = sheet->leftColumn( (dwidth - d->view->zoomHandler()->viewToDocumentX( p.x() ) +
00994 xOffset()), xpos );
00995 else
00996 col = sheet->leftColumn( (d->view->zoomHandler()->viewToDocumentX( p.x() ) +
00997 xOffset()), xpos );
00998
00999
01000 int row = sheet->topRow( (d->view->zoomHandler()->viewToDocumentY( p.y() ) +
01001 yOffset()), ypos );
01002
01003 Cell cell = Cell(sheet, col, row).masterCell();
01004 CellView cellView = view()->sheetView(sheet)->cellView(cell.column(), cell.row());
01005 if (cellView.isObscured())
01006 {
01007 cell = Cell(sheet, cellView.obscuringCell());
01008 cellView = view()->sheetView(sheet)->cellView(cellView.obscuringCell().x(), cellView.obscuringCell().y());
01009 }
01010
01011
01012
01013
01014
01015
01016
01017 QString tipText;
01018
01019 if (!cellView.dimensionFits())
01020 tipText = cell.displayText().replace('<', "<");
01021
01022
01023 if ( tipText.isEmpty() )
01024 tipText = cell.link().replace('<', "<");
01025
01026
01027 if (tipText.isEmpty() && cell.comment().isEmpty())
01028 return;
01029
01030
01031 const int maxLen = 256;
01032 if ( tipText.length() > maxLen )
01033 tipText = tipText.left(maxLen).append("...");
01034
01035
01036 const double cellWidth = cellView.cellWidth();
01037 const double cellHeight = cellView.cellHeight();
01038
01039
01040 QRect cellRect;
01041 bool insideCellRect = false;
01042 if ( sheet->layoutDirection() == Qt::RightToLeft )
01043 {
01044 const QRectF rect(dwidth - cellWidth - xpos + xOffset(), ypos - yOffset(), cellWidth, cellHeight);
01045 cellRect = viewConverter()->documentToView(rect).toRect();
01046 insideCellRect = cellRect.contains( p );
01047 }
01048 else
01049 {
01050 QRectF rect(xpos - xOffset(), ypos - yOffset(), cellWidth, cellHeight);
01051 cellRect = viewConverter()->documentToView(rect).toRect();
01052 insideCellRect = cellRect.contains( p );
01053 }
01054
01055
01056 if ( !insideCellRect )
01057 return;
01058
01059
01060 if (tipText.isEmpty())
01061 tipText = cell.comment().replace('<', "<");
01062 else if (!cell.comment().isEmpty())
01063 tipText += "</p><h4>" + i18n("Comment:") + "</h4><p>" + cell.comment().replace('<', "<");
01064
01065
01066 QToolTip::showText(mapToGlobal(cellRect.bottomRight()),
01067 "<p>" + tipText.replace('\n', "<br>") + "</p>",
01068 this, cellRect.translated(-mapToGlobal(cellRect.topLeft())));
01069 }
01070
01071 void Canvas::updateInputMethodInfo() {
01072 updateMicroFocus();
01073 }
01074
01075 #include "Canvas.moc"