]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetInfo.cpp
Fix bug #12772
[lyx.git] / src / insets / InsetInfo.cpp
index 2e42ad0e0ad239ab08f3687b84e2ef461233d83f..06851bb08059bdac277aedd00d500e0d92faaba0 100644 (file)
@@ -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<string> 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("//")))
@@ -168,7 +173,7 @@ set<string> getTexFileList(string const & filename)
        return list;
 }
 
-bool translateString(docstring const in, docstring & out, string const lcode)
+bool translateString(docstring const & in, docstring & out, string const & lcode)
 {
        out = translateIfPossible(in, lcode);
        return in != out;
@@ -176,7 +181,7 @@ bool translateString(docstring const in, docstring & out, string const lcode)
 } // 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)
@@ -201,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)
@@ -232,10 +237,8 @@ vector<pair<string,docstring>> 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)));
                }
@@ -297,7 +300,11 @@ vector<pair<string,docstring>> 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();
@@ -323,7 +330,11 @@ vector<pair<string,docstring>> 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();
@@ -454,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;
 }
 
@@ -624,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;
@@ -648,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();
@@ -675,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;
@@ -686,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);
@@ -743,13 +776,56 @@ 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<InsetInfo *>(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.
+       // 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.
@@ -758,8 +834,6 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) {
        if (buffer().isClone())
                return;
 
-       BufferParams const & bp = buffer().params();
-       params_.lang = it.paragraph().getFontSettings(bp, it.pos()).language();
        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;
@@ -804,8 +878,7 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) {
                string const lcode = params_.lang->code();
                docstring trans;
                bool is_translated = sequence != seq_untranslated;
-               for (size_t n = 0; n < sequence.size(); ++n) {
-                       char_type const c = sequence[n];
+               for (char_type const c : sequence) {
                        switch(c) {
                        case 0x21b5://Return
                                gui = _("Return[[Key]]");
@@ -933,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<int>(version.substr(0,4));
+                       int const m = convert<int>(version.substr(4,2));
+                       int const d = convert<int>(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 {
@@ -1037,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";
@@ -1066,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);
@@ -1088,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: {
@@ -1139,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
@@ -1156,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
@@ -1168,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<InsetInfo *>(this)->build();
+       InsetCollapsible::validate(features);
 }