1 /*
2  * Stellarium
3  * Copyright (C) 2008 Fabien Chereau
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #include "StelApp.hpp"
21 #include "StelCore.hpp"
22 #include "StelProjector.hpp"
23 
24 #include "StelUtils.hpp"
25 #include "SolarSystem.hpp"
26 #include "StelGuiItems.hpp"
27 #include "StelGui.hpp"
28 #include "StelLocaleMgr.hpp"
29 #include "StelLocation.hpp"
30 #include "StelMainView.hpp"
31 #include "StelMovementMgr.hpp"
32 #include "StelModuleMgr.hpp"
33 #include "StelActionMgr.hpp"
34 #include "StelProgressController.hpp"
35 #include "StelPropertyMgr.hpp"
36 #include "StelObserver.hpp"
37 #include "SkyGui.hpp"
38 #include "EphemWrapper.hpp"
39 
40 #include <QPainter>
41 #include <QGraphicsScene>
42 #include <QGraphicsView>
43 #include <QGraphicsLineItem>
44 #include <QRectF>
45 #include <QDebug>
46 #include <QGraphicsSceneMouseEvent>
47 #include <QGraphicsTextItem>
48 #include <QTimeLine>
49 #include <QMouseEvent>
50 #include <QPixmapCache>
51 #include <QProgressBar>
52 #include <QGraphicsWidget>
53 #include <QGraphicsProxyWidget>
54 #include <QGraphicsLinearLayout>
55 #include <QSettings>
56 #include <QGuiApplication>
57 
58 // Inspired by text-use-opengl-buffer branch: work around font problems in GUI buttons.
59 // May be useful in other broken OpenGL font situations. RasPi necessity as of 2016-03-26. Mesa 13 (2016-11) has finally fixed this on RasPi(VC4).
getTextPixmap(const QString & str,QFont font)60 QPixmap getTextPixmap(const QString& str, QFont font)
61 {
62 	// Render the text str into a QPixmap.
63 	QRect strRect = QFontMetrics(font).boundingRect(str);
64 	int w = strRect.width()+1+static_cast<int>(0.02f*strRect.width());
65 	int h = strRect.height();
66 
67 	QPixmap strPixmap(w, h);
68 	strPixmap.fill(Qt::transparent);
69 	QPainter painter(&strPixmap);
70 	font.setStyleStrategy(QFont::NoAntialias); // else: font problems on RasPi20160326
71 	painter.setFont(font);
72 	//painter.setRenderHints(QPainter::TextAntialiasing);
73 	painter.setPen(Qt::white);
74 	painter.drawText(-strRect.x(), -strRect.y(), str);
75 	return strPixmap;
76 }
77 
initCtor(const QPixmap & apixOn,const QPixmap & apixOff,const QPixmap & apixNoChange,const QPixmap & apixHover,StelAction * anAction,StelAction * otherAction,bool noBackground,bool isTristate)78 void StelButton::initCtor(const QPixmap& apixOn,
79                           const QPixmap& apixOff,
80                           const QPixmap& apixNoChange,
81                           const QPixmap& apixHover,
82 			  StelAction* anAction,
83 			  StelAction* otherAction,
84 			  bool noBackground,
85                           bool isTristate)
86 {
87 	pixOn = apixOn;
88 	pixOff = apixOff;
89 	pixHover = apixHover;
90 	pixNoChange = apixNoChange;
91 	noBckground = noBackground;
92 	isTristate_ = isTristate;
93 	opacity = 1.;
94 	hoverOpacity = 0.;
95 	action = anAction;
96 	secondAction = otherAction;
97 	checked = false;
98 	flagChangeFocus = false;
99 
100 	//Q_ASSERT(!pixOn.isNull());
101 	///Q_ASSERT(!pixOff.isNull());
102 
103 	if (isTristate_)
104 	{
105 		Q_ASSERT(!pixNoChange.isNull());
106 	}
107 
108 	setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
109 	setAcceptHoverEvents(true);
110 	timeLine = new QTimeLine(250, this);
111 	timeLine->setCurveShape(QTimeLine::EaseOutCurve);
112 	connect(timeLine, SIGNAL(valueChanged(qreal)),
113 	        this, SLOT(animValueChanged(qreal)));
114 	connect(&StelMainView::getInstance(), SIGNAL(updateIconsRequested()), this, SLOT(updateIcon()));  // Not sure if this is ever called?
115 	StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
116 	connect(gui, SIGNAL(flagUseButtonsBackgroundChanged(bool)), this, SLOT(updateIcon()));
117 
118 	if (action!=Q_NULLPTR)
119 	{
120 		if (action->isCheckable())
121 		{
122 			setChecked(action->isChecked());
123 			connect(action, SIGNAL(toggled(bool)), this, SLOT(setChecked(bool)));
124 			connect(this, SIGNAL(toggled(bool)), action, SLOT(setChecked(bool)));
125 		}
126 		else
127 		{
128 			QObject::connect(this, SIGNAL(triggered()), action, SLOT(trigger()));
129 		}
130 	}
131 	if (secondAction!=Q_NULLPTR)
132 	{
133 			QObject::connect(this, SIGNAL(triggeredRight()), secondAction, SLOT(trigger()));
134 	}
135 	else {
136 		setAcceptedMouseButtons(Qt::LeftButton);
137 	}
138 }
139 
StelButton(QGraphicsItem * parent,const QPixmap & pixOn,const QPixmap & pixOff,const QPixmap & pixHover,StelAction * action,bool noBackground,StelAction * otherAction)140 StelButton::StelButton(QGraphicsItem* parent,
141 		       const QPixmap& pixOn,
142 		       const QPixmap& pixOff,
143 		       const QPixmap& pixHover,
144 		       StelAction *action,
145 		       bool noBackground,
146 		       StelAction *otherAction) :
147 	QGraphicsPixmapItem(pixOff, parent)
148 {
149 	initCtor(pixOn, pixOff, QPixmap(), pixHover, action, otherAction, noBackground, false);
150 }
151 
StelButton(QGraphicsItem * parent,const QPixmap & pixOn,const QPixmap & pixOff,const QPixmap & pixNoChange,const QPixmap & pixHover,const QString & actionId,bool noBackground,bool isTristate)152 StelButton::StelButton(QGraphicsItem* parent,
153 		       const QPixmap& pixOn,
154 		       const QPixmap& pixOff,
155 		       const QPixmap& pixNoChange,
156 		       const QPixmap& pixHover,
157 		       const QString& actionId,
158 		       bool noBackground,
159 		       bool isTristate) :
160 	QGraphicsPixmapItem(pixOff, parent)
161 {
162 	StelAction *action = StelApp::getInstance().getStelActionManager()->findAction(actionId);
163 	initCtor(pixOn, pixOff, pixNoChange, pixHover, action, Q_NULLPTR, noBackground, isTristate);
164 }
165 
StelButton(QGraphicsItem * parent,const QPixmap & pixOn,const QPixmap & pixOff,const QPixmap & pixHover,const QString & actionId,bool noBackground,const QString & otherActionId)166 StelButton::StelButton(QGraphicsItem* parent,
167 		       const QPixmap& pixOn,
168 		       const QPixmap& pixOff,
169 		       const QPixmap& pixHover,
170 		       const QString& actionId,
171 		       bool noBackground,
172 		       const QString &otherActionId)
173 	:QGraphicsPixmapItem(pixOff, parent)
174 {
175 	StelAction *action = StelApp::getInstance().getStelActionManager()->findAction(actionId);
176 	StelAction *otherAction=Q_NULLPTR;
177 	if (otherActionId.length()>0)
178 		otherAction = StelApp::getInstance().getStelActionManager()->findAction(otherActionId);
179 
180 	initCtor(pixOn, pixOff, QPixmap(), pixHover, action, otherAction, noBackground, false);
181 }
182 
183 
toggleChecked(int checked)184 int StelButton::toggleChecked(int checked)
185 {
186 	if (!isTristate_)
187 		checked = !!!checked;
188 	else
189 	{
190 		if (++checked > ButtonStateNoChange)
191 			checked = ButtonStateOff;
192 	}
193 	return checked;
194 }
195 
hoverEnterEvent(QGraphicsSceneHoverEvent *)196 void StelButton::hoverEnterEvent(QGraphicsSceneHoverEvent*)
197 {
198 	timeLine->setDirection(QTimeLine::Forward);
199 	if (timeLine->state()!=QTimeLine::Running)
200 		timeLine->start();
201 
202 	emit(hoverChanged(true));
203 }
204 
hoverLeaveEvent(QGraphicsSceneHoverEvent *)205 void StelButton::hoverLeaveEvent(QGraphicsSceneHoverEvent*)
206 {
207 	timeLine->setDirection(QTimeLine::Backward);
208 	if (timeLine->state()!=QTimeLine::Running)
209 		timeLine->start();
210 	emit(hoverChanged(false));
211 }
212 
mousePressEvent(QGraphicsSceneMouseEvent * event)213 void StelButton::mousePressEvent(QGraphicsSceneMouseEvent* event)
214 {
215 	if (event->button()==Qt::LeftButton)
216 	{
217 		QGraphicsItem::mousePressEvent(event);
218 		event->accept();
219 		setChecked(toggleChecked(checked));
220 		if (!triggerOnRelease)
221 		{
222 			emit(toggled(checked));
223 			emit(triggered());
224 		}
225 	}
226 	else if  (event->button()==Qt::RightButton)
227 	{
228 		QGraphicsItem::mousePressEvent(event);
229 		event->accept();
230 		//setChecked(toggleChecked(checked));
231 		if (!triggerOnRelease)
232 		{
233 			//emit(toggled(checked));
234 			emit(triggeredRight());
235 		}
236 	}
237 }
238 
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)239 void StelButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
240 {
241 	if (event->button()==Qt::LeftButton)
242 	{
243 		if (action!=Q_NULLPTR && !action->isCheckable())
244 			setChecked(toggleChecked(checked));
245 
246 		if (flagChangeFocus) // true if button is on bottom bar
247 			StelMainView::getInstance().focusSky(); // Change the focus after clicking on button
248 		if (triggerOnRelease)
249 		{
250 			emit(toggled(checked));
251 			emit(triggered());
252 		}
253 	}
254 	else if  (event->button()==Qt::RightButton)
255 	{
256 		//if (flagChangeFocus) // true if button is on bottom bar
257 		//	StelMainView::getInstance().focusSky(); // Change the focus after clicking on button
258 		if (triggerOnRelease)
259 		{
260 			//emit(toggled(checked));
261 			emit(triggeredRight());
262 		}
263 	}
264 }
265 
updateIcon()266 void StelButton::updateIcon()
267 {
268 	if (opacity < 0.)
269 		opacity = 0;
270 	QPixmap pix(pixOn.size());
271 	pix.fill(QColor(0,0,0,0));
272 	QPainter painter(&pix);
273 	painter.setOpacity(opacity);
274 	if (!pixBackground.isNull() && noBckground==false && StelApp::getInstance().getStelPropertyManager()->getStelPropertyValue("StelGui.flagUseButtonsBackground").toBool())
275 		painter.drawPixmap(0, 0, pixBackground);
276 
277 	painter.drawPixmap(0, 0,
278 		(isTristate_ && checked == ButtonStateNoChange) ? (pixNoChange) :
279 		(checked == ButtonStateOn) ? (pixOn) :
280 		/* (checked == ButtonStateOff) ? */ (pixOff));
281 
282 	if (hoverOpacity > 0)
283 	{
284 		painter.setOpacity(hoverOpacity * opacity);
285 		painter.drawPixmap(0, 0, pixHover);
286 	}
287 	setPixmap(pix);
288 }
289 
animValueChanged(qreal value)290 void StelButton::animValueChanged(qreal value)
291 {
292 	hoverOpacity = value;
293 	updateIcon();
294 }
295 
setChecked(int b)296 void StelButton::setChecked(int b)
297 {
298 	checked=b;
299 	updateIcon();
300 }
301 
setBackgroundPixmap(const QPixmap & newBackground)302 void StelButton::setBackgroundPixmap(const QPixmap &newBackground)
303 {
304 	pixBackground = newBackground;
305 	updateIcon();
306 }
307 
LeftStelBar(QGraphicsItem * parent)308 LeftStelBar::LeftStelBar(QGraphicsItem* parent)
309 	: QGraphicsItem(parent)
310 	, hideTimeLine(Q_NULLPTR)
311 	, helpLabelPixmap(Q_NULLPTR)
312 {
313 	// Create the help label
314 	helpLabel = new QGraphicsSimpleTextItem("", this);
315 	helpLabel->setBrush(QBrush(QColor::fromRgbF(1,1,1,1)));
316 	if (qApp->property("text_texture")==true) // CLI option -t given?
317 		helpLabelPixmap=new QGraphicsPixmapItem(this);
318 }
319 
~LeftStelBar()320 LeftStelBar::~LeftStelBar()
321 {
322 	if (helpLabelPixmap) { delete helpLabelPixmap; helpLabelPixmap=Q_NULLPTR; }
323 }
324 
addButton(StelButton * button)325 void LeftStelBar::addButton(StelButton* button)
326 {
327 	double posY = 0;
328 	if (QGraphicsItem::childItems().size()!=0)
329 	{
330 		const QRectF& r = childrenBoundingRect();
331 		posY += r.bottom()-1;
332 	}
333 	button->setParentItem(this);
334 	button->setFocusOnSky(false);
335 	button->prepareGeometryChange(); // could possibly be removed when qt 4.6 become stable
336 	button->setPos(0., qRound(posY+10.5));
337 
338 	connect(button, SIGNAL(hoverChanged(bool)), this, SLOT(buttonHoverChanged(bool)));
339 }
340 
paint(QPainter *,const QStyleOptionGraphicsItem *,QWidget *)341 void LeftStelBar::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
342 {
343 }
344 
boundingRect() const345 QRectF LeftStelBar::boundingRect() const
346 {
347 	return childrenBoundingRect();
348 }
349 
boundingRectNoHelpLabel() const350 QRectF LeftStelBar::boundingRectNoHelpLabel() const
351 {
352 	// Re-use original Qt code, just remove the help label
353 	QRectF childRect;
354 	for (auto* child : QGraphicsItem::childItems())
355 	{
356 		if ((child==helpLabel) || (child==helpLabelPixmap))
357 			continue;
358 		QPointF childPos = child->pos();
359 		QTransform matrix = child->transform() * QTransform().translate(childPos.x(), childPos.y());
360 		childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
361 	}
362 	return childRect;
363 }
364 
365 
366 // Update the help label when a button is hovered
buttonHoverChanged(bool b)367 void LeftStelBar::buttonHoverChanged(bool b)
368 {
369 	StelButton* button = qobject_cast<StelButton*>(sender());
370 	Q_ASSERT(button);
371 	if (b==true)
372 	{
373 		if (button->action)
374 		{
375 			QString tip(button->action->getText());
376 			QString shortcut(button->action->getShortcut().toString(QKeySequence::NativeText));
377 			if (!shortcut.isEmpty())
378 			{
379 				//XXX: this should be unnecessary since we used NativeText.
380 				if (shortcut == "Space")
381 					shortcut = q_("Space");
382 				tip += "  [" + shortcut + "]";
383 			}
384 			helpLabel->setText(tip);
385 			helpLabel->setPos(qRound(boundingRectNoHelpLabel().width()+15.5),qRound(button->pos().y()+button->pixmap().size().height()/2-8));
386 			if (qApp->property("text_texture")==true)
387 			{
388 				helpLabel->setVisible(false);
389 				helpLabelPixmap->setPixmap(getTextPixmap(tip, helpLabel->font()));
390 				helpLabelPixmap->setPos(helpLabel->pos());
391 				helpLabelPixmap->setVisible(true);
392 			}
393 		}
394 	}
395 	else
396 	{
397 		helpLabel->setText("");
398 		if (qApp->property("text_texture")==true)
399 			helpLabelPixmap->setVisible(false);
400 	}
401 	// Update the screen as soon as possible.
402 	StelMainView::getInstance().thereWasAnEvent();
403 }
404 
405 // Set the pen for all the sub elements
setColor(const QColor & c)406 void LeftStelBar::setColor(const QColor& c)
407 {
408 	helpLabel->setBrush(c);
409 }
410 
BottomStelBar(QGraphicsItem * parent,const QPixmap & pixLeft,const QPixmap & pixRight,const QPixmap & pixMiddle,const QPixmap & pixSingle)411 BottomStelBar::BottomStelBar(QGraphicsItem* parent,
412                              const QPixmap& pixLeft,
413                              const QPixmap& pixRight,
414                              const QPixmap& pixMiddle,
415                              const QPixmap& pixSingle) :
416 	QGraphicsItem(parent),
417 	locationPixmap(Q_NULLPTR),
418 	datetimePixmap(Q_NULLPTR),
419 	fovPixmap(Q_NULLPTR),
420 	fpsPixmap(Q_NULLPTR),
421 	pixBackgroundLeft(pixLeft),
422 	pixBackgroundRight(pixRight),
423 	pixBackgroundMiddle(pixMiddle),
424 	pixBackgroundSingle(pixSingle),
425 	helpLabelPixmap(Q_NULLPTR)
426 {
427 	// The text is dummy just for testing
428 	datetime = new QGraphicsSimpleTextItem("2008-02-06  17:33", this);
429 	location = new QGraphicsSimpleTextItem("Munich, Earth, 500m", this);
430 	fov = new QGraphicsSimpleTextItem("FOV 43.45", this);
431 	fps = new QGraphicsSimpleTextItem("43.2 FPS", this);
432 	if (qApp->property("text_texture")==true) // CLI option -t given?
433 	{
434 		datetimePixmap=new QGraphicsPixmapItem(this);
435 		locationPixmap=new QGraphicsPixmapItem(this);
436 		fovPixmap=new QGraphicsPixmapItem(this);
437 		fpsPixmap=new QGraphicsPixmapItem(this);
438 		helpLabelPixmap=new QGraphicsPixmapItem(this);
439 	}
440 
441 	// Create the help label
442 	helpLabel = new QGraphicsSimpleTextItem("", this);
443 	helpLabel->setBrush(QBrush(QColor::fromRgbF(1,1,1,1)));
444 
445 	setColor(QColor::fromRgbF(1,1,1,1));
446 
447 	setFontSizeFromApp(StelApp::getInstance().getScreenFontSize());
448 	connect(&StelApp::getInstance(), SIGNAL(screenFontSizeChanged(int)), this, SLOT(setFontSizeFromApp(int)));
449 	connect(&StelApp::getInstance(), SIGNAL(fontChanged(QFont)), this, SLOT(setFont(QFont)));
450 
451 	QSettings* confSettings = StelApp::getInstance().getSettings();
452 	setFlagShowTime(confSettings->value("gui/flag_show_datetime", true).toBool());
453 	setFlagShowLocation(confSettings->value("gui/flag_show_location", true).toBool());
454 	setFlagShowFov(confSettings->value("gui/flag_show_fov", true).toBool());
455 	setFlagShowFps(confSettings->value("gui/flag_show_fps", true).toBool());
456 	setFlagTimeJd(confSettings->value("gui/flag_time_jd", false).toBool());
457 	setFlagFovDms(confSettings->value("gui/flag_fov_dms", false).toBool());
458 	setFlagShowTz(confSettings->value("gui/flag_show_tz", true).toBool());
459 }
460 
461 //! connect from StelApp to resize fonts on the fly.
setFontSizeFromApp(int size)462 void BottomStelBar::setFontSizeFromApp(int size)
463 {
464 	// Font size was developed based on base font size 13, i.e. 12
465 	int screenFontSize = size-1;
466 	QFont font=QGuiApplication::font();
467 	font.setPixelSize(screenFontSize);
468 	datetime->setFont(font);
469 	location->setFont(font);
470 	fov->setFont(font);
471 	fps->setFont(font);
472 	StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
473 	if (gui)
474 	{
475 		// to avoid crash
476 		SkyGui* skyGui=gui->getSkyGui();
477 		if (skyGui)
478 			skyGui->updateBarsPos();
479 	}
480 }
481 
482 //! connect from StelApp to resize fonts on the fly.
setFont(QFont font)483 void BottomStelBar::setFont(QFont font)
484 {
485 	font.setPixelSize(StelApp::getInstance().getScreenFontSize()-1);
486 	datetime->setFont(font);
487 	location->setFont(font);
488 	fov->setFont(font);
489 	fps->setFont(font);
490 	StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
491 	if (gui)
492 	{
493 		// to avoid crash
494 		SkyGui* skyGui=gui->getSkyGui();
495 		if (skyGui)
496 			skyGui->updateBarsPos();
497 	}
498 }
499 
~BottomStelBar()500 BottomStelBar::~BottomStelBar()
501 {
502 	// Remove currently hidden buttons which are not deleted by a parent element
503 	for (auto& group : buttonGroups)
504 	{
505 		for (auto* b : group.elems)
506 		{
507 			if (b->parentItem()==Q_NULLPTR)
508 			{
509 				delete b;
510 				b=Q_NULLPTR;
511 			}
512 		}
513 	}
514 	if (datetimePixmap) { delete datetimePixmap; datetimePixmap=Q_NULLPTR; }
515 	if (locationPixmap) { delete locationPixmap; locationPixmap=Q_NULLPTR; }
516 	if (fovPixmap) { delete fovPixmap; fovPixmap=Q_NULLPTR; }
517 	if (fpsPixmap) { delete fpsPixmap; fpsPixmap=Q_NULLPTR; }
518 	if (helpLabelPixmap) { delete helpLabelPixmap; helpLabelPixmap=Q_NULLPTR; }
519 }
520 
addButton(StelButton * button,const QString & groupName,const QString & beforeActionName)521 void BottomStelBar::addButton(StelButton* button, const QString& groupName, const QString& beforeActionName)
522 {
523 	QList<StelButton*>& g = buttonGroups[groupName].elems;
524 	bool done = false;
525 	for (int i=0; i<g.size(); ++i)
526 	{
527 		if (g[i]->action && g[i]->action->objectName()==beforeActionName)
528 		{
529 			g.insert(i, button);
530 			done = true;
531 			break;
532 		}
533 	}
534 	if (done == false)
535 		g.append(button);
536 
537 	button->setVisible(true);
538 	button->setParentItem(this);
539 	button->setFocusOnSky(true);
540 	updateButtonsGroups();
541 
542 	connect(button, SIGNAL(hoverChanged(bool)), this, SLOT(buttonHoverChanged(bool)));
543 	emit sizeChanged();
544 }
545 
hideButton(const QString & actionName)546 StelButton* BottomStelBar::hideButton(const QString& actionName)
547 {
548 	QString gName;
549 	StelButton* bToRemove = Q_NULLPTR;
550 	for (auto iter = buttonGroups.begin(); iter != buttonGroups.end(); ++iter)
551 	{
552 		int i=0;
553 		for (auto* b : iter.value().elems)
554 		{
555 			if (b->action && b->action->objectName()==actionName)
556 			{
557 				gName = iter.key();
558 				bToRemove = b;
559 				iter.value().elems.removeAt(i);
560 				break;
561 			}
562 			++i;
563 		}
564 	}
565 	if (bToRemove == Q_NULLPTR)
566 		return Q_NULLPTR;
567 	if (buttonGroups[gName].elems.size() == 0)
568 	{
569 		buttonGroups.remove(gName);
570 	}
571 	// Cannot really delete because some part of the GUI depend on the presence of some buttons
572 	// so just make invisible
573 	bToRemove->setParentItem(Q_NULLPTR);
574 	bToRemove->setVisible(false);
575 	updateButtonsGroups();
576 	emit sizeChanged();
577 	return bToRemove;
578 }
579 
580 // Set the margin at the left and right of a button group in pixels
setGroupMargin(const QString & groupName,int left,int right)581 void BottomStelBar::setGroupMargin(const QString& groupName, int left, int right)
582 {
583 	if (!buttonGroups.contains(groupName))
584 		return;
585 	buttonGroups[groupName].leftMargin = left;
586 	buttonGroups[groupName].rightMargin = right;
587 	updateButtonsGroups();
588 }
589 
590 //! Change the background of a group
setGroupBackground(const QString & groupName,const QPixmap & pixLeft,const QPixmap & pixRight,const QPixmap & pixMiddle,const QPixmap & pixSingle)591 void BottomStelBar::setGroupBackground(const QString& groupName,
592                                        const QPixmap& pixLeft,
593                                        const QPixmap& pixRight,
594                                        const QPixmap& pixMiddle,
595                                        const QPixmap& pixSingle)
596 {
597 	if (!buttonGroups.contains(groupName))
598 		return;
599 
600 	buttonGroups[groupName].pixBackgroundLeft = new QPixmap(pixLeft);
601 	buttonGroups[groupName].pixBackgroundRight = new QPixmap(pixRight);
602 	buttonGroups[groupName].pixBackgroundMiddle = new QPixmap(pixMiddle);
603 	buttonGroups[groupName].pixBackgroundSingle = new QPixmap(pixSingle);
604 	updateButtonsGroups();
605 }
606 
getButtonsBoundingRect() const607 QRectF BottomStelBar::getButtonsBoundingRect() const
608 {
609 	// Re-use original Qt code, just remove the help label
610 	QRectF childRect;
611 	bool hasBtn = false;
612 	for (auto* child : QGraphicsItem::childItems())
613 	{
614 		if (qgraphicsitem_cast<StelButton*>(child)==Q_NULLPTR)
615 			continue;
616 		hasBtn = true;
617 		QPointF childPos = child->pos();
618 		QTransform matrix = child->transform() * QTransform().translate(childPos.x(), childPos.y());
619 		childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
620 	}
621 
622 	if (hasBtn)
623 		return QRectF(0, 0, childRect.width()-1, childRect.height()-1);
624 	else
625 		return QRectF();
626 }
627 
updateButtonsGroups()628 void BottomStelBar::updateButtonsGroups()
629 {
630 	double x = 0;
631 	double y = datetime->boundingRect().height() + 3;
632 	for (auto& group : buttonGroups)
633 	{
634 		QList<StelButton*>& buttons = group.elems;
635 		if (buttons.empty())
636 			continue;
637 		x += group.leftMargin;
638 		int n = 0;
639 		for (auto* b : buttons)
640 		{
641 			// We check if the group has its own background if not the case
642 			// We apply a default background.
643 			if (n == 0)
644 			{
645 				if (buttons.size() == 1)
646 				{
647 					if (group.pixBackgroundSingle == Q_NULLPTR)
648 						b->setBackgroundPixmap(pixBackgroundSingle);
649 					else
650 						b->setBackgroundPixmap(*group.pixBackgroundSingle);
651 				}
652 				else
653 				{
654 					if (group.pixBackgroundLeft == Q_NULLPTR)
655 						b->setBackgroundPixmap(pixBackgroundLeft);
656 					else
657 						b->setBackgroundPixmap(*group.pixBackgroundLeft);
658 				}
659 			}
660 			else if (n == buttons.size()-1)
661 			{
662 				if (buttons.size() != 1)
663 				{
664 					if (group.pixBackgroundSingle == Q_NULLPTR)
665 						b->setBackgroundPixmap(pixBackgroundSingle);
666 					else
667 						b->setBackgroundPixmap(*group.pixBackgroundSingle);
668 				}
669 				if (group.pixBackgroundRight == Q_NULLPTR)
670 					b->setBackgroundPixmap(pixBackgroundRight);
671 				else
672 					b->setBackgroundPixmap(*group.pixBackgroundRight);
673 			}
674 			else
675 			{
676 				if (group.pixBackgroundMiddle == Q_NULLPTR)
677 					b->setBackgroundPixmap(pixBackgroundMiddle);
678 				else
679 					b->setBackgroundPixmap(*group.pixBackgroundMiddle);
680 			}
681 			// Update the button pixmap
682 			b->animValueChanged(0.);
683 			b->setPos(x, y);
684 			x += b->getButtonPixmapWidth();
685 			++n;
686 		}
687 		x+=group.rightMargin;
688 	}
689 	updateText(true);
690 }
691 
692 // create text elements and tooltips in bottom toolbar.
693 // Make sure to avoid any change if not necessary to avoid triggering useless redraw
updateText(bool updatePos)694 void BottomStelBar::updateText(bool updatePos)
695 {
696 	StelCore* core = StelApp::getInstance().getCore();
697 	const double jd = core->getJD();
698 	const double deltaT = core->getDeltaT();
699 	const double sigma = StelUtils::getDeltaTStandardError(jd);
700 	QString sigmaInfo = "";
701 	QString validRangeMarker = "";
702 	core->getCurrentDeltaTAlgorithmValidRangeDescription(jd, &validRangeMarker);
703 
704 	const StelLocaleMgr& locmgr = StelApp::getInstance().getLocaleMgr();
705 	QString tz = locmgr.getPrintableTimeZoneLocal(jd);
706 	QString newDateInfo = " ";
707 	if (getFlagShowTime())
708 	{
709 		if (getFlagShowTz())
710 			newDateInfo = QString("%1 %2 %3").arg(locmgr.getPrintableDateLocal(jd), locmgr.getPrintableTimeLocal(jd), tz);
711 		else
712 			newDateInfo = QString("%1 %2").arg(locmgr.getPrintableDateLocal(jd), locmgr.getPrintableTimeLocal(jd));
713 	}
714 	QString newDateAppx = QString("JD %1").arg(jd, 0, 'f', 5); // up to seconds
715 	if (getFlagTimeJd())
716 	{
717 		newDateAppx = newDateInfo;
718 		newDateInfo = QString("JD %1").arg(jd, 0, 'f', 5); // up to seconds
719 	}
720 
721 	QString planetName = core->getCurrentLocation().planetName;
722 	QString planetNameI18n;
723 	if (planetName=="SpaceShip") // Avoid crash
724 	{
725 		const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
726 		planetNameI18n = trans.qtranslate(planetName, "special celestial body"); // added context
727 	}
728 	else
729 		planetNameI18n = GETSTELMODULE(SolarSystem)->searchByEnglishName(planetName)->getNameI18n();
730 
731 	QString tzName = core->getCurrentTimeZone();
732 	if (tzName.contains("system_default") || (tzName.isEmpty() && planetName=="Earth"))
733 		tzName = q_("System default");
734 
735 	QString currTZ = QString("%1: %2").arg(q_("Time zone"), tzName);
736 
737 	if (tzName.contains("LMST") || tzName.contains("auto") || (planetName=="Earth" && jd<=StelCore::TZ_ERA_BEGINNING && !core->getUseCustomTimeZone()) )
738 		currTZ = q_("Local Mean Solar Time");
739 
740 	if (tzName.contains("LTST"))
741 		currTZ = q_("Local True Solar Time");
742 
743 	// TRANSLATORS: unit of measurement: minutes per second
744 	QString timeRateMU = qc_("min/s", "unit of measurement");
745 	double timeRate = qAbs(core->getTimeRate()/StelCore::JD_SECOND);
746 	double timeSpeed = timeRate/60.;
747 
748 	if (timeSpeed>=60.)
749 	{
750 		timeSpeed /= 60.;
751 		// TRANSLATORS: unit of measurement: hours per second
752 		timeRateMU = qc_("hr/s", "unit of measurement");
753 	}
754 	if (timeSpeed>=24.)
755 	{
756 		timeSpeed /= 24.;
757 		// TRANSLATORS: unit of measurement: days per second
758 		timeRateMU = qc_("d/s", "unit of measurement");
759 	}
760 	if (timeSpeed>=365.25)
761 	{
762 		timeSpeed /= 365.25;
763 		// TRANSLATORS: unit of measurement: years per second
764 		timeRateMU = qc_("yr/s", "unit of measurement");
765 	}
766 	QString timeRateInfo = QString("%1: x%2").arg(q_("Simulation speed"), QString::number(timeRate, 'f', 0));
767 	if (timeRate>60.)
768 		timeRateInfo = QString("%1: x%2 (%3 %4)").arg(q_("Simulation speed"), QString::number(timeRate, 'f', 0), QString::number(timeSpeed, 'f', 2), timeRateMU);
769 
770 	if (datetime->text()!=newDateInfo)
771 	{
772 		updatePos = true;
773 		datetime->setText(newDateInfo);
774 	}
775 
776 	if (core->getCurrentDeltaTAlgorithm()!=StelCore::WithoutCorrection)
777 	{
778 		if (sigma>0)
779 			sigmaInfo = QString("; %1(%2T) = %3s").arg(QChar(0x03c3)).arg(QChar(0x0394)).arg(sigma, 3, 'f', 1);
780 
781 		QString deltaTInfo = "";
782 		if (qAbs(deltaT)>60.)
783 			deltaTInfo = QString("%1 (%2s)%3").arg(StelUtils::hoursToHmsStr(deltaT/3600.)).arg(deltaT, 5, 'f', 2).arg(validRangeMarker);
784 		else
785 			deltaTInfo = QString("%1s%2").arg(deltaT, 3, 'f', 3).arg(validRangeMarker);
786 
787 		// the corrective ndot to be displayed could be set according to the currently used DeltaT algorithm.
788 		//float ndot=core->getDeltaTnDot();
789 		// or just to the used ephemeris. This has to be read as "Selected DeltaT formula used, but with the ephemeris's nDot applied it corrects DeltaT to..."
790 		const double ndot=( (EphemWrapper::use_de430(jd) || EphemWrapper::use_de431(jd) || EphemWrapper::use_de440(jd) || EphemWrapper::use_de441(jd)) ? -25.8 : -23.8946 );
791 
792 		datetime->setToolTip(QString("<p style='white-space:pre'>%1T = %2 [n%8 @ %3\"/cy%4%5]<br>%6<br>%7<br>%9</p>").arg(QChar(0x0394), deltaTInfo, QString::number(ndot, 'f', 4), QChar(0x00B2), sigmaInfo, newDateAppx, currTZ, QChar(0x2032), timeRateInfo));
793 	}
794 	else
795 		datetime->setToolTip(QString("<p style='white-space:pre'>%1<br>%2<br>%3</p>").arg(newDateAppx, currTZ, timeRateInfo));
796 
797 	if (qApp->property("text_texture")==true) // CLI option -t given?
798 	{
799 		datetime->setVisible(false); // hide normal thingy.
800 		datetimePixmap->setPixmap(getTextPixmap(newDateInfo, datetime->font()));
801 	}
802 
803 	// build location tooltip
804 	QString newLocation = "";
805 	if (getFlagShowLocation())
806 	{
807 		const StelLocation* loc = &core->getCurrentLocation();
808 		if(loc->name.isEmpty())
809 			newLocation = planetNameI18n +", "+StelUtils::decDegToDmsStr(loc->latitude)+", "+StelUtils::decDegToDmsStr(loc->longitude);
810 		else
811 		{
812 			if (loc->name.contains("->")) // a spaceship
813 				newLocation = QString("%1 [%2 %3]").arg(planetNameI18n, q_("flight"), loc->name);
814 			else
815 			{
816 				//TRANSLATORS: Unit of measure for distance - meter
817 				newLocation = planetNameI18n +", "+q_(loc->name) + ", "+ QString("%1 %2").arg(loc->altitude).arg(qc_("m", "distance"));
818 			}
819 		}
820 	}
821 	// TODO: When topocentric switch is toggled, this must be redrawn!
822 	if (location->text()!=newLocation)
823 	{
824 		updatePos = true;
825 		location->setText(newLocation);
826 		double lat = static_cast<double>(core->getCurrentLocation().latitude);
827 		double lon = static_cast<double>(core->getCurrentLocation().longitude);
828 		QString latStr, lonStr, pm;
829 		if (lat >= 0)
830 			pm = "N";
831 		else
832 		{
833 			pm = "S";
834 			lat *= -1;
835 		}
836 		latStr = QString("%1%2%3").arg(pm).arg(lat).arg(QChar(0x00B0));
837 		if (lon >= 0)
838 			pm = "E";
839 		else
840 		{
841 			pm = "W";
842 			lon *= -1;
843 		}
844 		lonStr = QString("%1%2%3").arg(pm).arg(lon).arg(QChar(0x00B0));
845 		QString rho, weather;
846 		if (core->getUseTopocentricCoordinates())
847 			rho = QString("%1 %2 %3").arg(q_("planetocentric distance")).arg(core->getCurrentObserver()->getDistanceFromCenter() * AU).arg(qc_("km", "distance"));
848 		else
849 			rho = q_("planetocentric observer");
850 
851 		if (newLocation.contains("->")) // a spaceship
852 			location->setToolTip(QString());
853 		else
854 		{
855 			if (core->getCurrentPlanet()->hasAtmosphere())
856 			{
857 				const StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
858 				weather = QString("%1: %2 %3; %4: %5 %6C").arg(q_("Atmospheric pressure"), QString::number(propMgr->getStelPropertyValue("StelSkyDrawer.atmospherePressure").toFloat(), 'f', 2), qc_("mbar", "pressure unit"), q_("temperature"), QString::number(propMgr->getStelPropertyValue("StelSkyDrawer.atmosphereTemperature").toFloat(), 'f', 1), QChar(0x00B0));
859 				location->setToolTip(QString("<p style='white-space:pre'>%1 %2; %3<br>%4</p>").arg(latStr, lonStr, rho, weather));
860 			}
861 			else
862 				location->setToolTip(QString("%1 %2; %3").arg(latStr, lonStr, rho));
863 		}
864 
865 		if (qApp->property("text_texture")==true) // CLI option -t given?
866 		{
867 			locationPixmap->setPixmap(getTextPixmap(newLocation, location->font()));
868 			location->setVisible(false);
869 		}
870 	}
871 
872 	QString str;
873 
874 	// build fov tooltip
875 	QTextStream wos(&str);
876 	// TRANSLATORS: Field of view. Please use abbreviation.
877 	QString fovstr = QString("%1 ").arg(qc_("FOV", "abbreviation"));
878 	if (getFlagFovDms())
879 	{
880 		wos << fovstr << StelUtils::decDegToDmsStr(core->getMovementMgr()->getCurrentFov());
881 	}
882 	else
883 	{
884 		wos << fovstr << qSetRealNumberPrecision(3) << core->getMovementMgr()->getCurrentFov() << QChar(0x00B0);
885 	}
886 
887 	if (fov->text()!=str)
888 	{
889 		updatePos = true;
890 		if (getFlagShowFov())
891 		{
892 			fov->setText(str);
893 			fov->setToolTip(q_("Field of view"));
894 			if (qApp->property("text_texture")==true) // CLI option -t given?
895 			{
896 				fovPixmap->setPixmap(getTextPixmap(str, fov->font()));
897 				fov->setVisible(false);
898 			}
899 		}
900 		else
901 		{
902 			fov->setText("");
903 			fov->setToolTip("");
904 		}
905 	}
906 
907 	str="";
908 
909 	// build fps tooltip
910 	QTextStream wos2(&str);
911 	// TRANSLATORS: Frames per second. Please use abbreviation.
912 	QString fpsstr = QString(" %1").arg(qc_("FPS", "abbreviation"));
913 	wos2 << qSetRealNumberPrecision(3) << StelApp::getInstance().getFps() << fpsstr;
914 	if (fps->text()!=str)
915 	{
916 		updatePos = true;
917 		if (getFlagShowFps())
918 		{
919 			fps->setText(str);
920 			fps->setToolTip(q_("Frames per second"));
921 			if (qApp->property("text_texture")==true) // CLI option -t given?
922 			{
923 				fpsPixmap->setPixmap(getTextPixmap(str, fps->font()));
924 				fps->setVisible(false);
925 			}
926 		}
927 		else
928 		{
929 			fps->setText("");
930 			fps->setToolTip("");
931 		}
932 	}
933 
934 	if (updatePos)
935 	{
936 		QFontMetrics fpsMetrics(fps->font());
937 		int fpsShift = fpsMetrics.boundingRect(fpsstr).width() + 50;
938 
939 		QFontMetrics fovMetrics(fov->font());
940 		int fovShift = fpsShift + fovMetrics.boundingRect(fovstr).width() + 80;
941 		if (getFlagFovDms())
942 			fovShift += 25;
943 
944 		QRectF rectCh = getButtonsBoundingRect();
945 		location->setPos(0, 0);
946 		int dtp = static_cast<int>(rectCh.right()-datetime->boundingRect().width())-5;
947 		if ((dtp%2) == 1) dtp--; // make even pixel
948 		datetime->setPos(dtp,0);
949 		fov->setPos(datetime->x()-fovShift, 0);
950 		fps->setPos(datetime->x()-fpsShift, 0);
951 		if (qApp->property("text_texture")==true) // CLI option -t given?
952 		{
953 			locationPixmap->setPos(0,0);
954 			int dtp = static_cast<int>(rectCh.right()-datetimePixmap->boundingRect().width())-5;
955 			if ((dtp%2) == 1) dtp--; // make even pixel
956 			datetimePixmap->setPos(dtp,0);
957 			fovPixmap->setPos(datetime->x()-fovShift, 0);
958 			fpsPixmap->setPos(datetime->x()-fpsShift, 0);
959 		}
960 	}
961 }
962 
paint(QPainter *,const QStyleOptionGraphicsItem *,QWidget *)963 void BottomStelBar::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
964 {
965 	updateText();
966 }
967 
boundingRect() const968 QRectF BottomStelBar::boundingRect() const
969 {
970 	if (QGraphicsItem::childItems().size()==0)
971 		return QRectF();
972 	const QRectF& r = childrenBoundingRect();
973 	return QRectF(0, 0, r.width()-1, r.height()-1);
974 }
975 
boundingRectNoHelpLabel() const976 QRectF BottomStelBar::boundingRectNoHelpLabel() const
977 {
978 	// Re-use original Qt code, just remove the help label
979 	QRectF childRect;
980 	for (auto* child : QGraphicsItem::childItems())
981 	{
982 		if ((child==helpLabel) || (child==helpLabelPixmap))
983 			continue;
984 		QPointF childPos = child->pos();
985 		QTransform matrix = child->transform() * QTransform().translate(childPos.x(), childPos.y());
986 		childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
987 	}
988 	return childRect;
989 }
990 
991 // Set the pen for all the sub elements
setColor(const QColor & c)992 void BottomStelBar::setColor(const QColor& c)
993 {
994 	datetime->setBrush(c);
995 	location->setBrush(c);
996 	fov->setBrush(c);
997 	fps->setBrush(c);
998 	helpLabel->setBrush(c);
999 }
1000 
1001 // Update the help label when a button is hovered
buttonHoverChanged(bool b)1002 void BottomStelBar::buttonHoverChanged(bool b)
1003 {
1004 	StelButton* button = qobject_cast<StelButton*>(sender());
1005 	Q_ASSERT(button);
1006 	if (b==true)
1007 	{
1008 		StelAction* action = button->action;
1009 		if (action)
1010 		{
1011 			QString tip(action->getText());
1012 			QString shortcut(action->getShortcut().toString(QKeySequence::NativeText));
1013 			if (!shortcut.isEmpty())
1014 			{
1015 				//XXX: this should be unnecessary since we used NativeText.
1016 				if (shortcut == "Space")
1017 					shortcut = q_("Space");
1018 				tip += "  [" + shortcut + "]";
1019 			}
1020 			helpLabel->setText(tip);
1021 			//helpLabel->setPos(button->pos().x()+button->pixmap().size().width()/2,-27);
1022 			helpLabel->setPos(20,-27);
1023 			if (qApp->property("text_texture")==true)
1024 			{
1025 				helpLabel->setVisible(false);
1026 				helpLabelPixmap->setPixmap(getTextPixmap(tip, helpLabel->font()));
1027 				helpLabelPixmap->setPos(helpLabel->pos());
1028 				helpLabelPixmap->setVisible(true);
1029 			}
1030 		}
1031 	}
1032 	else
1033 	{
1034 		helpLabel->setText("");
1035 		if (qApp->property("text_texture")==true)
1036 			helpLabelPixmap->setVisible(false);
1037 	}
1038 	// Update the screen as soon as possible.
1039 	StelMainView::getInstance().thereWasAnEvent();
1040 }
1041 
StelBarsPath(QGraphicsItem * parent)1042 StelBarsPath::StelBarsPath(QGraphicsItem* parent) : QGraphicsPathItem(parent), roundSize(6)
1043 {
1044 	QPen aPen(QColor::fromRgbF(0.7,0.7,0.7,0.5));
1045 	aPen.setWidthF(1.);
1046 	setBrush(QBrush(QColor::fromRgbF(0.22, 0.22, 0.23, 0.2)));
1047 	setPen(aPen);
1048 }
1049 
updatePath(BottomStelBar * bot,LeftStelBar * lef)1050 void StelBarsPath::updatePath(BottomStelBar* bot, LeftStelBar* lef)
1051 {
1052 	QPainterPath newPath;
1053 	QPointF p = lef->pos();
1054 	QRectF r = lef->boundingRectNoHelpLabel();
1055 	QPointF p2 = bot->pos();
1056 	QRectF r2 = bot->boundingRectNoHelpLabel();
1057 
1058 	newPath.moveTo(p.x()-roundSize, p.y()-roundSize);
1059 	newPath.lineTo(p.x()+r.width(),p.y()-roundSize);
1060 	newPath.arcTo(p.x()+r.width()-roundSize, p.y()-roundSize, 2.*roundSize, 2.*roundSize, 90, -90);
1061 	newPath.lineTo(p.x()+r.width()+roundSize, p2.y()-roundSize);
1062 	newPath.lineTo(p2.x()+r2.width(),p2.y()-roundSize);
1063 	newPath.arcTo(p2.x()+r2.width()-roundSize, p2.y()-roundSize, 2.*roundSize, 2.*roundSize, 90, -90);
1064 	newPath.lineTo(p2.x()+r2.width()+roundSize, p2.y()+r2.height()+roundSize);
1065 	newPath.lineTo(p.x()-roundSize, p2.y()+r2.height()+roundSize);
1066 	setPath(newPath);
1067 }
1068 
setBackgroundOpacity(double opacity)1069 void StelBarsPath::setBackgroundOpacity(double opacity)
1070 {
1071 	setBrush(QBrush(QColor::fromRgbF(0.22, 0.22, 0.23, opacity)));
1072 }
1073 
StelProgressBarMgr(QGraphicsItem * parent)1074 StelProgressBarMgr::StelProgressBarMgr(QGraphicsItem* parent):
1075 	QGraphicsWidget(parent)
1076 {
1077 	setLayout(new QGraphicsLinearLayout(Qt::Vertical));
1078 }
1079 /*
1080 QRectF StelProgressBarMgr::boundingRect() const
1081 {
1082 	if (QGraphicsItem::children().size()==0)
1083 		return QRectF();
1084 	const QRectF& r = childrenBoundingRect();
1085 	return QRectF(0, 0, r.width()-1, r.height()-1);
1086 }*/
1087 
addProgressBar(const StelProgressController * p)1088 void StelProgressBarMgr::addProgressBar(const StelProgressController* p)
1089 {
1090 	StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
1091 	QProgressBar* pb = new QProgressBar();
1092 	pb->setFixedHeight(25);
1093 	pb->setFixedWidth(200);
1094 	pb->setTextVisible(true);
1095 	pb->setValue(p->getValue());
1096 	pb->setMinimum(p->getMin());
1097 	pb->setMaximum(p->getMax());
1098 	pb->setFormat(p->getFormat());
1099 	if (gui!=Q_NULLPTR)
1100 		pb->setStyleSheet(gui->getStelStyle().qtStyleSheet);
1101 	QGraphicsProxyWidget* pbProxy = new QGraphicsProxyWidget();
1102 	pbProxy->setWidget(pb);
1103 	pbProxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
1104 	pbProxy->setZValue(150);
1105 	static_cast<QGraphicsLinearLayout*>(layout())->addItem(pbProxy);
1106 	allBars.insert(p, pb);
1107 	pb->setVisible(true);
1108 
1109 	connect(p, SIGNAL(changed()), this, SLOT(oneBarChanged()));
1110 }
1111 
removeProgressBar(const StelProgressController * p)1112 void StelProgressBarMgr::removeProgressBar(const StelProgressController *p)
1113 {
1114 	QProgressBar* pb = allBars[p];
1115 	pb->deleteLater();
1116 	allBars.remove(p);
1117 }
1118 
oneBarChanged()1119 void StelProgressBarMgr::oneBarChanged()
1120 {
1121 	const StelProgressController *p = static_cast<StelProgressController*>(QObject::sender());
1122 	QProgressBar* pb = allBars[p];
1123 	pb->setValue(p->getValue());
1124 	pb->setMinimum(p->getMin());
1125 	pb->setMaximum(p->getMax());
1126 	pb->setFormat(p->getFormat());
1127 }
1128 
CornerButtons(QGraphicsItem * parent)1129 CornerButtons::CornerButtons(QGraphicsItem* parent) :
1130 	QGraphicsItem(parent),
1131 	lastOpacity(10)
1132 {
1133 }
1134 
paint(QPainter *,const QStyleOptionGraphicsItem *,QWidget *)1135 void CornerButtons::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
1136 {
1137 	// Do nothing. Just paint the child widgets
1138 }
1139 
boundingRect() const1140 QRectF CornerButtons::boundingRect() const
1141 {
1142 	if (QGraphicsItem::childItems().size()==0)
1143 		return QRectF();
1144 	const QRectF& r = childrenBoundingRect();
1145 	return QRectF(0, 0, r.width()-1, r.height()-1);
1146 }
1147 
setOpacity(double opacity)1148 void CornerButtons::setOpacity(double opacity)
1149 {
1150 	if (opacity<=0. && lastOpacity<=0.)
1151 		return;
1152 	lastOpacity = opacity;
1153 	if (QGraphicsItem::childItems().size()==0)
1154 		return;
1155 	for (auto* child : QGraphicsItem::childItems())
1156 	{
1157 		StelButton* sb = qgraphicsitem_cast<StelButton*>(child);
1158 		Q_ASSERT(sb!=Q_NULLPTR);
1159 		sb->setOpacity(opacity);
1160 	}
1161 }
1162