/* * Stellarium * Copyright (C) 2008 Guillaume Chereau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Dialog.hpp" #include "LocationDialog.hpp" #include "StelLocationMgr.hpp" #include "ui_locationDialogGui.h" #include "StelApp.hpp" #include "StelCore.hpp" #include "StelNavigator.hpp" #include "StelModuleMgr.hpp" #include "SolarSystem.hpp" #include "Planet.hpp" #include "StelFileMgr.hpp" #include "StelLocaleMgr.hpp" #include "StelGui.hpp" #include "StelGuiItems.hpp" #include #include #include #include #include #include LocationDialog::LocationDialog() : isEditingNew(false) { ui = new Ui_locationDialogForm; lastVisionMode = StelApp::getInstance().getVisionModeNight(); } LocationDialog::~LocationDialog() { delete ui; } void LocationDialog::languageChanged() { if (dialog) ui->retranslateUi(dialog); } void LocationDialog::styleChanged() { // Make the map red if needed if (dialog) setMapForLocation(StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation()); } // Initialize the dialog widgets and connect the signals/slots void LocationDialog::createDialogContent() { // We try to directly connect to the observer slots as much as we can ui->setupUi(dialog); // Init the SpinBox entries ui->longitudeSpinBox->setDisplayFormat(AngleSpinBox::DMSSymbols); ui->longitudeSpinBox->setPrefixType(AngleSpinBox::Longitude); ui->latitudeSpinBox->setDisplayFormat(AngleSpinBox::DMSSymbols); ui->latitudeSpinBox->setPrefixType(AngleSpinBox::Latitude); QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel((QAbstractItemModel*)StelApp::getInstance().getLocationMgr().getModelAll()); proxyModel->sort(0, Qt::AscendingOrder); proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); ui->citiesListView->setModel(proxyModel); SolarSystem* ssystem = GETSTELMODULE(SolarSystem); ui->planetNameComboBox->insertItems(0, ssystem->getAllPlanetEnglishNames()); ui->countryNameComboBox->insertItems(0, StelLocaleMgr::getAllCountryNames()); connect(ui->citySearchLineEdit, SIGNAL(textChanged(const QString&)), proxyModel, SLOT(setFilterWildcard(const QString&))); connect(ui->citiesListView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(listItemActivated(const QModelIndex&))); // Connect all the QT signals connect(ui->closeStelWindow, SIGNAL(clicked()), this, SLOT(close())); connect(ui->mapLabel, SIGNAL(positionChanged(double, double)), this, SLOT(setPositionFromMap(double, double))); connect(ui->addLocationToListPushButton, SIGNAL(clicked()), this, SLOT(addCurrentLocationToList())); connect(ui->deleteLocationFromListPushButton, SIGNAL(clicked()), this, SLOT(deleteCurrentLocationFromList())); setFieldsFromLocation(StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation()); const bool b = StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation().getID() ==StelApp::getInstance().getCore()->getNavigator()->getDefaultLocationID(); ui->useAsDefaultLocationCheckBox->setChecked(b); ui->useAsDefaultLocationCheckBox->setEnabled(!b); connect(ui->useAsDefaultLocationCheckBox, SIGNAL(clicked()), this, SLOT(useAsDefaultClicked())); connectEditSignals(); QTimer* refreshTimer = new QTimer(this); connect(refreshTimer, SIGNAL(timeout()), this, SLOT(updateFromProgram())); refreshTimer->start(200); ui->citySearchLineEdit->setFocus(); } // Update the widget to make sure it is synchrone if the location is changed programmatically void LocationDialog::updateFromProgram() { if (!dialog->isVisible()) return; // Check that the use as default check box needs to be updated const bool b = StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation().getID() == StelApp::getInstance().getCore()->getNavigator()->getDefaultLocationID(); if (b!=ui->useAsDefaultLocationCheckBox->isChecked()) { ui->useAsDefaultLocationCheckBox->setChecked(b); ui->useAsDefaultLocationCheckBox->setEnabled(!b); } // removing this check and return... we might have the location changed // by a script or plugin, and as such we should update the map whenever the // location window is visible. if (isEditingNew==true) return; const QString& key1 = StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation().getID(); const QString& key2 = locationFromFields().getID(); if (key1!=key2) { setFieldsFromLocation(StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation()); } } void LocationDialog::disconnectEditSignals() { disconnect(ui->longitudeSpinBox, SIGNAL(valueChanged()), this, SLOT(spinBoxChanged())); disconnect(ui->latitudeSpinBox, SIGNAL(valueChanged()), this, SLOT(spinBoxChanged())); disconnect(ui->altitudeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(spinBoxChanged(int))); disconnect(ui->planetNameComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(comboBoxChanged(const QString&))); disconnect(ui->countryNameComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(comboBoxChanged(const QString&))); disconnect(ui->countryNameComboBox, SIGNAL(activated(const QString&)), this, SLOT(comboBoxChanged(const QString&))); disconnect(ui->cityNameLineEdit, SIGNAL(textEdited(const QString&)), this, SLOT(locationNameChanged(const QString&))); } void LocationDialog::connectEditSignals() { connect(ui->longitudeSpinBox, SIGNAL(valueChanged()), this, SLOT(spinBoxChanged())); connect(ui->latitudeSpinBox, SIGNAL(valueChanged()), this, SLOT(spinBoxChanged())); connect(ui->altitudeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(spinBoxChanged(int))); connect(ui->planetNameComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(comboBoxChanged(const QString&))); connect(ui->countryNameComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(comboBoxChanged(const QString&))); connect(ui->countryNameComboBox, SIGNAL(activated(const QString&)), this, SLOT(comboBoxChanged(const QString&))); connect(ui->cityNameLineEdit, SIGNAL(textEdited(const QString&)), this, SLOT(locationNameChanged(const QString&))); } void LocationDialog::setFieldsFromLocation(const StelLocation& loc) { // Deactivate edit signals disconnectEditSignals(); ui->cityNameLineEdit->setText(loc.name); int idx = ui->countryNameComboBox->findText(loc.country); if (idx==-1) { // Use France as default ui->countryNameComboBox->findText("France", Qt::MatchCaseSensitive); } ui->countryNameComboBox->setCurrentIndex(idx); ui->longitudeSpinBox->setDegrees(loc.longitude); ui->latitudeSpinBox->setDegrees(loc.latitude); ui->altitudeSpinBox->setValue(loc.altitude); idx = ui->planetNameComboBox->findText(loc.planetName, Qt::MatchCaseSensitive); if (idx==-1) { // Use Earth as default ui->planetNameComboBox->findText("Earth"); } ui->planetNameComboBox->setCurrentIndex(idx); setMapForLocation(loc); // Set pointer position ui->mapLabel->setCursorPos(loc.longitude, loc.latitude); ui->deleteLocationFromListPushButton->setEnabled(StelApp::getInstance().getLocationMgr().canDeleteUserLocation(loc.getID())); // Reactivate edit signals connectEditSignals(); } // Update the map for the given location. void LocationDialog::setMapForLocation(const StelLocation& loc) { // Avoids usless processing if (lastPlanet==loc.planetName && lastVisionMode==StelApp::getInstance().getVisionModeNight()) return; QPixmap pixmap; // Try to set the proper planet map image if (loc.planetName=="Earth") { // Special case for earth, we don't want to see the clouds pixmap = QPixmap(":/graphicGui/world.png"); } else { SolarSystem* ssm = GETSTELMODULE(SolarSystem); PlanetP p = ssm->searchByEnglishName(loc.planetName); QString path; if (p) { try { path = StelFileMgr::findFile("textures/"+p->getTextMapName()); } catch (std::runtime_error& e) { qWarning() << "ERROR - could not find planet map for " << loc.planetName << e.what(); return; } pixmap = QPixmap(path); } } if (StelApp::getInstance().getVisionModeNight()) { ui->mapLabel->setPixmap(StelButton::makeRed(pixmap)); } else { ui->mapLabel->setPixmap(pixmap); } // For caching lastPlanet = loc.planetName; lastVisionMode = StelApp::getInstance().getVisionModeNight(); } // Create a StelLocation instance from the fields StelLocation LocationDialog::locationFromFields() const { StelLocation loc; loc.planetName = ui->planetNameComboBox->currentText(); loc.name = ui->cityNameLineEdit->text(); loc.latitude = ui->latitudeSpinBox->valueDegrees(); loc.longitude = ui->longitudeSpinBox->valueDegrees(); loc.altitude = ui->altitudeSpinBox->value(); loc.country = ui->countryNameComboBox->currentText(); return loc; } void LocationDialog::listItemActivated(const QModelIndex& index) { isEditingNew=false; ui->addLocationToListPushButton->setEnabled(false); StelLocation loc = StelApp::getInstance().getLocationMgr().locationForSmallString(index.data().toString()); setFieldsFromLocation(loc); StelApp::getInstance().getCore()->getNavigator()->moveObserverTo(loc, 0.); const bool b = loc.getID()==StelApp::getInstance().getCore()->getNavigator()->getDefaultLocationID(); ui->useAsDefaultLocationCheckBox->setChecked(b); ui->useAsDefaultLocationCheckBox->setEnabled(!b); } void LocationDialog::setPositionFromMap(double longitude, double latitude) { reportEdit(); StelLocation loc = locationFromFields(); loc.latitude = latitude; loc.longitude = longitude; setFieldsFromLocation(loc); StelApp::getInstance().getCore()->getNavigator()->moveObserverTo(loc, 0.); } // Called when the planet name is changed by hand void LocationDialog::comboBoxChanged(const QString&) { reportEdit(); StelLocation loc = locationFromFields(); if (loc.planetName!=StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation().planetName) setFieldsFromLocation(loc); StelApp::getInstance().getCore()->getNavigator()->moveObserverTo(loc, 0.); } void LocationDialog::spinBoxChanged(int ) { reportEdit(); StelLocation loc = locationFromFields(); StelApp::getInstance().getCore()->getNavigator()->moveObserverTo(loc, 0.); } // Called when the location name is manually changed void LocationDialog::locationNameChanged(const QString&) { reportEdit(); } void LocationDialog::reportEdit() { if (isEditingNew==false) { // The user starts editing manually a field, this creates automatically a new location // and allows to save it to the user locations list isEditingNew=true; } StelLocation loc = locationFromFields(); if (!StelApp::getInstance().getLocationMgr().canSaveUserLocation(loc)) { if (ui->cityNameLineEdit->hasFocus()) { // The user is editing the location name: don't change it! ui->addLocationToListPushButton->setEnabled(false); ui->deleteLocationFromListPushButton->setEnabled(false); return; } else { ui->cityNameLineEdit->setText(q_("New Location")); ui->cityNameLineEdit->selectAll(); loc = locationFromFields(); } } ui->addLocationToListPushButton->setEnabled(isEditingNew && StelApp::getInstance().getLocationMgr().canSaveUserLocation(loc)); ui->deleteLocationFromListPushButton->setEnabled(StelApp::getInstance().getLocationMgr().canDeleteUserLocation(loc.getID())); } // Called when the user clic on the save button void LocationDialog::addCurrentLocationToList() { const StelLocation& loc = locationFromFields(); ui->citySearchLineEdit->clear(); StelApp::getInstance().getLocationMgr().saveUserLocation(loc); isEditingNew=false; ui->addLocationToListPushButton->setEnabled(false); const QAbstractItemModel* model = ui->citiesListView->model(); const QString id = loc.getID(); for (int i=0;irowCount();++i) { if (model->index(i,0).data()==id) { ui->citiesListView->scrollTo(model->index(i,0)); ui->citiesListView->selectionModel()->select(model->index(i,0), QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Rows); listItemActivated(model->index(i,0)); break; } } } // Called when the user wants to use the current location as default void LocationDialog::useAsDefaultClicked() { StelApp::getInstance().getCore()->getNavigator()->setDefaultLocationID(StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation().getID()); const bool b = StelApp::getInstance().getCore()->getNavigator()->getCurrentLocation().getID()== StelApp::getInstance().getCore()->getNavigator()->getDefaultLocationID(); ui->useAsDefaultLocationCheckBox->setChecked(b); ui->useAsDefaultLocationCheckBox->setEnabled(!b); } // Called when the user clic on the delete button void LocationDialog::deleteCurrentLocationFromList() { const StelLocation& loc = locationFromFields(); StelApp::getInstance().getLocationMgr().deleteUserLocation(loc.getID()); }