#include "GuiView.h"
+#include "DialogFactory.h"
#include "DispatchResult.h"
#include "FileDialog.h"
+#include "FindAndReplace.h"
#include "FontLoader.h"
#include "GuiApplication.h"
#include "GuiClickableLabel.h"
-#include "GuiCommandBuffer.h"
#include "GuiCompleter.h"
+#include "GuiFontMetrics.h"
#include "GuiKeySymbol.h"
#include "GuiToc.h"
#include "GuiToolbar.h"
#include "Format.h"
#include "FuncStatus.h"
#include "FuncRequest.h"
-#include "Intl.h"
+#include "KeySymbol.h"
#include "Language.h"
-#include "Layout.h"
#include "LayoutFile.h"
#include "Lexer.h"
#include "LyXAction.h"
#include "SpellChecker.h"
#include "Session.h"
#include "TexRow.h"
-#include "TextClass.h"
#include "Text.h"
#include "Toolbars.h"
#include "version.h"
+#include "graphics/PreviewLoader.h"
+
#include "support/convert.h"
#include "support/debug.h"
#include "support/ExceptionMessage.h"
#include "support/FileName.h"
-#include "support/filetools.h"
#include "support/gettext.h"
-#include "support/filetools.h"
#include "support/ForkedCalls.h"
#include "support/lassert.h"
#include "support/lstrings.h"
#include <QAction>
#include <QApplication>
#include <QCloseEvent>
-#include <QDebug>
-#include <QDesktopWidget>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QFuture>
#include <QMenu>
#include <QMenuBar>
#include <QMimeData>
-#include <QMovie>
#include <QPainter>
#include <QPixmap>
#include <QPoint>
-#include <QPushButton>
-#include <QScrollBar>
#include <QSettings>
#include <QShowEvent>
+#include <QSlider>
#include <QSplitter>
#include <QStackedWidget>
#include <QStatusBar>
#include <QSvgRenderer>
#include <QtConcurrentRun>
-#include <QTime>
#include <QTimer>
-#include <QToolBar>
#include <QUrl>
#include <QWindowStateChangeEvent>
+#include <QGestureEvent>
+#include <QPinchGesture>
// sync with GuiAlert.cpp
// Check how long the logo gets with the current font
// and adapt if the font is running wider than what
// we assume
- QFontMetrics fm(font);
+ GuiFontMetrics fm(font);
// Split the title into lines to measure the longest line
// in the current l7n.
QStringList titlesegs = htext.split('\n');
int wline = 0;
- int hline = fm.height();
- QStringList::const_iterator sit;
- for (sit = titlesegs.constBegin(); sit != titlesegs.constEnd(); ++sit) {
- if (fm.width(*sit) > wline)
- wline = fm.width(*sit);
+ int hline = fm.maxHeight();
+ for (QString const & seg : titlesegs) {
+ if (fm.width(seg) > wline)
+ wline = fm.width(seg);
}
// The longest line in the reference font (for English)
// is 180. Calculate scale factor from that.
setFocusPolicy(Qt::StrongFocus);
}
- void paintEvent(QPaintEvent *)
+ void paintEvent(QPaintEvent *) override
{
int const w = width_;
int const h = height_;
pain.drawPixmap(x, y, w, h, splash_);
}
- void keyPressEvent(QKeyEvent * ev)
+ void keyPressEvent(QKeyEvent * ev) override
{
KeySymbol sym;
setKeySymbol(&sym, ev);
Buffer::ExportStatus (*asyncFunc)(Buffer const *, Buffer *, string const &),
Buffer::ExportStatus (Buffer::*syncFunc)(string const &, bool) const,
Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const,
- bool allow_async);
+ bool allow_async, bool use_tmpdir = false);
QVector<GuiWorkArea*> guiWorkAreas();
///
QTimer statusbar_timer_;
+ QTimer statusbar_stats_timer_;
/// auto-saving of buffers
Timeout autosave_timeout_;
/// flag against a race condition due to multiclicks, see bug #1119
bool in_show_;
+
+ // Timers for statistic updates in buffer
+ /// Current time left to the nearest info update
+ int time_to_update = 1000;
+ ///Basic step for timer in ms. Basically reaction time for short selections
+ int const timer_rate = 500;
+ /// Real stats updates infrequently. First they take long time for big buffers, second
+ /// they are visible for fast-repeat keyboards even for mid documents.
+ int const default_stats_rate = 5000;
+ /// Detection of new selection, so we can react fast
+ bool already_in_selection_ = false;
+ /// Maximum size of "short" selection for which we can update with faster timer_rate
+ int const max_sel_chars = 5000;
+
};
QSet<Buffer const *> GuiView::GuiViewPrivate::busyBuffers;
GuiView::GuiView(int id)
: d(*new GuiViewPrivate(this)), id_(id), closing_(false), busy_(0),
- command_execute_(false), minibuffer_focus_(false), toolbarsMovable_(true),
- devel_mode_(false)
+ command_execute_(false), minibuffer_focus_(false), word_count_enabled_(true),
+ char_count_enabled_(true), char_nb_count_enabled_(false),
+ toolbarsMovable_(true), devel_mode_(false)
{
connect(this, SIGNAL(bufferViewChanged()),
this, SLOT(onBufferViewChanged()));
}
connect(&d.statusbar_timer_, SIGNAL(timeout()),
this, SLOT(clearMessage()));
+ connect(&d.statusbar_stats_timer_, SIGNAL(timeout()),
+ this, SLOT(showStats()));
+ d.statusbar_stats_timer_.start(d.timer_rate);
// We don't want to keep the window in memory if it is closed.
setAttribute(Qt::WA_DeleteOnClose, true);
// (such as "source" and "messages")
setDockOptions(QMainWindow::ForceTabbedDocks);
+#ifdef Q_OS_MAC
+ // use document mode tabs on docks
+ setDocumentMode(true);
+#endif
+
// For Drag&Drop.
setAcceptDrops(true);
+ QFontMetrics const fm(statusBar()->fontMetrics());
+ int const iconheight = max(int(d.normalIconSize), fm.height());
+ QSize const iconsize(iconheight, iconheight);
+
// add busy indicator to statusbar
- GuiClickableLabel * busylabel = new GuiClickableLabel(statusBar());
- statusBar()->addPermanentWidget(busylabel);
search_mode mode = theGuiApp()->imageSearchMode();
- QString fn = toqstr(lyx::libFileSearch("images", "busy", "gif", mode).absFileName());
- QMovie * busyanim = new QMovie(fn, QByteArray(), busylabel);
- busylabel->setMovie(busyanim);
- busyanim->start();
- busylabel->hide();
+ QString fn = toqstr(lyx::libFileSearch("images", "busy", "svgz", mode).absFileName());
+ PressableSvgWidget * busySVG = new PressableSvgWidget(fn);
+ statusBar()->addPermanentWidget(busySVG);
+ // make busy indicator square with 5px margins
+ busySVG->setMaximumSize(busySVG->height() - 5, busySVG->height() - 5);
+ busySVG->hide();
+ // Add cancel button
+ QPixmap ps = QIcon(getPixmap("images/", "process-stop", "svgz")).pixmap(iconsize);
+ GuiClickableLabel * processStop = new GuiClickableLabel(statusBar());
+ processStop->setPixmap(ps);
+ processStop->setToolTip(qt_("Click here to stop export/output process"));
+ processStop->hide();
+ statusBar()->addPermanentWidget(processStop);
connect(&d.processing_thread_watcher_, SIGNAL(started()),
- busylabel, SLOT(show()));
+ busySVG, SLOT(show()));
connect(&d.processing_thread_watcher_, SIGNAL(finished()),
- busylabel, SLOT(hide()));
- connect(busylabel, SIGNAL(clicked()), this, SLOT(checkCancelBackground()));
+ busySVG, SLOT(hide()));
+ connect(&d.processing_thread_watcher_, SIGNAL(started()),
+ processStop, SLOT(show()));
+ connect(&d.processing_thread_watcher_, SIGNAL(finished()),
+ processStop, SLOT(hide()));
+ connect(processStop, SIGNAL(pressed()), this, SLOT(checkCancelBackground()));
- QFontMetrics const fm(statusBar()->fontMetrics());
- int const iconheight = max(int(d.normalIconSize), fm.height());
- QSize const iconsize(iconheight, iconheight);
+ connect(this, SIGNAL(scriptKilled()), busySVG, SLOT(hide()));
+ connect(this, SIGNAL(scriptKilled()), processStop, SLOT(hide()));
+
+ stat_counts_ = new GuiClickableLabel(statusBar());
+ stat_counts_->setAlignment(Qt::AlignCenter);
+ stat_counts_->setFrameStyle(QFrame::StyledPanel);
+ stat_counts_->hide();
+ statusBar()->addPermanentWidget(stat_counts_);
+
+ connect(stat_counts_, SIGNAL(clicked()), this, SLOT(statsPressed()));
+
+ zoom_slider_ = new QSlider(Qt::Horizontal, statusBar());
+ // Small size slider for macOS to prevent the status bar from enlarging
+ zoom_slider_->setAttribute(Qt::WA_MacSmallSize);
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
+ zoom_slider_->setFixedWidth(fm.horizontalAdvance('x') * 15);
+#else
+ zoom_slider_->setFixedWidth(fm.width('x') * 15);
+#endif
+ // Make the defaultZoom center
+ zoom_slider_->setRange(10, (lyxrc.defaultZoom * 2) - 10);
+ // Initialize proper zoom value
+ QSettings settings;
+ zoom_ratio_ = settings.value("zoom_ratio", 1.0).toDouble();
+ // Actual zoom value: default zoom + fractional offset
+ int zoom = (int)(lyxrc.defaultZoom * zoom_ratio_);
+ zoom = min(max(zoom, zoom_min_), zoom_max_);
+ zoom_slider_->setValue(zoom);
+ zoom_slider_->setToolTip(qt_("Workarea zoom level. Drag, use Ctrl-+/- or Shift-Mousewheel to adjust."));
+
+ // Buttons to change zoom stepwise
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
+ QSize s(fm.horizontalAdvance('+'), fm.height());
+#else
+ QSize s(fm.width('+'), fm.height());
+#endif
+ zoom_in_ = new GuiClickableLabel(statusBar());
+ zoom_in_->setText("+");
+ zoom_in_->setFixedSize(s);
+ zoom_in_->setAlignment(Qt::AlignCenter);
+ zoom_out_ = new GuiClickableLabel(statusBar());
+ zoom_out_->setText(QString(QChar(0x2212)));
+ zoom_out_->setFixedSize(s);
+ zoom_out_->setAlignment(Qt::AlignCenter);
+
+ statusBar()->addPermanentWidget(zoom_out_);
+ zoom_out_->setEnabled(currentBufferView());
+ statusBar()->addPermanentWidget(zoom_slider_);
+ zoom_slider_->setEnabled(currentBufferView());
+ zoom_in_->setEnabled(currentBufferView());
+ statusBar()->addPermanentWidget(zoom_in_);
+
+ connect(zoom_slider_, SIGNAL(sliderMoved(int)), this, SLOT(zoomSliderMoved(int)));
+ connect(zoom_slider_, SIGNAL(valueChanged(int)), this, SLOT(zoomValueChanged(int)));
+ connect(this, SIGNAL(currentZoomChanged(int)), zoom_slider_, SLOT(setValue(int)));
+ connect(zoom_in_, SIGNAL(clicked()), this, SLOT(zoomInPressed()));
+ connect(zoom_out_, SIGNAL(clicked()), this, SLOT(zoomOutPressed()));
+
+ // QPalette palette = statusBar()->palette();
+
+ zoom_value_ = new GuiClickableLabel(statusBar());
+ connect(zoom_value_, SIGNAL(pressed()), this, SLOT(showZoomContextMenu()));
+ // zoom_value_->setPalette(palette);
+ zoom_value_->setForegroundRole(statusBar()->foregroundRole());
+ zoom_value_->setFixedHeight(fm.height());
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
+ zoom_value_->setMinimumWidth(fm.horizontalAdvance("444\%"));
+#else
+ zoom_value_->setMinimumWidth(fm.width("444\%"));
+#endif
+ zoom_value_->setAlignment(Qt::AlignCenter);
+ zoom_value_->setText(toqstr(bformat(_("[[ZOOM]]%1$d%"), zoom)));
+ statusBar()->addPermanentWidget(zoom_value_);
+ zoom_value_->setEnabled(currentBufferView());
+
+ statusBar()->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(statusBar(), SIGNAL(customContextMenuRequested(QPoint)),
+ this, SLOT(showStatusBarContextMenu()));
+
+ // enable pinch to zoom
+ grabGesture(Qt::PinchGesture);
QPixmap shellescape = QIcon(getPixmap("images/", "emblem-shellescape", "svgz,png")).pixmap(iconsize);
shell_escape_ = new QLabel(statusBar());
shell_escape_->setPixmap(shellescape);
- shell_escape_->setScaledContents(true);
shell_escape_->setAlignment(Qt::AlignCenter);
shell_escape_->setContextMenuPolicy(Qt::CustomContextMenu);
shell_escape_->setToolTip(qt_("WARNING: LaTeX is allowed to execute "
QPixmap readonly = QIcon(getPixmap("images/", "emblem-readonly", "svgz,png")).pixmap(iconsize);
read_only_ = new QLabel(statusBar());
read_only_->setPixmap(readonly);
- read_only_->setScaledContents(true);
read_only_->setAlignment(Qt::AlignCenter);
read_only_->hide();
statusBar()->addPermanentWidget(read_only_);
initToolbars();
// clear session data if any.
- QSettings settings;
settings.remove("views");
}
int const ret =
Alert::prompt(ttl, msg, 1, 1,
_("&Cancel export"), _("Co&ntinue"));
- if (ret == 0)
+ if (ret == 0) {
Systemcall::killscript();
+ // stop busy signal immediately so that in the subsequent
+ // "Export canceled" prompt the status bar icons are accurate.
+ Q_EMIT scriptKilled();
+ }
+}
+
+void GuiView::statsPressed()
+{
+ DispatchResult dr;
+ dispatch(FuncRequest(LFUN_STATISTICS), dr);
+}
+
+void GuiView::zoomSliderMoved(int value)
+{
+ DispatchResult dr;
+ dispatch(FuncRequest(LFUN_BUFFER_ZOOM, convert<string>(value)), dr);
+ scheduleRedrawWorkAreas();
+ zoom_value_->setText(toqstr(bformat(_("[[ZOOM]]%1$d%"), value)));
+}
+
+
+void GuiView::zoomValueChanged(int value)
+{
+ if (value != lyxrc.currentZoom)
+ zoomSliderMoved(value);
+}
+
+
+void GuiView::zoomInPressed()
+{
+ DispatchResult dr;
+ dispatch(FuncRequest(LFUN_BUFFER_ZOOM_IN), dr);
+ scheduleRedrawWorkAreas();
+}
+
+
+void GuiView::zoomOutPressed()
+{
+ DispatchResult dr;
+ dispatch(FuncRequest(LFUN_BUFFER_ZOOM_OUT), dr);
+ scheduleRedrawWorkAreas();
+}
+
+
+void GuiView::showZoomContextMenu()
+{
+ QMenu * menu = guiApp->menus().menu(toqstr("context-zoom"), * this);
+ if (!menu)
+ return;
+ menu->exec(QCursor::pos());
+}
+
+
+void GuiView::showStatusBarContextMenu()
+{
+ QMenu * menu = guiApp->menus().menu(toqstr("context-statusbar"), * this);
+ if (!menu)
+ return;
+ menu->exec(QCursor::pos());
+}
+
+
+void GuiView::scheduleRedrawWorkAreas()
+{
+ for (int i = 0; i < d.tabWorkAreaCount(); i++) {
+ TabWorkArea* ta = d.tabWorkArea(i);
+ for (int u = 0; u < ta->count(); u++) {
+ ta->workArea(u)->scheduleRedraw(true);
+ }
+ }
}
static void handleExportStatus(GuiView * view, Buffer::ExportStatus status,
string const & format)
{
- docstring const fmt = theFormats().prettyName(format);
+ docstring const fmt = translateIfPossible(theFormats().prettyName(format));
docstring msg;
switch (status) {
case Buffer::ExportSuccess:
settings.setValue("devel_mode", devel_mode_);
settings.beginGroup("views");
settings.beginGroup(QString::number(id_));
-#if defined(Q_WS_X11) || defined(QPA_XCB)
- settings.setValue("pos", pos());
- settings.setValue("size", size());
-#else
- settings.setValue("geometry", saveGeometry());
-#endif
+ if (guiApp->platformName() == "qt4x11" || guiApp->platformName() == "xcb") {
+ settings.setValue("pos", pos());
+ settings.setValue("size", size());
+ } else
+ settings.setValue("geometry", saveGeometry());
settings.setValue("layout", saveState(0));
settings.setValue("icon_size", toqstr(d.iconSize(iconSize())));
+ settings.setValue("zoom_value_visible", zoom_value_->isVisible());
+ settings.setValue("zoom_slider_visible", zoom_slider_->isVisible());
+ settings.setValue("word_count_enabled", word_count_enabled_);
+ settings.setValue("char_count_enabled", char_count_enabled_);
+ settings.setValue("char_nb_count_enabled", char_nb_count_enabled_);
}
QSettings settings;
// Save the toolbar private states
- ToolbarMap::iterator end = d.toolbars_.end();
- for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
- it->second->saveSession(settings);
+ for (auto const & tb_p : d.toolbars_)
+ tb_p.second->saveSession(settings);
// Now take care of all other dialogs
- map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
- for (; it!= d.dialogs_.end(); ++it)
- it->second->saveSession(settings);
+ for (auto const & dlg_p : d.dialogs_)
+ dlg_p.second->saveSession(settings);
+}
+
+
+void GuiView::setCurrentZoom(const int v)
+{
+ lyxrc.currentZoom = v;
+ zoom_value_->setText(toqstr(bformat(_("[[ZOOM]]%1$d%"), v)));
+ Q_EMIT currentZoomChanged(v);
}
zoom_ratio_ = settings.value("zoom_ratio", 1.0).toDouble();
// Actual zoom value: default zoom + fractional offset
int zoom = (int)(lyxrc.defaultZoom * zoom_ratio_);
- if (zoom < static_cast<int>(zoom_min_))
- zoom = zoom_min_;
- lyxrc.currentZoom = zoom;
+ zoom = min(max(zoom, zoom_min_), zoom_max_);
+ setCurrentZoom(zoom);
devel_mode_ = settings.value("devel_mode", devel_mode_).toBool();
settings.beginGroup("views");
settings.beginGroup(QString::number(id_));
//code below is skipped when when ~/.config/LyX is (re)created
setIconSize(d.iconSize(settings.value(icon_key).toString()));
-#if defined(Q_WS_X11) || defined(QPA_XCB)
- QPoint pos = settings.value("pos", QPoint(50, 50)).toPoint();
- QSize size = settings.value("size", QSize(690, 510)).toSize();
- resize(size);
- move(pos);
-#else
- // Work-around for bug #6034: the window ends up in an undetermined
- // state when trying to restore a maximized window when it is
- // already maximized.
- if (!(windowState() & Qt::WindowMaximized))
- if (!restoreGeometry(settings.value("geometry").toByteArray()))
- setGeometry(50, 50, 690, 510);
-#endif
+ zoom_value_->setVisible(settings.value("zoom_value_visible", true).toBool());
+
+ bool const show_zoom_slider = settings.value("zoom_slider_visible", true).toBool();
+ zoom_slider_->setVisible(show_zoom_slider);
+ zoom_in_->setVisible(show_zoom_slider);
+ zoom_out_->setVisible(show_zoom_slider);
+
+ word_count_enabled_ = settings.value("word_count_enabled", true).toBool();
+ char_count_enabled_ = settings.value("char_count_enabled", true).toBool();
+ char_nb_count_enabled_ = settings.value("char_nb_count_enabled", true).toBool();
+ stat_counts_->setVisible(word_count_enabled_ || char_count_enabled_ || char_nb_count_enabled_);
+
+ if (guiApp->platformName() == "qt4x11" || guiApp->platformName() == "xcb") {
+ QPoint pos = settings.value("pos", QPoint(50, 50)).toPoint();
+ QSize size = settings.value("size", QSize(690, 510)).toSize();
+ resize(size);
+ move(pos);
+ } else {
+ // Work-around for bug #6034: the window ends up in an undetermined
+ // state when trying to restore a maximized window when it is
+ // already maximized.
+ if (!(windowState() & Qt::WindowMaximized))
+ if (!restoreGeometry(settings.value("geometry").toByteArray()))
+ setGeometry(50, 50, 690, 510);
+ }
+
// Make sure layout is correctly oriented.
setLayoutDirection(qApp->layoutDirection());
initToolbars();
// init the toolbars that have not been restored
- Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
- Toolbars::Infos::iterator end = guiApp->toolbars().end();
- for (; cit != end; ++cit) {
- GuiToolbar * tb = toolbar(cit->name);
+ for (auto const & tb_p : guiApp->toolbars()) {
+ GuiToolbar * tb = toolbar(tb_p.name);
if (tb && !tb->isRestored())
- initToolbar(cit->name);
+ initToolbar(tb_p.name);
}
// update lock (all) toolbars positions
if (tb && tb->isMovable())
toolbarsMovable_ = true;
}
+#if QT_VERSION >= 0x050200
+ // set unified mac toolbars only when not movable as recommended:
+ // https://doc.qt.io/qt-5/qmainwindow.html#unifiedTitleAndToolBarOnMac-prop
+ setUnifiedTitleAndToolBarOnMac(!toolbarsMovable_);
+#endif
}
void GuiView::constructToolbars()
{
- ToolbarMap::iterator it = d.toolbars_.begin();
- for (; it != d.toolbars_.end(); ++it)
- delete it->second;
+ for (auto const & tb_p : d.toolbars_)
+ delete tb_p.second;
d.toolbars_.clear();
// I don't like doing this here, but the standard toolbar
d.layout_->move(0,0);
// extracts the toolbars from the backend
- Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
- Toolbars::Infos::iterator end = guiApp->toolbars().end();
- for (; cit != end; ++cit)
- d.toolbars_[cit->name] = new GuiToolbar(*cit, *this);
+ for (ToolbarInfo const & inf : guiApp->toolbars())
+ d.toolbars_[inf.name] = new GuiToolbar(inf, *this);
+
+ DynamicMenuButton::resetIconCache();
}
void GuiView::initToolbars()
{
// extracts the toolbars from the backend
- Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
- Toolbars::Infos::iterator end = guiApp->toolbars().end();
- for (; cit != end; ++cit)
- initToolbar(cit->name);
+ for (ToolbarInfo const & inf : guiApp->toolbars())
+ initToolbar(inf.name);
}
// We cannot use a for loop as the buffer list cycles.
Buffer * b = first;
do {
- if (!saveBufferIfNeeded(const_cast<Buffer &>(*b), false))
+ if (!saveBufferIfNeeded(*b, false))
return false;
b = theBufferList().next(b);
} while (b != first);
// Make sure the timer time out will not trigger a statusbar update.
d.statusbar_timer_.stop();
+ d.statusbar_stats_timer_.stop();
// Saving fullscreen requires additional tweaks in the toolbar code.
// It wouldn't also work under linux natively.
vector<const Format *> found_formats;
// Find all formats that have the correct extension.
- vector<const Format *> const & import_formats
- = theConverters().importableFormats();
- vector<const Format *>::const_iterator it = import_formats.begin();
- for (; it != import_formats.end(); ++it)
- if ((*it)->hasExtension(ext))
- found_formats.push_back(*it);
+ for (const Format * fmt : theConverters().importableFormats())
+ if (fmt->hasExtension(ext))
+ found_formats.push_back(fmt);
FuncRequest cmd;
- if (found_formats.size() >= 1) {
+ if (!found_formats.empty()) {
if (found_formats.size() > 1) {
//FIXME: show a dialog to choose the correct importable format
LYXERR(Debug::FILES,
d.statusbar_timer_.stop();
}
+void GuiView::showStats()
+{
+ if (!statsEnabled())
+ return;
+
+ d.time_to_update -= d.timer_rate;
+
+ BufferView * bv = currentBufferView();
+ Buffer * buf = bv ? &bv->buffer() : nullptr;
+ if (!buf) {
+ stat_counts_->hide();
+ return;
+ }
+
+ Cursor const & cur = bv->cursor();
+
+ // we start new selection and need faster update
+ if (!d.already_in_selection_ && cur.selection())
+ d.time_to_update = 0;
+
+ if (d.time_to_update > 0)
+ return;
+
+ DocIterator from, to;
+ if (cur.selection()) {
+ from = cur.selectionBegin();
+ to = cur.selectionEnd();
+ d.already_in_selection_ = true;
+ } else {
+ from = doc_iterator_begin(buf);
+ to = doc_iterator_end(buf);
+ d.already_in_selection_ = false;
+ }
+
+ buf->updateStatistics(from, to);
+
+ QStringList stats;
+ if (word_count_enabled_) {
+ int const words = buf->wordCount();
+ if (words == 1)
+ stats << toqstr(bformat(_("%1$d Word"), words));
+ else
+ stats << toqstr(bformat(_("%1$d Words"), words));
+ }
+ int const chars_with_blanks = buf->charCount(true);
+ if (char_count_enabled_) {
+ if (chars_with_blanks == 1)
+ stats << toqstr(bformat(_("%1$d Character"), chars_with_blanks));
+ else
+ stats << toqstr(bformat(_("%1$d Characters"), chars_with_blanks));
+ }
+ if (char_nb_count_enabled_) {
+ int const chars = buf->charCount(false);
+ if (chars == 1)
+ stats << toqstr(bformat(_("%1$d Character (no Blanks)"), chars));
+ else
+ stats << toqstr(bformat(_("%1$d Characters (no Blanks)"), chars));
+ }
+ stat_counts_->setText(stats.join(qt_(", [[stats separator]]")));
+ stat_counts_->show();
+
+ d.time_to_update = d.default_stats_rate;
+ // fast updates for small selections
+ if (chars_with_blanks < d.max_sel_chars && cur.selection())
+ d.time_to_update = d.timer_rate;
+}
+
void GuiView::updateWindowTitle(GuiWorkArea * wa)
{
// Buffer-dependent dialogs must be updated. This is done here because
// some dialogs require buffer()->text.
updateDialogs();
+ zoom_slider_->setEnabled(currentBufferView());
+ zoom_value_->setEnabled(currentBufferView());
+ zoom_in_->setEnabled(currentBufferView());
+ zoom_out_->setEnabled(currentBufferView());
}
}
+bool GuiView::statsEnabled() const
+{
+ return word_count_enabled_ || char_count_enabled_ || char_nb_count_enabled_;
+}
+
+
bool GuiView::event(QEvent * e)
{
switch (e->type())
if (lyxrc.full_screen_menubar)
menuBar()->hide();
if (lyxrc.full_screen_toolbars) {
- ToolbarMap::iterator end = d.toolbars_.end();
- for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
- if (it->second->isVisibiltyOn() && it->second->isVisible())
- it->second->hide();
+ for (auto const & tb_p : d.toolbars_)
+ if (tb_p.second->isVisibilityOn() && tb_p.second->isVisible())
+ tb_p.second->hide();
}
for (int i = 0; i != d.splitter_->count(); ++i)
d.tabWorkArea(i)->setFullScreen(true);
+#if QT_VERSION > 0x050903
+ //Qt's 5.9.4 ba44cdae38406c safe area measures won't allow us to go negative in margins
+ setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
+#endif
setContentsMargins(-2, -2, -2, -2);
// bug 5274
hideDialogs("prefs", nullptr);
if (lyxrc.full_screen_menubar && !menuBar()->isVisible())
menuBar()->show();
if (lyxrc.full_screen_toolbars) {
- ToolbarMap::iterator end = d.toolbars_.end();
- for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
- if (it->second->isVisibiltyOn() && !it->second->isVisible())
- it->second->show();
+ for (auto const & tb_p : d.toolbars_)
+ if (tb_p.second->isVisibilityOn() && !tb_p.second->isVisible())
+ tb_p.second->show();
//updateToolbars();
}
for (int i = 0; i != d.splitter_->count(); ++i)
d.tabWorkArea(i)->setFullScreen(false);
+#if QT_VERSION > 0x050903
+ setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, true);
+#endif
setContentsMargins(0, 0, 0, 0);
}
return result;
- }
+ }
+
case QEvent::WindowActivate: {
GuiView * old_view = guiApp->currentView();
if (this == old_view) {
return QMainWindow::event(e);
}
+ case QEvent::ApplicationPaletteChange: {
+ // runtime switch from/to dark mode
+ refillToolbars();
+ return QMainWindow::event(e);
+ }
+
+ case QEvent::Gesture: {
+ QGestureEvent *ge = static_cast<QGestureEvent*>(e);
+ QGesture *gp = ge->gesture(Qt::PinchGesture);
+ if (gp) {
+ QPinchGesture *pinch = static_cast<QPinchGesture *>(gp);
+ QPinchGesture::ChangeFlags changeFlags = pinch->changeFlags();
+ qreal totalScaleFactor = pinch->totalScaleFactor();
+ LYXERR(Debug::GUI, "totalScaleFactor: " << totalScaleFactor);
+ if (pinch->state() == Qt::GestureStarted) {
+ initialZoom_ = lyxrc.currentZoom;
+ LYXERR(Debug::GUI, "initialZoom_: " << initialZoom_);
+ }
+ if (changeFlags & QPinchGesture::ScaleFactorChanged) {
+ qreal factor = initialZoom_ * totalScaleFactor;
+ LYXERR(Debug::GUI, "scaleFactor: " << factor);
+ zoomValueChanged(factor);
+ }
+ }
+ return QMainWindow::event(e);
+ }
+
default:
return QMainWindow::event(e);
}
}
+bool GuiView::hasVisibleWorkArea(GuiWorkArea * wa) const
+{
+ for (int i = 0; i < d.splitter_->count(); ++i)
+ if (d.tabWorkArea(i)->currentWorkArea() == wa)
+ return true;
+
+ FindAndReplace * fr = static_cast<FindAndReplace*>(find("findreplaceadv", false));
+ return fr->isVisible() && fr->hasWorkArea(wa);
+}
+
+
LayoutBox * GuiView::getLayoutDialog() const
{
return d.layout_;
void GuiView::updateToolbars()
{
- ToolbarMap::iterator end = d.toolbars_.end();
if (d.current_work_area_) {
int context = 0;
if (d.current_work_area_->bufferView().cursor().inMathed()
minibuffer_focus_ = false;
}
- for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
- it->second->update(context);
+ for (auto const & tb_p : d.toolbars_)
+ tb_p.second->update(context);
} else
- for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
- it->second->update();
+ for (auto const & tb_p : d.toolbars_)
+ tb_p.second->update();
+}
+
+
+void GuiView::refillToolbars()
+{
+ DynamicMenuButton::resetIconCache();
+ for (auto const & tb_p : d.toolbars_)
+ tb_p.second->refill();
}
}
+namespace {
+
+double zoomRatio(FuncRequest const & cmd, double const zr)
+{
+ if (cmd.argument().empty()) {
+ if (cmd.action() == LFUN_BUFFER_ZOOM)
+ return 1.0;
+ else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
+ return zr + 0.1;
+ else // cmd.action() == LFUN_BUFFER_ZOOM_OUT
+ return zr - 0.1;
+ } else {
+ if (cmd.action() == LFUN_BUFFER_ZOOM)
+ return convert<int>(cmd.argument()) / double(lyxrc.defaultZoom);
+ else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
+ return zr + convert<int>(cmd.argument()) / 100.0;
+ else // cmd.action() == LFUN_BUFFER_ZOOM_OUT
+ return zr - convert<int>(cmd.argument()) / 100.0;
+ }
+}
+
+}
+
+
bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
{
bool enable = true;
flag.setOnOff(devel_mode_);
break;
+ case LFUN_TOOLBAR_SET: {
+ string const name = cmd.getArg(0);
+ string const state = cmd.getArg(1);
+ if (name.empty() || state.empty()) {
+ enable = false;
+ docstring const msg =
+ _("Function toolbar-set requires two arguments!");
+ flag.message(msg);
+ break;
+ }
+ if (state != "on" && state != "off" && state != "auto") {
+ enable = false;
+ docstring const msg =
+ bformat(_("Invalid argument \"%1$s\" to function toolbar-set!"),
+ from_utf8(state));
+ flag.message(msg);
+ break;
+ }
+ if (GuiToolbar * t = toolbar(name)) {
+ bool const autovis = t->visibility() & Toolbars::AUTO;
+ if (state == "on")
+ flag.setOnOff(t->isVisible() && !autovis);
+ else if (state == "off")
+ flag.setOnOff(!t->isVisible() && !autovis);
+ else if (state == "auto")
+ flag.setOnOff(autovis);
+ } else {
+ enable = false;
+ docstring const msg =
+ bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name));
+ flag.message(msg);
+ }
+ break;
+ }
+
case LFUN_TOOLBAR_TOGGLE: {
string const name = cmd.getArg(0);
if (GuiToolbar * t = toolbar(name))
break;
case LFUN_UI_TOGGLE:
- flag.setOnOff(isFullScreen());
+ if (cmd.argument() == "zoomlevel") {
+ flag.setOnOff(zoom_value_ ? zoom_value_->isVisible() : false);
+ } else if (cmd.argument() == "zoomslider") {
+ flag.setOnOff(zoom_slider_ ? zoom_slider_->isVisible() : false);
+ } else if (cmd.argument() == "statistics-w") {
+ flag.setOnOff(word_count_enabled_);
+ } else if (cmd.argument() == "statistics-cb") {
+ flag.setOnOff(char_count_enabled_);
+ } else if (cmd.argument() == "statistics-c") {
+ flag.setOnOff(char_nb_count_enabled_);
+ } else
+ flag.setOnOff(isFullScreen());
break;
case LFUN_DIALOG_DISCONNECT_INSET:
enable = FileName(doc_buffer->logName()).isReadableFile();
else if (name == "spellchecker")
enable = theSpellChecker()
- && !doc_buffer->isReadonly()
&& !doc_buffer->text().empty();
else if (name == "vclog")
enable = doc_buffer->lyxvc().inUse();
break;
case LFUN_BUFFER_ZOOM_OUT:
- case LFUN_BUFFER_ZOOM_IN: {
- // only diff between these two is that the default for ZOOM_OUT
- // is a neg. number
- bool const neg_zoom =
- convert<int>(cmd.argument()) < 0 ||
- (cmd.action() == LFUN_BUFFER_ZOOM_OUT && cmd.argument().empty());
- if (lyxrc.currentZoom <= zoom_min_ && neg_zoom) {
+ case LFUN_BUFFER_ZOOM_IN:
+ case LFUN_BUFFER_ZOOM: {
+ int const zoom = (int)(lyxrc.defaultZoom * zoomRatio(cmd, zoom_ratio_));
+ if (zoom < zoom_min_) {
docstring const msg =
bformat(_("Zoom level cannot be less than %1$d%."), zoom_min_);
flag.message(msg);
enable = false;
- } else
- enable = doc_buffer;
- break;
- }
-
- case LFUN_BUFFER_ZOOM: {
- bool const less_than_min_zoom =
- !cmd.argument().empty() && convert<int>(cmd.argument()) < zoom_min_;
- if (lyxrc.currentZoom <= zoom_min_ && less_than_min_zoom) {
+ } else if (zoom > zoom_max_) {
docstring const msg =
- bformat(_("Zoom level cannot be less than %1$d%."), zoom_min_);
+ bformat(_("Zoom level cannot be more than %1$d%."), zoom_max_);
flag.message(msg);
enable = false;
- }
- else
+ } else
enable = doc_buffer;
break;
}
+
case LFUN_BUFFER_MOVE_NEXT:
case LFUN_BUFFER_MOVE_PREVIOUS:
// we do not cycle when moving
case LFUN_WINDOW_RAISE:
break;
case LFUN_FORWARD_SEARCH:
- enable = !(lyxrc.forward_search_dvi.empty() && lyxrc.forward_search_pdf.empty());
+ enable = !(lyxrc.forward_search_dvi.empty() && lyxrc.forward_search_pdf.empty()) &&
+ doc_buffer && doc_buffer->isSyncTeXenabled();
break;
case LFUN_FILE_INSERT_PLAINTEXT:
flag.setOnOff(lyxrc.spellcheck_continuously);
break;
+ case LFUN_CITATION_OPEN:
+ enable = true;
+ break;
+
default:
return false;
}
Buffer * newBuffer = nullptr;
try {
newBuffer = checkAndLoadLyXFile(filename);
- } catch (ExceptionMessage const & e) {
+ } catch (ExceptionMessage const &) {
setBusy(false);
- throw(e);
+ throw;
}
setBusy(false);
dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
dlg.setButton2(qt_("&Examples"), toqstr(lyxrc.example_path));
- QStringList const filter(qt_("LyX Documents (*.lyx)"));
+ QStringList const filter({
+ qt_("LyX Documents (*.lyx)"),
+ qt_("LyX Document Backups (*.lyx~)"),
+ qt_("All Files (*.*)")
+ });
FileDialog::Result result =
dlg.open(toqstr(initpath), filter);
string loader_format;
vector<string> loaders = theConverters().loaders();
if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
- vector<string>::const_iterator it = loaders.begin();
- vector<string>::const_iterator en = loaders.end();
- for (; it != en; ++it) {
- if (!theConverters().isReachable(format, *it))
+ for (string const & loader : loaders) {
+ if (!theConverters().isReachable(format, loader))
continue;
string const tofile =
support::changeExtension(filename.absFileName(),
- theFormats().extension(*it));
+ theFormats().extension(loader));
if (theConverters().convert(nullptr, filename, FileName(tofile),
- filename, format, *it, errorList) != Converters::SUCCESS)
+ filename, format, loader, errorList) != Converters::SUCCESS)
return false;
- loader_format = *it;
+ loader_format = loader;
break;
}
if (loader_format.empty()) {
frontend::Alert::error(_("Couldn't import file"),
bformat(_("No information for importing the format %1$s."),
- theFormats().prettyName(format)));
+ translateIfPossible(theFormats().prettyName(format))));
return false;
}
} else
}
docstring const text = bformat(_("Select %1$s file to import"),
- theFormats().prettyName(format));
+ translateIfPossible(theFormats().prettyName(format)));
FileDialog dlg(toqstr(text));
dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
dlg.setButton2(qt_("&Examples"), toqstr(lyxrc.example_path));
- docstring filter = theFormats().prettyName(format);
+ docstring filter = translateIfPossible(theFormats().prettyName(format));
filter += " (*.{";
// FIXME UNICODE
filter += from_utf8(theFormats().extensions(format));
}
-void GuiView::insertLyXFile(docstring const & fname, bool ignorelang)
+bool GuiView::insertLyXFile(docstring const & fname, bool ignorelang)
{
BufferView * bv = documentBufferView();
if (!bv)
- return;
+ return false;
// FIXME UNICODE
FileName filename(to_utf8(fname));
QStringList(qt_("LyX Documents (*.lyx)")));
if (result.first == FileDialog::Later)
- return;
+ return false;
// FIXME UNICODE
filename.set(fromqstr(result.second));
if (filename.empty()) {
// emit message signal.
message(_("Canceled."));
- return;
+ return false;
}
}
bv->insertLyXFile(filename, ignorelang);
bv->buffer().errors("Parse");
+ return true;
}
dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
dlg.setButton2(qt_("&Templates"), toqstr(lyxrc.template_path));
- if (!isLyXFileName(fname.absFileName()))
- fname.changeExtension(".lyx");
+ fname.ensureExtension(".lyx");
string const path = as_template ?
getTemplatesPath(b)
if (fname.empty())
return false;
- if (!isLyXFileName(fname.absFileName()))
- fname.changeExtension(".lyx");
+ fname.ensureExtension(".lyx");
}
// fname is now the new Buffer location.
if (fmt_name.empty() || fname.empty())
return false;
+ fname.ensureExtension(theFormats().extension(fmt_name));
+
// fname is now the new Buffer location.
- if (FileName(fname).exists()) {
+ if (fname.exists()) {
docstring const file = makeDisplayPath(fname.absFileName(), 30);
docstring text = bformat(_("The document %1$s already "
"exists.\n\nDo you want to "
bool GuiView::closeBuffer(Buffer & buf)
{
bool success = true;
- ListOfBuffers clist = buf.getChildren();
- ListOfBuffers::const_iterator it = clist.begin();
- ListOfBuffers::const_iterator const bend = clist.end();
- for (; it != bend; ++it) {
- Buffer * child_buf = *it;
+ for (Buffer * child_buf : buf.getChildren()) {
if (theBufferList().isOthersChild(&buf, child_buf)) {
child_buf->setParent(nullptr);
continue;
if (success) {
// goto bookmark to update bookmark pit.
// FIXME: we should update only the bookmarks related to this buffer!
+ // FIXME: this is done also in LFUN_WINDOW_CLOSE!
LYXERR(Debug::DEBUG, "GuiView::closeBuffer()");
- for (unsigned int i = 0; i < theSession().bookmarks().size(); ++i)
- guiApp->gotoBookmark(i + 1, false, false);
+ for (unsigned int i = 1; i < theSession().bookmarks().size(); ++i)
+ guiApp->gotoBookmark(i, false, false);
if (saveBufferIfNeeded(buf, false)) {
buf.removeAutosaveFile();
void GuiView::checkExternallyModifiedBuffers()
{
- BufferList::iterator bit = theBufferList().begin();
- BufferList::iterator const bend = theBufferList().end();
- for (; bit != bend; ++bit) {
- Buffer * buf = *bit;
+ for (Buffer * buf : theBufferList()) {
if (buf->fileName().exists() && buf->isChecksumModified()) {
docstring text = bformat(_("Document \n%1$s\n has been externally modified."
" Reload now? Any local changes will be lost."),
setBuffer(buf);
bool success = documentBufferView()->setCursorFromRow(row);
if (!success) {
- LYXERR(Debug::LATEX,
+ LYXERR(Debug::OUTFILE,
"setCursorFromRow: invalid position for row " << row);
frontend::Alert::error(_("Inverse Search Failed"),
_("Invalid position requested by inverse search.\n"
}
-bool GuiView::GuiViewPrivate::asyncBufferProcessing(
- string const & argument,
+bool GuiView::GuiViewPrivate::asyncBufferProcessing(string const & argument,
Buffer const * used_buffer,
docstring const & msg,
Buffer::ExportStatus (*asyncFunc)(Buffer const *, Buffer *, string const &),
Buffer::ExportStatus (Buffer::*syncFunc)(string const &, bool) const,
Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const,
- bool allow_async)
+ bool allow_async, bool use_tmpdir)
{
if (!used_buffer)
return false;
} else {
Buffer::ExportStatus status;
if (syncFunc) {
- status = (used_buffer->*syncFunc)(format, false);
+ status = (used_buffer->*syncFunc)(format, use_tmpdir);
} else if (previewFunc) {
status = (used_buffer->*previewFunc)(format);
} else
_("Exporting ..."),
&GuiViewPrivate::compileAndDestroy,
&Buffer::doExport,
- nullptr, cmd.allowAsync());
+ nullptr, cmd.allowAsync(), true);
break;
}
case LFUN_BUFFER_VIEW: {
docstring(),
&GuiViewPrivate::compileAndDestroy,
&Buffer::doExport,
- nullptr, cmd.allowAsync());
+ nullptr, cmd.allowAsync(), true);
break;
}
case LFUN_MASTER_BUFFER_VIEW: {
}
case LFUN_EXPORT_CANCEL: {
Systemcall::killscript();
+ Q_EMIT scriptKilled();
break;
}
case LFUN_BUFFER_SWITCH: {
break;
case LFUN_FILE_INSERT: {
- if (cmd.getArg(1) == "ignorelang")
- insertLyXFile(from_utf8(cmd.getArg(0)), true);
- else
- insertLyXFile(cmd.argument());
+ bool const ignore_lang = cmd.getArg(1) == "ignorelang";
+ if (insertLyXFile(from_utf8(cmd.getArg(0)), ignore_lang)) {
+ dr.forceBufferUpdate();
+ dr.screenUpdate(Update::Force);
+ }
break;
}
dr.setMessage(_("Developer mode is now disabled."));
break;
+ case LFUN_TOOLBAR_SET: {
+ string const name = cmd.getArg(0);
+ string const state = cmd.getArg(1);
+ if (GuiToolbar * t = toolbar(name))
+ t->setState(state);
+ break;
+ }
+
case LFUN_TOOLBAR_TOGGLE: {
string const name = cmd.getArg(0);
if (GuiToolbar * t = toolbar(name))
dr.setMessage(_("Toolbars unlocked."));
else
dr.setMessage(_("Toolbars locked."));
- } else if (GuiToolbar * t = toolbar(name)) {
+ } else if (GuiToolbar * tb = toolbar(name))
// toggle current toolbar movablity
- t->movable();
- // update lock (all) toolbars positions
- updateLockToolbars();
- }
+ tb->movable();
+ // update lock (all) toolbars positions
+ updateLockToolbars();
break;
}
sdata = bv->cursor().getEncoding()->name();
if (!sdata.empty())
showDialog("symbols", sdata);
+ } else if (name == "findreplace") {
+ sdata = to_utf8(bv->cursor().selectionAsString(false));
+ showDialog(name, sdata);
// bug 5274
} else if (name == "prefs" && isFullScreen()) {
lfunUiToggle("fullscreen");
case LFUN_BUFFER_ZOOM_IN:
case LFUN_BUFFER_ZOOM_OUT:
case LFUN_BUFFER_ZOOM: {
- if (cmd.argument().empty()) {
- if (cmd.action() == LFUN_BUFFER_ZOOM)
- zoom_ratio_ = 1.0;
- else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
- zoom_ratio_ += 0.1;
- else
- zoom_ratio_ -= 0.1;
- } else {
- if (cmd.action() == LFUN_BUFFER_ZOOM)
- zoom_ratio_ = convert<int>(cmd.argument()) / double(lyxrc.defaultZoom);
- else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
- zoom_ratio_ += convert<int>(cmd.argument()) / 100.0;
- else
- zoom_ratio_ -= convert<int>(cmd.argument()) / 100.0;
- }
+ zoom_ratio_ = zoomRatio(cmd, zoom_ratio_);
// Actual zoom value: default zoom + fractional extra value
int zoom = (int)(lyxrc.defaultZoom * zoom_ratio_);
- if (zoom < static_cast<int>(zoom_min_))
- zoom = zoom_min_;
+ zoom = min(max(zoom, zoom_min_), zoom_max_);
- lyxrc.currentZoom = zoom;
+ setCurrentZoom(zoom);
dr.setMessage(bformat(_("Zoom level is now %1$d% (default value: %2$d%)"),
lyxrc.currentZoom, lyxrc.defaultZoom));
guiApp->fontLoader().update();
- dr.screenUpdate(Update::Force | Update::FitCursor);
+ // Regenerate instant previews
+ if (lyxrc.preview != LyXRC::PREVIEW_OFF
+ && doc_buffer && doc_buffer->loader())
+ doc_buffer->loader()->refreshPreviews();
+ dr.screenUpdate(Update::ForceAll | Update::FitCursor);
break;
}
dr.setMessage(_("Please, preview the document first."));
break;
}
+ bool const goto_dvi = have_dvi && !lyxrc.forward_search_dvi.empty();
+ bool const goto_pdf = have_pdf && !lyxrc.forward_search_pdf.empty();
string outname = dviname.onlyFileName();
string command = lyxrc.forward_search_dvi;
- if (!have_dvi || (have_pdf &&
- pdfname.lastModified() > dviname.lastModified())) {
+ if ((!goto_dvi || goto_pdf) &&
+ pdfname.lastModified() > dviname.lastModified()) {
outname = pdfname.onlyFileName();
command = lyxrc.forward_search_pdf;
}
dr.screenUpdate(Update::Force);
break;
+ case LFUN_CITATION_OPEN: {
+ string pdfv, psv;
+ if (theFormats().getFormat("pdf"))
+ pdfv = theFormats().getFormat("pdf")->viewer();
+ if (theFormats().getFormat("ps"))
+ psv = theFormats().getFormat("ps")->viewer();
+ frontend::showTarget(argument, pdfv, psv);
+ break;
+ }
+
default:
// The LFUN must be for one of BufferView, Buffer or Cursor;
// let's try that:
break;
}
- // Part of automatic menu appearance feature.
- if (isFullScreen()) {
- if (menuBar()->isVisible() && lyxrc.full_screen_menubar)
- menuBar()->hide();
- }
-
// Need to update bv because many LFUNs here might have destroyed it
bv = currentBufferView();
statusBar()->setVisible(!statusBar()->isVisible());
} else if (ui_component == "menubar") {
menuBar()->setVisible(!menuBar()->isVisible());
- } else
- if (ui_component == "frame") {
+ } else if (ui_component == "zoomlevel") {
+ zoom_value_->setVisible(!zoom_value_->isVisible());
+ } else if (ui_component == "zoomslider") {
+ zoom_slider_->setVisible(!zoom_slider_->isVisible());
+ zoom_in_->setVisible(zoom_slider_->isVisible());
+ zoom_out_->setVisible(zoom_slider_->isVisible());
+ } else if (ui_component == "statistics-w") {
+ word_count_enabled_ = !word_count_enabled_;
+ if (statsEnabled())
+ showStats();
+ } else if (ui_component == "statistics-cb") {
+ char_count_enabled_ = !char_count_enabled_;
+ if (statsEnabled())
+ showStats();
+ } else if (ui_component == "statistics-c") {
+ char_nb_count_enabled_ = !char_nb_count_enabled_;
+ if (statsEnabled())
+ showStats();
+ } else if (ui_component == "frame") {
int const l = contentsMargins().left();
//are the frames in default state?
d.current_work_area_->setFrameStyle(QFrame::NoFrame);
if (l == 0) {
+#if QT_VERSION > 0x050903
+ setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
+#endif
setContentsMargins(-2, -2, -2, -2);
} else {
+#if QT_VERSION > 0x050903
+ setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, true);
+#endif
setContentsMargins(0, 0, 0, 0);
}
} else
toggleFullScreen();
} else
return false;
+ stat_counts_->setVisible(statsEnabled());
return true;
}
void GuiView::flatGroupBoxes(const QObject * widget, bool flag)
{
- for (const QObject * child: qAsConst(widget->children())) {
+ for (QObject * child: widget->children()) {
if (child->inherits("QGroupBox")) {
QGroupBox * box = (QGroupBox*) child;
box->setFlat(flag);
}
-Dialog * GuiView::findOrBuild(string const & name, bool hide_it)
+Dialog * GuiView::find(string const & name, bool hide_it) const
{
if (!isValidName(name))
return nullptr;
it->second->hideView();
return it->second.get();
}
+ return nullptr;
+}
- Dialog * dialog = build(name);
+
+Dialog * GuiView::findOrBuild(string const & name, bool hide_it)
+{
+ Dialog * dialog = find(name, hide_it);
+ if (dialog != nullptr)
+ return dialog;
+
+ dialog = build(name);
d.dialogs_[name].reset(dialog);
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
// Force a uniform style for group boxes
// On Mac non-flat works better, on Linux flat is standard
flatGroupBoxes(dialog->asQWidget(), guiApp->platformName() != "cocoa");
+#endif
if (lyxrc.allow_geometry_session)
dialog->restoreSession();
if (hide_it)
// activateWindow is needed for floating dockviews
dialog->asQWidget()->raise();
dialog->asQWidget()->activateWindow();
- dialog->asQWidget()->setFocus();
+ if (dialog->wantInitialFocus())
+ dialog->asQWidget()->setFocus();
}
}
}
- catch (ExceptionMessage const & ex) {
+ catch (ExceptionMessage const &) {
d.in_show_ = false;
- throw ex;
+ throw;
}
d.in_show_ = false;
}
void GuiView::hideAll() const
{
- map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
- map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
-
- for(; it != end; ++it)
- it->second->hideView();
+ for(auto const & dlg_p : d.dialogs_)
+ dlg_p.second->hideView();
}
void GuiView::updateDialogs()
{
- map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
- map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
-
- for(; it != end; ++it) {
- Dialog * dialog = it->second.get();
+ for(auto const & dlg_p : d.dialogs_) {
+ Dialog * dialog = dlg_p.second.get();
if (dialog) {
if (dialog->needBufferOpen() && !documentBufferView())
hideDialog(fromqstr(dialog->name()), nullptr);
updateLayoutList();
}
-Dialog * createDialog(GuiView & lv, string const & name);
-
-// will be replaced by a proper factory...
-Dialog * createGuiAbout(GuiView & lv);
-Dialog * createGuiBibtex(GuiView & lv);
-Dialog * createGuiChanges(GuiView & lv);
-Dialog * createGuiCharacter(GuiView & lv);
-Dialog * createGuiCitation(GuiView & lv);
-Dialog * createGuiCompare(GuiView & lv);
-Dialog * createGuiCompareHistory(GuiView & lv);
-Dialog * createGuiDelimiter(GuiView & lv);
-Dialog * createGuiDocument(GuiView & lv);
-Dialog * createGuiErrorList(GuiView & lv);
-Dialog * createGuiExternal(GuiView & lv);
-Dialog * createGuiGraphics(GuiView & lv);
-Dialog * createGuiInclude(GuiView & lv);
-Dialog * createGuiIndex(GuiView & lv);
-Dialog * createGuiListings(GuiView & lv);
-Dialog * createGuiLog(GuiView & lv);
-Dialog * createGuiLyXFiles(GuiView & lv);
-Dialog * createGuiMathMatrix(GuiView & lv);
-Dialog * createGuiNote(GuiView & lv);
-Dialog * createGuiParagraph(GuiView & lv);
-Dialog * createGuiPhantom(GuiView & lv);
-Dialog * createGuiPreferences(GuiView & lv);
-Dialog * createGuiPrint(GuiView & lv);
-Dialog * createGuiPrintindex(GuiView & lv);
-Dialog * createGuiRef(GuiView & lv);
-Dialog * createGuiSearch(GuiView & lv);
-Dialog * createGuiSearchAdv(GuiView & lv);
-Dialog * createGuiSendTo(GuiView & lv);
-Dialog * createGuiShowFile(GuiView & lv);
-Dialog * createGuiSpellchecker(GuiView & lv);
-Dialog * createGuiSymbols(GuiView & lv);
-Dialog * createGuiTabularCreate(GuiView & lv);
-Dialog * createGuiTexInfo(GuiView & lv);
-Dialog * createGuiToc(GuiView & lv);
-Dialog * createGuiThesaurus(GuiView & lv);
-Dialog * createGuiViewSource(GuiView & lv);
-Dialog * createGuiWrap(GuiView & lv);
-Dialog * createGuiProgressView(GuiView & lv);
-
-
Dialog * GuiView::build(string const & name)
{
- LASSERT(isValidName(name), return nullptr);
-
- Dialog * dialog = createDialog(*this, name);
- if (dialog)
- return dialog;
-
- if (name == "aboutlyx")
- return createGuiAbout(*this);
- if (name == "bibtex")
- return createGuiBibtex(*this);
- if (name == "changes")
- return createGuiChanges(*this);
- if (name == "character")
- return createGuiCharacter(*this);
- if (name == "citation")
- return createGuiCitation(*this);
- if (name == "compare")
- return createGuiCompare(*this);
- if (name == "comparehistory")
- return createGuiCompareHistory(*this);
- if (name == "document")
- return createGuiDocument(*this);
- if (name == "errorlist")
- return createGuiErrorList(*this);
- if (name == "external")
- return createGuiExternal(*this);
- if (name == "file")
- return createGuiShowFile(*this);
- if (name == "findreplace")
- return createGuiSearch(*this);
- if (name == "findreplaceadv")
- return createGuiSearchAdv(*this);
- if (name == "graphics")
- return createGuiGraphics(*this);
- if (name == "include")
- return createGuiInclude(*this);
- if (name == "index")
- return createGuiIndex(*this);
- if (name == "index_print")
- return createGuiPrintindex(*this);
- if (name == "listings")
- return createGuiListings(*this);
- if (name == "log")
- return createGuiLog(*this);
- if (name == "lyxfiles")
- return createGuiLyXFiles(*this);
- if (name == "mathdelimiter")
- return createGuiDelimiter(*this);
- if (name == "mathmatrix")
- return createGuiMathMatrix(*this);
- if (name == "note")
- return createGuiNote(*this);
- if (name == "paragraph")
- return createGuiParagraph(*this);
- if (name == "phantom")
- return createGuiPhantom(*this);
- if (name == "prefs")
- return createGuiPreferences(*this);
- if (name == "ref")
- return createGuiRef(*this);
- if (name == "sendto")
- return createGuiSendTo(*this);
- if (name == "spellchecker")
- return createGuiSpellchecker(*this);
- if (name == "symbols")
- return createGuiSymbols(*this);
- if (name == "tabularcreate")
- return createGuiTabularCreate(*this);
- if (name == "texinfo")
- return createGuiTexInfo(*this);
- if (name == "thesaurus")
- return createGuiThesaurus(*this);
- if (name == "toc")
- return createGuiToc(*this);
- if (name == "view-source")
- return createGuiViewSource(*this);
- if (name == "wrap")
- return createGuiWrap(*this);
- if (name == "progress")
- return createGuiProgressView(*this);
-
- return nullptr;
+ return createDialog(*this, name);
}
parent, SLOT(disableShellEscape()));
}
+
+void PressableSvgWidget::mousePressEvent(QMouseEvent * event)
+{
+ if (event->button() == Qt::LeftButton) {
+ Q_EMIT pressed();
+ }
+}
+
} // namespace frontend
} // namespace lyx