kword

KWCanvas.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2002-2006 David Faure <faure@kde.org>
4 Copyright (C) 2005 Thomas Zander <zander@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22
23#include "KWCanvas.h"
24#include "KWTableFrameSet.h"
25#include "KWPartFrameSet.h"
26#include "KWFormulaFrameSet.h"
27#include "KWDocument.h"
28#include "KWView.h"
29#include "KWViewMode.h"
30#include "KWFrameDia.h"
31#include "KWCommand.h"
32#include "KWTableTemplate.h"
33#include "KWTextDocument.h"
34#include "KWFrameList.h"
35#include "KWPageManager.h"
36#include "KWPage.h"
37#include "KWPictureFrameSet.h"
38#include "KWFrameView.h"
39#include "KWFrameViewManager.h"
40
41#include <tqbuffer.h>
42#include <tqtimer.h>
43#include <tqclipboard.h>
44#include <tqprogressdialog.h>
45#include <tqobjectlist.h>
46#include <tqapplication.h>
47#include <tqwhatsthis.h>
48
49#include <KoStore.h>
50#include <KoStoreDrag.h>
51#include <KoPictureCollection.h>
52
53#include <tdetempfile.h>
54#include <tdelocale.h>
55#include <kcursor.h>
56#include <kdebug.h>
57#include <tdemessagebox.h>
58#include <tdemultipledrag.h>
59#include <kurl.h>
60#include <kurldrag.h>
61#include <tdeio/netaccess.h>
62#include <kmimetype.h>
63
64#include <assert.h>
65
66KWCanvas::KWCanvas(const TQString& viewMode, TQWidget *parent, KWDocument *d, KWGUI *lGui)
67 : TQScrollView( parent, "canvas", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase ), m_doc( d )
68{
69 m_frameViewManager = new KWFrameViewManager(d);
70 m_gui = lGui;
71 m_currentFrameSetEdit = 0L;
72 m_mouseMeaning = MEANING_NONE;
73 m_mousePressed = false;
74 m_imageDrag = false;
75 m_frameInline = false;
76 m_overwriteMode = false;
77
78 //used by insert picture dialogbox
79 m_picture.pictureInline = false;
80 m_picture.keepRatio = true;
81
82
83
84 m_frameInlineType = FT_TABLE;
85 m_viewMode = KWViewMode::create( viewMode, m_doc, this );
86 m_interactionPolicy = 0;
87
88 // Default table parameters.
89 m_table.rows = 3;
90 m_table.cols = 2;
91 m_table.width = KWTableFrameSet::TblAuto;
92 m_table.height = KWTableFrameSet::TblAuto;
93 m_table.floating = true;
94 m_table.tableTemplateName=TQString();
95 m_table.format=31;
96
97 m_footEndNote.noteType = FootNote;
98 m_footEndNote.numberingType = KWFootNoteVariable::Auto;
99
100
101 m_currentTable = 0L;
102 m_printing = false;
103 m_deleteMovingRect = false;
104 m_resizedFrameInitialMinHeight = 0;
105 m_temporaryStatusBarTextShown = false;
106
107 viewport()->setBackgroundMode( PaletteBase );
108 viewport()->setAcceptDrops( true );
109
110 setKeyCompression( true );
111 viewport()->setMouseTracking( true );
112
113 m_scrollTimer = new TQTimer( this );
114 connect( m_scrollTimer, TQ_SIGNAL( timeout() ),
115 this, TQ_SLOT( doAutoScroll() ) );
116
117 viewport()->setFocusProxy( this );
118 viewport()->setFocusPolicy( TQWidget::WheelFocus );
119 setInputMethodEnabled( true );
120 setFocus();
121 viewport()->installEventFilter( this );
122 installEventFilter( this );
123 KCursor::setAutoHideCursor( this, true, true );
124
125 connect( this, TQ_SIGNAL(contentsMoving( int, int )),
126 this, TQ_SLOT(slotContentsMoving( int, int )) );
127
128 connect( m_doc, TQ_SIGNAL( newContentsSize() ),
129 this, TQ_SLOT( slotNewContentsSize() ) );
130
131 connect( m_doc, TQ_SIGNAL( mainTextHeightChanged() ),
132 this, TQ_SLOT( slotMainTextHeightChanged() ) );
133
134 connect( m_doc, TQ_SIGNAL( sig_terminateEditing( KWFrameSet * ) ),
135 this, TQ_SLOT( terminateEditing( KWFrameSet * ) ) );
136
137 slotNewContentsSize();
138
139 m_mouseMode = MM_EDIT; // avoid UMR in setMouseMode
140 setMouseMode( MM_EDIT );
141
142 // Create the current frameset-edit last, to have everything ready for it
143 KWFrameSet * fs = 0L;
144 TQString fsName = m_doc->initialFrameSet();
145 if ( !fsName.isEmpty() )
146 fs = m_doc->frameSetByName( fsName );
147 if ( !fs )
148 fs = m_doc->frameSet( 0 );
149 //Q_ASSERT( fs ); // empty page template -> no fs
150 if ( fs && fs->isVisible( m_viewMode ) ) {
151 checkCurrentEdit( fs );
152 KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit);
153 if ( textedit ) {
154 int paragId = m_doc->initialCursorParag();
155 int index = m_doc->initialCursorIndex();
156 if ( paragId != 0 || index != 0 ) {
157 KoTextParag* parag = textedit->textDocument()->paragAt( paragId );
158 if ( parag )
159 textedit->setCursor( parag, index );
160 }
161 }
162 }
163 m_doc->deleteInitialEditingInfo();
164
165 connect(frameViewManager(), TQ_SIGNAL(sigFrameResized(const TQValueList<KWFrame*>&)),
166 m_doc, TQ_SLOT(framesChanged(const TQValueList<KWFrame*>&)));
167 connect(frameViewManager(), TQ_SIGNAL(sigFrameMoved(const TQValueList<KWFrame*>&)),
168 m_doc, TQ_SLOT(framesChanged(const TQValueList<KWFrame*>&)));
169}
170
171KWCanvas::~KWCanvas()
172{
173 delete m_interactionPolicy;
174 delete m_currentFrameSetEdit;
175 m_currentFrameSetEdit = 0;
176 delete m_viewMode;
177 m_viewMode = 0;
178 disconnect(frameViewManager(), TQ_SIGNAL(sigFrameResized(const TQValueList<KWFrame*>&)),
179 m_doc, TQ_SLOT(framesChanged(const TQValueList<KWFrame*>&)));
180 disconnect(frameViewManager(), TQ_SIGNAL(sigFrameMoved(const TQValueList<KWFrame*>&)),
181 m_doc, TQ_SLOT(framesChanged(const TQValueList<KWFrame*>&)));
182 delete m_frameViewManager;
183 m_frameViewManager = 0;
184}
185
186void KWCanvas::repaintChanged( KWFrameSet * fs, bool resetChanged )
187{
188 assert(fs); // the new code can't support fs being 0L here. Mail me if it happens (DF)
189 //kdDebug(32002) << "KWCanvas::repaintChanged this=" << this << " fs=" << fs << endl;
190 TQPainter p( viewport() );
191 p.translate( -contentsX(), -contentsY() );
192 p.setBrushOrigin( -contentsX(), -contentsY() );
193 TQRect crect( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
194 drawFrameSet( fs, &p, crect, true, resetChanged, m_viewMode );
195 // ###### This repaints the whole grid every time. Ouch.
196 // We should return a TQRegion from drawFrameSet.... Tricky.
197 if ( m_doc->showGrid() )
198 drawGrid( p, crect );
199}
200
201void KWCanvas::repaintAll( bool erase /* = false */ )
202{
203 //kdDebug(32002) << "KWCanvas::repaintAll erase=" << erase << endl;
204 viewport()->repaint( erase );
205}
206
207void KWCanvas::viewportResizeEvent( TQResizeEvent * )
208{
209 viewport()->update();
210}
211
212void KWCanvas::print( TQPainter *painter, KPrinter *printer )
213{
214 // Prevent cursor drawing and editing
215 if ( m_currentFrameSetEdit )
216 m_currentFrameSetEdit->focusOutEvent();
217 m_printing = true;
218 KWViewMode *viewMode = new KWViewModePrint( m_doc, this );
219 // Use page list specified in tdeprint dialogbox
220 TQValueList<int> pageList = printer->pageList();
221 TQProgressDialog progress( i18n( "Printing..." ), i18n( "Cancel" ),
222 pageList.count() + 1, this );
223 int j = 0;
224 progress.setProgress( 0 );
225 TQValueList<int>::Iterator it = pageList.begin();
226 for ( ; it != pageList.end(); ++it )
227 {
228 progress.setProgress( ++j );
229 tqApp->processEvents();
230
231 if ( progress.wasCancelled() )
232 break;
233
234 if ( it != pageList.begin() )
235 printer->newPage();
236
237 painter->save();
238 int pgNum = (*it);
239 int yOffset = m_doc->zoomItY( m_doc->pageManager()->topOfPage( pgNum ) );
240 kdDebug(32001) << "printing page " << pgNum << " yOffset=" << yOffset << endl;
241 TQRect pageRect = m_doc->pageManager()->page(pgNum)->zoomedRect(m_doc);
242 painter->fillRect( pageRect, white );
243
244 painter->translate( 0, -yOffset );
245 painter->setBrushOrigin( 0, -yOffset );
246 drawDocument( painter, pageRect, viewMode );
247 tqApp->processEvents();
248 painter->restore();
249 }
250 if ( m_currentFrameSetEdit )
251 m_currentFrameSetEdit->focusInEvent();
252 m_printing = false;
253 delete viewMode;
254}
255
256void KWCanvas::drawContents( TQPainter *painter, int cx, int cy, int cw, int ch )
257{
258 if ( isUpdatesEnabled() )
259 {
260 // Note: in drawContents, the painter is already translated to the contents coordinates
261 painter->setBrushOrigin( -contentsX(), -contentsY() );
262 drawDocument( painter, TQRect( cx, cy, cw, ch ), m_viewMode );
263 if ( m_doc->showGrid() )
264 drawGrid( *painter, TQRect( cx, cy, cw, ch ) );
265 else if ( m_doc->snapToGrid() && ( m_interactionPolicy && m_interactionPolicy->gotDragEvents()
266 || m_mouseMode != MM_EDIT ) )
267 drawGrid( *painter, TQRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()) );
268 }
269}
270
271void KWCanvas::drawDocument( TQPainter *painter, const TQRect &crect, KWViewMode* viewMode )
272{
273 //kdDebug(32002) << "KWCanvas::drawDocument crect: " << crect << endl;
274
275 // Draw the outside of the pages (shadow, gray area)
276 // and the empty area first (in case of transparent frames)
277 if ( painter->device()->devType() != TQInternal::Printer ) // except when printing
278 {
279 TQRegion emptySpaceRegion( crect );
280 m_doc->createEmptyRegion( crect, emptySpaceRegion, viewMode );
281 viewMode->drawPageBorders( painter, crect, emptySpaceRegion );
282 }
283
284 // Draw all framesets contents
285 TQPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
286 for ( ; fit.current() ; ++fit )
287 {
288 KWFrameSet * frameset = fit.current();
289 if(! frameset->isVisible()) continue;
290 drawFrameSet( frameset, painter, crect, false, true, viewMode );
291 }
292
293 m_doc->maybeDeleteDoubleBufferPixmap();
294}
295
296void KWCanvas::drawFrameSet( KWFrameSet * frameset, TQPainter * painter,
297 const TQRect & crect, bool onlyChanged, bool resetChanged, KWViewMode* viewMode )
298{
299 if ( !frameset->isVisible( viewMode ) )
300 return;
301 if ( !onlyChanged && frameset->isFloating() )
302 return;
303
304 bool focus = hasFocus() || viewport()->hasFocus();
305 if ( painter->device()->devType() == TQInternal::Printer )
306 focus = false;
307
308 TQColorGroup gb = TQApplication::palette().active();
309 if ( focus && m_currentFrameSetEdit && frameset == m_currentFrameSetEdit->frameSet() )
310 // Currently edited frameset
311 m_currentFrameSetEdit->drawContents( painter, crect, gb, onlyChanged, resetChanged, viewMode, m_frameViewManager );
312 else
313 frameset->drawContents( painter, crect, gb, onlyChanged, resetChanged, 0L, viewMode, m_frameViewManager );
314}
315
316void KWCanvas::keyPressEvent( TQKeyEvent *e )
317{
318 if( !m_doc->isReadWrite()) {
319 switch( e->key() ) {
320 case TQt::Key_Down:
321 setContentsPos( contentsX(), contentsY() + 10 );
322 break;
323 case TQt::Key_Up:
324 setContentsPos( contentsX(), contentsY() - 10 );
325 break;
326 case TQt::Key_Left:
327 setContentsPos( contentsX() - 10, contentsY() );
328 break;
329 case TQt::Key_Right:
330 setContentsPos( contentsX() + 10, contentsY() );
331 break;
332 case TQt::Key_PageUp:
333 setContentsPos( contentsX(), contentsY() - visibleHeight() );
334 break;
335 case TQt::Key_PageDown:
336 setContentsPos( contentsX(), contentsY() + visibleHeight() );
337 break;
338 case TQt::Key_Home:
339 setContentsPos( contentsX(), 0 );
340 break;
341 case TQt::Key_End:
342 setContentsPos( contentsX(), contentsHeight() - visibleHeight() );
343 break;
344 default:
345 break;
346 }
347 }
348 // The key events in read-write mode are handled by eventFilter(), otherwise
349 // we don't get <Tab> key presses.
350}
351
352void KWCanvas::switchViewMode( const TQString& newViewMode )
353{
354 delete m_viewMode;
355 m_viewMode = KWViewMode::create( newViewMode, m_doc, this );
356}
357
358void KWCanvas::mpCreate( const TQPoint& normalPoint, bool noGrid )
359{
360 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
361 if ( m_doc->snapToGrid() && !noGrid )
362 applyGrid( docPoint );
363 m_insRect.setCoords( docPoint.x(), docPoint.y(), 0, 0 );
364 m_deleteMovingRect = false;
365}
366
367void KWCanvas::mpCreatePixmap( const TQPoint& normalPoint, bool noGrid )
368{
369 if ( !m_kopicture.isNull() )
370 {
371 // Apply grid for the first corner only
372 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
373 if ( m_doc->snapToGrid() && ! noGrid )
374 applyGrid( docPoint );
375 int pageNum = m_doc->pageManager()->pageNumber( docPoint );
376 m_insRect.setRect( docPoint.x(), docPoint.y(), 0, 0 );
377 m_deleteMovingRect = false;
378
379 if ( !m_pixmapSize.isEmpty() )
380 {
381 // This ensures 1-1 at 100% on screen, but allows zooming and printing with correct DPI values
382 uint width = tqRound( (double)m_pixmapSize.width() * m_doc->zoomedResolutionX() / POINT_TO_INCH( KoGlobal::dpiX() ) );
383 uint height = tqRound( (double)m_pixmapSize.height() * m_doc->zoomedResolutionY() / POINT_TO_INCH( KoGlobal::dpiY() ) );
384 m_insRect.setWidth( m_doc->unzoomItX( width ) );
385 m_insRect.setHeight( m_doc->unzoomItY( height ) );
386 // Apply reasonable limits
387 width = kMin( width, m_doc->paperWidth(pageNum) - normalPoint.x() - 5 );
388 height = kMin( height, m_doc->paperHeight(pageNum) - normalPoint.y() - 5 );
389 // And apply aspect-ratio if set
390 if ( m_keepRatio )
391 {
392 double ratio = ((double) m_pixmapSize.width()) / ((double) m_pixmapSize.height());
393 applyAspectRatio( ratio, m_insRect );
394 }
395
396 TQPoint nPoint( normalPoint.x() + m_doc->zoomItX( m_insRect.width() ),
397 normalPoint.y() + m_doc->zoomItY( m_insRect.height() ) );
398 TQPoint vPoint = m_viewMode->normalToView( nPoint );
399 vPoint = contentsToViewport( vPoint );
400 TQRect viewportRect( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
401 if ( viewportRect.contains( vPoint ) ) // Don't move the mouse out of the viewport
402 TQCursor::setPos( viewport()->mapToGlobal( vPoint ) );
403 }
404 emit docStructChanged(Pictures);
405 if ( !m_doc->showGrid() && m_doc->snapToGrid() )
406 repaintContents( false ); //draw the grid over the whole canvas
407 }
408}
409
410void KWCanvas::contentsMousePressEvent( TQMouseEvent *e )
411{
412 TQPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
413 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
414
415
416 if ( e->button() == TQt::LeftButton )
417 {
418 m_mousePressed = true;
419 }
420
421 // Only edit-mode (and only LMB) allowed on read-only documents (to select text)
422 if ( !m_doc->isReadWrite() && ( m_mouseMode != MM_EDIT || e->button() != TQt::LeftButton ) )
423 return;
424 if ( m_printing )
425 return;
426
427 // This code here is common to all mouse buttons, so that RMB and MMB place the cursor (or select the frame) too
428 switch ( m_mouseMode ) {
429 case MM_EDIT:
430 {
431 if(! viewMode()->hasFrames() ) { // for the text mode we just forward the click to the text
432 // first, make clicks left of text be on the border;
433 docPoint = KoPoint(TQMAX(0, docPoint.x()), TQMAX(0, docPoint.y()));
434 if ( m_currentFrameSetEdit )
435 m_currentFrameSetEdit->mousePressEvent( e, normalPoint, docPoint );
436 break;
437 }
438 // See if we clicked on a frame's border
439 m_mouseMeaning = m_frameViewManager->mouseMeaning( docPoint, e->state());
440
441 //kdDebug(32001) << "contentsMousePressEvent meaning=" << m_mouseMeaning << endl;
442 switch ( m_mouseMeaning ) {
443 case MEANING_MOUSE_INSIDE:
444 case MEANING_MOUSE_OVER_LINK:
445 case MEANING_MOUSE_OVER_FOOTNOTE:
446 case MEANING_MOUSE_INSIDE_TEXT:
447 case MEANING_ACTIVATE_PART:
448 {
449 // LMB/MMB inside a frame always unselects all frames
450 // RMB inside a frame unselects too, except when
451 // right-clicking on a selected frame
452 KWFrameView *view = m_frameViewManager->view( docPoint, KWFrameViewManager::frameOnTop );
453 if ( ! ( e->button() == TQt::RightButton && view && view->selected() ) )
454 selectAllFrames( false );
455
456 KWFrame * frame = view ? view->frame() : 0L;
457 KWFrameSet * fs = frame ? frame->frameSet() : 0L;
458 if ( fs && fs->groupmanager() )
459 fs = fs->groupmanager();
460 bool emitChanged = false;
461 if ( fs )
462 {
463 // Clicked inside a frame - start editing it
464 emitChanged = checkCurrentEdit( fs );
465 }
466
467 if ( m_currentFrameSetEdit )
468 m_currentFrameSetEdit->mousePressEvent( e, normalPoint, docPoint );
469
470 if ( emitChanged ) { // emitted after mousePressEvent [for tables]
471 emit currentFrameSetEditChanged();
472 emit updateRuler();
473 }
474
475 if ( m_frameInline )
476 {
477 bool inlineCreated = true;
478 if(m_frameInlineType == FT_TABLE)
479 inlineCreated = insertInlineTable();
480 else if(m_frameInlineType == FT_PICTURE)
481 inlineCreated = insertInlinePicture();
482 if (!inlineCreated)
483 KMessageBox::information(0L, i18n("Read-only content cannot be changed. No modifications will be accepted."));
484 }
485 break;
486 }
487 case MEANING_RESIZE_COLUMN:
488 case MEANING_RESIZE_ROW:
489 {
490 terminateCurrentEdit();
491
492 // We know we're resizing a row or column, but we don't know which one yet...
493 // We're between two rows (or columns) so frameUnderMouse is a bit unprecise...
494 // We need it to find out which table we clicked on, though.
495 KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
496 if (view)
497 {
498 KWTableFrameSet::Cell* cell = dynamic_cast<KWTableFrameSet::Cell *>(view->frame()->frameSet());
499 if ( cell )
500 {
501 KWTableFrameSet* table = cell->groupmanager();
502 if ( m_mouseMeaning == MEANING_RESIZE_COLUMN )
503 {
504 m_rowColResized = table->columnEdgeAt( docPoint.x() );
505 m_previousTableSize = table->columnSize( m_rowColResized );
506 }
507 else
508 {
509 m_rowColResized = table->rowEdgeAt( docPoint.y() );
510 m_previousTableSize = table->rowSize( m_rowColResized );
511 }
512 m_currentTable = table;
513 kdDebug(32002) << "resizing row/col edge. m_rowColResized=" << m_rowColResized << endl;
514 }
515 }
516 break;
517 }
518 default:
519 m_mousePressed = true;
520 m_deleteMovingRect = false;
521
522 delete m_interactionPolicy;
523 m_interactionPolicy = InteractionPolicy::createPolicy(this, m_mouseMeaning, docPoint, e->button(), e->state());
524 if(m_interactionPolicy)
525 terminateCurrentEdit();
526 viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, e->state() ) );
527 }
528 }
529 break;
530 case MM_CREATE_TEXT: case MM_CREATE_PART: case MM_CREATE_TABLE:
531 case MM_CREATE_FORMULA:
532 if ( e->button() == TQt::LeftButton )
533 mpCreate( normalPoint, e->state() & TQt::ShiftButton);
534 break;
535 case MM_CREATE_PIX:
536 if ( e->button() == TQt::LeftButton )
537 mpCreatePixmap( normalPoint, e->state() & TQt::ShiftButton );
538 break;
539 default: break;
540 }
541 m_scrollTimer->start( 50 );
542
543 if ( e->button() == TQt::MidButton ) {
544 if ( m_doc->isReadWrite() && m_currentFrameSetEdit && m_mouseMode == MM_EDIT )
545 {
546 TQApplication::clipboard()->setSelectionMode( true );
547 m_currentFrameSetEdit->paste();
548 TQApplication::clipboard()->setSelectionMode( false );
549 }
550 }
551 else if ( e->button() == TQt::RightButton ) {
552 if(!m_doc->isReadWrite()) // The popups are not available in readonly mode, since the GUI isn't built...
553 return;
554 if ( m_deleteMovingRect )
555 deleteMovingRect();
556 // rmb menu
557 switch ( m_mouseMode )
558 {
559 case MM_EDIT:
560 if ( !viewMode()->hasFrames() ) { // text view mode
561 KWFrameView *view = m_frameViewManager->view(m_doc->frameSet( 0 )->frame(0));
562 view->showPopup(docPoint, m_gui->getView(), TQCursor::pos());
563 }
564 else
565 m_frameViewManager->showPopup(docPoint, m_gui->getView(), e->state(), TQCursor::pos());
566 break;
567 case MM_CREATE_TEXT:
568 case MM_CREATE_PART:
569 case MM_CREATE_TABLE:
570 case MM_CREATE_FORMULA:
571 case MM_CREATE_PIX:
572 setMouseMode( MM_EDIT );
573 default: break;
574 }
575 m_mousePressed = false;
576 }
577}
578
579// Called by KWTableDia
580void KWCanvas::createTable( unsigned int rows, unsigned int cols,
581 int wid, int hei,
582 bool isFloating,
583 KWTableTemplate *tt, int format )
584{
585 // Remember for next time in any case
586 m_table.rows = rows;
587 m_table.cols = cols;
588 m_table.width = wid;
589 m_table.height = hei;
590 m_table.floating = isFloating;
591 m_table.format = format;
592
593 m_table.tableTemplateName = tt ? tt->displayName():TQString();
594 m_table.tt = tt;
595
596 if ( isFloating )
597 {
598 m_frameInline=true;
599 m_frameInlineType=FT_TABLE;
600 m_gui->getView()->displayFrameInlineInfo();
601 }
602 else
603 {
604 m_frameInline=false;
605 setMouseMode( MM_CREATE_TABLE );
606 }
607}
608
609bool KWCanvas::insertInlinePicture() // also called by DCOP
610{
611 bool inserted = m_gui->getView()->insertInlinePicture();
612 if ( inserted )
613 m_frameInline = false;
614 return inserted;
615}
616
617bool KWCanvas::insertInlineTable()
618{
619 KWTextFrameSetEdit * edit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit);
620 if(edit)
621 {
622 if ( edit->textFrameSet()->textObject()->protectContent() )
623 return false;
624 m_insRect = KoRect( 0, 0, edit->frameSet()->frame(0)->width(), 10 );
625
626 KWTableFrameSet * table = createTable();
627 m_doc->addFrameSet( table, false );
628 edit->insertFloatingFrameSet( table, i18n("Insert Inline Table") );
629 table->finalize();
630
631 if (m_table.tt) {
632 KWTableTemplateCommand *ttCmd=new KWTableTemplateCommand( "Apply template to inline table", table, m_table.tt );
633 m_doc->addCommand(ttCmd);
634 ttCmd->execute();
635 }
636
637 m_doc->updateAllFrames();
638 m_doc->refreshDocStructure(Tables);
639 }
640 m_gui->getView()->updateFrameStatusBarItem();
641 m_frameInline = false;
642 return true;
643}
644
645void KWCanvas::applyGrid( KoPoint &p )
646{
647 if ( m_viewMode->type() != "ModeNormal" )
648 return;
649 // The 1e-10 here is a workaround for some weird division problem.
650 // 360.00062366 / 2.83465058 gives 127 'exactly' when shown as a double,
651 // but when casting into an int, we get 126. In fact it's 127 - 5.64e-15 !
652
653 // This is a problem when calling applyGrid twice, we get 1 less than the time before.
654 p.setX( static_cast<int>( p.x() / m_doc->gridX() + 1e-10 ) * m_doc->gridX() );
655 p.setY( static_cast<int>( p.y() / m_doc->gridY() + 1e-10 ) * m_doc->gridY() );
656
657 //FIXME It doesn't work in preview mode - apply viewmode
658}
659
660void KWCanvas::drawGrid( TQPainter &p, const TQRect& rect )
661{
662 // Grid-positioning makes no sense in text view mode
663 if ( !m_viewMode->hasFrames() )
664 return;
665 TQPen pen = TQPen( TQt::black, 6, TQt::DotLine );
666 TQPen oldPen = p.pen();
667 p.setPen( pen );
668
669 const double offsetX = m_doc->gridX();
670 const double offsetY = m_doc->gridY();
671
672 // per page, this is needed to paint correctly on preview mode as well as making sure
673 // we start the grid from the topleft of each page.
674 for ( int pgNum = m_doc->startPage() ; pgNum <= m_doc->lastPage() ; ++pgNum) {
675 const TQRect pageRect = m_viewMode->viewPageRect( pgNum );
676 const TQRect crect = pageRect & rect;
677 if ( crect.isEmpty() )
678 continue;
679
680 // To convert back to view coordinates later we can calculate the offset for each
681 // point again, or we can do it one time for the page and re-use the answer.
682 KoPoint pageTopLeft (0, m_doc->pageManager()->topOfPage(pgNum) + 2); // +2 to get around rounding problems..
683 TQPoint pageTopLeftView = m_viewMode->normalToView( m_doc->zoomPoint(pageTopLeft) );
684
685 // docRect is the part of the document that needs to be painted.. Coordinates in pt
686 const KoRect docRect = m_doc->unzoomRect( m_viewMode->viewToNormal( crect ) );
687 // kdDebug() << "drawGrid page " << pgNum << " pageRect=" << pageRect << " crect=" << crect << " docRect=" << docRect << endl;
688
689 // the following is effectively a docRect.y() modulo offsetY
690 const double firstOffsetY = pageTopLeft.y() - offsetY * static_cast<int>( docRect.y() / offsetY );
691 const double bottom = docRect.bottom() - pageTopLeft.y();
692
693 for ( double x = 0; x <= docRect.right(); x += offsetX ) {
694 const int zoomedX = m_doc->zoomItX( x ) + pageTopLeftView.x();
695 for ( double y = firstOffsetY; y <= bottom; y += offsetY ) {
696 const int zoomedY = m_doc->zoomItY( y ) + pageTopLeftView.y();
697 p.drawPoint( zoomedX, zoomedY );
698 }
699 }
700 }
701
702 p.setPen( oldPen );
703}
704
705void KWCanvas::applyAspectRatio( double ratio, KoRect& insRect )
706{
707 double width = insRect.width();
708 double height = insRect.height();
709 if ( width < height ) // the biggest border is the one in control
710 width = height * ratio;
711 else
712 height = width / ratio;
713 insRect.setRight( insRect.left() + width );
714 insRect.setBottom( insRect.top() + height );
715 //kdDebug() << "KWCanvas::applyAspectRatio: width=" << width << " height=" << height << " insRect=" << DEBUGRECT(insRect) << endl;
716}
717
718void KWCanvas::mmCreate( const TQPoint& normalPoint, bool noGrid ) // Mouse move when creating a frame
719{
720 TQPainter p;
721 p.begin( viewport() );
722 p.translate( -contentsX(), -contentsY() );
723 p.setRasterOp( NotROP );
724 p.setPen( black );
725 p.setBrush( NoBrush );
726
727 if ( m_deleteMovingRect )
728 drawMovingRect( p );
729
730 int page = m_doc->pageManager()->pageNumber( m_insRect );
731 if( page == -1) {
732 return;
733 }
734 KoRect oldRect = m_insRect;
735
736 // Resize the rectangle
737 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
738 if ( m_doc->snapToGrid() && m_mouseMode != MM_CREATE_PIX && !noGrid )
739 applyGrid( docPoint );
740
741 m_insRect.setRight( docPoint.x() );
742 m_insRect.setBottom( docPoint.y() );
743
744 // But not out of the page
745 KoRect r = m_insRect.normalize();
746 if ( !m_doc->pageManager()->page(page)->rect().contains(r) )
747 {
748 // Even better would be to go to the limit of the page boundary, so that the result,
749 // when moving the mouse of the page, doesn't depend on how fast we're moving it...
750 m_insRect = oldRect;
751 // #### TQCursor::setPos( viewport()->mapToGlobal( zoomPoint( m_insRect.bottomRight() ) ) );
752 }
753
754 // Apply keep-aspect-ratio feature
755 if ( m_mouseMode == MM_CREATE_PIX && m_keepRatio )
756 {
757 double ratio = (double)m_pixmapSize.width() / (double)m_pixmapSize.height();
758 applyAspectRatio( ratio, m_insRect );
759 }
760
761 drawMovingRect( p );
762 p.end();
763 m_deleteMovingRect = true;
764}
765
766void KWCanvas::drawMovingRect( TQPainter & p )
767{
768 p.setPen( black );
769 p.drawRect( m_viewMode->normalToView( m_doc->zoomRect( m_insRect ) ) );
770}
771
772void KWCanvas::deleteMovingRect()
773{
774 Q_ASSERT( m_deleteMovingRect );
775 TQPainter p;
776 p.begin( viewport() );
777 p.translate( -contentsX(), -contentsY() );
778 p.setRasterOp( NotROP );
779 p.setPen( black );
780 p.setBrush( NoBrush );
781 drawMovingRect( p );
782 m_deleteMovingRect = false;
783 p.end();
784}
785
786void KWCanvas::contentsMouseMoveEvent( TQMouseEvent *e )
787{
788 if ( m_printing )
789 return;
790 TQPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
791 if(normalPoint.x() == -1) // e->pos() is an exceptional state...
792 return;
793 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
794
795 if ( m_mousePressed ) {
796 //doAutoScroll();
797
798 switch ( m_mouseMode ) {
799 case MM_EDIT:
800 {
801 if ( m_currentFrameSetEdit )
802 m_currentFrameSetEdit->mouseMoveEvent( e, normalPoint, docPoint );
803 if( ! m_doc->isReadWrite() )
804 break;
805 if ( m_mouseMeaning == MEANING_RESIZE_COLUMN || m_mouseMeaning == MEANING_RESIZE_ROW )
806 {
807 // TODO undo/redo support (esp. in mouse-release)
808 TQRect oldRect( m_viewMode->normalToView( m_doc->zoomRect( m_currentTable->boundingRect() ) ) );
809 if ( m_mouseMeaning == MEANING_RESIZE_ROW )
810 m_currentTable->resizeRow( m_rowColResized, docPoint.y() );
811 else
812 m_currentTable->resizeColumn( m_rowColResized, docPoint.x() );
813 // Repaint only the changed rects (oldRect U newRect)
814 TQRect newRect( m_viewMode->normalToView( m_doc->zoomRect( m_currentTable->boundingRect() ) ) );
815 repaintContents( TQRegion(oldRect).unite(newRect).boundingRect(), false );
816 }
817 else if (m_interactionPolicy) {
818 m_interactionPolicy->handleMouseMove(e->state(),
819 m_doc->unzoomPoint( normalPoint ));
820 m_interactionPolicy->hadDragEvents();
821 }
822 } break;
823 case MM_CREATE_TEXT: case MM_CREATE_PIX: case MM_CREATE_PART:
824 case MM_CREATE_TABLE: case MM_CREATE_FORMULA:
825 mmCreate( normalPoint, e->state() & ShiftButton );
826 default:
827 break;
828 }
829 }
830 else {
831 if ( m_mouseMode == MM_EDIT )
832 {
833 MouseMeaning meaning = m_frameViewManager->mouseMeaning( docPoint, e->state() );
834 switch ( meaning ) {
835 case MEANING_MOUSE_OVER_FOOTNOTE:
836 {
837 KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
838 KWFrame* frame = view ? view->frame() : 0;
839 KWFrameSet * fs = frame ? frame->frameSet() : 0;
840 if (fs && fs->type() == FT_TEXT)
841 {
842 KoVariable* var = static_cast<KWTextFrameSet *>(fs)->variableUnderMouse(docPoint);
843 if ( var )
844 {
845 KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
846 if ( footNoteVar )
847 {
848 // show the content of the footnote in the status bar
849 gui()->getView()->setTemporaryStatusBarText( footNoteVar->frameSet()->textDocument()->firstParag()->string()->toString() );
850 m_temporaryStatusBarTextShown = true;
851 }
852 }
853
854 }
855 break;
856 }
857 case MEANING_MOUSE_OVER_LINK:
858 {
859 KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
860 KWFrame* frame = view ? view->frame() : 0;
861 KWFrameSet * fs = frame ? frame->frameSet() : 0L;
862 if (fs && fs->type() == FT_TEXT)
863 {
864 KWTextFrameSet *frameset = static_cast<KWTextFrameSet *>(fs);
865 //show the link target in the status bar
866 TQString link = frameset->linkVariableUnderMouse(docPoint)->url();
867 if ( link.startsWith("bkm://") )
868 link.replace( 0, 6, i18n("Bookmark target: ") );
869 gui()->getView()->setTemporaryStatusBarText( link );
870 m_temporaryStatusBarTextShown = true;
871 }
872 break;
873 }
874 default:
876 break;
877 }
878 if(viewMode()->hasFrames())
879 viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, e->state() ) );
880 else
881 viewport()->setCursor( TQt::ibeamCursor );
882 }
883 }
884}
885
886void KWCanvas::mrEditFrame() {
887 //kdDebug() << "KWCanvas::mrEditFrame" << endl;
888 if(m_interactionPolicy) {
889 m_interactionPolicy->finishInteraction();
890 KCommand *cmd = m_interactionPolicy->createCommand();
891 if(cmd)
892 m_doc->addCommand(cmd);
893 delete(m_interactionPolicy);
894 m_interactionPolicy = 0;
895 if ( !m_doc->showGrid() && m_doc->snapToGrid() )
896 repaintContents();
897 }
898 m_mousePressed = false;
899}
900
901KCommand *KWCanvas::createTextBox( const KoRect & rect )
902{
903 if ( !m_doc->snapToGrid() || ( rect.width() > m_doc->gridX() && rect.height() > m_doc->gridY() ) ) {
904 KWFrame *frame = new KWFrame(0L, rect.x(), rect.y(), rect.width(), rect.height() );
905 frame->setNewFrameBehavior(KWFrame::Reconnect);
906 frame->setZOrder( m_doc->maxZOrder( frame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
907
908 TQString name = m_doc->generateFramesetName( i18n( "Text Frameset %1" ) );
909 KWTextFrameSet *_frameSet = new KWTextFrameSet(m_doc, name );
910 _frameSet->addFrame( frame );
911 m_doc->addFrameSet( _frameSet );
912 KWCreateFrameCommand *cmd=new KWCreateFrameCommand( i18n("Create Text Frame"), frame );
913 if ( checkCurrentEdit(frame->frameSet(), true) )
914 emit currentFrameSetEditChanged();
915 return cmd;
916 }
917 return 0L;
918}
919
920void KWCanvas::mrCreateText()
921{
922 m_insRect = m_insRect.normalize();
923 if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
924 KWFrame *frame = new KWFrame(0L, m_insRect.x(), m_insRect.y(), m_insRect.width(), m_insRect.height() );
925 frame->setMinimumFrameHeight( frame->height() ); // so that AutoExtendFrame doesn't resize it down right away
926 frame->setNewFrameBehavior(KWFrame::Reconnect);
927 frame->setZOrder( m_doc->maxZOrder( frame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
928 KWFrameDia frameDia( this, frame, m_doc, FT_TEXT );
929 frameDia.setCaption(i18n("Connect Frame"));
930 frameDia.exec();
931 if ( checkCurrentEdit(frame->frameSet(), true) )
932 emit currentFrameSetEditChanged();
933 }
934 setMouseMode( MM_EDIT );
935 m_doc->repaintAllViews();
936 emit docStructChanged(TextFrames);
937 emit currentFrameSetEditChanged();
938}
939
940void KWCanvas::mrCreatePixmap()
941{
942 // kdDebug() << "KWCanvas::mrCreatePixmap m_insRect=" << DEBUGRECT(m_insRect) << endl;
943 Q_ASSERT(m_insRect.width() > 0 && m_insRect.height() > 0);
944 // Make sure the pic is completely in document.
945 double ratio = m_insRect.width() / m_insRect.height();
946 KoRect picRect(m_doc->pageManager()->clipToDocument(m_insRect.topLeft()),
947 m_doc->pageManager()->clipToDocument(m_insRect.bottomRight()) );
948 picRect = picRect.normalize();
949
950 // Make sure it's completely on page.
951 KWPage *page = m_doc->pageManager()->page( picRect.bottom() );
952 KoRect pageRect = page->rect();
953 picRect = pageRect.intersect(picRect);
954
955 // make sure we keep ratio!
956 double height = picRect.width() / ratio ;
957 if(picRect.height() > height)
958 picRect.setBottom(picRect.top() + height);
959 else // moving bottom would make it bigger, so alter width
960 picRect.setRight(picRect.left() + ratio * picRect.height());
961
962 setMouseMode( MM_EDIT );
963 if ( !m_kopicture.isNull() ) {
964 KWPictureFrameSet *fs = new KWPictureFrameSet( m_doc, TQString() /*automatic name*/ );
965 fs->insertPicture( m_kopicture );
966 fs->setKeepAspectRatio( m_keepRatio );
967 KWFrame *frame = new KWFrame(fs, picRect.x(), picRect.y(), picRect.width(),
968 picRect.height() );
969 frame->setZOrder( m_doc->maxZOrder( page->pageNumber() ) +1 ); // make sure it's on top
970 fs->addFrame( frame, false );
971 m_doc->addFrameSet( fs );
972 KWCreateFrameCommand *cmd=new KWCreateFrameCommand( i18n("Insert Picture"), frame );
973 m_doc->addCommand(cmd);
974 m_doc->frameChanged( frame );
975 frameViewManager()->view(frame)->setSelected(true);
976 }
977 emit docStructChanged(Pictures);
978}
979
980void KWCanvas::mrCreatePart() // mouse release, when creating part
981{
982 m_insRect = m_insRect.normalize();
983 if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
984 KWPartFrameSet *fs = m_doc->insertObject( m_insRect, m_partEntry, this );
985Q_ASSERT(viewMode()->canvas());
986 if(fs)
987 fs->updateChildGeometry(); // set initial coordinates of 'ch' correctly
988 }
989 setMouseMode( MM_EDIT );
990 emit docStructChanged(Embedded);
991}
992
993void KWCanvas::mrCreateFormula()
994{
995 m_insRect = m_insRect.normalize();
996 if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
997 KWFormulaFrameSet *frameset = new KWFormulaFrameSet( m_doc, TQString() );
998 KWFrame *frame = new KWFrame(frameset, m_insRect.x(), m_insRect.y(), m_insRect.width(), m_insRect.height() );
999 frame->setZOrder( m_doc->maxZOrder( frame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
1000 frameset->addFrame( frame, false );
1001 m_doc->addFrameSet( frameset );
1002 KWCreateFrameCommand *cmd=new KWCreateFrameCommand( i18n("Create Formula Frame"), frame );
1003 m_doc->addCommand(cmd);
1004 m_doc->frameChanged( frame );
1005 }
1006 setMouseMode( MM_EDIT );
1007 emit docStructChanged(FormulaFrames);
1008}
1009
1010void KWCanvas::mrCreateTable()
1011{
1012 m_insRect = m_insRect.normalize();
1013 if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
1014 if ( m_table.cols * s_minFrameWidth + m_insRect.x() > m_doc->pageManager()->pageLayout(0).ptWidth )
1015 {
1016 KMessageBox::sorry(0, i18n("KWord is unable to insert the table because there "
1017 "is not enough space available."));
1018 }
1019 else {
1020 KWTableFrameSet * table = createTable();
1021 KMacroCommand *macroCmd = new KMacroCommand( i18n("Create Table") );
1022
1023 KWCreateTableCommand *cmd=new KWCreateTableCommand( "Create table", table );
1024 macroCmd->addCommand(cmd);
1025 if (m_table.tt) {
1026 KWTableTemplateCommand *ttCmd=new KWTableTemplateCommand( "Apply template to table", table, m_table.tt );
1027 macroCmd->addCommand(ttCmd);
1028 }
1029 m_doc->addCommand(macroCmd);
1030 macroCmd->execute();
1031
1032 emit docStructChanged(Tables);
1033 }
1034 m_doc->updateAllFrames();
1035 m_doc->layout();
1036 repaintAll();
1037
1038 }
1039 setMouseMode( MM_EDIT );
1040}
1041
1042KWTableFrameSet * KWCanvas::createTable() // uses m_insRect and m_table to create the table
1043{
1044 KWTableFrameSet *table = new KWTableFrameSet( m_doc, TQString() /*automatic name*/ );
1045 int pageNum = m_doc->pageManager()->pageNumber(m_insRect.topLeft());
1046
1047 // Create a set of cells with random-size frames.
1048 for ( unsigned int i = 0; i < m_table.rows; i++ ) {
1049 for ( unsigned int j = 0; j < m_table.cols; j++ ) {
1050 KWTableFrameSet::Cell *cell = new KWTableFrameSet::Cell( table, i, j, TQString() /*automatic name*/ );
1051 KWFrame *frame = new KWFrame(cell, 0, 0, 0, 0, KWFrame::RA_BOUNDINGRECT ); // pos and size will be set in setBoundingRect
1052 frame->setZOrder( m_doc->maxZOrder( pageNum ) + 1 ); // make sure it's on top
1053 cell->addFrame( frame, false );
1054 frame->setFrameBehavior(KWFrame::AutoExtendFrame);
1055 frame->setNewFrameBehavior(KWFrame::NoFollowup);
1056 }
1057 }
1058 KWTableFrameSet::CellSize w;
1059 w=static_cast<KWTableFrameSet::CellSize>( m_table.width );
1060 if(m_frameInline) w=KWTableFrameSet::TblManual;
1061 table->setBoundingRect( m_insRect , w, static_cast<KWTableFrameSet::CellSize>( m_table.height ));
1062 return table;
1063}
1064
1065void KWCanvas::contentsMouseReleaseEvent( TQMouseEvent * e )
1066{
1067 if ( m_printing )
1068 return;
1069 if ( m_scrollTimer->isActive() )
1070 m_scrollTimer->stop();
1071 if ( m_mousePressed ) {
1072 if ( m_deleteMovingRect )
1073 deleteMovingRect();
1074
1075 TQPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
1076 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1077
1078 if(m_insRect.bottom()==0 && m_insRect.right()==0) {
1079 // if the user did not drag, just click; make a 200x150 square for him.
1080 int page = m_doc->pageManager()->pageNumber(docPoint);
1081 if(page == -1)
1082 return;
1083 KoPageLayout pageLayout = m_doc->pageManager()->pageLayout(page);
1084 m_insRect.setLeft(TQMIN(m_insRect.left(), pageLayout.ptWidth - 200));
1085 m_insRect.setTop(TQMIN(m_insRect.top(), pageLayout.ptHeight - 150));
1086 m_insRect.setBottom(m_insRect.top()+150);
1087 m_insRect.setRight(m_insRect.left()+200);
1088 }
1089 MouseMode old_mouseMove = m_mouseMode;
1090 switch ( m_mouseMode ) {
1091 case MM_EDIT:
1092 if ( m_currentFrameSetEdit )
1093 m_currentFrameSetEdit->mouseReleaseEvent( e, normalPoint, docPoint );
1094 else {
1095 if ( m_mouseMeaning == MEANING_RESIZE_COLUMN )
1096 {
1097 KWResizeColumnCommand *cmd = new KWResizeColumnCommand( m_currentTable, m_rowColResized, m_previousTableSize, docPoint.x() );
1098 m_doc->addCommand(cmd);
1099 cmd->execute();
1100 }
1101 else if ( m_mouseMeaning == MEANING_RESIZE_ROW )
1102 {
1103 KWResizeRowCommand *cmd = new KWResizeRowCommand( m_currentTable, m_rowColResized, m_previousTableSize, docPoint.y() );
1104 m_doc->addCommand(cmd);
1105 cmd->execute();
1106 }
1107 else
1108 mrEditFrame();
1109 m_mouseMeaning = MEANING_NONE;
1110 }
1111 break;
1112 case MM_CREATE_TEXT:
1113 mrCreateText();
1114 break;
1115 case MM_CREATE_PIX:
1116 mrCreatePixmap();
1117 break;
1118 case MM_CREATE_PART:
1119 mrCreatePart();
1120 break;
1121 case MM_CREATE_TABLE:
1122 mrCreateTable();
1123 break;
1124 case MM_CREATE_FORMULA:
1125 mrCreateFormula();
1126 break;
1127 }
1128
1129 if ( old_mouseMove != MM_EDIT && !m_doc->showGrid() && m_doc->snapToGrid() )
1130 repaintContents( false ); //draw the grid over the whole canvas
1131 m_mousePressed = false;
1132 }
1133}
1134
1135void KWCanvas::contentsMouseDoubleClickEvent( TQMouseEvent * e )
1136{
1137 if ( m_printing )
1138 return;
1139 TQPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
1140 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1141 switch ( m_mouseMode ) {
1142 case MM_EDIT:
1143 if ( m_currentFrameSetEdit )
1144 {
1145 m_mousePressed = true; // needed for the dbl-click + move feature.
1146 m_scrollTimer->start( 50 );
1147 m_currentFrameSetEdit->mouseDoubleClickEvent( e, normalPoint, docPoint );
1148 }
1149 else
1150 {
1151 // Double-click on an embedded object should edit it, not pop up the frame dialog
1152 // So we have to test for that.
1153 KWFrameView *view = m_frameViewManager->selectedFrame();
1154 bool isPartFrameSet = view && dynamic_cast<KWPartFrameSet*>(view->frame()->frameSet());
1155 if ( !isPartFrameSet )
1156 editFrameProperties();
1157 // KWDocumentChild::hitTest and KWView::slotChildActivated take care of embedded objects
1158 m_mousePressed = false;
1159 }
1160 break;
1161 default:
1162 break;
1163 }
1164}
1165
1166void KWCanvas::setFrameBackgroundColor( const TQBrush &_backColor )
1167{
1168 TQValueList<KWFrameView*> selectedFrames = m_frameViewManager->selectedFrames();
1169 if (selectedFrames.isEmpty())
1170 return;
1171 bool colorChanged=false;
1172 TQPtrList<FrameIndex> frameindexList;
1173 TQPtrList<TQBrush> oldColor;
1174
1175 TQValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
1176 while(framesIterator != selectedFrames.end()) {
1177 KWFrame *frame = KWFrameSet::settingsFrame( (*framesIterator)->frame() );
1178 FrameIndex *index=new FrameIndex( frame );
1179 frameindexList.append(index);
1180
1181 TQBrush *_color=new TQBrush(frame->backgroundColor());
1182 oldColor.append(_color);
1183
1184 if (frame->frameSet() && frame->frameSet()->type()!=FT_PICTURE && frame->frameSet()->type()!=FT_PART && _backColor!=frame->backgroundColor())
1185 {
1186 colorChanged=true;
1187 frame->setBackgroundColor(_backColor);
1188 }
1189 ++framesIterator;
1190 }
1191 if(colorChanged)
1192 {
1193 KWFrameBackGroundColorCommand *cmd=new KWFrameBackGroundColorCommand(i18n("Change Frame Background Color"),frameindexList,oldColor,_backColor);
1194 m_doc->addCommand(cmd);
1195 m_doc->repaintAllViews();
1196 }
1197 else
1198 {
1199 frameindexList.setAutoDelete(true);
1200 oldColor.setAutoDelete(true);
1201 }
1202}
1203
1204void KWCanvas::editFrameProperties( KWFrameSet * frameset )
1205{
1206 KWFrameDia *frameDia;
1207 KWFrame *frame = frameset->frame(0);
1208 frameDia = new KWFrameDia( this, frame );
1209 frameDia->exec();
1210 delete frameDia;
1211}
1212
1213void KWCanvas::editFrameProperties()
1214{
1215 TQValueList<KWFrameView*> selectedFrames = m_frameViewManager->selectedFrames();
1216 if(selectedFrames.count()==0) return;
1217
1218 KWFrameDia *frameDia;
1219 if(selectedFrames.count()==1)
1220 frameDia = new KWFrameDia( this, selectedFrames[0]->frame());
1221 else { // multi frame dia.
1222 TQPtrList<KWFrame> frames;
1223 TQValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
1224 for(;framesIterator != selectedFrames.end(); ++framesIterator)
1225 frames.append( (*framesIterator)->frame() );
1226 frameDia = new KWFrameDia( this, frames );
1227 }
1228 frameDia->exec();
1229 delete frameDia;
1230}
1231
1232void KWCanvas::selectAllFrames( bool select ) {
1233 TQValueList<KWFrameView*> frameViews = m_frameViewManager->frameViewsIterator();
1234 TQValueList<KWFrameView*>::iterator frames = frameViews.begin();
1235 for(; frames != frameViews.end(); ++frames ) {
1236 KWFrameSet *fs = (*frames)->frame()->frameSet();
1237 if ( !fs->isVisible() ) continue;
1238 if ( select && fs->isMainFrameset() )
1239 continue; // "select all frames" shouldn't select the page
1240 (*frames)->setSelected(select);
1241 }
1242}
1243
1244void KWCanvas::tableSelectCell(KWTableFrameSet *table, KWFrameSet *cell)
1245{
1246 terminateCurrentEdit();
1247 m_frameViewManager->view(cell->frame(0))->setSelected(true);
1248 m_currentTable = table;
1249}
1250
1251void KWCanvas::editFrameSet( KWFrameSet * frameSet, bool onlyText /*=false*/ )
1252{
1253 selectAllFrames( false );
1254 bool emitChanged = checkCurrentEdit( frameSet, onlyText );
1255
1256 if ( emitChanged ) // emitted after mousePressEvent [for tables]
1257 emit currentFrameSetEditChanged();
1258 emit updateRuler();
1259}
1260
1261void KWCanvas::editTextFrameSet( KWFrameSet * fs, KoTextParag* parag, int index )
1262{
1263 selectAllFrames( false );
1264
1265#if 0
1266 //active header/footer when it's possible
1267 // DF: what is this code doing here?
1268 if ( fs->isAHeader() && !m_doc->isHeaderVisible() && !(viewMode()->type()=="ModeText"))
1269 m_doc->setHeaderVisible( true );
1270 if ( fs->isAFooter() && !m_doc->isFooterVisible() && !(viewMode()->type()=="ModeText"))
1271 m_doc->setFooterVisible( true );
1272#endif
1273
1274 if ( !fs->isVisible( viewMode() ) )
1275 return;
1276 setMouseMode( MM_EDIT );
1277 bool emitChanged = checkCurrentEdit( fs );
1278
1279 if ( m_currentFrameSetEdit && m_currentFrameSetEdit->frameSet()->type()==FT_TEXT ) {
1280 if ( !parag )
1281 {
1282 KWTextDocument *tmp = static_cast<KWTextFrameSet*>(m_currentFrameSetEdit->frameSet())->kwTextDocument();
1283 parag = tmp->firstParag();
1284 }
1285 // The _new_ cursor position must be visible.
1286 KWTextFrameSetEdit *textedit = currentTextEdit();
1287 if ( textedit ) {
1288 textedit->hideCursor();
1289 textedit->setCursor( parag, index );
1290 textedit->showCursor();
1291 textedit->ensureCursorVisible();
1292 }
1293 }
1294 if ( emitChanged )
1295 emit currentFrameSetEditChanged();
1296 emit updateRuler();
1297}
1298
1299void KWCanvas::ensureCursorVisible()
1300{
1301 Q_ASSERT( m_currentFrameSetEdit );
1302 KWTextFrameSetEdit *textedit = currentTextEdit();
1303 if ( textedit )
1304 textedit->ensureCursorVisible();
1305}
1306
1307bool KWCanvas::checkCurrentEdit( KWFrameSet * fs , bool onlyText )
1308{
1309 bool emitChanged = false;
1310 if ( fs && m_currentFrameSetEdit && m_currentFrameSetEdit->frameSet() != fs )
1311 {
1312 KWTextFrameSet * tmp = dynamic_cast<KWTextFrameSet *>(fs );
1313 if ( tmp && tmp->protectContent() && !m_doc->cursorInProtectedArea() )
1314 return false;
1315
1316 KWTextFrameSetEdit *edit = currentTextEdit();
1317 if(edit && onlyText)
1318 {
1319 // Don't use terminateCurrentEdit here, we want to emit changed only once
1320 //don't remove selection in dnd
1321 m_currentFrameSetEdit->terminate(false);
1322 }
1323 else
1324 m_currentFrameSetEdit->terminate();
1325 delete m_currentFrameSetEdit;
1326 m_currentFrameSetEdit = 0L;
1327 emitChanged = true;
1328
1329 }
1330
1331 // Edit the frameset "fs"
1332 if ( fs && !m_currentFrameSetEdit )
1333 {
1334 KWTextFrameSet * tmp = dynamic_cast<KWTextFrameSet *>(fs );
1335 if ( tmp && tmp->protectContent() && !m_doc->cursorInProtectedArea() )
1336 return false;
1337 // test for "text frameset only" if requested
1338 if(fs->type()==FT_TABLE || fs->type()==FT_TEXT || !onlyText)
1339 {
1340 if ( fs->type() == FT_TABLE )
1341 m_currentTable = static_cast<KWTableFrameSet *>(fs);
1342 else if ( fs->type() == FT_TEXT )
1343 m_currentTable = static_cast<KWTextFrameSet *>(fs)->groupmanager();
1344 else
1345 m_currentTable = 0L;
1346 if ( m_currentTable ) {
1347 m_currentFrameSetEdit = m_currentTable->createFrameSetEdit( this );
1348 static_cast<KWTableFrameSetEdit *>( m_currentFrameSetEdit )->setCurrentCell( fs );
1349 }
1350 else
1351 m_currentFrameSetEdit = fs->createFrameSetEdit( this );
1352
1353 if ( m_currentFrameSetEdit ) {
1354 KWTextFrameSetEdit *edit = currentTextEdit();
1355 if ( edit )
1356 edit->setOverwriteMode( m_overwriteMode );
1357 }
1358 }
1359 emitChanged = true;
1360 }
1361 return emitChanged;
1362}
1363
1364void KWCanvas::terminateCurrentEdit()
1365{
1366 if(m_currentFrameSetEdit == 0)
1367 return;
1368 m_lastCaretPos = caretPos();
1369 m_currentFrameSetEdit->terminate();
1370 delete m_currentFrameSetEdit;
1371 m_currentFrameSetEdit = 0L;
1372 emit currentFrameSetEditChanged();
1373 repaintAll();
1374}
1375
1376void KWCanvas::terminateEditing( KWFrameSet *fs )
1377{
1378 if ( m_currentFrameSetEdit && m_currentFrameSetEdit->frameSet() == fs )
1379 terminateCurrentEdit();
1380 // Also deselect the frames from this frameset
1381 TQPtrListIterator<KWFrame> frameIt = fs->frameIterator();
1382 for ( ; frameIt.current(); ++frameIt ) {
1383 KWFrameView* view = m_frameViewManager->view(frameIt.current());
1384 Q_ASSERT(view);
1385 if(view) view->setSelected(false);
1386 }
1387}
1388
1389KWTextFrameSetEdit* KWCanvas::currentTextEdit() const
1390{
1391 if ( m_currentFrameSetEdit )
1392 return dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit->currentTextEdit());
1393 return 0;
1394}
1395
1396void KWCanvas::setMouseMode( MouseMode newMouseMode )
1397{
1398 if ( m_mouseMode != newMouseMode )
1399 {
1400 selectAllFrames( false );
1401
1402 if ( newMouseMode != MM_EDIT )
1403 terminateCurrentEdit();
1404
1405 m_mouseMode = newMouseMode;
1406 if ( !m_doc->showGrid() && m_doc->snapToGrid() )
1407 repaintContents( false ); //draw the grid over the whole canvas
1408 }
1409 else
1410 m_mouseMode = newMouseMode;
1411 emit currentMouseModeChanged(m_mouseMode);
1412
1413 switch ( m_mouseMode ) {
1414 case MM_EDIT: {
1415 TQPoint mousep = mapFromGlobal(TQCursor::pos()) + TQPoint( contentsX(), contentsY() );
1416 TQPoint normalPoint = m_viewMode->viewToNormal( mousep );
1417 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1418 viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, 0 ) );
1419 m_frameInline = false;
1420 } break;
1421 case MM_CREATE_TEXT:
1422 case MM_CREATE_PIX:
1423 case MM_CREATE_TABLE:
1424 case MM_CREATE_FORMULA:
1425 case MM_CREATE_PART:
1426 viewport()->setCursor( crossCursor );
1427 break;
1428 }
1429}
1430
1431void KWCanvas::insertPicture( const KoPicture& newPicture, TQSize pixmapSize, bool _keepRatio )
1432{
1433 setMouseMode( MM_CREATE_PIX );
1434 m_kopicture = newPicture;
1435 m_pixmapSize = pixmapSize;
1436 if ( pixmapSize.isEmpty() )
1437 m_pixmapSize = newPicture.getOriginalSize();
1438 m_keepRatio = _keepRatio;
1439}
1440
1441void KWCanvas::insertPictureDirect( const KoPicture& picture, const KoPoint& pos, const TQSize& sz )
1442{
1443 // Prepare things for mrCreatePixmap
1444 m_pixmapSize = sz.isEmpty() ? picture.getOriginalSize() : sz;
1445 m_kopicture = picture;
1446 m_insRect = KoRect( pos.x(), pos.y(), m_doc->unzoomItX( m_pixmapSize.width() ), m_doc->unzoomItY( m_pixmapSize.height() ) );
1447 m_keepRatio = true;
1448 mrCreatePixmap();
1449}
1450
1451void KWCanvas::insertPart( const KoDocumentEntry &entry )
1452{
1453 m_partEntry = entry;
1454 if ( m_partEntry.isEmpty() )
1455 {
1456 setMouseMode( MM_EDIT );
1457 return;
1458 }
1459 setMouseMode( MM_CREATE_PART );
1460}
1461
1462void KWCanvas::contentsDragEnterEvent( TQDragEnterEvent *e )
1463{
1464 int provides = KWView::checkClipboard( e );
1465 if ( ( provides & KWView::ProvidesImage ) || KURLDrag::canDecode( e ) )
1466 {
1467 m_imageDrag = true;
1468 e->acceptAction();
1469 }
1470 else
1471 {
1472 m_imageDrag = false;
1473 if ( m_currentFrameSetEdit )
1474 m_currentFrameSetEdit->dragEnterEvent( e );
1475 }
1476}
1477
1478void KWCanvas::contentsDragMoveEvent( TQDragMoveEvent *e )
1479{
1480 if ( !m_imageDrag /*&& m_currentFrameSetEdit*/ )
1481 {
1482 TQPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
1483 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1484 KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
1485 KWFrame *frame = view ? view->frame() : 0;
1486 KWFrameSet * fs = frame ? frame->frameSet() : 0L;
1487 bool emitChanged = false;
1488 if ( fs )
1489 {
1490 //kdDebug()<<"table :"<<table<<endl;
1491 emitChanged = checkCurrentEdit( fs, true );
1492 }
1493 if ( m_currentFrameSetEdit )
1494 {
1495 m_currentFrameSetEdit->dragMoveEvent( e, normalPoint, docPoint );
1496
1497 if ( emitChanged ) // emitted after mousePressEvent [for tables]
1498 emit currentFrameSetEditChanged();
1499 }
1500 }
1501}
1502
1503void KWCanvas::contentsDragLeaveEvent( TQDragLeaveEvent *e )
1504{
1505 if ( !m_imageDrag && m_currentFrameSetEdit )
1506 m_currentFrameSetEdit->dragLeaveEvent( e );
1507}
1508
1509void KWCanvas::contentsDropEvent( TQDropEvent *e )
1510{
1511 TQPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
1512 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1513
1514 if ( TQImageDrag::canDecode( e ) ) {
1515 pasteImage( e, docPoint );
1516 } else if ( KURLDrag::canDecode( e ) ) {
1517
1518 // TODO ask (with a popupmenu) between inserting a link and inserting the contents
1519 // TODO fix tdehtml to export images when dragging an image+link (as it does when using "Copy")
1520
1521 KURL::List lst;
1522 KURLDrag::decode( e, lst );
1523
1524 KURL::List::ConstIterator it = lst.begin();
1525 for ( ; it != lst.end(); ++it ) {
1526 const KURL &url( *it );
1527
1528 TQString filename;
1529 if ( !TDEIO::NetAccess::download( url, filename, this ) )
1530 continue;
1531
1532 KMimeType::Ptr res = KMimeType::findByFileContent( filename );
1533
1534 if ( res && res->isValid() ) {
1535 TQString mimetype = res->name();
1536 if ( mimetype.contains( "image" ) ) {
1537 KoPictureKey key;
1538 key.setKeyFromFile( filename );
1539 KoPicture newKoPicture;
1540 newKoPicture.setKey( key );
1541 newKoPicture.loadFromFile( filename );
1542 insertPictureDirect( newKoPicture, docPoint );
1543 }
1544 }
1545 TDEIO::NetAccess::removeTempFile( filename );
1546 }
1547 }
1548 else
1549 {
1550 if ( m_currentFrameSetEdit )
1551 m_currentFrameSetEdit->dropEvent( e, normalPoint, docPoint, m_gui->getView() );
1552 else
1553 m_gui->getView()->pasteData( e, true );
1554 }
1555 m_mousePressed = false;
1556 m_imageDrag = false;
1557}
1558
1559void KWCanvas::pasteImage( TQMimeSource *e, const KoPoint &docPoint )
1560{
1561 TQImage i;
1562 if ( !TQImageDrag::decode(e, i) ) {
1563 kdWarning() << "Couldn't decode image" << endl;
1564 return;
1565 }
1566 KTempFile tmpFile( TQString(), ".png");
1567 tmpFile.setAutoDelete( true );
1568 if ( !i.save(tmpFile.name(), "PNG") ) {
1569 kdWarning() << "Couldn't save image to " << tmpFile.name() << endl;
1570 return;
1571 }
1572 m_pixmapSize = i.size();
1573 // Prepare things for mrCreatePixmap
1574 KoPictureKey key;
1575 key.setKeyFromFile( tmpFile.name() );
1576 KoPicture newKoPicture;
1577 newKoPicture.setKey( key );
1578 newKoPicture.loadFromFile( tmpFile.name() );
1579 m_kopicture = newKoPicture;
1580 m_insRect = KoRect( docPoint.x(), docPoint.y(), m_doc->unzoomItX( i.width() ), m_doc->unzoomItY( i.height() ) );
1581 m_keepRatio = true;
1582 mrCreatePixmap();
1583}
1584
1585void KWCanvas::doAutoScroll()
1586{
1587 if ( !m_mousePressed )
1588 {
1589 m_scrollTimer->stop();
1590 return;
1591 }
1592
1593 // This code comes from tdehtml
1594 TQPoint pos( mapFromGlobal( TQCursor::pos() ) );
1595
1596 pos = TQPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
1597 if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
1598 (pos.x() < 0) || (pos.x() > visibleWidth()) )
1599 {
1600 int xm, ym;
1601 viewportToContents(pos.x(), pos.y(), xm, ym);
1602 if ( m_currentFrameSetEdit )
1603 m_currentFrameSetEdit->focusOutEvent(); // Hide cursor
1604 if ( m_deleteMovingRect )
1605 deleteMovingRect();
1606 ensureVisible( xm, ym, 0, 5 );
1607 if ( m_currentFrameSetEdit )
1608 m_currentFrameSetEdit->focusInEvent(); // Show cursor
1609 }
1610}
1611
1612void KWCanvas::slotContentsMoving( int cx, int cy )
1613{
1614 //TQPoint nPointTop = m_viewMode->viewToNormal( TQPoint( cx, cy ) );
1615 TQPoint nPointBottom = m_viewMode->viewToNormal( TQPoint( cx + visibleWidth(), cy + visibleHeight() ) );
1616 //kdDebug() << "KWCanvas::slotContentsMoving cx=" << cx << " cy=" << cy << endl;
1617 //kdDebug() << " visibleWidth()=" << visibleWidth() << " visibleHeight()=" << visibleHeight() << endl;
1618 // Update our "formatted paragraphs needs" in all the text framesets
1619 TQPtrList<KWTextFrameSet> textFrameSets = m_doc->allTextFramesets( false );
1620 TQPtrListIterator<KWTextFrameSet> fit( textFrameSets );
1621 for ( ; fit.current() ; ++fit )
1622 {
1623 if(! fit.current()->isVisible()) continue;
1624 fit.current()->updateViewArea( this, m_viewMode, nPointBottom );
1625 }
1626 // cx and cy contain the future values for contentsx and contentsy, so we need to
1627 // pass them to updateRulerOffsets.
1628 updateRulerOffsets( cx, cy );
1629
1630 // Tell KoView that the view transformations have changed (e.g. the centering of the page, or the scrolling offsets)
1631 // so that it will reposition any active embedded object.
1632 // This needs to be delayed since contents moving is emitted -before- moving,
1633 // and from resizeEvent it's too early too.
1634 TQTimer::singleShot( 0, this, TQ_SIGNAL( viewTransformationsChanged() ) );
1635}
1636
1637void KWCanvas::slotMainTextHeightChanged()
1638{
1639 // Check that the viewmode is a KWViewModeText, and that the rulers have been built already
1640 if ( dynamic_cast<KWViewModeText *>(m_viewMode) && m_gui->getHorzRuler() )
1641 {
1642 slotNewContentsSize();
1643 m_viewMode->setPageLayout( m_gui->getHorzRuler(), m_gui->getVertRuler(), KoPageLayout() /*unused*/ );
1644 emit updateRuler();
1645 }
1646}
1647
1648void KWCanvas::slotNewContentsSize()
1649{
1650 TQSize size = m_viewMode->contentsSize();
1651 if ( size != TQSize( contentsWidth(), contentsHeight() ) )
1652 {
1653 //kdDebug() << "KWCanvas::slotNewContentsSize " << size.width() << "x" << size.height() << endl;
1654 resizeContents( size.width(), size.height() );
1655 }
1656}
1657
1658void KWCanvas::resizeEvent( TQResizeEvent *e )
1659{
1660 slotContentsMoving( contentsX(), contentsY() );
1661 TQScrollView::resizeEvent( e );
1662}
1663
1664void KWCanvas::scrollToOffset( const KoPoint & d )
1665{
1666 kdDebug() << "KWCanvas::scrollToOffset " << d.x() << "," << d.y() << endl;
1667#if 0
1668 bool blinking = blinkTimer.isActive();
1669 if ( blinking )
1670 stopBlinkCursor();
1671#endif
1672 TQPoint nPoint = m_doc->zoomPoint( d );
1673 TQPoint cPoint = m_viewMode->normalToView( nPoint );
1674 setContentsPos( cPoint.x(), cPoint.y() );
1675
1676#if 0
1677 if ( blinking )
1678 startBlinkCursor();
1679#endif
1680}
1681
1682void KWCanvas::updateRulerOffsets( int cx, int cy )
1683{
1684 if ( cx == -1 && cy == -1 )
1685 {
1686 cx = contentsX();
1687 cy = contentsY();
1688 }
1689 // The offset is usually just the scrollview offset
1690 // But we also need to offset to the current page, for the graduations
1691 TQPoint pc = m_viewMode->pageCorner();
1692 //kdDebug() << "KWCanvas::updateRulerOffsets contentsX=" << cx << ", contentsY=" << cy << endl;
1693 if (m_gui->getHorzRuler())
1694 m_gui->getHorzRuler()->setOffset( cx - pc.x(), 0 );
1695 if (m_gui->getVertRuler())
1696 m_gui->getVertRuler()->setOffset( 0, cy - pc.y() );
1697
1698}
1699
1700bool KWCanvas::eventFilter( TQObject *o, TQEvent *e )
1701{
1702 if ( o == this || o == viewport() ) {
1703
1704 if(m_currentFrameSetEdit && o == this )
1705 {
1706 // Pass event to auto-hide-cursor code (see kcursor.h for details)
1707 KCursor::autoHideEventFilter( o, e );
1708 }
1709
1710 switch ( e->type() ) {
1711 case TQEvent::FocusIn:
1712 // kdDebug() << "KWCanvas::eventFilter TQEvent::FocusIn" << endl;
1713 if ( m_currentFrameSetEdit && !m_printing )
1714 m_currentFrameSetEdit->focusInEvent();
1715 break;
1716 case TQEvent::FocusOut:
1717 // kdDebug() << "KWCanvas::eventFilter TQEvent::FocusOut" << endl;
1718 if ( m_currentFrameSetEdit && !m_printing )
1719 m_currentFrameSetEdit->focusOutEvent();
1720 if ( m_scrollTimer->isActive() )
1721 m_scrollTimer->stop();
1722 m_mousePressed = false;
1723 break;
1724 case TQEvent::AccelOverride: // was part of KeyPress - changed due to tdelibs BUG!
1725 {
1726 // kdDebug() << " KeyPress m_currentFrameSetEdit=" << m_currentFrameSetEdit << " isRW="<<m_doc->isReadWrite() << endl;
1727 // kdDebug() << " m_printing=" << m_printing << " mousemode=" << m_mouseMode << " (MM_EDIT=" << MM_EDIT<<")"<<endl;
1728 TQKeyEvent * keyev = static_cast<TQKeyEvent*>(e);
1729#ifndef NDEBUG
1730 // Debug keys
1731 if ( ( keyev->state() & ControlButton ) && ( keyev->state() & ShiftButton ) )
1732 {
1733 switch ( keyev->key() ) {
1734 case TQt::Key_P: // 'P' -> paragraph debug
1735 printRTDebug( 0 );
1736 keyev->accept();
1737 break;
1738 case TQt::Key_V: // 'V' -> verbose parag debug
1739 printRTDebug( 1 );
1740 keyev->accept();
1741 break;
1742 case TQt::Key_F: // 'F' -> frames debug
1743 m_doc->printDebug();
1744 kdDebug(32002) << "Current framesetedit: " << m_currentFrameSetEdit << " " <<
1745 ( m_currentFrameSetEdit ? m_currentFrameSetEdit->frameSet()->className() : "" ) << endl;
1746 keyev->accept();
1747 break;
1748 case TQt::Key_S: // 'S' -> styles debug
1749 m_doc->printStyleDebug();
1750 keyev->accept();
1751 break;
1752 case TQt::Key_M: // 'M' -> mark debug output
1753 {
1754 const TQDateTime dtMark ( TQDateTime::currentDateTime() );
1755 kdDebug(32002) << "Developer mark: " << dtMark.toString("yyyy-MM-dd hh:mm:ss,zzz") << endl;
1756 keyev->accept();
1757 break;
1758 }
1759 default:
1760 break;
1761 };
1762 // For some reason 'T' doesn't work (maybe kxkb)
1763 }
1764#endif
1765 }
1766 break;
1767 case TQEvent::KeyPress:
1768 {
1769 // kdDebug() << " KeyPress m_currentFrameSetEdit=" << m_currentFrameSetEdit << " isRW="<<m_doc->isReadWrite() << endl;
1770 // kdDebug() << " m_printing=" << m_printing << " mousemode=" << m_mouseMode << " (MM_EDIT=" << MM_EDIT<<")"<<endl;
1771 TQKeyEvent * keyev = static_cast<TQKeyEvent*>(e);
1772 // By default PgUp and PgDown move the scrollbars and not the caret anymore - this is done here
1773 if ( !m_doc->pgUpDownMovesCaret() && ( (keyev->state() & ShiftButton) == 0 )
1774 && ( keyev->key() == TQt::Key_PageUp || keyev->key() == Key_PageDown ) )
1775 {
1776 viewportScroll( keyev->key() == TQt::Key_PageUp );
1777 }
1778 // Activate this code (and in focusNextPreviousChild() to allow Shift+Tab
1779 // out of document window. Disabled because it conflicts with Shift+Tab inside a table.
1780 // else if ( keyev->key() == TQt::Key_BackTab )
1781 // return false;
1782 else if ( keyev->key() == TDEGlobalSettings::contextMenuKey() ) {
1783 // The popups are not available in readonly mode, since the GUI isn't built...
1784 if(!m_doc->isReadWrite()) return true;
1785 if (m_mouseMode != MM_EDIT) return true;
1786 KoPoint docPoint = m_doc->unzoomPoint( TQCursor::pos() );
1787
1788 if ( viewMode()->type()=="ModeText") {
1789 KWFrameView *view = m_frameViewManager->view(m_doc->frameSet( 0 )->frame(0));
1790 view->showPopup(docPoint, m_gui->getView(), TQCursor::pos());
1791 }
1792 else {
1793 m_frameViewManager->showPopup( docPoint, m_gui->getView(), keyev->state(), pos());
1794 }
1795 return true;
1796 }
1797 else if ( keyev->key() == TQt::Key_Return && keyev->state() == 0
1798 && (m_mouseMode != MM_EDIT || m_frameInline )) {
1799 // When inserting an inline or non-line frame,
1800 // simulate mouse press and release at caret position.
1801 // In the case of a regular frame, the caret position was saved when
1802 // they left edit mode. In the case of an inline frame,
1803 // get current caret position, since user can type and move caret
1804 // around before they click or hit Enter.
1805 if (m_frameInline)
1806 m_lastCaretPos = caretPos();
1807 if (m_lastCaretPos.isNull()) return true;
1808 int page = m_doc->pageManager()->pageNumber(m_lastCaretPos);
1809 if(page == -1) return true;
1810 TQPoint normalPoint = m_doc->zoomPoint(m_lastCaretPos);
1811 // Coordinate is at the very top of the caret. In the case of an
1812 // inline frame, adjust slightly down and to the right in order
1813 // to avoid "clicking" the frame border.
1814 if (m_frameInline)
1815 normalPoint += TQPoint(2,2);
1816 TQPoint vP = m_viewMode->normalToView(normalPoint);
1817 TQPoint gP = mapToGlobal(vP);
1818 TQMouseEvent mevPress(TQEvent::MouseButtonPress, vP,
1819 gP, TQt::LeftButton, 0);
1820 contentsMousePressEvent(&mevPress);
1821 TQMouseEvent mevRelease(TQEvent::MouseButtonRelease, vP,
1822 gP, TQt::LeftButton, 0);
1823 contentsMouseReleaseEvent(&mevRelease);
1824 }
1825 else if ( keyev->key() == TQt::Key_Escape ) {
1826 if ( m_mouseMode != MM_EDIT ) // Abort frame creation
1827 setMouseMode( MM_EDIT );
1828 else if(m_interactionPolicy) {
1829 m_interactionPolicy->cancelInteraction();
1830 delete(m_interactionPolicy);
1831 m_interactionPolicy = 0;
1832 m_mousePressed = false;
1833
1834 // reset cursor
1835 TQPoint mousep = mapFromGlobal(TQCursor::pos()) + TQPoint( contentsX(), contentsY() );
1836 TQPoint normalPoint = m_viewMode->viewToNormal( mousep );
1837 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1838 viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, keyev->stateAfter() ) );
1839 if ( !m_doc->showGrid() && m_doc->snapToGrid() )
1840 repaintContents();
1841 }
1842 }
1843 else if ( keyev->key() == Key_Insert && keyev->state() == 0 ) {
1844 m_overwriteMode = !m_overwriteMode;
1845 KWTextFrameSetEdit *edit = currentTextEdit();
1846 if ( edit ) {
1847 edit->setOverwriteMode( m_overwriteMode );
1848 emit overwriteModeChanged( m_overwriteMode );
1849 }
1850 kdDebug()<<"Insert is pressed, overwrite mode: "<< m_overwriteMode << endl;
1851 }
1852 else // normal key processing
1853 if ( m_currentFrameSetEdit && m_mouseMode == MM_EDIT && m_doc->isReadWrite() && !m_printing )
1854 {
1855 KWTextFrameSetEdit *edit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit );
1856 if ( edit )
1857 {
1858 if ( !edit->textFrameSet()->textObject()->protectContent() || (keyev->text().length() == 0))
1859 m_currentFrameSetEdit->keyPressEvent( keyev );
1860 else if(keyev->text().length() > 0)
1861 KMessageBox::information(this, i18n("Read-only content cannot be changed. No modifications will be accepted."));
1862 }
1863 else
1864 m_currentFrameSetEdit->keyPressEvent( keyev );
1865 return true;
1866 }
1867
1868 // Because of the dependency on the control key, we need to update the mouse cursor here
1869 if ( keyev->key() == TQt::Key_Control )
1870 {
1871 TQPoint mousep = mapFromGlobal(TQCursor::pos()) + TQPoint( contentsX(), contentsY() );
1872 TQPoint normalPoint = m_viewMode->viewToNormal( mousep );
1873 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1874 viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, keyev->stateAfter() ) );
1875 }
1876 else if ( (keyev->key() == TQt::Key_Delete || keyev->key() ==Key_Backspace )
1877 && m_frameViewManager->selectedFrame() && !m_printing )
1878 m_gui->getView()->editDeleteFrame();
1879 } break;
1880 case TQEvent::KeyRelease:
1881 {
1882 TQKeyEvent * keyev = static_cast<TQKeyEvent*>(e);
1883 if ( keyev->key() == TQt::Key_Control )
1884 {
1885 TQPoint mousep = mapFromGlobal(TQCursor::pos()) + TQPoint( contentsX(), contentsY() );
1886 TQPoint normalPoint = m_viewMode->viewToNormal( mousep );
1887 KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
1888 viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, keyev->stateAfter() ) );
1889 }
1890
1891 if ( m_currentFrameSetEdit && m_mouseMode == MM_EDIT && m_doc->isReadWrite() && !m_printing )
1892 {
1893 m_currentFrameSetEdit->keyReleaseEvent( keyev );
1894 return true;
1895 }
1896 }
1897 break;
1898 case TQEvent::IMStart:
1899 {
1900 TQIMEvent * imev = static_cast<TQIMEvent *>(e);
1901 m_currentFrameSetEdit->imStartEvent( imev );
1902 }
1903 break;
1904 case TQEvent::IMCompose:
1905 {
1906 TQIMEvent * imev = static_cast<TQIMEvent *>(e);
1907 m_currentFrameSetEdit->imComposeEvent( imev );
1908 }
1909 break;
1910 case TQEvent::IMEnd:
1911 {
1912 TQIMEvent * imev = static_cast<TQIMEvent *>(e);
1913 m_currentFrameSetEdit->imEndEvent( imev );
1914 }
1915 break;
1916 default:
1917 break;
1918 }
1919 }
1920 return TQScrollView::eventFilter( o, e );
1921}
1922
1923bool KWCanvas::focusNextPrevChild( bool next)
1924{
1925 Q_UNUSED(next);
1926 return true; // Don't allow to go out of the canvas widget by pressing "Tab"
1927 // Don't allow to go out of the canvas widget by pressing Tab, but do allow Shift+Tab.
1928 // if (next) return true;
1929 // return TQWidget::focusNextPrevChild( next );
1930}
1931
1932void KWCanvas::updateCurrentFormat()
1933{
1934 KWTextFrameSetEdit * edit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit);
1935 if ( edit )
1936 edit->updateUI( true, true );
1937}
1938
1939#ifndef NDEBUG
1940void KWCanvas::printRTDebug( int info )
1941{
1942 KWTextFrameSet * textfs = 0L;
1943 if ( m_currentFrameSetEdit ) {
1944 KWTextFrameSetEdit* edit = currentTextEdit();
1945 if ( edit ) {
1946 textfs = dynamic_cast<KWTextFrameSet *>( edit->frameSet() );
1947 Q_ASSERT( textfs );
1948 }
1949 }
1950 if ( !textfs )
1951 textfs = dynamic_cast<KWTextFrameSet *>(m_doc->frameSet( 0 ));
1952 if ( textfs )
1953 textfs->textObject()->printRTDebug( info );
1954}
1955#endif
1956
1957void KWCanvas::setXimPosition( int x, int y, int w, int h )
1958{
1959 /* Check for hasFocus() to avoid crashes in TQXIMInputContext as in bug #123941.
1960 This is only a workaround, the real problem might be in TQt. See also
1961 http://lists.kde.org/?l=kde-core-devel&m=115770546313922&w=2 .
1962 */
1963 if (hasFocus())
1964 TQWidget::setMicroFocusHint( x - contentsX(), y - contentsY(), w, h );
1965}
1966
1967void KWCanvas::inlinePictureStarted()
1968{
1969 m_frameInline=true;
1970 m_frameInlineType=FT_PICTURE;
1971}
1972
1974{
1975 if ( !m_currentFrameSetEdit )
1976 return -1;
1977 KWTextFrameSetEdit *edit = currentTextEdit();
1978 if ( !edit )
1979 return -1;
1980 KWTextFrameSet* textfs = edit->textFrameSet();
1981 if ( textfs && textfs->groupmanager() )
1982 return static_cast<KWTableFrameSet::Cell *>(textfs)->firstRow();
1983 return -1;
1984}
1985
1987{
1988 if ( !m_currentFrameSetEdit )
1989 return -1;
1990 KWTextFrameSetEdit *edit = currentTextEdit();
1991 if ( !edit )
1992 return -1;
1993 KWTextFrameSet* textfs = edit->textFrameSet();
1994 if ( textfs && textfs->groupmanager() )
1995 return static_cast<KWTableFrameSet::Cell *>(textfs)->firstColumn();
1996 return -1;
1997}
1998
1999void KWCanvas::viewportScroll( bool up )
2000{
2001 if ( up )
2002 setContentsPos( contentsX(), contentsY() - visibleHeight() );
2003 else
2004 setContentsPos( contentsX(), contentsY() + visibleHeight() );
2005}
2006
2008{
2009 if ( m_temporaryStatusBarTextShown )
2010 {
2011 gui()->getView()->updateFrameStatusBarItem();
2012 m_temporaryStatusBarTextShown = false;
2013 }
2014}
2015
2016
2017/* Returns the caret position in document coordinates.
2018 The current frame must be editable, i.e., a caret is possible. */
2020{
2021 if (!m_currentFrameSetEdit) return KoPoint();
2022 KWTextFrameSetEdit* textEdit = currentTextEdit();
2023 if (!textEdit) return KoPoint();
2024 KoTextCursor* cursor = textEdit->cursor();
2025 if (!cursor) return KoPoint();
2026 KWTextFrameSet* textFrameset =
2027 dynamic_cast<KWTextFrameSet *>(m_currentFrameSetEdit->frameSet());
2028 if (!textFrameset) return KoPoint();
2029 KWFrame* currentFrame = m_currentFrameSetEdit->currentFrame();
2030 if (!currentFrame) return KoPoint();
2031
2032 TQPoint viewP = textFrameset->cursorPos(cursor, this, currentFrame);
2033 viewP.rx() += contentsX();
2034 viewP.ry() += contentsY();
2035 TQPoint normalP = m_viewMode->viewToNormal(viewP);
2036 KoPoint docP = m_doc->unzoomPoint(normalP);
2037 return docP;
2038}
2039
2040
2041// ************** InteractionPolicy ***********************
2042InteractionPolicy::InteractionPolicy(KWCanvas *parent, bool doInit, bool includeInlineFrames) {
2043 m_gotDragEvents = false;
2044 m_parent = parent;
2045 if(doInit) {
2046 TQValueList<KWFrameView*> selectedFrames = m_parent->frameViewManager()->selectedFrames();
2047 TQValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
2048 for(;framesIterator != selectedFrames.end(); ++framesIterator) {
2049 KWFrame *frame = (*framesIterator)->frame();
2050 KWFrameSet *fs = frame->frameSet();
2051 if(! fs) continue;
2052 if(!fs->isVisible()) continue;
2053 if(fs->isMainFrameset() ) continue;
2054 if(fs->isFloating() && !includeInlineFrames) continue;
2055 if(fs->isProtectSize() ) continue;
2056 if(fs->type() == FT_TABLE ) continue;
2057 if(fs->type() == FT_TEXT && fs->frameSetInfo() != KWFrameSet::FI_BODY ) continue;
2058 m_frames.append( frame );
2059 m_indexFrame.append( FrameIndex( frame ) );
2060 }
2061 }
2062}
2063
2064InteractionPolicy* InteractionPolicy::createPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, TQt::ButtonState buttonState, TQt::ButtonState keyState) {
2065 if(buttonState & TQt::LeftButton || buttonState & TQt::RightButton) {
2066 // little inner class to make sure we don't duplicate code
2067 class Selector {
2068 public:
2069 Selector(KWCanvas *canvas, KoPoint &point, TQt::ButtonState buttonState, TQt::ButtonState keyState) :
2070 m_canvas(canvas), m_point(point), m_state(keyState) {
2071 m_leftClick = buttonState & TQt::LeftButton;
2072 KWFrameView *view = canvas->frameViewManager()->view(point,
2073 KWFrameViewManager::frameOnTop);
2074 m_doSomething = (view && !view->selected());
2075 }
2076
2077 void doSelect() {
2078 if(! m_doSomething) return;
2079 m_canvas->frameViewManager()->selectFrames(m_point, m_state, m_leftClick);
2080 }
2081 private:
2082 KWCanvas *m_canvas;
2083 KoPoint m_point;
2084 TQt::ButtonState m_state;
2085 bool m_leftClick, m_doSomething;
2086 };
2087
2088 Selector selector(parent, point, buttonState, keyState);
2089 switch(meaning) {
2090 case MEANING_MOUSE_MOVE:
2091 selector.doSelect();
2092 return new FrameMovePolicy(parent, point);
2093 case MEANING_TOPLEFT:
2094 case MEANING_TOP:
2095 case MEANING_TOPRIGHT:
2096 case MEANING_RIGHT:
2097 case MEANING_BOTTOMRIGHT:
2098 case MEANING_BOTTOM:
2099 case MEANING_BOTTOMLEFT:
2100 case MEANING_LEFT:
2101 selector.doSelect();
2102 return new FrameResizePolicy(parent, meaning, point);
2103 default:
2104 FrameSelectPolicy *fsp = new FrameSelectPolicy(parent, meaning, point, buttonState, keyState);
2105 if(fsp->isValid())
2106 return fsp;
2107 delete fsp;
2108 }
2109 }
2110 return 0; // no interaction policy found
2111}
2112
2114 KCommand *cmd = createCommand();
2115 if(cmd) {
2116 cmd->unexecute();
2117 delete cmd;
2118 }
2119}
2120
2121
2122// ************** FrameResizePolicy ***********************
2123FrameResizePolicy::FrameResizePolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point) :
2124 InteractionPolicy (parent, true, true), m_boundingRect() {
2125
2126 if( meaning == MEANING_TOPLEFT) {
2127 m_top = true; m_bottom = false; m_left = true; m_right = false;
2128 }
2129 else if( meaning == MEANING_TOP) {
2130 m_top = true; m_bottom = false; m_left = false; m_right = false;
2131 }
2132 else if( meaning == MEANING_TOPRIGHT) {
2133 m_top = true; m_bottom = false; m_left = false; m_right = true;
2134 }
2135 else if( meaning == MEANING_RIGHT) {
2136 m_top = false; m_bottom = false; m_left = false; m_right = true;
2137 }
2138 else if( meaning == MEANING_BOTTOMRIGHT) {
2139 m_top = false; m_bottom = true; m_left = false; m_right = true;
2140 }
2141 else if( meaning == MEANING_BOTTOM) {
2142 m_top = false; m_bottom = true; m_left = false; m_right = false;
2143 }
2144 else if( meaning == MEANING_BOTTOMLEFT) {
2145 m_top = false; m_bottom = true; m_left = true; m_right = false;
2146 }
2147 else if( meaning == MEANING_LEFT) {
2148 m_top = false; m_bottom = false; m_left = true; m_right = false;
2149 }
2150
2151 TQValueListConstIterator<KWFrame*> framesIterator = m_frames.begin();
2152 for(;framesIterator != m_frames.end(); ++framesIterator) {
2153 KWFrame *frame = *framesIterator;
2154 FrameResizeStruct frs(*frame, frame->minimumFrameHeight(), *frame);
2155 m_frameResize.append(frs);
2156 m_boundingRect |= frame->outerKoRect();
2157 }
2158 m_hotSpot = point - m_boundingRect.topLeft();
2159}
2160
2161void FrameResizePolicy::handleMouseMove(TQt::ButtonState keyState, const KoPoint &point) {
2162 //kdDebug() << "handleMouseMove " << (m_top?"top ":"") << (m_bottom?"bottom ":"") << (m_left?"left ":"") << (m_right?"right":"") << endl;
2163 //kdDebug() << " + point: " << point
2164 // << " boundingrect: " << m_boundingRect << endl;
2165
2166 bool keepAspect = keyState & TQt::AltButton;
2167 for(unsigned int i=0; !keepAspect && i < m_frames.count(); i++) {
2168 KWPictureFrameSet *picFs = dynamic_cast<KWPictureFrameSet*>(m_frames[i]->frameSet());
2169 if(picFs)
2170 keepAspect = picFs->keepAspectRatio();
2171 }
2172
2173 bool noGrid = keyState & TQt::ShiftButton;
2174 bool scaleFromCenter = keyState & TQt::ControlButton;
2175
2176 KoPoint p( point.x() - (m_hotSpot.x() + m_boundingRect.x()),
2177 point.y() - (m_hotSpot.y() + m_boundingRect.y()) );
2178
2179 if ( m_parent->kWordDocument()->snapToGrid() && !noGrid )
2180 m_parent->applyGrid( p );
2181
2182 KoRect sizeRect = m_boundingRect;
2183 if(m_top)
2184 sizeRect.setY(sizeRect.y() + p.y());
2185 if(m_bottom)
2186 sizeRect.setBottom(sizeRect.bottom() + p.y());
2187 if(m_left)
2188 sizeRect.setX(sizeRect.left() + p.x());
2189 if(m_right)
2190 sizeRect.setRight(sizeRect.right() + p.x());
2191 if(keepAspect) {
2192 double ratio = m_boundingRect.width() / m_boundingRect.height();
2193 double width = sizeRect.width();
2194 double height = sizeRect.height();
2195 int toLargestEdge = (m_bottom?1:0) + (m_top?1:0) + // should be false when only one
2196 (m_left?1:0) + (m_right?1:0); // of the direction bools is set
2197 bool horizontal = m_left || m_right;
2198
2199 if(toLargestEdge != 1) { // one of the corners.
2200 if (width < height) // the biggest border is the one in control
2201 width = height * ratio;
2202 else
2203 height = width / ratio;
2204 } else {
2205 if (horizontal)
2206 height = width / ratio;
2207 else
2208 width = height * ratio;
2209 }
2210 if(m_bottom)
2211 sizeRect.setBottom(sizeRect.top() + height);
2212 else
2213 sizeRect.setTop(sizeRect.bottom() - height);
2214
2215 if(m_left)
2216 sizeRect.setLeft(sizeRect.right() - width);
2217 else
2218 sizeRect.setRight(sizeRect.left() + width);
2219 }
2220 if(scaleFromCenter) {
2221 KoPoint origCenter(m_boundingRect.x() + m_boundingRect.width() / 2,
2222 m_boundingRect.y() + m_boundingRect.height() / 2);
2223 KoPoint newCenter(sizeRect.x() + sizeRect.width() / 2,
2224 sizeRect.y() + sizeRect.height() / 2);
2225 sizeRect.moveTopLeft(sizeRect.topLeft() + (origCenter - newCenter));
2226 }
2227 if(m_parent) {
2228 KWPageManager *pageManager = m_parent->kWordDocument()->pageManager();
2229 sizeRect.moveTopLeft(pageManager->clipToDocument(sizeRect.topLeft()));
2230 sizeRect.moveBottomRight(pageManager->clipToDocument(sizeRect.bottomRight()));
2231 sizeRect.setX( TQMAX(0, sizeRect.x()) ); // otherwise it would get wider than the page
2232 }
2233
2234 // each frame in m_frames should be reshaped from the original size stored in the
2235 // m_frameResize data to a size that equals the reshaping of m_boundingrect to sizeRect
2236 class Converter {
2237 public:
2238 Converter(KoRect &from, KoRect &to, KWViewMode *viewMode) {
2239 m_from = from.topLeft();
2240 m_to = to.topLeft();
2241 m_viewMode = viewMode;
2242 m_diffX = to.width() / from.width();
2243 m_diffY = to.height() / from.height();
2244 //kdDebug() << "Converter " << from << ", " << to << " x: " << m_diffX << ", y: " << m_diffY << endl;
2245 }
2246 void update(KWFrame *frame, KoRect &orig) {
2247 TQRect oldRect( m_viewMode->normalToView( frame->outerRect(m_viewMode) ) );
2248 if(! frame->frameSet()->isFloating())
2249 frame->moveTopLeft( convert( orig.topLeft() ) );
2250 KoPoint bottomRight( convert( orig.bottomRight() ) );
2251 frame->setBottom( bottomRight.y() );
2252 frame->setRight( bottomRight.x() );
2253
2254 TQRect newRect( frame->outerRect(m_viewMode) );
2255 TQRect frameRect( m_viewMode->normalToView( newRect ) );
2256 // Repaint only the changed rects (oldRect U newRect)
2257 m_repaintRegion += TQRegion(oldRect).unite(frameRect).boundingRect();
2258 }
2259
2260 TQRegion repaintRegion() {
2261 return m_repaintRegion;
2262 }
2263
2264 private:
2265 KoPoint convert(KoPoint point) {
2266 double offsetX = point.x() - m_from.x();
2267 double offsetY = point.y() - m_from.y();
2268 KoPoint answer(m_to.x() + offsetX * m_diffX, m_to.y() + offsetY * m_diffY);
2269 return answer;
2270 }
2271 private: // vars
2272 KoPoint m_from, m_to;
2273 KWViewMode *m_viewMode;
2274 TQRegion m_repaintRegion;
2275 double m_diffX, m_diffY;
2276 };
2277
2278 Converter converter(m_boundingRect, sizeRect, m_parent->viewMode());
2279 for(unsigned int i=0; i < m_frames.count(); i++)
2280 converter.update(m_frames[i], m_frameResize[i].oldRect);
2281
2282 if ( !m_parent->kWordDocument()->showGrid() && m_parent->kWordDocument()->snapToGrid() )
2283 m_parent->repaintContents( false ); //draw the grid over the whole canvas
2284 else
2285 m_parent->repaintContents( converter.repaintRegion().boundingRect(), false );
2286 m_parent->gui()->getView()->updateFrameStatusBarItem();
2287}
2288
2290 for(unsigned int i=0; i < m_frames.count(); i++) {
2291 KWFrame *frame = m_frames[i];
2292 FrameResizeStruct frs = m_frameResize[i];
2293 frs.newRect = frame->rect();
2294 frs.newMinHeight = frame->height();
2295 m_frameResize[i] = frs;
2296 }
2297 return new KWFrameResizeCommand(i18n("Resize Frame"), m_indexFrame, m_frameResize);
2298}
2299
2301 KWFrameViewManager *frameViewManager = m_parent->frameViewManager();
2302 for(unsigned int i=0; i < m_frames.count(); i++) {
2303 KWFrame *frame = m_frames[i];
2304 frame->setMinimumFrameHeight(frame->height());
2305 frameViewManager->slotFrameResized(frame);
2306 }
2307}
2308
2309
2310// *************** FrameMovePolicy ************************
2311FrameMovePolicy::FrameMovePolicy(KWCanvas *parent, KoPoint &point) :
2312 InteractionPolicy (parent), m_boundingRect() {
2313
2314 TQValueListConstIterator<KWFrame*> framesIterator = m_frames.begin();
2315 for(;framesIterator != m_frames.end(); ++framesIterator) {
2316 KWFrame *frame = *framesIterator;
2317 m_boundingRect |= frame->outerKoRect();
2318 FrameMoveStruct fms(frame->topLeft(), KoPoint(0,0));
2319 m_frameMove.append(fms);
2320 }
2321
2322 m_hotSpot = point - m_boundingRect.topLeft();
2323 m_startPoint = m_boundingRect.topLeft();
2324}
2325
2326void FrameMovePolicy::handleMouseMove(TQt::ButtonState keyState, const KoPoint &point) {
2327 bool noGrid = keyState & TQt::ShiftButton;
2328 bool linearMove = (keyState & TQt::AltButton) || (keyState & TQt::ControlButton);
2329
2330 KWPageManager *pageManager = m_parent->kWordDocument()->pageManager();
2331
2332 KoRect oldBoundingRect = m_boundingRect;
2333 //kdDebug() << "KWCanvas::mmEditFrameMove point: " << point
2334 // << " boundingrect: " << m_boundingRect << endl;
2335
2336 KoPoint p( point.x() - m_hotSpot.x(), point.y() - m_hotSpot.y() );
2337 if(linearMove) {
2338 if(TQABS(p.x() - m_startPoint.x()) < TQABS(p.y() - m_startPoint.y()))
2339 p.setX(m_startPoint.x());
2340 else
2341 p.setY(m_startPoint.y());
2342 }
2343 if ( m_parent->kWordDocument()->snapToGrid() && !noGrid )
2344 m_parent->applyGrid( p );
2345
2346 p = pageManager->clipToDocument(p);
2347 m_boundingRect.moveTopLeft( p );
2348 m_boundingRect.moveBottomRight( pageManager->clipToDocument(m_boundingRect.bottomRight()) );
2349
2350 // Another annoying case is if the top and bottom points are not in the same page....
2351 int topPage = pageManager->pageNumber( m_boundingRect.topLeft() );
2352 int bottomPage = pageManager->pageNumber( m_boundingRect.bottomRight() );
2353 //kdDebug() << "KWCanvas::mmEditFrameMove topPage=" << topPage << " bottomPage=" << bottomPage << endl;
2354 if ( topPage != bottomPage ) {
2355 // Choose the closest page...
2356 Q_ASSERT( bottomPage == -1 || topPage + 1 == bottomPage ); // Not too sure what to do otherwise
2357 double topPart = m_boundingRect.bottom() - pageManager->bottomOfPage(topPage);
2358 if ( topPart < m_boundingRect.height() / 2 ) // Most of the rect is in the top page
2359 p.setY( pageManager->bottomOfPage(topPage) - m_boundingRect.height() - 1 );
2360 else // Most of the rect is in the bottom page
2361 p.setY( pageManager->topOfPage(bottomPage) );
2362 m_boundingRect.moveTopLeft( p );
2363 m_boundingRect.moveBottomRight( pageManager->clipToDocument(m_boundingRect.bottomRight()) );
2364 }
2365
2366 if( m_boundingRect.topLeft() == oldBoundingRect.topLeft() )
2367 return; // nothing happened (probably due to the grid)
2368
2369 /*kdDebug() << "boundingRect moved by " << m_boundingRect.left() - oldBoundingRect.left() << ","
2370 << m_boundingRect.top() - oldBoundingRect.top() << endl;
2371 kdDebug() << " boundingX+hotspotX=" << m_boundingRect.left() + m_hotSpot.x() << endl;
2372 kdDebug() << " point.x()=" << point.x() << endl; */
2373
2374 TQPtrList<KWTableFrameSet> tablesMoved;
2375 tablesMoved.setAutoDelete( false );
2376 TQRegion repaintRegion;
2377 KoPoint _move=m_boundingRect.topLeft() - oldBoundingRect.topLeft();
2378
2379 TQValueListIterator<KWFrame*> framesIterator = m_frames.begin();
2380 for(; framesIterator != m_frames.end(); ++framesIterator) {
2381 KWFrame *frame = *framesIterator;
2382 KWFrameSet *fs = frame->frameSet();
2383
2384 if ( fs->type() == FT_TABLE ) {
2385 if ( tablesMoved.findRef( static_cast<KWTableFrameSet *> (fs) ) == -1 )
2386 tablesMoved.append( static_cast<KWTableFrameSet *> (fs));
2387 }
2388 else {
2389 TQRect oldRect( m_parent->viewMode()->normalToView( frame->outerRect(m_parent->viewMode()) ) );
2390 // Move the frame
2391 frame->moveTopLeft( frame->topLeft() + _move );
2392 // Calculate new rectangle for this frame
2393 TQRect newRect( frame->outerRect(m_parent->viewMode()) );
2394
2395 TQRect frameRect( m_parent->viewMode()->normalToView( newRect ) );
2396 // Repaint only the changed rects (oldRect U newRect)
2397 repaintRegion += TQRegion(oldRect).unite(frameRect).boundingRect();
2398 }
2399 }
2400
2401 if ( !tablesMoved.isEmpty() ) {
2402 //kdDebug() << "KWCanvas::mmEditFrameMove TABLESMOVED" << endl;
2403 for ( unsigned int i = 0; i < tablesMoved.count(); i++ ) {
2404 KWTableFrameSet *table = tablesMoved.at( i );
2405 for ( KWTableFrameSet::TableIter k(table) ; k ; ++k ) {
2406 KWFrame * frame = k->frame( 0 );
2407 TQRect oldRect( m_parent->viewMode()->normalToView( frame->outerRect(m_parent->viewMode()) ) );
2408 frame->moveTopLeft( frame->topLeft() + _move );
2409 // Calculate new rectangle for this frame
2410 TQRect newRect( frame->outerRect(m_parent->viewMode()) );
2411 TQRect frameRect( m_parent->viewMode()->normalToView( newRect ) );
2412 // Repaing only the changed rects (oldRect U newRect)
2413 repaintRegion += TQRegion(oldRect).unite(frameRect).boundingRect();
2414 }
2415 }
2416 }
2417
2418 if ( !m_parent->kWordDocument()->showGrid() && m_parent->kWordDocument()->snapToGrid() )
2419 m_parent->repaintContents( false ); //draw the grid over the whole canvas
2420 else
2421 m_parent->repaintContents( repaintRegion.boundingRect(), false );
2422 m_parent->gui()->getView()->updateFrameStatusBarItem();
2423}
2424
2426 for(unsigned int i=0; i < m_frames.count(); i++) {
2427 KWFrame *frame = m_frames[i];
2428 FrameMoveStruct fms = m_frameMove[i];
2429 fms.newPos = frame->topLeft();
2430 m_frameMove[i] = fms;
2431 }
2432 return new KWFrameMoveCommand( i18n("Move Frame"), m_indexFrame, m_frameMove );
2433}
2434
2436 KWFrameViewManager *frameViewManager = m_parent->frameViewManager();
2437 for(unsigned int i=0; i < m_frames.count(); i++) {
2438 KWFrame *frame = m_frames[i];
2439 frameViewManager->slotFrameMoved(frame, m_frameMove[i].oldPos.y());
2440 }
2441}
2442
2443
2444// ************** FrameSelectPolicy ***********************
2445FrameSelectPolicy::FrameSelectPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, TQt::ButtonState buttonState, TQt::ButtonState keyState)
2446 : InteractionPolicy(parent, false) {
2447
2448 bool leftButton = buttonState & TQt::LeftButton;
2449 // this is a special case; if a frame that is curently being edited is 'selected' on the border
2450 // we redirect that click to the text part of the frame.
2451 // this means we give the user a lot more space to click on the left side of the frame to
2452 // select the first characters.
2453 KWFrameSetEdit *fse = parent->currentFrameSetEdit();
2454 if(leftButton && fse) {
2455 KWFrameView *view = m_parent->frameViewManager()->view(point,
2456 KWFrameViewManager::unselected, true);
2457 if(view && view->frame()->frameSet() == fse->frameSet()) {
2458 // make sure 'point' is inside the frame
2459 point.setX(TQMAX(point.x(), view->frame()->left()));
2460 point.setY(TQMAX(point.y(), view->frame()->top()));
2461 point.setX(TQMIN(point.x(), view->frame()->right()));
2462 point.setY(TQMIN(point.y(), view->frame()->bottom()));
2463
2464 // convert point to the view coordinate system.
2465 TQPoint normalPoint = parent->kWordDocument()->zoomPoint(point);
2466 TQPoint mousePos = parent->viewMode()->normalToView(normalPoint);
2467 TQMouseEvent *me = new TQMouseEvent(TQEvent::MouseButtonPress, mousePos,
2468 buttonState, keyState);
2469 fse->mousePressEvent(me, normalPoint, point );
2470 delete me;
2471
2472 m_validSelection = false;
2473 return;
2474 }
2475 }
2476
2477 m_validSelection = meaning != MEANING_NONE;
2478 m_parent->frameViewManager()->selectFrames(point, keyState, leftButton );
2479}
2480
2481void FrameSelectPolicy::handleMouseMove(TQt::ButtonState keyState, const KoPoint &point) {
2482 Q_UNUSED(keyState);
2483 Q_UNUSED(point);
2484}
2485
2487 return 0;
2488}
2489
2492
2493#include "KWCanvas.moc"
A policy that handles frame moves of any number of frames.
Definition KWCanvas.h:461
void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point)
Extending classes should implement this method to alter the frames or other data based on the new mou...
void finishInteraction()
Override to make final changes to the data on the end of an interaction.
KCommand * createCommand()
For interactions that are undo-able this method should be implemented to return such a command.
A policy that handles resizes of any number of frames.
Definition KWCanvas.h:442
void finishInteraction()
Override to make final changes to the data on the end of an interaction.
KCommand * createCommand()
For interactions that are undo-able this method should be implemented to return such a command.
void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point)
Extending classes should implement this method to alter the frames or other data based on the new mou...
A policy to select frames.
Definition KWCanvas.h:477
void finishInteraction()
Override to make final changes to the data on the end of an interaction.
void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point)
Extending classes should implement this method to alter the frames or other data based on the new mou...
KCommand * createCommand()
For interactions that are undo-able this method should be implemented to return such a command.
Interaction policy defines the behavior in case the user clicks or drags the mouse.
Definition KWCanvas.h:379
virtual void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point)=0
Extending classes should implement this method to alter the frames or other data based on the new mou...
static InteractionPolicy * createPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, TQt::ButtonState buttonState, TQt::ButtonState keyState)
This instanciates a new policy object and decides which policy is created based on the params.
virtual void finishInteraction()=0
Override to make final changes to the data on the end of an interaction.
InteractionPolicy(KWCanvas *parent, bool doInit=true, bool includeInlineFrames=false)
Constructor.
void cancelInteraction()
This method will undo frames based interactions by calling createCommand() and unexecuting that.
virtual KCommand * createCommand()=0
For interactions that are undo-able this method should be implemented to return such a command.
Class: KWCanvas This class is responsible for the rendering of the frames to the screen as well as th...
Definition KWCanvas.h:61
virtual void drawContents(TQPainter *p, int cx, int cy, int cw, int ch)
Reimplemented from TQScrollView, to draw the contents of the canvas.
Definition KWCanvas.cpp:256
void viewportResizeEvent(TQResizeEvent *)
We need to repaint if the window is resized.
Definition KWCanvas.cpp:207
int currentTableRow() const
When the cursor is in a table cell, this returns the row.
void drawDocument(TQPainter *painter, const TQRect &crect, KWViewMode *viewMode)
The main drawing method.
Definition KWCanvas.cpp:271
void editTextFrameSet(KWFrameSet *fs, KoTextParag *parag, int index)
Starting editing fs if we're not yet doing it.
void repaintChanged(KWFrameSet *fs, bool resetChanged)
Only repaint the frameset fs.
Definition KWCanvas.cpp:186
KoPoint caretPos()
Returns the caret position in document coordinates.
int currentTableCol() const
When the cursor is in a table cell, this returns the column.
void resetStatusBarText()
Resets the status bar text.
Command created when creating a frame.
Definition KWCommand.h:436
Command created when creating a table.
Definition KWCommand.h:481
The variable showing the footnote number in superscript, in the text.
Definition KWVariable.h:106
KWFootNoteFrameSet * frameSet() const
The frameset that contains the text for this footnote.
Definition KWVariable.h:126
Command created when changing background color of one or more frames.
Definition KWCommand.h:135
Command created when one or more frames are moved.
Definition KWCommand.h:273
Command created when a frame is resized (or "moved and resized" as for KWPartFrameSet)
Definition KWCommand.h:228
This object is created to edit a particular frameset in a particular view The view's canvas creates i...
virtual void drawContents(TQPainter *, const TQRect &, const TQColorGroup &, bool onlyChanged, bool resetChanged, KWViewMode *viewMode, KWFrameViewManager *frameViewManager)
Paint this frameset in "has focus" mode (e.g.
virtual void terminate(bool=true)
Called before destruction, when terminating edition - use to e.g.
virtual KWFrameSetEdit * currentTextEdit()
Return the current most-low-level text edit object.
Class: KWFrameSet Base type, a frameset holds content as well as frames to show that content.
Definition KWFrameSet.h:62
static KWFrame * settingsFrame(const KWFrame *frame)
Returns the original frame that the param frame is a copy off, or the frame itself.
virtual FrameSetType type() const
The type of frameset.
Definition KWFrameSet.h:76
const TQPtrList< KWFrame > & frameIterator() const
Iterator over the child frames.
Definition KWFrameSet.h:159
virtual KWFrameSetEdit * createFrameSetEdit(KWCanvas *)
Create a framesetedit object to edit this frameset in canvas.
Definition KWFrameSet.h:169
virtual void drawContents(TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrameViewManager *frameViewManager)
Paint this frameset.
bool isFloating() const
Return true if this frameset is floating (inline), false if it's fixed.
Definition KWFrameSet.h:372
KWTableFrameSet * groupmanager() const
returns the groupManager this frameset belongs to.
Definition KWFrameSet.h:408
KWFrame * frame(unsigned int _num) const
get a frame by number
Info frameSetInfo() const
Returns the type of TextFrameSet this is.
Definition KWFrameSet.h:95
bool isVisible(KWViewMode *viewMode=0L) const
Returns true if the frameset is visible.
Class that knows about all the (visible) frames in the document and will act as a manager between the...
void slotFrameResized(KWFrame *f)
notify this slot if a Frame has been resized
KWFrameView * selectedFrame() const
Returns the first selected frame.
void showPopup(const KoPoint &point, KWView *view, int keyState, const TQPoint &popupPoint) const
Show a context-sensitive popup menu based on the location of 'point'.
MouseMeaning mouseMeaning(const KoPoint &point, int keyState) const
Return the MouseMeaning of what a click of the mouse would do at the point.
TQValueList< KWFrameView * > selectedFrames() const
Return all currently selected frames.
KWFrameView * view(const KoPoint &point, SelectionType select, bool borderOnly=false) const
Returns a frameView representing a frame positioned at point, or 0 when no match found.
void selectFrames(const KoPoint &point, int keyState, bool leftClick)
Select frames based on a mouse click at point using keystate.
TQCursor mouseCursor(const KoPoint &point, int keyState) const
Similar to mouseMeaning(), but instead of returning the meaning this will return a mouse cursor to re...
void slotFrameMoved(KWFrame *f, double previousYPosition)
notify this slot if a Frame has been moved
an instance of a KWFrameView represents the view in the MVC model of a frame; there can be multiple K...
Definition KWFrameView.h:82
void setSelected(bool selected, MouseMeaning selectPolicy=MEANING_MOUSE_SELECT)
Set the selected state of this frameView.
KWFrame * frame() const
returns the frame this frameView represents
bool selected() const
returns if this frameView is selected. A selected frame is shown differently on screen.
Definition KWFrameView.h:93
void showPopup(const KoPoint &point, KWView *view, const TQPoint &popupPoint) const
Show a context-sensitive popup menu based on the location of 'point'.
This class represents a single frame.
Definition KWFrame.h:68
TQRect outerRect(KWViewMode *viewMode) const
Return the zoomed rectangle for this frame, including the border - for drawing.
Definition KWFrame.cpp:185
double minimumFrameHeight(void) const
Definition KWFrame.h:284
KWFrameSet * frameSet() const
Data stucture methods.
Definition KWFrame.h:143
void setMinimumFrameHeight(double h)
The property minimum frame height is used to make the automatic frame shrinking code stop.
Definition KWFrame.h:279
void setZOrder(int z)
The z-order of the frame, relative to the other frames on the same page.
Definition KWFrame.h:155
int pageNumber() const
The page on which this frame is.
Definition KWFrame.cpp:116
KoRect outerKoRect() const
Return the unzoomed rectangle, including the border, for the frames-on-top list.
Definition KWFrame.cpp:200
const KoRect & rect() const
Return the rectangle for this frame.
Definition KWFrame.h:201
The Page Manager manages all the pages a document contains and separates all the frames the document ...
double topOfPage(int pageNumber) const
Return the y-offset in this document of the top of page with pageNumber Note that pageNumber is NOT a...
KoPoint clipToDocument(const KoPoint &point)
Returns the argument point, with altered coordinats if the point happens to be outside all pages.
int pageNumber(const KoRect *rect) const
return pageNumber of frame, pagenumbers for a normal document start at 1.
double bottomOfPage(int pageNumber) const
Return the y-offset in this document of the bottom of page with pageNumber Note that pageNumber is NO...
This class represents a printed page of the document.
Definition KWPage.h:30
int pageNumber() const
returns the number of this page as it will be shown to the user.
Definition KWPage.h:102
const KoRect rect() const
return a KoRect with the (pt) sizes of this page. Margins are ignored for this function.
Definition KWPage.cpp:137
A frameset that contains an embedded object (a KWDocumentChild)
void updateChildGeometry()
Update the geometry of m_child based on the geometry of the frame.
The object created to edit this table.
This class implements tables by acting as the manager for the frame(set)s which make up the table cel...
virtual void finalize()
Called once the frameset has been completely loaded or constructed.
void resizeColumn(unsigned int col, double x)
move a column edge (i.e.
KoRect boundingRect()
Calculate the absolute size of the complete table.
void setBoundingRect(KoRect rect, CellSize widthMode, CellSize heightMode)
Layout all cells to fit inside the rect, cells will however use a minimum size, so the table might en...
int columnEdgeAt(double x) const
return the number of the column edge closest to x (between 0 and getCols()+1)
void resizeRow(unsigned int row, double y)
move a row edge (i.e.
int rowEdgeAt(double y) const
return the number of the row edge closest to x (between 0 and getRows()+1)
virtual KWFrameSetEdit * createFrameSetEdit(KWCanvas *canvas)
Create a framesetedit object to edit this frameset in canvas.
Command created when applying a tabletemplate.
Definition KWCommand.h:194
This is our KoTextDocument reimplementation, to create KWTextParag instead of KoTextParags,...
Object that is created to edit a Text frame set (KWTextFrameSet).
Class: KWTextFrameSet Contains text (KoTextObject) and frames to display that text.
KoTextObject * textObject() const
Return the contained text object.
The view mode used when printing (pages under one another, no selections)
Definition KWViewMode.h:177
The 'edit only one text frameset' view mode.
Definition KWViewMode.h:253
Abstract base class for KWCanvas's view modes.
Definition KWViewMode.h:48
virtual bool hasFrames()
Does this viewmode know anything about frames?
Definition KWViewMode.h:119
virtual void setPageLayout(KoRuler *hRuler, KoRuler *vRuler, const KoPageLayout &layout)
Called when the page layout is set, or changes.
virtual TQPoint pageCorner()
"Topleft of current page" - concept used by the rulers.
virtual TQPoint normalToView(const TQPoint &nPoint)=0
Normal coord -> view coord.
virtual TQRect viewPageRect(int pgNum)=0
Return view coord for page rect.
virtual TQSize contentsSize()=0
Size of the contents area, in pixels.
virtual TQPoint viewToNormal(const TQPoint &vPoint)=0
View coord -> normal coord.
virtual const TQString type() const =0
Return the name of the viewmode, used for loading/saving.
Identifies a frame.
Definition KWCommand.h:98