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

Stellarium / stellarium / 13149582607

03 Feb 2025 11:24AM UTC coverage: 12.101% (-0.04%) from 12.141%
13149582607

push

github

web-flow
Translate po/stellarium/stellarium.pot in zh_CN

100% translated source file: 'po/stellarium/stellarium.pot'
on 'zh_CN'.

14603 of 120671 relevant lines covered (12.1%)

18593.62 hits per line

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

0.0
/src/gui/ObsListDialog.cpp
1
/*
2
 * Stellarium
3
 * Copyright (C) 2020 Jocelyn GIROD
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (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 along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 */
19

20
#include <QDir>
21
#include <QFileDialog>
22
#include <QMessageBox>
23
#include <QUuid>
24

25
#include "StelTranslator.hpp"
26
#include "StelApp.hpp"
27
#include "StelMainView.hpp"
28
#include "StelObjectMgr.hpp"
29
#include "StelModuleMgr.hpp"
30
#include "StelLocationMgr.hpp"
31
#include "LandscapeMgr.hpp"
32
#include "StelFileMgr.hpp"
33
#include "StelPropertyMgr.hpp"
34
#include "StelMovementMgr.hpp"
35
#include "CustomObjectMgr.hpp"
36
#include "LandscapeMgr.hpp"
37
#include "HighlightMgr.hpp"
38
#include "StarMgr.hpp"
39
#include "NebulaMgr.hpp"
40
#include "StelCore.hpp"
41
#include "StelFileMgr.hpp"
42
#include "StelJsonParser.hpp"
43
#include "StelUtils.hpp"
44
#include "ObsListDialog.hpp"
45
#include "LabelMgr.hpp"
46
#include "StelLogger.hpp"
47

48
#include "ui_obsListDialog.h"
49

50
ObsListDialog::ObsListDialog(QObject *parent) :
×
51
        StelDialog("ObservingList", parent),
52
        ui(new Ui_obsListDialogForm()),
×
53
        core(StelApp::getInstance().getCore()),
×
54
        objectMgr(GETSTELMODULE(StelObjectMgr)),
×
55
        landscapeMgr(GETSTELMODULE(LandscapeMgr)),
×
56
        labelMgr(GETSTELMODULE(LabelMgr)),
×
57
        itemModel(new QStandardItemModel(0, ColumnCount)),
×
58
        observingListJsonPath(StelFileMgr::findFile("data", static_cast<StelFileMgr::Flags>(StelFileMgr::Directory | StelFileMgr::Writable)) + "/" + JSON_FILE_NAME),
×
59
        bookmarksJsonPath(    StelFileMgr::findFile("data", static_cast<StelFileMgr::Flags>(StelFileMgr::Directory | StelFileMgr::Writable)) + "/" + JSON_BOOKMARKS_FILE_NAME),
×
60
        tainted(false),
×
61
        isEditMode(false),
×
62
        isCreationMode(false)
×
63
{
64
        setObjectName("ObsListDialog");
×
65
        StelApp::getInstance().getStelPropertyManager()->registerObject(this);
×
66
        //Initialize the list of observing lists
67
        setObservingListHeaderNames();
×
68

69
        QSettings* conf  = StelApp::getInstance().getSettings();
×
70
        flagUseJD        = conf->value("bookmarks/useJD", false).toBool();
×
71
        flagUseLandscape = conf->value("bookmarks/useLandscape", false).toBool();
×
72
        flagUseLocation  = conf->value("bookmarks/useLocation", false).toBool();
×
73
        flagUseFov       = conf->value("bookmarks/useFOV", false).toBool();
×
74
}
×
75

76
ObsListDialog::~ObsListDialog() {
×
77
        // Only on exit we may need to write
78
        if (tainted)
×
79
        {
80
                // At this point we have added our lists to the observingLists map. Now update the jsonMap and store to file.
81
                QFile jsonFile(observingListJsonPath);
×
82
                if (!jsonFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
×
83
                        qWarning() << "[ObservingList] bookmarks list can not be saved. A file can not be open for reading and writing:"
×
84
                                   << QDir::toNativeSeparators(observingListJsonPath);
×
85
                        messageBox(q_("Error"), q_("Cannot open observingLists.json to write"));
×
86
                        return;
×
87
                }
88
                // Update the jsonMap and store
89
                jsonMap.insert(KEY_OBSERVING_LISTS, observingLists);
×
90
                jsonFile.resize(0);
×
91
                StelJsonParser::write(jsonMap, &jsonFile);
×
92
                jsonFile.flush();
×
93
                jsonFile.close();
×
94
        }
×
95

96
        delete ui;
×
97
        delete itemModel;
×
98
        ui = nullptr;
×
99
        itemModel = nullptr;
×
100
}
×
101

102
/*
103
 * Initialize the dialog widgets and connect the signals/slots.
104
*/
105
void ObsListDialog::createDialogContent()
×
106
{
107
        ui->setupUi(dialog);
×
108

109
        //Signals and slots
110
        connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslate()));
×
111
        connect(ui->titleBar, &TitleBar::closeClicked, this, &StelDialog::close);
×
112

113
        // Standard mode buttons: NewList/EditList/DeleteList
114
        connect(ui->newListButton,        SIGNAL(clicked()), this, SLOT(   newListButtonPressed()));
×
115
        connect(ui->editListButton,       SIGNAL(clicked()), this, SLOT(  editListButtonPressed()));
×
116
        connect(ui->deleteListButton,     SIGNAL(clicked()), this, SLOT(deleteListButtonPressed()));
×
117
        connect(ui->importListButton,     SIGNAL(clicked()), this, SLOT(importListButtonPressed()));
×
118
        connect(ui->exportListButton,     SIGNAL(clicked()), this, SLOT(exportListButtonPressed()));
×
119
        // Mark all objects of currentList in the sky
120
        connect(ui->highlightAllButton,   SIGNAL(clicked()), this, SLOT(highlightAll()));
×
121
        connect(ui->clearHighlightButton, SIGNAL(clicked()), this, SLOT(clearHighlights()));
×
122
        // Edits
123
        connect(ui->addObjectButton,      SIGNAL(clicked()), this, SLOT(   addObjectButtonPressed()));
×
124
        connect(ui->removeObjectButton,   SIGNAL(clicked()), this, SLOT(removeObjectButtonPressed()));
×
125
        connect(ui->saveButton,           SIGNAL(clicked()), this, SLOT(  saveButtonPressed()));
×
126
        connect(ui->cancelButton,         SIGNAL(clicked()), this, SLOT(cancelButtonPressed()));
×
127

128
        connect(ui->defaultListCheckBox, SIGNAL(clicked(bool)), this, SLOT(defaultClicked(bool)));
×
129

130
        // Allow loading one list entry
131
        connect(ui->treeView,           SIGNAL(doubleClicked(QModelIndex)), this, SLOT(selectAndGoToObject(QModelIndex)));
×
132

133
        switchEditMode(false, false); // start with view mode
×
134

135
        connectBoolProperty(ui->jdCheckBox,        "ObsListDialog.flagUseJD");
×
136
        connectBoolProperty(ui->locationCheckBox,  "ObsListDialog.flagUseLocation");
×
137
        connectBoolProperty(ui->landscapeCheckBox, "ObsListDialog.flagUseLandscape");
×
138
        connectBoolProperty(ui->fovCheckBox,       "ObsListDialog.flagUseFov");
×
139

140
        ui->obsListDirEdit->setText(StelFileMgr::getObsListDir());
×
141
        connect(ui->obsListDirEdit, SIGNAL(editingFinished()), this, SLOT(selectObsListDir()));
×
142
        connect(ui->obsListBrowseButton, SIGNAL(clicked()), this, SLOT(browseForObsListDir()));
×
143

144

145
        //obsListCombo settings: A change in the combobox loads the list.
146
        connect(ui->obsListComboBox, SIGNAL(activated(int)), this, SLOT(loadSelectedObservingList(int)));
×
147

148
        ui->treeView->setModel(itemModel);
×
149
        ui->treeView->header()->setSectionsMovable(false);
×
150
        ui->treeView->hideColumn(ColumnUUID);
×
151
        for (int c=ColumnDesignation; c<=ColumnLandscapeID; c++)
×
152
                ui->treeView->header()->setSectionResizeMode(c, QHeaderView::ResizeToContents);
×
153
        ui->treeView->header()->setStretchLastSection(true);
×
154
        //Enable the sort for columns
155
        ui->treeView->setSortingEnabled(true);
×
156
        connect(ui->treeView->header(), SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int)));
×
157

158
        // Load all observing lists from JSON.
159
        // We need to load the global list only once!
160
        QFile jsonFile(observingListJsonPath);
×
161
        if (!jsonFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
×
162
                qWarning() << "[ObservingList] JSON list file can not be opened for reading and writing:"
×
163
                           << QDir::toNativeSeparators(observingListJsonPath);
×
164
                return;
×
165
        }
166
        if (jsonFile.size() > 0) {
×
167
                jsonMap = StelJsonParser::parse(jsonFile.readAll()).toMap();
×
168
                observingLists = jsonMap.value(KEY_OBSERVING_LISTS).toMap();
×
169
        }
170
        else
171
        {
172
                // begin with empty maps
173
                const QString olud=QUuid::createUuid().toString();
×
174
                jsonMap = { {KEY_SHORT_NAME       , SHORT_NAME_VALUE},
175
                            {KEY_VERSION          , FILE_VERSION},
176
                            {KEY_DEFAULT_LIST_OLUD, olud}};
×
177
                observingLists = QMap<QString, QVariant>();
×
178
                // Create one default empty list
179
                // Creation date
180
                const double JD = StelUtils::getJDFromSystem();
×
181
                const QString listCreationDate = StelUtils::julianDayToISO8601String(JD + core->getUTCOffset(JD) / 24.).replace("T", " ");
×
182
                QVariantMap emptyList = {
183
                        // Name, description, current date for the list, current sorting
184
                        {KEY_NAME,          qc_("new list", "default name for observing list if none is available")},
×
185
                        {KEY_DESCRIPTION,   QString()},
×
186
                        {KEY_SORTING,       QString()},
×
187
                        {KEY_CREATION_DATE, listCreationDate },
188
                        {KEY_LAST_EDIT,     listCreationDate }};
×
189

190
                observingLists.insert(olud, emptyList);
×
191
                jsonMap.insert(KEY_OBSERVING_LISTS, observingLists);
×
192
        }
×
193

194
        // For no regression we must take into account the legacy bookmarks file
195
        QFile jsonBookmarksFile(bookmarksJsonPath);
×
196
        if (jsonBookmarksFile.exists())
×
197
        {
198
                //qDebug() << "Old Bookmarks found: Try if we need to process/import them";
199
                if (!checkIfBookmarksListExists())
×
200
                {
201
                        //qDebug() << "No bookmark list so far. Importing...";
202
                        QHash<QString, observingListItem> bookmarksForImport=loadBookmarksFile(jsonBookmarksFile);
×
203
                        saveBookmarksHashInObservingLists(bookmarksForImport);
×
204
                        jsonMap.insert(KEY_OBSERVING_LISTS, observingLists); // Update the global map
×
205
                }
×
206
                //else
207
                //        qDebug() << "Bookmark list exists. We can skip the import.";
208

209
                jsonFile.resize(0);
×
210
                StelJsonParser::write(jsonMap, &jsonFile);
×
211
                jsonFile.flush();
×
212
                jsonFile.close();
×
213
                tainted=false;
×
214
        }
215
        // Now we certainly have a json file and have parsed everything that exists.
216
        defaultOlud = jsonMap.value(KEY_DEFAULT_LIST_OLUD).toString();
×
217
        loadListNames(); // also populate Combobox and make sure at least some defaultOlud exists.
×
218
        loadDefaultList();
×
219
}
×
220

221
void ObsListDialog::browseForObsListDir()
×
222
{
223
        const QString &oldObsListDir = StelFileMgr::getObsListDir();
×
224
        QString newObsListDir = QFileDialog::getExistingDirectory(&StelMainView::getInstance(), q_("Select observing lists directory"), oldObsListDir, QFileDialog::ShowDirsOnly);
×
225

226
        if (!newObsListDir.isEmpty()) {
×
227
                // remove trailing slash
228
                if (newObsListDir.right(1) == "/")
×
229
                        newObsListDir = newObsListDir.left(newObsListDir.length()-1);
×
230

231
                ui->obsListDirEdit->setText(newObsListDir);
×
232
                selectObsListDir();
×
233
        }
234
}
×
235

236
void ObsListDialog::selectObsListDir()
×
237
{
238
        QString dir = ui->obsListDirEdit->text();
×
239
        try
240
        {
241
                StelFileMgr::setObsListDir(dir);
×
242
                QSettings* conf = StelApp::getInstance().getSettings();
×
243
                conf->setValue("main/observinglists_dir", dir);
×
244
        }
245
        catch (std::runtime_error& e)
×
246
        {
247
                Q_UNUSED(e)
248
                // nop
249
                // this will happen when people are only half way through typing dirs
250
        }
×
251
}
×
252

253
/*
254
 * Check if bookmarks list already exists in observing list file,
255
 * in fact if the file of bookmarks has already be loaded.
256
*/
257
bool ObsListDialog::checkIfBookmarksListExists()
×
258
{
259
        QMapIterator<QString,QVariant>it(observingLists);
×
260
        while(it.hasNext())
×
261
        {
262
                it.next();
×
263
                QVariantMap map = it.value().toMap();
×
264
                QString listName = map.value(KEY_NAME).toString();
×
265

266
                if (BOOKMARKS_LIST_NAME == listName)
×
267
                        return true;
×
268
        }
×
269
        return false;
×
270
}
×
271

272
/*
273
 * Retranslate dialog
274
*/
275
void ObsListDialog::retranslate()
×
276
{
277
        if (dialog)
×
278
        {
279
                ui->retranslateUi(dialog);
×
280
                setObservingListHeaderNames();
×
281
        }
282
}
×
283

284
/*
285
 * Set the header for the observing list table (obsListTreeView)
286
*/
287
void ObsListDialog::setObservingListHeaderNames()
×
288
{
289
        const QStringList headerStrings = {
290
                "UUID",                     // Hidden column
291
                q_("Object designation"),   // English name and/or catalog number
292
                q_("Object name"),          // Localized name
293
                q_("Type"),                 // Localized type description (not just class name)
294
                q_("Right ascension"),      // J2000.0 RA
295
                q_("Declination"),          // J2000.0 DE
296
                q_("Magnitude"),            // visual magnitude
297
                q_("Constellation"),        // IAU constellation code
298
                q_("Date"),                 // date string (if stored)
299
                q_("Location"),             // location (if stored)
300
                q_("Landscape")             // landscape ID (if stored)
301
        };
×
302
        Q_ASSERT(headerStrings.length()==ColumnCount);
×
303
        itemModel->setHorizontalHeaderLabels(headerStrings);
×
304
}
×
305

306
/*
307
 * Add row in the obsListListModel
308
*/
309
void ObsListDialog::addModelRow(const QString &olud, const QString &designation, const QString &nameI18n,
×
310
                                const QString &typeI18n, const QString &ra,
311
                                const QString &dec, const QString &magnitude, const QString &constellation,
312
                                const QString &date, const QString &location, const QString &landscapeID)
313
{
314
        const int number=itemModel->rowCount();
×
315
        QStandardItem *item = nullptr;
×
316

317
        item = new QStandardItem(olud);
×
318
        item->setEditable(false);
×
319
        itemModel->setItem(number, ColumnUUID, item);
×
320

321
        item = new QStandardItem(designation);
×
322
        item->setEditable(false);
×
323
        itemModel->setItem(number, ColumnDesignation, item);
×
324

325
        item = new QStandardItem(nameI18n);
×
326
        item->setEditable(false);
×
327
        itemModel->setItem(number, ColumnNameI18n, item);
×
328

329
        item = new QStandardItem(typeI18n);
×
330
        item->setEditable(false);
×
331
        itemModel->setItem(number, ColumnType, item);
×
332

333
        item = new QStandardItem(ra);
×
334
        item->setEditable(false);
×
335
        itemModel->setItem(number, ColumnRa, item);
×
336

337
        item = new QStandardItem(dec);
×
338
        item->setEditable(false);
×
339
        itemModel->setItem(number, ColumnDec, item);
×
340

341
        item = new QStandardItem(magnitude);
×
342
        item->setEditable(false);
×
343
        itemModel->setItem(number, ColumnMagnitude, item);
×
344

345
        item = new QStandardItem(constellation);
×
346
        item->setEditable(false);
×
347
        itemModel->setItem(number, ColumnConstellation, item);
×
348

349
        item = new QStandardItem(date);
×
350
        item->setEditable(false);
×
351
        itemModel->setItem(number, ColumnDate, item);
×
352

353
        item = new QStandardItem(location);
×
354
        item->setEditable(false);
×
355
        itemModel->setItem(number, ColumnLocation, item);
×
356

357
        item = new QStandardItem(landscapeID);
×
358
        item->setEditable(false);
×
359
        itemModel->setItem(number, ColumnLandscapeID, item);
×
360

361
        for (int i = 0; i < ColumnCount; ++i)
×
362
                ui->treeView->resizeColumnToContents(i);
×
363
}
×
364

365
/*
366
 * Load the lists names from jsonMap,
367
 * Populate the list names into combo box and extract defaultOlud
368
*/
369
void ObsListDialog::loadListNames(const QString& listID)
×
370
{
371
        listNames.clear();
×
372
        QVariantMap::iterator i;
×
373
        // Clean list of OL to avoid duplicates
374
        ui->obsListComboBox->clear();
×
375

376
        // Add the list name and OLUD (as item data) into the ComboBox.
377
        for (i = observingLists.begin(); i != observingLists.end(); ++i) {
×
378
                const QString &listUuid = i.key();
×
379
                if (i.value().canConvert<QVariantMap>()) // if this looks like an actual obsList?
×
380
                {
381
                        QVariant var = i.value();
×
382
                        QVariantMap data = var.value<QVariantMap>();
×
383
                        QString listName = data.value(KEY_NAME).toString();
×
384
                        listNames.append(listName);
×
385
                        ui->obsListComboBox->addItem(listName, listUuid);
×
386
                }
×
387
        }
388
        ui->obsListComboBox->model()->sort(0);
×
389
        if (!listID.isEmpty())
×
390
        {
391
                // select observing list by OLUD
392
                int idx = ui->obsListComboBox->findData(listID, Qt::UserRole);
×
393
                if (idx<0)
×
394
                        idx = 0;
×
395
                ui->obsListComboBox->setCurrentIndex(idx);
×
396
        }
397

398
        // If defaultOlud list not found, set first list as default.
399
        if (!observingLists.contains(defaultOlud))
×
400
        {
401
                qDebug() << "populateListNameInComboBox: Cannot find defaultListOlud" << defaultOlud << ". Setting to first list.";
×
402
                defaultOlud = observingLists.firstKey();
×
403
                jsonMap.insert(KEY_DEFAULT_LIST_OLUD, defaultOlud);
×
404
                tainted=true;
×
405
        }
406
}
×
407

408
/*
409
 * Load the default list
410
*/
411
void ObsListDialog::loadDefaultList()
×
412
{
413
        if (defaultOlud != "")
×
414
        {
415
                int index = ui->obsListComboBox->findData(defaultOlud);
×
416
                if (index != -1)
×
417
                {
418
                        ui->obsListComboBox->setCurrentIndex(index);
×
419
                        selectedOlud = defaultOlud;
×
420
                }
421
        }
422
        else
423
        {
424
                // If there is no default list we load the current, or the first list in the combo box
425
                int currentIndex = ui->obsListComboBox->currentIndex();
×
426
                if (currentIndex != -1)
×
427
                {
428
                        currentIndex=0;
×
429
                        ui->obsListComboBox->setCurrentIndex(0);
×
430
                }
431
                selectedOlud = ui->obsListComboBox->itemData(currentIndex).toString();
×
432
                defaultOlud = selectedOlud;
×
433
                jsonMap.insert(KEY_DEFAULT_LIST_OLUD, defaultOlud);
×
434
                tainted=true;
×
435
        }
436
        loadSelectedList();
×
437
}
×
438

439
/*
440
 * Load the selected observing list (selectedOlud) into the dialog.
441
*/
442
void ObsListDialog::loadSelectedList()
×
443
{
444
        // At this point selectedOlud must be set
445
        Q_ASSERT(selectedOlud.length()>0);
×
446

447
        bool conversionError=false;
×
448
        // We must keep selection for the user. It is not enough to store/restore the existingSelection.
449
        // The QList<StelObjectP> objects are apparently volatile. We must retrieve the actual object.
450
        const QList<StelObjectP>&existingSelection = objectMgr->getSelectedObject();
×
451
        QList<StelObjectP> existingSelectionToRestore;
×
452
        if (existingSelection.length()>0)
×
453
        {
454
                existingSelectionToRestore.append(existingSelection.at(0));
×
455
        }
456

457
        // Check or not default list checkbox information
458
        ui->defaultListCheckBox->setChecked(selectedOlud == defaultOlud);
×
459

460
        QVariantMap observingListMap = observingLists.value(selectedOlud).toMap();
×
461

462
        QVariantList listOfObjects;
×
463

464
        // Display description and creation date
465
        currentListName=observingListMap.value(KEY_NAME).toString();
×
466
        ui->listNameLineEdit->setText(currentListName);
×
467
        ui->descriptionLineEdit->setText(observingListMap.value(KEY_DESCRIPTION).toString());
×
468
        ui->creationDateLineEdit->setText(observingListMap.value(KEY_CREATION_DATE).toString());
×
469
        ui->lastEditLineEdit->setText(observingListMap.value(KEY_LAST_EDIT, observingListMap.value(KEY_CREATION_DATE)).toString());
×
470

471
        if (observingListMap.value(KEY_OBJECTS).canConvert<QVariantList>())
×
472
        {
473
                QVariant data = observingListMap.value(KEY_OBJECTS);
×
474
                listOfObjects = data.value<QVariantList>();
×
475
        }
×
476
        else
477
        {
478
                qCritical() << "[ObservingList] conversion error in list " << currentListName << "from" << observingListMap.value(KEY_CREATION_DATE).toString();
×
479
                qCritical() << "Cannot convert this objects entry:" << observingListMap.value(KEY_OBJECTS);
×
480
                conversionError=true;
×
481
        }
482

483
        // Clear model
484
        itemModel->removeRows(0, itemModel->rowCount()); // don't use clear() here!
×
485
        currentItemCollection.clear();
×
486

487
        if (!listOfObjects.isEmpty())
×
488
        {
489
                for (const QVariant &object: listOfObjects)
×
490
                {
491
                        if (object.canConvert<QVariantMap>())
×
492
                        {
493
                                QVariantMap objectMap = object.value<QVariantMap>();
×
494

495
                                observingListItem item;
×
496
                                const QString objectUUID = QUuid::createUuid().toString();
×
497
                                item.designation = objectMap.value(KEY_DESIGNATION).toString();  // This is the common name or catalog number (with catalog ID)
×
498
                                item.name = objectMap.value(KEY_NAME).toString();          // Preliminary: Do not rely on name in the JSON file. It may have changed in Stellarium's name lists! Retrieve name from the actual object later.
×
499
                                item.nameI18n = objectMap.value(KEY_NAME_I18N).toString(); // Preliminary: Do not rely on translated name in the JSON file. It may be in the wrong language or may have changed in Stellarium's name lists! Retrieve translated name from the actual object later.
×
500
                                item.objClass = objectMap.value(KEY_TYPE).toString();
×
501
                                item.objTypeI18n  = objectMap.value(KEY_OBJECTS_TYPE).toString(); // Preliminary: Do not rely on this translated string! Re-retrieve later
×
502
                                item.ra  = objectMap.value(KEY_RA).toString();
×
503
                                item.dec = objectMap.value(KEY_DEC).toString();
×
504
                                QList<StelObjectP> selectedObject;
×
505

506
                                if (objectMgr->findAndSelect(item.designation, item.objClass) && !objectMgr->getSelectedObject().isEmpty())
×
507
                                {
508
                                        //qDebug() << "ObsList: found an object of objClass" << item.objClass << "for" << item.designation;
509
                                        selectedObject = objectMgr->getSelectedObject();
×
510
                                }
511
                                else // try findAndSelect with any type. Note that this may lead to confusion!
512
                                        if (objectMgr->findAndSelect(item.designation) && !objectMgr->getSelectedObject().isEmpty())
×
513
                                {
514
                                        selectedObject = objectMgr->getSelectedObject();
×
515
                                        //qDebug() << "Changing item.objClass " << item.objClass << "to" << selectedObject[0]->getType();
516
                                        item.objClass = selectedObject[0]->getType();
×
517
                                }
518

519
                                if (!selectedObject.isEmpty())
×
520
                                {
521
                                        double ra, dec;
522
                                        StelUtils::rectToSphe(&ra, &dec, selectedObject[0]->getJ2000EquatorialPos(core));
×
523

524
                                        if (item.ra.isEmpty())
×
525
                                                item.ra = StelUtils::radToHmsStr(ra, false).trimmed();
×
526
                                        if (item.dec.isEmpty())
×
527
                                                item.dec = StelUtils::radToDmsStr(dec, false).trimmed();
×
528
                                        item.objTypeI18n = selectedObject[0]->getObjectTypeI18n();
×
529
                                        item.name=selectedObject[0]->getEnglishName();
×
530
                                        item.nameI18n=selectedObject[0]->getNameI18n();
×
531
                                }
532
                                else
533
                                {
534
                                        qWarning() << "[ObservingList] object: " << item.designation << " not found or empty.";
×
535
                                        qWarning() << "item.objType given as:" << item.objTypeI18n;
×
536
                                        qWarning() << "item.objClass given as:" << item.objClass;
×
537
                                }
538

539
                                item.magnitude = objectMap.value(KEY_MAGNITUDE).toString();
×
540
                                item.constellation = objectMap.value(KEY_CONSTELLATION).toString();
×
541

542
                                // Julian Day / Date
543
                                item.jd = objectMap.value(KEY_JD).toDouble();
×
544
                                QString dateStr;
×
545
                                if (item.jd != 0.)
×
546
                                        dateStr = StelUtils::julianDayToISO8601String(item.jd + core->getUTCOffset(item.jd) / 24.).replace("T", " ");
×
547

548
                                // Location, landscapeID, FoV (may be empty)
549
                                item.location = objectMap.value(KEY_LOCATION).toString();
×
550
                                item.landscapeID = objectMap.value(KEY_LANDSCAPE_ID).toString();
×
551

552
                                const QSettings* conf  = StelApp::getInstance().getSettings();
×
553
                                const double minFov=conf->value("navigation/min_fov", 1./3600.).toDouble();
×
554
                                item.fov = qBound(minFov, objectMap.value(KEY_FOV).toDouble(), 360.);
×
555

556
                                // Visible flag
557
                                item.isVisibleMarker = objectMap.value(KEY_IS_VISIBLE_MARKER).toBool();
×
558

559
                                QString LocationStr;
×
560
                                if (!item.location.isEmpty())
×
561
                                {
562
                                        StelLocation loc=StelApp::getInstance().getLocationMgr().locationForString(item.location);
×
563
                                        LocationStr=loc.name;
×
564
                                }
×
565

566
                                addModelRow(objectUUID,
×
567
                                            item.designation,
568
                                            item.nameI18n,
569
                                            item.objTypeI18n,
570
                                            item.ra,
571
                                            item.dec,
572
                                            item.magnitude,
573
                                            item.constellation,
574
                                            dateStr,
575
                                            LocationStr,
576
                                            item.landscapeID);
577

578
                                currentItemCollection.insert(objectUUID, item);
×
579
                        }
×
580
                        else
581
                        {
582
                                qCritical() << "[ObservingList] conversion error for object: "  << object;
×
583
                                conversionError=true;
×
584
                        }
585
                }
586
        }
587

588
        if (conversionError)
×
589
        {
590
                QMessageBox::warning(&StelMainView::getInstance(), q_("Attention!"), q_("Error during conversion. Please see logfile for details."));
×
591
                return;
×
592
        }
593

594
        // Sorting for the objects list.
595
        QString sortingBy = observingListMap.value(KEY_SORTING).toString();
×
596
        if (!sortingBy.isEmpty())
×
597
                sortObsListTreeViewByColumnName(sortingBy);
×
598

599
        // Restore selection that was active before calling this
600
        if (existingSelectionToRestore.length()>0)
×
601
                objectMgr->setSelectedObject(existingSelectionToRestore, StelModule::ReplaceSelection);
×
602
        else
603
                objectMgr->unSelect();
×
604
}
×
605

606
/*
607
 * Load the bookmarks of bookmarks.json file into observing lists file
608
*/
609
QHash<QString, ObsListDialog::observingListItem> ObsListDialog::loadBookmarksFile(QFile &file)
×
610
{
611
        qWarning() << "DEPRECATION WARNING";
×
612
        qWarning() << "  Loading old-style Bookmarks file. This file format is deprecated.";
×
613
        qWarning() << "  If you are loading this as a separate file, ";
×
614
        qWarning() << "  Please update the file (re-export the list into *.sol format).";
×
615
        bool importWarning=false;
×
616

617
        QHash<QString, observingListItem> bookmarksItemHash;
×
618

619
        if (!file.open(QIODevice::ReadOnly)) {
×
620
                qWarning() << "[ObservingList] cannot open" << QDir::toNativeSeparators(bookmarksJsonPath);
×
621
        }
622
        else
623
        {
624
                const double currentJD=core->getJDOfLastJDUpdate();// Restore at end
×
625
                const qint64 millis = core->getMilliSecondsOfLastJDUpdate();
×
626

627
                // We must keep selection for the user!
628
                const QList<StelObjectP>&existingSelection = objectMgr->getSelectedObject();
×
629
                QList<StelObjectP> existingSelectionToRestore;
×
630
                if (existingSelection.length()>0)
×
631
                {
632
                        existingSelectionToRestore.append(existingSelection.at(0));
×
633
                }
634

635
                try {
636
                        QVariantMap map = StelJsonParser::parse(file.readAll()).toMap();
×
637
                        file.close();
×
638
                        QVariantMap bookmarksMap = map.value(KEY_BOOKMARKS).toMap();
×
639

640
                        QMapIterator<QString,QVariant>it(bookmarksMap);
×
641
                        while(it.hasNext())
×
642
                        {
643
                                it.next();
×
644

645
                                QVariantMap bookmarkMap = it.value().toMap();
×
646
                                observingListItem item;
×
647

648
                                // Name
649
                                item.designation = bookmarkMap.value(KEY_NAME).toString();
×
650
                                QString nameI18n = bookmarkMap.value(KEY_NAME_I18N).toString();
×
651
                                item.nameI18n = nameI18n.isEmpty() ? DASH : nameI18n;
×
652

653
                                // We need to select the object to add additional information that is not in the Bookmark file
654
                                if (objectMgr->findAndSelect(item.designation) && !objectMgr->getSelectedObject().isEmpty()) {
×
655
                                        const QList<StelObjectP> &selectedObject = objectMgr->getSelectedObject();
×
656

657
                                        item.objClass = selectedObject[0]->getType(); // Assign class name
×
658
                                        item.objTypeI18n = selectedObject[0]->getObjectTypeI18n(); // Assign a detailed object type description
×
659
                                        item.name = selectedObject[0]->getEnglishName();
×
660
                                        item.nameI18n = selectedObject[0]->getNameI18n();
×
661
                                        item.jd = bookmarkMap.value(KEY_JD).toDouble();
×
662
                                        if (item.jd!=0.)
×
663
                                        {
664
                                                core->setJD(item.jd);
×
665
                                                core->update(0.); // Force position updates
×
666
                                        }
667

668
                                        // Ra & Dec - ra and dec are not empty in case of Custom Object
669
                                        item.ra = bookmarkMap.value(KEY_RA).toString();
×
670
                                        item.dec = bookmarkMap.value(KEY_DEC).toString();
×
671
                                        if (item.ra.isEmpty() || item.dec.isEmpty()) {
×
672
                                                double ra, dec;
673
                                                StelUtils::rectToSphe(&ra, &dec, selectedObject[0]->getJ2000EquatorialPos(core));
×
674
                                                item.ra = StelUtils::radToHmsStr(ra, false).trimmed();
×
675
                                                item.dec = StelUtils::radToDmsStr(dec, false).trimmed();
×
676
                                        }
677
                                        item.magnitude = getMagnitude(selectedObject, core);
×
678
                                        // Several data items were not part of the original bookmarks, so we have no entry.
679
                                        const Vec3d posNow = selectedObject[0]->getEquinoxEquatorialPos(core);
×
680
                                        item.constellation = core->getIAUConstellation(posNow);
×
681
                                        item.location = bookmarkMap.value(KEY_LOCATION).toString();
×
682
                                        // No landscape in original bookmarks. Just leave empty.
683
                                        //item.landscapeID = bookmarkData.value(KEY_LANDSCAPE_ID).toString();
684
                                        double bmFov = bookmarkMap.value(KEY_FOV).toDouble();
×
685
                                        if (bmFov>1.e-10) // FoV may look like 3.121251e-310, which is bogus.
×
686
                                                item.fov=bmFov;
×
687
                                        item.isVisibleMarker = bookmarkMap.value(KEY_IS_VISIBLE_MARKER, false).toBool();
×
688

689
                                        bookmarksItemHash.insert(it.key(), item);
×
690
                                }
691
                                else
692
                                {
693
                                        qWarning() << "Bookmark import: Cannot find Object " << item.designation << "(" << nameI18n << ")";
×
694
                                        importWarning=true;
×
695
                                }
696
                        }
×
697
                        if (importWarning)
×
698
                        {
699
                                qWarning() << "Some bookmarked objects in file" << file.fileName() << "were not found.";
×
700
                                qWarning() << "If these are Solar System objects, make sure you have imported the respective orbital elements, "
×
701
                                              "and the file loads without warnings in the current version.";
×
702
                                messageBox(q_("Note"), q_("Some bookmarked objects were not found. See logfile for details."));
×
703
                        }
704
                }
×
705
                catch (std::runtime_error &e)
×
706
                {
707
                        qWarning() << "[ObservingList] Load bookmarks in observing list: File format is wrong! Error: " << e.what();
×
708
                }
×
709
                // Restore selection that was active before calling this
710
                if (existingSelectionToRestore.length()>0)
×
711
                        objectMgr->setSelectedObject(existingSelectionToRestore, StelModule::ReplaceSelection);
×
712
                else
713
                        objectMgr->unSelect();
×
714

715
                core->setJD(currentJD);
×
716
                core->setMilliSecondsOfLastJDUpdate(millis); // restore millis.
×
717
                core->update(0); // enforce update to the previous positions
×
718
        }
×
719
        return bookmarksItemHash;
×
720
}
×
721

722
/*
723
 * Save the bookmarks into observingLists QVariantMap
724
*/
725
QString ObsListDialog::saveBookmarksHashInObservingLists(const QHash<QString, observingListItem> &bookmarksHash)
×
726
{
727
        // Creation date
728
        double JD = StelUtils::getJDFromSystem(); // Mark with current system time
×
729
        QString listCreationDate = StelUtils::julianDayToISO8601String(JD + core->getUTCOffset(JD) / 24.).replace("T", " ");
×
730

731
        QVariantMap bookmarksObsList = {
732
                {KEY_NAME,          BOOKMARKS_LIST_NAME},
733
                {KEY_DESCRIPTION,   BOOKMARKS_LIST_DESCRIPTION},
734
                {KEY_CREATION_DATE, listCreationDate},
735
                {KEY_LAST_EDIT,     listCreationDate},
736
                {KEY_SORTING,       SORTING_BY_NAME}};
×
737

738
        // Add actual list of (former) bookmark entries
739
        QVariantList objects;
×
740
        QHashIterator<QString, observingListItem> it(bookmarksHash);
×
741
        while (it.hasNext())
×
742
        {
743
                it.next();
×
744
                observingListItem item = it.value();
×
745
                objects.push_back(item.toVariantMap());
×
746
        }
×
747
        bookmarksObsList.insert(KEY_OBJECTS, objects);
×
748

749
        QList<QString> keys = bookmarksHash.keys();
×
750
        QString bookmarkListOlud= (keys.empty() ? QUuid::createUuid().toString() : keys.at(0));
×
751

752
        observingLists.insert(bookmarkListOlud, bookmarksObsList);
×
753
        return bookmarkListOlud;
×
754
}
×
755

756
/*
757
 * Select and go to object
758
*/
759
void ObsListDialog::selectAndGoToObject(QModelIndex index)
×
760
{
761
        QStandardItem *selectedItem = itemModel->itemFromIndex(index);
×
762
        int rowNumber = selectedItem->row();
×
763

764
        QStandardItem *uuidItem = itemModel->item(rowNumber, ColumnUUID);
×
765
        QString itemUuid = uuidItem->text();
×
766
        observingListItem item = currentItemCollection.value(itemUuid);
×
767

768
        // Load landscape/location before dealing with the object: It could be a view from another planet!
769
        // We load stored landscape/location if the respective checkbox is checked.
770
        if (getFlagUseLandscape() && !item.landscapeID.isEmpty())
×
771
                GETSTELMODULE(LandscapeMgr)->setCurrentLandscapeID(item.landscapeID, 0);
×
772
        if (getFlagUseLocation() && !item.location.isEmpty())
×
773
        {
774
                StelLocation loc=StelApp::getInstance().getLocationMgr().locationForString(item.location);
×
775
                if (loc.isValid())
×
776
                        core->moveObserverTo(loc);
×
777
                else
778
                        qWarning() << "ObservingLists: Cannot retrieve valid location for" << item.location;
×
779
        }
×
780
        // We also use stored jd only if the checkbox JD is checked.
781
        if (getFlagUseJD() && item.jd != 0.0)
×
782
                core->setJD(item.jd);
×
783

784
        StelMovementMgr *mvmgr = GETSTELMODULE(StelMovementMgr);
×
785
        //objectMgr->unSelect();
786

787
        bool objectFound = objectMgr->findAndSelect(item.designation); // TODO: We should prefer to use findAndSelect(item.designation, item.objClass). But what are the implications for markers?
×
788
        if (!item.ra.isEmpty() && !item.dec.isEmpty() && (!objectFound || item.designation.contains("marker", Qt::CaseInsensitive))) {
×
789
                Vec3d pos;
×
790
                StelUtils::spheToRect(StelUtils::getDecAngle(item.ra.trimmed()), StelUtils::getDecAngle(item.dec.trimmed()), pos);
×
791
                if (item.designation.contains("marker", Qt::CaseInsensitive))
×
792
                {
793
                        // Add a custom object on the sky
794
                        GETSTELMODULE(CustomObjectMgr)->addCustomObject(item.designation, pos, item.isVisibleMarker);
×
795
                        objectFound = objectMgr->findAndSelect(item.designation);
×
796
                }
797
                else
798
                {
799
                        // The unnamed stars
800
                        StelObjectP sobj=nullptr;
×
801
                        const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
×
802
                        double fov = (item.fov > 0.0 ? item.fov : 5.0);
×
803

804
                        mvmgr->zoomTo(fov, 0.0);
×
805
                        mvmgr->moveToJ2000(pos, mvmgr->mountFrameToJ2000(Vec3d(0., 0., 1.)), 0.0);
×
806

807
                        QList<StelObjectP> candidates = GETSTELMODULE(StarMgr)->searchAround(pos, 0.5, core);
×
808
                        if (candidates.empty()) { // The FOV is too big, let's reduce it to see dimmer objects.
×
809
                                mvmgr->zoomTo(0.5 * fov, 0.0);
×
810
                                candidates = GETSTELMODULE(StarMgr)->searchAround(pos, 0.5, core);
×
811
                        }
812

813
                        Vec3d winpos;
×
814
                        prj->project(pos, winpos);
×
815
                        double xpos = winpos[0];
×
816
                        double ypos = winpos[1];
×
817
                        double bestCandDistSq = 1.e6;
×
818
                        for (const auto &obj: candidates)
×
819
                        {
820
                                prj->project(obj->getJ2000EquatorialPos(core), winpos);
×
821
                                double sqrDistance = (xpos - winpos[0]) * (xpos - winpos[0]) + (ypos - winpos[1]) * (ypos - winpos[1]);
×
822
                                if (sqrDistance < bestCandDistSq)
×
823
                                {
824
                                        bestCandDistSq = sqrDistance;
×
825
                                        sobj = obj;
×
826
                                }
827
                        }
828
                        if (sobj)
×
829
                                objectFound = objectMgr->setSelectedObject(sobj);
×
830
                }
×
831
        }
832

833
        if (objectFound) {
×
834
                const QList<StelObjectP> newSelected = objectMgr->getSelectedObject();
×
835
                if (!newSelected.empty())
×
836
                {
837
                        const float amd = mvmgr->getAutoMoveDuration();
×
838
                        mvmgr->moveToObject(newSelected[0], amd);
×
839
                        mvmgr->setFlagTracking(true);
×
840
                        // We load stored FoV if the FoV checkbox is checked.
841
                        if (getFlagUseFov() && item.fov>1e-10) {
×
842
                                GETSTELMODULE(StelMovementMgr)->zoomTo(item.fov, amd);
×
843
                        }
844
                }
845
        }
×
846
}
×
847

848
/*
849
 * Method called when a list name is selected in the combobox
850
*/
851
void ObsListDialog::loadSelectedObservingList(int selectedIndex)
×
852
{
853
        //ui->editListButton->setEnabled(true);
854
        //ui->deleteListButton->setEnabled(true);
855
        selectedOlud = ui->obsListComboBox->itemData(selectedIndex).toString();
×
856
        loadSelectedList();
×
857
}
×
858

859
/*
860
 * Slot for button highlightAllButton: show all objects of active list.
861
*/
862
void ObsListDialog::highlightAll()
×
863
{
864
        // We must keep selection for the user. It is not enough to store/restore the existingSelection.
865
        // The QList<StelObjectP> objects are apparently volatile. We must retrieve the actual object.
866
        const QList<StelObjectP>&existingSelection = objectMgr->getSelectedObject();
×
867
        QList<StelObjectP> existingSelectionToRestore;
×
868
        if (existingSelection.length()>0)
×
869
        {
870
                existingSelectionToRestore.append(existingSelection.at(0));
×
871
        }
872

873
        QList<Vec3d> highlights;
×
874
        clearHighlights(); // Enable fool protection
×
875
        const int fontSize = StelApp::getInstance().getScreenFontSize();
×
876
        HighlightMgr *hlMgr = GETSTELMODULE(HighlightMgr);
×
877
        const QString color = hlMgr->getColor().toHtmlColor();
×
878
        float distance = hlMgr->getMarkersSize();
×
879

880
        for (const auto &item: std::as_const(currentItemCollection)) {
×
881
                const QString name = item.designation;
×
882
                const QString raStr = item.ra.trimmed();
×
883
                const QString decStr = item.dec.trimmed();
×
884

885
                Vec3d pos;
×
886
                bool usablePosition;
887
                if (!raStr.isEmpty() && !decStr.isEmpty())
×
888
                {
889
                        StelUtils::spheToRect(StelUtils::getDecAngle(raStr), StelUtils::getDecAngle(decStr), pos);
×
890
                        usablePosition = true;
×
891
                }
892
                else
893
                {
894
                        usablePosition = objectMgr->findAndSelect(name);
×
895
                        if (usablePosition) {
×
896
                                const QList<StelObjectP> &selected = objectMgr->getSelectedObject();
×
897
                                pos = selected[0]->getJ2000EquatorialPos(core);
×
898
                        }
899
                }
900
                if (usablePosition)
×
901
                        highlights.append(pos);
×
902

903
                // Add labels for named highlights (name in top right corner)
904
                if (!raStr.isEmpty() && !decStr.isEmpty()) // We may have a position for a timestamped event
×
905
                        highlightLabelIDs.append(labelMgr->labelEquatorial(name, raStr, decStr, true, fontSize, color, "NE", distance));
×
906
                else
907
                        highlightLabelIDs.append(labelMgr->labelObject(name, name, true, fontSize, color, "NE", distance));
×
908
        }
×
909

910
        hlMgr->fillHighlightList(highlights);
×
911

912
        // Restore selection that was active before calling this
913
        if (existingSelectionToRestore.length()>0)
×
914
                objectMgr->setSelectedObject(existingSelectionToRestore, StelModule::ReplaceSelection);
×
915
        else
916
                objectMgr->unSelect();
×
917
}
×
918

919
/*
920
 * Clear highlights
921
*/
922
void ObsListDialog::clearHighlights()
×
923
{
924
        GETSTELMODULE(HighlightMgr)->cleanHighlightList();
×
925
        // Clear labels
926
        for (int l: highlightLabelIDs) {
×
927
                labelMgr->deleteLabel(l);
×
928
        }
929
        highlightLabelIDs.clear();
×
930
}
×
931

932
/*
933
 * Slot for button newListButton
934
*/
935
void ObsListDialog::newListButtonPressed()
×
936
{
937
        selectedOlud=QUuid::createUuid().toString();
×
938
        itemModel->removeRows(0, itemModel->rowCount()); // don't use clear() here!
×
939
        currentItemCollection.clear();
×
940

941
        //ui->treeView->clearSelection(); ???
942
        switchEditMode(true, true);
×
943

944
        ui->listNameLineEdit->setText(q_("New Observation List"));
×
945
        ui->titleBar->setTitle(q_("Observing list creation mode"));
×
946
}
×
947
/*
948
 * Slot for editButton
949
*/
950
void ObsListDialog::editListButtonPressed()
×
951
{
952
        Q_ASSERT(!selectedOlud.isEmpty());
×
953

954
        if (!selectedOlud.isEmpty())
×
955
        {
956
                switchEditMode(true, false);
×
957

958
                ui->titleBar->setTitle(q_("Observing list editor mode"));
×
959
        }
960
        else
961
        {
962
                qCritical() << "ObsListDialog::editListButtonPressed(): selectedOlud is empty";
×
963
                messageBox(q_("Error"), q_("selectedOlud empty. This is a bug"));
×
964
        }
965
}
×
966

967
/*
968
 * Slot for button obsListExportListButton
969
 */
970
void ObsListDialog::exportListButtonPressed()
×
971
{
972
        static const QString filter = "Stellarium Single Observing List (*.sol);;Stellarium Observing List (*.ol)";
×
973
        const QString destinationDir=StelApp::getInstance().getSettings()->value("main/observinglists_dir", QDir::homePath()).toString();
×
974
        QString selectedFilter = "Stellarium Single Observing List (*.sol)";
×
975
        QString exportListJsonPath = QFileDialog::getSaveFileName(&StelMainView::getInstance(), q_("Export observing list as..."),
×
976
                                                              destinationDir + "/" + JSON_FILE_BASENAME + "_" + currentListName + ".sol", filter, &selectedFilter);
×
977

978
        if (exportListJsonPath.isEmpty()) // cancel pressed.
×
979
                return;
×
980

981
        QFile jsonFile(exportListJsonPath);
×
982
        if (!jsonFile.open(QIODevice::ReadWrite | QIODevice::Text))
×
983
        {
984
                qWarning() << "[ObservingList Creation/Edition] Error exporting observing list. "
×
985
                           << "File cannot be opened for reading and writing:"
×
986
                           << QDir::toNativeSeparators(exportListJsonPath);
×
987
                messageBox(q_("Error"), q_("Cannot export. See logfile for details."));
×
988
                return;
×
989
        }
990

991
        jsonFile.resize(0);
×
992
        QFileInfo fi(exportListJsonPath);
×
993
        if (fi.suffix()=="sol")
×
994
        {
995
                // Prepare a new json-able map
996
                QVariantMap exportJsonMap={
997
                        {KEY_DEFAULT_LIST_OLUD, ""}, // Do not set a default in this list!
998
                        {KEY_SHORT_NAME, SHORT_NAME_VALUE},
999
                        {KEY_VERSION, FILE_VERSION}};
×
1000

1001
                QVariantMap currentListMap={{selectedOlud, observingLists.value(selectedOlud).toMap()}};
×
1002
                //QVariantMap oneListMap={{KEY_OBSERVING_LISTS, currentListMap}};
1003
                //exportJsonMap.insert(KEY_OBSERVING_LISTS, oneListMap);
1004
                exportJsonMap.insert(KEY_OBSERVING_LISTS, currentListMap);
×
1005
                StelJsonParser::write(exportJsonMap, &jsonFile);
×
1006
        }
×
1007
        else
1008
        {
1009
                // just export complete map.
1010
                StelJsonParser::write(jsonMap, &jsonFile);
×
1011
        }
1012

1013
        jsonFile.flush();
×
1014
        jsonFile.close();
×
1015
}
×
1016

1017
/*
1018
 * Slot for button obsListImportListButton
1019
 */
1020
void ObsListDialog::importListButtonPressed()
×
1021
{
1022
        static const QString filter = "Stellarium Single Observing List (*.sol);;Stellarium Observing List (*.ol);;Stellarium Legacy JSON Observing List or Bookmarks (*.json)";
×
1023
        const QString destinationDir=StelApp::getInstance().getSettings()->value("main/observinglists_dir", QDir::homePath()).toString();
×
1024
        QString fileToImportJsonPath = QFileDialog::getOpenFileName(&StelMainView::getInstance(), q_("Import observing list"),
×
1025
                                                                    destinationDir,
1026
                                                                    filter);
×
1027
        if (fileToImportJsonPath.isEmpty()) // cancel pressed.
×
1028
                return;
×
1029

1030
        QVariantMap map;
×
1031
        QFile jsonFile(fileToImportJsonPath);
×
1032
        if (!jsonFile.open(QIODevice::ReadOnly))
×
1033
        {
1034
                qWarning() << "[ObservingList Import] cannot open"
×
1035
                           << QDir::toNativeSeparators(jsonFile.fileName());
×
1036
                messageBox(q_("Error"), q_("Cannot open selected file for import"));
×
1037
                return;
×
1038
        }
1039
        else
1040
        {
1041
                try {
1042
                        map = StelJsonParser::parse(jsonFile.readAll()).toMap();
×
1043
                        jsonFile.close();
×
1044

1045
                        if (map.contains(KEY_OBSERVING_LISTS))
×
1046
                        {
1047
                                // Case of observingList import: Import all lists from that file! A .sol only has one list but is else structured identically.
1048
                                const QVariantMap observingListMapToImport = map.value(KEY_OBSERVING_LISTS).toMap();
×
1049
                                if (observingListMapToImport.isEmpty())
×
1050
                                {
1051
                                        qWarning() << "[ObservingList Creation/Edition import] empty list:" << fileToImportJsonPath;
×
1052
                                        messageBox(q_("Error"), q_("Empty list."));
×
1053
                                        return;
×
1054
                                }
1055
                                else
1056
                                {
1057
                                        QVariantMap::const_iterator it;
×
1058
                                        for (it = observingListMapToImport.begin(); it != observingListMapToImport.end(); it++) {
×
1059
                                                if (it.value().canConvert<QVariantMap>())
×
1060
                                                {
1061
                                                        // check here to avoid overwriting of existing lists
1062
                                                        bool overwrite=true;
×
1063
                                                        if (observingLists.contains(it.key())) // Same OLUD?
×
1064
                                                        {
1065
                                                                QVariantMap importedMap=it.value().toMap(); // This is a map of {{UUID, QMap},...}
×
1066
                                                                QString importedName=importedMap.value(KEY_NAME).toString();
×
1067
                                                                QString importedDate=importedMap.value(KEY_CREATION_DATE).toString();
×
1068
                                                                QString importedLastEditDate=importedMap.value(KEY_LAST_EDIT, importedMap.value(KEY_CREATION_DATE)).toString();
×
1069
                                                                qDebug() << "Imported Map named:" << importedName << "created" << importedDate << "changed" << importedLastEditDate << ":" << importedMap;
×
1070
                                                                QVariantMap existingMap=observingLists.value(it.key()).toMap();
×
1071
                                                                QString existingName=existingMap.value(KEY_NAME).toString();
×
1072
                                                                QString existingDate=existingMap.value(KEY_CREATION_DATE).toString();
×
1073
                                                                QString existingLastEdit=existingMap.value(KEY_LAST_EDIT, existingMap.value(KEY_CREATION_DATE)).toString();
×
1074
                                                                QString message=QString(q_("A list named '%1', created %2 and last modified %3 would overwrite your existing list '%4', dated %5 and last modified %6. Accept?")).arg(importedName, importedDate, importedLastEditDate, existingName, existingDate, existingLastEdit);
×
1075
                                                                overwrite=askConfirmation(message);
×
1076
                                                        }
×
1077
                                                        if (overwrite)
×
1078
                                                        {
1079
                                                                observingLists.insert(it.key(), it.value());
×
1080
                                                                selectedOlud=it.key();
×
1081
                                                        }
1082
                                                }
1083
                                        }
1084
                                }
1085
                        }
×
1086
                        else if (map.contains(KEY_BOOKMARKS))
×
1087
                        {
1088
                                // Case of legacy bookmarks import
1089
                                QVariantMap bookmarksListMap = map.value(KEY_BOOKMARKS).toMap();
×
1090
                                if (bookmarksListMap.isEmpty())
×
1091
                                {
1092
                                        qWarning() << "[ObservingList Creation/Edition import] the file is empty or doesn't contain legacy bookmarks.";
×
1093
                                        messageBox(q_("Error"), q_("The file is empty or doesn't contain legacy bookmarks."));
×
1094
                                        return;
×
1095
                                }
1096
                                else
1097
                                {
1098
                                        QHash<QString, ObsListDialog::observingListItem> bookmarksHash=loadBookmarksFile(jsonFile);
×
1099
                                        // Put them to the main list. Note that this may create another list named "bookmarks list", however, with a different OLUD than the existing.
1100
                                        selectedOlud=saveBookmarksHashInObservingLists(bookmarksHash);
×
1101
                                }
×
1102
                        }
×
1103
                        else
1104
                        {
1105
                                messageBox(q_("Error"), q_("File does not contain observing lists or legacy bookmarks"));
×
1106
                                return;
×
1107
                        }
1108

1109
                        // At this point we have added our lists to the observingLists map. Now update the jsonMap and store to file.
1110
                        QFile jsonFile(observingListJsonPath);
×
1111
                        if (!jsonFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
×
1112
                                qWarning() << "[ObservingList] bookmarks list can not be saved. A file can not be open for reading and writing:"
×
1113
                                           << QDir::toNativeSeparators(observingListJsonPath);
×
1114
                                messageBox(q_("Error"), q_("Cannot open observingLists.json to write"));
×
1115
                                return;
×
1116
                        }
1117
                        // Update the jsonMap and store
1118
                        jsonMap.insert(KEY_OBSERVING_LISTS, observingLists);
×
1119
                        jsonFile.resize(0);
×
1120
                        StelJsonParser::write(jsonMap, &jsonFile);
×
1121
                        jsonFile.flush();
×
1122
                        jsonFile.close();
×
1123
                        tainted=false;
×
1124

1125
                        // Now we have stored to file, but the program is not aware of the new lists!
1126
                        loadListNames(selectedOlud); // also populate Combobox and make sure at least some defaultOlud exists.
×
1127
                        Q_ASSERT(selectedOlud.length()>0);
×
1128

1129
                        loadSelectedList();
×
1130
                } catch (std::runtime_error &e) {
×
1131
                        qWarning() << "[ObservingList Creation/Edition] File format is wrong! Error: " << e.what();
×
1132
                        messageBox(q_("Error"), q_("File format is wrong!"));
×
1133
                        return;
×
1134
                }
×
1135
        }
1136
}
×
1137

1138
/*
1139
 * Delete the currently selected list. There must be at least one list.
1140
*/
1141
void ObsListDialog::deleteListButtonPressed()
×
1142
{
1143
        if (observingLists.count()>1 && (selectedOlud!=defaultOlud))
×
1144
        {
1145
                if (!askConfirmation()) // place inside to avoid error message below.
×
1146
                        return;
×
1147

1148
                QFile jsonFile(observingListJsonPath);
×
1149
                if (!jsonFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
×
1150
                        qWarning() << "[ObservingList] bookmarks list can not be saved. A file can not be open for reading and writing:"
×
1151
                                   << QDir::toNativeSeparators(observingListJsonPath);
×
1152
                        messageBox(q_("Error"), q_("Cannot open JSON output file. Will not delete."));
×
1153
                        return;
×
1154
                }
1155

1156
                observingLists.remove(selectedOlud);
×
1157
                currentItemCollection.clear();
×
1158

1159
                selectedOlud=defaultOlud;
×
1160
                // Update the jsonMap and store
1161
                jsonMap.insert(KEY_OBSERVING_LISTS, observingLists);
×
1162
                jsonFile.resize(0);
×
1163
                StelJsonParser::write(jsonMap, &jsonFile);
×
1164
                jsonFile.flush();
×
1165
                jsonFile.close();
×
1166
                tainted=false;
×
1167

1168
                // Clean up UI
1169
                clearHighlights();
×
1170
                loadListNames();
×
1171
                loadSelectedList();
×
1172
        }
×
1173
        else
1174
        {
1175
                qDebug() << "deleteButtonPressed: You cannot delete the default or the last list.";
×
1176
                messageBox(q_("Information"), q_("You cannot delete the default or the last list."));
×
1177
        }
1178
}
1179

1180
/*
1181
 * Slot for addObjectButton.
1182
 * Save selected object into the list of observed objects.
1183
 */
1184
void ObsListDialog::addObjectButtonPressed()
×
1185
{
1186
        const double JD = core->getJD();
×
1187
        const double fov = (ui->fovCheckBox->isChecked() ? GETSTELMODULE(StelMovementMgr)->getCurrentFov() : -1.0);
×
1188
        const QString Location = core->getCurrentLocation().serializeToLine(); // store completely
×
1189
        const QString landscapeID=GETSTELMODULE(LandscapeMgr)->getCurrentLandscapeID();
×
1190

1191
        const QList<StelObjectP> &selectedObject = objectMgr->getSelectedObject();
×
1192

1193
        if (!selectedObject.isEmpty())
×
1194
        {
1195
// TBD: this test should prevent adding duplicate entries, but fails. Maybe for V23.4!
1196
//                // No duplicate item in the same list
1197
//                bool is_already_in_list = false;
1198
//                QHash<QString, observingListItem>::iterator i;
1199
//                for (i = observingListItemCollection.begin(); i != observingListItemCollection.end(); i++)
1200
//                {
1201
//                        if ((i.value().name.compare(selectedObject[0]->getEnglishName()) == 0) &&
1202
//                                (ui->obsListJDCheckBox->isChecked()        && i.value().jd == JD) &&
1203
//                                (ui->obsListFovCheckBox->isChecked()       && i.value().fov == fov) &&
1204
//                                (ui->obsListLandscapeCheckBox->isChecked() && i.value().landscapeID == landscapeID) &&
1205
//                                (ui->obsListLocationCheckBox->isChecked()  && i.value().location == Location))
1206
//                        {
1207
//                                is_already_in_list = true;
1208
//                                break;
1209
//                        }
1210
//                }
1211
//
1212
//                if (!is_already_in_list)
1213
//                {
1214
                        observingListItem item;
×
1215

1216
                        const QString objectUUID = QUuid::createUuid().toString();
×
1217

1218
                        // Object name (designation) and object name I18n
1219
                        if (selectedObject[0]->getType() == "Nebula")
×
1220
                                item.designation = GETSTELMODULE(NebulaMgr)->getLatestSelectedDSODesignationWIC(); // Store most common catalog ID as of our catalog sequence, even if catalog is not active
×
1221
                        else
1222
                                item.designation = selectedObject[0]->getEnglishName();
×
1223
                        item.name = selectedObject[0]->getEnglishName();
×
1224
                        item.nameI18n = selectedObject[0]->getNameI18n();
×
1225
                        if(item.nameI18n.isEmpty())
×
1226
                                item.nameI18n = DASH;
×
1227
                        // Check if the object name is empty.
1228
                        if (item.designation.isEmpty())
×
1229
                        {
1230
                                item.designation = "Unnamed object";
×
1231
                                if (item.nameI18n.isEmpty()) {
×
1232
                                        item.nameI18n = q_("Unnamed object");
×
1233
                                }
1234
                        }
1235
                        // Type, Object Type
1236
                        item.objClass = selectedObject[0]->getType();
×
1237
                        item.objTypeI18n = selectedObject[0]->getObjectTypeI18n();
×
1238

1239
                        // Ra & Dec
1240
                        if (ui->coordinatesCheckBox->isChecked() || (item.objClass == "Planet" && getFlagUseJD()) || item.objClass == CUSTOM_OBJECT || item.designation.isEmpty()) {
×
1241
                                double ra, dec;
1242
                                StelUtils::rectToSphe(&ra, &dec, selectedObject[0]->getJ2000EquatorialPos(core));
×
1243
                                item.ra  = StelUtils::radToHmsStr(ra,  false).trimmed();
×
1244
                                item.dec = StelUtils::radToDmsStr(dec, false).trimmed();
×
1245
                        }
1246
                        item.isVisibleMarker=!item.designation.contains("marker", Qt::CaseInsensitive);
×
1247
                        item.magnitude = getMagnitude(selectedObject, core);
×
1248

1249
                        // Constellation
1250
                        const Vec3d posNow = selectedObject[0]->getEquinoxEquatorialPos(core);
×
1251
                        item.constellation = core->getIAUConstellation(posNow);
×
1252

1253
                        // Optional: JD, Location, landscape, fov
1254
                        if (getFlagUseJD())
×
1255
                                item.jd = JD;
×
1256
                        if (getFlagUseLocation())
×
1257
                                item.location = Location;
×
1258
                        if (getFlagUseLandscape())
×
1259
                                item.landscapeID = landscapeID;
×
1260
                        if (getFlagUseFov() && (fov > 1.e-6))
×
1261
                                item.fov = fov;
×
1262

1263
                        currentItemCollection.insert(objectUUID, item);
×
1264
                        tainted=true;
×
1265

1266
                        // Add object in row model
1267
                        StelLocation loc=StelLocation::createFromLine(Location);
×
1268
                        addModelRow(objectUUID,
×
1269
                                    item.designation,
1270
                                    item.nameI18n,
1271
                                    item.objTypeI18n,
1272
                                    item.ra,
1273
                                    item.dec,
1274
                                    item.magnitude,
1275
                                    item.constellation,
1276
                                    ui->jdCheckBox->isChecked() ? StelUtils::julianDayToISO8601String(JD + core->getUTCOffset(JD) / 24.).replace("T", " ") : "",
×
1277
                                    ui->locationCheckBox->isChecked() ? loc.name : "",
×
1278
                                    item.landscapeID);
1279
//                }
1280
        }
×
1281
        else
1282
                qWarning() << "Selected object is empty!";
×
1283
}
×
1284

1285
/*
1286
 * Slot for button obsListRemoveObjectButton
1287
 */
1288
void ObsListDialog::removeObjectButtonPressed()
×
1289
{
1290
        Q_ASSERT(isEditMode);
×
1291

1292
        int number = ui->treeView->currentIndex().row();
×
1293
        QString uuid = itemModel->index(number, ColumnUUID).data().toString();
×
1294
        itemModel->removeRow(number);
×
1295
        currentItemCollection.remove(uuid);
×
1296
        tainted=true;
×
1297
}
×
1298

1299
/*
1300
 * Slot for saveButton
1301
 */
1302
void ObsListDialog::saveButtonPressed()
×
1303
{
1304
        Q_ASSERT(isEditMode);
×
1305
        if (!isEditMode)
×
1306
        {
1307
                qCritical() << "CALLING ERROR: saveButtonPressed() while not in edit mode.";
×
1308
                return;
×
1309
        }
1310

1311
        // we have a valid selectedListOlud. In addition, the list must have a human-readable name.
1312
        QString listName = ui->listNameLineEdit->text().trimmed();
×
1313
        if (listName.length()==0)
×
1314
        {
1315
                messageBox(q_("Error"), q_("Empty name"));
×
1316
                return;
×
1317
        }
1318
        if (listNames.contains(listName) && isCreationMode)
×
1319
        {
1320
                messageBox(q_("Error"), q_("List name already exists"));
×
1321
                return;
×
1322
        }
1323

1324
        // Last chance to detect any change: Just list name changed?
1325
        if (currentListName!=listName)
×
1326
                tainted=true;
×
1327

1328
        if (!tainted)
×
1329
                return;
×
1330

1331
        //OK, we save this and keep it as current list.
1332
        currentListName=listName;
×
1333

1334
        QFile jsonFile(observingListJsonPath);
×
1335
        if (!jsonFile.open(QIODevice::ReadWrite | QIODevice::Text))
×
1336
        {
1337
                qWarning() << "[ObservingList Save] Error saving observing list. "
×
1338
                           << "File cannot be opened for reading and writing:"
×
1339
                           << QDir::toNativeSeparators(observingListJsonPath);
×
1340
                return;
×
1341
        }
1342

1343
        QVariantMap currentList=prepareCurrentList(currentItemCollection);
×
1344
        observingLists.insert(selectedOlud, currentList);
×
1345
        jsonMap.insert(KEY_OBSERVING_LISTS, observingLists);
×
1346

1347
        jsonFile.resize(0);
×
1348
        StelJsonParser::write(jsonMap, &jsonFile);
×
1349
        jsonFile.flush();
×
1350
        jsonFile.close();
×
1351

1352
        tainted=false;
×
1353
        switchEditMode(false, false); // Set GUI to normal mode
×
1354
        loadListNames(selectedOlud); // reload Combobox
×
1355
        loadSelectedList();
×
1356
}
×
1357

1358
/*
1359
 * Slot for cancelButton
1360
 */
1361
void ObsListDialog::cancelButtonPressed()
×
1362
{
1363
        Q_ASSERT(isEditMode);
×
1364
        if (!isEditMode)
×
1365
        {
1366
                qCritical() << "CALLING ERROR: cancelButtonPressed() while not in edit mode.";
×
1367
                return;
×
1368
        }
1369
        // Depending on creation or regular edit mode, delete current list and load default, or reload current list,
1370
        if (isCreationMode)
×
1371
                loadDefaultList();
×
1372
        else
1373
                loadSelectedList();
×
1374

1375
        // then close editing mode and set GUI to normal mode
1376
        switchEditMode(false, false);
×
1377
}
1378

1379
void ObsListDialog::switchEditMode(bool enableEditMode, bool newList)
×
1380
{
1381
                isEditMode=enableEditMode;
×
1382
                isCreationMode=newList;
×
1383
                // The Layout classes have no setVisible(bool), we must configure individual buttons! :-(
1384

1385
                ui->titleBar->setTitle(q_("Observing lists"));
×
1386
                //ui->horizontalLayoutCombo->setEnabled(!isEditMode);     // disable list selection
1387
                ui->obsListComboLabel->setVisible(!isEditMode);
×
1388
                ui->obsListComboBox->setVisible(!isEditMode);
×
1389

1390
                // horizontalLayoutLineEdit_1: labelListName, nameOfListLIneEdit
1391
                //ui->horizontalLayout_Name->setEnabled(isEditMode);  // enable list name editing
1392
                ui->listNameLabel->setVisible(isEditMode);
×
1393
                //ui->horizontalSpacer_listName->sizePolicy().setHeightForWidth(isEditMode);// ->setVisible(isEditMode);
1394
                //qDebug() << "Spacer geometry, policy:" << ui->horizontalSpacer_listName->geometry() << ui->horizontalSpacer_listName->sizePolicy();
1395
                ui->listNameLineEdit->setVisible(isEditMode);
×
1396
                ui->listNameLineEdit->setText(currentListName);
×
1397

1398
                ui->descriptionLineEdit->setEnabled(isEditMode);    // (activate description line)
×
1399

1400
                ui->creationDateLabel->setVisible(!isEditMode);         // Creation date:
×
1401
                ui->creationDateLineEdit->setVisible(!isEditMode);      //
×
1402
                ui->lastEditLabel->setVisible(!isEditMode);             // Last edit date:
×
1403
                ui->lastEditLineEdit->setVisible(!isEditMode);          //
×
1404

1405
                // line with optional store items
1406
                ui->alsoStoreLabel->setVisible(isEditMode);            // Also store
×
1407
                ui->coordinatesCheckBox->setVisible(isEditMode);// hide "Coordinates"
×
1408
                ui->alsoLoadLabel->setVisible(!isEditMode);  // Also load
×
1409

1410
                //ui->horizontalLayoutButtons->setEnabled(!isEditMode);   // Highlight/Clear/NewList/EditList/DeleteList/ExportList/ImportList
1411
                ui->highlightAllButton->setVisible(!isEditMode);
×
1412
                ui->clearHighlightButton->setVisible(!isEditMode);
×
1413
                ui->newListButton->setVisible(!isEditMode);
×
1414
                ui->editListButton->setVisible(!isEditMode);
×
1415
                ui->deleteListButton->setVisible(!isEditMode);
×
1416
                ui->exportListButton->setVisible(!isEditMode);
×
1417
                ui->importListButton->setVisible(!isEditMode);
×
1418

1419
                //ui->horizontalLayoutButtons_1->setEnabled(isEditMode); // Add/Remove/Export/Import
1420
                ui->addObjectButton->setVisible(isEditMode);
×
1421
                ui->removeObjectButton->setVisible(isEditMode);
×
1422
                ui->saveButton->setVisible(isEditMode);
×
1423
                ui->cancelButton->setVisible(isEditMode);
×
1424
}
×
1425

1426
/*
1427
 * Sort the treeView by the column name given in parameter
1428
*/
1429
void ObsListDialog::sortObsListTreeViewByColumnName(const QString &columnName)
×
1430
{
1431
        static const QMap<QString,int>map={
1432
                {SORTING_BY_NAME,          ColumnDesignation},
×
1433
                {SORTING_BY_NAMEI18N,      ColumnNameI18n},
×
1434
                {SORTING_BY_TYPE,          ColumnType},
×
1435
                {SORTING_BY_RA,            ColumnRa},
×
1436
                {SORTING_BY_DEC,           ColumnDec},
×
1437
                {SORTING_BY_MAGNITUDE,     ColumnMagnitude},
×
1438
                {SORTING_BY_CONSTELLATION, ColumnConstellation},
×
1439
                {SORTING_BY_DATE,          ColumnDate},
×
1440
                {SORTING_BY_LOCATION,      ColumnLocation},
×
1441
                {SORTING_BY_LANDSCAPE_ID,  ColumnLandscapeID}
×
1442
        };
×
1443
    ObsListDialogSortFilterProxyModel *proxyModel = new ObsListDialogSortFilterProxyModel;
×
1444
    proxyModel->setSourceModel(itemModel);
×
1445
    ui->treeView->setModel(proxyModel);
×
1446
    proxyModel->sort(map.value(columnName), Qt::AscendingOrder);
×
1447
}
×
1448

1449
void ObsListDialog::setFlagUseJD(bool b)
×
1450
{
1451
        QSettings* conf = StelApp::getInstance().getSettings();
×
1452
        flagUseJD=b;
×
1453
        conf->setValue("bookmarks/useJD", b);
×
1454
        emit flagUseJDChanged(b);
×
1455
}
×
1456
void ObsListDialog::setFlagUseLandscape(bool b)
×
1457
{
1458
        QSettings* conf = StelApp::getInstance().getSettings();
×
1459
        flagUseLandscape=b;
×
1460
        conf->setValue("bookmarks/useLandscape", b);
×
1461
        emit flagUseLandscapeChanged(b);
×
1462
}
×
1463
void ObsListDialog::setFlagUseLocation(bool b)
×
1464
{
1465
        QSettings* conf = StelApp::getInstance().getSettings();
×
1466
        flagUseLocation=b;
×
1467
        conf->setValue("bookmarks/useLocation", b);
×
1468
        emit flagUseLocationChanged(b);
×
1469
}
×
1470
void ObsListDialog::setFlagUseFov(bool b)
×
1471
{
1472
        QSettings* conf = StelApp::getInstance().getSettings();
×
1473
        flagUseFov=b;
×
1474
        conf->setValue("bookmarks/useFOV", b);
×
1475
        emit flagUseFovChanged(b);
×
1476
}
×
1477

1478
/*
1479
 * Prepare the currently displayed/edited list for storage
1480
 * Returns QVariantList with keys={creation date, last edit, description, name, objects, sorting}
1481
 */
1482
QVariantMap ObsListDialog::prepareCurrentList(QHash<QString, observingListItem> &itemHash)
×
1483
{
1484
        // Edit date
1485
        const double JD = StelUtils::getJDFromSystem();
×
1486
        const QString lastEditDate = StelUtils::julianDayToISO8601String(JD + core->getUTCOffset(JD) / 24.).replace("T", " ");
×
1487
        QVariantMap currentList = {
1488
                // Name, description, current date for the list, current sorting
1489
                {KEY_NAME,          currentListName},
×
1490
                {KEY_DESCRIPTION,   ui->descriptionLineEdit->text()},
×
1491
                {KEY_SORTING,       sorting},
×
1492
                {KEY_CREATION_DATE, ui->creationDateLineEdit->text()},
×
1493
                {KEY_LAST_EDIT,     lastEditDate }
1494
        };
×
1495

1496
        // List of objects
1497
        QVariantList listOfObjects;
×
1498
        QHashIterator<QString, observingListItem> i(itemHash);
×
1499
        while (i.hasNext())
×
1500
        {
1501
                i.next();
×
1502
                observingListItem item = i.value();
×
1503
                listOfObjects.push_back(item.toVariantMap());
×
1504
        }
×
1505
        currentList.insert(KEY_OBJECTS, listOfObjects);
×
1506

1507
        return currentList;
×
1508
}
×
1509

1510
/*
1511
 * Slot for obsListCreationEditionTreeView header
1512
 */
1513
void ObsListDialog::headerClicked(int index)
×
1514
{
1515
        static const QMap<int,QString> map={
1516
                {ColumnDesignation,   SORTING_BY_NAME},
×
1517
                {ColumnNameI18n,      SORTING_BY_NAMEI18N},
×
1518
                {ColumnType,          SORTING_BY_TYPE},
×
1519
                {ColumnRa,            SORTING_BY_RA},
×
1520
                {ColumnDec,           SORTING_BY_DEC},
×
1521
                {ColumnMagnitude,     SORTING_BY_MAGNITUDE},
×
1522
                {ColumnConstellation, SORTING_BY_CONSTELLATION},
×
1523
                {ColumnDate,          SORTING_BY_DATE},
×
1524
                {ColumnLocation,      SORTING_BY_LOCATION},
×
1525
                {ColumnLandscapeID,   SORTING_BY_LANDSCAPE_ID}};
×
1526
        sorting=map.value(index, "");
×
1527
        //qDebug() << "Sorting = " << sorting;
1528
        sortObsListTreeViewByColumnName(sorting);
×
1529
}
×
1530

1531
// Get the magnitude from selected object (or a dash if unavailable)
1532
QString ObsListDialog::getMagnitude(const QList<StelObjectP> &selectedObject, StelCore *core)
×
1533
{
1534
        if (!core)
×
1535
                return DASH;
×
1536

1537
        QString objectMagnitudeStr(DASH);
×
1538
        const float objectMagnitude = selectedObject[0]->getVMagnitude(core);
×
1539
        if (objectMagnitude > 98.f)
×
1540
        {
1541
                if (QString::compare(selectedObject[0]->getType(), "Nebula", Qt::CaseSensitive) == 0)
×
1542
                {
1543
                        auto &r_nebula = dynamic_cast<Nebula &>(*selectedObject[0]);
×
1544
                        const float mB = r_nebula.getBMagnitude(core);
×
1545
                        if (mB < 98.f)
×
1546
                                objectMagnitudeStr = QString::number(mB);
×
1547
                }
1548
        }
1549
        else
1550
                objectMagnitudeStr = QString::number(objectMagnitude, 'f', 2);
×
1551

1552
        return objectMagnitudeStr;
×
1553
}
×
1554

1555
void ObsListDialog::defaultClicked(bool b)
×
1556
{
1557
        defaultOlud = (b ? selectedOlud : "");
×
1558
        jsonMap.insert(KEY_DEFAULT_LIST_OLUD, defaultOlud);
×
1559
        tainted=true;
×
1560
}
×
1561

1562
const QString ObsListDialog::JSON_FILE_NAME     = QStringLiteral("observingList.json");
1563
const QString ObsListDialog::JSON_FILE_BASENAME = QStringLiteral("observingList");
1564
const QString ObsListDialog::FILE_VERSION       = QStringLiteral("2.1");
1565

1566
const QString ObsListDialog::JSON_BOOKMARKS_FILE_NAME   = QStringLiteral("bookmarks.json");
1567
const QString ObsListDialog::BOOKMARKS_LIST_NAME        = QStringLiteral("bookmarks list");
1568
const QString ObsListDialog::BOOKMARKS_LIST_DESCRIPTION = QStringLiteral("Bookmarks of previous Stellarium version.");
1569
const QString ObsListDialog::SHORT_NAME_VALUE           = QStringLiteral("Observing list for Stellarium");
1570

1571
const QString ObsListDialog::KEY_DEFAULT_LIST_OLUD = QStringLiteral("defaultListOlud");
1572
const QString ObsListDialog::KEY_OBSERVING_LISTS   = QStringLiteral("observingLists");
1573
const QString ObsListDialog::KEY_CREATION_DATE     = QStringLiteral("creation date");
1574
const QString ObsListDialog::KEY_LAST_EDIT         = QStringLiteral("last edit");
1575
const QString ObsListDialog::KEY_BOOKMARKS         = QStringLiteral("bookmarks");
1576
const QString ObsListDialog::KEY_NAME              = QStringLiteral("name");
1577
const QString ObsListDialog::KEY_NAME_I18N         = QStringLiteral("nameI18n");
1578
const QString ObsListDialog::KEY_JD                = QStringLiteral("jd");
1579
const QString ObsListDialog::KEY_RA                = QStringLiteral("ra");
1580
const QString ObsListDialog::KEY_DEC               = QStringLiteral("dec");
1581
const QString ObsListDialog::KEY_FOV               = QStringLiteral("fov");
1582
const QString ObsListDialog::KEY_DESCRIPTION       = QStringLiteral("description");
1583
const QString ObsListDialog::KEY_LANDSCAPE_ID      = QStringLiteral("landscapeID");
1584
const QString ObsListDialog::KEY_OBJECTS           = QStringLiteral("objects");
1585
const QString ObsListDialog::KEY_OBJECTS_TYPE      = QStringLiteral("objtype");
1586
const QString ObsListDialog::KEY_TYPE              = QStringLiteral("type");
1587
const QString ObsListDialog::KEY_DESIGNATION       = QStringLiteral("designation");
1588
const QString ObsListDialog::KEY_SORTING           = QStringLiteral("sorting");
1589
const QString ObsListDialog::KEY_LOCATION          = QStringLiteral("location");
1590
const QString ObsListDialog::KEY_MAGNITUDE         = QStringLiteral("magnitude");
1591
const QString ObsListDialog::KEY_CONSTELLATION     = QStringLiteral("constellation");
1592
const QString ObsListDialog::KEY_VERSION           = QStringLiteral("version");
1593
const QString ObsListDialog::KEY_SHORT_NAME        = QStringLiteral("shortName");
1594
const QString ObsListDialog::KEY_IS_VISIBLE_MARKER = QStringLiteral("isVisibleMarker");
1595

1596
const QString ObsListDialog::SORTING_BY_NAME          = QStringLiteral("name");
1597
const QString ObsListDialog::SORTING_BY_NAMEI18N      = QStringLiteral("nameI18n");
1598
const QString ObsListDialog::SORTING_BY_TYPE          = QStringLiteral("type");
1599
const QString ObsListDialog::SORTING_BY_RA            = QStringLiteral("right ascension");
1600
const QString ObsListDialog::SORTING_BY_DEC           = QStringLiteral("declination");
1601
const QString ObsListDialog::SORTING_BY_MAGNITUDE     = QStringLiteral("magnitude");
1602
const QString ObsListDialog::SORTING_BY_CONSTELLATION = QStringLiteral("constellation");
1603
const QString ObsListDialog::SORTING_BY_DATE          = QStringLiteral("date");
1604
const QString ObsListDialog::SORTING_BY_LOCATION      = QStringLiteral("location");
1605
const QString ObsListDialog::SORTING_BY_LANDSCAPE_ID  = QStringLiteral("landscapeID");
1606

1607
const QString ObsListDialog::CUSTOM_OBJECT = QStringLiteral("CustomObject");
1608

1609
const QString ObsListDialog::DASH = QString(QChar(0x2014));
1610

1611
bool ObsListDialogSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
×
1612
{
1613
    if (sortColumn() == ObsListDialog::ColumnRa)
×
1614
    {
1615
        QString raLeft = sourceModel()->data(left).toString();
×
1616
        QString raRight = sourceModel()->data(right).toString();
×
1617
        return StelUtils::getDecAngle(raLeft) < StelUtils::getDecAngle(raRight);
×
1618
    }
×
1619
    if (sortColumn() == ObsListDialog::ColumnDec)
×
1620
    {
1621
        QString decLeft = sourceModel()->data(left).toString();
×
1622
        QString decRight = sourceModel()->data(right).toString();
×
1623
        return StelUtils::getDecAngle(decLeft) < StelUtils::getDecAngle(decRight);
×
1624
    }
×
1625
    if (sortColumn() == ObsListDialog::ColumnMagnitude)
×
1626
    {
1627
        QString magLeft = sourceModel()->data(left).toString();
×
1628
        QString magRight = sourceModel()->data(right).toString();
×
1629
        return magLeft.toDouble() < magRight.toDouble();
×
1630
    }
×
1631
    return QSortFilterProxyModel::lessThan(left, right);
×
1632
}
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