• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 13258187680

11 Feb 2025 07:50AM UTC coverage: 12.127% (+0.03%) from 12.101%
13258187680

Pull #3751

github

10110111
converter: fix a crash
Pull Request #3751: Switch skycultures to the new format

14613 of 120497 relevant lines covered (12.13%)

18620.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/gui/StelGuiItems.cpp
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

23
#include "StelUtils.hpp"
24
#include "SolarSystem.hpp"
25
#include "StelGuiItems.hpp"
26
#include "StelGui.hpp"
27
#include "StelLocaleMgr.hpp"
28
#include "StelLocation.hpp"
29
#include "StelMainView.hpp"
30
#include "StelMovementMgr.hpp"
31
#include "StelModuleMgr.hpp"
32
#include "StelActionMgr.hpp"
33
#include "StelProgressController.hpp"
34
#include "StelPropertyMgr.hpp"
35
#include "StelObserver.hpp"
36
#include "SkyGui.hpp"
37
#include "EphemWrapper.hpp"
38

39
#include <QPainter>
40
#include <QGraphicsScene>
41
#include <QGraphicsView>
42
#include <QGraphicsLineItem>
43
#include <QRectF>
44
#include <QDebug>
45
#include <QScreen>
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
namespace
59
{
60

61
void brightenImage(QImage &img, float factor)
×
62
{
63
        for (int y=0; y<img.height(); y++)
×
64
                for (int x=0; x<img.width(); x++)
×
65
                {
66
                        QColor col=img.pixelColor(x, y);
×
67
#if (QT_VERSION<QT_VERSION_CHECK(6,0,0))
68
                        qreal h, s, v, a;
69
#else
70
                        float h, s, v, a;
71
#endif
72
                        col.getHsvF(&h, &s, &v, &a);
×
73
                        v*=factor; // increase brightness.
×
74
#if (QT_VERSION<QT_VERSION_CHECK(6,0,0))
75
                        v=qBound(0., v, 1.);
76
#else
77
                        v=qBound(0.f, v, 1.f);
×
78
#endif
79
                        col.setHsvF(h, s, v, a);
×
80
                        img.setPixelColor(x, y, col);
×
81
                }
82
}
×
83

84
}
85

86
void StelButton::initCtor(const QPixmap& apixOn,
×
87
                                                  const QPixmap& apixOff,
88
                                                  const QPixmap& apixNoChange,
89
                                                  const QPixmap& apixHover,
90
                                                  StelAction* anAction,
91
                                                  StelAction* otherAction,
92
                                                  bool noBackground,
93
                                                  bool isTristate)
94
{
95
        // Allow a much-wanted brightness tweak, at least manually configured.
96
        const float brightenFactor=qBound(1.f, StelApp::getInstance().getSettings()->value("gui/pixmaps_brightness", 1.0).toFloat(), 1.8f);
×
97
        QImage pixOnImg=apixOn.toImage();
×
98
        QImage pixOffImg=apixOff.toImage();
×
99
        QImage pixHoverImg=apixHover.toImage();
×
100
        QImage pixNoChangeImg=apixNoChange.toImage();
×
101
        brightenImage(pixOnImg, brightenFactor);
×
102
        brightenImage(pixOffImg, brightenFactor);
×
103
        brightenImage(pixHoverImg, brightenFactor);
×
104
        brightenImage(pixNoChangeImg, brightenFactor);
×
105
        pixOn = QPixmap::fromImage(pixOnImg);
×
106
        pixOff = QPixmap::fromImage(pixOffImg);
×
107
        pixHover = QPixmap::fromImage(pixHoverImg);
×
108
        pixNoChange = QPixmap::fromImage(pixNoChangeImg);
×
109

110
        if(!pixmapsScale)
×
111
        {
112
                pixmapsScale = StelApp::getInstance().getSettings()->value("gui/pixmaps_scale", GUI_INPUT_PIXMAPS_SCALE).toDouble();
×
113
        }
114
        if(pixmapsScale != GUI_INPUT_PIXMAPS_SCALE)
×
115
        {
116
                const auto scale = pixmapsScale/GUI_INPUT_PIXMAPS_SCALE;
×
117
                pixOn = pixOn.scaled(pixOn.size()*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
×
118
                pixOff = pixOff.scaled(pixOff.size()*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
×
119
                if(!pixHover.isNull())
×
120
                        pixHover = pixHover.scaled(pixHover.size()*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
×
121
                if(!pixNoChange.isNull())
×
122
                        pixNoChange = pixNoChange.scaled(pixNoChange.size()*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
×
123
        }
124
        pixOn.setDevicePixelRatio(pixmapsScale);
×
125
        pixOff.setDevicePixelRatio(pixmapsScale);
×
126
        pixHover.setDevicePixelRatio(pixmapsScale);
×
127
        pixNoChange.setDevicePixelRatio(pixmapsScale);
×
128

129
        noBckground = noBackground;
×
130
        isTristate_ = isTristate;
×
131
        opacity = 1.;
×
132
        hoverOpacity = 0.;
×
133
        action = anAction;
×
134
        secondAction = otherAction;
×
135
        checked = false;
×
136
        flagChangeFocus = false;
×
137

138
        //Q_ASSERT(!pixOn.isNull());
139
        ///Q_ASSERT(!pixOff.isNull());
140

141
        if (isTristate_)
×
142
        {
143
                Q_ASSERT(!pixNoChange.isNull());
×
144
        }
145

146
        setShapeMode(QGraphicsPixmapItem::BoundingRectShape);        
×
147
        setAcceptHoverEvents(true);
×
148
        timeLine = new QTimeLine(250, this);
×
149
        timeLine->setEasingCurve(QEasingCurve(QEasingCurve::OutCurve));
×
150
        connect(timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
×
151
        connect(&StelMainView::getInstance(), SIGNAL(updateIconsRequested()), this, SLOT(updateIcon()));  // Not sure if this is ever called?
×
152
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
153
        connect(gui, SIGNAL(flagUseButtonsBackgroundChanged(bool)), this, SLOT(updateIcon()));
×
154

155
        if (action!=nullptr)
×
156
        {
157
                if (action->isCheckable())
×
158
                {
159
                        setChecked(action->isChecked());
×
160
                        connect(action, SIGNAL(toggled(bool)), this, SLOT(setChecked(bool)));
×
161
                        connect(this, SIGNAL(toggled(bool)), action, SLOT(setChecked(bool)));
×
162
                }
163
                else
164
                {
165
                        QObject::connect(this, SIGNAL(triggered()), action, SLOT(trigger()));
×
166
                }
167
        }
168
        if (secondAction!=nullptr)
×
169
        {
170
                        QObject::connect(this, SIGNAL(triggeredRight()), secondAction, SLOT(trigger()));
×
171
        }
172
        else {
173
                setAcceptedMouseButtons(Qt::LeftButton);
×
174
        }
175
}
×
176

177
StelButton::StelButton(QGraphicsItem* parent,
×
178
                                           const QPixmap& pixOn,
179
                                           const QPixmap& pixOff,
180
                                           const QPixmap& pixHover,
181
                                           StelAction *action,
182
                                           bool noBackground,
183
                                           StelAction *otherAction)
×
184
        : QGraphicsPixmapItem(pixOff, parent)
×
185
{
186
        initCtor(pixOn, pixOff, QPixmap(), pixHover, action, otherAction, noBackground, false);
×
187
}
×
188

189
StelButton::StelButton(QGraphicsItem* parent,
×
190
                                           const QPixmap& pixOn,
191
                                           const QPixmap& pixOff,
192
                                           const QPixmap& pixNoChange,
193
                                           const QPixmap& pixHover,
194
                                           const QString& actionId,
195
                                           bool noBackground,
196
                                           bool isTristate)
×
197
        : QGraphicsPixmapItem(pixOff, parent)
×
198
{
199
        StelAction *action = StelApp::getInstance().getStelActionManager()->findAction(actionId);
×
200
        if (!actionId.isEmpty() && !action)
×
201
                qWarning() << "Couldn't find action" << actionId;
×
202
        initCtor(pixOn, pixOff, pixNoChange, pixHover, action, nullptr, noBackground, isTristate);
×
203
}
×
204

205
StelButton::StelButton(QGraphicsItem* parent,
×
206
                                           const QPixmap& pixOn,
207
                                           const QPixmap& pixOff,
208
                                           const QPixmap& pixHover,
209
                                           const QString& actionId,
210
                                           bool noBackground,
211
                                           const QString &otherActionId)
×
212
        : QGraphicsPixmapItem(pixOff, parent)
×
213
{
214
        StelAction *action = StelApp::getInstance().getStelActionManager()->findAction(actionId);
×
215
        if (!actionId.isEmpty() && !action)
×
216
                qWarning() << "Couldn't find action" << actionId;
×
217
        StelAction *otherAction=nullptr;
×
218
        if (!otherActionId.isEmpty())
×
219
                otherAction = StelApp::getInstance().getStelActionManager()->findAction(otherActionId);
×
220

221
        initCtor(pixOn, pixOff, QPixmap(), pixHover, action, otherAction, noBackground, false);
×
222
}
×
223

224

225
int StelButton::toggleChecked(int checked)
×
226
{
227
        if (!isTristate_)
×
228
                checked = !!!checked;
×
229
        else
230
        {
231
                if (++checked > ButtonStateNoChange)
×
232
                        checked = ButtonStateOff;
×
233
        }
234
        return checked;
×
235
}
236

237
void StelButton::hoverEnterEvent(QGraphicsSceneHoverEvent*)
×
238
{
239
        timeLine->setDirection(QTimeLine::Forward);
×
240
        if (timeLine->state()!=QTimeLine::Running)
×
241
                timeLine->start();
×
242

243
        emit hoverChanged(true);
×
244
}
×
245

246
void StelButton::hoverLeaveEvent(QGraphicsSceneHoverEvent*)
×
247
{
248
        timeLine->setDirection(QTimeLine::Backward);
×
249
        if (timeLine->state()!=QTimeLine::Running)
×
250
                timeLine->start();
×
251
        emit hoverChanged(false);
×
252
}
×
253

254
void StelButton::mousePressEvent(QGraphicsSceneMouseEvent* event)
×
255
{
256
        if (event->button()==Qt::LeftButton)
×
257
        {
258
                QGraphicsItem::mousePressEvent(event);
×
259
                event->accept();
×
260
                setChecked(toggleChecked(checked));
×
261
                if (!triggerOnRelease)
×
262
                {
263
                        emit toggled(checked);
×
264
                        emit triggered();
×
265
                }
266
        }
267
        else if  (event->button()==Qt::RightButton)
×
268
        {
269
                QGraphicsItem::mousePressEvent(event);
×
270
                event->accept();
×
271
                //setChecked(toggleChecked(checked));
272
                if (!triggerOnRelease)
×
273
                {
274
                        //emit toggled(checked);
275
                        emit triggeredRight();
×
276
                }
277
        }
278
}
×
279

280
void StelButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
×
281
{
282
        if (event->button()==Qt::LeftButton)
×
283
        {
284
                if (action!=nullptr && !action->isCheckable())
×
285
                        setChecked(toggleChecked(checked));
×
286

287
                if (flagChangeFocus) // true if button is on bottom bar
×
288
                        StelMainView::getInstance().focusSky(); // Change the focus after clicking on button
×
289
                if (triggerOnRelease)
×
290
                {
291
                        emit toggled(checked);
×
292
                        emit triggered();
×
293
                }
294
        }
295
        else if  (event->button()==Qt::RightButton)
×
296
        {
297
                //if (flagChangeFocus) // true if button is on bottom bar
298
                //        StelMainView::getInstance().focusSky(); // Change the focus after clicking on button
299
                if (triggerOnRelease)
×
300
                {
301
                        //emit toggled(checked);
302
                        emit triggeredRight();
×
303
                }
304
        }
305
}
×
306

307
void StelButton::updateIcon()
×
308
{
309
        if (opacity < 0.)
×
310
                opacity = 0;
×
311
        QPixmap pix(pixOn.size());
×
312
        pix.setDevicePixelRatio(pixmapsScale);
×
313
        pix.fill(QColor(0,0,0,0));
×
314
        QPainter painter(&pix);
×
315
        painter.setOpacity(opacity);
×
316
        if (!pixBackground.isNull() && noBckground==false && StelApp::getInstance().getStelPropertyManager()->getStelPropertyValue("StelGui.flagUseButtonsBackground").toBool())
×
317
                painter.drawPixmap(0, 0, pixBackground);
×
318

319
        painter.drawPixmap(0, 0,
×
320
                (isTristate_ && checked == ButtonStateNoChange) ? (pixNoChange) :
×
321
                (checked == ButtonStateOn) ? (pixOn) :
×
322
                /* (checked == ButtonStateOff) ? */ (pixOff));
323

324
        if (hoverOpacity > 0)
×
325
        {
326
                painter.setOpacity(hoverOpacity * opacity);
×
327
                painter.drawPixmap(0, 0, pixHover);
×
328
        }
329
        setPixmap(pix);
×
330
        scaledCurrentPixmap = {};
×
331
}
×
332

333
void StelButton::animValueChanged(qreal value)
×
334
{
335
        hoverOpacity = value;
×
336
        updateIcon();
×
337
}
×
338

339
void StelButton::setChecked(int b)
×
340
{
341
        checked=b;
×
342
        updateIcon();
×
343
}
×
344

345
void StelButton::setBackgroundPixmap(const QPixmap &newBackground)
×
346
{
347
        pixBackground = newBackground;
×
348
        updateIcon();
×
349
}
×
350

351
QRectF StelButton::boundingRect() const
×
352
{
353
        return QRectF(0,0, getButtonPixmapWidth(), getButtonPixmapHeight());
×
354
}
355

356

357
int StelButton::getButtonPixmapWidth() const
×
358
{
359
        const double baseWidth = pixOn.width() / pixmapsScale * StelApp::getInstance().screenFontSizeRatio();
×
360
        return std::lround(baseWidth);
×
361
}
362
int StelButton::getButtonPixmapHeight() const
×
363
{
364
        const double baseHeight = pixOn.height() / pixmapsScale * StelApp::getInstance().screenFontSizeRatio();
×
365
        return std::lround(baseHeight);
×
366
}
367

368
void StelButton::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
×
369
{
370
        /* QPixmap::scaled has much better quality than that scaling via QPainter::drawPixmap, so let's
371
         * have our scaled copy of the pixmap.
372
         * NOTE: we cache this copy for two reasons:
373
         * 1. Performance
374
         * 2. Work around a Qt problem (I think it's a bug): when rendering multiple StelButton items
375
         *    in sequence, only the first one gets the necessary texture parameters set, particularly
376
         *    GL_TEXTURE_MIN_FILTER. On deletion of QPixmap the texture is deleted, and its Id gets
377
         *    assigned to the next QPixmap. Apparently, the Id gets cached somewhere in Qt internals, and
378
         *    becomes similar to a dangling pointer, informing Qt as if the necessary setup has already
379
         *    been done. The result is that after the first button all others in the same panel are black
380
         *    rectangles.
381
         *    Our keeping QPixmap alive instead of deleting it on return from this function prevents this.
382
         */
383
        const double ratio = QOpenGLContext::currentContext()->screen()->devicePixelRatio();
×
384
        if(scaledCurrentPixmap.isNull() || ratio != scaledCurrentPixmap.devicePixelRatioF())
×
385
        {
386
                const auto size = boundingRect().size() * ratio;
×
387
                scaledCurrentPixmap = pixmap().scaled(size.toSize(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
×
388
                scaledCurrentPixmap.setDevicePixelRatio(ratio);
×
389
        }
390
        // Align the pixmap to pixel grid, otherwise we'll get artifacts at some scaling factors.
391
        const auto transform = painter->combinedTransform();
×
392
        const auto shift = QPointF(-std::fmod(transform.dx(), 1.),
×
393
                                                           -std::fmod(transform.dy(), 1.));
×
394
        painter->drawPixmap(shift/ratio, scaledCurrentPixmap);
×
395
}
×
396

397
LeftStelBar::LeftStelBar(QGraphicsItem* parent)
×
398
        : QGraphicsItem(parent)
399
        , hideTimeLine(nullptr)
×
400
{
401
        // Create the help label
402
        helpLabel = new QGraphicsSimpleTextItem("", this);
×
403
        helpLabel->setBrush(QBrush(QColor::fromRgbF(1,1,1,1)));
×
404

405
        setFontSizeFromApp(StelApp::getInstance().getScreenFontSize());
×
406
        connect(&StelApp::getInstance(), &StelApp::screenFontSizeChanged, this, &LeftStelBar::setFontSizeFromApp);
×
407
        connect(&StelApp::getInstance(), &StelApp::fontChanged, this, &LeftStelBar::setFont);
×
408
}
×
409

410
LeftStelBar::~LeftStelBar()
×
411
{
412
}
×
413

414
void LeftStelBar::addButton(StelButton* button)
×
415
{
416
        prepareGeometryChange();
×
417
        double posY = 0;
×
418
        if (QGraphicsItem::childItems().size()!=0)
×
419
        {
420
                const QRectF& r = childrenBoundingRect();
×
421
                posY += r.bottom();
×
422
        }
423
        button->setParentItem(this);
×
424
        button->setFocusOnSky(false);
×
425
        //button->prepareGeometryChange(); // could possibly be removed when qt 4.6 become stable
426
        button->setPos(0., qRound(posY + 9.5 * StelApp::getInstance().screenFontSizeRatio()));
×
427

428
        connect(button, SIGNAL(hoverChanged(bool)), this, SLOT(buttonHoverChanged(bool)));
×
429
}
×
430

431
void LeftStelBar::updateButtonPositions()
×
432
{
433
        double posY = 0;
×
434
        for (const auto button : childItems())
×
435
        {
436
                if (const auto b = dynamic_cast<StelButton*>(button))
×
437
                        b->animValueChanged(0.); // update button pixmap
×
438
                button->setPos(0., posY);
×
439
                posY += std::round(button->boundingRect().height() + 9.5 * StelApp::getInstance().screenFontSizeRatio());
×
440
        }
×
441
}
×
442

443
void LeftStelBar::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
×
444
{
445
}
×
446

447
QRectF LeftStelBar::boundingRect() const
×
448
{
449
        return childrenBoundingRect();
×
450
}
451

452
QRectF LeftStelBar::boundingRectNoHelpLabel() const
×
453
{
454
        // Re-use original Qt code, just remove the help label
455
        QRectF childRect;
×
456
        for (auto* child : QGraphicsItem::childItems())
×
457
        {
458
                if (child==helpLabel)
×
459
                        continue;
×
460
                QPointF childPos = child->pos();
×
461
                QTransform matrix = child->transform() * QTransform().translate(childPos.x(), childPos.y());
×
462
                childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
×
463
        }
×
464
        return childRect;
×
465
}
466

467

468
// Update the help label when a button is hovered
469
void LeftStelBar::buttonHoverChanged(bool b)
×
470
{
471
        StelButton* button = qobject_cast<StelButton*>(sender());
×
472
        Q_ASSERT(button);
×
473
        if (b==true)
×
474
        {
475
                if (button->action)
×
476
                {
477
                        QString tip(button->action->getText());
×
478
                        QString shortcut(button->action->getShortcut().toString(QKeySequence::NativeText));
×
479
                        if (!shortcut.isEmpty())
×
480
                        {
481
                                //XXX: this should be unnecessary since we used NativeText.
482
                                if (shortcut == "Space")
×
483
                                        shortcut = q_("Space");
×
484
                                tip += "  [" + shortcut + "]";
×
485
                        }
486
                        helpLabel->setText(tip);
×
487
                        helpLabel->setPos(qRound(boundingRectNoHelpLabel().width()+15.5),qRound(button->pos().y()+button->getButtonPixmapHeight()/2-8));
×
488
                }
×
489
        }
490
        else
491
        {
492
                helpLabel->setText("");
×
493
        }
494
        // Update the screen as soon as possible.
495
        StelMainView::getInstance().thereWasAnEvent();
×
496
}
×
497

498
// Set the pen for all the sub elements
499
void LeftStelBar::setColor(const QColor& c)
×
500
{
501
        helpLabel->setBrush(c);
×
502
}
×
503

504
//! connect from StelApp to resize fonts on the fly.
505
void LeftStelBar::setFontSizeFromApp(int size)
×
506
{
507
        prepareGeometryChange();
×
508
        // Font size was developed based on base font size 13, i.e. 12
509
        int screenFontSize = size-1;
×
510
        QFont font=QGuiApplication::font();
×
511
        font.setPixelSize(screenFontSize);
×
512
        helpLabel->setFont(font);
×
513
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
514
        if (gui)
×
515
        {
516
                // to avoid crash
517
                SkyGui* skyGui=gui->getSkyGui();
×
518
                if (skyGui)
×
519
                {
520
                        skyGui->updateBarsPos();
×
521
                        updateButtonPositions();
×
522
                }
523
        }
524
}
×
525

526
//! connect from StelApp to resize fonts on the fly.
527
void LeftStelBar::setFont(const QFont &cfont)
×
528
{
529
        QFont font(cfont);
×
530
        font.setPixelSize(StelApp::getInstance().getScreenFontSize()-1);
×
531
        helpLabel->setFont(font);
×
532
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
533
        if (gui)
×
534
        {
535
                // to avoid crash
536
                SkyGui* skyGui=gui->getSkyGui();
×
537
                if (skyGui)
×
538
                        skyGui->updateBarsPos();
×
539
        }
540
}
×
541

542

543
BottomStelBar::BottomStelBar(QGraphicsItem* parent,
×
544
                             const QPixmap& pixLeft,
545
                             const QPixmap& pixRight,
546
                             const QPixmap& pixMiddle,
547
                             const QPixmap& pixSingle) :
×
548
        QGraphicsItem(parent),
549
        gap(2),
×
550
        pixBackgroundLeft(pixLeft),
×
551
        pixBackgroundRight(pixRight),
×
552
        pixBackgroundMiddle(pixMiddle),
×
553
        pixBackgroundSingle(pixSingle)
×
554
{
555
        // The text is dummy just for testing
556
        datetime = new QGraphicsSimpleTextItem("2008-02-06  17:33", this);
×
557
        location = new QGraphicsSimpleTextItem("Munich, Earth, 500m", this);
×
558
        fov = new QGraphicsSimpleTextItem("FOV 43.45", this);
×
559
        fps = new QGraphicsSimpleTextItem("43.2 FPS", this);
×
560

561
        // Create the help label
562
        helpLabel = new QGraphicsSimpleTextItem("", this);
×
563
        helpLabel->setBrush(QBrush(QColor::fromRgbF(1,1,1,1)));
×
564

565
        setColor(QColor::fromRgbF(1,1,1,1));
×
566

567
        setFontSizeFromApp(StelApp::getInstance().getScreenFontSize());
×
568
        connect(&StelApp::getInstance(), &StelApp::screenFontSizeChanged, this, [=](int fontsize){setFontSizeFromApp(fontsize); setFontSizeFromApp(fontsize);}); // We must call that twice to force all geom. updates
×
569
        connect(&StelApp::getInstance(), &StelApp::fontChanged, this, &BottomStelBar::setFont);
×
570
        connect(StelApp::getInstance().getCore(), &StelCore::flagUseTopocentricCoordinatesChanged, this, [=](bool){updateText(false, true);});
×
571

572
        QSettings* confSettings = StelApp::getInstance().getSettings();
×
573
        setFlagShowTime(confSettings->value("gui/flag_show_datetime", true).toBool());
×
574
        setFlagShowLocation(confSettings->value("gui/flag_show_location", true).toBool());
×
575
        setFlagShowFov(confSettings->value("gui/flag_show_fov", true).toBool());
×
576
        setFlagShowFps(confSettings->value("gui/flag_show_fps", true).toBool());
×
577
        setFlagTimeJd(confSettings->value("gui/flag_time_jd", false).toBool());
×
578
        setFlagFovDms(confSettings->value("gui/flag_fov_dms", false).toBool());
×
579
        setFlagShowTz(confSettings->value("gui/flag_show_tz", true).toBool());
×
580
}
×
581

582
//! connect from StelApp to resize fonts on the fly.
583
void BottomStelBar::setFontSizeFromApp(int size)
×
584
{
585
        prepareGeometryChange();
×
586
        QFont font=QGuiApplication::font();
×
587
        // Font size was developed based on base font size 13, i.e. 12
588
        font.setPixelSize(size-1);
×
589
        datetime->setFont(font);
×
590
        location->setFont(font);
×
591
        fov->setFont(font);
×
592
        fps->setFont(font);
×
593
        helpLabel->setFont(font);
×
594
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
595
        if (gui)
×
596
        {
597
                // to avoid crash
598
                SkyGui* skyGui=gui->getSkyGui();
×
599
                if (skyGui)
×
600
                {
601
                        skyGui->updateBarsPos();
×
602
                        updateButtonsGroups(); // Make sure bounding boxes are readjusted.
×
603
                }
604
        }
605
}
×
606

607
//! connect from StelApp to resize fonts on the fly.
608
void BottomStelBar::setFont(const QFont &cfont)
×
609
{
610
        QFont font(cfont);
×
611
        font.setPixelSize(StelApp::getInstance().getScreenFontSize()-1);
×
612
        datetime->setFont(font);
×
613
        location->setFont(font);
×
614
        fov->setFont(font);
×
615
        fps->setFont(font);
×
616
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
617
        if (gui)
×
618
        {
619
                // to avoid crash
620
                SkyGui* skyGui=gui->getSkyGui();
×
621
                if (skyGui)
×
622
                        skyGui->updateBarsPos();
×
623
        }
624
}
×
625

626
BottomStelBar::~BottomStelBar()
×
627
{
628
        // Remove currently hidden buttons which are not deleted by a parent element
629
        for (auto& group : buttonGroups)
×
630
        {
631
                for (auto* b : std::as_const(group.elems))
×
632
                {
633
                        if (b->parentItem()==nullptr)
×
634
                        {
635
                                delete b;
×
636
                                b=nullptr;
×
637
                        }
638
                }
639
        }
640
}
×
641

642
void BottomStelBar::addButton(StelButton* button, const QString& groupName, const QString& beforeActionName)
×
643
{
644
        prepareGeometryChange();
×
645
        QList<StelButton*>& g = buttonGroups[groupName].elems;
×
646
        bool done = false;
×
647
        for (int i=0; i<g.size(); ++i)
×
648
        {
649
                if (g[i]->action && g[i]->action->objectName()==beforeActionName)
×
650
                {
651
                        g.insert(i, button);
×
652
                        done = true;
×
653
                        break;
×
654
                }
655
        }
656
        if (done == false)
×
657
                g.append(button);
×
658

659
        button->setVisible(true);
×
660
        button->setParentItem(this);
×
661
        button->setFocusOnSky(true);
×
662
        updateButtonsGroups();
×
663

664
        connect(button, SIGNAL(hoverChanged(bool)), this, SLOT(buttonHoverChanged(bool)));
×
665
        emit sizeChanged();
×
666
}
×
667

668
StelButton* BottomStelBar::hideButton(const QString& actionName)
×
669
{
670
        QString gName;
×
671
        StelButton* bToRemove = nullptr;
×
672
        for (auto iter = buttonGroups.begin(); iter != buttonGroups.end(); ++iter)
×
673
        {
674
                int i=0;
×
675
                for (auto* b : std::as_const(iter.value().elems))
×
676
                {
677
                        if (b->action && b->action->objectName()==actionName)
×
678
                        {
679
                                gName = iter.key();
×
680
                                bToRemove = b;
×
681
                                iter.value().elems.removeAt(i);
×
682
                                break;
×
683
                        }
684
                        ++i;
×
685
                }
686
        }
687
        if (bToRemove == nullptr)
×
688
                return nullptr;
×
689
        if (buttonGroups[gName].elems.size() == 0)
×
690
        {
691
                buttonGroups.remove(gName);
×
692
        }
693
        // Cannot really delete because some part of the GUI depend on the presence of some buttons
694
        // so just make invisible
695
        bToRemove->setParentItem(nullptr);
×
696
        bToRemove->setVisible(false);
×
697
        updateButtonsGroups();
×
698
        emit sizeChanged();
×
699
        return bToRemove;
×
700
}
×
701

702
// Set the margin at the left and right of a button group in pixels
703
void BottomStelBar::setGroupMargin(const QString& groupName, int left, int right)
×
704
{
705
        if (!buttonGroups.contains(groupName))
×
706
                return;
×
707
        buttonGroups[groupName].leftMargin = left;
×
708
        buttonGroups[groupName].rightMargin = right;
×
709
        updateButtonsGroups();
×
710
}
711

712
//! Change the background of a group
713
void BottomStelBar::setGroupBackground(const QString& groupName,
×
714
                                       const QPixmap& pixLeft,
715
                                       const QPixmap& pixRight,
716
                                       const QPixmap& pixMiddle,
717
                                       const QPixmap& pixSingle)
718
{
719
        if (!buttonGroups.contains(groupName))
×
720
                return;
×
721

722
        buttonGroups[groupName].pixBackgroundLeft = new QPixmap(pixLeft);
×
723
        buttonGroups[groupName].pixBackgroundRight = new QPixmap(pixRight);
×
724
        buttonGroups[groupName].pixBackgroundMiddle = new QPixmap(pixMiddle);
×
725
        buttonGroups[groupName].pixBackgroundSingle = new QPixmap(pixSingle);
×
726
        updateButtonsGroups();
×
727
}
728

729
QRectF BottomStelBar::getButtonsBoundingRect() const
×
730
{
731
        QRectF childRect;
×
732
        bool hasBtn = false;
×
733
        for (auto* child : QGraphicsItem::childItems())
×
734
        {
735
                if (qgraphicsitem_cast<StelButton*>(child)==nullptr)
×
736
                        continue;
×
737
                hasBtn = true;
×
738
                QPointF childPos = child->pos();
×
739
                //qDebug() << "childPos" << childPos;
740
                QTransform matrix = child->transform() * QTransform().translate(childPos.x(), childPos.y());
×
741
                childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
×
742
        }
×
743

744
        if (hasBtn)
×
745
                return QRectF(0, 0, childRect.width(), childRect.height());
×
746
        else
747
                return QRectF();
×
748
}
749

750
void BottomStelBar::updateButtonsGroups()
×
751
{
752
        double x = 0;
×
753
        QFontMetrics statusFM(datetime->font());
×
754
        const double y = statusFM.lineSpacing()+gap; // Take natural font geometry into account
×
755
        for (auto& group : buttonGroups)
×
756
        {
757
                QList<StelButton*>& buttons = group.elems;
×
758
                if (buttons.empty())
×
759
                        continue;
×
760
                x += group.leftMargin;
×
761
                int n = 0;
×
762
                for (auto* b : buttons)
×
763
                {
764
                        // We check if the group has its own background if not the case
765
                        // We apply a default background.
766
                        if (n == 0)
×
767
                        {
768
                                if (buttons.size() == 1)
×
769
                                {
770
                                        if (group.pixBackgroundSingle == nullptr)
×
771
                                                b->setBackgroundPixmap(pixBackgroundSingle);
×
772
                                        else
773
                                                b->setBackgroundPixmap(*group.pixBackgroundSingle);
×
774
                                }
775
                                else
776
                                {
777
                                        if (group.pixBackgroundLeft == nullptr)
×
778
                                                b->setBackgroundPixmap(pixBackgroundLeft);
×
779
                                        else
780
                                                b->setBackgroundPixmap(*group.pixBackgroundLeft);
×
781
                                }
782
                        }
783
                        else if (n == buttons.size()-1)
×
784
                        {
785
                                if (buttons.size() != 1)
×
786
                                {
787
                                        if (group.pixBackgroundSingle == nullptr)
×
788
                                                b->setBackgroundPixmap(pixBackgroundSingle);
×
789
                                        else
790
                                                b->setBackgroundPixmap(*group.pixBackgroundSingle);
×
791
                                }
792
                                if (group.pixBackgroundRight == nullptr)
×
793
                                        b->setBackgroundPixmap(pixBackgroundRight);
×
794
                                else
795
                                        b->setBackgroundPixmap(*group.pixBackgroundRight);
×
796
                        }
797
                        else
798
                        {
799
                                if (group.pixBackgroundMiddle == nullptr)
×
800
                                        b->setBackgroundPixmap(pixBackgroundMiddle);
×
801
                                else
802
                                        b->setBackgroundPixmap(*group.pixBackgroundMiddle);
×
803
                        }
804
                        // Update the button pixmap
805
                        b->animValueChanged(0.);
×
806
                        b->setPos(x, y);
×
807
                        x += b->getButtonPixmapWidth();
×
808
                        ++n;
×
809
                }
810
                x+=group.rightMargin;
×
811
        }
812
        updateText(true);
×
813
}
×
814

815
// create text elements and tooltips in bottom toolbar.
816
// Make sure to avoid any change if not necessary to avoid triggering useless redraw
817
// This is also called when button groups have been updated.
818
void BottomStelBar::updateText(bool updatePos, bool updateTopocentric)
×
819
{
820
        static StelCore* core = StelApp::getInstance().getCore();
×
821
        const double jd = core->getJD();
×
822
        const double utcOffsetHrs=core->getUTCOffset(jd);
×
823
        const double deltaT = core->getDeltaT();
×
824
        const double sigma = StelUtils::getDeltaTStandardError(jd);
×
825
        QString validRangeMarker = "";
×
826
        core->getCurrentDeltaTAlgorithmValidRangeDescription(jd, &validRangeMarker);
×
827

828
        static StelLocaleMgr& locmgr = StelApp::getInstance().getLocaleMgr();
×
829
        QString newDateInfo = " ";
×
830
        if (getFlagShowTime())
×
831
        {
832
                if (getFlagShowTz())
×
833
                {
834
                        QString tz = locmgr.getPrintableTimeZoneLocal(jd, utcOffsetHrs);
×
835
                        newDateInfo = QString("%1 %2 %3").arg(locmgr.getPrintableDateLocal(jd, utcOffsetHrs), locmgr.getPrintableTimeLocal(jd, utcOffsetHrs), tz);
×
836
                }
×
837
                else
838
                        newDateInfo = QString("%1 %2").arg(locmgr.getPrintableDateLocal(jd, utcOffsetHrs), locmgr.getPrintableTimeLocal(jd, utcOffsetHrs));
×
839
        }
840
        QString newDateAppx = QString("JD %1").arg(jd, 0, 'f', 5); // up to seconds
×
841
        if (getFlagTimeJd())
×
842
        {
843
                newDateAppx = newDateInfo;
×
844
                newDateInfo = QString("JD %1").arg(jd, 0, 'f', 5); // up to seconds
×
845
        }
846

847
        QString planetName = core->getCurrentLocation().planetName;
×
848
        if (planetName!=planetNameEnglish)
×
849
        {
850
                planetNameEnglish=planetName;
×
851
                if (planetName=="SpaceShip") // Avoid crash
×
852
                {
853
                        const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
×
854
                        planetNameI18n = trans.qtranslate(planetName, "special celestial body"); // added context
×
855
                }
856
                else
857
                        planetNameI18n = GETSTELMODULE(SolarSystem)->searchByEnglishName(planetName)->getNameI18n();
×
858
        }
859
        QString tzName = core->getCurrentTimeZone();
×
860
        if (tzName.contains("system_default") || (tzName.isEmpty() && planetName=="Earth"))
×
861
                tzName = q_("System default");
×
862

863
        QString currTZ = QString("%1: %2").arg(q_("Time zone"), tzName);
×
864

865
        if (tzName.contains("LMST") || tzName.contains("auto") || (planetName=="Earth" && jd<=StelCore::TZ_ERA_BEGINNING && !core->getUseCustomTimeZone()) )
×
866
                currTZ = q_("Local Mean Solar Time");
×
867

868
        if (tzName.contains("LTST"))
×
869
                currTZ = q_("Local True Solar Time");
×
870

871
        // TRANSLATORS: unit of measurement: minutes per second
872
        QString timeRateMU = qc_("min/s", "unit of measurement");
×
873
        double timeRate = qAbs(core->getTimeRate()/StelCore::JD_SECOND);
×
874
        double timeSpeed = timeRate/60.;
×
875

876
        if (timeSpeed>=60.)
×
877
        {
878
                timeSpeed /= 60.;
×
879
                // TRANSLATORS: unit of measurement: hours per second
880
                timeRateMU = qc_("hr/s", "unit of measurement");
×
881
        }
882
        if (timeSpeed>=24.)
×
883
        {
884
                timeSpeed /= 24.;
×
885
                // TRANSLATORS: unit of measurement: days per second
886
                timeRateMU = qc_("d/s", "unit of measurement");
×
887
        }
888
        if (timeSpeed>=365.25)
×
889
        {
890
                timeSpeed /= 365.25;
×
891
                // TRANSLATORS: unit of measurement: years per second
892
                timeRateMU = qc_("yr/s", "unit of measurement");
×
893
        }
894
        QString timeRateInfo = QString("%1: x%2").arg(q_("Simulation speed"), QString::number(timeRate, 'f', 0));
×
895
        if (timeRate>60.)
×
896
                timeRateInfo = QString("%1: x%2 (%3 %4)").arg(q_("Simulation speed"), QString::number(timeRate, 'f', 0), QString::number(timeSpeed, 'f', 2), timeRateMU);
×
897

898
        if (datetime->text()!=newDateInfo)
×
899
        {
900
                updatePos = true;
×
901
                datetime->setText(newDateInfo);
×
902
        }
903

904
        if (core->getCurrentDeltaTAlgorithm()!=StelCore::WithoutCorrection)
×
905
        {
906
                QString sigmaInfo("");
×
907
                if (sigma>0)
×
908
                        sigmaInfo = QString("; %1(%2T) = %3s").arg(QChar(0x03c3)).arg(QChar(0x0394)).arg(sigma, 3, 'f', 1);
×
909

910
                QString deltaTInfo;
×
911
                if (qAbs(deltaT)>60.)
×
912
                        deltaTInfo = QString("%1 (%2s)%3").arg(StelUtils::hoursToHmsStr(deltaT/3600.)).arg(deltaT, 5, 'f', 2).arg(validRangeMarker);
×
913
                else
914
                        deltaTInfo = QString("%1s%2").arg(deltaT, 3, 'f', 3).arg(validRangeMarker);
×
915

916
                // the corrective ndot to be displayed could be set according to the currently used DeltaT algorithm.
917
                //float ndot=core->getDeltaTnDot();
918
                // 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..."
919
                const double ndot=( (EphemWrapper::use_de430(jd) || EphemWrapper::use_de431(jd) || EphemWrapper::use_de440(jd) || EphemWrapper::use_de441(jd)) ? -25.8 : -23.8946 );
×
920

921
                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));
×
922
        }
×
923
        else
924
                datetime->setToolTip(QString("<p style='white-space:pre'>%1<br>%2<br>%3</p>").arg(newDateAppx, currTZ, timeRateInfo));
×
925

926
        // build location tooltip
927
        QString newLocation("");
×
928
        if (getFlagShowLocation())
×
929
        {
930
                const StelLocation* loc = &core->getCurrentLocation();
×
931
                if (core->getCurrentPlanet()->getPlanetType()==Planet::isObserver)
×
932
                        newLocation = planetNameI18n;
×
933
                else if(loc->name.isEmpty())
×
934
                        newLocation = planetNameI18n +", "+StelUtils::decDegToDmsStr(loc->getLatitude())+", "+StelUtils::decDegToDmsStr(loc->getLongitude());
×
935
                else if (loc->name.contains("->")) // a spaceship
×
936
                        newLocation = QString("%1 [%2 %3]").arg(planetNameI18n, q_("flight"), loc->name);
×
937
                else
938
                        //TRANSLATORS: Unit of measure for distance - meter
939
                        newLocation = planetNameI18n +", "+q_(loc->name) + ", "+ QString("%1 %2").arg(loc->altitude).arg(qc_("m", "distance"));
×
940
        }
941
        // When topocentric switch is toggled, this must be redrawn!
942
        if (location->text()!=newLocation || updateTopocentric)
×
943
        {
944
                updatePos = true;
×
945
                location->setText(newLocation);
×
946
                double lat = static_cast<double>(core->getCurrentLocation().getLatitude());
×
947
                double lon = static_cast<double>(core->getCurrentLocation().getLongitude());
×
948
                QString latStr, lonStr, pm;
×
949
                if (lat >= 0)
×
950
                        pm = "N";
×
951
                else
952
                {
953
                        pm = "S";
×
954
                        lat *= -1;
×
955
                }
956
                latStr = QString("%1%2%3").arg(pm).arg(lat).arg(QChar(0x00B0));
×
957
                if (lon >= 0)
×
958
                        pm = "E";
×
959
                else
960
                {
961
                        pm = "W";
×
962
                        lon *= -1;
×
963
                }
964
                lonStr = QString("%1%2%3").arg(pm).arg(lon).arg(QChar(0x00B0));
×
965
                QString rho, weather;
×
966
                if (core->getUseTopocentricCoordinates())
×
967
                        rho = QString("%1 %2 %3").arg(q_("planetocentric distance")).arg(core->getCurrentObserver()->getDistanceFromCenter() * AU).arg(qc_("km", "distance"));
×
968
                else
969
                        rho = q_("planetocentric observer");
×
970

971
                if (newLocation.contains("->")) // a spaceship
×
972
                        location->setToolTip(QString());
×
973
                else
974
                {
975
                        if (core->getCurrentPlanet()->hasAtmosphere())
×
976
                        {
977
                                const StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
978
                                weather = QString("%1: %2 %3; %4: %5 °C").arg(q_("Atmospheric pressure"), QString::number(propMgr->getStelPropertyValue("StelSkyDrawer.atmospherePressure").toDouble(), 'f', 2), qc_("mbar", "pressure unit"), q_("temperature"), QString::number(propMgr->getStelPropertyValue("StelSkyDrawer.atmosphereTemperature").toDouble(), 'f', 1));
×
979
                                location->setToolTip(QString("<p style='white-space:pre'>%1 %2; %3<br>%4</p>").arg(latStr, lonStr, rho, weather));
×
980
                        }
981
                        else if (core->getCurrentPlanet()->getPlanetType()==Planet::isObserver)
×
982
                                newLocation = planetNameI18n;
×
983
                        else
984
                                location->setToolTip(QString("%1 %2; %3").arg(latStr, lonStr, rho));
×
985
                }
986
        }
×
987

988
        // build fov tooltip
989
        // TRANSLATORS: Field of view. Please use abbreviation.
990
        QString fovdms = StelUtils::decDegToDmsStr(core->getMovementMgr()->getCurrentFov());
×
991
        QString fovText;
×
992
        if (getFlagFovDms())
×
993
                fovText=QString("%1 %2").arg(qc_("FOV", "abbreviation"), fovdms);
×
994
        else
995
                fovText=QString("%1 %2%3").arg(qc_("FOV", "abbreviation"), QString::number(core->getMovementMgr()->getCurrentFov(), 'g', 3), QChar(0x00B0));
×
996

997
        if (fov->text()!=fovText)
×
998
        {
999
                updatePos = true;
×
1000
                if (getFlagShowFov())
×
1001
                {
1002
                        fov->setText(fovText);
×
1003
                        fov->setToolTip(QString("%1: %2").arg(q_("Field of view"), fovdms));
×
1004
                }
1005
                else
1006
                {
1007
                        fov->setText("");
×
1008
                        fov->setToolTip("");
×
1009
                }
1010
        }
1011

1012
        // build fps tooltip
1013
        // TRANSLATORS: Frames per second. Please use abbreviation.
1014
        QString fpsText = QString("%1 %2").arg(QString::number(StelApp::getInstance().getFps(), 'g', 4), qc_("FPS", "abbreviation"));
×
1015
        if (fps->text()!=fpsText)
×
1016
        {
1017
                updatePos = true;
×
1018
                if (getFlagShowFps())
×
1019
                {
1020
                        fps->setText(fpsText);
×
1021
                        fps->setToolTip(q_("Frames per second"));
×
1022
                }
1023
                else
1024
                {
1025
                        fps->setText("");
×
1026
                        fps->setToolTip("");
×
1027
                }
1028
        }
1029

1030
        if (updatePos)
×
1031
        {
1032
                // The location string starts at left, dateTime ends at right. FoV and FPS come ahead of dateTime.
1033
                // In case the strings are wider than available button space, they are now pushed to the right.
1034
                QFontMetrics fontMetrics(location->font());
×
1035
                int fpsShift     = qMax(fontMetrics.boundingRect(fps->text()+"MMM").width(), fontMetrics.boundingRect(qc_("FPS", "abbreviation")+"MM.M MMM").width());
×
1036
                int fovShift     = fontMetrics.boundingRect(fov->text()+"MMM").width() + fpsShift;
×
1037
                int locationWidth= fontMetrics.boundingRect(location->text() + "MMM").width();
×
1038
                location->setPos(0, 0);
×
1039

1040
                QRectF rectCh = getButtonsBoundingRect();
×
1041
                int dateTimePos = static_cast<int>(rectCh.right()-datetime->boundingRect().width())-5;
×
1042
                if ((dateTimePos%2) == 1) dateTimePos--; // make even pixel
×
1043

1044
                const int rightPush=qMax(0, locationWidth-(dateTimePos-fovShift));
×
1045
                datetime->setPos(dateTimePos+rightPush, 0);
×
1046
                fov->setPos(datetime->x()-fovShift, 0);
×
1047
                fps->setPos(datetime->x()-fpsShift, 0);
×
1048
                //emit sizeChanged(); // This causes max fps!
1049
        }
×
1050
}
×
1051

1052
void BottomStelBar::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
×
1053
{
1054
        updateText();
×
1055
}
×
1056

1057
QRectF BottomStelBar::boundingRect() const
×
1058
{
1059
        if (QGraphicsItem::childItems().size()==0)
×
1060
                return QRectF();
×
1061
        const QRectF& r = childrenBoundingRect(); // BBX of status text (Location/FoV/FPS/Time) and buttons
×
1062
        return QRectF(0, 0, r.width(), r.height());
×
1063
}
1064

1065
QRectF BottomStelBar::boundingRectNoHelpLabel() const
×
1066
{
1067
        // Re-use original Qt code, just remove the help label
1068
        QRectF childRect;
×
1069
        for (const auto* child : QGraphicsItem::childItems())
×
1070
        {
1071
                if (child==helpLabel)
×
1072
                        continue;
×
1073
                QPointF childPos = child->pos();
×
1074
                QTransform matrix = child->transform() * QTransform().translate(childPos.x(), childPos.y());
×
1075
                childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
×
1076
        }
×
1077
        return childRect;
×
1078
}
1079

1080
// Set the brush for all the sub elements
1081
void BottomStelBar::setColor(const QColor& c)
×
1082
{
1083
        datetime->setBrush(c);
×
1084
        location->setBrush(c);
×
1085
        fov->setBrush(c);
×
1086
        fps->setBrush(c);
×
1087
        helpLabel->setBrush(c);
×
1088
}
×
1089

1090
// Update the help label when a button is hovered
1091
void BottomStelBar::buttonHoverChanged(bool b)
×
1092
{
1093
        StelButton* button = qobject_cast<StelButton*>(sender());
×
1094
        Q_ASSERT(button);
×
1095
        if (b==true)
×
1096
        {
1097
                StelAction* action = button->action;
×
1098
                if (action)
×
1099
                {
1100
                        QString tip(action->getText());
×
1101
                        QString shortcut(action->getShortcut().toString(QKeySequence::NativeText));
×
1102
                        if (!shortcut.isEmpty())
×
1103
                        {
1104
                                //XXX: this should be unnecessary since we used NativeText.
1105
                                if (shortcut == "Space")
×
1106
                                        shortcut = q_("Space");
×
1107
                                tip += "  [" + shortcut + "]";
×
1108
                        }
1109
                        helpLabel->setText(tip);
×
1110
                        //helpLabel->setPos(button->pos().x()+button->pixmap().size().width()/2,-27);
1111
                        helpLabel->setPos(20,-10-location->font().pixelSize()); // Set help text XY position. Y adjusted for font size!
×
1112
                }
×
1113
        }
1114
        else
1115
        {
1116
                helpLabel->setText("");
×
1117
        }
1118
        // Update the screen as soon as possible.
1119
        StelMainView::getInstance().thereWasAnEvent();
×
1120
}
×
1121

1122
void BottomStelBar::enableTopoCentricUpdate(bool enable)
×
1123
{
1124
        bool ok;
1125
        if (enable)
×
1126
                ok=connect(StelApp::getInstance().getCore(), &StelCore::flagUseTopocentricCoordinatesChanged, this, [=](bool){updateText(false, true);});
×
1127
        else
1128
                ok=disconnect(StelApp::getInstance().getCore(), &StelCore::flagUseTopocentricCoordinatesChanged, nullptr, nullptr); //, this, [=](bool b, bool update){if (update) updateText(false, true);});
×
1129

1130
        if (!ok)
×
1131
                qCritical() << "BottomStelBar: enableTopoCentricUpdate failed.";
×
1132
}
×
1133

1134
StelBarsFrame::StelBarsFrame(QGraphicsItem* parent) : QGraphicsPathItem(parent), roundSize(6)
×
1135
{
1136
        setBrush(QBrush(QColor::fromRgbF(0.22, 0.22, 0.23, 0.2))); // background color
×
1137
        QPen aPen(QColor::fromRgbF(0.7,0.7,0.7,0.5));              // perimeter line color
×
1138
        // aPen.setWidthF(1.); // 1=default!
1139
        setPen(aPen);
×
1140
}
×
1141

1142
void StelBarsFrame::updatePath(BottomStelBar* bottom, LeftStelBar* left)
×
1143
{
1144
        const QPointF l = left->pos() + QPointF(-0.5,0.5);   // pos() is the top-left point in the parent's coordinate system.
×
1145
        const QRectF lB = left->boundingRectNoHelpLabel();
×
1146
        const QPointF b = bottom->pos() + QPointF(-0.5,0.5);
×
1147
        const QRectF bB = bottom->boundingRectNoHelpLabel();
×
1148

1149
        QPainterPath path(QPointF(l.x()-roundSize, l.y()-roundSize));                                 // top left point
×
1150
        //path.lineTo(l.x()+lB.width()-roundSize,l.y()-roundSize);                                    // top edge. Not needed because the arc connects anyhow!
1151
        path.arcTo(l.x()+lB.width()-roundSize, l.y()-roundSize, 2.*roundSize, 2.*roundSize, 90, -90); // top-right curve of left bar
×
1152
        path.lineTo(l.x()+lB.width()+roundSize, b.y()-roundSize);                                     // vertical to inside sharp edge
×
1153
        //path.lineTo(b.x()+bB.width(),b.y()-roundSize);                                              // Top edge of bottom bar. Not needed because the arc connects anyhow!
1154
        path.arcTo(b.x()+bB.width()-roundSize, b.y()-roundSize, 2.*roundSize, 2.*roundSize, 90, -90); // top right curved edge of bottom bar (just connects.)
×
1155
        path.lineTo(b.x()+bB.width()+roundSize, b.y()+bB.height()+roundSize);
×
1156
        path.lineTo(l.x()-roundSize, b.y()+bB.height()+roundSize);                                    // bottom line (outside screen area!)
×
1157
        path.closeSubpath();                                                                          // vertical line up left outside screen
×
1158
        setPath(path);
×
1159
}
×
1160

1161
void StelBarsFrame::setBackgroundOpacity(double opacity)
×
1162
{
1163
        setBrush(QBrush(QColor::fromRgbF(0.22, 0.22, 0.23, opacity))); // repeated background color and new opacity
×
1164
}
×
1165

1166
StelProgressBarMgr::StelProgressBarMgr(QGraphicsItem* parent):
×
1167
        QGraphicsWidget(parent)
×
1168
{
1169
        setLayout(new QGraphicsLinearLayout(Qt::Vertical));
×
1170
}
×
1171
/*
1172
QRectF StelProgressBarMgr::boundingRect() const
1173
{
1174
        if (QGraphicsItem::children().size()==0)
1175
                return QRectF();
1176
        const QRectF& r = childrenBoundingRect();
1177
        return QRectF(0, 0, r.width()-1, r.height()-1);
1178
}*/
1179

1180
void StelProgressBarMgr::addProgressBar(const StelProgressController* p)
×
1181
{
1182
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
1183
        QProgressBar* pb = new QProgressBar();
×
1184
        pb->setFixedHeight(25);
×
1185
        pb->setFixedWidth(200);
×
1186
        pb->setTextVisible(true);
×
1187
        pb->setValue(p->getValue());
×
1188
        pb->setMinimum(p->getMin());
×
1189
        pb->setMaximum(p->getMax());
×
1190
        pb->setFormat(p->getFormat());
×
1191
        if (gui!=nullptr)
×
1192
                pb->setStyleSheet(gui->getStelStyle().qtStyleSheet);
×
1193
        QGraphicsProxyWidget* pbProxy = new QGraphicsProxyWidget();
×
1194
        pbProxy->setWidget(pb);
×
1195
        pbProxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
×
1196
        pbProxy->setZValue(150);        
×
1197
        static_cast<QGraphicsLinearLayout*>(layout())->addItem(pbProxy);
×
1198
        allBars.insert(p, pb);
×
1199
        pb->setVisible(true);
×
1200
        
1201
        connect(p, SIGNAL(changed()), this, SLOT(oneBarChanged()));
×
1202
}
×
1203

1204
void StelProgressBarMgr::removeProgressBar(const StelProgressController *p)
×
1205
{
1206
        QProgressBar* pb = allBars[p];
×
1207
        pb->deleteLater();
×
1208
        allBars.remove(p);
×
1209
}
×
1210

1211
void StelProgressBarMgr::oneBarChanged()
×
1212
{
1213
        const StelProgressController *p = static_cast<StelProgressController*>(QObject::sender());
×
1214
        QProgressBar* pb = allBars[p];
×
1215
        pb->setValue(p->getValue());
×
1216
        pb->setMinimum(p->getMin());
×
1217
        pb->setMaximum(p->getMax());
×
1218
        pb->setFormat(p->getFormat());
×
1219
}
×
1220

1221
CornerButtons::CornerButtons(QGraphicsItem* parent) :
×
1222
        QGraphicsItem(parent),
1223
        lastOpacity(10)
×
1224
{
1225
}
×
1226

1227
void CornerButtons::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
×
1228
{
1229
        // Do nothing. Just paint the child widgets
1230
}
×
1231

1232
QRectF CornerButtons::boundingRect() const
×
1233
{
1234
        if (QGraphicsItem::childItems().size()==0)
×
1235
                return QRectF();
×
1236
        const QRectF& r = childrenBoundingRect();
×
1237
        return QRectF(0, 0, r.width(), r.height());
×
1238
}
1239

1240
void CornerButtons::setOpacity(double opacity)
×
1241
{
1242
        if (opacity<=0. && lastOpacity<=0.)
×
1243
                return;
×
1244
        lastOpacity = opacity;
×
1245
        if (QGraphicsItem::childItems().size()==0)
×
1246
                return;
×
1247
        for (auto* child : QGraphicsItem::childItems())
×
1248
        {
1249
                StelButton* sb = qgraphicsitem_cast<StelButton*>(child);
×
1250
                Q_ASSERT(sb!=nullptr);
×
1251
                sb->setOpacity(opacity);
×
1252
        }
×
1253
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc