F:/KPlato/koffice/libs/kotext/KoTextTool.cpp

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002  * Copyright (C) 2006 Thomas Zander <zander@kde.org>
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public License
00015  * along with this library; see the file COPYING.LIB.  If not, write to
00016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include <KoTextTool.h>
00021 #include <KoCanvasBase.h>
00022 #include <KoSelection.h>
00023 #include <KoShapeManager.h>
00024 #include <KoPointerEvent.h>
00025 
00026 #include <kdebug.h>
00027 #include <QKeyEvent>
00028 #include <QTextBlock>
00029 #include <QTextLayout>
00030 #include <QAbstractTextDocumentLayout>
00031 
00032 KoTextTool::KoTextTool(KoCanvasBase *canvas)
00033 : KoTool(canvas)
00034 , m_textShape(0)
00035 , m_textShapeData(0)
00036 {
00037 }
00038 
00039 KoTextTool::~KoTextTool() {
00040 }
00041 
00042 void KoTextTool::paint( QPainter &painter, KoViewConverter &converter) {
00043     if(painter.hasClipping()) {
00044         QRect shape = converter.documentToView(m_textShape->boundingRect()).toRect();
00045         if(painter.clipRegion().intersect( QRegion(shape) ).isEmpty())
00046             return;
00047     }
00048 
00049     painter.setMatrix( painter.matrix() * m_textShape->transformationMatrix(&converter) );
00050     double zoomX, zoomY;
00051     converter.zoom(&zoomX, &zoomY);
00052     painter.scale(zoomX, zoomY);
00053     //const QTextDocument *document = m_caret.block().document();
00054 
00055 /*
00056     QAbstractTextDocumentLayout::PaintContext pc;
00057     pc.cursorPosition = m_caret.position();
00058     QAbstractTextDocumentLayout::Selection selection;
00059     selection.cursor = m_caret;
00060     selection.format.setTextOutline(QPen(Qt::red));
00061     pc.selections.append(selection);
00062     document->documentLayout()->draw( &painter, pc);
00063 */
00064 
00065     QTextBlock block = m_caret.block();
00066     if(! block.layout())
00067         return;
00068 
00069 #if 0
00070 Hmm, not useful right now due to the implementation of QAbstractTextDocumentLayout
00071     if(m_caret.selectionStart() != m_caret.selectionEnd()) { // paint selection
00072         //kDebug(32500) << "Selection: " << m_caret.selectionStart() << "-" << m_caret.selectionEnd() << "\n";
00073         bool first = true;
00074         QList<QTextLine> lines;
00075         QTextBlock block = document->findBlock(m_caret.selectionStart());
00076         do { // for all textBlocks
00077             QTextLayout *layout = block.layout();
00078             if(!block.isValid() || block.position() > m_caret.selectionEnd())
00079                 break;
00080             if(layout == 0)
00081                 continue;
00082             layout->setCacheEnabled(true);
00083 kDebug() << " block '" << block.text() << "'" << endl;
00084             for(int i=0; i < layout->lineCount(); i++) {
00085                 QTextLine line = layout->lineAt(i);
00086 kDebug() << " line: " << line.textStart() << "-" << (line.textStart() + line.textLength()) << endl;
00087                 if(first && line.textStart() + line.textLength() < m_caret.selectionStart())
00088                     continue;
00089                 lines.append(line);
00090 kDebug() << "    appending" << endl;
00091                 if(line.textStart() + line.textLength() > m_caret.selectionEnd())
00092                     break;
00093             }
00094             first = false;
00095             block = block.next();
00096         } while(block.position() + block.length() < m_caret.selectionEnd());
00097 
00098         kDebug(32500) << "found " << lines.count() << " lines that contain the selection" << endl;
00099         foreach(QTextLine line, lines) {
00100             if(! line.isValid())
00101                 continue;
00102             if(painter.clipRegion().intersect(QRegion(line.rect().toRect())).isEmpty())
00103                 continue;
00104             painter.fillRect(line.rect(), QBrush(Qt::yellow));
00105         }
00106     }
00107 #endif
00108 
00109     // paint caret.
00110     QPen pen(Qt::black);
00111     if(! m_textShape->hasTransparency()) {
00112         QColor bg = m_textShape->background().color();
00113         QColor invert = QColor(255 - bg.red(), 255 - bg.green(), 255 - bg.blue());
00114         pen.setColor(invert);
00115     }
00116     painter.setPen(pen);
00117     painter.translate(0, -m_textShapeData->documentOffset());
00118     block.layout()->drawCursor(&painter, QPointF(0,0), m_caret.position() - block.position());
00119 }
00120 
00121 void KoTextTool::mousePressEvent( KoPointerEvent *event ) {
00122     if(! m_textShape->boundingRect().contains(event->point)) {
00123         QRectF area(event->point, QSizeF(1,1));
00124         foreach(KoShape *shape, m_canvas->shapeManager()->shapesAt(area, true)) {
00125             KoTextShape *textShape = dynamic_cast<KoTextShape*> (shape);
00126             if(textShape) {
00127                 m_textShape = textShape;
00128                 KoTextShapeData *d = static_cast<KoTextShapeData*> (textShape->userData());
00129                 if(d->document() == m_textShapeData->document())
00130                     break; // stop looking.
00131             }
00132         }
00133         m_textShapeData = static_cast<KoTextShapeData*> (m_textShape->userData());
00134         // in case its a different doc...
00135         m_caret = QTextCursor(m_textShapeData->document());
00136     }
00137 
00138     int position = pointToPosition(event->point);
00139     repaint();
00140     m_caret.setPosition(position);
00141     repaint();
00142 }
00143 
00144 int KoTextTool::pointToPosition(const QPointF & point) const {
00145     QPointF p = m_textShape->convertScreenPos(point);
00146     int caretPos = m_caret.block().document()->documentLayout()->hitTest(p, Qt::FuzzyHit);
00147     caretPos = qMax(caretPos, m_textShapeData->position());
00148     if(m_textShapeData->endPosition() == -1)
00149         kWarning() << "Clicking in not fully laid-out textframe\n";
00150     caretPos = qMin(caretPos, m_textShapeData->endPosition());
00151     return caretPos;
00152 }
00153 
00154 void KoTextTool::mouseDoubleClickEvent( KoPointerEvent *event ) {
00155     // TODO select whole word, or when clicking in between two words select 2 words.
00156 }
00157 
00158 void KoTextTool::mouseMoveEvent( KoPointerEvent *event ) {
00159     useCursor(Qt::IBeamCursor);
00160     if(event->buttons() == Qt::NoButton)
00161         return;
00162     int position = pointToPosition(event->point);
00163     if(position >= 0) {
00164         repaint();
00165         m_caret.setPosition(position, QTextCursor::KeepAnchor);
00166         repaint();
00167     }
00168 }
00169 
00170 void KoTextTool::mouseReleaseEvent( KoPointerEvent *event ) {
00171     // TODO
00172 }
00173 
00174 void KoTextTool::keyPressEvent(QKeyEvent *event) {
00175     QTextCursor::MoveOperation moveOperation = QTextCursor::NoMove;
00176     switch(event->key()) { // map input to moveOperation
00177 /* TODO
00178  * Look at KoTextView::handleKeyPressEvent
00179  * Use    if ( KShortcut(  e->key() ) == KStdAccel::deleteWordBack() )  and friends
00180  */
00181         case Qt::Key_Backspace:
00182             useCursor(Qt::BlankCursor);
00183             m_caret.deletePreviousChar();
00184             break;
00185         case Qt::Key_Tab:
00186             kDebug(32500) << "Tab key pressed";
00187             break;
00188         case Qt::Key_Delete:
00189             useCursor(Qt::BlankCursor);
00190             m_caret.deleteChar();
00191             break;
00192         case Qt::Key_Left:
00193             if(event->modifiers() & Qt::ControlModifier)
00194                 moveOperation = QTextCursor::WordLeft;
00195             else
00196                 moveOperation = QTextCursor::Left;
00197             break;
00198         case Qt::Key_Up:
00199             moveOperation = QTextCursor::Up;
00200             break;
00201         case Qt::Key_Right:
00202             if(event->modifiers() & Qt::ControlModifier)
00203                 moveOperation = QTextCursor::NextWord;
00204             else
00205                 moveOperation = QTextCursor::Right;
00206             break;
00207         case Qt::Key_Down:
00208             moveOperation = QTextCursor::Down;
00209             break;
00210         case Qt::Key_PageUp:
00211             //moveOperation = QTextCursor::Left;
00212             break;
00213         case Qt::Key_PageDown:
00214             //moveOperation = QTextCursor::Left;
00215             break;
00216         case Qt::Key_End:
00217             moveOperation = QTextCursor::EndOfLine;
00218             break;
00219         case Qt::Key_Home:
00220             moveOperation = QTextCursor::StartOfLine;
00221             break;
00222         default:
00223             if(event->text().length() == 0)
00224                 return;
00225             useCursor(Qt::BlankCursor);
00226             m_caret.insertText(event->text());
00227     }
00228     if(moveOperation != QTextCursor::NoMove) {
00229         repaint();
00230         m_caret.movePosition(moveOperation,
00231             (event->modifiers() & Qt::ShiftModifier)?QTextCursor::KeepAnchor:QTextCursor::MoveAnchor);
00232         repaint();
00233     }
00234     event->accept();
00235 }
00236 
00237 void KoTextTool::keyReleaseEvent(QKeyEvent *event) {
00238     event->accept();
00239 }
00240 
00241 void KoTextTool::activate (bool temporary) {
00242     Q_UNUSED(temporary);
00243     KoSelection *selection = m_canvas->shapeManager()->selection();
00244     foreach(KoShape *shape, selection->selectedShapes().toList()) {
00245         m_textShape = dynamic_cast<KoTextShape*> (shape);
00246         if(m_textShape)
00247             break;
00248     }
00249     if(m_textShape == 0) { // none found
00250         emit sigDone();
00251         return;
00252     }
00253     foreach(KoShape *shape, selection->selectedShapes().toList()) {
00254         // deselect others.
00255         if(m_textShape == shape) continue;
00256         selection->deselect(shape);
00257     }
00258     m_textShapeData = static_cast<KoTextShapeData*> (m_textShape->userData());
00259     m_textShapeData->document()->setUndoRedoEnabled(true); // allow undo history
00260     m_caret = QTextCursor(m_textShapeData->document());
00261     useCursor(Qt::IBeamCursor, true);
00262     m_textShape->repaint();
00263 }
00264 
00265 void KoTextTool::deactivate() {
00266     m_textShape = 0;
00267     if(m_textShapeData)
00268         m_textShapeData->document()->setUndoRedoEnabled(false); // erase undo history.
00269     m_textShapeData = 0;
00270 }
00271 
00272 void KoTextTool::repaint() {
00273     QTextBlock block = m_caret.block();
00274     if(block.isValid()) {
00275         QTextLine tl = block.layout()->lineForTextPosition(m_caret.position() - block.position());
00276         QRectF repaintRect;
00277         if(tl.isValid())
00278             repaintRect = tl.rect();
00279         else // layouting info was removed already :(
00280             repaintRect = block.layout()->boundingRect();
00281         repaintRect.moveTop(repaintRect.y() - m_textShapeData->documentOffset());
00282         repaintRect.moveTopLeft(repaintRect.topLeft() + m_textShape->position());
00283         m_canvas->updateCanvas(repaintRect);
00284     }
00285 }

Généré le Wed Nov 22 23:41:10 2006 pour KPlato par  doxygen 1.5.1-p1