From: Juergen Spitzmueller Date: Wed, 1 Aug 2018 07:28:03 +0000 (+0200) Subject: More GuiInfo usability work X-Git-Tag: lyx-2.4.0dev-acb2ca7b~3226 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=8d451794032b5eb0a4e4579a4d794511878ee783;p=lyx.git More GuiInfo usability work --- diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index 8a1910e260..5e8d38c798 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -3049,6 +3049,15 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new) } +set LyXRC::getRCs() +{ + set 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 c56c5818e4..b499c7aebf 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 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 cafcca8634..84bd4f2011 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(inset); + inset_ = const_cast(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(inset_); + vector> 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 f0ebfc474c..3e4ce76c3e 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 39cb57c8bf..d7e82d63fc 100644 --- a/src/frontends/qt4/ui/InfoUi.ui +++ b/src/frontends/qt4/ui/InfoUi.ui @@ -7,7 +7,7 @@ 0 0 320 - 90 + 311 @@ -16,31 +16,44 @@ true - - - - + + + + + + + - Information Type: + Infor&mation Type: + + + typeCO - + Select the type of information to be output. Then specify the requested information below. - + + + + + - Information Name: + &Custom: + + + nameLE - + diff --git a/src/insets/InsetInfo.cpp b/src/insets/InsetInfo.cpp index 88dd347f1a..c0e18eaca5 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 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 getTexFileList(string const & filename) +{ + set list; + FileName const file = libFileSearch(string(), filename); + if (file.empty()) + return list; + + // FIXME Unicode. + vector 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> InsetInfo::getArguments(string const & type) const +{ + vector> 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 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 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 4a4bf89d4d..e1c42a7c91 100644 --- a/src/insets/InsetInfo.h +++ b/src/insets/InsetInfo.h @@ -124,6 +124,8 @@ public: /// bool validateModifyArgument(docstring const & argument) const; /// + std::vector> getArguments(std::string const &) const; + /// bool showInsetDialog(BufferView * bv) const; /// bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;