1 /* This file is part of the KDE project
2    Copyright 2006 Robert Knight <robertknight@gmail.com>
3    Copyright 2006 Inge Wallin <inge@lysator.liu.se>
4    Copyright 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
5    Copyright 1999-2002,2004 Laurent Montel <montel@kde.org>
6    Copyright 2002-2005 Ariya Hidayat <ariya@kde.org>
7    Copyright 1999-2004 David Faure <faure@kde.org>
8    Copyright 2004-2005 Meni Livne <livne@kde.org>
9    Copyright 2001-2003 Philipp Mueller <philipp.mueller@gmx.de>
10    Copyright 2002-2003 Norbert Andres <nandres@web.de>
11    Copyright 2003 Hamish Rodda <rodda@kde.org>
12    Copyright 2003 Joseph Wenninger <jowenn@kde.org>
13    Copyright 2003 Lukas Tinkl <lukas@kde.org>
14    Copyright 2000-2002 Werner Trobin <trobin@kde.org>
15    Copyright 2002 Harri Porten <porten@kde.org>
16    Copyright 2002 John Dailey <dailey@vt.edu>
17    Copyright 2002 Daniel Naber <daniel.naber@t-online.de>
18    Copyright 1999-2000 Torben Weis <weis@kde.org>
19    Copyright 1999-2000 Stephan Kulow <coolo@kde.org>
20    Copyright 2000 Bernd Wuebben <wuebben@kde.org>
21    Copyright 2000 Wilco Greven <greven@kde.org>
22    Copyright 2000 Simon Hausmann <hausmann@kde.org
23    Copyright 1999 Michael Reiher <michael.reiher@gmx.de>
24    Copyright 1999 Boris Wedl <boris.wedl@kfunigraz.ac.at>
25    Copyright 1999 Reginald Stadlbauer <reggie@kde.org>
26 
27    This library is free software; you can redistribute it and/or
28    modify it under the terms of the GNU Library General Public
29    License as published by the Free Software Foundation; either
30    version 2 of the License, or (at your option) any later version.
31 
32    This library is distributed in the hope that it will be useful,
33    but WITHOUT ANY WARRANTY; without even the implied warranty of
34    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
35    Library General Public License for more details.
36 
37    You should have received a copy of the GNU Library General Public License
38    along with this library; see the file COPYING.LIB.  If not, write to
39    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
40    Boston, MA 02110-1301, USA.
41 */
42 
43 // Local
44 #include "HeaderWidgets.h"
45 
46 // Qt
47 #include <QApplication>
48 #include <QDesktopWidget>
49 #include <QLabel>
50 #include <QPainter>
51 #include <QRubberBand>
52 #include <QStyle>
53 #include <QTextLayout>
54 #include <QToolTip>
55 #include <QScrollBar>
56 
57 // KF5
58 #include <KLocalizedString>
59 
60 // Calligra
61 #include <KoCanvasController.h>
62 #include <KoToolProxy.h>
63 #include <KoZoomHandler.h>
64 #include <KoPointerEvent.h>
65 #include <KoUnit.h>
66 
67 // Sheets
68 #include "Canvas.h"
69 #include "Cell.h"
70 #include "Doc.h"
71 #include "calligra_sheets_limits.h"
72 #include "RowColumnFormat.h"
73 #include "Sheet.h"
74 #include "View.h"
75 
76 // commands
77 #include "commands/RowColumnManipulators.h"
78 
79 // ui
80 #include "ui/Selection.h"
81 
82 using namespace Calligra::Sheets;
83 
84 /****************************************************************
85  *
86  * RowHeaderWidget
87  *
88  ****************************************************************/
89 
RowHeaderWidget(QWidget * _parent,Canvas * _canvas,View * _view)90 RowHeaderWidget::RowHeaderWidget(QWidget *_parent, Canvas *_canvas, View *_view)
91         : QWidget(_parent), RowHeader(_canvas), m_rubberband(0)
92 {
93     setAttribute(Qt::WA_StaticContents);
94     setMouseTracking(true);
95 
96     connect(_view, SIGNAL(autoScroll(QPoint)),
97             this, SLOT(slotAutoScroll(QPoint)));
98     connect(m_pCanvas->toolProxy(), SIGNAL(toolChanged(QString)),
99             this, SLOT(toolChanged(QString)));
100 }
101 
102 
~RowHeaderWidget()103 RowHeaderWidget::~RowHeaderWidget()
104 {
105 }
106 
mousePressEvent(QMouseEvent * _ev)107 void RowHeaderWidget::mousePressEvent(QMouseEvent * _ev)
108 {
109     KoPointerEvent pev(_ev, QPointF());
110     mousePress(&pev);
111 }
112 
mouseReleaseEvent(QMouseEvent * _ev)113 void RowHeaderWidget::mouseReleaseEvent(QMouseEvent * _ev)
114 {
115     KoPointerEvent pev(_ev, QPointF());
116     mouseRelease(&pev);
117 }
118 
mouseDoubleClickEvent(QMouseEvent * _ev)119 void RowHeaderWidget::mouseDoubleClickEvent(QMouseEvent * _ev)
120 {
121     KoPointerEvent pev(_ev, QPointF());
122     mouseDoubleClick(&pev);
123 }
124 
mouseMoveEvent(QMouseEvent * _ev)125 void RowHeaderWidget::mouseMoveEvent(QMouseEvent * _ev)
126 {
127     KoPointerEvent pev(_ev, QPointF());
128     mouseMove(&pev);
129 }
130 
slotAutoScroll(const QPoint & scrollDistance)131 void RowHeaderWidget::slotAutoScroll(const QPoint& scrollDistance)
132 {
133     // NOTE Stefan: This slot is triggered by the same signal as
134     //              Canvas::slotAutoScroll and ColumnHeaderWidget::slotAutoScroll.
135     //              Therefore, nothing has to be done except the scrolling was
136     //              initiated in this header.
137     if (!m_bMousePressed)
138         return;
139     if (scrollDistance.y() == 0)
140         return;
141     const QPoint offset = m_pCanvas->viewConverter()->documentToView(m_pCanvas->offset()).toPoint();
142     if (offset.y() + scrollDistance.y() < 0)
143         return;
144     m_pCanvas->setDocumentOffset(offset + QPoint(0, scrollDistance.y()));
145     QMouseEvent event(QEvent::MouseMove, mapFromGlobal(QCursor::pos()),
146                       Qt::NoButton, Qt::NoButton, QApplication::keyboardModifiers());
147     QApplication::sendEvent(this, &event);
148     m_pCanvas->update();
149 }
150 
wheelEvent(QWheelEvent * _ev)151 void RowHeaderWidget::wheelEvent(QWheelEvent* _ev)
152 {
153     QApplication::sendEvent(static_cast<Canvas*>(m_pCanvas), _ev);
154 }
155 
paintSizeIndicator(int mouseY)156 void RowHeaderWidget::paintSizeIndicator(int mouseY)
157 {
158     register Sheet * const sheet = m_pCanvas->activeSheet();
159     if (!sheet)
160         return;
161 
162     m_iResizePos = mouseY;
163 
164     // Don't make the row have a height < 2 pixel.
165     double y = m_pCanvas->zoomHandler()->zoomItY(sheet->rowPosition(m_iResizedRow) - m_pCanvas->yOffset());
166     if (m_iResizePos < y + 2)
167         m_iResizePos = (int) y;
168 
169     if (!m_rubberband) {
170         m_rubberband = new QRubberBand(QRubberBand::Line, static_cast<Canvas*>(m_pCanvas));
171         m_rubberband->setGeometry(0, m_iResizePos, m_pCanvas->width(), 2);
172         m_rubberband->show();
173     }
174     m_rubberband->move(0, m_iResizePos);
175 
176     QString tmpSize;
177     double hh = m_pCanvas->zoomHandler()->unzoomItY(m_iResizePos - y);
178     double hu = m_pCanvas->doc()->unit().toUserValue(hh);
179     if (hu > 0.01)
180         tmpSize = i18n("Height: %1 %2", hu, m_pCanvas->doc()->unit().symbol());
181     else
182         tmpSize = i18n("Hide Row");
183 
184     if (!m_lSize) {
185         int screenNo = QApplication::desktop()->screenNumber(this);
186         m_lSize = new QLabel(QApplication::desktop()->screen(screenNo) , Qt::ToolTip);
187         m_lSize->setAlignment(Qt::AlignVCenter);
188         m_lSize->setAutoFillBackground(true);
189         m_lSize->setPalette(QToolTip::palette());
190         m_lSize->setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, m_lSize));
191         m_lSize->setFrameShape(QFrame::Box);
192         m_lSize->setIndent(1);
193     }
194 
195     m_lSize->setText(tmpSize);
196     m_lSize->adjustSize();
197     QPoint pos = (sheet->layoutDirection() == Qt::RightToLeft) ? QPoint(m_pCanvas->width() - m_lSize->width() - 3, (int)y + 3) :
198                  QPoint(3, (int)y + 3);
199     pos -= QPoint(0, m_lSize->height());
200     m_lSize->move(m_pCanvas->mapToGlobal(pos).x(), m_pCanvas->mapToGlobal(pos).y());
201     m_lSize->show();
202 }
203 
removeSizeIndicator()204 void RowHeaderWidget::removeSizeIndicator()
205 {
206     delete m_rubberband;
207     m_rubberband = 0;
208 }
209 
updateRows(int from,int to)210 void RowHeaderWidget::updateRows(int from, int to)
211 {
212     register Sheet * const sheet = m_pCanvas->activeSheet();
213     if (!sheet)
214         return;
215 
216     double y0 = m_pCanvas->zoomHandler()->zoomItY(sheet->rowPosition(from));
217     double y1 = m_pCanvas->zoomHandler()->zoomItY(sheet->rowPosition(to + 1));
218     QWidget::update(0, (int) y0, QWidget::width(), (int)(y1 - y0));
219 }
220 
paintEvent(QPaintEvent * event)221 void RowHeaderWidget::paintEvent(QPaintEvent* event)
222 {
223     QPainter painter(this);
224     paint(&painter, event->rect());
225 }
226 
227 
focusOutEvent(QFocusEvent * _ev)228 void RowHeaderWidget::focusOutEvent(QFocusEvent * _ev)
229 {
230     focusOut(_ev);
231 }
232 
toolChanged(const QString & toolId)233 void RowHeaderWidget::toolChanged(const QString& toolId)
234 {
235     doToolChanged(toolId);
236 }
237 
238 /****************************************************************
239  *
240  * ColumnHeaderWidget
241  *
242  ****************************************************************/
243 
ColumnHeaderWidget(QWidget * _parent,Canvas * _canvas,View * _view)244 ColumnHeaderWidget::ColumnHeaderWidget(QWidget *_parent, Canvas *_canvas, View *_view)
245         : QWidget(_parent), ColumnHeader(_canvas), m_rubberband(0)
246 {
247     setAttribute(Qt::WA_StaticContents);
248     setMouseTracking(true);
249 
250     connect(_view, SIGNAL(autoScroll(QPoint)),
251             this, SLOT(slotAutoScroll(QPoint)));
252     connect(m_pCanvas->toolProxy(), SIGNAL(toolChanged(QString)),
253             this, SLOT(toolChanged(QString)));
254 }
255 
256 
~ColumnHeaderWidget()257 ColumnHeaderWidget::~ColumnHeaderWidget()
258 {
259 }
260 
mousePressEvent(QMouseEvent * _ev)261 void ColumnHeaderWidget::mousePressEvent(QMouseEvent * _ev)
262 {
263     KoPointerEvent pev(_ev, QPointF());
264     mousePress(&pev);
265 }
266 
mouseReleaseEvent(QMouseEvent * _ev)267 void ColumnHeaderWidget::mouseReleaseEvent(QMouseEvent * _ev)
268 {
269     KoPointerEvent pev(_ev, QPointF());
270     mouseRelease(&pev);
271 }
272 
mouseDoubleClickEvent(QMouseEvent * _ev)273 void ColumnHeaderWidget::mouseDoubleClickEvent(QMouseEvent * _ev)
274 {
275     KoPointerEvent pev(_ev, QPointF());
276     mouseDoubleClick(&pev);
277 }
278 
mouseMoveEvent(QMouseEvent * _ev)279 void ColumnHeaderWidget::mouseMoveEvent(QMouseEvent * _ev)
280 {
281     KoPointerEvent pev(_ev, QPointF());
282     mouseMove(&pev);
283 }
284 
slotAutoScroll(const QPoint & scrollDistance)285 void ColumnHeaderWidget::slotAutoScroll(const QPoint& scrollDistance)
286 {
287     // NOTE Stefan: This slot is triggered by the same signal as
288     //              Canvas::slotAutoScroll and RowHeaderWidget::slotAutoScroll.
289     //              Therefore, nothing has to be done except the scrolling was
290     //              initiated in this header.
291     if (!m_bMousePressed)
292         return;
293     if (scrollDistance.x() == 0)
294         return;
295     const QPoint offset = m_pCanvas->viewConverter()->documentToView(m_pCanvas->offset()).toPoint();
296     if (offset.x() + scrollDistance.x() < 0)
297         return;
298     m_pCanvas->setDocumentOffset(offset + QPoint(scrollDistance.x(), 0));
299     QMouseEvent event(QEvent::MouseMove, mapFromGlobal(QCursor::pos()),
300                       Qt::NoButton, Qt::NoButton, QApplication::keyboardModifiers());
301     QApplication::sendEvent(this, &event);
302     m_pCanvas->update();
303 }
304 
wheelEvent(QWheelEvent * _ev)305 void ColumnHeaderWidget::wheelEvent(QWheelEvent* _ev)
306 {
307     QApplication::sendEvent(static_cast<Canvas*>(m_pCanvas), _ev);
308 }
309 
resizeEvent(QResizeEvent * _ev)310 void ColumnHeaderWidget::resizeEvent(QResizeEvent* _ev)
311 {
312     ColumnHeader::resize(_ev->size(), _ev->oldSize());
313 }
314 
paintSizeIndicator(int mouseX)315 void ColumnHeaderWidget::paintSizeIndicator(int mouseX)
316 {
317     register Sheet * const sheet = m_pCanvas->activeSheet();
318     if (!sheet)
319         return;
320 
321     if (sheet->layoutDirection() == Qt::RightToLeft)
322         m_iResizePos = mouseX + m_pCanvas->width() - QWidget::width();
323     else
324         m_iResizePos = mouseX;
325 
326     // Don't make the column have a width < 2 pixels.
327     double x = m_pCanvas->zoomHandler()->zoomItX(sheet->columnPosition(m_iResizedColumn) - m_pCanvas->xOffset());
328 
329     if (sheet->layoutDirection() == Qt::RightToLeft) {
330         x = m_pCanvas->width() - x;
331 
332         if (m_iResizePos > x - 2)
333             m_iResizePos = (int) x;
334     } else {
335         if (m_iResizePos < x + 2)
336             m_iResizePos = (int) x;
337     }
338 
339     if (!m_rubberband) {
340         m_rubberband = new QRubberBand(QRubberBand::Line, static_cast<Canvas*>(m_pCanvas));
341         m_rubberband->setGeometry(m_iResizePos, 0, 2, m_pCanvas->height());
342         m_rubberband->show();
343     }
344     m_rubberband->move(m_iResizePos, 0);
345 
346     QString tmpSize;
347     double ww = m_pCanvas->zoomHandler()->unzoomItX((sheet->layoutDirection() == Qt::RightToLeft) ? x - m_iResizePos : m_iResizePos - x);
348     double wu = m_pCanvas->doc()->unit().toUserValue(ww);
349     if (wu > 0.01)
350         tmpSize = i18n("Width: %1 %2", wu, m_pCanvas->doc()->unit().symbol());
351     else
352         tmpSize = i18n("Hide Column");
353 
354     if (!m_lSize) {
355         int screenNo = QApplication::desktop()->screenNumber(this);
356         m_lSize = new QLabel(QApplication::desktop()->screen(screenNo) , Qt::ToolTip);
357         m_lSize->setAlignment(Qt::AlignVCenter);
358         m_lSize->setAutoFillBackground(true);
359         m_lSize->setPalette(QToolTip::palette());
360         m_lSize->setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, m_lSize));
361         m_lSize->setFrameShape(QFrame::Box);
362         m_lSize->setIndent(1);
363     }
364 
365     m_lSize->setText(tmpSize);
366     m_lSize->adjustSize();
367     QPoint pos = (sheet->layoutDirection() == Qt::RightToLeft) ? QPoint((int) x - 3 - m_lSize->width(), 3) :
368                  QPoint((int) x + 3, 3);
369     pos -= QPoint(0, m_lSize->height());
370     m_lSize->move(m_pCanvas->mapToGlobal(pos).x(), mapToGlobal(pos).y());
371     m_lSize->show();
372 }
373 
removeSizeIndicator()374 void ColumnHeaderWidget::removeSizeIndicator()
375 {
376     delete m_rubberband;
377     m_rubberband = 0;
378 }
379 
updateColumns(int from,int to)380 void ColumnHeaderWidget::updateColumns(int from, int to)
381 {
382     register Sheet * const sheet = m_pCanvas->activeSheet();
383     if (!sheet)
384         return;
385 
386     double x0 = m_pCanvas->zoomHandler()->zoomItX(sheet->columnPosition(from));
387     double x1 = m_pCanvas->zoomHandler()->zoomItX(sheet->columnPosition(to + 1));
388     QWidget::update((int) x0, 0, (int)(x1 - x0), QWidget::height());
389 }
390 
paintEvent(QPaintEvent * event)391 void ColumnHeaderWidget::paintEvent(QPaintEvent* event)
392 {
393     QPainter painter(this);
394     paint(&painter, event->rect());
395 }
396 
397 
focusOutEvent(QFocusEvent * _ev)398 void ColumnHeaderWidget::focusOutEvent(QFocusEvent * _ev)
399 {
400     focusOut(_ev);
401 }
402 
toolChanged(const QString & toolId)403 void ColumnHeaderWidget::toolChanged(const QString& toolId)
404 {
405     doToolChanged(toolId);
406 }
407 
408 
409 /****************************************************************
410  *
411  * SelectAllButtonWidget
412  *
413  ****************************************************************/
414 
SelectAllButtonWidget(CanvasBase * canvasBase)415 SelectAllButtonWidget::SelectAllButtonWidget(CanvasBase* canvasBase)
416         : QWidget(canvasBase->canvasWidget())
417         , SelectAllButton(canvasBase)
418 {
419     connect(canvasBase->toolProxy(), SIGNAL(toolChanged(QString)),
420             this, SLOT(toolChanged(QString)));
421 }
422 
~SelectAllButtonWidget()423 SelectAllButtonWidget::~SelectAllButtonWidget()
424 {
425 }
426 
paintEvent(QPaintEvent * event)427 void SelectAllButtonWidget::paintEvent(QPaintEvent* event)
428 {
429     QPainter painter(this);
430     paint(&painter, event->rect());
431 }
432 
mousePressEvent(QMouseEvent * _ev)433 void SelectAllButtonWidget::mousePressEvent(QMouseEvent* _ev)
434 {
435     KoPointerEvent pev(_ev, QPointF());
436     mousePress(&pev);
437 }
438 
mouseReleaseEvent(QMouseEvent * _ev)439 void SelectAllButtonWidget::mouseReleaseEvent(QMouseEvent* _ev)
440 {
441     KoPointerEvent pev(_ev, QPointF());
442     mouseRelease(&pev);
443 }
444 
wheelEvent(QWheelEvent * _ev)445 void SelectAllButtonWidget::wheelEvent(QWheelEvent* _ev)
446 {
447     QApplication::sendEvent(static_cast<Canvas*>(m_canvasBase), _ev);
448 }
449 
toolChanged(const QString & toolId)450 void SelectAllButtonWidget::toolChanged(const QString& toolId)
451 {
452     doToolChanged(toolId);
453 }
454