File indexing completed on 2024-05-12 16:35:45
0001 /* This file is part of the KDE project 0002 Copyright 2006 Robert Knight <robertknight@gmail.com> 0003 Copyright 2006 Inge Wallin <inge@lysator.liu.se> 0004 Copyright 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0005 Copyright 1999-2002,2004 Laurent Montel <montel@kde.org> 0006 Copyright 2002-2005 Ariya Hidayat <ariya@kde.org> 0007 Copyright 1999-2004 David Faure <faure@kde.org> 0008 Copyright 2004-2005 Meni Livne <livne@kde.org> 0009 Copyright 2001-2003 Philipp Mueller <philipp.mueller@gmx.de> 0010 Copyright 2002-2003 Norbert Andres <nandres@web.de> 0011 Copyright 2003 Hamish Rodda <rodda@kde.org> 0012 Copyright 2003 Joseph Wenninger <jowenn@kde.org> 0013 Copyright 2003 Lukas Tinkl <lukas@kde.org> 0014 Copyright 2000-2002 Werner Trobin <trobin@kde.org> 0015 Copyright 2002 Harri Porten <porten@kde.org> 0016 Copyright 2002 John Dailey <dailey@vt.edu> 0017 Copyright 2002 Daniel Naber <daniel.naber@t-online.de> 0018 Copyright 1999-2000 Torben Weis <weis@kde.org> 0019 Copyright 1999-2000 Stephan Kulow <coolo@kde.org> 0020 Copyright 2000 Bernd Wuebben <wuebben@kde.org> 0021 Copyright 2000 Wilco Greven <greven@kde.org> 0022 Copyright 2000 Simon Hausmann <hausmann@kde.org 0023 Copyright 1999 Michael Reiher <michael.reiher@gmx.de> 0024 Copyright 1999 Boris Wedl <boris.wedl@kfunigraz.ac.at> 0025 Copyright 1999 Reginald Stadlbauer <reggie@kde.org> 0026 0027 This library is free software; you can redistribute it and/or 0028 modify it under the terms of the GNU Library General Public 0029 License as published by the Free Software Foundation; either 0030 version 2 of the License, or (at your option) any later version. 0031 0032 This library is distributed in the hope that it will be useful, 0033 but WITHOUT ANY WARRANTY; without even the implied warranty of 0034 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0035 Library General Public License for more details. 0036 0037 You should have received a copy of the GNU Library General Public License 0038 along with this library; see the file COPYING.LIB. If not, write to 0039 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0040 Boston, MA 02110-1301, USA. 0041 */ 0042 0043 // Local 0044 #include "Headers.h" 0045 0046 // Qt 0047 #include <QApplication> 0048 #include <QLabel> 0049 #include <QPainter> 0050 #include <QTextLayout> 0051 #include <QToolTip> 0052 0053 // KF5 0054 #include <KLocalizedString> 0055 #include <kmessagebox.h> 0056 0057 // Calligra 0058 #include <KoCanvasController.h> 0059 #include <KoToolProxy.h> 0060 #include <KoZoomHandler.h> 0061 #include <KoPointerEvent.h> 0062 #include <KoGlobal.h> 0063 0064 // Sheets 0065 #include "CanvasBase.h" 0066 #include "Cell.h" 0067 #include "Doc.h" 0068 #include "calligra_sheets_limits.h" 0069 #include "RowColumnFormat.h" 0070 #include "RowFormatStorage.h" 0071 #include "Sheet.h" 0072 #include "ElapsedTime_p.h" 0073 0074 // commands 0075 #include "commands/RowColumnManipulators.h" 0076 0077 // ui 0078 #include "ui/Selection.h" 0079 0080 using namespace Calligra::Sheets; 0081 0082 /**************************************************************** 0083 * 0084 * RowHeader 0085 * 0086 ****************************************************************/ 0087 0088 RowHeader::RowHeader(CanvasBase *_canvas) 0089 : m_pCanvas(_canvas), m_bSelection(false), 0090 m_iSelectionAnchor(1), m_bResize(false), m_lSize(0), m_bMousePressed(false), 0091 m_cellToolIsActive(true), m_font(KoGlobal::defaultFont()) 0092 { 0093 } 0094 0095 0096 RowHeader::~RowHeader() 0097 { 0098 } 0099 0100 void RowHeader::mousePress(KoPointerEvent * _ev) 0101 { 0102 if (!m_cellToolIsActive) 0103 return; 0104 0105 register Sheet * const sheet = m_pCanvas->activeSheet(); 0106 if (!sheet) 0107 return; 0108 0109 if (_ev->button() == Qt::LeftButton) { 0110 m_bMousePressed = true; 0111 m_pCanvas->enableAutoScroll(); 0112 } 0113 0114 double ev_PosY = m_pCanvas->zoomHandler()->unzoomItY(_ev->pos().y()) + m_pCanvas->yOffset(); 0115 double dHeight = m_pCanvas->zoomHandler()->unzoomItY(height()); 0116 m_bResize = false; 0117 m_bSelection = false; 0118 0119 // We were editing a cell -> save value and get out of editing mode 0120 m_pCanvas->selection()->emitCloseEditor(true); // save changes 0121 0122 // Find the first visible row and the y position of this row. 0123 qreal y; 0124 int row = sheet->topRow(m_pCanvas->yOffset(), y); 0125 0126 // Did the user click between two rows? 0127 while (y < (dHeight + m_pCanvas->yOffset()) && (!m_bResize) && row <= KS_rowMax) { 0128 double h = sheet->rowFormats()->rowHeight(row); 0129 row++; 0130 if (row > KS_rowMax) 0131 row = KS_rowMax; 0132 if ((ev_PosY >= y + h - 2) && 0133 (ev_PosY <= y + h + 1) && 0134 !(sheet->rowFormats()->isHiddenOrFiltered(row) && row == 1)) 0135 m_bResize = true; 0136 y += h; 0137 } 0138 0139 //if row is hide and it's the first row 0140 //you mustn't resize it. 0141 qreal tmp2; 0142 int tmpRow = sheet->topRow(ev_PosY - 1, tmp2); 0143 if (sheet->rowFormats()->isHiddenOrFiltered(tmpRow) && tmpRow == 1) 0144 m_bResize = false; 0145 0146 // So the user clicked between two rows ? 0147 if (m_bResize) { 0148 // Determine row to resize 0149 qreal tmp; 0150 m_iResizedRow = sheet->topRow(ev_PosY - 1, tmp); 0151 if (!sheet->isProtected()) 0152 paintSizeIndicator(_ev->pos().y()); 0153 } else { 0154 if (_ev->button() != Qt::RightButton) { 0155 m_bSelection = true; 0156 } 0157 0158 qreal tmp; 0159 int hit_row = sheet->topRow(ev_PosY, tmp); 0160 if (hit_row > KS_rowMax) 0161 return; 0162 0163 m_iSelectionAnchor = hit_row; 0164 0165 if (!m_pCanvas->selection()->contains(QPoint(1, hit_row)) || 0166 !(_ev->button() == Qt::RightButton) || 0167 !m_pCanvas->selection()->isRowSelected()) { 0168 QPoint newMarker(1, hit_row); 0169 QPoint newAnchor(KS_colMax, hit_row); 0170 if (_ev->modifiers() == Qt::ControlModifier) { 0171 m_pCanvas->selection()->extend(QRect(newAnchor, newMarker)); 0172 } else if (_ev->modifiers() == Qt::ShiftModifier) { 0173 m_pCanvas->selection()->update(newMarker); 0174 } else { 0175 m_pCanvas->selection()->initialize(QRect(newAnchor, newMarker)); 0176 } 0177 } 0178 0179 if (_ev->button() == Qt::RightButton) { 0180 m_pCanvas->mousePressed(_ev); 0181 } 0182 } 0183 } 0184 0185 void RowHeader::mouseRelease(KoPointerEvent * _ev) 0186 { 0187 if (!m_cellToolIsActive) 0188 return; 0189 m_pCanvas->disableAutoScroll(); 0190 if (m_lSize) 0191 m_lSize->hide(); 0192 0193 m_bMousePressed = false; 0194 0195 register Sheet * const sheet = m_pCanvas->activeSheet(); 0196 if (!sheet) 0197 return; 0198 0199 double ev_PosY = m_pCanvas->zoomHandler()->unzoomItY(_ev->pos().y()) + m_pCanvas->yOffset(); 0200 0201 if (m_bResize) { 0202 // Remove size indicator painted by paintSizeIndicator 0203 removeSizeIndicator(); 0204 0205 QRect rect; 0206 rect.setCoords(1, m_iResizedRow, KS_colMax, m_iResizedRow); 0207 if (m_pCanvas->selection()->isRowSelected()) { 0208 if (m_pCanvas->selection()->contains(QPoint(1, m_iResizedRow))) { 0209 rect = m_pCanvas->selection()->lastRange(); 0210 } 0211 } 0212 0213 double height = 0.0; 0214 double y = sheet->rowPosition(m_iResizedRow); 0215 if (ev_PosY - y <= 0.0) 0216 height = 0.0; 0217 else 0218 height = ev_PosY - y; 0219 0220 if (height != 0.0) { 0221 ResizeRowManipulator* command = new ResizeRowManipulator(); 0222 command->setSheet(sheet); 0223 command->setSize(height); 0224 command->add(Region(rect, sheet)); 0225 if (!command->execute()) 0226 delete command; 0227 } else { // hide 0228 HideShowManipulator* command = new HideShowManipulator(); 0229 command->setSheet(sheet); 0230 command->setManipulateRows(true); 0231 command->add(Region(rect, sheet)); 0232 if (!command->execute()) 0233 delete command; 0234 } 0235 delete m_lSize; 0236 m_lSize = 0; 0237 } else if (m_bSelection) { 0238 QRect rect = m_pCanvas->selection()->lastRange(); 0239 0240 // TODO: please don't remove. Right now it's useless, but it's for a future feature 0241 // Norbert 0242 bool m_frozen = false; 0243 if (m_frozen) { 0244 debugSheets << "selected: T" << rect.top() << " B" << rect.bottom(); 0245 0246 int i; 0247 QList<int> hiddenRows; 0248 0249 for (i = rect.top(); i <= rect.bottom(); ++i) { 0250 if (sheet->rowFormats()->isHidden(i)) { 0251 hiddenRows.append(i); 0252 } 0253 } 0254 0255 if (hiddenRows.count() > 0) { 0256 if (m_pCanvas->selection()->isColumnSelected()) { 0257 KMessageBox::error(/* XXX TODO this*/0, i18n("Area is too large.")); 0258 return; 0259 } 0260 0261 HideShowManipulator* command = new HideShowManipulator(); 0262 command->setSheet(sheet); 0263 command->setManipulateRows(true); 0264 command->setReverse(true); 0265 command->add(*m_pCanvas->selection()); 0266 command->execute(); 0267 } 0268 } 0269 } 0270 0271 m_bSelection = false; 0272 m_bResize = false; 0273 } 0274 0275 void RowHeader::equalizeRow(double resize) 0276 { 0277 if (resize != 0.0) { 0278 ResizeRowManipulator* command = new ResizeRowManipulator(); 0279 command->setSheet(m_pCanvas->activeSheet()); 0280 command->setSize(qMax(2.0, resize)); 0281 command->add(*m_pCanvas->selection()); 0282 if (!command->execute()) 0283 delete command; 0284 } else { // hide 0285 HideShowManipulator* command = new HideShowManipulator(); 0286 command->setSheet(m_pCanvas->activeSheet()); 0287 command->setManipulateRows(true); 0288 command->add(*m_pCanvas->selection()); 0289 if (!command->execute()) 0290 delete command; 0291 } 0292 } 0293 0294 void RowHeader::mouseDoubleClick(KoPointerEvent*) 0295 { 0296 if (!m_cellToolIsActive) 0297 return; 0298 register Sheet * const sheet = m_pCanvas->activeSheet(); 0299 if (!sheet) 0300 return; 0301 0302 if (sheet->isProtected()) 0303 return; 0304 0305 AdjustColumnRowManipulator* command = new AdjustColumnRowManipulator(); 0306 command->setSheet(sheet); 0307 command->setAdjustRow(true); 0308 command->add(*m_pCanvas->selection()); 0309 command->execute(); 0310 } 0311 0312 0313 void RowHeader::mouseMove(KoPointerEvent* _ev) 0314 { 0315 if (!m_cellToolIsActive) { 0316 setCursor(Qt::ArrowCursor); 0317 return; 0318 } 0319 0320 register Sheet * const sheet = m_pCanvas->activeSheet(); 0321 if (!sheet) 0322 return; 0323 0324 qreal ev_PosY = m_pCanvas->zoomHandler()->unzoomItY(_ev->pos().y()) + m_pCanvas->yOffset(); 0325 qreal dHeight = m_pCanvas->zoomHandler()->unzoomItY(height()); 0326 0327 // The button is pressed and we are resizing ? 0328 if (m_bResize) { 0329 if (!sheet->isProtected()) 0330 paintSizeIndicator(_ev->pos().y()); 0331 } 0332 // The button is pressed and we are selecting ? 0333 else if (m_bSelection) { 0334 qreal y; 0335 int row = sheet->topRow(ev_PosY, y); 0336 if (row > KS_rowMax || row <= 0) 0337 return; 0338 0339 QPoint newAnchor = m_pCanvas->selection()->anchor(); 0340 QPoint newMarker = m_pCanvas->selection()->marker(); 0341 newMarker.setY(row); 0342 newAnchor.setY(m_iSelectionAnchor); 0343 m_pCanvas->selection()->update(newMarker); 0344 0345 if (_ev->pos().y() < 0) 0346 m_pCanvas->setVertScrollBarPos(qMax<qreal>(0, ev_PosY)); 0347 else if (_ev->pos().y() > m_pCanvas->height()) { 0348 if (row < KS_rowMax) { 0349 const qreal rowHeight = sheet->rowFormats()->rowHeight(row + 1); 0350 y = sheet->rowPosition(row + 1); 0351 m_pCanvas->setVertScrollBarPos(ev_PosY + rowHeight - dHeight); 0352 } 0353 } 0354 } 0355 // No button is pressed and the mouse is just moved 0356 else { 0357 0358 //What is the internal size of 1 pixel 0359 const double unzoomedPixel = m_pCanvas->zoomHandler()->unzoomItY(1.0); 0360 qreal y; 0361 int tmpRow = sheet->topRow(m_pCanvas->yOffset(), y); 0362 0363 while (y < dHeight + m_pCanvas->yOffset() && tmpRow <= KS_rowMax) { 0364 double h = sheet->rowFormats()->visibleHeight(tmpRow); 0365 //if col is hide and it's the first column 0366 //you mustn't resize it. 0367 if (ev_PosY >= y + h - 2 * unzoomedPixel && 0368 ev_PosY <= y + h + unzoomedPixel && 0369 !(sheet->rowFormats()->isHiddenOrFiltered(tmpRow) && tmpRow == 1)) { 0370 setCursor(Qt::SplitVCursor); 0371 return; 0372 } 0373 y += h; 0374 tmpRow++; 0375 } 0376 setCursor(Qt::ArrowCursor); 0377 } 0378 } 0379 0380 void RowHeader::paint(QPainter* painter, const QRectF& painterRect) 0381 { 0382 register Sheet * const sheet = m_pCanvas->activeSheet(); 0383 if (!sheet) 0384 return; 0385 0386 // ElapsedTime et( "Painting vertical header", ElapsedTime::PrintOnlyTime ); 0387 0388 // FIXME Stefan: Make use of clipping. Find the repaint call after the scrolling. 0389 // debugSheetsRender << event->rect(); 0390 0391 // painting rectangle 0392 const QRectF paintRect = m_pCanvas->zoomHandler()->viewToDocument(painterRect); 0393 0394 // the painter 0395 painter->setRenderHint(QPainter::TextAntialiasing); 0396 0397 // fonts 0398 QFont normalFont(m_font); 0399 QFont boldFont(normalFont); 0400 boldFont.setBold(true); 0401 0402 // background brush/color 0403 const QBrush backgroundBrush(palette().window()); 0404 const QColor backgroundColor(backgroundBrush.color()); 0405 0406 // selection brush/color 0407 QColor selectionColor(palette().highlight().color()); 0408 selectionColor.setAlpha(127); 0409 const QBrush selectionBrush(selectionColor); 0410 0411 qreal yPos; 0412 // Get the top row and the current y-position 0413 int y = sheet->topRow(qMax<qreal>(0, paintRect.y() + m_pCanvas->yOffset()), yPos); 0414 // Align to the offset 0415 yPos = yPos - m_pCanvas->yOffset(); 0416 0417 const KoViewConverter *converter = m_pCanvas->zoomHandler(); 0418 const qreal width = this->width() - 1; 0419 0420 QSet<int> selectedRows; 0421 QSet<int> affectedRows; 0422 if (!m_pCanvas->selection()->referenceSelectionMode() && m_cellToolIsActive) { 0423 selectedRows = m_pCanvas->selection()->rowsSelected(); 0424 affectedRows = m_pCanvas->selection()->rowsAffected(); 0425 } 0426 // Loop through the rows, until we are out of range 0427 while (yPos <= paintRect.bottom() && y <= KS_rowMax) { 0428 const bool selected = (selectedRows.contains(y)); 0429 const bool highlighted = (!selected && affectedRows.contains(y)); 0430 0431 if (sheet->rowFormats()->isHiddenOrFiltered(y)) { 0432 ++y; 0433 continue; 0434 } 0435 const qreal rawHeight = sheet->rowFormats()->rowHeight(y); 0436 const qreal height = converter->documentToViewY(rawHeight); 0437 const QRectF rect(0, converter->documentToViewY(yPos), width, height); 0438 0439 if (selected || highlighted) { 0440 painter->setPen(QPen(selectionColor.dark(150), 0)); 0441 painter->setBrush(selectionBrush); 0442 } else { 0443 painter->setPen(QPen(backgroundColor.dark(150), 0)); 0444 painter->setBrush(backgroundBrush); 0445 } 0446 painter->drawRect(rect); 0447 0448 const QString rowText = QString::number(y); 0449 0450 // Reset painter 0451 painter->setFont(normalFont); 0452 painter->setPen(palette().text().color()); 0453 0454 if (selected) 0455 painter->setPen(palette().highlightedText().color()); 0456 else if (highlighted) 0457 painter->setFont(boldFont); 0458 0459 QFontMetricsF fm(painter->font()); 0460 #if 0 0461 if (height < fm.ascent() - fm.descent()) { 0462 // try to scale down the font to make it fit 0463 QFont font = painter->font(); 0464 qreal maxSize = font.pointSizeF(); 0465 qreal minSize = maxSize / 2; 0466 while (minSize > 1) { 0467 font.setPointSizeF(minSize); 0468 const QFontMetricsF fm2(font); 0469 if (height >= fm2.ascent() - fm2.descent()) 0470 break; 0471 minSize /= 2; 0472 } 0473 while (minSize < 0.99 * maxSize) { 0474 qreal middle = (maxSize + minSize) / 2; 0475 font.setPointSizeF(middle); 0476 const QFontMetricsF fm2(font); 0477 if (height >= fm2.ascent() - fm2.descent()) { 0478 minSize = middle; 0479 } else { 0480 maxSize = middle; 0481 } 0482 } 0483 painter->setFont(font); 0484 fm = QFontMetricsF(font); 0485 } 0486 #endif 0487 if (height >= fm.ascent() - fm.descent()) { 0488 painter->drawText(rect, Qt::AlignCenter, rowText); 0489 } 0490 0491 yPos += rawHeight; 0492 y++; 0493 } 0494 } 0495 0496 0497 void RowHeader::focusOut(QFocusEvent*) 0498 { 0499 m_pCanvas->disableAutoScroll(); 0500 m_bMousePressed = false; 0501 } 0502 0503 void RowHeader::doToolChanged(const QString& toolId) 0504 { 0505 m_cellToolIsActive = toolId.startsWith(QLatin1String("KSpread")); 0506 update(); 0507 } 0508 0509 void RowHeader::setHeaderFont(const QFont &font) 0510 { 0511 m_font = font; 0512 update(); 0513 } 0514 0515 QFont RowHeader::headerFont() const 0516 { 0517 return m_font; 0518 } 0519 0520 /**************************************************************** 0521 * 0522 * ColumnHeader 0523 * 0524 ****************************************************************/ 0525 0526 ColumnHeader::ColumnHeader(CanvasBase *_canvas) 0527 : m_pCanvas(_canvas), m_bSelection(false), 0528 m_iSelectionAnchor(1), m_bResize(false), m_lSize(0), m_bMousePressed(false), 0529 m_cellToolIsActive(true), m_font(KoGlobal::defaultFont()) 0530 { 0531 } 0532 0533 0534 ColumnHeader::~ColumnHeader() 0535 { 0536 } 0537 0538 void ColumnHeader::mousePress(KoPointerEvent * _ev) 0539 { 0540 if (!m_cellToolIsActive) 0541 return; 0542 0543 if (_ev->button() == Qt::LeftButton) { 0544 m_bMousePressed = true; 0545 m_pCanvas->enableAutoScroll(); 0546 } 0547 0548 const register Sheet * const sheet = m_pCanvas->activeSheet(); 0549 if (!sheet) 0550 return; 0551 0552 // We were editing a cell -> save value and get out of editing mode 0553 m_pCanvas->selection()->emitCloseEditor(true); // save changes 0554 0555 double ev_PosX; 0556 double dWidth = m_pCanvas->zoomHandler()->unzoomItX(width()); 0557 if (sheet->layoutDirection() == Qt::RightToLeft) 0558 ev_PosX = dWidth - m_pCanvas->zoomHandler()->unzoomItX(_ev->pos().x()) + m_pCanvas->xOffset(); 0559 else 0560 ev_PosX = m_pCanvas->zoomHandler()->unzoomItX(_ev->pos().x()) + m_pCanvas->xOffset(); 0561 m_bResize = false; 0562 m_bSelection = false; 0563 0564 // Find the first visible column and the x position of this column. 0565 qreal x; 0566 0567 const double unzoomedPixel = m_pCanvas->zoomHandler()->unzoomItX(1.0); 0568 if (sheet->layoutDirection() == Qt::RightToLeft) { 0569 int tmpCol = sheet->leftColumn(m_pCanvas->xOffset(), x); 0570 0571 debugSheets << "evPos:" << ev_PosX << ", x:" << x << ", COL:" << tmpCol; 0572 while (ev_PosX > x && (!m_bResize) && tmpCol <= KS_colMax) { 0573 double w = sheet->columnFormat(tmpCol)->width(); 0574 0575 debugSheets << "evPos:" << ev_PosX << ", x:" << x << ", w:" << w << ", COL:" << tmpCol; 0576 0577 ++tmpCol; 0578 if (tmpCol > KS_colMax) 0579 tmpCol = KS_colMax; 0580 //if col is hide and it's the first column 0581 //you mustn't resize it. 0582 0583 if (ev_PosX >= x + w - unzoomedPixel && 0584 ev_PosX <= x + w + unzoomedPixel && 0585 !(sheet->columnFormat(tmpCol)->isHiddenOrFiltered() && tmpCol == 1)) { 0586 m_bResize = true; 0587 } 0588 x += w; 0589 } 0590 0591 //if col is hide and it's the first column 0592 //you mustn't resize it. 0593 qreal tmp2; 0594 tmpCol = sheet->leftColumn(dWidth - ev_PosX + 1, tmp2); 0595 if (sheet->columnFormat(tmpCol)->isHiddenOrFiltered() && tmpCol == 0) { 0596 debugSheets << "No resize:" << tmpCol << "," << sheet->columnFormat(tmpCol)->isHiddenOrFiltered(); 0597 m_bResize = false; 0598 } 0599 0600 debugSheets << "Resize:" << m_bResize; 0601 } else { 0602 int col = sheet->leftColumn(m_pCanvas->xOffset(), x); 0603 0604 // Did the user click between two columns? 0605 while (x < (dWidth + m_pCanvas->xOffset()) && (!m_bResize) && col <= KS_colMax) { 0606 double w = sheet->columnFormat(col)->width(); 0607 col++; 0608 if (col > KS_colMax) 0609 col = KS_colMax; 0610 if ((ev_PosX >= x + w - unzoomedPixel) && 0611 (ev_PosX <= x + w + unzoomedPixel) && 0612 !(sheet->columnFormat(col)->isHiddenOrFiltered() && col == 1)) 0613 m_bResize = true; 0614 x += w; 0615 } 0616 0617 //if col is hide and it's the first column 0618 //you mustn't resize it. 0619 qreal tmp2; 0620 int tmpCol = sheet->leftColumn(ev_PosX - 1, tmp2); 0621 if (sheet->columnFormat(tmpCol)->isHiddenOrFiltered() && tmpCol == 1) 0622 m_bResize = false; 0623 } 0624 0625 // So the user clicked between two rows ? 0626 if (m_bResize) { 0627 // Determine the column to resize 0628 qreal tmp; 0629 if (sheet->layoutDirection() == Qt::RightToLeft) { 0630 m_iResizedColumn = sheet->leftColumn(ev_PosX - 1, tmp); 0631 // debugSheets <<"RColumn:" << m_iResizedColumn <<", PosX:" << ev_PosX; 0632 0633 if (!sheet->isProtected()) 0634 paintSizeIndicator(_ev->pos().x()); 0635 } else { 0636 m_iResizedColumn = sheet->leftColumn(ev_PosX - 1, tmp); 0637 0638 if (!sheet->isProtected()) 0639 paintSizeIndicator(_ev->pos().x()); 0640 } 0641 0642 // debugSheets <<"Column:" << m_iResizedColumn; 0643 } else { 0644 if (_ev->button() != Qt::RightButton) { 0645 m_bSelection = true; 0646 } 0647 0648 qreal tmp; 0649 int hit_col = sheet->leftColumn(ev_PosX, tmp); 0650 if (hit_col > KS_colMax) 0651 return; 0652 0653 m_iSelectionAnchor = hit_col; 0654 0655 if (!m_pCanvas->selection()->contains(QPoint(hit_col, 1)) || 0656 !(_ev->button() == Qt::RightButton) || 0657 !m_pCanvas->selection()->isColumnSelected()) { 0658 QPoint newMarker(hit_col, 1); 0659 QPoint newAnchor(hit_col, KS_rowMax); 0660 if (_ev->modifiers() == Qt::ControlModifier) { 0661 m_pCanvas->selection()->extend(QRect(newAnchor, newMarker)); 0662 } else if (_ev->modifiers() == Qt::ShiftModifier) { 0663 m_pCanvas->selection()->update(newMarker); 0664 } else { 0665 m_pCanvas->selection()->initialize(QRect(newAnchor, newMarker)); 0666 } 0667 } 0668 0669 if (_ev->button() == Qt::RightButton) { 0670 m_pCanvas->mousePressed(_ev); 0671 } 0672 } 0673 } 0674 0675 void ColumnHeader::mouseRelease(KoPointerEvent * _ev) 0676 { 0677 if (!m_cellToolIsActive) 0678 return; 0679 m_pCanvas->disableAutoScroll(); 0680 if (m_lSize) 0681 m_lSize->hide(); 0682 0683 m_bMousePressed = false; 0684 0685 register Sheet * const sheet = m_pCanvas->activeSheet(); 0686 if (!sheet) 0687 return; 0688 0689 if (m_bResize) { 0690 double dWidth = m_pCanvas->zoomHandler()->unzoomItX(width()); 0691 double ev_PosX; 0692 0693 // Remove size indicator painted by paintSizeIndicator 0694 removeSizeIndicator(); 0695 0696 QRect rect; 0697 rect.setCoords(m_iResizedColumn, 1, m_iResizedColumn, KS_rowMax); 0698 if (m_pCanvas->selection()->isColumnSelected()) { 0699 if (m_pCanvas->selection()->contains(QPoint(m_iResizedColumn, 1))) { 0700 rect = m_pCanvas->selection()->lastRange(); 0701 } 0702 } 0703 0704 double width = 0.0; 0705 double x; 0706 0707 if (sheet->layoutDirection() == Qt::RightToLeft) 0708 ev_PosX = dWidth - m_pCanvas->zoomHandler()->unzoomItX(_ev->pos().x()) + m_pCanvas->xOffset(); 0709 else 0710 ev_PosX = m_pCanvas->zoomHandler()->unzoomItX(_ev->pos().x()) + m_pCanvas->xOffset(); 0711 0712 x = sheet->columnPosition(m_iResizedColumn); 0713 0714 if (ev_PosX - x <= 0.0) 0715 width = 0.0; 0716 else 0717 width = ev_PosX - x; 0718 0719 if (width != 0.0) { 0720 ResizeColumnManipulator* command = new ResizeColumnManipulator(); 0721 command->setSheet(sheet); 0722 command->setSize(width); 0723 command->add(Region(rect, sheet)); 0724 if (!command->execute()) 0725 delete command; 0726 } else { // hide 0727 HideShowManipulator* command = new HideShowManipulator(); 0728 command->setSheet(sheet); 0729 command->setManipulateColumns(true); 0730 command->add(Region(rect, sheet)); 0731 if (!command->execute()) 0732 delete command; 0733 } 0734 delete m_lSize; 0735 m_lSize = 0; 0736 } else if (m_bSelection) { 0737 QRect rect = m_pCanvas->selection()->lastRange(); 0738 0739 // TODO: please don't remove. Right now it's useless, but it's for a future feature 0740 // Norbert 0741 bool m_frozen = false; 0742 if (m_frozen) { 0743 debugSheets << "selected: L" << rect.left() << " R" << rect.right(); 0744 0745 int i; 0746 QList<int> hiddenCols; 0747 0748 for (i = rect.left(); i <= rect.right(); ++i) { 0749 if (sheet->columnFormat(i)->isHidden()) { 0750 hiddenCols.append(i); 0751 } 0752 } 0753 0754 if (hiddenCols.count() > 0) { 0755 if (m_pCanvas->selection()->isRowSelected()) { 0756 KMessageBox::error(0 /* XXX TODO this */, i18n("Area is too large.")); 0757 return; 0758 } 0759 0760 HideShowManipulator* command = new HideShowManipulator(); 0761 command->setSheet(sheet); 0762 command->setManipulateColumns(true); 0763 command->setReverse(true); 0764 command->add(*m_pCanvas->selection()); 0765 command->execute(); 0766 } 0767 } 0768 } 0769 0770 m_bSelection = false; 0771 m_bResize = false; 0772 } 0773 0774 void ColumnHeader::equalizeColumn(double resize) 0775 { 0776 if (resize != 0.0) { 0777 ResizeColumnManipulator* command = new ResizeColumnManipulator(); 0778 command->setSheet(m_pCanvas->activeSheet()); 0779 command->setSize(qMax(2.0, resize)); 0780 command->add(*m_pCanvas->selection()); 0781 if (!command->execute()) 0782 delete command; 0783 } else { // hide 0784 HideShowManipulator* command = new HideShowManipulator(); 0785 command->setSheet(m_pCanvas->activeSheet()); 0786 command->setManipulateColumns(true); 0787 command->add(*m_pCanvas->selection()); 0788 if (!command->execute()) 0789 delete command; 0790 } 0791 } 0792 0793 void ColumnHeader::mouseDoubleClick(KoPointerEvent*) 0794 { 0795 if (!m_cellToolIsActive) 0796 return; 0797 register Sheet * const sheet = m_pCanvas->activeSheet(); 0798 if (!sheet) 0799 return; 0800 0801 if (sheet->isProtected()) 0802 return; 0803 0804 AdjustColumnRowManipulator* command = new AdjustColumnRowManipulator(); 0805 command->setSheet(sheet); 0806 command->setAdjustColumn(true); 0807 command->add(*m_pCanvas->selection()); 0808 command->execute(); 0809 } 0810 0811 void ColumnHeader::mouseMove(KoPointerEvent* _ev) 0812 { 0813 if (!m_cellToolIsActive) 0814 return; 0815 0816 register Sheet * const sheet = m_pCanvas->activeSheet(); 0817 0818 if (!sheet) 0819 return; 0820 0821 double dWidth = m_pCanvas->zoomHandler()->unzoomItX(width()); 0822 double ev_PosX; 0823 if (sheet->layoutDirection() == Qt::RightToLeft) 0824 ev_PosX = dWidth - m_pCanvas->zoomHandler()->unzoomItX(_ev->pos().x()) + m_pCanvas->xOffset(); 0825 else 0826 ev_PosX = m_pCanvas->zoomHandler()->unzoomItX(_ev->pos().x()) + m_pCanvas->xOffset(); 0827 0828 // The button is pressed and we are resizing ? 0829 if (m_bResize) { 0830 if (!sheet->isProtected()) 0831 paintSizeIndicator(_ev->pos().x()); 0832 } 0833 // The button is pressed and we are selecting ? 0834 else if (m_bSelection) { 0835 qreal x; 0836 int col = sheet->leftColumn(ev_PosX, x); 0837 0838 if (col > KS_colMax || col <= 0) 0839 return; 0840 0841 QPoint newMarker = m_pCanvas->selection()->marker(); 0842 QPoint newAnchor = m_pCanvas->selection()->anchor(); 0843 newMarker.setX(col); 0844 newAnchor.setX(m_iSelectionAnchor); 0845 m_pCanvas->selection()->update(newMarker); 0846 0847 if (sheet->layoutDirection() == Qt::RightToLeft) { 0848 if (_ev->pos().x() < width() - m_pCanvas->width()) { 0849 const ColumnFormat *cl = sheet->columnFormat(col + 1); 0850 x = sheet->columnPosition(col + 1); 0851 m_pCanvas->setHorizScrollBarPos(- (int)((ev_PosX + cl->width()) - dWidth)); 0852 } else if (_ev->pos().x() > width()) 0853 m_pCanvas->setHorizScrollBarPos(- (ev_PosX - dWidth + m_pCanvas->zoomHandler()->unzoomItX(m_pCanvas->width()))); 0854 } else { 0855 if (_ev->pos().x() < 0) 0856 m_pCanvas->setHorizScrollBarPos(ev_PosX); 0857 else if (_ev->pos().x() > m_pCanvas->width()) { 0858 if (col < KS_colMax) { 0859 const ColumnFormat *cl = sheet->columnFormat(col + 1); 0860 x = sheet->columnPosition(col + 1); 0861 m_pCanvas->setHorizScrollBarPos(ev_PosX + cl->width() - dWidth); 0862 } 0863 } 0864 } 0865 0866 } 0867 // No button is pressed and the mouse is just moved 0868 else { 0869 //What is the internal size of 1 pixel 0870 const double unzoomedPixel = m_pCanvas->zoomHandler()->unzoomItX(1.0); 0871 qreal x; 0872 0873 if (sheet->layoutDirection() == Qt::RightToLeft) { 0874 int tmpCol = sheet->leftColumn(m_pCanvas->xOffset(), x); 0875 0876 while (ev_PosX > x && tmpCol <= KS_colMax) { 0877 double w = sheet->columnFormat(tmpCol)->visibleWidth(); 0878 ++tmpCol; 0879 0880 //if col is hide and it's the first column 0881 //you mustn't resize it. 0882 if (ev_PosX >= x + w - unzoomedPixel && 0883 ev_PosX <= x + w + unzoomedPixel && 0884 !(sheet->columnFormat(tmpCol)->isHiddenOrFiltered() && tmpCol == 0)) { 0885 setCursor(Qt::SplitHCursor); 0886 return; 0887 } 0888 x += w; 0889 } 0890 setCursor(Qt::ArrowCursor); 0891 } else { 0892 int tmpCol = sheet->leftColumn(m_pCanvas->xOffset(), x); 0893 0894 while (x < m_pCanvas->zoomHandler()->unzoomItY(width()) + m_pCanvas->xOffset() && tmpCol <= KS_colMax) { 0895 double w = sheet->columnFormat(tmpCol)->visibleWidth(); 0896 //if col is hide and it's the first column 0897 //you mustn't resize it. 0898 if (ev_PosX >= x + w - unzoomedPixel && 0899 ev_PosX <= x + w + unzoomedPixel && 0900 !(sheet->columnFormat(tmpCol)->isHiddenOrFiltered() && tmpCol == 1)) { 0901 setCursor(Qt::SplitHCursor); 0902 return; 0903 } 0904 x += w; 0905 tmpCol++; 0906 } 0907 setCursor(Qt::ArrowCursor); 0908 } 0909 } 0910 } 0911 0912 void ColumnHeader::resize(const QSizeF& size, const QSizeF& oldSize) 0913 { 0914 register Sheet * const sheet = m_pCanvas->activeSheet(); 0915 if (!sheet) 0916 return; 0917 0918 // workaround to allow horizontal resizing and zoom changing when sheet 0919 // direction and interface direction don't match (e.g. an RTL sheet on an 0920 // LTR interface) 0921 if (sheet->layoutDirection() == Qt::RightToLeft && !QApplication::isRightToLeft()) { 0922 int dx = size.width() - oldSize.width(); 0923 scroll(dx, 0); 0924 } else if (sheet->layoutDirection() == Qt::LeftToRight && QApplication::isRightToLeft()) { 0925 int dx = size.width() - oldSize.width(); 0926 scroll(-dx, 0); 0927 } 0928 } 0929 0930 void ColumnHeader::paint(QPainter* painter, const QRectF& painterRect) 0931 { 0932 register Sheet * const sheet = m_pCanvas->activeSheet(); 0933 if (!sheet) 0934 return; 0935 0936 // ElapsedTime et( "Painting horizontal header", ElapsedTime::PrintOnlyTime ); 0937 0938 // FIXME Stefan: Make use of clipping. Find the repaint call after the scrolling. 0939 // debugSheetsRender << event->rect(); 0940 0941 // painting rectangle 0942 const QRectF paintRect = m_pCanvas->zoomHandler()->viewToDocument(painterRect); 0943 0944 // the painter 0945 painter->setRenderHint(QPainter::TextAntialiasing); 0946 0947 // fonts 0948 QFont normalFont(m_font); 0949 QFont boldFont(normalFont); 0950 boldFont.setBold(true); 0951 0952 // background brush/color 0953 const QBrush backgroundBrush(palette().window()); 0954 const QColor backgroundColor(backgroundBrush.color()); 0955 0956 // selection brush/color 0957 QColor selectionColor(palette().highlight().color()); 0958 selectionColor.setAlpha(127); 0959 const QBrush selectionBrush(selectionColor); 0960 0961 qreal xPos; 0962 int x; 0963 0964 if (sheet->layoutDirection() == Qt::RightToLeft) { 0965 //Get the left column and the current x-position 0966 x = sheet->leftColumn(int(m_pCanvas->zoomHandler()->unzoomItX(width()) - paintRect.x() + m_pCanvas->xOffset()), xPos); 0967 //Align to the offset 0968 xPos = m_pCanvas->zoomHandler()->unzoomItX(width()) - xPos + m_pCanvas->xOffset(); 0969 } else { 0970 //Get the left column and the current x-position 0971 x = sheet->leftColumn(int(paintRect.x() + m_pCanvas->xOffset()), xPos); 0972 //Align to the offset 0973 xPos = xPos - m_pCanvas->xOffset(); 0974 } 0975 0976 const KoViewConverter *converter = m_pCanvas->zoomHandler(); 0977 const qreal height = this->height() - 1; 0978 0979 QSet<int> selectedColumns; 0980 QSet<int> affectedColumns; 0981 if (!m_pCanvas->selection()->referenceSelectionMode() && m_cellToolIsActive) { 0982 selectedColumns = m_pCanvas->selection()->columnsSelected(); 0983 affectedColumns = m_pCanvas->selection()->columnsAffected(); 0984 } 0985 0986 int deltaX = 1; 0987 if (sheet->layoutDirection() == Qt::RightToLeft) { 0988 if (x > KS_colMax) 0989 x = KS_colMax; 0990 0991 xPos -= sheet->columnFormat(x)->width(); 0992 deltaX = -1; 0993 } 0994 0995 //Loop through the columns, until we are out of range 0996 while (xPos <= paintRect.right() && x <= KS_colMax) { 0997 bool selected = (selectedColumns.contains(x)); 0998 bool highlighted = (!selected && affectedColumns.contains(x)); 0999 1000 const ColumnFormat *columnFormat = sheet->columnFormat(x); 1001 if (columnFormat->isHiddenOrFiltered()) { 1002 ++x; 1003 continue; 1004 } 1005 const qreal width = converter->documentToViewX(columnFormat->width()); 1006 const QRectF rect(converter->documentToViewX(xPos), 0, width, height); 1007 1008 if (selected || highlighted) { 1009 painter->setPen(QPen(selectionColor.dark(150), 0)); 1010 painter->setBrush(selectionBrush); 1011 } else { 1012 painter->setPen(QPen(backgroundColor.dark(150), 0)); 1013 painter->setBrush(backgroundBrush); 1014 } 1015 painter->drawRect(rect); 1016 1017 // Reset painter 1018 painter->setFont(normalFont); 1019 painter->setPen(palette().text().color()); 1020 1021 if (selected) 1022 painter->setPen(palette().highlightedText().color()); 1023 else if (highlighted) 1024 painter->setFont(boldFont); 1025 1026 QString colText = sheet->getShowColumnNumber() ? QString::number(x) : Cell::columnName(x); 1027 QFontMetricsF fm(painter->font()); 1028 #if 0 1029 if (width < fm.width(colText)) { 1030 // try to scale down the font to make it fit 1031 QFont font = painter->font(); 1032 qreal maxSize = font.pointSizeF(); 1033 qreal minSize = maxSize / 2; 1034 while (minSize > 1) { 1035 font.setPointSizeF(minSize); 1036 const QFontMetricsF fm2(font); 1037 if (width >= fm2.width(colText)) 1038 break; 1039 minSize /= 2; 1040 } 1041 while (minSize < 0.99 * maxSize) { 1042 qreal middle = (maxSize + minSize) / 2; 1043 font.setPointSizeF(middle); 1044 const QFontMetricsF fm2(font); 1045 if (width >= fm2.width(colText)) { 1046 minSize = middle; 1047 } else { 1048 maxSize = middle; 1049 } 1050 } 1051 painter->setFont(font); 1052 fm = QFontMetricsF(font); 1053 } 1054 #endif 1055 if (width >= fm.width(colText)) { 1056 #if 0 1057 switch (x % 3) { 1058 case 0: colText = QString::number(height) + 'h'; break; 1059 case 1: colText = QString::number(fm.ascent()) + 'a'; break; 1060 case 2: colText = QString::number(fm.descent()) + 'd'; break; 1061 } 1062 #endif 1063 painter->drawText(rect, Qt::AlignCenter, colText); 1064 } 1065 1066 xPos += columnFormat->width(); 1067 1068 x += deltaX; 1069 } 1070 } 1071 1072 void ColumnHeader::focusOut(QFocusEvent*) 1073 { 1074 m_pCanvas->disableAutoScroll(); 1075 m_bMousePressed = false; 1076 } 1077 1078 void ColumnHeader::doToolChanged(const QString& toolId) 1079 { 1080 m_cellToolIsActive = toolId.startsWith(QLatin1String("KSpread")); 1081 update(); 1082 } 1083 1084 void ColumnHeader::setHeaderFont(const QFont &font) 1085 { 1086 m_font = font; 1087 update(); 1088 } 1089 1090 QFont ColumnHeader::headerFont() const 1091 { 1092 return m_font; 1093 } 1094 1095 /**************************************************************** 1096 * 1097 * SelectAllButton 1098 * 1099 ****************************************************************/ 1100 1101 SelectAllButton::SelectAllButton(CanvasBase* canvasBase) 1102 : m_canvasBase(canvasBase) 1103 , m_mousePressed(false) 1104 , m_cellToolIsActive(true) 1105 { 1106 } 1107 1108 SelectAllButton::~SelectAllButton() 1109 { 1110 } 1111 1112 void SelectAllButton::paint(QPainter* painter, const QRectF& painterRect) 1113 { 1114 // the painter 1115 painter->setClipRect(painterRect); 1116 1117 // if all cells are selected 1118 if (m_canvasBase->selection()->isAllSelected() && 1119 !m_canvasBase->selection()->referenceSelectionMode() && m_cellToolIsActive) { 1120 // selection brush/color 1121 QColor selectionColor(palette().highlight().color()); 1122 selectionColor.setAlpha(127); 1123 const QBrush selectionBrush(selectionColor); 1124 1125 painter->setPen(QPen(selectionColor.dark(150), 0)); 1126 painter->setBrush(selectionBrush); 1127 } else { 1128 // background brush/color 1129 const QBrush backgroundBrush(palette().window()); 1130 const QColor backgroundColor(backgroundBrush.color()); 1131 1132 painter->setPen(QPen(backgroundColor.dark(150), 0)); 1133 painter->setBrush(backgroundBrush); 1134 } 1135 painter->drawRect(painterRect.adjusted(0, 0, -1, -1)); 1136 } 1137 1138 void SelectAllButton::mousePress(KoPointerEvent* event) 1139 { 1140 if (!m_cellToolIsActive) 1141 return; 1142 if (event->button() == Qt::LeftButton) 1143 m_mousePressed = true; 1144 } 1145 1146 void SelectAllButton::mouseRelease(KoPointerEvent* event) 1147 { 1148 if (!m_cellToolIsActive) 1149 return; 1150 Q_UNUSED(event); 1151 if (!m_mousePressed) 1152 return; 1153 m_mousePressed = false; 1154 m_canvasBase->selection()->selectAll(); 1155 } 1156 1157 void SelectAllButton::doToolChanged(const QString& toolId) 1158 { 1159 m_cellToolIsActive = toolId.startsWith(QLatin1String("KSpread")); 1160 update(); 1161 }