File indexing completed on 2024-05-12 16:36:01
0001 /* This file is part of the KDE project 0002 Copyright 2008 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "AbstractSelectionStrategy.h" 0021 0022 #include "CellToolBase.h" 0023 #include "calligra_sheets_limits.h" 0024 #include "RowColumnFormat.h" 0025 #include "RowFormatStorage.h" 0026 #include "Selection.h" 0027 #include "Sheet.h" 0028 0029 #include <KoCanvasBase.h> 0030 #include <KoSelection.h> 0031 #include <KoShapeManager.h> 0032 #include <KoViewConverter.h> 0033 0034 using namespace Calligra::Sheets; 0035 0036 class AbstractSelectionStrategy::Private 0037 { 0038 public: 0039 CellToolBase *cellTool; 0040 QPointF start; 0041 }; 0042 0043 AbstractSelectionStrategy::AbstractSelectionStrategy(CellToolBase *cellTool, 0044 const QPointF &documentPos, Qt::KeyboardModifiers modifiers) 0045 : KoInteractionStrategy(cellTool) 0046 , d(new Private) 0047 { 0048 Q_UNUSED(modifiers) 0049 d->cellTool = cellTool; 0050 d->start = documentPos; 0051 } 0052 0053 AbstractSelectionStrategy::~AbstractSelectionStrategy() 0054 { 0055 delete d; 0056 } 0057 0058 void AbstractSelectionStrategy::handleMouseMove(const QPointF& documentPos, Qt::KeyboardModifiers modifiers) 0059 { 0060 Q_UNUSED(modifiers) 0061 Selection *const selection = d->cellTool->selection(); 0062 const QPointF position = documentPos - cellTool()->offset(); 0063 // In which cell did the user click? 0064 qreal xpos; 0065 qreal ypos; 0066 int col = selection->activeSheet()->leftColumn(position.x(), xpos); 0067 int row = selection->activeSheet()->topRow(position.y(), ypos); 0068 // Check boundaries. 0069 if (col < 1 || col > KS_colMax || row < 1 || row > KS_rowMax) { 0070 debugSheetsUI << "col or row is out of range:" << "col:" << col << " row:" << row; 0071 return; 0072 } 0073 // Test whether mouse is over the Selection.handle 0074 if (hitTestSelectionSizeGrip(tool()->canvas(), selection, position)) { 0075 // If the cursor is over the handle, than it might be already on the next cell. 0076 // Recalculate the cell position! 0077 col = selection->activeSheet()->leftColumn(position.x() - tool()->canvas()->viewConverter()->viewToDocumentX(2.0), xpos); 0078 row = selection->activeSheet()->topRow(position.y() - tool()->canvas()->viewConverter()->viewToDocumentY(2.0), ypos); 0079 } 0080 // Update the selection. 0081 selection->update(QPoint(col, row)); 0082 tool()->repaintDecorations(); 0083 } 0084 0085 KUndo2Command* AbstractSelectionStrategy::createCommand() 0086 { 0087 return 0; 0088 } 0089 0090 void AbstractSelectionStrategy::finishInteraction(Qt::KeyboardModifiers modifiers) 0091 { 0092 Q_UNUSED(modifiers) 0093 tool()->repaintDecorations(); 0094 } 0095 0096 // static 0097 bool AbstractSelectionStrategy::hitTestSelectionSizeGrip(KoCanvasBase *canvas, 0098 Selection *selection, 0099 const QPointF &position) 0100 { 0101 if (selection->referenceSelectionMode() || !selection->isValid()) { 0102 return false; 0103 } 0104 0105 // Define the (normal) selection size grip. 0106 const qreal pixelX = canvas->viewConverter()->viewToDocumentX(1); 0107 const qreal pixelY = canvas->viewConverter()->viewToDocumentY(1); 0108 const QRectF gripArea(-2 * pixelX, -2 * pixelY, 5 * pixelX, 5 * pixelY); 0109 0110 Sheet *const sheet = selection->activeSheet(); 0111 0112 int column, row; 0113 if (selection->isColumnOrRowSelected()) { 0114 // complete rows/columns are selected, use the marker. 0115 const QPoint marker = selection->marker(); 0116 column = marker.x(); 0117 row = marker.y(); 0118 } else { 0119 const QRect range = selection->lastRange(); 0120 column = range.right(); 0121 row = range.bottom(); 0122 } 0123 0124 const double xpos = sheet->columnPosition(column); 0125 const double ypos = sheet->rowPosition(row); 0126 const double width = sheet->columnFormat(column)->width(); 0127 const double height = sheet->rowFormats()->rowHeight(row); 0128 return gripArea.translated(xpos + width, ypos + height).contains(position); 0129 } 0130 0131 // static 0132 bool AbstractSelectionStrategy::hitTestReferenceSizeGrip(KoCanvasBase *canvas, 0133 Selection *selection, 0134 const QPointF &position) 0135 { 0136 if (!selection->referenceSelectionMode() || !selection->isValid()) { 0137 return false; 0138 } 0139 0140 // Define the reference selection size grip. 0141 const qreal pixelX = canvas->viewConverter()->viewToDocumentX(1); 0142 const qreal pixelY = canvas->viewConverter()->viewToDocumentY(1); 0143 const QRectF gripArea(-3 * pixelX, -3 * pixelY, 6 * pixelX, 6 * pixelY); 0144 0145 // Iterate over the referenced ranges. 0146 const Region::ConstIterator end(selection->constEnd()); 0147 for (Region::ConstIterator it(selection->constBegin()); it != end; ++it) { 0148 Sheet *const sheet = (*it)->sheet(); 0149 // Only check the ranges on the active sheet. 0150 if (sheet != selection->activeSheet()) { 0151 continue; 0152 } 0153 const QRect range = (*it)->rect(); 0154 const QRectF area = sheet->cellCoordinatesToDocument(range); 0155 const QPointF corner(area.bottomRight()); 0156 if (gripArea.translated(corner).contains(position)) { 0157 return true; 0158 } 0159 } 0160 return false; 0161 } 0162 0163 CellToolBase *AbstractSelectionStrategy::cellTool() const 0164 { 0165 return d->cellTool; 0166 } 0167 0168 Selection* AbstractSelectionStrategy::selection() const 0169 { 0170 return d->cellTool->selection(); 0171 } 0172 0173 const QPointF& AbstractSelectionStrategy::startPosition() const 0174 { 0175 return d->start; 0176 }