+static FileName selectTemplateFile()
+{
+ FileDialog dlg(qt_("Select template file"));
+ dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
+ dlg.setButton1(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
+
+ FileDialog::Result result =
+ dlg.open(toqstr(lyxrc.template_path),
+ FileFilterList(_("LyX Documents (*.lyx)")));
+
+ if (result.first == FileDialog::Later)
+ return FileName();
+ if (result.second.isEmpty())
+ return FileName();
+ return FileName(fromqstr(result.second));
+}
+
+
+Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
+{
+ setBusy(true);
+
+ Buffer * newBuffer = checkAndLoadLyXFile(filename);
+
+ if (!newBuffer) {
+ message(_("Document not loaded."));
+ setBusy(false);
+ return 0;
+ }
+
+ setBuffer(newBuffer);
+
+ // scroll to the position when the file was last closed
+ if (lyxrc.use_lastfilepos) {
+ LastFilePosSection::FilePos filepos =
+ LyX::ref().session().lastFilePos().load(filename);
+ view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
+ }
+
+ if (tolastfiles)
+ LyX::ref().session().lastFiles().add(filename);
+
+ setBusy(false);
+ return newBuffer;
+}
+
+
+void GuiView::openDocument(string const & fname)
+{
+ string initpath = lyxrc.document_path;
+
+ if (buffer()) {
+ string const trypath = buffer()->filePath();
+ // If directory is writeable, use this as default.
+ if (FileName(trypath).isDirWritable())
+ initpath = trypath;
+ }
+
+ string filename;
+
+ if (fname.empty()) {
+ FileDialog dlg(qt_("Select document to open"), LFUN_FILE_OPEN);
+ dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
+ dlg.setButton2(qt_("Examples|#E#e"),
+ toqstr(addPath(package().system_support().absFilename(), "examples")));
+
+ FileDialog::Result result =
+ dlg.open(toqstr(initpath), FileFilterList(_("LyX Documents (*.lyx)")));
+
+ if (result.first == FileDialog::Later)
+ return;
+
+ filename = fromqstr(result.second);
+
+ // check selected filename
+ if (filename.empty()) {
+ message(_("Canceled."));
+ return;
+ }
+ } else
+ filename = fname;
+
+ // get absolute path of file and add ".lyx" to the filename if
+ // necessary.
+ FileName const fullname =
+ fileSearch(string(), filename, "lyx", support::may_not_exist);
+ if (!fullname.empty())
+ filename = fullname.absFilename();
+
+ // if the file doesn't exist, let the user create one
+ if (!fullname.exists()) {
+ // the user specifically chose this name. Believe him.
+ Buffer * const b = newFile(filename, string(), true);
+ if (b)
+ setBuffer(b);
+ return;
+ }
+
+ docstring const disp_fn = makeDisplayPath(filename);
+ message(bformat(_("Opening document %1$s..."), disp_fn));
+
+ docstring str2;
+ Buffer * buf = loadDocument(fullname);
+ if (buf) {
+ updateLabels(*buf);
+
+ setBuffer(buf);
+ buf->errors("Parse");
+ str2 = bformat(_("Document %1$s opened."), disp_fn);
+ } else {
+ str2 = bformat(_("Could not open document %1$s"), disp_fn);
+ }
+ message(str2);
+}
+
+// FIXME: clean that
+static bool import(GuiView * lv, FileName const & filename,
+ string const & format, ErrorList & errorList)
+{
+ FileName const lyxfile(support::changeExtension(filename.absFilename(), ".lyx"));
+
+ string loader_format;
+ vector<string> loaders = theConverters().loaders();
+ if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
+ for (vector<string>::const_iterator it = loaders.begin();
+ it != loaders.end(); ++it) {
+ if (!theConverters().isReachable(format, *it))
+ continue;
+
+ string const tofile =
+ support::changeExtension(filename.absFilename(),
+ formats.extension(*it));
+ if (!theConverters().convert(0, filename, FileName(tofile),
+ filename, format, *it, errorList))
+ return false;
+ loader_format = *it;
+ break;
+ }
+ if (loader_format.empty()) {
+ frontend::Alert::error(_("Couldn't import file"),
+ bformat(_("No information for importing the format %1$s."),
+ formats.prettyName(format)));
+ return false;
+ }
+ } else
+ loader_format = format;
+
+ if (loader_format == "lyx") {
+ Buffer * buf = lv->loadDocument(lyxfile);
+ if (!buf)
+ return false;
+ updateLabels(*buf);
+ lv->setBuffer(buf);
+ buf->errors("Parse");
+ } else {
+ Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
+ if (!b)
+ return false;
+ lv->setBuffer(b);
+ bool as_paragraphs = loader_format == "textparagraph";
+ string filename2 = (loader_format == format) ? filename.absFilename()
+ : support::changeExtension(filename.absFilename(),
+ formats.extension(loader_format));
+ lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
+ theLyXFunc().setLyXView(lv);
+ lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
+ }
+
+ return true;
+}
+
+
+void GuiView::importDocument(string const & argument)
+{
+ string format;
+ string filename = split(argument, format, ' ');
+
+ LYXERR(Debug::INFO, format << " file: " << filename);
+
+ // need user interaction
+ if (filename.empty()) {
+ string initpath = lyxrc.document_path;
+
+ Buffer const * buf = buffer();
+ if (buf) {
+ string const trypath = buf->filePath();
+ // If directory is writeable, use this as default.
+ if (FileName(trypath).isDirWritable())
+ initpath = trypath;
+ }
+
+ docstring const text = bformat(_("Select %1$s file to import"),
+ formats.prettyName(format));
+
+ FileDialog dlg(toqstr(text), LFUN_BUFFER_IMPORT);
+ dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
+ dlg.setButton2(qt_("Examples|#E#e"),
+ toqstr(addPath(package().system_support().absFilename(), "examples")));
+
+ docstring filter = formats.prettyName(format);
+ filter += " (*.";
+ // FIXME UNICODE
+ filter += from_utf8(formats.extension(format));
+ filter += ')';
+
+ FileDialog::Result result =
+ dlg.open(toqstr(initpath), FileFilterList(filter));
+
+ if (result.first == FileDialog::Later)
+ return;
+
+ filename = fromqstr(result.second);
+
+ // check selected filename
+ if (filename.empty())
+ message(_("Canceled."));
+ }
+
+ if (filename.empty())
+ return;
+
+ // get absolute path of file
+ FileName const fullname(makeAbsPath(filename));
+
+ FileName const lyxfile(support::changeExtension(fullname.absFilename(), ".lyx"));
+
+ // Check if the document already is open
+ Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
+ if (buf) {
+ setBuffer(buf);
+ if (!closeBuffer()) {
+ message(_("Canceled."));
+ return;
+ }
+ }
+
+ docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
+
+ // if the file exists already, and we didn't do
+ // -i lyx thefile.lyx, warn
+ if (lyxfile.exists() && fullname != lyxfile) {
+
+ docstring text = bformat(_("The document %1$s already exists.\n\n"
+ "Do you want to overwrite that document?"), displaypath);
+ int const ret = Alert::prompt(_("Overwrite document?"),
+ text, 0, 1, _("&Overwrite"), _("&Cancel"));
+
+ if (ret == 1) {
+ message(_("Canceled."));
+ return;
+ }
+ }
+
+ message(bformat(_("Importing %1$s..."), displaypath));
+ ErrorList errorList;
+ if (import(this, fullname, format, errorList))
+ message(_("imported."));
+ else
+ message(_("file not imported!"));
+
+ // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
+}
+
+
+void GuiView::newDocument(string const & filename, bool from_template)
+{
+ FileName initpath(lyxrc.document_path);
+ Buffer * buf = buffer();
+ if (buf) {
+ FileName const trypath(buf->filePath());
+ // If directory is writeable, use this as default.
+ if (trypath.isDirWritable())
+ initpath = trypath;
+ }
+
+ string templatefile = from_template ?
+ selectTemplateFile().absFilename() : string();
+ Buffer * b;
+ if (filename.empty())
+ b = newUnnamedFile(templatefile, initpath);
+ else
+ b = newFile(filename, templatefile, true);
+
+ if (b)
+ setBuffer(b);
+ // Ensure the cursor is correctly positionned on screen.
+ view()->showCursor();
+}
+
+
+void GuiView::insertLyXFile(docstring const & fname)
+{
+ BufferView * bv = view();
+ if (!bv)
+ return;
+
+ // FIXME UNICODE
+ FileName filename(to_utf8(fname));
+
+ if (!filename.empty()) {
+ bv->insertLyXFile(filename);
+ return;
+ }
+
+ // Launch a file browser
+ // FIXME UNICODE
+ string initpath = lyxrc.document_path;
+ string const trypath = bv->buffer().filePath();
+ // If directory is writeable, use this as default.
+ if (FileName(trypath).isDirWritable())
+ initpath = trypath;
+
+ // FIXME UNICODE
+ FileDialog dlg(qt_("Select LyX document to insert"), LFUN_FILE_INSERT);
+ dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
+ dlg.setButton2(qt_("Examples|#E#e"),
+ toqstr(addPath(package().system_support().absFilename(),
+ "examples")));
+
+ FileDialog::Result result =
+ dlg.open(toqstr(initpath),
+ FileFilterList(_("LyX Documents (*.lyx)")));
+
+ if (result.first == FileDialog::Later)
+ return;
+
+ // FIXME UNICODE
+ filename.set(fromqstr(result.second));
+
+ // check selected filename
+ if (filename.empty()) {
+ // emit message signal.
+ message(_("Canceled."));
+ return;
+ }
+
+ bv->insertLyXFile(filename);
+}
+
+
+void GuiView::insertPlaintextFile(docstring const & fname,
+ bool asParagraph)
+{
+ BufferView * bv = view();
+ if (!bv)
+ return;
+
+ // FIXME UNICODE
+ FileName filename(to_utf8(fname));
+
+ if (!filename.empty()) {
+ bv->insertPlaintextFile(filename, asParagraph);
+ return;
+ }
+
+ FileDialog dlg(qt_("Select file to insert"), (asParagraph ?
+ LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
+
+ FileDialog::Result result = dlg.open(toqstr(bv->buffer().filePath()),
+ FileFilterList());
+
+ if (result.first == FileDialog::Later)
+ return;
+
+ // FIXME UNICODE
+ filename.set(fromqstr(result.second));
+
+ // check selected filename
+ if (filename.empty()) {
+ // emit message signal.
+ message(_("Canceled."));
+ return;
+ }
+
+ bv->insertPlaintextFile(filename, asParagraph);
+}
+
+
+bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
+{
+ FileName fname = b.fileName();
+ FileName const oldname = fname;
+
+ if (!newname.empty()) {
+ // FIXME UNICODE
+ fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
+ } else {
+ // Switch to this Buffer.
+ setBuffer(&b);
+
+ /// No argument? Ask user through dialog.
+ // FIXME UNICODE
+ FileDialog dlg(qt_("Choose a filename to save document as"),
+ LFUN_BUFFER_WRITE_AS);
+ dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
+ dlg.setButton2(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
+
+ if (!isLyXFilename(fname.absFilename()))
+ fname.changeExtension(".lyx");
+
+ FileFilterList const filter(_("LyX Documents (*.lyx)"));
+
+ FileDialog::Result result =
+ dlg.save(toqstr(fname.onlyPath().absFilename()),
+ filter,
+ toqstr(fname.onlyFileName()));
+
+ if (result.first == FileDialog::Later)
+ return false;
+
+ fname.set(fromqstr(result.second));
+
+ if (fname.empty())
+ return false;
+
+ if (!isLyXFilename(fname.absFilename()))
+ fname.changeExtension(".lyx");
+ }
+
+ if (FileName(fname).exists()) {
+ docstring const file = makeDisplayPath(fname.absFilename(), 30);
+ docstring text = bformat(_("The document %1$s already "
+ "exists.\n\nDo you want to "
+ "overwrite that document?"),
+ file);
+ int const ret = Alert::prompt(_("Overwrite document?"),
+ text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
+ switch (ret) {
+ case 0: break;
+ case 1: return renameBuffer(b, docstring());
+ case 2: return false;
+ }
+ }
+
+ // Ok, change the name of the buffer
+ b.setFileName(fname.absFilename());
+ b.markDirty();
+ bool unnamed = b.isUnnamed();
+ b.setUnnamed(false);
+ b.saveCheckSum(fname);
+
+ if (!saveBuffer(b)) {
+ b.setFileName(oldname.absFilename());
+ b.setUnnamed(unnamed);
+ b.saveCheckSum(oldname);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool GuiView::saveBuffer(Buffer & b)
+{
+ if (b.isUnnamed())
+ return renameBuffer(b, docstring());
+
+ if (b.save()) {
+ LyX::ref().session().lastFiles().add(b.fileName());
+ return true;
+ }
+
+ // Switch to this Buffer.
+ setBuffer(&b);
+
+ // FIXME: we don't tell the user *WHY* the save failed !!
+ docstring const file = makeDisplayPath(b.absFileName(), 30);
+ docstring text = bformat(_("The document %1$s could not be saved.\n\n"
+ "Do you want to rename the document and "
+ "try again?"), file);
+ int const ret = Alert::prompt(_("Rename and save?"),
+ text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
+ switch (ret) {
+ case 0:
+ if (!renameBuffer(b, docstring()))
+ return false;
+ break;
+ case 1:
+ break;
+ case 2:
+ return false;
+ }
+
+ return saveBuffer(b);
+}
+
+
+bool GuiView::closeBuffer()
+{
+ Buffer * buf = buffer();
+ return buf && closeBuffer(*buf);
+}
+
+
+bool GuiView::closeBuffer(Buffer & buf)
+{
+ // goto bookmark to update bookmark pit.
+ //FIXME: we should update only the bookmarks related to this buffer!
+ for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
+ theLyXFunc().gotoBookmark(i+1, false, false);
+
+ if (buf.isClean() || buf.paragraphs().empty()) {
+ if (buf.masterBuffer() == &buf)
+ LyX::ref().session().lastOpened().add(buf.fileName());
+ theBufferList().release(&buf);
+ return true;
+ }
+ // Switch to this Buffer.
+ setBuffer(&buf);
+
+ docstring file;
+ // FIXME: Unicode?
+ if (buf.isUnnamed())
+ file = from_utf8(buf.fileName().onlyFileName());
+ else
+ file = buf.fileName().displayName(30);
+
+ // Bring this window to top before asking questions.
+ raise();
+ activateWindow();
+
+ docstring const text = bformat(_("The document %1$s has unsaved changes."
+ "\n\nDo you want to save the document or discard the changes?"), file);
+ int const ret = Alert::prompt(_("Save changed document?"),
+ text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
+
+ switch (ret) {
+ case 0:
+ if (!saveBuffer(buf))
+ return false;
+ break;
+ case 1:
+ // if we crash after this we could
+ // have no autosave file but I guess
+ // this is really improbable (Jug)
+ removeAutosaveFile(buf.absFileName());
+ break;
+ case 2:
+ return false;
+ }
+
+ // save file names to .lyx/session
+ // if master/slave are both open, do not save slave since it
+ // will be automatically loaded when the master is loaded
+ if (buf.masterBuffer() == &buf)
+ LyX::ref().session().lastOpened().add(buf.fileName());
+
+ theBufferList().release(&buf);
+ return true;
+}
+
+