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