*
* \author Dekel Tsur
* \author Jürgen Spitzmüller
- * \author Richard Heck
+ * \author Richard Kimberly Heck
*
* Full author contact details are available in file CREDITS.
*/
#include "qt_helpers.h"
-#include "FileDialog.h"
+#include "Format.h"
#include "LengthCombo.h"
+#include "LyXRC.h"
#include "frontends/alert.h"
-#include "BufferParams.h"
-#include "FloatList.h"
-#include "FuncRequest.h"
-#include "Language.h"
-#include "LyX.h"
-#include "LyXRC.h"
-#include "LyXAction.h"
-#include "TextClass.h"
-
#include "support/convert.h"
#include "support/debug.h"
#include "support/gettext.h"
-#include "support/Length.h"
#include "support/lstrings.h"
-#include "support/lyxalgo.h"
-#include "support/os.h"
#include "support/Package.h"
#include "support/PathChanger.h"
#include "support/Systemcall.h"
#include <QComboBox>
#include <QDesktopServices>
#include <QDir>
+#include <QInputDialog>
#include <QLineEdit>
+#include <QMessageBox>
#include <QLocale>
#include <QPalette>
+#include <QPushButton>
#include <QSet>
+#include <QSettings>
#include <QTextLayout>
#include <QTextDocument>
#include <QToolTip>
// for FileFilter.
// FIXME: Remove
-#include "support/regex.h"
-
+#include <regex>
using namespace std;
using namespace lyx::support;
// Don't return unit-from-choice if the input(field) contains a unit
if (isValidGlueLength(fromqstr(length)))
return fromqstr(length);
+ // Also try with localized version
+ if (isValidGlueLength(fromqstr(unlocLengthString(length))))
+ return fromqstr(unlocLengthString(length));
Length::UNIT const unit = combo->currentLengthItem();
// don't return unit-from-choice if the input(field) contains a unit
if (isValidGlueLength(fromqstr(length)))
return Length(fromqstr(length));
+ // Also try with localized version
+ if (isValidGlueLength(fromqstr(unlocLengthString(length))))
+ return Length(fromqstr(unlocLengthString(length)));
Length::UNIT unit = Length::UNIT_NONE;
QString const item = combo->currentText();
} else if (!isValidLength(len) && !isStrDbl(len)) {
// use input field only for gluelengths
combo->setCurrentItem(defaultUnit);
- input->setText(toqstr(len));
+ input->setText(locLengthString(toqstr(len)));
} else {
lengthToWidgets(input, combo, Length(len), defaultUnit);
}
}
-void doubleToWidget(QLineEdit * input, double const & value, char f, int prec)
+void doubleToWidget(QLineEdit * input, double value, char f, int prec)
{
QLocale loc;
loc.setNumberOptions(QLocale::OmitGroupSeparator);
void setValid(QWidget * widget, bool valid)
{
if (valid) {
- widget->setPalette(QPalette());
+ if (qobject_cast<QCheckBox*>(widget) != nullptr)
+ // Check boxes need to be treated differenty, see
+ // https://forum.qt.io/topic/93253/
+ widget->setStyleSheet("");
+ else
+ widget->setPalette(QPalette());
} else {
- QPalette pal = widget->palette();
- pal.setColor(QPalette::Active, QPalette::Foreground, QColor(255, 0, 0));
- widget->setPalette(pal);
+ if (qobject_cast<QCheckBox*>(widget) != nullptr) {
+ // Check boxes need to be treated differenty, see
+ // https://forum.qt.io/topic/93253/
+ if (qobject_cast<QCheckBox*>(widget)->isChecked())
+ widget->setStyleSheet("QCheckBox:unchecked{ color: red; }QCheckBox:checked{ color: red; }");
+ } else {
+ QPalette pal = widget->palette();
+ pal.setColor(QPalette::Active, QPalette::WindowText, QColor(255, 0, 0));
+ pal.setColor(QPalette::Active, QPalette::Text, QColor(255, 0, 0));
+ widget->setPalette(pal);
+ }
}
}
QPalette pal = QApplication::palette();
QPalette newpal(pal.color(QPalette::Active, QPalette::HighlightedText),
pal.color(QPalette::Active, QPalette::Highlight));
+ newpal.setColor(QPalette::WindowText,
+ pal.color(QPalette::Active, QPalette::HighlightedText));
for (QWidget * w : highlighted)
w->setPalette(newpal);
for (QWidget * w : plain)
}
-/// wrapper to hide the change of method name to setSectionResizeMode
-void setSectionResizeMode(QHeaderView * view,
- int logicalIndex, QHeaderView::ResizeMode mode) {
-#if (QT_VERSION >= 0x050000)
- view->setSectionResizeMode(logicalIndex, mode);
-#else
- view->setResizeMode(logicalIndex, mode);
-#endif
-}
-
-void setSectionResizeMode(QHeaderView * view, QHeaderView::ResizeMode mode) {
-#if (QT_VERSION >= 0x050000)
- view->setSectionResizeMode(mode);
-#else
- view->setResizeMode(mode);
-#endif
-}
-
void showDirectory(FileName const & directory)
{
if (!directory.exists())
QUrl qurl(QUrl::fromLocalFile(QDir::toNativeSeparators(toqstr(directory.absFileName()))));
// Give hints in case of bugs
if (!qurl.isValid()) {
- LYXERR0("QUrl is invalid!");
+ frontend::Alert::error(_("Invalid URL"),
+ bformat(_("The URL `%1$s' could not be resolved."),
+ qstring_to_ucs4(qurl.toString())));
return;
}
if (!QDesktopServices::openUrl(qurl))
- LYXERR0("Unable to open QUrl even though dir exists!");
+ frontend::Alert::error(_("URL could not be accessed"),
+ bformat(_("The URL `%1$s' could not be opened although it exists!"),
+ qstring_to_ucs4(qurl.toString())));
}
-void showTarget(string const & target, string const & pdfv, string const & psv)
+void showTarget(string const & target_in, Buffer const & buf)
{
- LYXERR(Debug::INSETS, "Showtarget:" << target << "\n");
- if (prefixIs(target, "EXTERNAL ")) {
+ LYXERR(Debug::INSETS, "Showtarget: " << target_in << "\n");
+
+ string target = target_in;
+ string const & docpath = buf.absFileName();
+ vector<string> targets;
+
+ bool const is_external = prefixIs(target, "EXTERNAL ");
+ if (is_external) {
if (!lyxrc.citation_search)
return;
- string tmp, tar, opts;
+ string tmp, tar;
tar = split(target, tmp, ' ');
- if (!pdfv.empty())
- opts = " -v " + pdfv;
- if (!psv.empty())
- opts += " -w " + psv;
- if (!opts.empty())
- opts += " ";
- Systemcall one;
- string const command = lyxrc.citation_search_view + " " + opts + tar;
- int const result = one.startscript(Systemcall::Wait, command);
- if (result == 1)
+ string const scriptcmd = subst(lyxrc.citation_search_view, "$${python}", os::python());
+ string const command = scriptcmd + " " + tar;
+ cmd_ret const ret = runCommand(commandPrep(command));
+ if (!ret.valid) {
// Script failed
frontend::Alert::error(_("Could not open file"),
_("The lyxpaperview script failed."));
- else if (result == 2)
+ return;
+ }
+ // lyxpaperview returns a \n-separated list of paths
+ targets = getVectorFromString(rtrim(ret.result, "\n"), "\n");
+ if (targets.empty()) {
frontend::Alert::error(_("Could not open file"),
bformat(_("No file was found using the pattern `%1$s'."),
from_utf8(tar)));
- return;
+ return;
+ }
+ }
+ if (prefixIs(target, "file://")) {
+ // file might have a \n-separated list of paths
+ targets = getVectorFromString(target, "\n");
}
- if (!QDesktopServices::openUrl(QUrl(toqstr(target), QUrl::TolerantMode)))
+ if (!targets.empty()) {
+ if (targets.size() > 1) {
+ QStringList files;
+ for (auto const & t : targets)
+ files << toqstr(t);
+ bool ok;
+ QString file = QInputDialog::getItem(nullptr, qt_("Multiple files found!"),
+ qt_("Select the file that should be opened:"),
+ files, 0, false, &ok);
+ if (!ok || file.isEmpty())
+ return;
+ target = fromqstr(file);
+ } else
+ target = targets.front();
+ }
+ // security measure: ask user before opening if document is not marked trusted.
+ QSettings settings;
+ if (!settings.value("trusted documents/" + toqstr(docpath), false).toBool()) {
+ QCheckBox * dontShowAgainCB = new QCheckBox();
+ dontShowAgainCB->setText(qt_("&Trust this document and do not ask me again!"));
+ dontShowAgainCB->setToolTip(qt_("If you check this, LyX will open all targets without asking for the given document in the future."));
+ docstring const warn = bformat(_("LyX wants to open the following target in an external application:\n\n"
+ "%1$s\n\n"
+ "Be aware that this might entail security infringements!\n\n"
+ "Only do this if you trust the origin of the document and the target of the link!\n\n"
+ "How do you want to proceed?"), from_utf8(target));
+ QMessageBox box(QMessageBox::Warning, qt_("Open external target?"), toqstr(warn),
+ QMessageBox::NoButton, qApp->focusWidget());
+ QPushButton * openButton = box.addButton(qt_("&Open Target"), QMessageBox::ActionRole);
+ box.addButton(QMessageBox::Abort);
+ box.setCheckBox(dontShowAgainCB);
+ box.setDefaultButton(QMessageBox::Abort);
+ box.exec();
+ if (box.clickedButton() != openButton)
+ return;
+ if (dontShowAgainCB->isChecked())
+ settings.setValue("trusted documents/"
+ + toqstr(docpath), true);
+ }
+
+ bool success = false;
+ QUrl url = is_external
+ ? QUrl::fromLocalFile(toqstr(target))
+ : QUrl(toqstr(target), QUrl::TolerantMode);
+ if (url.isLocalFile()) {
+ // For local files, we use our own viewers
+ // (QDesktopServices employs xdg-open which
+ // does not yet work everywhere)
+ FileName fn(fromqstr(url.path()));
+ string const format = theFormats().getFormatFromFile(fn);
+ success = theFormats().view(buf, fn, format);
+ } else
+ // For external files, we rely on QDesktopServices
+ success = QDesktopServices::openUrl(url);
+
+ if (!success)
frontend::Alert::error(_("Could not open file"),
bformat(_("The target `%1$s' could not be resolved."),
from_utf8(target)));
set.insert(qfile);
}
- // remove duplicates
+ // remove duplicates
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
- return QList<QString>(set.begin(), set.end());
+ return QList<QString>(set.begin(), set.end());
#else
- return QList<QString>::fromSet(set);
+ return QList<QString>::fromSet(set);
#endif
}
{
// Matches " *.{abc,def,ghi}", storing "*." as group 1 and
// "abc,def,ghi" as group 2, while allowing spaces in group 2.
- static lyx::regex const glob_re(" *([^ {]*)\\{([^}]+)\\}");
+ static regex const glob_re(" *([^ {]*)\\{([^}]+)\\}");
// Matches "abc" and "abc,", storing "abc" as group 1,
// while ignoring surrounding spaces.
- static lyx::regex const block_re(" *([^ ,}]+) *,? *");
+ static regex const block_re(" *([^ ,}]+) *,? *");
string pattern;
std::vector<Filter> filters_;
};
-
FileFilterList::FileFilterList(docstring const & qt_style_filter)
{
// FIXME UNICODE
string const filter = to_utf8(qt_style_filter)
+ (qt_style_filter.empty() ? string() : ";;")
- + to_utf8(_("All Files "))
-#if defined(_WIN32)
- + ("(*.*)");
-#else
- + ("(*)");
-#endif
+ + to_utf8(_("All Files")) + " " + fromqstr(wildcardAllFiles());
// Split data such as "TeX documents (*.tex);;LyX Documents (*.lyx)"
// into individual filters.
- static lyx::regex const separator_re(";;");
+ static regex const separator_re(";;");
string::const_iterator it = filter.begin();
string::const_iterator const end = filter.end();
while (true) {
match_results<string::const_iterator> what;
- if (!lyx::regex_search(it, end, what, separator_re)) {
+ if (!regex_search(it, end, what, separator_re)) {
parse_filter(string(it, end));
break;
}
{
// Matches "TeX documents (plain) (*.tex)",
// storing "TeX documents (plain) " as group 1 and "*.tex" as group 2.
- static lyx::regex const filter_re("(.*)\\(([^()]+)\\) *$");
+ static regex const filter_re("(.*)\\(([^()]+)\\) *$");
match_results<string::const_iterator> what;
- if (!lyx::regex_search(filter, what, filter_re)) {
+ if (!regex_search(filter, what, filter_re)) {
// Just a glob, no description.
filters_.push_back(Filter(docstring(), trim(filter)));
} else {
}
+QString wildcardAllFiles()
+{
+#if defined(_WIN32)
+ return "(*.*)";
+#else
+ return "(*)";
+#endif
+}
+
+
/** \returns the equivalent of the string passed in
* although any brace expressions are expanded.
* (E.g. "*.{png,jpg}" -> "*.png *.jpg")
}
-QString formatToolTip(QString text, int em)
+QString formatToolTip(QString text, int width)
{
// 1. QTooltip activates word wrapping only if mightBeRichText()
// is true. So we convert the text to rich text.
text = Qt::convertFromPlainText(text, Qt::WhiteSpaceNormal);
// Compute desired width in pixels
QFont const font = QToolTip::font();
- int const px_width = em * QFontMetrics(font).width("M");
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
+ int const px_width = width * QFontMetrics(font).horizontalAdvance("M");
+#else
+ int const px_width = width * QFontMetrics(font).width("M");
+#endif
// Determine the ideal width of the tooltip
QTextDocument td("");
td.setHtml(text);
}
-QString qtHtmlToPlainText(QString const & html)
+QString qtHtmlToPlainText(QString const & text)
{
- if (!Qt::mightBeRichText(html))
- return html;
+ if (!Qt::mightBeRichText(text))
+ return text;
QTextDocument td;
- td.setHtml(html);
+ td.setHtml(text);
return td.toPlainText();
}