Warning, file /office/calligra/libs/widgets/KoRuler.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> 0003 Copyright (C) 2006 Peter Simonsson <peter.simonsson@gmail.com> 0004 Copyright (C) 2007 C. Boemann <cbo@boemann.dk> 0005 Copyright (C) 2007-2008 Jan Hambrecht <jaham@gmx.net> 0006 Copyright (C) 2007 Thomas Zander <zander@kde.org> 0007 0008 This library is free software; you can redistribute it and/or 0009 modify it under the terms of the GNU Library General Public 0010 License as published by the Free Software Foundation; either 0011 version 2 of the License, or (at your option) any later version. 0012 0013 This library is distributed in the hope that it will be useful, 0014 but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 Library General Public License for more details. 0017 0018 You should have received a copy of the GNU Library General Public License 0019 along with this library; see the file COPYING.LIB. If not, write to 0020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 Boston, MA 02110-1301, USA. 0022 */ 0023 0024 #include "KoRuler.h" 0025 0026 #include "KoRuler_p.h" 0027 #include <KoToolBase.h> 0028 #include <KoToolManager.h> 0029 0030 #include <klocalizedstring.h> 0031 #include <WidgetsDebug.h> 0032 0033 #include <QPainter> 0034 #include <QResizeEvent> 0035 #include <QMenu> 0036 #include <QMouseEvent> 0037 #include <QFontDatabase> 0038 0039 #include <KoViewConverter.h> 0040 0041 #include <algorithm> 0042 0043 // the distance in pixels of a mouse position considered outside the rule 0044 static const int OutsideRulerThreshold = 20; 0045 // 0046 static const int fullStepMarkerLength = 6; 0047 static const int halfStepMarkerLength = 6; 0048 static const int quarterStepMarkerLength = 3; 0049 static const int measurementTextAboveBelowMargin = 1; 0050 0051 0052 void RulerTabChooser::mousePressEvent(QMouseEvent *) 0053 { 0054 if (! m_showTabs) { 0055 return; 0056 } 0057 0058 switch(m_type) { 0059 case QTextOption::LeftTab: 0060 m_type = QTextOption::RightTab; 0061 break; 0062 case QTextOption::RightTab: 0063 m_type = QTextOption::CenterTab; 0064 break; 0065 case QTextOption::CenterTab: 0066 m_type = QTextOption::DelimiterTab; 0067 break; 0068 case QTextOption::DelimiterTab: 0069 m_type = QTextOption::LeftTab; 0070 break; 0071 } 0072 update(); 0073 } 0074 0075 void RulerTabChooser::paintEvent(QPaintEvent *) 0076 { 0077 if (! m_showTabs) { 0078 return; 0079 } 0080 0081 QPainter painter(this); 0082 QPolygonF polygon; 0083 0084 painter.setPen(QPen(palette().color(QPalette::Text), 0)); 0085 painter.setBrush(palette().color(QPalette::Text)); 0086 painter.setRenderHint( QPainter::Antialiasing ); 0087 0088 qreal x= width()/2; 0089 painter.translate(0,-height()/2+5); 0090 0091 switch (m_type) { 0092 case QTextOption::LeftTab: 0093 polygon << QPointF(x+0.5, height() - 8.5) 0094 << QPointF(x+6.5, height() - 2.5) 0095 << QPointF(x+0.5, height() - 2.5); 0096 painter.drawPolygon(polygon); 0097 break; 0098 case QTextOption::RightTab: 0099 polygon << QPointF(x+0.5, height() - 8.5) 0100 << QPointF(x-5.5, height() - 2.5) 0101 << QPointF(x+0.5, height() - 2.5); 0102 painter.drawPolygon(polygon); 0103 break; 0104 case QTextOption::CenterTab: 0105 polygon << QPointF(x+0.5, height() - 8.5) 0106 << QPointF(x-5.5, height() - 2.5) 0107 << QPointF(x+6.5, height() - 2.5); 0108 painter.drawPolygon(polygon); 0109 break; 0110 case QTextOption::DelimiterTab: 0111 polygon << QPointF(x-5.5, height() - 2.5) 0112 << QPointF(x+6.5, height() - 2.5); 0113 painter.drawPolyline(polygon); 0114 polygon << QPointF(x+0.5, height() - 2.5) 0115 << QPointF(x+0.5, height() - 8.5); 0116 painter.drawPolyline(polygon); 0117 break; 0118 default: 0119 break; 0120 } 0121 } 0122 0123 static int compareTabs(KoRuler::Tab &tab1, KoRuler::Tab &tab2) 0124 { 0125 return tab1.position < tab2.position; 0126 } 0127 0128 QRectF HorizontalPaintingStrategy::drawBackground(const KoRulerPrivate *d, QPainter &painter) 0129 { 0130 lengthInPixel = d->viewConverter->documentToViewX(d->rulerLength); 0131 QRectF rectangle; 0132 rectangle.setX(qMax(0, d->offset)); 0133 rectangle.setY(0); 0134 rectangle.setWidth(qMin(qreal(d->ruler->width() - 1.0 - rectangle.x()), 0135 (d->offset >= 0) ? lengthInPixel : lengthInPixel + d->offset)); 0136 rectangle.setHeight(d->ruler->height() - 1); 0137 QRectF activeRangeRectangle; 0138 activeRangeRectangle.setX(qMax(rectangle.x() + 1, 0139 d->viewConverter->documentToViewX(d->effectiveActiveRangeStart()) + d->offset)); 0140 activeRangeRectangle.setY(rectangle.y() + 1); 0141 activeRangeRectangle.setRight(qMin(rectangle.right() - 1, 0142 d->viewConverter->documentToViewX(d->effectiveActiveRangeEnd()) + d->offset)); 0143 activeRangeRectangle.setHeight(rectangle.height() - 2); 0144 0145 painter.setPen(QPen(d->ruler->palette().color(QPalette::Mid), 0)); 0146 0147 0148 painter.fillRect(rectangle,d->ruler->palette().color(QPalette::AlternateBase)); // make background slightly different so it is easier to see 0149 painter.drawRect(rectangle); 0150 0151 if(d->effectiveActiveRangeStart() != d->effectiveActiveRangeEnd()) 0152 painter.fillRect(activeRangeRectangle, d->ruler->palette().brush(QPalette::Base)); 0153 0154 if(d->showSelectionBorders) { 0155 // Draw first selection border 0156 if(d->firstSelectionBorder > 0) { 0157 qreal border = d->viewConverter->documentToViewX(d->firstSelectionBorder) + d->offset; 0158 painter.drawLine(QPointF(border, rectangle.y() + 1), QPointF(border, rectangle.bottom() - 1)); 0159 } 0160 // Draw second selection border 0161 if(d->secondSelectionBorder > 0) { 0162 qreal border = d->viewConverter->documentToViewX(d->secondSelectionBorder) + d->offset; 0163 painter.drawLine(QPointF(border, rectangle.y() + 1), QPointF(border, rectangle.bottom() - 1)); 0164 } 0165 } 0166 0167 return rectangle; 0168 } 0169 0170 void HorizontalPaintingStrategy::drawTabs(const KoRulerPrivate *d, QPainter &painter) 0171 { 0172 if (! d->showTabs) 0173 return; 0174 QPolygonF polygon; 0175 0176 const QColor tabColor = d->ruler->palette().color(QPalette::Text); 0177 painter.setPen(QPen(tabColor, 0)); 0178 painter.setBrush(tabColor); 0179 painter.setRenderHint( QPainter::Antialiasing ); 0180 0181 qreal position = -10000; 0182 0183 foreach (const KoRuler::Tab & t, d->tabs) { 0184 qreal x; 0185 if (d->rightToLeft) { 0186 x = d->viewConverter->documentToViewX(d->effectiveActiveRangeEnd() 0187 - (d->relativeTabs ? d->paragraphIndent : 0) - t.position) + d->offset; 0188 } else { 0189 x = d->viewConverter->documentToViewX(d->effectiveActiveRangeStart() 0190 + (d->relativeTabs ? d->paragraphIndent : 0) + t.position) + d->offset; 0191 } 0192 position = qMax(position, t.position); 0193 0194 polygon.clear(); 0195 switch (t.type) { 0196 case QTextOption::LeftTab: 0197 polygon << QPointF(x+0.5, d->ruler->height() - 6.5) 0198 << QPointF(x+6.5, d->ruler->height() - 0.5) 0199 << QPointF(x+0.5, d->ruler->height() - 0.5); 0200 painter.drawPolygon(polygon); 0201 break; 0202 case QTextOption::RightTab: 0203 polygon << QPointF(x+0.5, d->ruler->height() - 6.5) 0204 << QPointF(x-5.5, d->ruler->height() - 0.5) 0205 << QPointF(x+0.5, d->ruler->height() - 0.5); 0206 painter.drawPolygon(polygon); 0207 break; 0208 case QTextOption::CenterTab: 0209 polygon << QPointF(x+0.5, d->ruler->height() - 6.5) 0210 << QPointF(x-5.5, d->ruler->height() - 0.5) 0211 << QPointF(x+6.5, d->ruler->height() - 0.5); 0212 painter.drawPolygon(polygon); 0213 break; 0214 case QTextOption::DelimiterTab: 0215 polygon << QPointF(x-5.5, d->ruler->height() - 0.5) 0216 << QPointF(x+6.5, d->ruler->height() - 0.5); 0217 painter.drawPolyline(polygon); 0218 polygon << QPointF(x+0.5, d->ruler->height() - 0.5) 0219 << QPointF(x+0.5, d->ruler->height() - 6.5); 0220 painter.drawPolyline(polygon); 0221 break; 0222 default: 0223 break; 0224 } 0225 } 0226 0227 // and also draw the regular interval tab that are non editable 0228 if (d->tabDistance > 0.0) { 0229 // first possible position 0230 position = qMax(position, d->relativeTabs ? 0 : d->paragraphIndent); 0231 if (position < 0) { 0232 position = int(position / d->tabDistance) * d->tabDistance; 0233 } else { 0234 position = (int(position / d->tabDistance) + 1) * d->tabDistance; 0235 } 0236 while (position < d->effectiveActiveRangeEnd() - d->effectiveActiveRangeStart() 0237 - d->endIndent) { 0238 qreal x; 0239 if (d->rightToLeft) { 0240 x = d->viewConverter->documentToViewX(d->effectiveActiveRangeEnd() 0241 - (d->relativeTabs ? d->paragraphIndent : 0) - position) + d->offset; 0242 } else { 0243 x = d->viewConverter->documentToViewX(d->effectiveActiveRangeStart() 0244 + (d->relativeTabs ? d->paragraphIndent : 0) + position) + d->offset; 0245 } 0246 0247 polygon.clear(); 0248 polygon << QPointF(x+0.5, d->ruler->height() - 3.5) 0249 << QPointF(x+4.5, d->ruler->height() - 0.5) 0250 << QPointF(x+0.5, d->ruler->height() - 0.5); 0251 painter.drawPolygon(polygon); 0252 0253 position += d->tabDistance; 0254 } 0255 } 0256 } 0257 0258 void HorizontalPaintingStrategy::drawMeasurements(const KoRulerPrivate *d, QPainter &painter, const QRectF &rectangle) 0259 { 0260 qreal numberStep = d->numberStepForUnit(); // number step in unit 0261 // QRectF activeRangeRectangle; 0262 int numberStepPixel = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue(numberStep))); 0263 // const bool adjustMillimeters = (d->unit.type() == KoUnit::Millimeter); 0264 0265 const QFont font = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); 0266 const QFontMetrics fontMetrics(font); 0267 painter.setFont(font); 0268 0269 if (numberStepPixel == 0 || numberStep == 0) 0270 return; 0271 0272 // Calc the longest text length 0273 int textLength = 0; 0274 for(int i = 0; i < lengthInPixel; i += numberStepPixel) { 0275 int number = qRound((i / numberStepPixel) * numberStep); 0276 0277 textLength = qMax(textLength, fontMetrics.width(QString::number(number))); 0278 } 0279 textLength += 4; // Add some padding 0280 0281 // Change number step so all digits fits 0282 while(textLength > numberStepPixel) { 0283 numberStepPixel += numberStepPixel; 0284 numberStep += numberStep; 0285 } 0286 0287 int start=0; 0288 // Calc the first number step 0289 if(d->offset < 0) 0290 start = qAbs(d->offset); 0291 0292 // make a little hack so rulers shows correctly inversed number aligned 0293 const qreal lengthInUnit = d->unit.toUserValue(d->rulerLength); 0294 const qreal hackyLength = lengthInUnit - fmod(lengthInUnit, numberStep); 0295 if(d->rightToLeft) { 0296 start -= int(d->viewConverter->documentToViewX(fmod(d->rulerLength, 0297 d->unit.fromUserValue(numberStep)))); 0298 } 0299 0300 int stepCount = (start / numberStepPixel) + 1; 0301 int halfStepCount = (start / qRound(numberStepPixel * 0.5)) + 1; 0302 int quarterStepCount = (start / qRound(numberStepPixel * 0.25)) + 1; 0303 0304 int pos = 0; 0305 const QPen numberPen(d->ruler->palette().color(QPalette::Text), 0); 0306 const QPen markerPen(d->ruler->palette().color(QPalette::Inactive, QPalette::Text), 0); 0307 painter.setPen(markerPen); 0308 0309 if(d->offset > 0) 0310 painter.translate(d->offset, 0); 0311 0312 const int len = qRound(rectangle.width()) + start; 0313 int nextStep = qRound(d->viewConverter->documentToViewX( 0314 d->unit.fromUserValue(numberStep * stepCount))); 0315 int nextHalfStep = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue( 0316 numberStep * 0.5 * halfStepCount))); 0317 int nextQuarterStep = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue( 0318 numberStep * 0.25 * quarterStepCount))); 0319 0320 for(int i = start; i < len; ++i) { 0321 pos = i - start; 0322 0323 if(i == nextStep) { 0324 if(pos != 0) 0325 painter.drawLine(QPointF(pos, rectangle.bottom()-1), 0326 QPointF(pos, rectangle.bottom() - fullStepMarkerLength)); 0327 0328 int number = qRound(stepCount * numberStep); 0329 0330 QString numberText = QString::number(number); 0331 int x = pos; 0332 if (d->rightToLeft) { // this is done in a hacky way with the fine tuning done above 0333 numberText = QString::number(hackyLength - stepCount * numberStep); 0334 } 0335 painter.setPen(numberPen); 0336 painter.drawText(QPointF(x-fontMetrics.width(numberText)/2.0, 0337 rectangle.bottom() -fullStepMarkerLength -measurementTextAboveBelowMargin), 0338 numberText); 0339 painter.setPen(markerPen); 0340 0341 ++stepCount; 0342 nextStep = qRound(d->viewConverter->documentToViewX( 0343 d->unit.fromUserValue(numberStep * stepCount))); 0344 ++halfStepCount; 0345 nextHalfStep = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue( 0346 numberStep * 0.5 * halfStepCount))); 0347 ++quarterStepCount; 0348 nextQuarterStep = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue( 0349 numberStep * 0.25 * quarterStepCount))); 0350 } 0351 else if(i == nextHalfStep) { 0352 if(pos != 0) 0353 painter.drawLine(QPointF(pos, rectangle.bottom()-1), 0354 QPointF(pos, rectangle.bottom() - halfStepMarkerLength)); 0355 0356 ++halfStepCount; 0357 nextHalfStep = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue( 0358 numberStep * 0.5 * halfStepCount))); 0359 ++quarterStepCount; 0360 nextQuarterStep = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue( 0361 numberStep * 0.25 * quarterStepCount))); 0362 } 0363 else if(i == nextQuarterStep) { 0364 if(pos != 0) 0365 painter.drawLine(QPointF(pos, rectangle.bottom()-1), 0366 QPointF(pos, rectangle.bottom() - quarterStepMarkerLength)); 0367 0368 ++quarterStepCount; 0369 nextQuarterStep = qRound(d->viewConverter->documentToViewX(d->unit.fromUserValue( 0370 numberStep * 0.25 * quarterStepCount))); 0371 } 0372 } 0373 0374 // Draw the mouse indicator 0375 const int mouseCoord = d->mouseCoordinate - start; 0376 if (d->selected == KoRulerPrivate::None || d->selected == KoRulerPrivate::HotSpot) { 0377 const qreal top = rectangle.y() + 1; 0378 const qreal bottom = rectangle.bottom() -1; 0379 if (d->selected == KoRulerPrivate::None && d->showMousePosition && mouseCoord > 0 && mouseCoord < rectangle.width() ) 0380 painter.drawLine(QPointF(mouseCoord, top), QPointF(mouseCoord, bottom)); 0381 foreach (const KoRulerPrivate::HotSpotData & hp, d->hotspots) { 0382 const qreal x = d->viewConverter->documentToViewX(hp.position) + d->offset; 0383 painter.drawLine(QPointF(x, top), QPointF(x, bottom)); 0384 } 0385 } 0386 } 0387 0388 void HorizontalPaintingStrategy::drawIndents(const KoRulerPrivate *d, QPainter &painter) 0389 { 0390 QPolygonF polygon; 0391 0392 painter.setBrush(d->ruler->palette().brush(QPalette::Base)); 0393 painter.setRenderHint( QPainter::Antialiasing ); 0394 0395 qreal x; 0396 // Draw first line start indent 0397 if (d->rightToLeft) 0398 x = d->effectiveActiveRangeEnd() - d->firstLineIndent - d->paragraphIndent; 0399 else 0400 x = d->effectiveActiveRangeStart() + d->firstLineIndent + d->paragraphIndent; 0401 // convert and use the +0.5 to go to nearest integer so that the 0.5 added below ensures sharp lines 0402 x = int(d->viewConverter->documentToViewX(x) + d->offset + 0.5); 0403 polygon << QPointF(x+6.5, 0.5) 0404 << QPointF(x+0.5, 8.5) 0405 << QPointF(x-5.5, 0.5) 0406 << QPointF(x+5.5, 0.5); 0407 painter.drawPolygon(polygon); 0408 0409 // draw the hanging indent. 0410 if (d->rightToLeft) 0411 x = d->effectiveActiveRangeStart() + d->endIndent; 0412 else 0413 x = d->effectiveActiveRangeStart() + d->paragraphIndent; 0414 // convert and use the +0.5 to go to nearest integer so that the 0.5 added below ensures sharp lines 0415 x = int(d->viewConverter->documentToViewX(x) + d->offset + 0.5); 0416 const int bottom = d->ruler->height(); 0417 polygon.clear(); 0418 polygon << QPointF(x+6.5, bottom - 0.5) 0419 << QPointF(x+0.5, bottom - 8.5) 0420 << QPointF(x-5.5, bottom - 0.5) 0421 << QPointF(x+5.5, bottom - 0.5); 0422 painter.drawPolygon(polygon); 0423 0424 // Draw end-indent or paragraph indent if mode is rightToLeft 0425 qreal diff; 0426 if (d->rightToLeft) 0427 diff = d->viewConverter->documentToViewX(d->effectiveActiveRangeEnd() 0428 - d->paragraphIndent) + d->offset - x; 0429 else 0430 diff = d->viewConverter->documentToViewX(d->effectiveActiveRangeEnd() - d->endIndent) 0431 + d->offset - x; 0432 polygon.translate(diff, 0); 0433 painter.drawPolygon(polygon); 0434 } 0435 0436 QSize HorizontalPaintingStrategy::sizeHint() 0437 { 0438 // assumes that digits for the number only use glyphs which do not go below the baseline 0439 const QFontMetrics fm(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0440 const int digitsHeight = fm.ascent() + 1; // +1 for baseline 0441 const int minimum = digitsHeight + fullStepMarkerLength + 2*measurementTextAboveBelowMargin; 0442 0443 return QSize(0, minimum); 0444 } 0445 0446 QRectF VerticalPaintingStrategy::drawBackground(const KoRulerPrivate *d, QPainter &painter) 0447 { 0448 lengthInPixel = d->viewConverter->documentToViewY(d->rulerLength); 0449 QRectF rectangle; 0450 rectangle.setX(0); 0451 rectangle.setY(qMax(0, d->offset)); 0452 rectangle.setWidth(d->ruler->width() - 1.0); 0453 rectangle.setHeight(qMin(qreal(d->ruler->height() - 1.0 - rectangle.y()), 0454 (d->offset >= 0) ? lengthInPixel : lengthInPixel + d->offset)); 0455 0456 QRectF activeRangeRectangle; 0457 activeRangeRectangle.setX(rectangle.x() + 1); 0458 activeRangeRectangle.setY(qMax(rectangle.y() + 1, 0459 d->viewConverter->documentToViewY(d->effectiveActiveRangeStart()) + d->offset)); 0460 activeRangeRectangle.setWidth(rectangle.width() - 2); 0461 activeRangeRectangle.setBottom(qMin(rectangle.bottom() - 1, 0462 d->viewConverter->documentToViewY(d->effectiveActiveRangeEnd()) + d->offset)); 0463 0464 painter.setPen(QPen(d->ruler->palette().color(QPalette::Mid), 0)); 0465 0466 painter.fillRect(rectangle,d->ruler->palette().color(QPalette::AlternateBase)); 0467 painter.drawRect(rectangle); 0468 0469 if(d->effectiveActiveRangeStart() != d->effectiveActiveRangeEnd()) 0470 painter.fillRect(activeRangeRectangle, d->ruler->palette().brush(QPalette::Base)); 0471 0472 if(d->showSelectionBorders) { 0473 // Draw first selection border 0474 if(d->firstSelectionBorder > 0) { 0475 qreal border = d->viewConverter->documentToViewY(d->firstSelectionBorder) + d->offset; 0476 painter.drawLine(QPointF(rectangle.x() + 1, border), QPointF(rectangle.right() - 1, border)); 0477 } 0478 // Draw second selection border 0479 if(d->secondSelectionBorder > 0) { 0480 qreal border = d->viewConverter->documentToViewY(d->secondSelectionBorder) + d->offset; 0481 painter.drawLine(QPointF(rectangle.x() + 1, border), QPointF(rectangle.right() - 1, border)); 0482 } 0483 } 0484 0485 return rectangle; 0486 } 0487 0488 void VerticalPaintingStrategy::drawMeasurements(const KoRulerPrivate *d, QPainter &painter, const QRectF &rectangle) 0489 { 0490 qreal numberStep = d->numberStepForUnit(); // number step in unit 0491 int numberStepPixel = qRound(d->viewConverter->documentToViewY( d->unit.fromUserValue(numberStep))); 0492 if (numberStepPixel <= 0) 0493 return; 0494 0495 const QFont font = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); 0496 const QFontMetrics fontMetrics(font); 0497 painter.setFont(font); 0498 0499 // Calc the longest text length 0500 int textLength = 0; 0501 0502 for(int i = 0; i < lengthInPixel; i += numberStepPixel) { 0503 int number = qRound((i / numberStepPixel) * numberStep); 0504 textLength = qMax(textLength, fontMetrics.width(QString::number(number))); 0505 } 0506 textLength += 4; // Add some padding 0507 0508 if (numberStepPixel == 0 || numberStep == 0) 0509 return; 0510 // Change number step so all digits will fit 0511 while(textLength > numberStepPixel) { 0512 numberStepPixel += numberStepPixel; 0513 numberStep += numberStep; 0514 } 0515 0516 // Calc the first number step 0517 const int start = d->offset < 0 ? qAbs(d->offset) : 0; 0518 0519 // make a little hack so rulers shows correctly inversed number aligned 0520 int stepCount = (start / numberStepPixel) + 1; 0521 int halfStepCount = (start / qRound(numberStepPixel * 0.5)) + 1; 0522 int quarterStepCount = (start / qRound(numberStepPixel * 0.25)) + 1; 0523 0524 const QPen numberPen(d->ruler->palette().color(QPalette::Text), 0); 0525 const QPen markerPen(d->ruler->palette().color(QPalette::Inactive, QPalette::Text), 0); 0526 painter.setPen(markerPen); 0527 0528 if(d->offset > 0) 0529 painter.translate(0, d->offset); 0530 0531 const int len = qRound(rectangle.height()) + start; 0532 int nextStep = qRound(d->viewConverter->documentToViewY( 0533 d->unit.fromUserValue(numberStep * stepCount))); 0534 int nextHalfStep = qRound(d->viewConverter->documentToViewY(d->unit.fromUserValue( 0535 numberStep * 0.5 * halfStepCount))); 0536 int nextQuarterStep = qRound(d->viewConverter->documentToViewY(d->unit.fromUserValue( 0537 numberStep * 0.25 * quarterStepCount))); 0538 0539 int pos = 0; 0540 for(int i = start; i < len; ++i) { 0541 pos = i - start; 0542 0543 if(i == nextStep) { 0544 painter.save(); 0545 painter.translate(rectangle.right()-fullStepMarkerLength, pos); 0546 if(pos != 0) 0547 painter.drawLine(QPointF(0, 0), QPointF(fullStepMarkerLength-1, 0)); 0548 0549 painter.rotate(-90); 0550 int number = qRound(stepCount * numberStep); 0551 QString numberText = QString::number(number); 0552 painter.setPen(numberPen); 0553 painter.drawText(QPointF(-fontMetrics.width(numberText) / 2.0, -measurementTextAboveBelowMargin), numberText); 0554 painter.restore(); 0555 0556 ++stepCount; 0557 nextStep = qRound(d->viewConverter->documentToViewY( 0558 d->unit.fromUserValue(numberStep * stepCount))); 0559 ++halfStepCount; 0560 nextHalfStep = qRound(d->viewConverter->documentToViewY(d->unit.fromUserValue( 0561 numberStep * 0.5 * halfStepCount))); 0562 ++quarterStepCount; 0563 nextQuarterStep = qRound(d->viewConverter->documentToViewY(d->unit.fromUserValue( 0564 numberStep * 0.25 * quarterStepCount))); 0565 } else if(i == nextHalfStep) { 0566 if(pos != 0) 0567 painter.drawLine(QPointF(rectangle.right() - halfStepMarkerLength, pos), 0568 QPointF(rectangle.right() - 1, pos)); 0569 0570 ++halfStepCount; 0571 nextHalfStep = qRound(d->viewConverter->documentToViewY(d->unit.fromUserValue( 0572 numberStep * 0.5 * halfStepCount))); 0573 ++quarterStepCount; 0574 nextQuarterStep = qRound(d->viewConverter->documentToViewY(d->unit.fromUserValue( 0575 numberStep * 0.25 * quarterStepCount))); 0576 } else if(i == nextQuarterStep) { 0577 if(pos != 0) 0578 painter.drawLine(QPointF(rectangle.right() - quarterStepMarkerLength, pos), 0579 QPointF(rectangle.right() - 1, pos)); 0580 0581 ++quarterStepCount; 0582 nextQuarterStep = qRound(d->viewConverter->documentToViewY(d->unit.fromUserValue( 0583 numberStep * 0.25 * quarterStepCount))); 0584 } 0585 } 0586 0587 // Draw the mouse indicator 0588 const int mouseCoord = d->mouseCoordinate - start; 0589 if (d->selected == KoRulerPrivate::None || d->selected == KoRulerPrivate::HotSpot) { 0590 const qreal left = rectangle.left() + 1; 0591 const qreal right = rectangle.right() -1; 0592 if (d->selected == KoRulerPrivate::None && d->showMousePosition && mouseCoord > 0 && mouseCoord < rectangle.height() ) 0593 painter.drawLine(QPointF(left, mouseCoord), QPointF(right, mouseCoord)); 0594 foreach (const KoRulerPrivate::HotSpotData & hp, d->hotspots) { 0595 const qreal y = d->viewConverter->documentToViewY(hp.position) + d->offset; 0596 painter.drawLine(QPointF(left, y), QPointF(right, y)); 0597 } 0598 } 0599 } 0600 0601 QSize VerticalPaintingStrategy::sizeHint() 0602 { 0603 // assumes that digits for the number only use glyphs which do not go below the baseline 0604 const QFontMetrics fm(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0605 const int digitsHeight = fm.ascent() + 1; // +1 for baseline 0606 const int minimum = digitsHeight + fullStepMarkerLength + 2*measurementTextAboveBelowMargin; 0607 0608 return QSize(minimum, 0); 0609 } 0610 0611 0612 void HorizontalDistancesPaintingStrategy::drawDistanceLine(const KoRulerPrivate *d, QPainter &painter, const qreal start, const qreal end) 0613 { 0614 0615 // Don't draw too short lines 0616 if (qMax(start, end) - qMin(start, end) < 1) 0617 return; 0618 0619 painter.save(); 0620 painter.translate(d->offset, d->ruler->height() / 2); 0621 painter.setPen(QPen(d->ruler->palette().color(QPalette::Text), 0)); 0622 painter.setBrush(d->ruler->palette().color(QPalette::Text)); 0623 0624 QLineF line(QPointF(d->viewConverter->documentToViewX(start), 0), 0625 QPointF(d->viewConverter->documentToViewX(end), 0)); 0626 QPointF midPoint = line.pointAt(0.5); 0627 0628 // Draw the label text 0629 const QFont font = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); 0630 const QFontMetrics fontMetrics(font); 0631 QString label = d->unit.toUserStringValue( 0632 d->viewConverter->viewToDocumentX(line.length())) + ' ' + d->unit.symbol(); 0633 QPointF labelPosition = QPointF(midPoint.x() - fontMetrics.width(label)/2, 0634 midPoint.y() + fontMetrics.ascent()/2); 0635 painter.setFont(font); 0636 painter.drawText(labelPosition, label); 0637 0638 // Draw the arrow lines 0639 qreal arrowLength = (line.length() - fontMetrics.width(label)) / 2 - 2; 0640 arrowLength = qMax(qreal(0.0), arrowLength); 0641 QLineF startArrow(line.p1(), line.pointAt(arrowLength / line.length())); 0642 QLineF endArrow(line.p2(), line.pointAt(1.0 - arrowLength / line.length())); 0643 painter.drawLine(startArrow); 0644 painter.drawLine(endArrow); 0645 0646 // Draw the arrow heads 0647 QPolygonF arrowHead; 0648 arrowHead << line.p1() << QPointF(line.x1()+3, line.y1()-3) 0649 << QPointF(line.x1()+3, line.y1()+3); 0650 painter.drawPolygon(arrowHead); 0651 arrowHead.clear(); 0652 arrowHead << line.p2() << QPointF(line.x2()-3, line.y2()-3) 0653 << QPointF(line.x2()-3, line.y2()+3); 0654 painter.drawPolygon(arrowHead); 0655 0656 painter.restore(); 0657 } 0658 0659 void HorizontalDistancesPaintingStrategy::drawMeasurements(const KoRulerPrivate *d, QPainter &painter, const QRectF&) 0660 { 0661 QList<qreal> points; 0662 points << 0.0; 0663 points << d->effectiveActiveRangeStart() + d->paragraphIndent + d->firstLineIndent; 0664 points << d->effectiveActiveRangeStart() + d->paragraphIndent; 0665 points << d->effectiveActiveRangeEnd() - d->endIndent; 0666 points << d->effectiveActiveRangeStart(); 0667 points << d->effectiveActiveRangeEnd(); 0668 points << d->rulerLength; 0669 std::sort(points.begin(), points.end()); 0670 QListIterator<qreal> i(points); 0671 i.next(); 0672 while (i.hasNext() && i.hasPrevious()) { 0673 drawDistanceLine(d, painter, i.peekPrevious(), i.peekNext()); 0674 i.next(); 0675 } 0676 } 0677 0678 KoRulerPrivate::KoRulerPrivate(KoRuler *parent, const KoViewConverter *vc, Qt::Orientation o) 0679 : unit(KoUnit(KoUnit::Point)), 0680 orientation(o), 0681 viewConverter(vc), 0682 offset(0), 0683 rulerLength(0), 0684 activeRangeStart(0), 0685 activeRangeEnd(0), 0686 activeOverrideRangeStart(0), 0687 activeOverrideRangeEnd(0), 0688 mouseCoordinate(-1), 0689 showMousePosition(0), 0690 showSelectionBorders(false), 0691 firstSelectionBorder(0), 0692 secondSelectionBorder(0), 0693 showIndents(false), 0694 firstLineIndent(0), 0695 paragraphIndent(0), 0696 endIndent(0), 0697 showTabs(false), 0698 relativeTabs(false), 0699 tabMoved(false), 0700 originalIndex(-1), 0701 currentIndex(0), 0702 rightToLeft(false), 0703 selected(None), 0704 selectOffset(0), 0705 tabChooser(0), 0706 normalPaintingStrategy(o == Qt::Horizontal ? 0707 (PaintingStrategy*)new HorizontalPaintingStrategy() : (PaintingStrategy*)new VerticalPaintingStrategy()), 0708 distancesPaintingStrategy((PaintingStrategy*)new HorizontalDistancesPaintingStrategy()), 0709 paintingStrategy(normalPaintingStrategy), 0710 ruler(parent) 0711 { 0712 } 0713 0714 KoRulerPrivate::~KoRulerPrivate() 0715 { 0716 delete normalPaintingStrategy; 0717 delete distancesPaintingStrategy; 0718 } 0719 0720 qreal KoRulerPrivate::numberStepForUnit() const 0721 { 0722 switch(unit.type()) { 0723 case KoUnit::Inch: 0724 case KoUnit::Centimeter: 0725 case KoUnit::Decimeter: 0726 case KoUnit::Millimeter: 0727 return 1.0; 0728 case KoUnit::Pica: 0729 case KoUnit::Cicero: 0730 return 10.0; 0731 case KoUnit::Point: 0732 default: 0733 return 100.0; 0734 } 0735 } 0736 0737 qreal KoRulerPrivate::doSnapping(const qreal value) const 0738 { 0739 qreal numberStep = unit.fromUserValue(numberStepForUnit()/4.0); 0740 return numberStep * qRound(value / numberStep); 0741 } 0742 0743 KoRulerPrivate::Selection KoRulerPrivate::selectionAtPosition(const QPoint & pos, int *selectOffset ) 0744 { 0745 const int height = ruler->height(); 0746 if (rightToLeft) { 0747 int x = int(viewConverter->documentToViewX(effectiveActiveRangeEnd() - firstLineIndent - paragraphIndent) + offset); 0748 if (pos.x() >= x - 8 && pos.x() <= x +8 && pos.y() < height / 2) { 0749 if (selectOffset) 0750 *selectOffset = x - pos.x(); 0751 return KoRulerPrivate::FirstLineIndent; 0752 } 0753 0754 x = int(viewConverter->documentToViewX(effectiveActiveRangeEnd() - paragraphIndent) + offset); 0755 if (pos.x() >= x - 8 && pos.x() <= x +8 && pos.y() > height / 2) { 0756 if (selectOffset) 0757 *selectOffset = x - pos.x(); 0758 return KoRulerPrivate::ParagraphIndent; 0759 } 0760 0761 x = int(viewConverter->documentToViewX(effectiveActiveRangeStart() + endIndent) + offset); 0762 if (pos.x() >= x - 8 && pos.x() <= x + 8) { 0763 if (selectOffset) 0764 *selectOffset = x - pos.x(); 0765 return KoRulerPrivate::EndIndent; 0766 } 0767 } 0768 else { 0769 int x = int(viewConverter->documentToViewX(effectiveActiveRangeStart() + firstLineIndent + paragraphIndent) + offset); 0770 if (pos.x() >= x -8 && pos.x() <= x + 8 && pos.y() < height / 2) { 0771 if (selectOffset) 0772 *selectOffset = x - pos.x(); 0773 return KoRulerPrivate::FirstLineIndent; 0774 } 0775 0776 x = int(viewConverter->documentToViewX(effectiveActiveRangeStart() + paragraphIndent) + offset); 0777 if (pos.x() >= x - 8 && pos.x() <= x + 8 && pos.y() > height/2) { 0778 if (selectOffset) 0779 *selectOffset = x - pos.x(); 0780 return KoRulerPrivate::ParagraphIndent; 0781 } 0782 0783 x = int(viewConverter->documentToViewX(effectiveActiveRangeEnd() - endIndent) + offset); 0784 if (pos.x() >= x - 8 && pos.x() <= x + 8) { 0785 if (selectOffset) 0786 *selectOffset = x - pos.x(); 0787 return KoRulerPrivate::EndIndent; 0788 } 0789 } 0790 0791 return KoRulerPrivate::None; 0792 } 0793 0794 int KoRulerPrivate::hotSpotIndex(const QPoint & pos) 0795 { 0796 for(int counter = 0; counter < hotspots.count(); counter++) { 0797 bool hit; 0798 if (orientation == Qt::Horizontal) 0799 hit = qAbs(viewConverter->documentToViewX(hotspots[counter].position) - pos.x() + offset) < 3; 0800 else 0801 hit = qAbs(viewConverter->documentToViewY(hotspots[counter].position) - pos.y() + offset) < 3; 0802 0803 if (hit) 0804 return counter; 0805 } 0806 return -1; 0807 } 0808 0809 qreal KoRulerPrivate::effectiveActiveRangeStart() const 0810 { 0811 if (activeOverrideRangeStart != activeOverrideRangeEnd) { 0812 return activeOverrideRangeStart; 0813 } else { 0814 return activeRangeStart; 0815 } 0816 } 0817 0818 qreal KoRulerPrivate::effectiveActiveRangeEnd() const 0819 { 0820 if (activeOverrideRangeStart != activeOverrideRangeEnd) { 0821 return activeOverrideRangeEnd; 0822 } else { 0823 return activeRangeEnd; 0824 } 0825 } 0826 0827 void KoRulerPrivate::emitTabChanged() 0828 { 0829 KoRuler::Tab tab; 0830 if (currentIndex >= 0) 0831 tab = tabs[currentIndex]; 0832 emit ruler->tabChanged(originalIndex, currentIndex >= 0 ? &tab : 0); 0833 } 0834 0835 0836 KoRuler::KoRuler(QWidget* parent, Qt::Orientation orientation, const KoViewConverter* viewConverter) 0837 : QWidget(parent) 0838 , d( new KoRulerPrivate( this, viewConverter, orientation) ) 0839 { 0840 setMouseTracking( true ); 0841 } 0842 0843 KoRuler::~KoRuler() 0844 { 0845 delete d; 0846 } 0847 0848 KoUnit KoRuler::unit() const 0849 { 0850 return d->unit; 0851 } 0852 0853 void KoRuler::setUnit(const KoUnit &unit) 0854 { 0855 d->unit = unit; 0856 update(); 0857 } 0858 0859 qreal KoRuler::rulerLength() const 0860 { 0861 return d->rulerLength; 0862 } 0863 0864 Qt::Orientation KoRuler::orientation() const 0865 { 0866 return d->orientation; 0867 } 0868 0869 void KoRuler::setOffset(int offset) 0870 { 0871 d->offset = offset; 0872 update(); 0873 } 0874 0875 void KoRuler::setRulerLength(qreal length) 0876 { 0877 d->rulerLength = length; 0878 update(); 0879 } 0880 0881 void KoRuler::paintEvent(QPaintEvent* event) 0882 { 0883 QPainter painter(this); 0884 painter.setClipRegion(event->region()); 0885 painter.save(); 0886 QRectF rectangle = d->paintingStrategy->drawBackground(d, painter); 0887 painter.restore(); 0888 painter.save(); 0889 d->paintingStrategy->drawMeasurements(d, painter, rectangle); 0890 painter.restore(); 0891 if (d->showIndents) { 0892 painter.save(); 0893 d->paintingStrategy->drawIndents(d, painter); 0894 painter.restore(); 0895 } 0896 d->paintingStrategy->drawTabs(d, painter); 0897 } 0898 0899 QSize KoRuler::minimumSizeHint() const 0900 { 0901 return d->paintingStrategy->sizeHint(); 0902 } 0903 0904 QSize KoRuler::sizeHint() const 0905 { 0906 return d->paintingStrategy->sizeHint(); 0907 } 0908 0909 void KoRuler::setActiveRange(qreal start, qreal end) 0910 { 0911 d->activeRangeStart = start; 0912 d->activeRangeEnd = end; 0913 update(); 0914 } 0915 0916 void KoRuler::setOverrideActiveRange(qreal start, qreal end) 0917 { 0918 d->activeOverrideRangeStart = start; 0919 d->activeOverrideRangeEnd = end; 0920 update(); 0921 } 0922 0923 void KoRuler::updateMouseCoordinate(int coordinate) 0924 { 0925 if(d->mouseCoordinate == coordinate) 0926 return; 0927 d->mouseCoordinate = coordinate; 0928 update(); 0929 } 0930 0931 void KoRuler::setShowMousePosition(bool show) 0932 { 0933 d->showMousePosition = show; 0934 update(); 0935 } 0936 0937 void KoRuler::setRightToLeft(bool isRightToLeft) 0938 { 0939 d->rightToLeft = isRightToLeft; 0940 update(); 0941 } 0942 0943 void KoRuler::setShowIndents(bool show) 0944 { 0945 d->showIndents = show; 0946 update(); 0947 } 0948 0949 void KoRuler::setFirstLineIndent(qreal indent) 0950 { 0951 d->firstLineIndent = indent; 0952 if (d->showIndents) { 0953 update(); 0954 } 0955 } 0956 0957 void KoRuler::setParagraphIndent(qreal indent) 0958 { 0959 d->paragraphIndent = indent; 0960 if (d->showIndents) { 0961 update(); 0962 } 0963 } 0964 0965 void KoRuler::setEndIndent(qreal indent) 0966 { 0967 d->endIndent = indent; 0968 if (d->showIndents) { 0969 update(); 0970 } 0971 } 0972 0973 qreal KoRuler::firstLineIndent() const 0974 { 0975 return d->firstLineIndent; 0976 } 0977 0978 qreal KoRuler::paragraphIndent() const 0979 { 0980 return d->paragraphIndent; 0981 } 0982 0983 qreal KoRuler::endIndent() const 0984 { 0985 return d->endIndent; 0986 } 0987 0988 QWidget *KoRuler::tabChooser() 0989 { 0990 if ((d->tabChooser == 0) && (d->orientation == Qt::Horizontal)) { 0991 d->tabChooser = new RulerTabChooser(parentWidget()); 0992 d->tabChooser->setShowTabs(d->showTabs); 0993 } 0994 0995 return d->tabChooser; 0996 } 0997 0998 void KoRuler::setShowSelectionBorders(bool show) 0999 { 1000 d->showSelectionBorders = show; 1001 update(); 1002 } 1003 1004 void KoRuler::updateSelectionBorders(qreal first, qreal second) 1005 { 1006 d->firstSelectionBorder = first; 1007 d->secondSelectionBorder = second; 1008 1009 if(d->showSelectionBorders) 1010 update(); 1011 } 1012 1013 void KoRuler::setShowTabs(bool show) 1014 { 1015 if (d->showTabs == show) { 1016 return; 1017 } 1018 1019 d->showTabs = show; 1020 if (d->tabChooser) { 1021 d->tabChooser->setShowTabs(show); 1022 } 1023 update(); 1024 } 1025 1026 void KoRuler::setRelativeTabs(bool relative) 1027 { 1028 d->relativeTabs = relative; 1029 if (d->showTabs) { 1030 update(); 1031 } 1032 } 1033 1034 void KoRuler::updateTabs(const QList<KoRuler::Tab> &tabs, qreal tabDistance) 1035 { 1036 d->tabs = tabs; 1037 d->tabDistance = tabDistance; 1038 if (d->showTabs) { 1039 update(); 1040 } 1041 } 1042 1043 QList<KoRuler::Tab> KoRuler::tabs() const 1044 { 1045 QList<Tab> answer = d->tabs; 1046 std::sort(answer.begin(), answer.end(), compareTabs); 1047 1048 return answer; 1049 } 1050 1051 void KoRuler::setPopupActionList(const QList<QAction*> &popupActionList) 1052 { 1053 d->popupActions = popupActionList; 1054 } 1055 1056 QList<QAction*> KoRuler::popupActionList() const 1057 { 1058 return d->popupActions; 1059 } 1060 1061 void KoRuler::mousePressEvent ( QMouseEvent* ev ) 1062 { 1063 d->tabMoved = false; 1064 d->selected = KoRulerPrivate::None; 1065 if (ev->button() == Qt::RightButton && !d->popupActions.isEmpty()) 1066 QMenu::exec(d->popupActions, ev->globalPos()); 1067 if (ev->button() != Qt::LeftButton) { 1068 ev->ignore(); 1069 return; 1070 } 1071 1072 QPoint pos = ev->pos(); 1073 1074 if (d->showTabs) { 1075 int i = 0; 1076 int x; 1077 foreach (const Tab & t, d->tabs) { 1078 if (d->rightToLeft) { 1079 x = d->viewConverter->documentToViewX(d->effectiveActiveRangeEnd() 1080 - (d->relativeTabs ? d->paragraphIndent : 0) - t.position) + d->offset; 1081 } else { 1082 x = d->viewConverter->documentToViewX(d->effectiveActiveRangeStart() 1083 + (d->relativeTabs ? d->paragraphIndent : 0) + t.position) + d->offset; 1084 } 1085 if (pos.x() >= x-6 && pos.x() <= x+6) { 1086 d->selected = KoRulerPrivate::Tab; 1087 d->selectOffset = x - pos.x(); 1088 d->currentIndex = i; 1089 break; 1090 } 1091 i++; 1092 } 1093 d->originalIndex = d->currentIndex; 1094 } 1095 1096 if (d->selected == KoRulerPrivate::None) 1097 d->selected = d->selectionAtPosition(ev->pos(), &d->selectOffset); 1098 if (d->selected == KoRulerPrivate::None) { 1099 int hotSpotIndex = d->hotSpotIndex(ev->pos()); 1100 if (hotSpotIndex >= 0) { 1101 d->selected = KoRulerPrivate::HotSpot; 1102 update(); 1103 } 1104 } 1105 1106 if (d->showTabs && d->selected == KoRulerPrivate::None) { 1107 // still haven't found something so let assume the user wants to add a tab 1108 qreal tabpos; 1109 if (d->rightToLeft) { 1110 tabpos = d->viewConverter->viewToDocumentX(pos.x() - d->offset) 1111 + d->effectiveActiveRangeEnd() + (d->relativeTabs ? d->paragraphIndent : 0); 1112 } else { 1113 tabpos = d->viewConverter->viewToDocumentX(pos.x() - d->offset) 1114 - d->effectiveActiveRangeStart() - (d->relativeTabs ? d->paragraphIndent : 0); 1115 } 1116 Tab t = {tabpos, d->tabChooser ? d->tabChooser->type() : 1117 d->rightToLeft ? QTextOption::RightTab : 1118 QTextOption::LeftTab}; 1119 d->tabs.append(t); 1120 d->selectOffset = 0; 1121 d->selected = KoRulerPrivate::Tab; 1122 d->currentIndex = d->tabs.count() - 1; 1123 d->originalIndex = -1; // new! 1124 update(); 1125 } 1126 if (d->orientation == Qt::Horizontal && (ev->modifiers() & Qt::ShiftModifier) && 1127 (d->selected == KoRulerPrivate::FirstLineIndent || 1128 d->selected == KoRulerPrivate::ParagraphIndent || 1129 d->selected == KoRulerPrivate::Tab || 1130 d->selected == KoRulerPrivate::EndIndent)) 1131 d->paintingStrategy = d->distancesPaintingStrategy; 1132 1133 if (d->selected != KoRulerPrivate::None) 1134 emit aboutToChange(); 1135 } 1136 1137 void KoRuler::mouseReleaseEvent ( QMouseEvent* ev ) 1138 { 1139 ev->accept(); 1140 if (d->selected == KoRulerPrivate::Tab) { 1141 if (d->originalIndex >= 0 && !d->tabMoved) { 1142 int type = d->tabs[d->currentIndex].type; 1143 type++; 1144 if (type > 3) 1145 type = 0; 1146 d->tabs[d->currentIndex].type = static_cast<QTextOption::TabType> (type); 1147 update(); 1148 } 1149 d->emitTabChanged(); 1150 } 1151 else if( d->selected != KoRulerPrivate::None) 1152 emit indentsChanged(true); 1153 else 1154 ev->ignore(); 1155 1156 d->paintingStrategy = d->normalPaintingStrategy; 1157 d->selected = KoRulerPrivate::None; 1158 } 1159 1160 void KoRuler::mouseMoveEvent ( QMouseEvent* ev ) 1161 { 1162 QPoint pos = ev->pos(); 1163 1164 qreal activeLength = d->effectiveActiveRangeEnd() - d->effectiveActiveRangeStart(); 1165 1166 switch (d->selected) { 1167 case KoRulerPrivate::FirstLineIndent: 1168 if (d->rightToLeft) 1169 d->firstLineIndent = d->effectiveActiveRangeEnd() - d->paragraphIndent - 1170 d->viewConverter->viewToDocumentX(pos.x() + d->selectOffset - d->offset); 1171 else 1172 d->firstLineIndent = d->viewConverter->viewToDocumentX(pos.x() + d->selectOffset 1173 - d->offset) - d->effectiveActiveRangeStart() - d->paragraphIndent; 1174 if( ! (ev->modifiers() & Qt::ShiftModifier)) { 1175 d->firstLineIndent = d->doSnapping(d->firstLineIndent); 1176 d->paintingStrategy = d->normalPaintingStrategy; 1177 } else { 1178 if (d->orientation == Qt::Horizontal) 1179 d->paintingStrategy = d->distancesPaintingStrategy; 1180 } 1181 1182 emit indentsChanged(false); 1183 break; 1184 case KoRulerPrivate::ParagraphIndent: 1185 if (d->rightToLeft) 1186 d->paragraphIndent = d->effectiveActiveRangeEnd() - 1187 d->viewConverter->viewToDocumentX(pos.x() + d->selectOffset - d->offset); 1188 else 1189 d->paragraphIndent = d->viewConverter->viewToDocumentX(pos.x() + d->selectOffset 1190 - d->offset) - d->effectiveActiveRangeStart(); 1191 if( ! (ev->modifiers() & Qt::ShiftModifier)) { 1192 d->paragraphIndent = d->doSnapping(d->paragraphIndent); 1193 d->paintingStrategy = d->normalPaintingStrategy; 1194 } else { 1195 if (d->orientation == Qt::Horizontal) 1196 d->paintingStrategy = d->distancesPaintingStrategy; 1197 } 1198 1199 if (d->paragraphIndent + d->endIndent > activeLength) 1200 d->paragraphIndent = activeLength - d->endIndent; 1201 emit indentsChanged(false); 1202 break; 1203 case KoRulerPrivate::EndIndent: 1204 if (d->rightToLeft) 1205 d->endIndent = d->viewConverter->viewToDocumentX(pos.x() 1206 + d->selectOffset - d->offset) - d->effectiveActiveRangeStart(); 1207 else 1208 d->endIndent = d->effectiveActiveRangeEnd() - d->viewConverter->viewToDocumentX(pos.x() 1209 + d->selectOffset - d->offset); 1210 if (!(ev->modifiers() & Qt::ShiftModifier)) { 1211 d->endIndent = d->doSnapping(d->endIndent); 1212 d->paintingStrategy = d->normalPaintingStrategy; 1213 } else { 1214 if (d->orientation == Qt::Horizontal) 1215 d->paintingStrategy = d->distancesPaintingStrategy; 1216 } 1217 1218 if (d->paragraphIndent + d->endIndent > activeLength) 1219 d->endIndent = activeLength - d->paragraphIndent; 1220 emit indentsChanged(false); 1221 break; 1222 case KoRulerPrivate::Tab: 1223 d->tabMoved = true; 1224 if (d->currentIndex < 0) { // tab is deleted. 1225 if (ev->pos().y() < height()) { // reinstante it. 1226 d->currentIndex = d->tabs.count(); 1227 d->tabs.append(d->deletedTab); 1228 } else { 1229 break; 1230 } 1231 } 1232 if (d->rightToLeft) 1233 d->tabs[d->currentIndex].position = d->effectiveActiveRangeEnd() - 1234 d->viewConverter->viewToDocumentX(pos.x() + d->selectOffset - d->offset); 1235 else 1236 d->tabs[d->currentIndex].position = d->viewConverter->viewToDocumentX(pos.x() + d->selectOffset 1237 - d->offset) - d->effectiveActiveRangeStart(); 1238 if (!(ev->modifiers() & Qt::ShiftModifier)) 1239 d->tabs[d->currentIndex].position = d->doSnapping(d->tabs[d->currentIndex].position); 1240 if (d->tabs[d->currentIndex].position < 0) 1241 d->tabs[d->currentIndex].position = 0; 1242 if (d->tabs[d->currentIndex].position > activeLength) 1243 d->tabs[d->currentIndex].position = activeLength; 1244 1245 if (ev->pos().y() > height() + OutsideRulerThreshold ) { // moved out of the ruler, delete it. 1246 d->deletedTab = d->tabs.takeAt(d->currentIndex); 1247 d->currentIndex = -1; 1248 // was that a temporary added tab? 1249 if ( d->originalIndex == -1 ) 1250 emit guideLineCreated(d->orientation, 1251 d->orientation == Qt::Horizontal 1252 ? d->viewConverter->viewToDocumentY(ev->pos().y()) 1253 : d->viewConverter->viewToDocumentX(ev->pos().x())); 1254 } 1255 1256 d->emitTabChanged(); 1257 break; 1258 case KoRulerPrivate::HotSpot: 1259 qreal newPos; 1260 if (d->orientation == Qt::Horizontal) 1261 newPos= d->viewConverter->viewToDocumentX(pos.x() - d->offset); 1262 else 1263 newPos= d->viewConverter->viewToDocumentY(pos.y() - d->offset); 1264 d->hotspots[d->currentIndex].position = newPos; 1265 emit hotSpotChanged(d->hotspots[d->currentIndex].id, newPos); 1266 break; 1267 case KoRulerPrivate::None: 1268 d->mouseCoordinate = (d->orientation == Qt::Horizontal ? pos.x() : pos.y()) - d->offset; 1269 int hotSpotIndex = d->hotSpotIndex(pos); 1270 if (hotSpotIndex >= 0) { 1271 setCursor(QCursor( d->orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor )); 1272 break; 1273 } 1274 unsetCursor(); 1275 1276 KoRulerPrivate::Selection selection = d->selectionAtPosition(pos); 1277 QString text; 1278 switch(selection) { 1279 case KoRulerPrivate::FirstLineIndent: text = i18n("First line indent"); break; 1280 case KoRulerPrivate::ParagraphIndent: text = i18n("Left indent"); break; 1281 case KoRulerPrivate::EndIndent: text = i18n("Right indent"); break; 1282 case KoRulerPrivate::None: 1283 if (ev->buttons() & Qt::LeftButton) { 1284 if (d->orientation == Qt::Horizontal && ev->pos().y() > height() + OutsideRulerThreshold) 1285 emit guideLineCreated(d->orientation, d->viewConverter->viewToDocumentY(ev->pos().y())); 1286 else if (d->orientation == Qt::Vertical && ev->pos().x() > width() + OutsideRulerThreshold) 1287 emit guideLineCreated(d->orientation, d->viewConverter->viewToDocumentX(ev->pos().x())); 1288 } 1289 break; 1290 default: 1291 break; 1292 } 1293 setToolTip(text); 1294 } 1295 update(); 1296 } 1297 1298 void KoRuler::clearHotSpots() 1299 { 1300 if (d->hotspots.isEmpty()) 1301 return; 1302 d->hotspots.clear(); 1303 update(); 1304 } 1305 1306 void KoRuler::setHotSpot(qreal position, int id) 1307 { 1308 uint hotspotCount = d->hotspots.count(); 1309 for( uint i = 0; i < hotspotCount; ++i ) { 1310 KoRulerPrivate::HotSpotData & hs = d->hotspots[i]; 1311 if (hs.id == id) { 1312 hs.position = position; 1313 update(); 1314 return; 1315 } 1316 } 1317 // not there yet, then insert it. 1318 KoRulerPrivate::HotSpotData hs; 1319 hs.position = position; 1320 hs.id = id; 1321 d->hotspots.append(hs); 1322 } 1323 1324 bool KoRuler::removeHotSpot(int id) 1325 { 1326 QList<KoRulerPrivate::HotSpotData>::Iterator iter = d->hotspots.begin(); 1327 while(iter != d->hotspots.end()) { 1328 if (iter->id == id) { 1329 d->hotspots.erase(iter); 1330 update(); 1331 return true; 1332 } 1333 } 1334 return false; 1335 } 1336 1337 void KoRuler::createGuideToolConnection(KoCanvasBase *canvas) 1338 { 1339 Q_ASSERT(canvas); 1340 KoToolBase *tool = KoToolManager::instance()->toolById(canvas, QLatin1String("GuidesTool_ID")); 1341 if (!tool) return; // It's perfectly fine to have no guides tool, we don't have to warn the user about it 1342 connect(this, SIGNAL(guideLineCreated(Qt::Orientation,qreal)), 1343 tool, SLOT(createGuideLine(Qt::Orientation,qreal))); 1344 }