X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetInfo.cpp;h=06851bb08059bdac277aedd00d500e0d92faaba0;hb=4ed0312c51704780af1c452d3a82a84171b3725a;hp=d6c68ed6b2eaf3b93af4ea8d3260a3fc6a0fb952;hpb=523d284729312376609e8b239b16e434c156da2a;p=lyx.git diff --git a/src/insets/InsetInfo.cpp b/src/insets/InsetInfo.cpp index d6c68ed6b2..06851bb080 100644 --- a/src/insets/InsetInfo.cpp +++ b/src/insets/InsetInfo.cpp @@ -15,6 +15,8 @@ #include "Buffer.h" #include "BufferParams.h" #include "BufferView.h" +#include "Changes.h" +#include "Cursor.h" #include "CutAndPaste.h" #include "Font.h" #include "FuncRequest.h" @@ -25,7 +27,6 @@ #include "LaTeXFeatures.h" #include "Language.h" #include "LayoutFile.h" -#include "Length.h" #include "LyXAction.h" #include "LyXRC.h" #include "LyXVC.h" @@ -37,6 +38,7 @@ #include "frontends/Application.h" +#include "support/Changer.h" #include "support/convert.h" #include "support/debug.h" #include "support/docstream.h" @@ -45,6 +47,7 @@ #include "support/FileName.h" #include "support/filetools.h" #include "support/gettext.h" +#include "support/Length.h" #include "support/Messages.h" #include "support/lstrings.h" #include "support/qstring_helpers.h" @@ -156,6 +159,8 @@ set getTexFileList(string const & filename) getVectorFromString(file.fileContents("UTF-8"), from_ascii("\n")); // Normalise paths like /foo//bar ==> /foo/bar + // No "auto const &" because doc is modified later + // coverity[auto_causes_copy] for (auto doc : doclist) { doc = subst(doc, from_ascii("\r"), docstring()); while (contains(doc, from_ascii("//"))) @@ -167,10 +172,16 @@ set getTexFileList(string const & filename) // remove duplicates return list; } + +bool translateString(docstring const & in, docstring & out, string const & lcode) +{ + out = translateIfPossible(in, lcode); + return in != out; +} } // namespace anon -docstring InsetInfoParams::getDate(string const iname, QDate const date) const +docstring InsetInfoParams::getDate(string const & iname, QDate const date) const { QLocale loc; if (lang) @@ -195,7 +206,7 @@ docstring InsetInfoParams::getDate(string const iname, QDate const date) const } -docstring InsetInfoParams::getTime(string const iname, QTime const time) const +docstring InsetInfoParams::getTime(string const & iname, QTime const time) const { QLocale loc; if (lang) @@ -226,10 +237,8 @@ vector> InsetInfoParams::getArguments(Buffer const * buf, case MENU_INFO: case ICON_INFO: { result.push_back(make_pair("custom", _("Custom"))); - LyXAction::const_iterator fit = lyxaction.func_begin(); - LyXAction::const_iterator const fen = lyxaction.func_end(); - for (; fit != fen; ++fit) { - string const lfun = fit->first; + for (auto const & name_code : lyxaction) { + string const lfun = name_code.first; if (!lfun.empty()) result.push_back(make_pair(lfun, from_ascii(lfun))); } @@ -272,6 +281,7 @@ vector> InsetInfoParams::getArguments(Buffer const * buf, break; } result.push_back(make_pair("revision", _("Revision[[Version Control]]"))); + result.push_back(make_pair("revision-abbrev", _("Abbreviated revision[[Version Control]]"))); result.push_back(make_pair("tree-revision", _("Tree revision"))); result.push_back(make_pair("author", _("Author"))); result.push_back(make_pair("date", _("Date"))); @@ -290,7 +300,11 @@ vector> InsetInfoParams::getArguments(Buffer const * buf, string const dt = split(name, '@'); QDate date; if (itype == "moddate") +#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) + date = QDateTime::fromSecsSinceEpoch(buf->fileName().lastModified()).date(); +#else date = QDateTime::fromTime_t(buf->fileName().lastModified()).date(); +#endif else if (itype == "fixdate" && !dt.empty()) { QDate const gdate = QDate::fromString(toqstr(dt), Qt::ISODate); date = (gdate.isValid()) ? gdate : QDate::currentDate(); @@ -316,7 +330,11 @@ vector> InsetInfoParams::getArguments(Buffer const * buf, string const tt = split(name, '@'); QTime time; if (itype == "modtime") +#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) + time = QDateTime::fromSecsSinceEpoch(buf->fileName().lastModified()).time(); +#else time = QDateTime::fromTime_t(buf->fileName().lastModified()).time(); +#endif else if (itype == "fixtime" && !tt.empty()) { QTime const gtime = QTime::fromString(toqstr(tt), Qt::ISODate); time = (gtime.isValid()) ? gtime : QTime::currentTime(); @@ -379,7 +397,7 @@ bool InsetInfoParams::validateArgument(Buffer const * buf, docstring const & arg || name == "path" || name == "class"); case VCS_INFO: - if (name == "revision" || name == "tree-revision" + if (name == "revision" || name == "revision-abbrev" || name == "tree-revision" || name == "author" || name == "date" || name == "time") return buf->lyxvc().inUse(); return false; @@ -447,13 +465,29 @@ string InsetInfoParams::infoType() const ///////////////////////////////////////////////////////////////////////// +namespace { + +class InsetGraphicsTight : public InsetGraphics +{ +public: + /// + explicit InsetGraphicsTight(Buffer * buf) : InsetGraphics(buf) {} + + /// + int leftOffset(BufferView const *) const override { return 0; } + /// + int rightOffset(BufferView const *) const override { return 0; } +}; -InsetInfo::InsetInfo(Buffer * buf, string const & name) +} + + +InsetInfo::InsetInfo(Buffer * buf, string const & info) : InsetCollapsible(buf), initialized_(false) { params_.type = InsetInfoParams::UNKNOWN_INFO; params_.force_ltr = false; - setInfo(name); + setInfo(info); status_ = Collapsed; } @@ -523,6 +557,8 @@ docstring InsetInfo::toolTip(BufferView const &, int, int) const case InsetInfoParams::VCS_INFO: if (params_.name == "revision") result = _("Version control revision"); + else if (params_.name == "revision-abbrev") + result = _("Version control abbreviated revision"); else if (params_.name == "tree-revision") result = _("Version control tree revision"); else if (params_.name == "author") @@ -615,6 +651,8 @@ bool InsetInfo::getStatus(Cursor & cur, FuncRequest const & cmd, return true; case LFUN_INSET_MODIFY: + if (nameTranslator().find(cmd.getArg(0)) == InsetInfoParams::UNKNOWN_INFO) + return Inset::getStatus(cur, cmd, flag); if (params_.validateArgument(&buffer(), cmd.argument())) { flag.setEnabled(true); string typestr; @@ -639,6 +677,10 @@ void InsetInfo::doDispatch(Cursor & cur, FuncRequest & cmd) { switch (cmd.action()) { case LFUN_INSET_MODIFY: + if (nameTranslator().find(cmd.getArg(0)) == InsetInfoParams::UNKNOWN_INFO) { + cur.undispatched(); + break; + } cur.recordUndo(); setInfo(to_utf8(cmd.argument())); cur.forceBufferUpdate(); @@ -666,9 +708,9 @@ void InsetInfo::doDispatch(Cursor & cur, FuncRequest & cmd) } -void InsetInfo::setInfo(string const & name) +void InsetInfo::setInfo(string const & info) { - if (name.empty()) + if (info.empty()) return; string saved_date_specifier; @@ -677,7 +719,7 @@ void InsetInfo::setInfo(string const & name) saved_date_specifier = split(params_.name, '@'); // info_type name string type; - params_.name = trim(split(name, type, ' ')); + params_.name = trim(split(info, type, ' ')); params_.type = nameTranslator().find(type); if (params_.name.empty()) params_.name = defaultValueTranslator().find(params_.type); @@ -710,15 +752,21 @@ void InsetInfo::setInfo(string const & name) void InsetInfo::error(docstring const & err, Language const * lang) { - setText(bformat(translateIfPossible(err, lang->code()), from_utf8(params_.name)), - Font(inherit_font, lang), false); + docstring const res = translateIfPossible(err, lang->code()); + bool const translated = res != err; + // If the string is not translated, we use default lang (English) + Font const f = translated ? Font(inherit_font, lang) : Font(inherit_font); + setText(bformat(res, from_utf8(params_.name)), f, false); } void InsetInfo::info(docstring const & err, Language const * lang) { - setText(translateIfPossible(err, lang->code()), - Font(inherit_font, lang), false); + docstring const res = translateIfPossible(err, lang->code()); + bool const translated = res != err; + // If the string is not translated, we use default lang (English) + Font const f = translated ? Font(inherit_font, lang) : Font(inherit_font); + setText(translateIfPossible(err, lang->code()), f, false); } @@ -728,23 +776,64 @@ void InsetInfo::setText(docstring const & str, Language const * lang) } -bool InsetInfo::forceLTR() const +bool InsetInfo::forceLTR(OutputParams const &) const { return params_.force_ltr; } -void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { +bool InsetInfo::forceLocalFontSwitch() const +{ + return params_.type == InsetInfoParams::MENU_INFO + || params_.type == InsetInfoParams::SHORTCUTS_INFO + || params_.type == InsetInfoParams::SHORTCUT_INFO + || params_.type == InsetInfoParams::L7N_INFO; +} + + +void InsetInfo::metrics(MetricsInfo & mi, Dimension & dim) const +{ + const_cast(this)->build(); + InsetCollapsible::metrics(mi, dim); +} + + +void InsetInfo::draw(PainterInfo & pi, int x, int y) const +{ + Changer chg = changeVar(lyxrc.mark_foreign_language, false); + InsetCollapsible::draw(pi, x, y); +} + +void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype, bool const deleted) + +{ // If the Buffer is a clone, then we neither need nor want to do any // of what follows. We want, rather, just to inherit how things were // in the original Buffer. This is especially important for VCS. // Otherwise, we could in principle have different settings here // than in the Buffer we were exporting. - if (buffer().isClone()) + // However, we need to check whether the inset is in an intitle + // context. + if (buffer().isClone()) { + InsetText::checkIntitleContext(it); return; - + } BufferParams const & bp = buffer().params(); params_.lang = it.paragraph().getFontSettings(bp, it.pos()).language(); + InsetCollapsible::updateBuffer(it, utype, deleted); +} + + +void InsetInfo::build() +{ + // If the Buffer is a clone, then we neither need nor want to do any + // of what follows. We want, rather, just to inherit how things were + // in the original Buffer. This is especially important for VCS. + // Otherwise, we could in principle have different settings here + // than in the Buffer we were exporting. + if (buffer().isClone()) + return; + Language const * tryguilang = languages.getFromCode(Messages::guiLanguage()); // Some info insets use the language of the GUI (if available) Language const * guilang = tryguilang ? tryguilang : params_.lang; @@ -774,84 +863,104 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { break; } docstring sequence; - if (params_.type == InsetInfoParams::SHORTCUT_INFO) + docstring seq_untranslated; + if (params_.type == InsetInfoParams::SHORTCUT_INFO) { sequence = bindings.begin()->print(KeySequence::ForGui); - else + seq_untranslated = bindings.begin()->print(KeySequence::ForGui, true); + } else { sequence = theTopLevelKeymap().printBindings(func, KeySequence::ForGui); + seq_untranslated = theTopLevelKeymap().printBindings(func, KeySequence::ForGui, true); + } // QKeySequence returns special characters for keys on the mac // Since these are not included in many fonts, we // re-translate them to textual names (see #10641) odocstringstream ods; string const lcode = params_.lang->code(); - for (size_t n = 0; n < sequence.size(); ++n) { - char_type const c = sequence[n]; + docstring trans; + bool is_translated = sequence != seq_untranslated; + for (char_type const c : sequence) { switch(c) { case 0x21b5://Return gui = _("Return[[Key]]"); - ods << translateIfPossible(from_ascii("Return[[Key]]"), lcode); + is_translated = translateString(from_ascii("Return[[Key]]"), trans, lcode); + ods << trans; break; case 0x21b9://Tab both directions (Win) gui = _("Tab[[Key]]"); - ods << translateIfPossible(from_ascii("Tab[[Key]]"), lcode); + is_translated = translateString(from_ascii("Tab[[Key]]"), trans, lcode); + ods << trans; break; case 0x21de://Qt::Key_PageUp gui = _("PgUp"); - ods << translateIfPossible(from_ascii("PgUp"), lcode); + is_translated = translateString(from_ascii("PgUp"), trans, lcode); + ods << trans; break; case 0x21df://Qt::Key_PageDown gui = _("PgDown"); - ods << translateIfPossible(from_ascii("PgDown"), lcode); + is_translated = translateString(from_ascii("PgDown"), trans, lcode); + ods << trans; break; case 0x21e4://Qt::Key_Backtab gui = _("Backtab"); - ods << translateIfPossible(from_ascii("Backtab"), lcode); + is_translated = translateString(from_ascii("Backtab"), trans, lcode); + ods << trans; break; case 0x21e5://Qt::Key_Tab gui = _("Tab"); - ods << translateIfPossible(from_ascii("Tab"), lcode); + is_translated = translateString(from_ascii("Tab"), trans, lcode); + ods << trans; break; case 0x21e7://Shift gui = _("Shift"); - ods << translateIfPossible(from_ascii("Shift"), lcode); + is_translated = translateString(from_ascii("Shift"), trans, lcode); + ods << trans; break; case 0x21ea://Qt::Key_CapsLock gui = _("CapsLock"); - ods << translateIfPossible(from_ascii("CapsLock"), lcode); + is_translated = translateString(from_ascii("CapsLock"), trans, lcode); + ods << trans; break; case 0x2303://Control gui = _("Control[[Key]]"); - ods << translateIfPossible(from_ascii("Control[[Key]]"), lcode); + is_translated = translateString(from_ascii("Control[[Key]]"), trans, lcode); + ods << trans; break; case 0x2318://CMD gui = _("Command[[Key]]"); - ods << translateIfPossible(from_ascii("Command[[Key]]"), lcode); + is_translated = translateString(from_ascii("Command[[Key]]"), trans, lcode); + ods << trans; break; case 0x2324://Qt::Key_Enter gui = _("Return[[Key]]"); - ods << translateIfPossible(from_ascii("Return[[Key]]"), lcode); + is_translated = translateString(from_ascii("Return[[Key]]"), trans, lcode); + ods << trans; break; case 0x2325://Option key gui = _("Option[[Key]]"); - ods << translateIfPossible(from_ascii("Option[[Key]]"), lcode); + is_translated = translateString(from_ascii("Option[[Key]]"), trans, lcode); + ods << trans; break; case 0x2326://Qt::Key_Delete gui = _("Delete[[Key]]"); - ods << translateIfPossible(from_ascii("Delete[[Key]]"), lcode); + is_translated = translateString(from_ascii("Delete[[Key]]"), trans, lcode); + ods << trans; break; case 0x232b://Qt::Key_Backspace gui = _("Fn+Del"); - ods << translateIfPossible(from_ascii("Fn+Delete"), lcode); + is_translated = translateString(from_ascii("Fn+Del"), trans, lcode); + ods << trans; break; case 0x238b://Qt::Key_Escape gui = _("Esc"); - ods << translateIfPossible(from_ascii("Esc"), lcode); + is_translated = translateString(from_ascii("Esc"), trans, lcode); + ods << trans; break; default: ods.put(c); } } - setText(ods.str(), guilang); - params_.force_ltr = !guilang->rightToLeft() && !params_.lang->rightToLeft(); + setText(ods.str(), is_translated ? guilang : nullptr); + params_.force_ltr = !is_translated || (!guilang->rightToLeft() && !params_.lang->rightToLeft()); break; } case InsetInfoParams::LYXRC_INFO: { @@ -897,7 +1006,19 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { if (initialized_) break; // check in packages.lst - if (LaTeXFeatures::isAvailable(params_.name)) { + bool available; + // we also allow version check with version separated by blank + if (contains(params_.name, ' ')) { + string name; + string const version = split(params_.name, name, ' '); + int const y = convert(version.substr(0,4)); + int const m = convert(version.substr(4,2)); + int const d = convert(version.substr(6,2)); + available = LaTeXFeatures::isAvailableAtLeastFrom(name, y, m, d); + } else + available = LaTeXFeatures::isAvailable(params_.name); + + if (available) { gui = _("yes"); info(from_ascii("yes"), params_.lang); } else { @@ -1001,14 +1122,6 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { initialized_ = true; FuncRequest func = lyxaction.lookupFunc(params_.name); docstring icon_name = frontend::Application::iconName(func, true); - // FIXME: We should use the icon directly instead of - // going through FileName. The code below won't work - // if the icon is embedded in the executable through - // the Qt resource system. - // This is only a negligible performance problem: - // If the installed icon differs from the resource icon the - // installed one is preferred anyway, and all icons that are - // embedded in the resources are installed as well. FileName file(to_utf8(icon_name)); if (file.onlyFileNameWithoutExt() == "unknown") { string dir = "images"; @@ -1030,12 +1143,16 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { percent_scale = (100 * iconsize + imgsize / 2)/imgsize; } } - InsetGraphics * inset = new InsetGraphics(buffer_); + InsetGraphicsTight * inset = new InsetGraphicsTight(buffer_); InsetGraphicsParams igp; igp.filename = file; igp.lyxscale = percent_scale; igp.scale = string(); igp.width = Length(1, Length::EM); + if (contains(file.absoluteFilePath(), from_ascii("math")) + || contains(file.absoluteFilePath(), from_ascii("ert-insert")) + || suffixIs(file.onlyPath().absoluteFilePath(), from_ascii("ipa"))) + igp.darkModeSensitive = true; inset->setParams(igp); clear(); Font const f(inherit_font, params_.lang); @@ -1052,7 +1169,7 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { else if (params_.name == "path") setText(from_utf8(os::latex_path(buffer().filePath())), params_.lang); else if (params_.name == "class") - setText(from_utf8(bp.documentClass().name()), params_.lang); + setText(from_utf8(buffer().params().documentClass().name()), params_.lang); break; } case InsetInfoParams::VCS_INFO: { @@ -1066,6 +1183,8 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { LyXVC::RevisionInfo itype = LyXVC::Unknown; if (params_.name == "revision") itype = LyXVC::File; + else if (params_.name == "revision-abbrev") + itype = LyXVC::FileAbbrev; else if (params_.name == "tree-revision") itype = LyXVC::Tree; else if (params_.name == "author") @@ -1101,7 +1220,11 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { ? split(params_.name, date_format, '@') : string(); QDate date; if (params_.type == InsetInfoParams::MODDATE_INFO) +#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) + date = QDateTime::fromSecsSinceEpoch(buffer().fileName().lastModified()).date(); +#else date = QDateTime::fromTime_t(buffer().fileName().lastModified()).date(); +#endif else if (params_.type == InsetInfoParams::FIXDATE_INFO && !date_specifier.empty()) date = QDate::fromString(toqstr(date_specifier), Qt::ISODate); else @@ -1118,7 +1241,11 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { ? split(params_.name, time_format, '@') : string(); QTime time; if (params_.type == InsetInfoParams::MODTIME_INFO) +#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) + time = QDateTime::fromSecsSinceEpoch(buffer().fileName().lastModified()).time(); +#else time = QDateTime::fromTime_t(buffer().fileName().lastModified()).time(); +#endif else if (params_.type == InsetInfoParams::FIXTIME_INFO && !time_specifier.empty()) time = QTime::fromString(toqstr(time_specifier), Qt::ISODate); else @@ -1130,7 +1257,13 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) { // Just to do something with that string LYXERR(Debug::INFO, "info inset text: " << gui); - InsetCollapsible::updateBuffer(it, utype); +} + + +void InsetInfo::validate(LaTeXFeatures & features) const +{ + const_cast(this)->build(); + InsetCollapsible::validate(features); }