Bo Peng wrote:
 If you're agreed, I can change the patch this way. The only task is to
 write the update() method, really---we could just take over the old
 createBibFiles, but that seems like overkill---and for me to undo some
 other bits, like registerEmbeddedFile(). OK?

 I knew we'd figure this out eventually.

I am still not convinced that, even after I can read and restore
params correctly, the need to separate params and EmbeddedFileList.
IMHO, having a single representation is easier to maintain.
I agree, but you don't have a single representation. Some parameters are represented one way, and some are represented another way. See line 110 below.

As far as
I can tell, params are changed only during inset creation, copying,
and modification, and they are already handled correctly now. (And params are updated after EmbeddedFileList changes.)
Could you please explain this? When does this happen, and why do the inset's *parameters* need to be updated as a result of external changes? I suspect it's not the parameters that need updating but rather information that the EmbeddedFile object needs. If so, then let's do that. Indeed, it seems to me that the inset's parameters ought NOT to be updated from outside like this, except possibly for the "embed" parameter that holds the inzipName. If so, then let's just do that.

The only problem
is the restoration of original user input for latex output purposes,
and my short patch fixes that easily.

If I understand you correctly, you would like to  update params in the
traditional way, and output EmbeddedFileList when necessary. However,
because  file movement needs to happen *during* inset creation,
copying and modification, you have to create an embedded file in those
events, enable them to move files around, and disable embedding if
file movement fails.
Why does it need to happen then? (I understand that this is a high-level design question.) This seems like something that needs to happen only when there are certain buffer-level events: Export, saving, etc. As long as it gets done before it needs doing, isn't that good enough? My idea was to do it when the EmbeddedFileList is accessed, "just in time". Surely it can't need doing before that list is read. Of course, as you say below, if the embedding fails for some reason, then we need to change the parameters. But that can be done.

If, in some case as you mentioned, some developer
change params without checking EmbeddedFile, lyx may crash due to
inconsistent embedded file. THAT IS TO SAY, you can NOT change params
independently, so what is the point of separating them?

If the problem is that bad, then the solution you're suggesting would require us to reimplement the whole parameter-setting mechanism, it seems to me. Otherwise, you are asking for problems down the road. If we have to go that way, we can, of course, but it seems very messy to me. And I don't see why the InsetCommand structure should change just to accommodate the EmbeddedFile feature.

In programming terms, you first need to determine if you want to use
enable(...., true) in your getEmbeddedFileList function. The answer is
obviously no (use enable(.... false)), because you do not want to
update an embedded file from external file each time it is used. Then,
if you use enable(...., false), you will have to make sure your params
are CORRECT, meaning that if a file is embedded, the embedded file
indeed exists.

OK, that would need sorting out. But let's come back to it if necessary. Part of why I'm puzzled is that I don't see where this is happening in the existing code. This is the old code:
87     void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd)
91             case LFUN_INSET_MODIFY: {
92                     InsetCommandParams p(BIBTEX_CODE);
93                     try {
94                             if (!InsetCommand::string2params("bibtex",
95 to_utf8(cmd.argument()), p)) {
96                                     cur.noUpdate();
97                                     break;
98                             }
99                     } catch (ExceptionMessage const & message) {
...
108                     createBibFiles(p["bibfiles"], p["embed"]);
109                     updateParam();
110                     setParam("options", p["options"]);
111                     buffer().updateBibfilesCache();
112                     break;
113             }
And here's createBibFiles:
749     void InsetBibtex::createBibFiles(docstring const & bibParam,
750             docstring const & embedParam) const
751     {
752             bibfiles_.clear();
...
763             bibfiles = split(bibfiles, tmp, ',');
764             embedStatus = split(embedStatus, emb, ',');
765 766 while (!tmp.empty()) { 767 EmbeddedFile file(changeExtension(tmp, "bib"), buffer().filePath()); 768 769 file.setInzipName(emb);
770                     file.setEmbed(!emb.empty());
771                     file.enable(buffer().embedded(), &buffer(), false);
772                     bibfiles_.push_back(file);
773                     // Get next file name
774                     bibfiles = split(bibfiles, tmp, ',');
775                     embedStatus = split(embedStatus, emb, ',');
776             }
777     }
This destroys the old EFList and creates a new one from scratch every time the inset is modified. Now if I use the ICP representation of the parameters, why can't I just do this instead:
108                     setParams(p);
109                     createBibFiles();
110                     // changing the signature to use our params
Surely this is equivalent to your code, right? But then, to ask the question from before again, why do I have to call createBibFiles() then? Why not wait until we access the bibfiles_ data to do it?

And as far as the true/false issue goes, why don't I have that problem at line 771? Answer: Because you do the true call in GuiBibtex. But that's insufficient, because this doesn't have to be called from there. LFUNs can be called in lots of ways, including from the mini-buffer. So you really need true here. Or else, what seems a better solution, don't destroy bibfiles_ and recreate it. Just make the new ones and do the true call for those. But I can do that as well, right?

Richard

Reply via email to