Repository navigation
Conversation
383a418 to
09fabfd
Compare
09fabfd to
731b85d
Compare
731b85d to
759eaff
Compare
trisyoungs
left a comment
There was a problem hiding this comment.
Looks good. I'm reminded of the proposed move towards project folders, but that is somewhere in the distance and we need the capability of this PR right now!
RobBuchananCompPhys
left a comment
There was a problem hiding this comment.
Approved with a couple of suggestions (one strictly code, the other more architectural)
| { | ||
| saveDialog.open() | ||
| } | ||
| else | ||
| { | ||
| dissolve.save() | ||
| } |
There was a problem hiding this comment.
| { | |
| saveDialog.open() | |
| } | |
| else | |
| { | |
| dissolve.save() | |
| } | |
| saveDialog.open() | |
| else | |
| dissolve.save() |
There was a problem hiding this comment.
@RobBuchananCompPhys I'm not going to apply this suggestion, despite it being a good suggestion. The reason is that we will eventually be running qmlformat to bring all the QML documents back in line (and get our QC tests passing again), so I think we should defer these types for formatting discussions until after we know what we will be working with.
| bool save(); | ||
| bool saveAs(QUrl filename); |
There was a problem hiding this comment.
Up until now, I've been solely using the Q_INVOKABLE macro to decorate functions which are intended to be called on an object from QML. It's my understanding that listing them under Q_SLOTS basically achieves the same thing, but I wonder if at some point we should commit to using one or the other exclusively (and refactor accordingly). The reason for that is that - at least for me- the Q_SLOT feels makes more sense as a function that only exists as a call back corresponding to a Q_SIGNAL. Making a decision to use slots in this way, rather than for exposing methods to QML could help us organise our header files more clearly, especially as one thing I've found challenging writing integrated QML and C++ is tripping up on runtime errors whose source is obscured by emissions of signals on the C++ side which can be slightly more challenging to debug. Would be great to get your thoughts on this.
There was a problem hiding this comment.
From my own incomplete research, the only practical difference that I can find between between Q_INVOKEABLE and Q_SLOTS is that constructors can be Q_INVOKEABLE, but can't be a slot. Beyond that, they seem to operate identically under the hood (e.g. a signal can be connected to an invokeable instead of a slot).
Since we do have two things that do the same thing, that leaves us with two questions:
- Should we use this extra, redundant bit of information to communicate information to the programmer, even if it's identical within the software itself?
- If we do unify under a single banner, which one would we choose?
I'll address the second issue first. Unifying under invokeable gives the advantage that we can also include constructors, though we have not done this to date. On the other hand, unifying under slots gives the advantage that slots can be declared together as a group (e.g. public slots:) while invokeable needs to be manually declared for each and every instance. Given the improvement to readability, I would lean toward going with slots in this situation.
However, that is assuming that we are choosing a single syntax. We could make the distinction that invokeable is for methods called from QML, while slots are for connecting to signals. This does provide intent to the coder, but it also raises a couple of issues. First, I find the line blurry on a QML level. For example, does the line
onTriggered: dissolveModel.save()represent the triggered signal being connected to the save slot on DissolveModel, or is it the save method being invoked within the onTriggered method? If it's a signal, does it remain a signal when we do any of
onTriggered: newfile != "" ? dissolveModel.saveAs(newFile) : dissolveModel.save()
onTriggered: {
console.log("Saved file")
dissoleModel.save()
}
onTriggered: {
if (newfile != "")
dissolveModel.saveAs(newfile)
else
dissolveModel.save()
}Also, if we have been invoking a function and we later find that we need to connect it to a signal, do we change it to a signal or does it remain invokeable? Do we write a copy of the function literally to maintain the distinction?
My personal feeling at the moment is that there is no useful distinction between the invokeable and the slot, so we should stick to declaring slots, as the syntax is nicer. However, I am happy to hear alternate viewpoints on this matter, as there may be much that I have not considered.
This adds support for saving and loading files from the GUI. It also clears up a couple of bugs in the TOML processing of
optional<Number>andFunction1DWrapperKnown issues outside the scope of this PR: