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

Stellarium / stellarium / 4853788370

pending completion
4853788370

push

github

Alexander V. Wolf
Special patch for John Simple

3 of 3 new or added lines in 3 files covered. (100.0%)

14729 of 125046 relevant lines covered (11.78%)

20166.5 hits per line

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

0.0
/src/gui/HelpDialog.cpp
1
/*
2
 * Stellarium
3
 * Copyright (C) 2007 Matthew Gates
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 <QString>
21
#include <QTextBrowser>
22
#include <QScrollBar>
23
#include <QVBoxLayout>
24
#include <QWidget>
25
#include <QFrame>
26
#include <QResizeEvent>
27
#include <QSize>
28
#include <QMultiMap>
29
#include <QList>
30
#include <QSet>
31
#include <QPair>
32
#include <QtAlgorithms>
33
#include <QDebug>
34
#include <QFileInfo>
35
#include <QFile>
36
#include <QDir>
37
#include <QProcess>
38
#include <QSysInfo>
39
#include <QNetworkAccessManager>
40
#include <QNetworkReply>
41
#include <QRegularExpression>
42

43
#include "ui_helpDialogGui.h"
44
#include "HelpDialog.hpp"
45

46
#include "StelUtils.hpp"
47
#include "StelApp.hpp"
48
#include "StelFileMgr.hpp"
49
#include "StelGui.hpp"
50
#include "StelLogger.hpp"
51
#include "StelStyle.hpp"
52
#include "StelActionMgr.hpp"
53
#include "StelMovementMgr.hpp"
54
#include "StelModuleMgr.hpp"
55
#include "StelJsonParser.hpp"
56
#include "StelTranslator.hpp"
57
#include "ContributorsList.hpp"
58

59
HelpDialog::HelpDialog(QObject* parent)
×
60
        : StelDialog("Help", parent)
61
        , message("")
×
62
        , updateState(CompleteNoUpdates)
×
63
        , networkManager(nullptr)
×
64
        , downloadReply(nullptr)
×
65
{
66
        ui = new Ui_helpDialogForm;        
×
67
}
×
68

69
HelpDialog::~HelpDialog()
×
70
{
71
        delete ui;
×
72
        ui = nullptr;
×
73
}
×
74

75
void HelpDialog::retranslate()
×
76
{
77
        if (dialog)
×
78
        {
79
                ui->retranslateUi(dialog);
×
80
                updateHelpText();
×
81
                updateAboutText();
×
82
                updateTabBarListWidgetWidth();
×
83
        }
84
}
×
85

86
void HelpDialog::styleChanged(const QString &style)
×
87
{
88
        StelDialog::styleChanged(style);
×
89
        if (dialog)
×
90
        {
91
                updateHelpText();
×
92
                updateAboutText();
×
93
        }
94
}
×
95

96
void HelpDialog::createDialogContent()
×
97
{
98
        ui->setupUi(dialog);
×
99
        connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslate()));
×
100
        ui->stackedWidget->setCurrentIndex(0);
×
101
        ui->stackListWidget->setCurrentRow(0);
×
102
        connect(ui->closeStelWindow, SIGNAL(clicked()), this, SLOT(close()));
×
103
        connect(ui->TitleBar, SIGNAL(movedTo(QPoint)), this, SLOT(handleMovedTo(QPoint)));
×
104

105
        // Kinetic scrolling
106
        kineticScrollingList << ui->helpBrowser << ui->aboutBrowser << ui->logBrowser;
×
107
        StelGui* gui= dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
108
        if (gui)
×
109
        {
110
                enableKineticScrolling(gui->getFlagUseKineticScrolling());
×
111
                connect(gui, SIGNAL(flagUseKineticScrollingChanged(bool)), this, SLOT(enableKineticScrolling(bool)));
×
112
        }
113

114

115
        // Help page
116
        StelMovementMgr* mmgr = GETSTELMODULE(StelMovementMgr);
×
117
        updateHelpText();
×
118
        setKeyButtonState(mmgr->getFlagEnableMoveKeys());
×
119
        connect(ui->editShortcutsButton, SIGNAL(clicked()), this, SLOT(showShortcutsWindow()));
×
120
        connect(StelApp::getInstance().getStelActionManager(), SIGNAL(shortcutsChanged()), this, SLOT(updateHelpText()));
×
121
        connect(mmgr, SIGNAL(flagEnableMoveKeysChanged(bool)), this, SLOT(setKeyButtonState(bool)));
×
122

123
        // About page
124
        updateAboutText();
×
125

126
        // Log page        
127
        ui->logPathLabel->setText(QString("%1:").arg(StelLogger::getLogFileName()));
×
128
        connect(ui->stackedWidget, SIGNAL(currentChanged(int)), this, SLOT(updateLog(int)));
×
129
        connect(ui->refreshButton, SIGNAL(clicked()), this, SLOT(refreshLog()));
×
130

131
        // Config page
132
        ui->configPathLabel->setText(QString("%1:").arg(StelApp::getInstance().getSettings()->fileName()));
×
133
        connect(ui->stackedWidget, SIGNAL(currentChanged(int)), this, SLOT(updateConfig(int)));
×
134
        connect(ui->refreshConfigButton, SIGNAL(clicked()), this, SLOT(refreshConfig()));
×
135

136
        // Set up download manager for checker of updates
137
        networkManager = StelApp::getInstance().getNetworkAccessManager();
×
138
        updateState = CompleteNoUpdates;
×
139
        connect(ui->checkUpdatesButton, SIGNAL(clicked()), this, SLOT(checkUpdates()));
×
140
        connect(this, SIGNAL(checkUpdatesComplete(void)), this, SLOT(updateAboutText()));
×
141

142
        connect(ui->stackListWidget, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(changePage(QListWidgetItem *, QListWidgetItem*)));
×
143
        updateTabBarListWidgetWidth();
×
144

145
        connect((dynamic_cast<StelGui*>(StelApp::getInstance().getGui())), &StelGui::htmlStyleChanged, this, [=](const QString &style){
×
146
                ui->helpBrowser->document()->setDefaultStyleSheet(style);
×
147
                ui->aboutBrowser->document()->setDefaultStyleSheet(style);
×
148
        });
×
149
}
×
150

151
void HelpDialog::setKeyButtonState(bool state)
×
152
{
153
        ui->editShortcutsButton->setEnabled(state);
×
154
}
×
155

156
void HelpDialog::checkUpdates()
×
157
{
158
#if (QT_VERSION<QT_VERSION_CHECK(6,0,0))
159
        // In Qt6 this is no longer available. Here we have to assume we are connected and test the reply.
160
        // There is QNetworkInformation in Qt6.1, but it may give wrong results under certain circumstances.
161
        // https://doc.qt.io/qt-6/qnetworkinformation.html
162
        if (networkManager->networkAccessible()==QNetworkAccessManager::Accessible)
×
163
#endif
164
        {
165
                if (updateState==HelpDialog::Updating)
×
166
                {
167
                        qWarning() << "Already checking updates...";
×
168
                        return;
×
169
                }
170

171
                QUrl API("https://api.github.com/repos/Stellarium/stellarium/releases/latest");
×
172
                connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadComplete(QNetworkReply*)));
×
173
                QNetworkRequest request;
×
174
                request.setUrl(API);
×
175
                request.setRawHeader("User-Agent", StelUtils::getUserAgentString().toUtf8());
×
176
#if (QT_VERSION<QT_VERSION_CHECK(6,0,0))
177
                request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
×
178
#endif
179
                downloadReply = networkManager->get(request);
×
180

181
                updateState = HelpDialog::Updating;
×
182
        }
×
183
}
184

185
void HelpDialog::downloadComplete(QNetworkReply *reply)
×
186
{
187
        if (reply == nullptr)
×
188
                return;
×
189

190
        disconnect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadComplete(QNetworkReply*)));
×
191

192
        if (reply->error() || reply->bytesAvailable()==0)
×
193
        {
194
                qWarning() << "Error: While trying to access"
×
195
                           << reply->url().toString()
×
196
                           << "the following error occurred:"
×
197
                           << reply->errorString();
×
198

199
                reply->deleteLater();
×
200
                downloadReply = nullptr;
×
201
                updateState = HelpDialog::DownloadError;
×
202
                message = q_("Cannot check updates...");
×
203
                return;
×
204
        }
205

206
        QVariantMap map;
×
207
        try
208
        {
209
                map = StelJsonParser::parse(reply->readAll()).toMap();
×
210
        }
211
        catch (std::runtime_error &e)
×
212
        {
213
                qDebug() << "Answer format is wrong! Error: " << e.what();
×
214
                message = q_("Cannot check updates...");
×
215
                return;
×
216
        }
×
217

218
        updateState = HelpDialog::CompleteUpdates;
×
219

220
        QString latestVersion = map["name"].toString();
×
221
        latestVersion.replace("v","", Qt::CaseInsensitive);
×
222
        QStringList v = latestVersion.split(".");
×
223
        if (v.count()==2)
×
224
                v.append("0");
×
225

226
        QString appVersion = StelUtils::getApplicationVersion();
×
227
        QStringList c = appVersion.split(".");
×
228
        int r = StelUtils::compareVersions(latestVersion, appVersion);
×
229
        if (r==-1 || c.count()>v.count() || c.last().contains("-"))
×
230
                message = q_("Looks like you are using the development version of Stellarium.");
×
231
        else if (r==0)
×
232
                message = q_("This is latest stable version of Stellarium.");
×
233
        else
234
                message = QString("%1 <a href='%2'>%3</a>").arg(q_("This version of Stellarium is outdated!"), map["html_url"].toString(), q_("Download new version."));
×
235

236
        reply->deleteLater();
×
237
        downloadReply = nullptr;
×
238

239
        emit checkUpdatesComplete();
×
240
}
×
241

242
void HelpDialog::showShortcutsWindow()
×
243
{
244
        StelAction* action = StelApp::getInstance().getStelActionManager()->findAction("actionShow_Shortcuts_Window_Global");
×
245
        if (action)
×
246
                action->setChecked(true);
×
247
}
×
248

249
void HelpDialog::updateLog(int)
×
250
{
251
        if (ui->stackedWidget->currentWidget() == ui->pageLog)
×
252
                refreshLog();
×
253
}
×
254

255
void HelpDialog::updateConfig(int)
×
256
{
257
        if (ui->stackedWidget->currentWidget() == ui->pageConfig)
×
258
                refreshConfig();
×
259
}
×
260

261
void HelpDialog::refreshLog() const
×
262
{
263
        ui->logBrowser->setPlainText(StelLogger::getLog());
×
264
        QScrollBar *sb = ui->logBrowser->verticalScrollBar();
×
265
        sb->setValue(sb->maximum());
×
266
}
×
267

268
void HelpDialog::refreshConfig() const
×
269
{
270
        QFile config(StelApp::getInstance().getSettings()->fileName());
×
271
        if(config.open(QIODevice::ReadOnly))
×
272
        {
273
                ui->configBrowser->setPlainText(config.readAll());
×
274
                ui->configBrowser->setFont(QFont("Courier New"));
×
275
                config.close();
×
276
        }
277
}
×
278

279
void HelpDialog::updateHelpText(void) const
×
280
{
281
        QString htmlText = "<html><head><title>";
×
282
        htmlText += q_("Stellarium Help").toHtmlEscaped();
×
283
        htmlText += "</title></head><body>\n";
×
284

285
        // WARNING! Section titles are re-used below!
286
        htmlText += "<p align=\"center\"><a href=\"#keys\">" +
×
287
                    q_("Keys").toHtmlEscaped() +
×
288
                    "</a> &bull; <a href=\"#links\">" +
×
289
                    q_("Further Reading").toHtmlEscaped() +
×
290
                    "</a></p>\n";
×
291

292
        htmlText += "<h2 id='keys'>" + q_("Keys").toHtmlEscaped() + "</h2>\n";
×
293
        htmlText += "<table cellpadding='10%' width='100%'>\n";
×
294
        // Describe keys for those keys which do not have actions.
295
        // navigate
296
        htmlText += "<tr><td>" + q_("Pan view around the sky").toHtmlEscaped() + "</td>";
×
297
        htmlText += "<td><b>" + q_("Arrow keys & left mouse drag").toHtmlEscaped() + "</b></td></tr>\n";
×
298
        // zoom in/out
299
        htmlText += "<tr><td rowspan='2'>" + q_("Zoom in/out").toHtmlEscaped() + "</td>";
×
300
        htmlText += "<td><b>" + hotkeyTextWrapper("Page Up") + "/" + hotkeyTextWrapper("Page Down") + "</b></td></tr>\n";
×
301
        htmlText += "<tr><td><b>" + hotkeyTextWrapper("Ctrl+Up") + "/" + hotkeyTextWrapper("Ctrl+Down") + "</b></td></tr>\n";
×
302
        // time dragging/scrolling
303
        QString delimiter = "";
×
304
        #ifdef Q_OS_MACOS
305
        // TRANSLATORS: The char mean "and"
306
        delimiter = QString(" %1 ").arg(q_("&"));
307
        #endif
308
        htmlText += "<tr><td>" + q_("Time dragging").toHtmlEscaped() + "</td><td><b>" +
×
309
                        QKeySequence(Qt::CTRL).toString(QKeySequence::NativeText) + delimiter + q_("left mouse drag").toHtmlEscaped() + "</b></td></tr>";
×
310
        htmlText += "<tr><td>" + q_("Time scrolling: minutes").toHtmlEscaped() + "</td><td><b>" +
×
311
                        QKeySequence(Qt::CTRL).toString(QKeySequence::NativeText) + delimiter + q_("mouse wheel").toHtmlEscaped() + "</b></td></tr>";
×
312
        htmlText += "<tr><td>" + q_("Time scrolling: hours").toHtmlEscaped() + "</td><td><b>" +
×
313
        #if (QT_VERSION>=QT_VERSION_CHECK(6,0,0))
314
                        QKeySequence(Qt::CTRL | Qt::SHIFT).toString(QKeySequence::NativeText) + delimiter + q_("mouse wheel").toHtmlEscaped() + "</b></td></tr>";
315
        htmlText += "<tr><td>" + q_("Time scrolling: days").toHtmlEscaped() + "</td><td><b>" +
316
                        QKeySequence(Qt::CTRL | Qt::ALT).toString(QKeySequence::NativeText) + delimiter + q_("mouse wheel").toHtmlEscaped() + "</b></td></tr>";
317
        htmlText += "<tr><td>" + q_("Time scrolling: years").toHtmlEscaped() + "</td><td><b>" +
318
                        QKeySequence(Qt::CTRL | Qt::ALT | Qt::SHIFT).toString(QKeySequence::NativeText) + delimiter + q_("mouse wheel").toHtmlEscaped() + "</b></td></tr>";
319
        #else
320
                        QKeySequence(Qt::CTRL + Qt::SHIFT).toString(QKeySequence::NativeText) + delimiter + q_("mouse wheel").toHtmlEscaped() + "</b></td></tr>";
×
321
        htmlText += "<tr><td>" + q_("Time scrolling: days").toHtmlEscaped() + "</td><td><b>" +
×
322
                        QKeySequence(Qt::CTRL + Qt::ALT).toString(QKeySequence::NativeText) + delimiter + q_("mouse wheel").toHtmlEscaped() + "</b></td></tr>";
×
323
        htmlText += "<tr><td>" + q_("Time scrolling: years").toHtmlEscaped() + "</td><td><b>" +
×
324
                        QKeySequence(Qt::CTRL + Qt::ALT + Qt::SHIFT).toString(QKeySequence::NativeText) + delimiter + q_("mouse wheel").toHtmlEscaped() + "</b></td></tr>";
×
325
        #endif
326

327
        // select object
328
        htmlText += "<tr><td>" + q_("Select object").toHtmlEscaped() + "</td>";
×
329
        htmlText += "<td><b>" + q_("Left click").toHtmlEscaped() + "</b></td></tr>\n";
×
330
        // clear selection
331
        htmlText += "<tr><td>";
×
332
        htmlText += q_("Clear selection").toHtmlEscaped() + "</td>";
×
333
        #ifdef Q_OS_MACOS
334
        htmlText += "<td><b>" + QKeySequence(Qt::CTRL).toString(QKeySequence::NativeText) + delimiter + q_("& left click").toHtmlEscaped() + "</b></td></tr>\n";
335
        #else
336
        htmlText += "<td><b>" + q_("Right click").toHtmlEscaped() + "</b></td></tr>\n";
×
337
        #endif
338
        // add custom marker
339
        htmlText += "<tr><td>" + q_("Add custom marker").toHtmlEscaped() + "</td>";
×
340
        htmlText += "<td><b>" + QKeySequence(Qt::SHIFT).toString(QKeySequence::NativeText) + delimiter + q_("left click").toHtmlEscaped() + "</b></td></tr>\n";
×
341
        // delete one custom marker
342
        htmlText += "<tr><td>" + q_("Delete marker closest to mouse cursor").toHtmlEscaped() + "</td>";
×
343
        htmlText += "<td><b>" + QKeySequence(Qt::SHIFT).toString(QKeySequence::NativeText) + delimiter + q_("right click").toHtmlEscaped() + "</b></td></tr>\n";
×
344
        // delete all custom markers
345
        htmlText += "<tr><td>" + q_("Delete all custom markers").toHtmlEscaped() + "</td>";
×
346
        #if (QT_VERSION>=QT_VERSION_CHECK(6,0,0))
347
        htmlText += "<td><b>" + QKeySequence(Qt::SHIFT | Qt::ALT).toString(QKeySequence::NativeText) + delimiter + q_("right click").toHtmlEscaped() + "</b></td></tr>\n";
348
        #else
349
        htmlText += "<td><b>" + QKeySequence(Qt::SHIFT + Qt::ALT).toString(QKeySequence::NativeText) + delimiter + q_("right click").toHtmlEscaped() + "</b></td></tr>\n";
×
350
        #endif
351

352
        htmlText += "</table>\n<p>" +
×
353
                        q_("Below are listed only the actions with assigned keys. Further actions may be available via the \"%1\" button.")
×
354
                        .arg(ui->editShortcutsButton->text()).toHtmlEscaped() +
×
355
                        "</p><table cellpadding='10%' width='100%'>\n";
×
356

357
        // Append all StelAction shortcuts.
358
        StelActionMgr* actionMgr = StelApp::getInstance().getStelActionManager();
×
359
        typedef QPair<QString, QString> KeyDescription;
360
        QString keydelimiter = QString("</b> %1 <b>").arg(q_("or"));
×
361
        QVector<KeyDescription> groups;
×
362
        const QStringList groupList = actionMgr->getGroupList();
×
363
        for (const auto &group : groupList)
×
364
        {
365
                groups.append(KeyDescription(q_(group), group));
×
366
        }
367
        groups.append(KeyDescription(q_("Text User Interface (TUI)"), "TUI")); // Special case: TUI
×
368
        std::sort(groups.begin(), groups.end());
×
369
        for (const auto &group : groups)
×
370
        {
371
                QVector<KeyDescription> descriptions;
×
372
                const QList<StelAction *>actionList = actionMgr->getActionList(group.second);
×
373
                for (auto* action : actionList)
×
374
                {
375
                        QString text = action->getText();
×
376
                        QStringList keys = { action->getShortcut().toString(QKeySequence::NativeText), action->getAltShortcut().toString(QKeySequence::NativeText)};
×
377
                        keys.removeAll(QString("")); // remove empty shortcuts
×
378
                        if (keys.count()>0)
×
379
                                descriptions.append(KeyDescription(text, keys.join(keydelimiter)));
×
380
                }
×
381
                std::sort(descriptions.begin(), descriptions.end());
×
382
                if (descriptions.count()>0)
×
383
                {
384
                        htmlText += "<tr><td colspan='2'>&nbsp;</td></tr>";
×
385
                        htmlText += "<tr><td colspan='2'><b><u>" + group.first.toHtmlEscaped() + ":</u></b></td></tr>\n";
×
386
                        for (const auto& desc : descriptions)
×
387
                        {
388
                                htmlText += "<tr><td>" + desc.first.toHtmlEscaped() + "</td>";
×
389
                                htmlText += "<td><b>" + desc.second + "</b></td></tr>\n";
×
390
                        }
391
                }
392
                if (group.second=="TUI") // Special case: TUI
×
393
                {
394
                        htmlText += "<tr><td colspan='2'>&nbsp;</td></tr>";
×
395
                        htmlText += "<tr><td colspan='2'><b><u>" + group.first.toHtmlEscaped() + ":</u></b></td></tr>\n";
×
396
                        htmlText += "<tr><td>" + q_("Activate TUI") + "</td>";
×
397
                        htmlText += "<td><b>" + hotkeyTextWrapper("Alt+T") + "</b></td></tr>\n";
×
398
                }
399
        }
×
400

401
        htmlText += "<tr><td colspan='2'>&nbsp;</td></tr>";
×
402
        htmlText += "<tr><td colspan='2'><b><u>" + q_("Special local keys") + ":</u></b></td></tr>\n";
×
403
        htmlText += "<tr><td colspan='2'>" + q_("All these hotkeys are locally available to run when specific window or tab is opened.") + "</td></tr>";
×
404
        htmlText += "<tr><td colspan='2'><b><em>" + q_("Script console") + ":</em></b></td></tr>\n";
×
405
        htmlText += "<tr><td>" + q_("Load script from file") + "</td>";
×
406
        htmlText += "<td><b>" + hotkeyTextWrapper("Ctrl+Shift+O") + "</b></td></tr>\n";
×
407
        htmlText += "<tr><td>" + q_("Save script to file") + "</td>";
×
408
        htmlText += "<td><b>" + hotkeyTextWrapper("Ctrl+Shift+S") + "</b></td></tr>\n";
×
409
        htmlText += "<tr><td>" + q_("Run script") + "</td>";
×
410
        htmlText += "<td><b>" + hotkeyTextWrapper("Ctrl+Return") + "</b></td></tr>\n";
×
411
        htmlText += "<tr><td colspan='2'><b><em>" + q_("Astronomical calculations") + ":</em></b></td></tr>\n";
×
412
        htmlText += "<tr><td>" + q_("Update positions") + "</td>";
×
413
        QString shiftF10 = hotkeyTextWrapper("Shift+F10");
×
414
        htmlText += "<td><b>" + shiftF10 + "</b></td></tr>\n";
×
415
        htmlText += "<tr><td>" + q_("Calculate ephemeris") + "</td>";
×
416
        htmlText += "<td><b>" + shiftF10 + "</b></td></tr>\n";
×
417
        // TRANSLATOR: RTS = rise, transit, set
418
        htmlText += "<tr><td>" + q_("Calculate RTS") + "</td>";
×
419
        htmlText += "<td><b>" + shiftF10 + "</b></td></tr>\n";
×
420
        htmlText += "<tr><td>" + q_("Calculate phenomena") + "</td>";
×
421
        htmlText += "<td><b>" + shiftF10 + "</b></td></tr>\n";
×
422
        htmlText += "<tr><td>" + q_("Calculate solar eclipses") + "</td>";
×
423
        htmlText += "<td><b>" + shiftF10 + "</b></td></tr>\n";
×
424
        htmlText += "<tr><td>" + q_("Calculate lunar eclipses") + "</td>";
×
425
        htmlText += "<td><b>" + shiftF10 + "</b></td></tr>\n";
×
426
        htmlText += "<tr><td>" + q_("Calculate transits") + "</td>";
×
427
        htmlText += "<td><b>" + shiftF10 + "</b></td></tr>\n";
×
428

429
        htmlText += "</table>";
×
430

431
        // Regexp to replace {text} with an HTML link.
432
        static const QRegularExpression a_rx("[{]([^{]*)[}]");
×
433

434
        // WARNING! Section titles are re-used above!
435
        htmlText += "<h2 id=\"links\">" + q_("Further Reading").toHtmlEscaped() + "</h2>\n";
×
436
        htmlText += q_("The following links are external web links, and will launch your web browser:\n").toHtmlEscaped();
×
437

438
        htmlText += "<p>";
×
439
        // TRANSLATORS: The text between braces is the text of an HTML link.
440
        htmlText += q_("{Frequently Asked Questions} about Stellarium.  Answers too.").toHtmlEscaped().replace(a_rx, "<a href=\"https://github.com/Stellarium/stellarium/wiki/FAQ\">\\1</a>");
×
441
        htmlText += "</p>\n";
×
442

443
        htmlText += "<p>";
×
444
        // TRANSLATORS: The text between braces is the text of an HTML link.
445
        htmlText += q_("{The Stellarium Wiki} - general information.").toHtmlEscaped().replace(a_rx, "<a href=\"https://github.com/Stellarium/stellarium/wiki\">\\1</a>");
×
446
        htmlText += "</p>\n";
×
447

448
        htmlText += "<p>";
×
449
        // TRANSLATORS: The text between braces is the text of an HTML link.
450
        htmlText += q_("{The landscapes} - user-contributed landscapes for Stellarium.").toHtmlEscaped().replace(a_rx, "<a href=\"https://stellarium.org/landscapes.html\">\\1</a>");
×
451
        htmlText += "</p>\n";
×
452

453
        htmlText += "<p>";
×
454
        // TRANSLATORS: The text between braces is the text of an HTML link.
455
        htmlText += q_("{The scripts} - user-contributed and official scripts for Stellarium.").toHtmlEscaped().replace(a_rx, "<a href=\"https://stellarium.org/scripts.html\">\\1</a>");
×
456
        htmlText += "</p>\n";
×
457

458
        htmlText += "<p>";
×
459
        // TRANSLATORS: The text between braces is the text of an HTML link.
460
        htmlText += q_("{Bug reporting and feature request system} - if something doesn't work properly or is missing and is not listed in the tracker, you can open bug reports here.").toHtmlEscaped().replace(a_rx, "<a href=\"https://github.com/Stellarium/stellarium/issues\">\\1</a>");
×
461
        htmlText += "</p>\n";
×
462

463
        htmlText += "<p>";
×
464
        // TRANSLATORS: The text between braces is the text of an HTML link.
465
        htmlText += q_("{Google Groups} - discuss Stellarium with other users.").toHtmlEscaped().replace(a_rx, "<a href=\"https://groups.google.com/forum/#!forum/stellarium\">\\1</a>");
×
466
        htmlText += "</p>\n";
×
467

468
        htmlText += "<p>";
×
469
        // TRANSLATORS: The text between braces is the text of an HTML link.
470
        htmlText += q_("{Open Collective} - donations to the Stellarium development team.").toHtmlEscaped().replace(a_rx, "<a href=\"https://opencollective.com/stellarium\">\\1</a>");
×
471
        htmlText += "</p>\n";
×
472

473
        htmlText += "</body></html>\n";
×
474

475
        ui->helpBrowser->clear();
×
476
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
477
        if (gui)
×
478
                ui->helpBrowser->document()->setDefaultStyleSheet(QString(gui->getStelStyle().htmlStyleSheet));
×
479
        ui->helpBrowser->insertHtml(htmlText);
×
480
        ui->helpBrowser->scrollToAnchor("top");
×
481
}
×
482

483
QString HelpDialog::hotkeyTextWrapper(const QString hotkey) const
×
484
{
485
        return QKeySequence(hotkey).toString(QKeySequence::NativeText);
×
486
}
487

488
void HelpDialog::updateAboutText(void) const
×
489
{
490
        QStringList allContributors = StelContributors::contributorsList;
×
491
        allContributors.sort();
×
492
        allContributors.removeDuplicates();
×
493

494
        typedef QPair<QString, int> donator;
495
        QVector<donator> financialContributors = {
496
                // Individuals
497
                { "Laurence Holt", 1000 }, { "John Bellora", 570 }, { "Jeff Moe (Spacecruft)", 512 }, { "Vernon Hermsen", 324 },
×
498
                { "Marla Pinaire", 320 }, { "Satish Mallesh", 260 }, { "Vlad Magdalin", 250  }, { "Philippe Renoux", 250 },
×
499
                { "Fito Martin", 250 },
×
500
                // Organizations
501
                { "Astronomie-Werkstatt \"Sterne ohne Grenzen\"", 580 }, { "Triplebyte", 280 }
×
502
        };
×
503
        std::sort(financialContributors.begin(), financialContributors.end(), [](donator i, donator j){ return i.second > j.second; });
×
504
        QStringList bestFinancialContributors;
×
505
        for (auto fc = financialContributors.begin(); fc != financialContributors.end(); ++fc)
×
506
        {
507
                bestFinancialContributors << fc->first;
×
508
        }
509

510
        // Regexp to replace {text} with an HTML link.
511
        static const QRegularExpression a_rx("[{]([^{]*)[}]");
×
512

513
        // populate About tab
514
        QString newHtml = "<h1>" + StelUtils::getApplicationName() + "</h1>";
×
515
        newHtml += QString("<p><strong>%1 %2").arg(q_("Version"), StelUtils::getApplicationVersion());
×
516
        newHtml += QString("<br />%1 %2</strong></p>").arg(q_("Based on Qt"), QT_VERSION_STR);
×
517
        if (!message.isEmpty())
×
518
                newHtml += "<p><strong>" + message + "</strong></p>";
×
519
        // Note: this legal notice is not suitable for translation
520
        newHtml += QString("<h3>%1</h3>").arg(STELLARIUM_COPYRIGHT);
×
521
        // newHtml += "<p><em>Version 0.15 is dedicated in memory of our team member Barry Gerdes.</em></p>";
522
        newHtml += "<p>This program is free software; you can redistribute it and/or ";
×
523
        newHtml += "modify it under the terms of the GNU General Public License ";
×
524
        newHtml += "as published by the Free Software Foundation; either version 2 ";
×
525
        newHtml += "of the License, or (at your option) any later version.</p>";
×
526
        newHtml += "<p>This program is distributed in the hope that it will be useful, ";
×
527
        newHtml += "but WITHOUT ANY WARRANTY; without even the implied ";
×
528
        newHtml += "warranty of MERCHANTABILITY or FITNESS FOR A ";
×
529
        newHtml += "PARTICULAR PURPOSE.  See the GNU General Public ";
×
530
        newHtml += "License for more details.</p>";
×
531
        newHtml += "<p>You should have received a copy of the GNU General Public ";
×
532
        newHtml += "License along with this program; if not, write to:</p>";
×
533
        newHtml += "<pre>Free Software Foundation, Inc.\n";
×
534
        newHtml += "51 Franklin Street, Suite 500\n";
×
535
        newHtml += "Boston, MA  02110-1335, USA.\n</pre>";
×
536
        newHtml += "<p><a href=\"http://www.fsf.org\">www.fsf.org</a></p>";
×
537
        newHtml += "<h3>" + q_("Developers").toHtmlEscaped() + "</h3><ul>";
×
538
        newHtml += "<li>" + q_("Project coordinator & lead developer: %1").arg(QString("Fabien Chéreau")).toHtmlEscaped() + "</li>";
×
539
        newHtml += "<li>" + q_("Graphic/other designer: %1").arg(QString("Martín Bernardi")).toHtmlEscaped() + "</li>";
×
540
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Guillaume Chéreau")).toHtmlEscaped() + "</li>";
×
541
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Georg Zotti")).toHtmlEscaped() + "</li>";
×
542
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Alexander V. Wolf")).toHtmlEscaped() + "</li>";
×
543
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Ruslan Kabatsayev")).toHtmlEscaped() + "</li>";
×
544
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Worachate Boonplod")).toHtmlEscaped() + "</li>";
×
545
        newHtml += "<li>" + q_("Sky cultures researcher: %1").arg(QString("Susanne M. Hoffmann")).toHtmlEscaped() + "</li>";
×
546
        newHtml += "<li>" + q_("Continuous Integration: %1").arg(QString("Hans Lambermont")).toHtmlEscaped() + "</li>";
×
547
        newHtml += "<li>" + q_("Tester: %1").arg(QString("Khalid AlAjaji")).toHtmlEscaped() + "</li></ul>";
×
548
        newHtml += "<h3>" + q_("Former Developers").toHtmlEscaped() + "</h3>";
×
549
        newHtml += "<p>"  + q_("Several people have made significant contributions, but are no longer active. Their work has made a big difference to the project:").toHtmlEscaped() + "</p><ul>";
×
550
        newHtml += "<li>" + q_("Graphic/other designer: %1").arg(QString("Johan Meuris")).toHtmlEscaped() + "</li>";
×
551
        newHtml += "<li>" + q_("Doc author/developer: %1").arg(QString("Matthew Gates")).toHtmlEscaped() + "</li>";
×
552
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Johannes Gajdosik")).toHtmlEscaped() + "</li>";
×
553
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Rob Spearman")).toHtmlEscaped() + "</li>";
×
554
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Bogdan Marinov")).toHtmlEscaped() + "</li>";
×
555
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Timothy Reaves")).toHtmlEscaped() + "</li>";
×
556
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Florian Schaukowitsch")).toHtmlEscaped() + "</li>";
×
557
        newHtml += "<li>" + q_("Developer: %1").arg(QString("András Mohari")).toHtmlEscaped() + "</li>";
×
558
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Mike Storm")).toHtmlEscaped() + "</li>";
×
559
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Ferdinand Majerech")).toHtmlEscaped() + "</li>";
×
560
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Jörg Müller")).toHtmlEscaped() + "</li>";
×
561
        newHtml += "<li>" + q_("Developer: %1").arg(QString("Marcos Cardinot")).toHtmlEscaped() + "</li>";        
×
562
        newHtml += "<li>" + q_("OSX Developer: %1").arg(QString("Nigel Kerr")).toHtmlEscaped() + "</li>";
×
563
        newHtml += "<li>" + q_("OSX Developer: %1").arg(QString("Diego Marcos")).toHtmlEscaped() + "</li></ul>";
×
564
        newHtml += "<h3>" + q_("Contributors").toHtmlEscaped() + "</h3>";
×
565
        newHtml += "<p>"  + q_("Many individuals have made contributions to the project and their work has made Stellarium better. Alphabetically sorted list of all contributors: %1.").arg(allContributors.join(", ")).toHtmlEscaped() + "</p>";
×
566
        newHtml += "<h3>" + q_("Financial support").toHtmlEscaped() + "</h3>";
×
567
        newHtml += "<p>"  + q_("Many individuals and organizations are supporting the development of Stellarium by donations, and the most generous financial contributors (with donations of $250 or more) are %1.").arg(bestFinancialContributors.join(", ")).toHtmlEscaped();
×
568
        // TRANSLATORS: The text between braces is the text of an HTML link.
569
        newHtml += " " + q_("The full list of financial contributors you may see on our {Open Collective page}.").toHtmlEscaped().replace(a_rx, "<a href=\"https://opencollective.com/stellarium\">\\1</a>") + "</p>";
×
570
        newHtml += "<h3>" + q_("Acknowledgment").toHtmlEscaped() + "</h3>";
×
571
        newHtml += "<p>"  + q_("If the Stellarium planetarium was helpful for your research work, the following acknowledgment would be appreciated:").toHtmlEscaped() + "</p>";
×
572
        newHtml += "<p><em>"  + q_("This research has made use of the Stellarium planetarium") + "</em></p>";
×
573
        newHtml += "<p>Zotti, G., Hoffmann, S. M., Wolf, A., Chéreau, F., & Chéreau, G. (2021). The Simulated Sky: Stellarium for Cultural Astronomy Research. Journal of Skyscape Archaeology, 6(2), 221–258. <a href='https://doi.org/10.1558/jsa.17822'>https://doi.org/10.1558/jsa.17822</a></p>";
×
574
        // TRANSLATORS: The text between braces is the text of an HTML link.
575
        newHtml += "<p>" + q_("Or you may {download the BibTeX file of the paper} to create another citation format.").toHtmlEscaped().replace(a_rx, "<a href=\"https://stellarium.org/files/stellarium.bib\">\\1</a>") + "</p>";
×
576
        newHtml += "<p>";
×
577

578
        ui->aboutBrowser->clear();
×
579
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
580
        if (gui)
×
581
                ui->aboutBrowser->document()->setDefaultStyleSheet(QString(gui->getStelStyle().htmlStyleSheet));
×
582
        ui->aboutBrowser->insertHtml(newHtml);
×
583
        ui->aboutBrowser->scrollToAnchor("top");
×
584
}
×
585

586
void HelpDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous)
×
587
{
588
        if (!current)
×
589
                current = previous;
×
590
        ui->stackedWidget->setCurrentIndex(ui->stackListWidget->row(current));
×
591
}
×
592

593
void HelpDialog::updateTabBarListWidgetWidth()
×
594
{
595
        ui->stackListWidget->setWrapping(false);
×
596
        // Update list item sizes after translation
597
        ui->stackListWidget->adjustSize();
×
598
        QAbstractItemModel* model = ui->stackListWidget->model();
×
599
        if (!model)
×
600
                return;
×
601

602
        // stackListWidget->font() does not work properly!
603
        // It has a incorrect fontSize in the first loading, which produces the bug#995107.
604
        QFont font;
×
605
        font.setPixelSize(14);
×
606
        font.setWeight(QFont::Bold);
×
607
        QFontMetrics fontMetrics(font);
×
608
        int iconSize = ui->stackListWidget->iconSize().width();
×
609
        int width = 0;
×
610
        for (int row = 0; row < model->rowCount(); row++)
×
611
        {
612
                int textWidth = fontMetrics.boundingRect(ui->stackListWidget->item(row)->text()).width();
×
613
                width += iconSize > textWidth ? iconSize : textWidth; // use the wider one
×
614
                width += 24; // margin - 12px left and 12px right
×
615
        }
616
        // Hack to force the window to be resized...
617
        ui->stackListWidget->setMinimumWidth(width);
×
618
        ui->stackListWidget->updateGeometry();
×
619
}
×
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