1 /*
2 * Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov (add/remove landscapes feature)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
19 */
20 #include "AddRemoveLandscapesDialog.hpp"
21 #include "ui_addRemoveLandscapesDialog.h"
22
23 #include "Dialog.hpp"
24 #include "LandscapeMgr.hpp"
25 #include "StelApp.hpp"
26 #include "StelModuleMgr.hpp"
27 #include "StelLocaleMgr.hpp"
28 #include "StelMainView.hpp"
29
30 #include <QDebug>
31 #include <QFileDialog>
32 #include <QString>
33 #include <QMessageBox>
34
AddRemoveLandscapesDialog()35 AddRemoveLandscapesDialog::AddRemoveLandscapesDialog() : StelDialog("AddRemoveLandscapes")
36 {
37 ui = new Ui_addRemoveLandscapesDialogForm;
38 landscapeManager = GETSTELMODULE(LandscapeMgr);
39 lastUsedDirectoryPath = QDir::homePath();
40 }
41
~AddRemoveLandscapesDialog()42 AddRemoveLandscapesDialog::~AddRemoveLandscapesDialog()
43 {
44 delete ui;
45 }
46
retranslate()47 void AddRemoveLandscapesDialog::retranslate()
48 {
49 if (dialog)
50 ui->retranslateUi(dialog);
51 }
52
53 // Initialize the dialog widgets and connect the signals/slots
createDialogContent()54 void AddRemoveLandscapesDialog::createDialogContent()
55 {
56 ui->setupUi(dialog);
57
58 //Signals and slots
59 connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslate()));
60 connect(ui->closeStelWindow, SIGNAL(clicked()), this, SLOT(close()));
61 connect(ui->TitleBar, SIGNAL(movedTo(QPoint)), this, SLOT(handleMovedTo(QPoint)));
62
63 connect(ui->pushButtonBrowseForArchive, SIGNAL(clicked()), this, SLOT(browseForArchiveClicked()));
64 connect(ui->listWidgetUserLandscapes, SIGNAL(currentRowChanged(int)), this, SLOT(updateSidePane(int)));
65 connect(ui->pushButtonRemove, SIGNAL(clicked()), this, SLOT(removeClicked()));
66 connect(ui->pushButtonMessageOK, SIGNAL(clicked()), this, SLOT(messageAcknowledged()));
67
68 connect(landscapeManager, SIGNAL(landscapesChanged()), this, SLOT(populateLists()));
69 connect(landscapeManager, SIGNAL(errorUnableToOpen(QString)), this, SLOT(messageUnableToOpen(QString)));
70 connect(landscapeManager, SIGNAL(errorNotArchive()), this, SLOT(messageNotArchive()));
71 connect(landscapeManager, SIGNAL(errorNotUnique(QString)), this, SLOT(messageNotUnique(QString)));
72 connect(landscapeManager, SIGNAL(errorRemoveManually(QString)), this, SLOT(messageRemoveManually(QString)));
73
74 ui->groupBoxMessage->setVisible(false);
75
76 populateLists();
77 }
78
setVisible(bool v)79 void AddRemoveLandscapesDialog::setVisible(bool v)
80 {
81 StelDialog::setVisible(v);
82 //Make sure that every time when the dialog is displayed, the current
83 //landscape is selected in the list of user landscapes if it is in the list.
84 populateLists();
85 }
86
populateLists()87 void AddRemoveLandscapesDialog::populateLists()
88 {
89 ui->listWidgetUserLandscapes->clear();
90 QStringList landscapes = landscapeManager->getUserLandscapeIDs();
91 if (!landscapes.isEmpty())
92 {
93 landscapes.sort();
94 ui->listWidgetUserLandscapes->addItems(landscapes);
95 //If the current landscape is in the list of user landscapes, select its entry
96 if((ui->listWidgetUserLandscapes->findItems(landscapeManager->getCurrentLandscapeID(), Qt::MatchExactly).isEmpty()))
97 {
98 //If the current landscape is not in the list, simply select the first row
99 ui->listWidgetUserLandscapes->setCurrentRow(0);
100 }
101 else
102 {
103 ui->listWidgetUserLandscapes->setCurrentItem(ui->listWidgetUserLandscapes->findItems(landscapeManager->getCurrentLandscapeID(), Qt::MatchExactly).first());
104 }
105 }
106 else
107 {
108 //Force disabling the side pane
109 updateSidePane(-1);
110 }
111 }
112
browseForArchiveClicked()113 void AddRemoveLandscapesDialog::browseForArchiveClicked()
114 {
115 QString caption = q_("Select a ZIP archive that contains a Stellarium landscape");
116 // TRANSLATORS: This string is displayed in the "Files of type:" drop-down list in the standard file selection dialog.
117 QString filter = q_("ZIP archives");
118 filter += " (*.zip)";
119 QString sourceArchivePath = QFileDialog::getOpenFileName(Q_NULLPTR, caption, lastUsedDirectoryPath, filter);
120 bool useLandscape = ui->checkBoxUseLandscape->isChecked();
121 if (!sourceArchivePath.isEmpty() && QFile::exists(sourceArchivePath))
122 {
123 //Remember the last successfully used directory
124 lastUsedDirectoryPath = QFileInfo(sourceArchivePath).path();
125
126 QString newLandscapeID = landscapeManager->installLandscapeFromArchive(sourceArchivePath, useLandscape);
127 if(!newLandscapeID.isEmpty())
128 {
129 //Show a message
130 QString successMessage = QString(q_("Landscape \"%1\" has been installed successfully.")).arg(newLandscapeID);
131 displayMessage(q_("Success"), successMessage);
132
133 //Make the new landscape selected in the list
134 //populateLists(); //No longer needed after the migration to signals/slots
135 ui->listWidgetUserLandscapes->setCurrentItem((ui->listWidgetUserLandscapes->findItems(newLandscapeID, Qt::MatchExactly)).first());
136 }
137 else
138 {
139 //If no error message has been displayed by the signal/slot mechanism,
140 //display a generic message.
141 if (!ui->groupBoxMessage->isVisible())
142 {
143 //Show an error message
144 QString failureMessage = q_("No landscape was installed.");
145 displayMessage(q_("Error!"), failureMessage);
146 }
147 }
148 }
149 }
150
removeClicked()151 void AddRemoveLandscapesDialog::removeClicked()
152 {
153 int reply = QMessageBox(QMessageBox::Question,
154 q_("Remove an installed landscape"),
155 q_("Do you really want to remove this landscape?"),
156 QMessageBox::Yes|QMessageBox::No,
157 &StelMainView::getInstance()).exec();
158
159 if (reply == QMessageBox::Yes)
160 {
161 QString landscapeID = ui->listWidgetUserLandscapes->currentItem()->data(0).toString();
162 if(landscapeManager->removeLandscape(landscapeID))
163 {
164 //populateLists();//No longer needed after the migration to signals/slots
165 QString successMessage = QString(q_("Landscape \"%1\" has been removed successfully.")).arg(landscapeID);
166 displayMessage(q_("Success"), successMessage);
167 }
168 else
169 {
170 //If no error message has been displayed by the signal/slot mechanism,
171 //display a generic message.
172 if (!ui->groupBoxMessage->isVisible())
173 {
174 //Show an error message
175 //NB! This string is used elsewhere. Modify both to avoid two nearly identical translations.
176 QString failureMessage = q_("The selected landscape could not be (completely) removed.");
177 displayMessage(q_("Error!"), failureMessage);
178 }
179 }
180 }
181 }
182
updateSidePane(int newRow)183 void AddRemoveLandscapesDialog::updateSidePane(int newRow)
184 {
185 bool displaySidePane = (newRow >= 0);
186 ui->labelLandscapeName->setVisible(displaySidePane);
187 ui->labelLandscapeSize->setVisible(displaySidePane);
188 ui->pushButtonRemove->setEnabled(displaySidePane);
189 ui->labelWarning->setEnabled(displaySidePane);
190 if (!displaySidePane)
191 return;
192
193 QString landscapeID = ui->listWidgetUserLandscapes->item(newRow)->data(0).toString();
194 //Name
195 ui->labelLandscapeName->setText("<h3>"+landscapeManager->loadLandscapeName(landscapeID)+"</h3>");
196 //Size in MiB
197 double landscapeSize = landscapeManager->loadLandscapeSize(landscapeID) / static_cast<double>(1024*1024);
198 // TRANSLATORS: MiB = mebibytes (IEC 60027-2 standard for 2^20 bytes)
199 ui->labelLandscapeSize->setText(QString(q_("Size on disk: %1 MiB")).arg(landscapeSize, 0, 'f', 2));
200 }
201
messageAcknowledged()202 void AddRemoveLandscapesDialog::messageAcknowledged()
203 {
204 ui->groupBoxMessage->setVisible(false);
205 ui->groupBoxAdd->setVisible(true);
206 ui->groupBoxRemove->setVisible(true);
207 ui->labelMessage->clear();
208 ui->groupBoxMessage->setTitle(QString());
209 }
210
displayMessage(QString title,QString message)211 void AddRemoveLandscapesDialog::displayMessage(QString title, QString message)
212 {
213 ui->labelMessage->setText(message);
214 ui->groupBoxMessage->setTitle(title);
215 ui->groupBoxMessage->setVisible(true);
216 ui->groupBoxAdd->setVisible(false);
217 ui->groupBoxRemove->setVisible(false);
218 }
219
messageUnableToOpen(QString path)220 void AddRemoveLandscapesDialog::messageUnableToOpen(QString path)
221 {
222 QString failureMessage = q_("No landscape was installed.");
223 failureMessage.append(" ");
224 // TRANSLATORS: The parameter is a file/directory path that may be quite long.
225 failureMessage.append(q_("Stellarium cannot open for reading or writing %1").arg(path));
226 displayMessage(q_("Error!"), failureMessage);
227 }
228
messageNotArchive()229 void AddRemoveLandscapesDialog::messageNotArchive()
230 {
231 QString failureMessage = q_("No landscape was installed.") + " " + q_("The selected file is not a ZIP archive or does not contain a Stellarium landscape.");
232 displayMessage(q_("Error!"), failureMessage);
233 }
234
messageNotUnique(QString nameOrID)235 void AddRemoveLandscapesDialog::messageNotUnique(QString nameOrID)
236 {
237 // TRANSLATORS: The parameter is the duplicate name or identifier.
238 QString nameMessage = q_("A landscape with the same name or identifier (%1) already exists.").arg(nameOrID);
239 QString failureMessage = q_("No landscape was installed.") + " " + nameMessage;
240 displayMessage(q_("Error!"), failureMessage);
241 }
242
messageRemoveManually(QString path)243 void AddRemoveLandscapesDialog::messageRemoveManually(QString path)
244 {
245 //NB! This string is used elsewhere. Modify both to avoid two nearly identical translations.
246 QString failureMessage = q_("The selected landscape could not be (completely) removed.");
247 failureMessage.append(" ");
248 // TRANSLATORS: The parameter is a file/directory path that may be quite long. "It" refers to a landscape that can't be removed.
249 failureMessage.append(q_("You can remove it manually by deleting the following directory: %1").arg(path));
250 displayMessage(q_("Error!"), failureMessage);
251 }
252