X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt%2FGuiView.cpp;h=791a2c2b42a52bc34d29c82eb02425608deb904f;hb=d4324034300f73f76e5ac34fb1e7653fa6e2ddf5;hp=ba2951e4a6ac58410cc1faf5df15960aff37abfe;hpb=9a147255df735d35dd03c3279bdbb35e39678ce0;p=features.git diff --git a/src/frontends/qt/GuiView.cpp b/src/frontends/qt/GuiView.cpp index ba2951e4a6..791a2c2b42 100644 --- a/src/frontends/qt/GuiView.cpp +++ b/src/frontends/qt/GuiView.cpp @@ -15,13 +15,14 @@ #include "GuiView.h" +#include "DialogFactory.h" #include "DispatchResult.h" #include "FileDialog.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" @@ -51,9 +52,8 @@ #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" @@ -64,7 +64,6 @@ #include "SpellChecker.h" #include "Session.h" #include "TexRow.h" -#include "TextClass.h" #include "Text.h" #include "Toolbars.h" #include "version.h" @@ -73,9 +72,7 @@ #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" @@ -89,35 +86,32 @@ #include #include #include -#include -#include #include #include #include #include +#include #include #include #include #include #include -#include #include #include #include -#include -#include #include #include +#include #include #include #include #include #include -#include #include -#include #include - +#include +#include +#include // sync with GuiAlert.cpp @@ -209,16 +203,15 @@ public: // 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. @@ -235,7 +228,7 @@ public: setFocusPolicy(Qt::StrongFocus); } - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { int const w = width_; int const h = height_; @@ -249,7 +242,7 @@ public: pain.drawPixmap(x, y, w, h, splash_); } - void keyPressEvent(QKeyEvent * ev) + void keyPressEvent(QKeyEvent * ev) override { KeySymbol sym; setKeySymbol(&sym, ev); @@ -499,7 +492,7 @@ public: 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 guiWorkAreas(); @@ -610,33 +603,108 @@ GuiView::GuiView(int id) // (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); // 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(); 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(busySVG, SIGNAL(pressed()), this, SLOT(checkCancelBackground())); QFontMetrics const fm(statusBar()->fontMetrics()); + + 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_); + if (zoom < static_cast(zoom_min_)) + zoom = zoom_min_; + 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 QLabel(statusBar()); + // 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(showZoomContextMenu())); + + // enable pinch to zoom + grabGesture(Qt::PinchGesture); + int const iconheight = max(int(d.normalIconSize), fm.height()); QSize const iconsize(iconheight, iconheight); 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 " @@ -651,7 +719,6 @@ GuiView::GuiView(int id) 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_); @@ -696,7 +763,6 @@ GuiView::GuiView(int id) initToolbars(); // clear session data if any. - QSettings settings; settings.remove("views"); } @@ -730,6 +796,58 @@ void GuiView::checkCancelBackground() } +void GuiView::zoomSliderMoved(int value) +{ + DispatchResult dr; + dispatch(FuncRequest(LFUN_BUFFER_ZOOM, convert(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-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); + } + } +} + + QVector GuiView::GuiViewPrivate::guiWorkAreas() { QVector areas; @@ -745,7 +863,7 @@ QVector GuiView::GuiViewPrivate::guiWorkAreas() 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: @@ -825,14 +943,15 @@ void GuiView::saveLayout() const 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()); } @@ -841,13 +960,19 @@ void GuiView::saveUISettings() const 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::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); } @@ -859,7 +984,7 @@ bool GuiView::restoreLayout() int zoom = (int)(lyxrc.defaultZoom * zoom_ratio_); if (zoom < static_cast(zoom_min_)) zoom = zoom_min_; - lyxrc.currentZoom = zoom; + setCurrentZoom(zoom); devel_mode_ = settings.value("devel_mode", devel_mode_).toBool(); settings.beginGroup("views"); settings.beginGroup(QString::number(id_)); @@ -870,19 +995,27 @@ bool GuiView::restoreLayout() //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); + + 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()); @@ -901,12 +1034,10 @@ bool GuiView::restoreLayout() 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 @@ -936,14 +1067,18 @@ void GuiView::updateLockToolbars() 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 @@ -953,20 +1088,18 @@ void GuiView::constructToolbars() 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); } @@ -1082,7 +1215,7 @@ bool GuiView::prepareAllBuffersForLogout() // We cannot use a for loop as the buffer list cycles. Buffer * b = first; do { - if (!saveBufferIfNeeded(const_cast(*b), false)) + if (!saveBufferIfNeeded(*b, false)) return false; b = theBufferList().next(b); } while (b != first); @@ -1178,15 +1311,12 @@ void GuiView::dropEvent(QDropEvent * event) vector found_formats; // Find all formats that have the correct extension. - vector const & import_formats - = theConverters().importableFormats(); - vector::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, @@ -1319,6 +1449,10 @@ void GuiView::onBufferViewChanged() // 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()); } @@ -1401,6 +1535,55 @@ bool GuiView::event(QEvent * e) //case QEvent::Drop: // break; + case QEvent::WindowStateChange: { + QWindowStateChangeEvent * ev = (QWindowStateChangeEvent*)e; + bool ofstate = (ev->oldState() & Qt::WindowFullScreen); + bool result = QMainWindow::event(e); + bool nfstate = (windowState() & Qt::WindowFullScreen); + if (!ofstate && nfstate) { + LYXERR(Debug::DEBUG, "GuiView: WindowStateChange(): full-screen " << nfstate); + // switch to full-screen state + if (lyxrc.full_screen_statusbar) + statusBar()->hide(); + if (lyxrc.full_screen_menubar) + menuBar()->hide(); + if (lyxrc.full_screen_toolbars) { + 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); + } else if (ofstate && !nfstate) { + LYXERR(Debug::DEBUG, "GuiView: WindowStateChange(): full-screen " << nfstate); + // switch back from full-screen state + if (lyxrc.full_screen_statusbar && !statusBar()->isVisible()) + statusBar()->show(); + if (lyxrc.full_screen_menubar && !menuBar()->isVisible()) + menuBar()->show(); + if (lyxrc.full_screen_toolbars) { + 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) { @@ -1437,6 +1620,27 @@ bool GuiView::event(QEvent * e) 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(e); + QGesture *gp = ge->gesture(Qt::PinchGesture); + if (gp) { + QPinchGesture *pinch = static_cast(gp); + QPinchGesture::ChangeFlags changeFlags = pinch->changeFlags(); + if (changeFlags & QPinchGesture::ScaleFactorChanged) { + qreal factor = lyxrc.currentZoom*pinch->scaleFactor(); + //factor = ceil(factor/20)*20; + zoomValueChanged(factor); + } + } + return QMainWindow::event(e); + } + default: return QMainWindow::event(e); } @@ -1674,7 +1878,6 @@ void GuiView::updateLayoutList() 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() @@ -1699,11 +1902,19 @@ void GuiView::updateToolbars() 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(); } @@ -2090,6 +2301,41 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) 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)) @@ -2129,7 +2375,12 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) break; case LFUN_UI_TOGGLE: - flag.setOnOff(isFullScreen()); + if (cmd.argument() == "zoom") { + flag.setOnOff(zoom_value_ ? zoom_value_->isVisible() : false); + } else if (cmd.argument() == "zoomslider") { + flag.setOnOff(zoom_slider_ ? zoom_slider_->isVisible() : false); + } else + flag.setOnOff(isFullScreen()); break; case LFUN_DIALOG_DISCONNECT_INSET: @@ -2166,7 +2417,6 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) 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(); @@ -2247,7 +2497,8 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) bformat(_("Zoom level cannot be less than %1$d%."), zoom_min_); flag.message(msg); enable = false; - } + } else if (cmd.argument().empty() && lyxrc.currentZoom == lyxrc.defaultZoom) + enable = false; else enable = doc_buffer; break; @@ -2327,6 +2578,10 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) flag.setOnOff(lyxrc.spellcheck_continuously); break; + case LFUN_CITATION_OPEN: + enable = true; + break; + default: return false; } @@ -2362,9 +2617,9 @@ Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles) Buffer * newBuffer = nullptr; try { newBuffer = checkAndLoadLyXFile(filename); - } catch (ExceptionMessage const & e) { + } catch (ExceptionMessage const &) { setBusy(false); - throw(e); + throw; } setBusy(false); @@ -2403,7 +2658,11 @@ void GuiView::openDocument(string const & fname) 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); @@ -2470,25 +2729,23 @@ static bool import(GuiView * lv, FileName const & filename, string loader_format; vector loaders = theConverters().loaders(); if (find(loaders.begin(), loaders.end(), format) == loaders.end()) { - vector::const_iterator it = loaders.begin(); - vector::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 @@ -2535,13 +2792,13 @@ void GuiView::importDocument(string const & argument) } 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)); @@ -2653,11 +2910,11 @@ void GuiView::newDocument(string const & filename, string templatefile, } -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)); @@ -2679,7 +2936,7 @@ void GuiView::insertLyXFile(docstring const & fname, bool ignorelang) QStringList(qt_("LyX Documents (*.lyx)"))); if (result.first == FileDialog::Later) - return; + return false; // FIXME UNICODE filename.set(fromqstr(result.second)); @@ -2688,12 +2945,13 @@ void GuiView::insertLyXFile(docstring const & fname, bool ignorelang) if (filename.empty()) { // emit message signal. message(_("Canceled.")); - return; + return false; } } bv->insertLyXFile(filename, ignorelang); bv->buffer().errors("Parse"); + return true; } @@ -2963,7 +3221,7 @@ bool GuiView::exportBufferAs(Buffer & b, docstring const & iformat) return false; // 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 " @@ -3070,7 +3328,9 @@ bool GuiView::closeWorkArea(GuiWorkArea * wa) " Tools->Preferences->Look&Feel->UserInterface\n" ), file); int ret = Alert::prompt(_("Close or hide document?"), - text, 0, 1, _("&Close"), _("&Hide")); + text, 0, 2, _("&Close"), _("&Hide"), _("&Cancel")); + if (ret == 2) + return false; close_buffer = (ret == 0); } } @@ -3107,6 +3367,14 @@ void GuiView::writeSession() const { bool GuiView::closeBufferAll() { + + for (auto & buf : theBufferList()) { + if (!saveBufferIfNeeded(*buf, false)) { + // Closing has been cancelled, so abort. + return false; + } + } + // Close the workareas in all other views QList const ids = guiApp->viewIds(); for (int i = 0; i != ids.size(); ++i) { @@ -3118,9 +3386,6 @@ bool GuiView::closeBufferAll() if (!closeWorkAreaAll()) return false; - // Now close the hidden buffers. We prevent hidden buffers from being - // dirty, so we can just close them. - theBufferList().closeAll(); return true; } @@ -3180,11 +3445,7 @@ bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer) 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; @@ -3209,12 +3470,13 @@ bool GuiView::closeBuffer(Buffer & buf) // Even in this case, children can be dirty (e.g., // after a label change in the master, see #11405). // Therefore, check this - if (closing_ && (child_buf->isClean() || child_buf->paragraphs().empty())) + if (closing_ && (child_buf->isClean() || child_buf->paragraphs().empty())) { // If we are in a close_event all children will be closed in some time, // so no need to do it here. This will ensure that the children end up // in the session file in the correct order. If we close the master // buffer, we can close or release the child buffers here too. continue; + } // Save dirty buffers also if closing_! if (saveBufferIfNeeded(*child_buf, false)) { child_buf->removeAutosaveFile(); @@ -3230,9 +3492,10 @@ bool GuiView::closeBuffer(Buffer & buf) 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 (size_t 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(); @@ -3434,10 +3697,7 @@ bool GuiView::reloadBuffer(Buffer & buf) 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."), @@ -3781,14 +4041,13 @@ Buffer::ExportStatus GuiView::GuiViewPrivate::previewAndDestroy( } -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; @@ -3824,7 +4083,7 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing( } 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 @@ -3981,7 +4240,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) _("Exporting ..."), &GuiViewPrivate::compileAndDestroy, &Buffer::doExport, - nullptr, cmd.allowAsync()); + nullptr, cmd.allowAsync(), true); break; } case LFUN_BUFFER_VIEW: { @@ -3999,7 +4258,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) docstring(), &GuiViewPrivate::compileAndDestroy, &Buffer::doExport, - nullptr, cmd.allowAsync()); + nullptr, cmd.allowAsync(), true); break; } case LFUN_MASTER_BUFFER_VIEW: { @@ -4094,10 +4353,11 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) 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; } @@ -4246,6 +4506,14 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) 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)) @@ -4270,12 +4538,11 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) 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; } @@ -4352,6 +4619,9 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) 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"); @@ -4470,13 +4740,13 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) if (zoom < static_cast(zoom_min_)) zoom = zoom_min_; - 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); + dr.screenUpdate(Update::ForceAll | Update::FitCursor); break; } @@ -4568,6 +4838,16 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) 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: @@ -4575,12 +4855,6 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) 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(); @@ -4611,15 +4885,26 @@ bool GuiView::lfunUiToggle(string const & ui_component) statusBar()->setVisible(!statusBar()->isVisible()); } else if (ui_component == "menubar") { menuBar()->setVisible(!menuBar()->isVisible()); - } else - if (ui_component == "frame") { + } else if (ui_component == "zoom") { + 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 == "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 @@ -4633,35 +4918,7 @@ bool GuiView::lfunUiToggle(string const & ui_component) void GuiView::toggleFullScreen() { - if (isFullScreen()) { - for (int i = 0; i != d.splitter_->count(); ++i) - d.tabWorkArea(i)->setFullScreen(false); - setContentsMargins(0, 0, 0, 0); - setWindowState(windowState() ^ Qt::WindowFullScreen); - restoreLayout(); - menuBar()->show(); - statusBar()->show(); - } else { - // bug 5274 - hideDialogs("prefs", nullptr); - for (int i = 0; i != d.splitter_->count(); ++i) - d.tabWorkArea(i)->setFullScreen(true); - setContentsMargins(-2, -2, -2, -2); - saveLayout(); - setWindowState(windowState() ^ Qt::WindowFullScreen); - if (lyxrc.full_screen_statusbar) - statusBar()->hide(); - 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) - it->second->hide(); - } - } - - // give dialogs like the TOC a chance to adapt - updateDialogs(); + setWindowState(windowState() ^ Qt::WindowFullScreen); } @@ -4763,6 +5020,19 @@ void GuiView::resetDialogs() } +void GuiView::flatGroupBoxes(const QObject * widget, bool flag) +{ + for (QObject * child: widget->children()) { + if (child->inherits("QGroupBox")) { + QGroupBox * box = (QGroupBox*) child; + box->setFlat(flag); + } else { + flatGroupBoxes(child, flag); + } + } +} + + Dialog * GuiView::findOrBuild(string const & name, bool hide_it) { if (!isValidName(name)) @@ -4778,6 +5048,11 @@ Dialog * GuiView::findOrBuild(string const & name, bool hide_it) 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) @@ -4816,13 +5091,14 @@ void GuiView::doShowDialog(QString const & qname, QString const & qdata, // 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; } @@ -4869,21 +5145,15 @@ void GuiView::disconnectDialog(string const & name) void GuiView::hideAll() const { - map::const_iterator it = d.dialogs_.begin(); - map::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::const_iterator it = d.dialogs_.begin(); - map::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); @@ -4895,134 +5165,10 @@ void GuiView::updateDialogs() 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); } @@ -5033,6 +5179,14 @@ SEMenu::SEMenu(QWidget * parent) parent, SLOT(disableShellEscape())); } + +void PressableSvgWidget::mousePressEvent(QMouseEvent * event) +{ + if (event->button() == Qt::LeftButton) { + Q_EMIT pressed(); + } +} + } // namespace frontend } // namespace lyx