]> git.lyx.org Git - lyx.git/commitdiff
More GuiInfo usability work
authorJuergen Spitzmueller <spitz@lyx.org>
Wed, 1 Aug 2018 07:28:03 +0000 (09:28 +0200)
committerJuergen Spitzmueller <spitz@lyx.org>
Wed, 1 Aug 2018 07:28:03 +0000 (09:28 +0200)
src/LyXRC.cpp
src/LyXRC.h
src/frontends/qt4/GuiInfo.cpp
src/frontends/qt4/GuiInfo.h
src/frontends/qt4/ui/InfoUi.ui
src/insets/InsetInfo.cpp
src/insets/InsetInfo.h

index 8a1910e260448b80dcf574125dfd893f36cefd6e..5e8d38c79893e250f4a00c3ace23409edb6d17eb 100644 (file)
@@ -3049,6 +3049,15 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
 }
 
 
+set<string> LyXRC::getRCs()
+{
+       set<string> res;
+       for (int i = 0; i != lyxrcCount; ++i)
+               res.insert(ltrim(lyxrcTags[i].tag, "\\"));
+       return res;
+}
+
+
 #if 0
 string const LyXRC::getDescription(LyXRCTags tag)
 {
index c56c5818e436685e96d562e84da44d41d1f0415f..b499c7aebfaa5fba7ee9e77bdb3304a1c4f62cef 100644 (file)
@@ -217,6 +217,8 @@ public:
                   std::string const & tag = std::string()) const;
        ///
        void print() const;
+       ///
+       std::set<std::string> getRCs();
        // FIXME unused (was used for xforms. Do we still need this?)
        //static docstring const getDescription(LyXRCTags);
        ///
index cafcca8634f7a69b54a04c65d784cb96af68bfa0..84bd4f201139687eb13c7f60c94d25258c5594bb 100644 (file)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Abdelrazak Younes
+ * \author Jürgen Spitzmüller
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -50,8 +51,8 @@ char const * info_types_gui[] =
 
 char const * info_name_gui[] =
 { N_("Not Applicable"), N_("LyX Function"), N_("LyX Function"), N_("Preferences Key"),  N_("Package Name"),
-  N_("Class Name"), N_("LyX Function"), N_("LyX Function"), N_("Information"),
-  N_("Information"), N_("Information"), ""};
+  N_("Class Name"), N_("LyX Function"), N_("LyX Function"), N_("Not Applicable"), N_("Not Applicable"),
+  N_("Not Applicable"), ""};
 
 char const * info_tooltip[] =
 { N_("Please select a valid type above"),
@@ -59,7 +60,7 @@ char const * info_tooltip[] =
      "The output is the most recently assigned keyboard shortcut for this function"),
   N_("Enter a function name such as 'math-insert \\alpha'. Please refer to Help > LyX Functions for a comprehensive list of functions. "
      "The output lists all possible keyboard shortcuts for this function"),
-  N_("Enter a LyX preferences key such as 'bind_file'. Please refer to src/LyXRC.h for available entries. "
+  N_("Enter a LyX preferences key such as 'bind_file'. See the proposed list for available entries. "
      "The output is the current setting of this preference."),
   N_("Enter a LaTeX package name such as 'hyperref' (extension is optional). "
      "The output will be 'Yes' (package available) or 'No' (package unavailable)."),
@@ -69,9 +70,9 @@ char const * info_tooltip[] =
      "The output is the path to the function in the menu (using the current localization)."),
   N_("Enter a function name such as 'math-insert \\alpha'. Please refer to Help > LyX Functions for a comprehensive list of functions. "
      "The output is the toolbar icon for this function (using the active icon theme)."),
-  N_("Enter either 'name' (outputs the filename of the current document), 'path' (outputs the file path), or 'class' (outputs the text class)."),
-  N_("Enter either 'revision', 'tree-revision', 'author', 'time' or 'date'. If available, the respective version control information is output."),
-  N_("Currently supported information type: 'version' (outputs the current LyX version)."),
+  N_("Please select a valid type above"),
+  N_("Please select a valid type above"),
+  N_("Please select a valid type above"),
   ""};
 
 
@@ -84,24 +85,41 @@ GuiInfo::GuiInfo(QWidget * parent) : InsetParamsWidget(parent)
                typeCO->addItem(qt_(info_types_gui[n]), info_types[n]);
        typeCO->blockSignals(false);
 
-       connect(typeCO, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
+       connect(typeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(updateArguments(int)));
        connect(nameLE, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
+       connect(infoLW, SIGNAL(currentTextChanged(QString)), this, SIGNAL(changed()));
 }
 
 
 void GuiInfo::paramsToDialog(Inset const * inset)
 {
        InsetInfo const * ii = static_cast<InsetInfo const *>(inset);
+       inset_ = const_cast<Inset*>(inset);
        QString const type = toqstr(ii->infoType());
        QString const name = toqstr(ii->infoName());
        typeCO->blockSignals(true);
        nameLE->blockSignals(true);
+       nameLE->clear();
        int const i = typeCO->findData(type);
        typeCO->setCurrentIndex(i);
-       // Without this test, 'math-insert' (name) will replace 'math-insert '
-       // in nameLE and effectively disallow the input of spaces after a LFUN.
-       if (nameLE->text().trimmed() != name)
-               nameLE->setText(name);
+       updateArguments(i);
+       int argindex = -1;
+       int customindex = 0;
+       for (int i = 0 ; i < infoLW->count() ; ++i) {
+               if (infoLW->item(i)->data(Qt::UserRole).toString() == name)
+                       argindex = i;
+               else if (infoLW->item(i)->data(Qt::UserRole).toString() == "custom")
+                       customindex = i;
+       }
+       if (argindex != -1)
+               infoLW->setCurrentRow(argindex);
+       else {
+               // Without this test, 'math-insert' (name) will replace 'math-insert '
+               // in nameLE and effectively disallow the input of spaces after a LFUN.
+               if (nameLE->text().trimmed() != name)
+                       nameLE->setText(name);
+               infoLW->setCurrentRow(customindex);
+       }
        typeCO->blockSignals(false);
        nameLE->blockSignals(false);
 }
@@ -111,28 +129,60 @@ docstring GuiInfo::dialogToParams() const
 {
        QString type =
                typeCO->itemData(typeCO->currentIndex()).toString();
-       QString const name = nameLE->text();
+       QString name = infoLW->currentItem() ?
+                               infoLW->currentItem()->data(Qt::UserRole).toString()
+                             : QString();
+       if (name == "custom")
+               name = nameLE->text();
        return qstring_to_ucs4(type + ' ' + name);
 }
 
 
+void GuiInfo::updateArguments(int i)
+{
+       infoLW->clear();
+       if (inset_) {
+               InsetInfo const * ii = static_cast<InsetInfo const *>(inset_);
+               vector<pair<string,docstring>> args = ii->getArguments(info_types[i]);
+               for (auto const & p : args) {
+                       QListWidgetItem * li = new QListWidgetItem(toqstr(p.second));
+                       li->setData(Qt::UserRole, toqstr(p.first));
+                       if (p.first == "invalid")
+                               // non-selectable, disabled item!
+                               li->setFlags(Qt::NoItemFlags);
+                       if (p.first == "custom")
+                               li->setData(Qt::ToolTipRole, qt_("Enter a valid value below"));
+                       infoLW->addItem(li);
+               }
+       }
+       if (infoLW->count() > 0)
+               infoLW->setCurrentRow(0);
+       changed();
+}
+
+
 bool GuiInfo::checkWidgets(bool readonly) const
 {
        nameLE->setReadOnly(readonly);
        typeCO->setEnabled(!readonly);
        nameLA->setText(qt_(info_name_gui[typeCO->currentIndex()]) + toqstr(":"));
-       bool const type_enabled =
-               typeCO->itemData(typeCO->currentIndex()).toString() != "unknown";
+
+       QString const arg = infoLW->currentItem() ?
+                               infoLW->currentItem()->data(Qt::UserRole).toString()
+                             : QString();
+
+       bool const type_enabled = (arg == "custom");
        nameLA->setEnabled(type_enabled);
        nameLE->setEnabled(type_enabled);
        nameLE->setToolTip(qt_(info_tooltip[typeCO->currentIndex()]));
 
        if (!InsetParamsWidget::checkWidgets())
                return false;
-       return !nameLE->text().isEmpty();
+       return !arg.isEmpty() && (arg != "custom" || !nameLE->text().isEmpty());
 }
 
 
+
 } // namespace frontend
 } // namespace lyx
 
index f0ebfc474cd64a07fa7c501b9f1e593a74001df6..3e4ce76c3e1809c78bac181599658e2c072ca390 100644 (file)
@@ -25,6 +25,9 @@ class GuiInfo : public InsetParamsWidget, public Ui::InfoUi
 {
        Q_OBJECT
 
+protected Q_SLOTS:
+       void updateArguments(int i);
+
 public:
        GuiInfo(QWidget * parent = 0);
 
@@ -38,6 +41,7 @@ private:
        docstring dialogToParams() const;
        bool checkWidgets(bool readonly) const;
        //@}
+       Inset * inset_;
 };
 
 } // namespace frontend
index 39cb57c8bfffb0af60c68e1499e0ea70a84fc5a2..d7e82d63fc22ffff47e77e7fb707e96c902ecd98 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>320</width>
-    <height>90</height>
+    <height>311</height>
    </rect>
   </property>
   <property name="windowTitle">
   <property name="sizeGripEnabled" stdset="0">
    <bool>true</bool>
   </property>
-  <layout class="QVBoxLayout">
-   <item>
-    <layout class="QGridLayout">
-     <item row="0" column="0">
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="1" column="0">
+    <widget class="QListWidget" name="infoLW"/>
+   </item>
+   <item row="0" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
       <widget class="QLabel" name="typeLA">
        <property name="text">
-        <string>Information Type:</string>
+        <string>Infor&amp;mation Type:</string>
+       </property>
+       <property name="buddy">
+        <cstring>typeCO</cstring>
        </property>
       </widget>
      </item>
-     <item row="0" column="1">
+     <item>
       <widget class="QComboBox" name="typeCO">
        <property name="toolTip">
         <string>Select the type of information to be output. Then specify the requested information below.</string>
        </property>
       </widget>
      </item>
-     <item row="1" column="0">
+    </layout>
+   </item>
+   <item row="2" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
       <widget class="QLabel" name="nameLA">
        <property name="text">
-        <string>Information Name:</string>
+        <string>&amp;Custom:</string>
+       </property>
+       <property name="buddy">
+        <cstring>nameLE</cstring>
        </property>
       </widget>
      </item>
-     <item row="1" column="1">
+     <item>
       <widget class="QLineEdit" name="nameLE"/>
      </item>
     </layout>
index 88dd347f1a89d50a5561b309dd60414839893c59..c0e18eaca59bd784583f3ac242149010b05da26c 100644 (file)
@@ -247,9 +247,8 @@ bool InsetInfo::validateModifyArgument(docstring const & arg) const
        }
 
        case LYXRC_INFO: {
-               ostringstream oss;
-               lyxrc.write(oss, true, name);
-               return !oss.str().empty();
+               set<string> rcs = lyxrc.getRCs();
+               return rcs.find(name) != rcs.end();
        }
 
        case PACKAGE_INFO:
@@ -273,6 +272,104 @@ bool InsetInfo::validateModifyArgument(docstring const & arg) const
 }
 
 
+namespace{
+set<string> getTexFileList(string const & filename)
+{
+       set<string> list;
+       FileName const file = libFileSearch(string(), filename);
+       if (file.empty())
+               return list;
+
+       // FIXME Unicode.
+       vector<docstring> doclist =
+               getVectorFromString(file.fileContents("UTF-8"), from_ascii("\n"));
+
+       // Normalise paths like /foo//bar ==> /foo/bar
+       for (auto doc : doclist) {
+               subst(doc, from_ascii("\r"), docstring());
+               while (contains(doc, from_ascii("//")))
+                       subst(doc, from_ascii("//"), from_ascii("/"));
+               if (!doc.empty())
+                       list.insert(removeExtension(onlyFileName(to_utf8(doc))));
+       }
+
+       // remove duplicates
+       return list;
+}
+} // namespace anon
+
+
+vector<pair<string,docstring>> InsetInfo::getArguments(string const & type) const
+{
+       vector<pair<string,docstring>> result;
+
+       switch (nameTranslator().find(type)) {
+       case UNKNOWN_INFO:
+               result.push_back(make_pair("invalid", _("Please select a valid type!")));
+               break;
+
+       case SHORTCUT_INFO:
+       case SHORTCUTS_INFO:
+       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;
+                       if (!lfun.empty())
+                               result.push_back(make_pair(lfun, from_ascii(lfun)));
+               }
+               break;
+       }
+
+       case LYXRC_INFO: {
+               result.push_back(make_pair("custom", _("Custom")));
+               set<string> rcs = lyxrc.getRCs();
+               for (auto const & rc : rcs)
+                       result.push_back(make_pair(rc, from_ascii(rc)));
+               break;
+       }
+
+       case PACKAGE_INFO:
+       case TEXTCLASS_INFO: {
+               result.push_back(make_pair("custom", _("Custom")));
+               string const filename = (type == "package") ? "styFiles.lst"
+                                                           : "clsFiles.lst";
+               set<string> flist = getTexFileList(filename);
+               for (auto const & f : flist)
+                       result.push_back(make_pair(f, from_utf8(f)));
+               break;
+       }
+
+       case BUFFER_INFO:
+               result.push_back(make_pair("name", _("File name")));
+               result.push_back(make_pair("path", _("File path")));
+               result.push_back(make_pair("class", _("Used text class")));
+               break;
+
+       case VCS_INFO: {
+               if (!buffer().lyxvc().inUse()) {
+                       result.push_back(make_pair("invalid", _("No version control!")));
+                       break;
+               }
+               result.push_back(make_pair("revision", _("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")));
+               result.push_back(make_pair("time", _("Time")));
+               break;
+       }
+
+       case LYX_INFO:
+               result.push_back(make_pair("version", _("LyX version")));
+               break;
+       }
+
+       return result;
+}
+
+
 bool InsetInfo::showInsetDialog(BufferView * bv) const
 {
        bv->showDialog("info");
@@ -595,8 +692,8 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) {
                // this information could change, in principle, so we will 
                // recalculate each time through
                if (!buffer().lyxvc().inUse()) {
-                       gui = _("No version control");
-                       info(from_ascii("No version control"), lang);
+                       gui = _("No version control!");
+                       info(from_ascii("No version control!"), lang);
                        break;
                }
                LyXVC::RevisionInfo itype = LyXVC::Unknown;
index 4a4bf89d4d711d04b68b8a4fdf38c3ca1d5fcbba..e1c42a7c91578573fe6694cb3d237e773049d0c1 100644 (file)
@@ -124,6 +124,8 @@ public:
        ///
        bool validateModifyArgument(docstring const & argument) const;
        ///
+       std::vector<std::pair<std::string,docstring>> getArguments(std::string const &) const;
+       ///
        bool showInsetDialog(BufferView * bv) const;
        ///
        bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;