File indexing completed on 2024-05-12 16:36:10

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 "SelectionStrategy.h"
0021 
0022 #include "CellEditor.h"
0023 #include "CellToolBase.h"
0024 #include "calligra_sheets_limits.h"
0025 #include "Selection.h"
0026 #include "Sheet.h"
0027 
0028 #include <KoCanvasBase.h>
0029 #include <KoSelection.h>
0030 #include <KoShapeManager.h>
0031 
0032 using namespace Calligra::Sheets;
0033 
0034 class Q_DECL_HIDDEN SelectionStrategy::Private
0035 {
0036 public:
0037     Cell startCell;
0038 };
0039 
0040 SelectionStrategy::SelectionStrategy(CellToolBase *cellTool,
0041                                      const QPointF &documentPos, Qt::KeyboardModifiers modifiers)
0042         : AbstractSelectionStrategy(cellTool, documentPos, modifiers)
0043         , d(new Private)
0044 {
0045     d->startCell = Cell();
0046 
0047     const QPointF position = documentPos;
0048     Sheet *const sheet = this->selection()->activeSheet();
0049     Selection *const selection = this->selection();
0050 
0051 #if 0 // CALLIGRA_SHEETS_WIP_DRAG_REFERENCE_SELECTION
0052     // Check, if the selected area was hit.
0053     bool hitSelection = false;
0054     const Region::ConstIterator end(selection->constEnd());
0055     for (Region::ConstIterator it(selection->constBegin()); it != end; ++it) {
0056         // Only process ranges on the active sheet.
0057         if (sheet != (*it)->sheet()) {
0058             continue;
0059         }
0060         const QRect range = (*it)->rect();
0061         if (sheet->cellCoordinatesToDocument(range).contains(position)) {
0062             hitSelection = true;
0063             break;
0064         }
0065     }
0066 #endif // CALLIGRA_SHEETS_WIP_DRAG_REFERENCE_SELECTION
0067 
0068     // In which cell did the user click?
0069     qreal xpos;
0070     qreal ypos;
0071     const int col = sheet->leftColumn(position.x(), xpos);
0072     const int row = sheet->topRow(position.y(), ypos);
0073     // Check boundaries.
0074     if (col > KS_colMax || row > KS_rowMax) {
0075         debugSheetsUI << "col or row is out of range:" << "col:" << col << " row:" << row;
0076     } else {
0077         d->startCell = Cell(sheet, col, row);
0078         if (selection->referenceSelectionMode()) {
0079             selection->emitRequestFocusEditor();
0080             const bool sizeGripHit = hitTestReferenceSizeGrip(tool()->canvas(), selection, position);
0081             const bool shiftPressed = modifiers & Qt::ShiftModifier;
0082             if (sizeGripHit) {
0083                 // FIXME The size grip is partly located in the adjacent cells.
0084                 // Activate the selection's location/range.
0085                 const int index = selection->setActiveElement(d->startCell);
0086                 // If successful, activate the editor's location/range.
0087                 if (index >= 0 && cellTool->editor()) {
0088                     cellTool->editor()->setActiveSubRegion(index);
0089                 }
0090                 selection->update(QPoint(col, row));
0091             } else if (shiftPressed) {
0092                 selection->update(QPoint(col, row));
0093             } else if (modifiers & Qt::ControlModifier) {
0094                 // Extend selection, if control modifier is pressed.
0095                 selection->extend(QPoint(col, row), sheet);
0096 #if 0 // CALLIGRA_SHEETS_WIP_DRAG_REFERENCE_SELECTION
0097             } else if (hitSelection) {
0098                 // start cell is already set above
0099                 // No change; the range will be moved
0100 #endif // CALLIGRA_SHEETS_WIP_DRAG_REFERENCE_SELECTION
0101             } else {
0102                 selection->initialize(QPoint(col, row), sheet);
0103             }
0104         } else {
0105             selection->emitCloseEditor(true);
0106             if (modifiers & Qt::ControlModifier) {
0107                 // Extend selection, if control modifier is pressed.
0108                 selection->extend(QPoint(col, row), sheet);
0109             } else if (modifiers & Qt::ShiftModifier) {
0110                 selection->update(QPoint(col, row));
0111             } else {
0112                 selection->initialize(QPoint(col, row), sheet);
0113             }
0114         }
0115     }
0116     tool()->repaintDecorations();
0117 }
0118 
0119 SelectionStrategy::~SelectionStrategy()
0120 {
0121     delete d;
0122 }
0123 
0124 void SelectionStrategy::handleMouseMove(const QPointF &documentPos,
0125                                         Qt::KeyboardModifiers modifiers)
0126 {
0127 #if 0 // CALLIGRA_SHEETS_WIP_DRAG_REFERENCE_SELECTION
0128     Q_UNUSED(modifiers);
0129     //const KoShape* shape = tool()->canvas()->shapeManager()->selection()->firstSelectedShape();
0130     const QPointF position = documentPos /*- (shape ? shape->position() : QPointF(0.0, 0.0))*/;
0131     Sheet *const sheet = selection()->activeSheet();
0132 
0133     if (selection()->referenceSelectionMode()) {
0134         // In which cell did the user move?
0135         double xpos;
0136         double ypos;
0137         const int col = sheet->leftColumn(position.x(), xpos);
0138         const int row = sheet->topRow(position.y(), ypos);
0139         // Check boundaries.
0140         if (col > KS_colMax || row > KS_rowMax) {
0141             debugSheetsUI << "col or row is out of range:" << "col:" << col << " row:" << row;
0142         } else if (!(d->startCell == Cell(sheet, col, row))) {
0143             const QRect range = selection()->activeElement()->rect();
0144             const QPoint offset = d->startCell.cellPosition() - range.topLeft();
0145             const QPoint topLeft = QPoint(col, row) + offset;
0146             selection()->initialize(QRect(topLeft, range.size()), sheet);
0147             return;
0148         }
0149     }
0150 #endif // CALLIGRA_SHEETS_WIP_DRAG_REFERENCE_SELECTION
0151     AbstractSelectionStrategy::handleMouseMove(documentPos, modifiers);
0152 }