1 /*
2    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
3    Copyright (c) 2011 Martin Koller <kollix@aon.at>
4    All rights reserved.
5 
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9 
10    1. Redistributions of source code must retain the above copyright
11       notice, this list of conditions and the following disclaimer.
12    2. Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in the
14       documentation and/or other materials provided with the distribution.
15 
16    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 #define DEBUG_STATUS_BAR (DEBUG_KP_MAIN_WINDOW && 0)
29 
30 
31 #include "mainWindow/kpMainWindow.h"
32 #include "kpMainWindowPrivate.h"
33 
34 #include <QLabel>
35 #include <QStatusBar>
36 #include <QString>
37 
38 #include "kpLogCategories.h"
39 #include "kpDefs.h"
40 #include "document/kpDocument.h"
41 #include "tools/kpTool.h"
42 #include "views/manager/kpViewManager.h"
43 #include "kpViewScrollableContainer.h"
44 #include "views/kpZoomedView.h"
45 
46 #include <KSqueezedTextLabel>
47 #include <KLocalizedString>
48 
49 //---------------------------------------------------------------------
50 
51 // private
addPermanentStatusBarItem(int id,int maxTextLen)52 void kpMainWindow::addPermanentStatusBarItem (int id, int maxTextLen)
53 {
54     QStatusBar *sb = statusBar ();
55 
56     QLabel *label = new QLabel (sb);
57     label->setAlignment (Qt::AlignCenter);
58     label->setFixedHeight (label->fontMetrics ().height () + 2);
59     int maxWidth = label->fontMetrics().horizontalAdvance(QLatin1Char ('8')) * maxTextLen;
60     // add some margins
61     maxWidth += label->fontMetrics ().height ();
62     label->setFixedWidth (maxWidth);
63 
64     // Permanent --> place on the right
65     sb->addPermanentWidget (label);
66 
67     d->statusBarLabels.append (label);
68     Q_ASSERT (d->statusBarLabels.at(id) == label);
69 }
70 
71 //---------------------------------------------------------------------
72 
73 // private
createStatusBar()74 void kpMainWindow::createStatusBar ()
75 {
76     QStatusBar *sb = statusBar();
77 
78     // 9999 pixels "ought to be enough for anybody"
79     const int maxDimenLength = 4;
80 
81     d->statusBarMessageLabel = new KSqueezedTextLabel(sb);
82     // this is done to have the same height as the other labels in status bar; done like in kstatusbar.cpp
83     d->statusBarMessageLabel->setFixedHeight(d->statusBarMessageLabel->fontMetrics().height() + 2);
84     d->statusBarMessageLabel->setTextElideMode(Qt::ElideRight);  // this is the reason why we explicitly set a widget
85     sb->addWidget(d->statusBarMessageLabel, 1/*stretch*/);
86 
87     addPermanentStatusBarItem (StatusBarItemShapePoints,
88                                (maxDimenLength + 1/*,*/ + maxDimenLength) * 2 + 3/* - */);
89     addPermanentStatusBarItem (StatusBarItemShapeSize,
90                                (1/*+/-*/ + maxDimenLength) * 2 + 1/*x*/);
91 
92     QString numSample = i18n("%1 x %2", 5000, 5000);  // localized string; can e.g. be "5 000"
93     addPermanentStatusBarItem(StatusBarItemDocSize, numSample.length());
94 
95     addPermanentStatusBarItem(StatusBarItemDocDepth, 5/*XXbpp*/);
96 
97     addPermanentStatusBarItem (StatusBarItemZoom,
98                                5/*1600%*/);
99 
100     d->statusBarShapeLastPointsInitialised = false;
101     d->statusBarShapeLastSizeInitialised = false;
102     d->statusBarCreated = true;
103 }
104 
105 //---------------------------------------------------------------------
106 
107 // private slot
setStatusBarMessage(const QString & message)108 void kpMainWindow::setStatusBarMessage (const QString &message)
109 {
110 #if DEBUG_STATUS_BAR && 1
111     qCDebug(kpLogMainWindow) << "kpMainWindow::setStatusBarMessage("
112                << message
113                << ") ok=" << d->statusBarCreated;
114 #endif
115 
116     if (!d->statusBarCreated) {
117         return;
118     }
119 
120     d->statusBarMessageLabel->setText (message);
121 }
122 
123 //---------------------------------------------------------------------
124 
125 // private slot
setStatusBarShapePoints(const QPoint & startPoint,const QPoint & endPoint)126 void kpMainWindow::setStatusBarShapePoints (const QPoint &startPoint,
127                                             const QPoint &endPoint)
128 {
129 #if DEBUG_STATUS_BAR && 0
130     qCDebug(kpLogMainWindow) << "kpMainWindow::setStatusBarShapePoints("
131                << startPoint << "," << endPoint
132                << ") ok=" << d->statusBarCreated;
133 #endif
134 
135     if (!d->statusBarCreated) {
136         return;
137     }
138 
139     if (d->statusBarShapeLastPointsInitialised &&
140         startPoint == d->statusBarShapeLastStartPoint &&
141         endPoint == d->statusBarShapeLastEndPoint)
142     {
143     #if DEBUG_STATUS_BAR && 0
144         qCDebug(kpLogMainWindow) << "\tNOP";
145     #endif
146         return;
147     }
148 
149     QLabel *statusBarLabel = d->statusBarLabels.at (StatusBarItemShapePoints);
150     if (startPoint == KP_INVALID_POINT)
151     {
152         statusBarLabel->setText (QString());
153     }
154     else if (endPoint == KP_INVALID_POINT)
155     {
156         statusBarLabel->setText (i18n ("%1,%2",
157                                       startPoint.x (),
158                                       startPoint.y ()));
159     }
160     else
161     {
162         statusBarLabel->setText (i18n ("%1,%2 - %3,%4",
163                                       startPoint.x (),
164                                       startPoint.y (),
165                                       endPoint.x (),
166                                       endPoint.y ()));
167     }
168 
169     d->statusBarShapeLastStartPoint = startPoint;
170     d->statusBarShapeLastEndPoint = endPoint;
171     d->statusBarShapeLastPointsInitialised = true;
172 }
173 
174 //---------------------------------------------------------------------
175 
176 // private slot
setStatusBarShapeSize(const QSize & size)177 void kpMainWindow::setStatusBarShapeSize (const QSize &size)
178 {
179 #if DEBUG_STATUS_BAR && 0
180     qCDebug(kpLogMainWindow) << "kpMainWindow::setStatusBarShapeSize("
181                << size
182                << ") ok=" << d->statusBarCreated;
183 #endif
184 
185     if (!d->statusBarCreated) {
186         return;
187     }
188 
189     if (d->statusBarShapeLastSizeInitialised &&
190         size == d->statusBarShapeLastSize)
191     {
192     #if DEBUG_STATUS_BAR && 0
193         qCDebug(kpLogMainWindow) << "\tNOP";
194     #endif
195         return;
196     }
197 
198     QLabel *statusBarLabel = d->statusBarLabels.at (StatusBarItemShapeSize);
199     if (size == KP_INVALID_SIZE)
200     {
201         statusBarLabel->setText (QString());
202     }
203     else
204     {
205         statusBarLabel->setText (i18n ("%1x%2",
206                                       size.width (),
207                                       size.height ()));
208     }
209 
210     d->statusBarShapeLastSize = size;
211     d->statusBarShapeLastSizeInitialised = true;
212 }
213 
214 //---------------------------------------------------------------------
215 
216 // private slot
setStatusBarDocSize(const QSize & size)217 void kpMainWindow::setStatusBarDocSize (const QSize &size)
218 {
219 #if DEBUG_STATUS_BAR && 0
220     qCDebug(kpLogMainWindow) << "kpMainWindow::setStatusBarDocSize("
221                << size
222                << ") ok=" << d->statusBarCreated;
223 #endif
224 
225     if (!d->statusBarCreated) {
226         return;
227     }
228 
229     QLabel *statusBarLabel = d->statusBarLabels.at (StatusBarItemDocSize);
230     if (size == KP_INVALID_SIZE)
231     {
232         statusBarLabel->setText (QString());
233     }
234     else
235     {
236         statusBarLabel->setText (i18n ("%1 x %2",
237                                       size.width (),
238                                       size.height ()));
239     }
240 }
241 
242 //---------------------------------------------------------------------
243 
244 // private slot
setStatusBarDocDepth(int depth)245 void kpMainWindow::setStatusBarDocDepth (int depth)
246 {
247 #if DEBUG_STATUS_BAR && 0
248     qCDebug(kpLogMainWindow) << "kpMainWindow::setStatusBarDocDepth("
249                << depth
250                << ") ok=" << d->statusBarCreated;
251 #endif
252 
253     if (!d->statusBarCreated) {
254         return;
255     }
256 
257     QLabel *statusBarLabel = d->statusBarLabels.at (StatusBarItemDocDepth);
258     if (depth <= 0)
259     {
260         statusBarLabel->setText (QString());
261     }
262     else
263     {
264         statusBarLabel->setText (i18n ("%1bpp", depth));
265     }
266 }
267 
268 //---------------------------------------------------------------------
269 
270 // private slot
setStatusBarZoom(int zoom)271 void kpMainWindow::setStatusBarZoom (int zoom)
272 {
273 #if DEBUG_STATUS_BAR && 0
274     qCDebug(kpLogMainWindow) << "kpMainWindow::setStatusBarZoom("
275                << zoom
276                << ") ok=" << d->statusBarCreated;
277 #endif
278 
279     if (!d->statusBarCreated) {
280         return;
281     }
282 
283     QLabel *statusBarLabel = d->statusBarLabels.at (StatusBarItemZoom);
284     if (zoom <= 0)
285     {
286         statusBarLabel->setText (QString());
287     }
288     else
289     {
290         statusBarLabel->setText (i18n ("%1%", zoom));
291     }
292 }
293 
294 //---------------------------------------------------------------------
295 
recalculateStatusBarMessage()296 void kpMainWindow::recalculateStatusBarMessage ()
297 {
298 #if DEBUG_STATUS_BAR && 1
299     qCDebug(kpLogMainWindow) << "kpMainWindow::recalculateStatusBarMessage()";
300 #endif
301     QString scrollViewMessage = d->scrollView->statusMessage ();
302 #if DEBUG_STATUS_BAR && 1
303     qCDebug(kpLogMainWindow) << "\tscrollViewMessage=" << scrollViewMessage;
304     qCDebug(kpLogMainWindow) << "\tresizing doc? " << !d->scrollView->newDocSize ().isEmpty ();
305     qCDebug(kpLogMainWindow) << "\tviewUnderCursor? "
306                << (d->viewManager && d->viewManager->viewUnderCursor ());
307 #endif
308 
309     // HACK: To work around kpViewScrollableContainer's unreliable
310     //       status messages (which in turn is due to Qt not updating
311     //       QWidget::underMouse() on drags and we needing to hack around it)
312     if (!scrollViewMessage.isEmpty () &&
313         d->scrollView->newDocSize ().isEmpty () &&
314         d->viewManager && d->viewManager->viewUnderCursor ())
315     {
316     #if DEBUG_STATUS_BAR && 1
317         qCDebug(kpLogMainWindow) << "\t\tnot resizing & viewUnderCursor - message is wrong - clearing";
318     #endif
319         d->scrollView->blockSignals (true);
320         d->scrollView->clearStatusMessage ();
321         d->scrollView->blockSignals (false);
322 
323         scrollViewMessage.clear ();
324     #if DEBUG_STATUS_BAR && 1
325         qCDebug(kpLogMainWindow) << "\t\t\tdone";
326     #endif
327     }
328 
329     if (!scrollViewMessage.isEmpty ())
330     {
331         setStatusBarMessage (scrollViewMessage);
332     }
333     else
334     {
335         const kpTool *t = tool ();
336         if (t)
337         {
338             setStatusBarMessage (t->userMessage ());
339         }
340         else
341         {
342             setStatusBarMessage ();
343         }
344     }
345 }
346 
347 //---------------------------------------------------------------------
348 
349 // private slot
recalculateStatusBarShape()350 void kpMainWindow::recalculateStatusBarShape ()
351 {
352 #if DEBUG_STATUS_BAR && 0
353     qCDebug(kpLogMainWindow) << "kpMainWindow::recalculateStatusBarShape()";
354 #endif
355 
356     QSize docResizeTo = d->scrollView->newDocSize ();
357 #if DEBUG_STATUS_BAR && 0
358     qCDebug(kpLogMainWindow) << "\tdocResizeTo=" << docResizeTo;
359 #endif
360     if (docResizeTo.isValid ())
361     {
362         const QPoint startPoint (d->document->width (), d->document->height ());
363     #if DEBUG_STATUS_BAR && 0
364         qCDebug(kpLogMainWindow) << "\thavedMovedFromOrgSize="
365                    << d->scrollView->haveMovedFromOriginalDocSize ();
366     #endif
367         if (!d->scrollView->haveMovedFromOriginalDocSize ())
368         {
369             setStatusBarShapePoints (startPoint);
370             setStatusBarShapeSize ();
371         }
372         else
373         {
374             const int newWidth = docResizeTo.width ();
375             const int newHeight = docResizeTo.height ();
376 
377             setStatusBarShapePoints (startPoint, QPoint (newWidth, newHeight));
378             const QPoint sizeAsPoint (QPoint (newWidth, newHeight) - startPoint);
379             setStatusBarShapeSize (QSize (sizeAsPoint.x (), sizeAsPoint.y ()));
380         }
381     }
382     else
383     {
384         const kpTool *t = tool ();
385     #if DEBUG_STATUS_BAR && 0
386         qCDebug(kpLogMainWindow) << "\ttool=" << t;
387     #endif
388         if (t)
389         {
390             setStatusBarShapePoints (t->userShapeStartPoint (),
391                                      t->userShapeEndPoint ());
392             setStatusBarShapeSize (t->userShapeSize ());
393         }
394         else
395         {
396             setStatusBarShapePoints ();
397             setStatusBarShapeSize ();
398         }
399     }
400 }
401 
402 //---------------------------------------------------------------------
403 
404 // private slot
recalculateStatusBar()405 void kpMainWindow::recalculateStatusBar ()
406 {
407 #if DEBUG_STATUS_BAR && 1
408     qCDebug(kpLogMainWindow) << "kpMainWindow::recalculateStatusBar() ok="
409                << d->statusBarCreated;
410 #endif
411 
412     if (!d->statusBarCreated) {
413         return;
414     }
415 
416     recalculateStatusBarMessage ();
417     recalculateStatusBarShape ();
418 
419     if (d->document)
420     {
421         setStatusBarDocSize (QSize (d->document->width (), d->document->height ()));
422         setStatusBarDocDepth (d->document->image ().depth ());
423     }
424     else
425     {
426         setStatusBarDocSize ();
427         setStatusBarDocDepth ();
428     }
429 
430     if (d->mainView)
431     {
432         setStatusBarZoom (d->mainView->zoomLevelX ());
433     }
434     else
435     {
436         setStatusBarZoom ();
437     }
438 }
439 
440 //---------------------------------------------------------------------
441