-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Templates dock #1612
Templates dock #1612
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only a few minor comments. It's looking good and I think you've planned a good next step. I'm looking forward to see the remaining functionality!
src/tiled/objecttemplatemodel.cpp
Outdated
QModelIndex ObjectTemplateModel::index(int row, int column, | ||
const QModelIndex &parent) const | ||
{ | ||
if (parent == QModelIndex()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use if (!parent.isValid())
src/tiled/objecttemplatemodel.cpp
Outdated
QModelIndex ObjectTemplateModel::parent(const QModelIndex &index) const | ||
{ | ||
if (ObjectTemplate *objectTemplate = toObjectTemplate(index)) | ||
return createIndex(0, 0, objectTemplate->templateGroup()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Row 0 can't be always right, you need to determine the index of the template group in mTemplateGroups
.
src/tiled/objecttemplatemodel.h
Outdated
Q_OBJECT | ||
|
||
public: | ||
ObjectTemplateModel(const QList<TemplateGroup *> &templateGroups, QObject *parent = 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use nullptr
.
908f143
to
9ab31dc
Compare
The dock shows a pre-made template group as a list.
ca91c66
to
01d2b3d
Compare
I've finished loading templates on startup. testing is cumbersome because the file doesn't exist by default. The file is called templatedocuments.xml and is located in the default data location, this is it's structure
I think renaming it to templategroups.xml and have internal elements as templategroups might be a good idea but not sure. To make testing easier I will start implementing the new group button to be able to create groups then will work on adding an object to a loaded group as a template, after that I will work on error handling. One particular part that I don't like is getting a parent of a template group in the model, I loop through all the documents to find the correct parent. |
Yes, I think these would be better names as well. The "Document" is only an internal thing referring to the fact that it is a file of which the changes and format are tracked. I'm considering to rename this to "Asset", which is a common name for this as well.
That's fine. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of small comments this time. :-)
src/libtiled/templategroup.h
Outdated
private: | ||
QList<ObjectTemplate*> mTemplates; | ||
QVector<SharedTileset> mTilesets; | ||
TemplateGroupFormat *mFormat; | ||
QString mName; | ||
}; | ||
|
||
typedef QList<TemplateGroup*> TemplateGroups; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused now, should be removed.
src/tiled/objecttemplatemodel.cpp
Outdated
{ | ||
if (!parent.isValid()) { | ||
if (row < mTemplateDocuments.size()) { | ||
return createIndex(row, column, mTemplateDocuments.at(row)->templateGroup()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coding style: One space too much after return
. Also, when all branches of conditions are single lines, we leave out the {
and }
.
src/tiled/objecttemplatemodel.cpp
Outdated
if (row < mTemplateDocuments.size()) { | ||
return createIndex(row, column, mTemplateDocuments.at(row)->templateGroup()); | ||
} else { | ||
return QModelIndex(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line could be removed if the below if
is changed to an else if
.
src/tiled/objecttemplatemodel.cpp
Outdated
QVariant ObjectTemplateModel::data(const QModelIndex &index, int role) const | ||
{ | ||
if (!index.isValid()) | ||
return QVariant(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines can be removed. In general no invalid index should be passed to data
, but in case it happens, it will return QVariant()
also without this additional check.
src/tiled/templategroupdocument.cpp
Outdated
writer.setAutoFormattingIndent(1); | ||
|
||
writer.writeStartDocument(); | ||
writer.writeStartElement(QLatin1String("templateDocuments")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should keep the element names lowercase for consistency (also I see the reader requires it to be lowercase :-)).
src/tiled/templategroupdocument.cpp
Outdated
return false; | ||
} | ||
|
||
Format format = mFormat; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it sucks to have multiple formats, but since we did the same thing for maps, tilesets and the object types, it only makes sense to do the same thing for the templates since people's games are expected to load these things...
I somewhat wonder if there would be a way to serialize through some kind of interface, with different implementations storing things in different ways (XML, JSON, Lua...). Though that gets even more tricky for loading than for saving. And for sure it can't be done without changing some of these formats. :-(
Maybe we can serialize into a QVariantMap
and then save that in the various other formats in some standard way (JSON is easy by using QJsonDocument::fromVariant
). It's at least an approach we can try for new files.
src/tiled/templategroupdocument.cpp
Outdated
const QXmlStreamAttributes atts = reader.attributes(); | ||
const QString path(atts.value(QLatin1String("path")).toString()); | ||
|
||
auto templateGroupFormat = new TtxTemplateGroupFormat(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, there should be only one instance of TtxTemplateGroupFormat
. Like this it is a memory leak. I would suggest to just make a singleton for now, by adding a static method:
TtxTemplateGroupFormat *TtxTemplateGroupFormat::instance()
{
static TtxTemplateGroupFormat format;
return &format;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new way for implementing a singleton :), I thought of creating the static object as a member and manually checking every time when the instance function is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A member is only needed when the object needs to be manually deleted. This static variable is automatically destroyed at some point when the program exists, which I think will not cause any problems.
src/tiled/templategroupdocument.cpp
Outdated
|
||
auto templateGroupFormat = new TtxTemplateGroupFormat(); | ||
|
||
// TODO: handle errors that might happen while loading |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, at least don't put nullptr
into templateDocuments
. :-)
Also, don't forget to initialize templateGroup
in MapReaderPrivate::readTemplateGroup
with nullptr
or you're going to have trouble detecting errors.
src/tiled/objecttemplatemodel.cpp
Outdated
|
||
if (ObjectTemplate *objectTemplate = toObjectTemplate(index)) { | ||
auto templateGroup = objectTemplate->templateGroup(); | ||
// TODO: this doesn't work properly when multiple documents have the same group |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can't happen. You're comparing pointers here and at no point in the code would it insert the same pointer twice.
src/tiled/preferences.cpp
Outdated
void Preferences::setTemplateDocuments(const TemplateDocuments &templateDocuments) | ||
{ | ||
mTemplateDocuments = templateDocuments; | ||
// This signal isn't used yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Connect to it in TemplatesDock
. :-)
4523921
to
42709ac
Compare
Currently groups can be created and templates can be saved and viewed in the dock, the workflow still need some refining I will work on it in the upcoming days. There parts that I'm not sure how to do yet so I left TODOs there. |
src/tiled/objecttemplatemodel.cpp
Outdated
auto templateGroupDocument = new TemplateGroupDocument(templateGroup, fileName); | ||
|
||
if (!templateGroupDocument->save(fileName, error)) | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will leak the above allocated objects. Can use QScopedPointer
to prevent leaking (probably only for the templateGroupDocument
, given that the document should probably own its template group and delete it in its destructor).
src/tiled/templategroupdocument.cpp
Outdated
for (const TemplateGroupDocument *templateDocument : templateDocuments) { | ||
writer.writeStartElement(QLatin1String("templatedocument")); | ||
|
||
writer.writeAttribute(QLatin1String("path"), templateDocument->fileName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use a relative path here (can check the MapWriter
for examples regarding external tilesets and tileset images).
src/tiled/templatesdock.h
Outdated
TemplatesView(QWidget *parent = nullptr); | ||
|
||
void applyTemplateGroups(); | ||
ObjectTemplateModel *objectTemplateModel(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be const
.
d7cdc0d
to
37b0744
Compare
I've done a punch of improvements
I've also handled the tilesets so a template group will have no duplicates, this required storing a reference upon saving any template that had a new tileset. The references then were required to be deleted upon exit which initially violated some assertions. I had to change the destruction order in the main window as the preferences object which stored the documents was deleted after the tileset manager. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I think we're almost ready to merge this one. I've added some minor comments.
src/tiled/objecttemplatemodel.cpp
Outdated
while (it.hasNext()) { | ||
if (it.next()->fileName() == fileName) { | ||
int pos = mTemplateDocuments.indexOf(it.value()); | ||
delete it.value(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid potential invalid memory access, you should move this delete to after the beginRemoveRows
.
src/tiled/objecttemplatemodel.cpp
Outdated
QMutableListIterator<TemplateGroupDocument*> it(mTemplateDocuments); | ||
while (it.hasNext()) { | ||
if (it.next()->fileName() == fileName) { | ||
int pos = mTemplateDocuments.indexOf(it.value()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of iterating the list forwards and for each match, finding the index, you could instead iterate the list backwards like for (int i = mTemplateDocuments.size() - 1; i >= 0; --i) {
.
src/tiled/templategroupdocument.cpp
Outdated
} | ||
|
||
TemplateGroupDocument::~TemplateGroupDocument() | ||
{ | ||
TilesetManager *tilesetManager = TilesetManager::instance(); | ||
tilesetManager->removeReferences(mTemplateGroup->tilesets()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you add references in the TemplateGroup
, then please remove them there as well.
b64b0c7
to
899b9d8
Compare
Embedded tileset references are not managed and are currently disabled.
Update the elements to "templategroup" instead of "templatedocument"
The last two items in the list will be moved to other PRs. |
This pull request represents the second checkpoint of the Reusable Object Templates project, it's mainly concerned with creating the dock and managing the created templates.
These are the main items I will focus on doing: