LandscapeMgr.cpp   LandscapeMgr.cpp 
/* /*
* Stellarium * Stellarium
* Copyright (C) 2006 Fabien Chereau * Copyright (C) 2006 Fabien Chereau
* Copyright (C) 2010 Bogdan Marinov (add/remove landscapes feature)
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA.
*/ */
#include <QDebug> #include <QDebug>
#include <QSettings> #include <QSettings>
#include <QString> #include <QString>
#include <QDir>
#include <QFile>
#include <QTemporaryFile>
#ifdef USE_OPENGL_ES2 #ifdef USE_OPENGL_ES2
#include "GLES2/gl2.h" #include "GLES2/gl2.h"
#else #else
#include <QtOpenGL> #include <QtOpenGL>
#endif #endif
#include <stdexcept>
#include "LandscapeMgr.hpp" #include "LandscapeMgr.hpp"
#include "Landscape.hpp" #include "Landscape.hpp"
#include "Atmosphere.hpp" #include "Atmosphere.hpp"
#include "StelApp.hpp" #include "StelApp.hpp"
#include "SolarSystem.hpp" #include "SolarSystem.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelLocaleMgr.hpp" #include "StelLocaleMgr.hpp"
#include "StelModuleMgr.hpp" #include "StelModuleMgr.hpp"
#include "StelFileMgr.hpp" #include "StelFileMgr.hpp"
#include "Planet.hpp" #include "Planet.hpp"
#include "StelIniParser.hpp" #include "StelIniParser.hpp"
#include "StelSkyDrawer.hpp" #include "StelSkyDrawer.hpp"
#include "StelPainter.hpp" #include "StelPainter.hpp"
#include "karchive.h"
#include "kzip.h"
// Class which manages the cardinal points displaying // Class which manages the cardinal points displaying
class Cardinals class Cardinals
{ {
public: public:
Cardinals(float _radius = 1.); Cardinals(float _radius = 1.);
virtual ~Cardinals(); virtual ~Cardinals();
void draw(const StelCore* core, double latitude) const; void draw(const StelCore* core, double latitude) const;
void setColor(const Vec3f& c) {color = c;} void setColor(const Vec3f& c) {color = c;}
Vec3f get_color() {return color;} Vec3f get_color() {return color;}
skipping to change at line 116 skipping to change at line 124
// Normal transparency mode // Normal transparency mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Vec3f pos; Vec3f pos;
Vec3f xy; Vec3f xy;
float shift = sPainter.getFontMetrics().width(sNorth)/2; float shift = sPainter.getFontMetrics().width(sNorth)/2;
// N for North // N for North
pos.set(-1.f, 0.f, 0.f); pos.set(-1.f, 0.f, 0.f);
if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[0], 0., -shift, -shift); if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[0], 0., -shift, -shift, false);
// S for South // S for South
pos.set(1.f, 0.f, 0.f); pos.set(1.f, 0.f, 0.f);
if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[1], 0., -shift, -shift); if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[1], 0., -shift, -shift, false);
// E for East // E for East
pos.set(0.f, 1.f, 0.f); pos.set(0.f, 1.f, 0.f);
if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[2], 0., -shift, -shift); if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[2], 0., -shift, -shift, false);
// W for West // W for West
pos.set(0.f, -1.f, 0.f); pos.set(0.f, -1.f, 0.f);
if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[3], 0., -shift, -shift); if (prj->project(pos,xy)) sPainter.drawText(xy[0], xy[1], d[3], 0., -shift, -shift, false);
} }
// Translate cardinal labels with gettext to current sky language and updat e font for the language // Translate cardinal labels with gettext to current sky language and updat e font for the language
void Cardinals::updateI18n() void Cardinals::updateI18n()
{ {
StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSky Translator(); StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getApp StelTranslator();
sNorth = trans.qtranslate("N"); sNorth = trans.qtranslate("N");
sSouth = trans.qtranslate("S"); sSouth = trans.qtranslate("S");
sEast = trans.qtranslate("E"); sEast = trans.qtranslate("E");
sWest = trans.qtranslate("W"); sWest = trans.qtranslate("W");
} }
LandscapeMgr::LandscapeMgr() : atmosphere(NULL), cardinalsPoints(NULL), lan dscape(NULL), flagLandscapeSetsLocation(false) LandscapeMgr::LandscapeMgr() : atmosphere(NULL), cardinalsPoints(NULL), lan dscape(NULL), flagLandscapeSetsLocation(false)
{ {
setObjectName("LandscapeMgr"); setObjectName("LandscapeMgr");
//TODO: Find a way to obtain this list automatically.
//Note: The first entry in the list is used as the default 'default
landscape' in removeLandscape().
packagedLandscapeIDs = (QStringList() << "guereins" << "trees" << "m
oon" << "hurricane" << "ocean" << "garching" << "mars" << "saturn");
} }
LandscapeMgr::~LandscapeMgr() LandscapeMgr::~LandscapeMgr()
{ {
delete atmosphere; delete atmosphere;
delete cardinalsPoints; delete cardinalsPoints;
delete landscape; delete landscape;
landscape = NULL; landscape = NULL;
} }
skipping to change at line 409 skipping to change at line 421
QStringList result; QStringList result;
// We just look over the map of names to IDs and extract the keys // We just look over the map of names to IDs and extract the keys
foreach (QString i, nameToDirMap.values()) foreach (QString i, nameToDirMap.values())
{ {
result += i; result += i;
} }
return result; return result;
} }
QStringList LandscapeMgr::getUserLandscapeIDs() const
{
QMap<QString,QString> nameToDirMap = getNameToDirMap();
QStringList result;
foreach (QString id, nameToDirMap.values())
{
if(!packagedLandscapeIDs.contains(id))
{
result += id;
}
}
return result;
}
QString LandscapeMgr::getCurrentLandscapeName() const QString LandscapeMgr::getCurrentLandscapeName() const
{ {
return landscape->getName(); return landscape->getName();
} }
QString LandscapeMgr::getCurrentLandscapeHtmlDescription() const QString LandscapeMgr::getCurrentLandscapeHtmlDescription() const
{ {
QString desc = QString("<h3>%1</h3>").arg(landscape->getName()); QString desc = QString("<h3>%1</h3>").arg(landscape->getName());
desc += landscape->getDescription(); desc += landscape->getDescription();
desc+="<br><br>"; desc+="<br><br>";
skipping to change at line 602 skipping to change at line 628
QString k = landscapeIni.value("landscape/name").toS tring(); QString k = landscapeIni.value("landscape/name").toS tring();
result[k] = dir; result[k] = dir;
} }
catch (std::runtime_error& e) catch (std::runtime_error& e)
{ {
//qDebug << "WARNING: unable to successfully read la ndscape.ini file from landscape " << dir; //qDebug << "WARNING: unable to successfully read la ndscape.ini file from landscape " << dir;
} }
} }
return result; return result;
} }
QString LandscapeMgr::installLandscapeFromArchive(QString sourceFilePath, b
ool display, bool toMainDirectory)
{
Q_UNUSED(toMainDirectory);
if (!QFile::exists(sourceFilePath))
{
qDebug() << "LandscapeMgr: File does not exist:" << sourceFi
lePath;
emit errorUnableToOpen(sourceFilePath);
return QString();
}
QDir parentDestinationDir;
//TODO: Fix the "for all users" option
parentDestinationDir.setPath(StelFileMgr::getUserDir());
if (!parentDestinationDir.exists("landscapes"))
{
//qDebug() << "LandscapeMgr: No 'landscapes' subdirectory ex
ists in" << parentDestinationDir.absolutePath();
if (!parentDestinationDir.mkdir("landscapes"))
{
qWarning() << "LandscapeMgr: Unable to install lands
cape: Unable to create sub-directory 'landscapes' in" << parentDestinationD
ir.absolutePath();
emit errorUnableToOpen(QDir::cleanPath(parentDestina
tionDir.filePath("landscapes")));//parentDestinationDir.absolutePath()
return QString();
}
}
QDir destinationDir (parentDestinationDir.absoluteFilePath("landscap
es"));
KZip sourceArchive(sourceFilePath);
if(!sourceArchive.open(QIODevice::ReadOnly))
{
qWarning() << "LandscapeMgr: Unable to open as a ZIP archive
:" << sourceFilePath;
emit errorNotArchive();
return QString();
}
//Detect top directory
const KArchiveDirectory * archiveTopDirectory = NULL;
QStringList topLevelContents = sourceArchive.directory()->entries();
if(topLevelContents.contains("landscape.ini"))
{
//If the landscape archive has no top level directory...
//(test case is "tulipfield" from the Stellarium Wiki)
archiveTopDirectory = sourceArchive.directory();
}
else
{
foreach (QString entryPath, topLevelContents)
{
if (sourceArchive.directory()->entry(entryPath)->isD
irectory())
{
if((dynamic_cast<const KArchiveDirectory*>(s
ourceArchive.directory()->entry(entryPath)))->entries().contains("landscape
.ini"))
{
archiveTopDirectory = dynamic_cast<c
onst KArchiveDirectory*>(sourceArchive.directory()->entry(entryPath));
break;
}
}
}
}
if (archiveTopDirectory == NULL)
{
qWarning() << "LandscapeMgr: Unable to install landscape. Th
ere is no directory that contains a 'landscape.ini' file in the source arch
ive.";
emit errorNotArchive();
return QString();
}
/*
qDebug() << "LandscapeMgr: Contents of the source archive:" << endl
<< "- top level direcotory:" << archiveTopDirectory
->name() << endl
<< "- contents:" << archiveTopDirectory->entries();
*/
//Check if the top directory name is unique
//TODO: Prompt rename? Rename silently?
/*
if (destinationDir.exists(archiveTopDirectory->name()))
{
qWarning() << "LandscapeMgr: Unable to install landscape. A
directory named" << archiveTopDirectory->name() << "already exists in" << d
estinationDir.absolutePath();
return QString();
}
*/
//Determine the landscape's identifier
QString landscapeID = archiveTopDirectory->name();
if (landscapeID.length() < 2)
{
//If the archive has no top level directory (landscapeID is
"/"),
//use the first 65 characters of its file name for an identi
fier
QFileInfo sourceFileInfo(sourceFilePath);
landscapeID = sourceFileInfo.baseName().left(65);
}
//Check for duplicate IDs
if (getAllLandscapeIDs().contains(landscapeID))
{
qWarning() << "LandscapeMgr: Unable to install landscape. A
landscape with the ID" << landscapeID << "already exists.";
emit errorNotUnique(landscapeID);
return QString();
}
//Read the .ini file and check if the landscape name is unique
QTemporaryFile tempLandscapeIni("landscapeXXXXXX.ini");
if (tempLandscapeIni.open())
{
const KZipFileEntry * archLandscapeIni = static_cast<const K
ZipFileEntry*>(archiveTopDirectory->entry("landscape.ini"));
tempLandscapeIni.write(archLandscapeIni->createDevice()->rea
dAll());
tempLandscapeIni.close();
QSettings confLandscapeIni(tempLandscapeIni.fileName(), Stel
IniFormat);
QString landscapeName = confLandscapeIni.value("landscape/na
me").toString();
if (getAllLandscapeNames().contains(landscapeName))
{
qWarning() << "LandscapeMgr: Unable to install lands
cape. There is already a landscape named" << landscapeName;
emit errorNotUnique(landscapeName);
return QString();
}
}
//Copy the landscape directory to the target
//sourceArchive.directory()->copyTo(destinationDir.absolutePath());
//This case already has been handled - and commented out - above. :)
if(destinationDir.exists(landscapeID))
{
qWarning() << "LandscapeMgr: A subdirectory" << landscapeID
<< "already exists in" << destinationDir.absolutePath() << "Its contents ma
y be overwritten.";
}
else if(!destinationDir.mkdir(landscapeID))
{
qWarning() << "LandscapeMgr: Unable to install landscape. Un
able to create" << landscapeID << "directory in" << destinationDir.absolute
Path();
emit errorUnableToOpen(QDir::cleanPath(destinationDir.filePa
th(landscapeID)));
return QString();
}
destinationDir.cd(landscapeID);
QString destinationDirPath = destinationDir.absolutePath();
QStringList landscapeFileEntries = archiveTopDirectory->entries();
foreach (QString entry, landscapeFileEntries)
{
const KArchiveEntry * archEntry = archiveTopDirectory->entry
(entry);
if(archEntry->isFile())
{
static_cast<const KZipFileEntry*>(archEntry)->copyTo
(destinationDirPath);
}
}
sourceArchive.close();
//If necessary, make the new landscape the current landscape
if (display)
{
setCurrentLandscapeID(landscapeID);
}
//Make sure that everyone knows that the list of available landscape
s has changed
emit landscapesChanged();
qDebug() << "LandscapeMgr: Successfully installed landscape director
y" << landscapeID << "to" << destinationDir.absolutePath();
return landscapeID;
}
bool LandscapeMgr::removeLandscape(QString landscapeID)
{
if (landscapeID.isEmpty())
{
qWarning() << "LandscapeMgr: Error! No landscape ID passed t
o removeLandscape().";
return false;
}
if (packagedLandscapeIDs.contains(landscapeID))
{
qWarning() << "LandscapeMgr: Landscapes that are part of the
default installation cannot be removed.";
return false;
}
qDebug() << "LandscapeMgr: Trying to remove landscape" << landscapeI
D;
QString landscapePath = getLandscapePath(landscapeID);
if (landscapePath.isEmpty())
return false;
QDir landscapeDir(landscapePath);
foreach (QString fileName, landscapeDir.entryList(QDir::Files | QDir
::NoDotAndDotDot))
{
if(!landscapeDir.remove(fileName))
{
qWarning() << "LandscapeMgr: Unable to remove" << fi
leName;
emit errorRemoveManually(landscapeDir.absolutePath()
);
return false;
}
}
landscapeDir.cdUp();
if(!landscapeDir.rmdir(landscapeID))
{
qWarning() << "LandscapeMgr: Error! Landscape" << landscapeI
D
<< "could not be removed. "
<< "Some files were deleted, but not all.
"
<< endl
<< "LandscapeMgr: You can delete manually
" << QDir::cleanPath(landscapeDir.filePath(landscapeID));
emit errorRemoveManually(QDir::cleanPath(landscapeDir.filePa
th(landscapeID)));
return false;
}
qDebug() << "LandscapeMgr: Successfully removed" << landscapePath;
//If the landscape has been selected, revert to the default one
//TODO: Make this optional?
if (getCurrentLandscapeID() == landscapeID)
{
if(getDefaultLandscapeID() == landscapeID)
{
setDefaultLandscapeID(packagedLandscapeIDs.first());
//TODO: Find what happens if a missing landscape is
specified in the configuration file
}
setCurrentLandscapeID(getDefaultLandscapeID());
}
//Make sure that everyone knows that the list of available landscape
s has changed
emit landscapesChanged();
return true;
}
QString LandscapeMgr::getLandscapePath(QString landscapeID)
{
QString result;
//Is this necessary? This function is private.
if (landscapeID.isEmpty())
return result;
try
{
result = StelFileMgr::findFile("landscapes/" + landscapeID,
StelFileMgr::Directory);
}
catch (std::runtime_error &e)
{
qWarning() << "LandscapeMgr: Error! Unable to find" << lands
capeID << ":" << e.what();
return result;
}
return result;
}
QString LandscapeMgr::loadLandscapeName(QString landscapeID)
{
QString landscapeName;
if (landscapeID.isEmpty())
{
qWarning() << "LandscapeMgr: Error! No landscape ID passed t
o loadLandscapeName().";
return landscapeName;
}
QString landscapePath = getLandscapePath(landscapeID);
if (landscapePath.isEmpty())
return landscapeName;
QDir landscapeDir(landscapePath);
if (landscapeDir.exists("landscape.ini"))
{
QString landscapeSettingsPath = landscapeDir.filePath("lands
cape.ini");
QSettings landscapeSettings(landscapeSettingsPath, StelIniFo
rmat);
landscapeName = landscapeSettings.value("landscape/name").to
String();
}
else
{
qWarning() << "LandscapeMgr: Error! Landscape directory" <<
landscapePath << "does not contain a 'landscape.ini' file";
}
return landscapeName;
}
quint64 LandscapeMgr::loadLandscapeSize(QString landscapeID)
{
quint64 landscapeSize = 0;
if (landscapeID.isEmpty())
{
qWarning() << "LandscapeMgr: Error! No landscape ID passed t
o loadLandscapeSize().";
return landscapeSize;
}
QString landscapePath = getLandscapePath(landscapeID);
if (landscapePath.isEmpty())
return landscapeSize;
QDir landscapeDir(landscapePath);
foreach (QFileInfo file, landscapeDir.entryInfoList(QDir::Files | QD
ir::NoDotAndDotDot))
{
//qDebug() << "name:" << file.baseName() << "size:" << file.
size();
landscapeSize += file.size();
}
return landscapeSize;
}
 End of changes. 12 change blocks. 
5 lines changed or deleted 33 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/