X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLyX.cpp;h=4e97f7ae64b92286ef5aa0a3152349942c1f2e32;hb=b28599f3f7ed37f6bf79aeb0938ce61e1ebab5f5;hp=b4c02168c8ed36f1d539d1030863eb6398245058;hpb=7ac700920f0de8165b834010e211517098afbe14;p=lyx.git diff --git a/src/LyX.cpp b/src/LyX.cpp index b4c02168c8..4e97f7ae64 100644 --- a/src/LyX.cpp +++ b/src/LyX.cpp @@ -22,6 +22,7 @@ #include "Buffer.h" #include "BufferList.h" #include "CmdDef.h" +#include "CiteEnginesList.h" #include "ColorSet.h" #include "ConverterCache.h" #include "Converter.h" @@ -51,6 +52,7 @@ #include "frontends/Application.h" #include "support/ConsoleApplication.h" +#include "support/convert.h" #include "support/lassert.h" #include "support/debug.h" #include "support/environment.h" @@ -61,18 +63,19 @@ #include "support/Messages.h" #include "support/os.h" #include "support/Package.h" - -#include "support/bind.h" -#include +#include "support/unique_ptr.h" #include -#include #include +#include +#include #include #include #include #include +#include // For QT_VERSION + using namespace std; using namespace lyx::support; @@ -93,6 +96,19 @@ namespace os = support::os; bool use_gui = true; +// Report on the terminal about spawned commands. The default is false +// and can be changed with the option -v (--verbose). + +bool verbose = false; + + +// Do not treat the "missing glyphs" warning of fontspec as an error message. +// The default is false and can be changed with the option +// --ignore-error-message missing_glyphs +// This is used in automated testing. +bool ignore_missing_glyphs = false; + + // We default to open documents in an already running instance, provided that // the lyxpipe has been setup. This can be overridden either on the command // line or through preference settings. @@ -108,6 +124,14 @@ RunMode run_mode = PREFERRED; OverwriteFiles force_overwrite = UNSPECIFIED; +// Scale the GUI by this factor. This works whether we have a HiDpi screen +// or not and scales everything, also fonts. Can only be changed by setting +// the QT_SCALE_FACTOR environment variable before launching LyX and only +// works properly with Qt 5.6 or higher. + +double qt_scale_factor = 1.0; + + namespace { // Filled with the command line arguments "foo" of "-sysdir foo" or @@ -126,7 +150,7 @@ void showFileError(string const & error) "Please check your installation."), from_utf8(error))); } -} // namespace anon +} // namespace /// The main application class private implementation. struct LyX::Impl { @@ -150,13 +174,13 @@ struct LyX::Impl { /// CmdDef toplevel_cmddef_; /// - boost::scoped_ptr lyx_server_; + unique_ptr lyx_server_; /// - boost::scoped_ptr lyx_socket_; + unique_ptr lyx_socket_; /// - boost::scoped_ptr application_; + unique_ptr application_; /// lyx session, containing lastfiles, lastfilepos, and lastopened - boost::scoped_ptr session_; + unique_ptr session_; /// Files to load at start. vector files_to_load_; @@ -166,10 +190,15 @@ struct LyX::Impl { /// The file converters. Converters converters_; - - // The system converters copy after reading lyxrc.defaults. + /// The system converters after reading lyxrc.defaults. Converters system_converters_; + /// Global format information + Formats formats_; + /// The system formats after reading lyxrc.defaults. + Formats system_formats_; + + /// Movers movers_; /// @@ -229,7 +258,6 @@ LyX::~LyX() { delete pimpl_; singleton_ = 0; - WordList::cleanupWordLists(); } @@ -291,6 +319,17 @@ int LyX::exec(int & argc, char * argv[]) // we need to parse for "-dbg" and "-help" easyParse(argc, argv); +#if QT_VERSION >= 0x050600 + // Check whether Qt will scale all GUI elements and accordingly + // set the scale factor so that to avoid blurred images and text + char const * const scale_factor = getenv("QT_SCALE_FACTOR"); + if (scale_factor) { + qt_scale_factor = convert(scale_factor); + if (qt_scale_factor < 1.0) + qt_scale_factor = 1.0; + } +#endif + try { init_package(os::utf8_argv(0), cl_system_support, cl_user_support); } catch (ExceptionMessage const & message) { @@ -355,7 +394,7 @@ int LyX::exec(int & argc, char * argv[]) FileName(package().temp_dir().absFileName() + "/lyxsocket"))); // Start the real execution loop. - if (!theServer().deferredLoadingToOtherInstance()) + if (!pimpl_->lyx_server_->deferredLoadingToOtherInstance()) exit_status = pimpl_->application_->exec(); else if (!pimpl_->files_to_load_.empty()) { vector::const_iterator it = pimpl_->files_to_load_.begin(); @@ -380,8 +419,12 @@ void LyX::prepareExit() // Write the index file of the converter cache ConverterCache::get().writeIndex(); - // close buffers first - pimpl_->buffer_list_.closeAll(); + // closing buffer may throw exceptions, but we ignore them since we + // are quitting. + try { + // close buffers first + pimpl_->buffer_list_.closeAll(); + } catch (ExceptionMessage const &) {} // register session changes and shutdown server and socket if (use_gui) { @@ -404,10 +447,8 @@ void LyX::prepareExit() LYXERR(Debug::INFO, "Deleting tmp dir " << package().temp_dir().absFileName()); if (!package().temp_dir().destroyDirectory()) { - docstring const msg = - bformat(_("Unable to remove the temporary directory %1$s"), - from_utf8(package().temp_dir().absFileName())); - Alert::warning(_("Unable to remove temporary directory"), msg); + LYXERR0(bformat(_("Unable to remove the temporary directory %1$s"), + from_utf8(package().temp_dir().absFileName()))); } } } @@ -474,21 +515,51 @@ int LyX::execWithoutGui(int & argc, char * argv[]) return exit_status; } - // this is correct, since return values are inverted. - exit_status = !loadFiles(); + // Used to keep track of which buffers were explicitly loaded by user request. + // This is necessary because master and child document buffers are loaded, even + // if they were not named on the command line. We do not want to dispatch to + // those. + vector command_line_buffers; - if (pimpl_->batch_commands.empty() || pimpl_->buffer_list_.empty()) { + // Load the files specified on the command line + vector::const_iterator it = pimpl_->files_to_load_.begin(); + vector::const_iterator end = pimpl_->files_to_load_.end(); + for (; it != end; ++it) { + // get absolute path of file and add ".lyx" to the filename if necessary + FileName fname = fileSearch(string(), os::internal_path(*it), "lyx", + may_not_exist); + + if (fname.empty()) + continue; + + Buffer * buf = pimpl_->buffer_list_.newBuffer(fname.absFileName()); + LYXERR(Debug::FILES, "Loading " << fname); + if (buf && buf->loadLyXFile() == Buffer::ReadSuccess) { + ErrorList const & el = buf->errorList("Parse"); + for(ErrorItem const & e : el) + printError(e); + command_line_buffers.push_back(buf); + } else { + if (buf) + pimpl_->buffer_list_.release(buf); + docstring const error_message = + bformat(_("LyX failed to load the following file: %1$s"), + from_utf8(fname.absFileName())); + lyxerr << to_utf8(error_message) << endl; + exit_status = 1; // failed + } + } + + if (exit_status || pimpl_->batch_commands.empty() || pimpl_->buffer_list_.empty()) { prepareExit(); return exit_status; } - BufferList::iterator begin = pimpl_->buffer_list_.begin(); - + // Iterate through the buffers that were specified on the command line bool final_success = false; - for (BufferList::iterator I = begin; I != pimpl_->buffer_list_.end(); ++I) { - Buffer * buf = *I; - if (buf != buf->masterBuffer()) - continue; + vector::iterator buf_it = command_line_buffers.begin(); + for (; buf_it != command_line_buffers.end(); ++buf_it) { + Buffer * buf = *buf_it; vector::const_iterator bcit = pimpl_->batch_commands.begin(); vector::const_iterator bcend = pimpl_->batch_commands.end(); DispatchResult dr; @@ -503,42 +574,6 @@ int LyX::execWithoutGui(int & argc, char * argv[]) } -bool LyX::loadFiles() -{ - LATTEST(!use_gui); - bool success = true; - vector::const_iterator it = pimpl_->files_to_load_.begin(); - vector::const_iterator end = pimpl_->files_to_load_.end(); - - for (; it != end; ++it) { - // get absolute path of file and add ".lyx" to - // the filename if necessary - FileName fname = fileSearch(string(), os::internal_path(*it), "lyx", - may_not_exist); - - if (fname.empty()) - continue; - - Buffer * buf = pimpl_->buffer_list_.newBuffer(fname.absFileName()); - if (buf->loadLyXFile() == Buffer::ReadSuccess) { - ErrorList const & el = buf->errorList("Parse"); - if (!el.empty()) - for_each(el.begin(), el.end(), - bind(&LyX::printError, this, _1)); - } - else { - pimpl_->buffer_list_.release(buf); - docstring const error_message = - bformat(_("LyX failed to load the following file: %1$s"), - from_utf8(fname.absFileName())); - lyxerr << to_utf8(error_message) << endl; - success = false; - } - } - return success; -} - - void execBatchCommands() { LAPPERR(singleton_); @@ -740,7 +775,7 @@ namespace { return std::string(line, nameLen); } } -} +} // namespace void cleanDuplicateEnvVars() { @@ -783,33 +818,35 @@ void cleanDuplicateEnvVars() static void initTemplatePath() { FileName const package_template_path = - FileName(addPath(package().system_support().absFileName(), "templates")); + FileName(addName(package().system_support().absFileName(), "templates")); if (lyxrc.template_path.empty()) { lyxrc.template_path = package_template_path.absFileName(); } #if defined (USE_MACOSX_PACKAGING) FileName const user_template_path = - FileName(addPath(package().user_support().absFileName(), "templates")); + FileName(addName(package().user_support().absFileName(), "templates")); if (package_template_path != FileName(lyxrc.template_path) && user_template_path != FileName(lyxrc.template_path)) { return; } - /// addPath cannot be used here. - /// The path with trailing slash doesn't work as symlink name. FileName const user_template_link = - FileName(user_template_path.absFileName() + "SystemTemplates"); - if (user_template_link.isSymLink()) { + FileName(addName(user_template_path.absFileName(),"SystemTemplates")); + if (user_template_link.isSymLink() && !equivalent(user_template_link, package_template_path)) { user_template_link.removeFile(); } if (!user_template_link.exists()) { if (!package_template_path.link(user_template_link)) { - LYXERR(Debug::INIT, "Cannot create symlink " + user_template_link.absFileName()); - lyxrc.template_path = package_template_path.absFileName(); + FileName const user_support = package().user_support(); + if (user_support.exists() && user_support.isDirectory()) { + LYXERR(Debug::INIT, "Cannot create symlink " + user_template_link.absFileName()); + lyxrc.template_path = package_template_path.absFileName(); + } return; } + LYXERR(Debug::INIT, "Symlink \"" << user_template_link.absFileName() << "\" created."); } lyxrc.template_path = user_template_path.absFileName(); #endif @@ -883,6 +920,8 @@ bool LyX::init() if (queryUserLyXDir(package().explicit_user_support())) { package().reconfigureUserLyXDir(""); + // Now the user directory is present on first start. + initTemplatePath(); } fileUnlock(fd, lock_file.c_str()); } @@ -908,13 +947,13 @@ bool LyX::init() return false; // Query the OS to know what formats are viewed natively - formats.setAutoOpen(); + theFormats().setAutoOpen(); // Read lyxrc.dist again to be able to override viewer auto-detection. readRcFile("lyxrc.dist"); system_lyxrc = lyxrc; - system_formats = formats; + theSystemFormats() = theFormats(); pimpl_->system_converters_ = pimpl_->converters_; pimpl_->system_movers_ = pimpl_->movers_; system_lcolor = lcolor; @@ -934,8 +973,10 @@ bool LyX::init() LYXERR(Debug::INIT, "Reading layouts..."); // Load the layouts LayoutFileList::get().read(); - //...and the modules + //... the modules theModuleList.read(); + //... and the cite engines + theCiteEnginesList.read(); // read keymap and ui files in batch mode as well // because InsetInfo needs to know these to produce @@ -1019,7 +1060,9 @@ bool LyX::queryUserLyXDir(bool explicit_userdir) return configFileNeedsUpdate("lyxrc.defaults") || configFileNeedsUpdate("lyxmodules.lst") || configFileNeedsUpdate("textclass.lst") - || configFileNeedsUpdate("packages.lst"); + || configFileNeedsUpdate("packages.lst") + || configFileNeedsUpdate("lyxciteengines.lst") + || configFileNeedsUpdate("xtemplates.lst"); } first_start = !explicit_userdir; @@ -1113,7 +1156,7 @@ bool LyX::readEncodingsFile(string const & enc_name, namespace { /// return the the number of arguments consumed -typedef boost::function cmd_helper; +typedef function cmd_helper; int parse_dbg(string const & arg, string const &, string &) { @@ -1148,7 +1191,8 @@ int parse_help(string const &, string const &, string &) " where fmt is the export format of choice. Look in\n" " Tools->Preferences->File Handling->File Formats->Short Name\n" " to see which parameter (which differs from the format name\n" - " in the File->Export menu) should be passed.\n" + " in the File->Export menu) should be passed. To export to\n" + " the document's default output format, use 'default'.\n" " Note that the order of -e and -x switches matters.\n" "\t-E [--export-to] fmt filename\n" " where fmt is the export format of choice (see --export),\n" @@ -1161,11 +1205,17 @@ int parse_help(string const &, string const &, string &) " specifying whether all files, main file only, or no files,\n" " respectively, are to be overwritten during a batch export.\n" " Anything else is equivalent to `all', but is not consumed.\n" + "\t--ignore-error-message which\n" + " allows you to ignore specific LaTeX error messages.\n" + " Do not use for final documents! Currently supported values:\n" + " * missing_glyphs: Fontspec `missing glyphs' error.\n" "\t-n [--no-remote]\n" " open documents in a new instance\n" "\t-r [--remote]\n" " open documents in an already running instance\n" " (a working lyxpipe is needed)\n" + "\t-v [--verbose]\n" + " report on terminal about spawned commands.\n" "\t-batch execute commands without launching GUI and exit.\n" "\t-version summarize version and build info\n" "Check the LyX man page for more details.")) << endl; @@ -1300,6 +1350,23 @@ int parse_remote(string const &, string const &, string &) } +int parse_verbose(string const &, string const &, string &) +{ + verbose = true; + return 0; +} + + +int parse_ignore_error_message(string const & arg1, string const &, string &) +{ + if (arg1 == "missing_glyphs") { + ignore_missing_glyphs = true; + return 1; + } + return 0; +} + + int parse_force(string const & arg, string const &, string &) { if (arg == "all") { @@ -1317,7 +1384,7 @@ int parse_force(string const & arg, string const &, string &) } -} // namespace anon +} // namespace void LyX::easyParse(int & argc, char * argv[]) @@ -1347,6 +1414,9 @@ void LyX::easyParse(int & argc, char * argv[]) cmdmap["--no-remote"] = parse_noremote; cmdmap["-r"] = parse_remote; cmdmap["--remote"] = parse_remote; + cmdmap["-v"] = parse_verbose; + cmdmap["--verbose"] = parse_verbose; + cmdmap["--ignore-error-message"] = parse_ignore_error_message; for (int i = 1; i < argc; ++i) { map::const_iterator it @@ -1419,7 +1489,7 @@ Server & theServer() // FIXME: this should not be use_gui dependent LWARNIF(use_gui); LAPPERR(singleton_); - return *singleton_->pimpl_->lyx_server_.get(); + return *singleton_->pimpl_->lyx_server_; } @@ -1428,7 +1498,7 @@ ServerSocket & theServerSocket() // FIXME: this should not be use_gui dependent LWARNIF(use_gui); LAPPERR(singleton_); - return *singleton_->pimpl_->lyx_socket_.get(); + return *singleton_->pimpl_->lyx_socket_; } @@ -1439,17 +1509,31 @@ KeyMap & theTopLevelKeymap() } +Formats & theFormats() +{ + LAPPERR(singleton_); + return singleton_->pimpl_->formats_; +} + + +Formats & theSystemFormats() +{ + LAPPERR(singleton_); + return singleton_->pimpl_->system_formats_; +} + + Converters & theConverters() { LAPPERR(singleton_); - return singleton_->pimpl_->converters_; + return singleton_->pimpl_->converters_; } Converters & theSystemConverters() { LAPPERR(singleton_); - return singleton_->pimpl_->system_converters_; + return singleton_->pimpl_->system_converters_; }