File indexing completed on 2024-05-12 16:35:46

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 "HeaderWidgets.h"
0045 
0046 // Qt
0047 #include <QApplication>
0048 #include <QDesktopWidget>
0049 #include <QLabel>
0050 #include <QPainter>
0051 #include <QRubberBand>
0052 #include <QStyle>
0053 #include <QTextLayout>
0054 #include <QToolTip>
0055 #include <QScrollBar>
0056 
0057 // KF5
0058 #include <KLocalizedString>
0059 
0060 // Calligra
0061 #include <KoCanvasController.h>
0062 #include <KoToolProxy.h>
0063 #include <KoZoomHandler.h>
0064 #include <KoPointerEvent.h>
0065 #include <KoUnit.h>
0066 
0067 // Sheets
0068 #include "Canvas.h"
0069 #include "Cell.h"
0070 #include "Doc.h"
0071 #include "calligra_sheets_limits.h"
0072 #include "RowColumnFormat.h"
0073 #include "Sheet.h"
0074 #include "View.h"
0075 
0076 // commands
0077 #include "commands/RowColumnManipulators.h"
0078 
0079 // ui
0080 #include "ui/Selection.h"
0081 
0082 using namespace Calligra::Sheets;
0083 
0084 /****************************************************************
0085  *
0086  * RowHeaderWidget
0087  *
0088  ****************************************************************/
0089 
0090 RowHeaderWidget::RowHeaderWidget(QWidget *_parent, Canvas *_canvas, View *_view)
0091         : QWidget(_parent), RowHeader(_canvas), m_rubberband(0)
0092 {
0093     setAttribute(Qt::WA_StaticContents);
0094     setMouseTracking(true);
0095 
0096     connect(_view, SIGNAL(autoScroll(QPoint)),
0097             this, SLOT(slotAutoScroll(QPoint)));
0098     connect(m_pCanvas->toolProxy(), SIGNAL(toolChanged(QString)),
0099             this, SLOT(toolChanged(QString)));
0100 }
0101 
0102 
0103 RowHeaderWidget::~RowHeaderWidget()
0104 {
0105 }
0106 
0107 void RowHeaderWidget::mousePressEvent(QMouseEvent * _ev)
0108 {
0109     KoPointerEvent pev(_ev, QPointF());
0110     mousePress(&pev);
0111 }
0112 
0113 void RowHeaderWidget::mouseReleaseEvent(QMouseEvent * _ev)
0114 {
0115     KoPointerEvent pev(_ev, QPointF());
0116     mouseRelease(&pev);
0117 }
0118 
0119 void RowHeaderWidget::mouseDoubleClickEvent(QMouseEvent * _ev)
0120 {
0121     KoPointerEvent pev(_ev, QPointF());
0122     mouseDoubleClick(&pev);
0123 }
0124 
0125 void RowHeaderWidget::mouseMoveEvent(QMouseEvent * _ev)
0126 {
0127     KoPointerEvent pev(_ev, QPointF());
0128     mouseMove(&pev);
0129 }
0130 
0131 void RowHeaderWidget::slotAutoScroll(const QPoint& scrollDistance)
0132 {
0133     // NOTE Stefan: This slot is triggered by the same signal as
0134     //              Canvas::slotAutoScroll and ColumnHeaderWidget::slotAutoScroll.
0135     //              Therefore, nothing has to be done except the scrolling was
0136     //              initiated in this header.
0137     if (!m_bMousePressed)
0138         return;
0139     if (scrollDistance.y() == 0)
0140         return;
0141     const QPoint offset = m_pCanvas->viewConverter()->documentToView(m_pCanvas->offset()).toPoint();
0142     if (offset.y() + scrollDistance.y() < 0)
0143         return;
0144     m_pCanvas->setDocumentOffset(offset + QPoint(0, scrollDistance.y()));
0145     QMouseEvent event(QEvent::MouseMove, mapFromGlobal(QCursor::pos()),
0146                       Qt::NoButton, Qt::NoButton, QApplication::keyboardModifiers());
0147     QApplication::sendEvent(this, &event);
0148     m_pCanvas->update();
0149 }
0150 
0151 void RowHeaderWidget::wheelEvent(QWheelEvent* _ev)
0152 {
0153     QApplication::sendEvent(static_cast<Canvas*>(m_pCanvas), _ev);
0154 }
0155 
0156 void RowHeaderWidget::paintSizeIndicator(int mouseY)
0157 {
0158     register Sheet * const sheet = m_pCanvas->activeSheet();
0159     if (!sheet)
0160         return;
0161 
0162     m_iResizePos = mouseY;
0163 
0164     // Don't make the row have a height < 2 pixel.
0165     double y = m_pCanvas->zoomHandler()->zoomItY(sheet->rowPosition(m_iResizedRow) - m_pCanvas->yOffset());
0166     if (m_iResizePos < y + 2)
0167         m_iResizePos = (int) y;
0168 
0169     if (!m_rubberband) {
0170         m_rubberband = new QRubberBand(QRubberBand::Line, static_cast<Canvas*>(m_pCanvas));
0171         m_rubberband->setGeometry(0, m_iResizePos, m_pCanvas->width(), 2);
0172         m_rubberband->show();
0173     }
0174     m_rubberband->move(0, m_iResizePos);
0175 
0176     QString tmpSize;
0177     double hh = m_pCanvas->zoomHandler()->unzoomItY(m_iResizePos - y);
0178     double hu = m_pCanvas->doc()->unit().toUserValue(hh);
0179     if (hu > 0.01)
0180         tmpSize = i18n("Height: %1 %2", hu, m_pCanvas->doc()->unit().symbol());
0181     else
0182         tmpSize = i18n("Hide Row");
0183 
0184     if (!m_lSize) {
0185         int screenNo = QApplication::desktop()->screenNumber(this);
0186         m_lSize = new QLabel(QApplication::desktop()->screen(screenNo) , Qt::ToolTip);
0187         m_lSize->setAlignment(Qt::AlignVCenter);
0188         m_lSize->setAutoFillBackground(true);
0189         m_lSize->setPalette(QToolTip::palette());
0190         m_lSize->setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, m_lSize));
0191         m_lSize->setFrameShape(QFrame::Box);
0192         m_lSize->setIndent(1);
0193     }
0194 
0195     m_lSize->setText(tmpSize);
0196     m_lSize->adjustSize();
0197     QPoint pos = (sheet->layoutDirection() == Qt::RightToLeft) ? QPoint(m_pCanvas->width() - m_lSize->width() - 3, (int)y + 3) :
0198                  QPoint(3, (int)y + 3);
0199     pos -= QPoint(0, m_lSize->height());
0200     m_lSize->move(m_pCanvas->mapToGlobal(pos).x(), m_pCanvas->mapToGlobal(pos).y());
0201     m_lSize->show();
0202 }
0203 
0204 void RowHeaderWidget::removeSizeIndicator()
0205 {
0206     delete m_rubberband;
0207     m_rubberband = 0;
0208 }
0209 
0210 void RowHeaderWidget::updateRows(int from, int to)
0211 {
0212     register Sheet * const sheet = m_pCanvas->activeSheet();
0213     if (!sheet)
0214         return;
0215 
0216     double y0 = m_pCanvas->zoomHandler()->zoomItY(sheet->rowPosition(from));
0217     double y1 = m_pCanvas->zoomHandler()->zoomItY(sheet->rowPosition(to + 1));
0218     QWidget::update(0, (int) y0, QWidget::width(), (int)(y1 - y0));
0219 }
0220 
0221 void RowHeaderWidget::paintEvent(QPaintEvent* event)
0222 {
0223     QPainter painter(this);
0224     paint(&painter, event->rect());
0225 }
0226 
0227 
0228 void RowHeaderWidget::focusOutEvent(QFocusEvent * _ev)
0229 {
0230     focusOut(_ev);
0231 }
0232 
0233 void RowHeaderWidget::toolChanged(const QString& toolId)
0234 {
0235     doToolChanged(toolId);
0236 }
0237 
0238 /****************************************************************
0239  *
0240  * ColumnHeaderWidget
0241  *
0242  ****************************************************************/
0243 
0244 ColumnHeaderWidget::ColumnHeaderWidget(QWidget *_parent, Canvas *_canvas, View *_view)
0245         : QWidget(_parent), ColumnHeader(_canvas), m_rubberband(0)
0246 {
0247     setAttribute(Qt::WA_StaticContents);
0248     setMouseTracking(true);
0249 
0250     connect(_view, SIGNAL(autoScroll(QPoint)),
0251             this, SLOT(slotAutoScroll(QPoint)));
0252     connect(m_pCanvas->toolProxy(), SIGNAL(toolChanged(QString)),
0253             this, SLOT(toolChanged(QString)));
0254 }
0255 
0256 
0257 ColumnHeaderWidget::~ColumnHeaderWidget()
0258 {
0259 }
0260 
0261 void ColumnHeaderWidget::mousePressEvent(QMouseEvent * _ev)
0262 {
0263     KoPointerEvent pev(_ev, QPointF());
0264     mousePress(&pev);
0265 }
0266 
0267 void ColumnHeaderWidget::mouseReleaseEvent(QMouseEvent * _ev)
0268 {
0269     KoPointerEvent pev(_ev, QPointF());
0270     mouseRelease(&pev);
0271 }
0272 
0273 void ColumnHeaderWidget::mouseDoubleClickEvent(QMouseEvent * _ev)
0274 {
0275     KoPointerEvent pev(_ev, QPointF());
0276     mouseDoubleClick(&pev);
0277 }
0278 
0279 void ColumnHeaderWidget::mouseMoveEvent(QMouseEvent * _ev)
0280 {
0281     KoPointerEvent pev(_ev, QPointF());
0282     mouseMove(&pev);
0283 }
0284 
0285 void ColumnHeaderWidget::slotAutoScroll(const QPoint& scrollDistance)
0286 {
0287     // NOTE Stefan: This slot is triggered by the same signal as
0288     //              Canvas::slotAutoScroll and RowHeaderWidget::slotAutoScroll.
0289     //              Therefore, nothing has to be done except the scrolling was
0290     //              initiated in this header.
0291     if (!m_bMousePressed)
0292         return;
0293     if (scrollDistance.x() == 0)
0294         return;
0295     const QPoint offset = m_pCanvas->viewConverter()->documentToView(m_pCanvas->offset()).toPoint();
0296     if (offset.x() + scrollDistance.x() < 0)
0297         return;
0298     m_pCanvas->setDocumentOffset(offset + QPoint(scrollDistance.x(), 0));
0299     QMouseEvent event(QEvent::MouseMove, mapFromGlobal(QCursor::pos()),
0300                       Qt::NoButton, Qt::NoButton, QApplication::keyboardModifiers());
0301     QApplication::sendEvent(this, &event);
0302     m_pCanvas->update();
0303 }
0304 
0305 void ColumnHeaderWidget::wheelEvent(QWheelEvent* _ev)
0306 {
0307     QApplication::sendEvent(static_cast<Canvas*>(m_pCanvas), _ev);
0308 }
0309 
0310 void ColumnHeaderWidget::resizeEvent(QResizeEvent* _ev)
0311 {
0312     ColumnHeader::resize(_ev->size(), _ev->oldSize());
0313 }
0314 
0315 void ColumnHeaderWidget::paintSizeIndicator(int mouseX)
0316 {
0317     register Sheet * const sheet = m_pCanvas->activeSheet();
0318     if (!sheet)
0319         return;
0320 
0321     if (sheet->layoutDirection() == Qt::RightToLeft)
0322         m_iResizePos = mouseX + m_pCanvas->width() - QWidget::width();
0323     else
0324         m_iResizePos = mouseX;
0325 
0326     // Don't make the column have a width < 2 pixels.
0327     double x = m_pCanvas->zoomHandler()->zoomItX(sheet->columnPosition(m_iResizedColumn) - m_pCanvas->xOffset());
0328 
0329     if (sheet->layoutDirection() == Qt::RightToLeft) {
0330         x = m_pCanvas->width() - x;
0331 
0332         if (m_iResizePos > x - 2)
0333             m_iResizePos = (int) x;
0334     } else {
0335         if (m_iResizePos < x + 2)
0336             m_iResizePos = (int) x;
0337     }
0338 
0339     if (!m_rubberband) {
0340         m_rubberband = new QRubberBand(QRubberBand::Line, static_cast<Canvas*>(m_pCanvas));
0341         m_rubberband->setGeometry(m_iResizePos, 0, 2, m_pCanvas->height());
0342         m_rubberband->show();
0343     }
0344     m_rubberband->move(m_iResizePos, 0);
0345 
0346     QString tmpSize;
0347     double ww = m_pCanvas->zoomHandler()->unzoomItX((sheet->layoutDirection() == Qt::RightToLeft) ? x - m_iResizePos : m_iResizePos - x);
0348     double wu = m_pCanvas->doc()->unit().toUserValue(ww);
0349     if (wu > 0.01)
0350         tmpSize = i18n("Width: %1 %2", wu, m_pCanvas->doc()->unit().symbol());
0351     else
0352         tmpSize = i18n("Hide Column");
0353 
0354     if (!m_lSize) {
0355         int screenNo = QApplication::desktop()->screenNumber(this);
0356         m_lSize = new QLabel(QApplication::desktop()->screen(screenNo) , Qt::ToolTip);
0357         m_lSize->setAlignment(Qt::AlignVCenter);
0358         m_lSize->setAutoFillBackground(true);
0359         m_lSize->setPalette(QToolTip::palette());
0360         m_lSize->setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, m_lSize));
0361         m_lSize->setFrameShape(QFrame::Box);
0362         m_lSize->setIndent(1);
0363     }
0364 
0365     m_lSize->setText(tmpSize);
0366     m_lSize->adjustSize();
0367     QPoint pos = (sheet->layoutDirection() == Qt::RightToLeft) ? QPoint((int) x - 3 - m_lSize->width(), 3) :
0368                  QPoint((int) x + 3, 3);
0369     pos -= QPoint(0, m_lSize->height());
0370     m_lSize->move(m_pCanvas->mapToGlobal(pos).x(), mapToGlobal(pos).y());
0371     m_lSize->show();
0372 }
0373 
0374 void ColumnHeaderWidget::removeSizeIndicator()
0375 {
0376     delete m_rubberband;
0377     m_rubberband = 0;
0378 }
0379 
0380 void ColumnHeaderWidget::updateColumns(int from, int to)
0381 {
0382     register Sheet * const sheet = m_pCanvas->activeSheet();
0383     if (!sheet)
0384         return;
0385 
0386     double x0 = m_pCanvas->zoomHandler()->zoomItX(sheet->columnPosition(from));
0387     double x1 = m_pCanvas->zoomHandler()->zoomItX(sheet->columnPosition(to + 1));
0388     QWidget::update((int) x0, 0, (int)(x1 - x0), QWidget::height());
0389 }
0390 
0391 void ColumnHeaderWidget::paintEvent(QPaintEvent* event)
0392 {
0393     QPainter painter(this);
0394     paint(&painter, event->rect());
0395 }
0396 
0397 
0398 void ColumnHeaderWidget::focusOutEvent(QFocusEvent * _ev)
0399 {
0400     focusOut(_ev);
0401 }
0402 
0403 void ColumnHeaderWidget::toolChanged(const QString& toolId)
0404 {
0405     doToolChanged(toolId);
0406 }
0407 
0408 
0409 /****************************************************************
0410  *
0411  * SelectAllButtonWidget
0412  *
0413  ****************************************************************/
0414 
0415 SelectAllButtonWidget::SelectAllButtonWidget(CanvasBase* canvasBase)
0416         : QWidget(canvasBase->canvasWidget())
0417         , SelectAllButton(canvasBase)
0418 {
0419     connect(canvasBase->toolProxy(), SIGNAL(toolChanged(QString)),
0420             this, SLOT(toolChanged(QString)));
0421 }
0422 
0423 SelectAllButtonWidget::~SelectAllButtonWidget()
0424 {
0425 }
0426 
0427 void SelectAllButtonWidget::paintEvent(QPaintEvent* event)
0428 {
0429     QPainter painter(this);
0430     paint(&painter, event->rect());
0431 }
0432 
0433 void SelectAllButtonWidget::mousePressEvent(QMouseEvent* _ev)
0434 {
0435     KoPointerEvent pev(_ev, QPointF());
0436     mousePress(&pev);
0437 }
0438 
0439 void SelectAllButtonWidget::mouseReleaseEvent(QMouseEvent* _ev)
0440 {
0441     KoPointerEvent pev(_ev, QPointF());
0442     mouseRelease(&pev);
0443 }
0444 
0445 void SelectAllButtonWidget::wheelEvent(QWheelEvent* _ev)
0446 {
0447     QApplication::sendEvent(static_cast<Canvas*>(m_canvasBase), _ev);
0448 }
0449 
0450 void SelectAllButtonWidget::toolChanged(const QString& toolId)
0451 {
0452     doToolChanged(toolId);
0453 }