Skip to content

Commit

Permalink
Save As dialog can save in all formats it is safe to save in
Browse files Browse the repository at this point in the history
* All Plugins, which can be read as well, can be used for
  saving as well.

* MapDocument class contains a new member (mWriterPluginFileName),
  which determines in which format the map should be saved.
  (It needs to be set accordingly, when opening a new File)

* The plugin manager has some more conversions.

* MapDocuments setFileName (only used by its saving function)
  is private now.

Closes mapeditor#18.
  • Loading branch information
stefanbeller committed Sep 23, 2012
1 parent ccc607c commit 4cab9ea
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 13 deletions.
59 changes: 50 additions & 9 deletions src/tiled/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,17 +553,27 @@ bool MainWindow::openFile(const QString &fileName,
}
}

if (!mapReader)
// check if we can save in that format as well
QString writerPluginFileName;
PluginManager *pm = PluginManager::instance();
if (mapReader) {
if (dynamic_cast<MapWriterInterface*>(mapReader)) {
if (const Plugin *plugin = pm->asPlugin(mapReader))
writerPluginFileName = plugin->fileName;
}
} else {
mapReader = &tmxMapReader;
}

Map *map = mapReader->read(fileName);
if (!map) {
QMessageBox::critical(this, tr("Error Opening Map"),
mapReader->errorString());
return false;
}

addMapDocument(new MapDocument(map, fileName));
MapDocument *mapDocument = new MapDocument(map, fileName);
mapDocument->setWriterPluginFileName(writerPluginFileName);
addMapDocument(mapDocument);
setRecentFile(fileName);
return true;
}
Expand Down Expand Up @@ -700,21 +710,45 @@ bool MainWindow::saveFile()

const QString currentFileName = mMapDocument->fileName();

if (currentFileName.endsWith(QLatin1String(".tmx"), Qt::CaseInsensitive))
return saveFile(currentFileName);
else
if (!saveFile(currentFileName))
return saveFileAs();

return true;
}

bool MainWindow::saveFileAs()
{
const QString tmxfilter = tr("Tiled map files (*.tmx)");
QString filter = QString(tmxfilter);
PluginManager *pm = PluginManager::instance();
foreach (const Plugin &plugin, pm->plugins()) {
const MapWriterInterface *writer = qobject_cast<MapWriterInterface*>
(plugin.instance);
const MapReaderInterface *reader = qobject_cast<MapReaderInterface*>
(plugin.instance);
if (writer && reader) {
foreach (const QString &str, writer->nameFilters()) {
if (!str.isEmpty()) {
filter += QLatin1String(";;");
filter += str;
}
}
}
}

QString selectedFilter;
if (mMapDocument)
selectedFilter = mMapDocument->writerPluginFileName();

if (selectedFilter.isEmpty())
selectedFilter = tmxfilter;

QString suggestedFileName;
if (mMapDocument && !mMapDocument->fileName().isEmpty()) {
const QFileInfo fileInfo(mMapDocument->fileName());
suggestedFileName = fileInfo.path();
suggestedFileName += QLatin1Char('/');
suggestedFileName += fileInfo.completeBaseName();
suggestedFileName += QLatin1String(".tmx");
suggestedFileName += fileInfo.fileName();
} else {
suggestedFileName = fileDialogStartLocation();
suggestedFileName += QLatin1Char('/');
Expand All @@ -723,7 +757,14 @@ bool MainWindow::saveFileAs()

const QString fileName =
QFileDialog::getSaveFileName(this, QString(), suggestedFileName,
tr("Tiled map files (*.tmx)"));
filter, &selectedFilter);

QString writerPluginFilename;
if (const Plugin *p = pm->getPluginByNameFilter(selectedFilter))
writerPluginFilename = p->fileName;

mMapDocument->setWriterPluginFileName(writerPluginFilename);

if (!fileName.isEmpty())
return saveFile(fileName);
return false;
Expand Down
13 changes: 11 additions & 2 deletions src/tiled/mapdocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "offsetlayer.h"
#include "orthogonalrenderer.h"
#include "painttilelayer.h"
#include "pluginmanager.h"
#include "resizelayer.h"
#include "resizemap.h"
#include "staggeredrenderer.h"
Expand Down Expand Up @@ -117,11 +118,19 @@ bool MapDocument::save(QString *error)

bool MapDocument::save(const QString &fileName, QString *error)
{
PluginManager *pm = PluginManager::instance();

MapWriterInterface *chosenWriter = 0;
if (const Plugin *plugin = pm->getPluginByFileName(mWriterPluginFileName))
chosenWriter = qobject_cast<MapWriterInterface*>(plugin->instance);

TmxMapWriter mapWriter;
if (!chosenWriter)
chosenWriter = &mapWriter;

if (!mapWriter.write(map(), fileName)) {
if (!chosenWriter->write(map(), fileName)) {
if (error)
*error = mapWriter.errorString();
*error = chosenWriter->errorString();
return false;
}

Expand Down
19 changes: 17 additions & 2 deletions src/tiled/mapdocument.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,18 @@ class MapDocument : public QObject
* file was saved successfully. If not, <i>error</i> will be set to the
* error message if it is not 0.
*
* If the save was succesful, the file name of this document will be set
* If the save was successful, the file name of this document will be set
* to \a fileName.
*
* The map format will be the same as this map was opened with.
*/
bool save(const QString &fileName, QString *error = 0);

QString fileName() const { return mFileName; }
void setFileName(const QString &fileName);

QString writerPluginFileName() const { return mWriterPluginFileName; }
void setWriterPluginFileName(const QString &writerPluginFileName)
{ mWriterPluginFileName = writerPluginFileName; }

QString displayName() const;

Expand Down Expand Up @@ -295,9 +300,19 @@ private slots:
void onLayerRemoved(int index);

private:
void setFileName(const QString &fileName);
void deselectObjects(const QList<MapObject*> &objects);

QString mFileName;

/**
* The filename of a plugin is unique. So it can be used to determine
* the right plugin to be used for saving the map again.
* The nameFilter of a plugin can not be used, since it's translatable.
* The filename of a plugin must not change while maps are open using this
* plugin.
*/
QString mWriterPluginFileName;
Map *mMap;
LayerModel *mLayerModel;
QRegion mTileSelection;
Expand Down
22 changes: 22 additions & 0 deletions src/tiled/pluginmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include "pluginmanager.h"

#include "mapwriterinterface.h"

#include <QApplication>
#include <QDebug>
#include <QDir>
Expand Down Expand Up @@ -87,3 +89,23 @@ void PluginManager::loadPlugins()
mPlugins.append(Plugin(pluginFile, instance));
}
}

const Plugin *PluginManager::getPluginByFileName(QString pluginFileName) const
{
foreach (const Plugin &plugin, mPlugins)
if (pluginFileName == plugin.fileName)
return &plugin;

return 0;
}

const Plugin *PluginManager::getPluginByNameFilter(QString pluginFilter) const
{
foreach (const Plugin &plugin, mPlugins)
if (MapWriterInterface *result =
qobject_cast<MapWriterInterface*>(plugin.instance))
if (result->nameFilters().contains(pluginFilter))
return &plugin;

return 0;
}
18 changes: 18 additions & 0 deletions src/tiled/pluginmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,24 @@ class PluginManager
return results;
}

const Plugin *getPluginByFileName(QString pluginFileName) const;

const Plugin *getPluginByNameFilter(QString pluginFilter) const;

/**
* Returns the plugin, which implements the given interface.
* This must be done via searching the plugins for the right plugins,
* since casting doesn't work, an interface is not a plugin.
*/
template<typename T> const Plugin *asPlugin(T *interface) const
{
foreach (const Plugin &plugin, mPlugins)
if (T *result = qobject_cast<T*>(plugin.instance))
if (result == interface)
return &plugin;
return 0;
}

private:
Q_DISABLE_COPY(PluginManager)

Expand Down

0 comments on commit 4cab9ea

Please sign in to comment.