commit 8d451794032b5eb0a4e4579a4d794511878ee783
Author: Juergen Spitzmueller <[email protected]>
Date: Wed Aug 1 09:28:03 2018 +0200
More GuiInfo usability work
---
src/LyXRC.cpp | 9 +++
src/LyXRC.h | 2 +
src/frontends/qt4/GuiInfo.cpp | 80 ++++++++++++++++++++++++------
src/frontends/qt4/GuiInfo.h | 4 ++
src/frontends/qt4/ui/InfoUi.ui | 33 +++++++++----
src/insets/InsetInfo.cpp | 107 ++++++++++++++++++++++++++++++++++++++--
src/insets/InsetInfo.h | 2 +
7 files changed, 207 insertions(+), 30 deletions(-)
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index 8a1910e..5e8d38c 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -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)
{
diff --git a/src/LyXRC.h b/src/LyXRC.h
index c56c581..b499c7a 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -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);
///
diff --git a/src/frontends/qt4/GuiInfo.cpp b/src/frontends/qt4/GuiInfo.cpp
index cafcca8..84bd4f2 100644
--- a/src/frontends/qt4/GuiInfo.cpp
+++ b/src/frontends/qt4/GuiInfo.cpp
@@ -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
diff --git a/src/frontends/qt4/GuiInfo.h b/src/frontends/qt4/GuiInfo.h
index f0ebfc4..3e4ce76 100644
--- a/src/frontends/qt4/GuiInfo.h
+++ b/src/frontends/qt4/GuiInfo.h
@@ -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
diff --git a/src/frontends/qt4/ui/InfoUi.ui b/src/frontends/qt4/ui/InfoUi.ui
index 39cb57c..d7e82d6 100644
--- a/src/frontends/qt4/ui/InfoUi.ui
+++ b/src/frontends/qt4/ui/InfoUi.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>320</width>
- <height>90</height>
+ <height>311</height>
</rect>
</property>
<property name="windowTitle">
@@ -16,31 +16,44 @@
<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&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>&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>
diff --git a/src/insets/InsetInfo.cpp b/src/insets/InsetInfo.cpp
index 88dd347..c0e18ea 100644
--- a/src/insets/InsetInfo.cpp
+++ b/src/insets/InsetInfo.cpp
@@ -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;
diff --git a/src/insets/InsetInfo.h b/src/insets/InsetInfo.h
index 4a4bf89..e1c42a7 100644
--- a/src/insets/InsetInfo.h
+++ b/src/insets/InsetInfo.h
@@ -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;