]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiView.cpp
Use QFontMetrics information for underlines (and friends) width and position
[lyx.git] / src / frontends / qt4 / GuiView.cpp
index 5e8893bfc87770c210a7a5763ef3e327bf09be79..ed7835fcca2d419ebcf98da81f18b24c723d16e7 100644 (file)
@@ -32,6 +32,7 @@
 #include "TocModel.h"
 
 #include "qt_helpers.h"
+#include "support/filetools.h"
 
 #include "frontends/alert.h"
 #include "frontends/KeySymbol.h"
 #include <QSplitter>
 #include <QStackedWidget>
 #include <QStatusBar>
+#if QT_VERSION >= 0x050000
+#include <QSvgRenderer>
+#endif
 #include <QtConcurrentRun>
 #include <QTime>
 #include <QTimer>
@@ -149,7 +153,8 @@ namespace {
 class BackgroundWidget : public QWidget
 {
 public:
-       BackgroundWidget()
+       BackgroundWidget(int width, int height)
+               : width_(width), height_(height)
        {
                LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
                if (!lyxrc.show_banner)
@@ -157,32 +162,44 @@ public:
                /// The text to be written on top of the pixmap
                QString const text = lyx_version ?
                        qt_("version ") + lyx_version : qt_("unknown version");
+#if QT_VERSION >= 0x050000
+               QString imagedir = "images/";
+               FileName fname = imageLibFileSearch(imagedir, "banner", "svgz");
+               QSvgRenderer svgRenderer(toqstr(fname.absFileName()));
+               if (svgRenderer.isValid()) {
+                       splash_ = QPixmap(splashSize());
+                       QPainter painter(&splash_);
+                       svgRenderer.render(&painter);
+                       splash_.setDevicePixelRatio(pixelRatio());
+               } else {
+                       splash_ = getPixmap("images/", "banner", "png");
+               }
+#else
                splash_ = getPixmap("images/", "banner", "svgz,png");
+#endif
 
                QPainter pain(&splash_);
                pain.setPen(QColor(0, 0, 0));
-               double const multiplier = splashPixelRatio() / pixelRatio();
-               int const size = static_cast<int>(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble() * multiplier);
-               int const x = static_cast<int>(190 * multiplier);
-               int const y = static_cast<int>(225 * multiplier);
+               qreal const fsize = fontSize();
+               QPointF const position = textPosition();
                LYXERR(Debug::GUI,
                        "widget pixel ratio: " << pixelRatio() <<
                        " splash pixel ratio: " << splashPixelRatio() <<
-                       " version text size,position: " << size << "@" << x << "+" << y);
+                       " version text size,position: " << fsize << "@" << position.x() << "+" << position.y());
                QFont font;
                // The font used to display the version info
                font.setStyleHint(QFont::SansSerif);
                font.setWeight(QFont::Bold);
-               font.setPointSize(size);
+               font.setPointSizeF(fsize);
                pain.setFont(font);
-               pain.drawText(x, y, text);
+               pain.drawText(position, text);
                setFocusPolicy(Qt::StrongFocus);
        }
 
        void paintEvent(QPaintEvent *)
        {
-               int const w = static_cast<int>(splash_.width() / splashPixelRatio());
-               int const h = static_cast<int>(splash_.height() / splashPixelRatio());
+               int const w = width_;
+               int const h = height_;
                int const x = (width() - w) / 2;
                int const y = (height() - h) / 2;
                LYXERR(Debug::GUI,
@@ -207,6 +224,8 @@ public:
 
 private:
        QPixmap splash_;
+       int const width_;
+       int const height_;
 
        /// Current ratio between physical pixels and device-independent pixels
        double pixelRatio() const {
@@ -217,6 +236,20 @@ private:
 #endif
        }
 
+       qreal fontSize() const {
+               return toqstr(lyxrc.font_sizes[FONT_SIZE_NORMAL]).toDouble();
+       }
+
+       QPointF textPosition() const {
+               return QPointF(width_/2 - 18, height_/2 + 45);
+       }
+
+       QSize splashSize() const {
+               return QSize(
+                       static_cast<unsigned int>(width_ * pixelRatio()),
+                       static_cast<unsigned int>(height_ * pixelRatio()));
+       }
+
        /// Ratio between physical pixels and device-independent pixels of splash image
        double splashPixelRatio() const {
 #if QT_VERSION >= 0x050000
@@ -264,7 +297,7 @@ struct GuiView::GuiViewPrivate
                }
 
                splitter_ = new QSplitter;
-               bg_widget_ = new BackgroundWidget;
+               bg_widget_ = new BackgroundWidget(400, 250);
                stack_widget_ = new QStackedWidget;
                stack_widget_->addWidget(bg_widget_);
                stack_widget_->addWidget(splitter_);
@@ -475,7 +508,8 @@ QSet<Buffer const *> GuiView::GuiViewPrivate::busyBuffers;
 
 
 GuiView::GuiView(int id)
-       : d(*new GuiViewPrivate(this)), id_(id), closing_(false), busy_(0)
+       : d(*new GuiViewPrivate(this)), id_(id), closing_(false), busy_(0),
+         command_execute_(false)
 {
        // GuiToolbars *must* be initialised before the menu bar.
        normalSizedIcons(); // at least on Mac the default is 32 otherwise, which is huge
@@ -841,6 +875,16 @@ void GuiView::setFocus()
 }
 
 
+bool GuiView::hasFocus() const
+{
+       if (currentWorkArea())
+               return currentWorkArea()->hasFocus();
+       if (currentMainWorkArea())
+               return currentMainWorkArea()->hasFocus();
+       return d.bg_widget_->hasFocus();
+}
+
+
 void GuiView::focusInEvent(QFocusEvent * e)
 {
        LYXERR(Debug::DEBUG, "GuiView::focusInEvent()" << this);
@@ -1300,6 +1344,13 @@ void GuiView::setBusy(bool busy)
 }
 
 
+void GuiView::resetCommandExecute()
+{
+       command_execute_ = false;
+       updateToolbars();
+}
+
+
 double GuiView::pixelRatio() const
 {
 #if QT_VERSION >= 0x050000
@@ -1491,24 +1542,27 @@ void GuiView::updateToolbars()
 {
        ToolbarMap::iterator end = d.toolbars_.end();
        if (d.current_work_area_) {
-               bool const math =
-                       d.current_work_area_->bufferView().cursor().inMathed()
-                       && !d.current_work_area_->bufferView().cursor().inRegexped();
-               bool const table =
-                       lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
-               bool const review =
-                       lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
-                       lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onOff(true);
-               bool const mathmacrotemplate =
-                       lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
-               bool const ipa =
-                       lyx::getStatus(FuncRequest(LFUN_IN_IPA)).enabled();
+               int context = 0;
+               if (d.current_work_area_->bufferView().cursor().inMathed()
+                       && !d.current_work_area_->bufferView().cursor().inRegexped())
+                       context |= Toolbars::MATH;
+               if (lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled())
+                       context |= Toolbars::TABLE;
+               if (lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled()
+                       && lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onOff(true))
+                       context |= Toolbars::REVIEW;
+               if (lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled())
+                       context |= Toolbars::MATHMACROTEMPLATE;
+               if (lyx::getStatus(FuncRequest(LFUN_IN_IPA)).enabled())
+                       context |= Toolbars::IPA;
+               if (command_execute_)
+                       context |= Toolbars::MINIBUFFER;
 
                for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
-                       it->second->update(math, table, review, mathmacrotemplate, ipa);
+                       it->second->update(context);
        } else
                for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
-                       it->second->update(false, false, false, false, false);
+                       it->second->update();
 }
 
 
@@ -1699,6 +1753,21 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
        Buffer * doc_buffer = documentBufferView()
                ? &(documentBufferView()->buffer()) : 0;
 
+#ifdef Q_OS_MAC
+       /* In LyX/Mac, when a dialog is open, the menus of the
+          application can still be accessed without giving focus to
+          the main window. In this case, we want to disable the menu
+          entries that are buffer-related.
+          This code must not be used on Linux and Windows, since it
+          would disable buffer-related entries when hovering over the
+          menu (see bug #9574).
+        */
+       if (cmd.origin() == FuncRequest::MENU && !hasFocus()) {
+               buf = 0;
+               doc_buffer = 0;
+       }
+#endif
+
        // Check whether we need a buffer
        if (!lyxaction.funcHasFlag(cmd.action(), LyXAction::NoBuffer) && !buf) {
                // no, exit directly
@@ -1841,9 +1910,6 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                                || name == "texinfo"
                                || name == "progress"
                                || name == "compare";
-               else if (name == "print")
-                       enable = doc_buffer->params().isExportable("dvi")
-                               && lyxrc.print_command != "none";
                else if (name == "character" || name == "symbols"
                        || name == "mathdelimiter" || name == "mathmatrix") {
                        if (!buf || buf->isReadonly())
@@ -1921,6 +1987,9 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                enable = doc_buffer;
                break;
 
+       case LFUN_BUFFER_MOVE_NEXT:
+       case LFUN_BUFFER_MOVE_PREVIOUS:
+               // we do not cycle when moving
        case LFUN_BUFFER_NEXT:
        case LFUN_BUFFER_PREVIOUS:
                // because we cycle, it doesn't matter whether on first or last
@@ -2917,7 +2986,7 @@ bool GuiView::inOtherView(Buffer & buf)
 }
 
 
-void GuiView::gotoNextOrPreviousBuffer(NextOrPrevious np)
+void GuiView::gotoNextOrPreviousBuffer(NextOrPrevious np, bool const move)
 {
        if (!documentBufferView())
                return;
@@ -2932,7 +3001,10 @@ void GuiView::gotoNextOrPreviousBuffer(NextOrPrevious np)
                                        next_index = (i == nwa - 1 ? 0 : i + 1);
                                else
                                        next_index = (i == 0 ? nwa - 1 : i - 1);
-                               setBuffer(&workArea(next_index)->bufferView().buffer());
+                               if (move)
+                                       twa->moveTab(i, next_index);
+                               else
+                                       setBuffer(&workArea(next_index)->bufferView().buffer());
                                break;
                        }
                }
@@ -3546,22 +3618,23 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                }
 
                case LFUN_BUFFER_NEXT:
-                       gotoNextOrPreviousBuffer(NEXTBUFFER);
+                       gotoNextOrPreviousBuffer(NEXTBUFFER, false);
+                       break;
+
+               case LFUN_BUFFER_MOVE_NEXT:
+                       gotoNextOrPreviousBuffer(NEXTBUFFER, true);
                        break;
 
                case LFUN_BUFFER_PREVIOUS:
-                       gotoNextOrPreviousBuffer(PREVBUFFER);
+                       gotoNextOrPreviousBuffer(PREVBUFFER, false);
+                       break;
+
+               case LFUN_BUFFER_MOVE_PREVIOUS:
+                       gotoNextOrPreviousBuffer(PREVBUFFER, true);
                        break;
 
                case LFUN_COMMAND_EXECUTE: {
-                       bool const show_it = cmd.argument() != "off";
-                       // FIXME: this is a hack, "minibuffer" should not be
-                       // hardcoded.
-                       if (GuiToolbar * t = toolbar("minibuffer")) {
-                               t->setVisible(show_it);
-                               if (show_it && t->commandBuffer())
-                                       t->commandBuffer()->setFocus();
-                       }
+                       command_execute_ = true;
                        break;
                }
                case LFUN_DROP_LAYOUTS_CHOICE:
@@ -4357,8 +4430,6 @@ Dialog * GuiView::build(string const & name)
                return createGuiPhantom(*this);
        if (name == "prefs")
                return createGuiPreferences(*this);
-       if (name == "print")
-               return createGuiPrint(*this);
        if (name == "ref")
                return createGuiRef(*this);
        if (name == "sendto")