More GuiInfo usability work

This commit is contained in:
Juergen Spitzmueller 2018-08-01 09:28:03 +02:00
parent 7f3fd5a809
commit 8d45179403
7 changed files with 207 additions and 30 deletions

View 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 #if 0
string const LyXRC::getDescription(LyXRCTags tag) string const LyXRC::getDescription(LyXRCTags tag)
{ {

View File

@ -217,6 +217,8 @@ public:
std::string const & tag = std::string()) const; std::string const & tag = std::string()) const;
/// ///
void print() const; void print() const;
///
std::set<std::string> getRCs();
// FIXME unused (was used for xforms. Do we still need this?) // FIXME unused (was used for xforms. Do we still need this?)
//static docstring const getDescription(LyXRCTags); //static docstring const getDescription(LyXRCTags);
/// ///

View File

@ -4,6 +4,7 @@
* Licence details can be found in the file COPYING. * Licence details can be found in the file COPYING.
* *
* \author Abdelrazak Younes * \author Abdelrazak Younes
* \author Jürgen Spitzmüller
* *
* Full author contact details are available in file CREDITS. * Full author contact details are available in file CREDITS.
*/ */
@ -50,8 +51,8 @@ char const * info_types_gui[] =
char const * info_name_gui[] = char const * info_name_gui[] =
{ N_("Not Applicable"), N_("LyX Function"), N_("LyX Function"), N_("Preferences Key"), N_("Package Name"), { 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_("Class Name"), N_("LyX Function"), N_("LyX Function"), N_("Not Applicable"), N_("Not Applicable"),
N_("Information"), N_("Information"), ""}; N_("Not Applicable"), ""};
char const * info_tooltip[] = char const * info_tooltip[] =
{ N_("Please select a valid type above"), { 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"), "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. " 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"), "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."), "The output is the current setting of this preference."),
N_("Enter a LaTeX package name such as 'hyperref' (extension is optional). " N_("Enter a LaTeX package name such as 'hyperref' (extension is optional). "
"The output will be 'Yes' (package available) or 'No' (package unavailable)."), "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)."), "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. " 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)."), "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_("Please select a valid type above"),
N_("Enter either 'revision', 'tree-revision', 'author', 'time' or 'date'. If available, the respective version control information is output."), N_("Please select a valid type above"),
N_("Currently supported information type: 'version' (outputs the current LyX version)."), 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->addItem(qt_(info_types_gui[n]), info_types[n]);
typeCO->blockSignals(false); 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(nameLE, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
connect(infoLW, SIGNAL(currentTextChanged(QString)), this, SIGNAL(changed()));
} }
void GuiInfo::paramsToDialog(Inset const * inset) void GuiInfo::paramsToDialog(Inset const * inset)
{ {
InsetInfo const * ii = static_cast<InsetInfo const *>(inset); InsetInfo const * ii = static_cast<InsetInfo const *>(inset);
inset_ = const_cast<Inset*>(inset);
QString const type = toqstr(ii->infoType()); QString const type = toqstr(ii->infoType());
QString const name = toqstr(ii->infoName()); QString const name = toqstr(ii->infoName());
typeCO->blockSignals(true); typeCO->blockSignals(true);
nameLE->blockSignals(true); nameLE->blockSignals(true);
nameLE->clear();
int const i = typeCO->findData(type); int const i = typeCO->findData(type);
typeCO->setCurrentIndex(i); typeCO->setCurrentIndex(i);
// Without this test, 'math-insert' (name) will replace 'math-insert ' updateArguments(i);
// in nameLE and effectively disallow the input of spaces after a LFUN. int argindex = -1;
if (nameLE->text().trimmed() != name) int customindex = 0;
nameLE->setText(name); 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); typeCO->blockSignals(false);
nameLE->blockSignals(false); nameLE->blockSignals(false);
} }
@ -111,28 +129,60 @@ docstring GuiInfo::dialogToParams() const
{ {
QString type = QString type =
typeCO->itemData(typeCO->currentIndex()).toString(); 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); 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 bool GuiInfo::checkWidgets(bool readonly) const
{ {
nameLE->setReadOnly(readonly); nameLE->setReadOnly(readonly);
typeCO->setEnabled(!readonly); typeCO->setEnabled(!readonly);
nameLA->setText(qt_(info_name_gui[typeCO->currentIndex()]) + toqstr(":")); 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); nameLA->setEnabled(type_enabled);
nameLE->setEnabled(type_enabled); nameLE->setEnabled(type_enabled);
nameLE->setToolTip(qt_(info_tooltip[typeCO->currentIndex()])); nameLE->setToolTip(qt_(info_tooltip[typeCO->currentIndex()]));
if (!InsetParamsWidget::checkWidgets()) if (!InsetParamsWidget::checkWidgets())
return false; return false;
return !nameLE->text().isEmpty(); return !arg.isEmpty() && (arg != "custom" || !nameLE->text().isEmpty());
} }
} // namespace frontend } // namespace frontend
} // namespace lyx } // namespace lyx

View File

@ -25,6 +25,9 @@ class GuiInfo : public InsetParamsWidget, public Ui::InfoUi
{ {
Q_OBJECT Q_OBJECT
protected Q_SLOTS:
void updateArguments(int i);
public: public:
GuiInfo(QWidget * parent = 0); GuiInfo(QWidget * parent = 0);
@ -38,6 +41,7 @@ private:
docstring dialogToParams() const; docstring dialogToParams() const;
bool checkWidgets(bool readonly) const; bool checkWidgets(bool readonly) const;
//@} //@}
Inset * inset_;
}; };
} // namespace frontend } // namespace frontend

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>320</width> <width>320</width>
<height>90</height> <height>311</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -16,31 +16,44 @@
<property name="sizeGripEnabled" stdset="0"> <property name="sizeGripEnabled" stdset="0">
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QVBoxLayout"> <layout class="QGridLayout" name="gridLayout">
<item> <item row="1" column="0">
<layout class="QGridLayout"> <widget class="QListWidget" name="infoLW"/>
<item row="0" column="0"> </item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="typeLA"> <widget class="QLabel" name="typeLA">
<property name="text"> <property name="text">
<string>Information Type:</string> <string>Infor&amp;mation Type:</string>
</property>
<property name="buddy">
<cstring>typeCO</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item>
<widget class="QComboBox" name="typeCO"> <widget class="QComboBox" name="typeCO">
<property name="toolTip"> <property name="toolTip">
<string>Select the type of information to be output. Then specify the requested information below.</string> <string>Select the type of information to be output. Then specify the requested information below.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> </layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="nameLA"> <widget class="QLabel" name="nameLA">
<property name="text"> <property name="text">
<string>Information Name:</string> <string>&amp;Custom:</string>
</property>
<property name="buddy">
<cstring>nameLE</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item>
<widget class="QLineEdit" name="nameLE"/> <widget class="QLineEdit" name="nameLE"/>
</item> </item>
</layout> </layout>

View File

@ -247,9 +247,8 @@ bool InsetInfo::validateModifyArgument(docstring const & arg) const
} }
case LYXRC_INFO: { case LYXRC_INFO: {
ostringstream oss; set<string> rcs = lyxrc.getRCs();
lyxrc.write(oss, true, name); return rcs.find(name) != rcs.end();
return !oss.str().empty();
} }
case PACKAGE_INFO: 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 bool InsetInfo::showInsetDialog(BufferView * bv) const
{ {
bv->showDialog("info"); bv->showDialog("info");
@ -595,8 +692,8 @@ void InsetInfo::updateBuffer(ParIterator const & it, UpdateType utype) {
// this information could change, in principle, so we will // this information could change, in principle, so we will
// recalculate each time through // recalculate each time through
if (!buffer().lyxvc().inUse()) { if (!buffer().lyxvc().inUse()) {
gui = _("No version control"); gui = _("No version control!");
info(from_ascii("No version control"), lang); info(from_ascii("No version control!"), lang);
break; break;
} }
LyXVC::RevisionInfo itype = LyXVC::Unknown; LyXVC::RevisionInfo itype = LyXVC::Unknown;

View File

@ -124,6 +124,8 @@ public:
/// ///
bool validateModifyArgument(docstring const & argument) const; bool validateModifyArgument(docstring const & argument) const;
/// ///
std::vector<std::pair<std::string,docstring>> getArguments(std::string const &) const;
///
bool showInsetDialog(BufferView * bv) const; bool showInsetDialog(BufferView * bv) const;
/// ///
bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const; bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;