]> git.lyx.org Git - features.git/blobdiff - src/frontends/qt/FancyLineEdit.cpp
Show suggestions containing the input in the command buffer
[features.git] / src / frontends / qt / FancyLineEdit.cpp
index b8d761bf49cd8ee47ea8b8115a707df6940b6b89..b9874d2e89389a25e7b9ea2c6986544843b4bcbe 100644 (file)
 
 #include "FancyLineEdit.h"
 
+#if QT_VERSION < 0x050200
+#include "GuiApplication.h"
+#endif
+
 #if QT_VERSION >= 0x040600
 
 #include <QEvent>
@@ -29,6 +33,9 @@
 #include <QPainter>
 #include <QStyle>
 #include <QPaintEvent>
+#if QT_VERSION >= 0x050000
+#include <QWindow>
+#endif
 
 enum { margin = 6 };
 
@@ -39,165 +46,203 @@ enum { margin = 6 };
 namespace lyx {
 namespace frontend {
 
-// --------- FancyLineEditPrivate
+////////////////////////////////////////////////////////////////////////
+//
+// FancyLineEditPrivate
+//
+////////////////////////////////////////////////////////////////////////
+
 class FancyLineEditPrivate : public QObject {
 public:
-    explicit FancyLineEditPrivate(FancyLineEdit *parent);
+       explicit FancyLineEditPrivate(FancyLineEdit *parent);
 
-    bool eventFilter(QObject *obj, QEvent *event) override;
+       bool eventFilter(QObject *obj, QEvent *event) override;
 
-    FancyLineEdit  *m_lineEdit;
-    QPixmap m_pixmap[2];
-    QMenu *m_menu[2];
-    bool m_menuTabFocusTrigger[2];
-    IconButton *m_iconbutton[2];
-    bool m_iconEnabled[2];
+       FancyLineEdit  *m_lineEdit;
+       QPixmap m_pixmap[2];
+       QMenu *m_menu[2];
+       bool m_menuTabFocusTrigger[2];
+       IconButton *m_iconbutton[2];
+       bool m_iconEnabled[2];
 };
 
 
-FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
-    QObject(parent),
-    m_lineEdit(parent)
+FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent)
+       : QObject(parent), m_lineEdit(parent)
 {
-    for (int i = 0; i < 2; ++i) {
-        m_menu[i] = nullptr;
-        m_menuTabFocusTrigger[i] = false;
-        m_iconbutton[i] = new IconButton(parent);
-        m_iconbutton[i]->installEventFilter(this);
-        m_iconbutton[i]->hide();
-        m_iconbutton[i]->setAutoHide(false);
-        m_iconEnabled[i] = false;
-    }
+       for (int i = 0; i < 2; ++i) {
+               m_menu[i] = nullptr;
+               m_menuTabFocusTrigger[i] = false;
+               m_iconbutton[i] = new IconButton(parent);
+               m_iconbutton[i]->installEventFilter(this);
+               m_iconbutton[i]->hide();
+               m_iconbutton[i]->setAutoHide(false);
+               m_iconEnabled[i] = false;
+       }
 }
 
+
 bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
 {
-    int buttonIndex = -1;
-    for (int i = 0; i < 2; ++i) {
-        if (obj == m_iconbutton[i]) {
-            buttonIndex = i;
-            break;
-        }
-    }
-    if (buttonIndex == -1)
-        return QObject::eventFilter(obj, event);
-    switch (event->type()) {
-    case QEvent::FocusIn:
-        if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
-            m_lineEdit->setFocus();
-            m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
-                    m_iconbutton[buttonIndex]->rect().center()));
-            return true;
-        }
-    default:
-        break;
-    }
-    return QObject::eventFilter(obj, event);
+       int buttonIndex = -1;
+       for (int i = 0; i < 2; ++i) {
+               if (obj == m_iconbutton[i]) {
+                       buttonIndex = i;
+                       break;
+               }
+       }
+       if (buttonIndex == -1)
+               return QObject::eventFilter(obj, event);
+       switch (event->type()) {
+       case QEvent::FocusIn:
+               if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
+                       m_lineEdit->setFocus();
+                       m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
+                                                         m_iconbutton[buttonIndex]->rect().center()));
+                       return true;
+               }
+       default:
+               break;
+       }
+       return QObject::eventFilter(obj, event);
 }
 
 
-// --------- FancyLineEdit
+////////////////////////////////////////////////////////////////////////
+//
+// FancyLineEdit
+//
+////////////////////////////////////////////////////////////////////////
+
 FancyLineEdit::FancyLineEdit(QWidget *parent) :
     QLineEdit(parent),
     m_d(new FancyLineEditPrivate(this))
 {
-    ensurePolished();
-    updateMargins();
-
-    connect(this, SIGNAL(textChanged(QString)),
-            this, SLOT(checkButtons(QString)));
-    connect(m_d->m_iconbutton[Left], SIGNAL(clicked()),
-            this, SLOT(iconClicked()));
-    connect(m_d->m_iconbutton[Right], SIGNAL(clicked()),
-            this, SLOT(iconClicked()));
+       ensurePolished();
+       updateMargins();
+       
+       connect(this, SIGNAL(textChanged(QString)),
+               this, SLOT(checkButtons(QString)));
+       connect(m_d->m_iconbutton[Left], SIGNAL(clicked()),
+               this, SLOT(iconClicked()));
+       connect(m_d->m_iconbutton[Right], SIGNAL(clicked()),
+               this, SLOT(iconClicked()));
 }
 
+
 void FancyLineEdit::checkButtons(const QString &text)
 {
-    if (m_oldText.isEmpty() || text.isEmpty()) {
-        for (int i = 0; i < 2; ++i) {
-            if (m_d->m_iconbutton[i]->hasAutoHide())
-                m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
-        }
-        m_oldText = text;
-    }
+       if (m_oldText.isEmpty() || text.isEmpty()) {
+               for (int i = 0; i < 2; ++i) {
+                       if (m_d->m_iconbutton[i]->hasAutoHide())
+                               m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
+               }
+               m_oldText = text;
+       }
 }
 
+
+void FancyLineEdit::setClearButton(bool visible)
+{
+// QLineEdit::setClearButtonEnabled() has been implemented in Qt 5.2.
+// In earlier Qt versions, we roll our own button
+#if QT_VERSION < 0x050200
+       setButtonPixmap(FancyLineEdit::Right, getPixmap("images/", "editclear", "svgz,png"));
+       setButtonVisible(FancyLineEdit::Right, visible);
+       setAutoHideButton(FancyLineEdit::Right, true);
+#else
+       setClearButtonEnabled(visible);
+#endif
+}
+
+
 void FancyLineEdit::setButtonVisible(Side side, bool visible)
 {
-    m_d->m_iconbutton[side]->setVisible(visible);
-    m_d->m_iconEnabled[side] = visible;
-    updateMargins();
+       m_d->m_iconbutton[side]->setVisible(visible);
+       m_d->m_iconEnabled[side] = visible;
+       updateMargins();
 }
 
+
 bool FancyLineEdit::isButtonVisible(Side side) const
 {
-    return m_d->m_iconEnabled[side];
+       return m_d->m_iconEnabled[side];
 }
 
+
 void FancyLineEdit::iconClicked()
 {
-    IconButton *button = qobject_cast<IconButton *>(sender());
-    int index = -1;
-    for (int i = 0; i < 2; ++i)
-        if (m_d->m_iconbutton[i] == button)
-            index = i;
-    if (index == -1)
-        return;
-    if (m_d->m_menu[index]) {
-        m_d->m_menu[index]->exec(QCursor::pos());
-    } else {
+       IconButton *button = qobject_cast<IconButton *>(sender());
+       int index = -1;
+       for (int i = 0; i < 2; ++i)
+               if (m_d->m_iconbutton[i] == button)
+                       index = i;
+       if (index == -1)
+               return;
+       if (m_d->m_menu[index]) {
+               m_d->m_menu[index]->exec(QCursor::pos());
+       } else {
                buttonClicked((Side)index);
-        if (index == Left)
+               if (index == Left)
                        leftButtonClicked();
-        else if (index == Right)
+               else if (index == Right)
                        rightButtonClicked();
-    }
+       }
 }
 
+
 void FancyLineEdit::updateMargins()
 {
-    bool leftToRight = (layoutDirection() == Qt::LeftToRight);
-    Side realLeft = (leftToRight ? Left : Right);
-    Side realRight = (leftToRight ? Right : Left);
-
-    int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;
-    int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;
-    // Note KDE does not reserve space for the highlight color
-    if (style()->inherits("OxygenStyle")) {
-        leftMargin = qMax(24, leftMargin);
-        rightMargin = qMax(24, rightMargin);
-    }
-
-    QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
-                     (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
-
-    setTextMargins(margins);
+       bool leftToRight = (layoutDirection() == Qt::LeftToRight);
+       Side realLeft = (leftToRight ? Left : Right);
+       Side realRight = (leftToRight ? Right : Left);
+
+       qreal dpr = 1.0;
+#if QT_VERSION >= 0x050000
+       // Consider device/pixel ratio (HiDPI)
+       dpr = devicePixelRatio();
+#endif
+       int leftMargin = (m_d->m_iconbutton[realLeft]->pixmap().width() / dpr ) + 8;
+       int rightMargin = (m_d->m_iconbutton[realRight]->pixmap().width() / dpr) + 8;
+       // Note KDE does not reserve space for the highlight color
+       if (style()->inherits("OxygenStyle")) {
+               leftMargin = qMax(24, leftMargin);
+               rightMargin = qMax(24, rightMargin);
+       }
+
+       QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
+                        (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
+
+       setTextMargins(margins);
 }
 
+
 void FancyLineEdit::updateButtonPositions()
 {
-    QRect contentRect = rect();
-    for (int i = 0; i < 2; ++i) {
-        Side iconpos = (Side)i;
-        if (layoutDirection() == Qt::RightToLeft)
-            iconpos = (iconpos == Left ? Right : Left);
-
-        if (iconpos == FancyLineEdit::Right) {
-            const int iconoffset = textMargins().right() + 4;
-            m_d->m_iconbutton[i]->
-                   setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0));
-        } else {
-            const int iconoffset = textMargins().left() + 4;
-            m_d->m_iconbutton[i]->
-                   setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0));
-        }
-    }
+       QRect contentRect = rect();
+       for (int i = 0; i < 2; ++i) {
+               Side iconpos = (Side)i;
+               if (layoutDirection() == Qt::RightToLeft)
+                       iconpos = (iconpos == Left ? Right : Left);
+               
+               if (iconpos == FancyLineEdit::Right) {
+                       const int iconoffset = textMargins().right() + 4;
+                       m_d->m_iconbutton[i]->setGeometry(
+                                               contentRect.adjusted(width() - iconoffset,
+                                                                    0, 0, 0));
+               } else {
+                       const int iconoffset = textMargins().left() + 4;
+                       m_d->m_iconbutton[i]->setGeometry(
+                                               contentRect.adjusted(0, 0,
+                                                                    -width() + iconoffset, 0));
+               }
+       }
 }
 
+
 void FancyLineEdit::resizeEvent(QResizeEvent *)
 {
-    updateButtonPositions();
+       updateButtonPositions();
 }
 
 
@@ -212,102 +257,124 @@ void FancyLineEdit::keyPressEvent(QKeyEvent * e)
 
 void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
 {
-    m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
-    updateMargins();
-    updateButtonPositions();
-    update();
+       m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
+       updateMargins();
+       updateButtonPositions();
+       update();
 }
 
+
 QPixmap FancyLineEdit::buttonPixmap(Side side) const
 {
-    return m_d->m_pixmap[side];
+       return m_d->m_pixmap[side];
 }
 
+
 void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
 {
-     m_d->m_menu[side] = buttonMenu;
-     m_d->m_iconbutton[side]->setIconOpacity(1.0);
- }
+       m_d->m_menu[side] = buttonMenu;
+       m_d->m_iconbutton[side]->setIconOpacity(1.0);
+}
 
 QMenu *FancyLineEdit::buttonMenu(Side side) const
 {
-    return  m_d->m_menu[side];
+       return  m_d->m_menu[side];
 }
 
+
 bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
 {
-    return m_d->m_menuTabFocusTrigger[side];
+       return m_d->m_menuTabFocusTrigger[side];
 }
 
+
 void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
 {
-    if (m_d->m_menuTabFocusTrigger[side] == v)
-        return;
+       if (m_d->m_menuTabFocusTrigger[side] == v)
+               return;
 
-    m_d->m_menuTabFocusTrigger[side] = v;
-    m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
+       m_d->m_menuTabFocusTrigger[side] = v;
+       m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
 }
 
+
 bool FancyLineEdit::hasAutoHideButton(Side side) const
 {
-    return m_d->m_iconbutton[side]->hasAutoHide();
+       return m_d->m_iconbutton[side]->hasAutoHide();
 }
 
+
 void FancyLineEdit::setAutoHideButton(Side side, bool h)
 {
-    m_d->m_iconbutton[side]->setAutoHide(h);
-    if (h)
-        m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ?  0.0 : 1.0);
-    else
-        m_d->m_iconbutton[side]->setIconOpacity(1.0);
+       m_d->m_iconbutton[side]->setAutoHide(h);
+       if (h)
+               m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ?  0.0 : 1.0);
+       else
+               m_d->m_iconbutton[side]->setIconOpacity(1.0);
 }
 
+
 void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
 {
-    m_d->m_iconbutton[side]->setToolTip(tip);
+       m_d->m_iconbutton[side]->setToolTip(tip);
 }
 
+
 void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
 {
-    m_d->m_iconbutton[side]->setFocusPolicy(policy);
+       m_d->m_iconbutton[side]->setFocusPolicy(policy);
 }
 
+
+////////////////////////////////////////////////////////////////////////
+//
 // IconButton - helper class to represent a clickable icon
+//
+////////////////////////////////////////////////////////////////////////
 
 IconButton::IconButton(QWidget *parent)
-    : QAbstractButton(parent), m_iconOpacity(0.0), m_autoHide(false)
+       : QAbstractButton(parent), m_iconOpacity(0.0), m_autoHide(false)
 {
-    setCursor(Qt::ArrowCursor);
-    setFocusPolicy(Qt::NoFocus);
+       setCursor(Qt::ArrowCursor);
+       setFocusPolicy(Qt::NoFocus);
 }
 
+
 void IconButton::paintEvent(QPaintEvent *)
 {
-    QPainter painter(this);
-    QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
-    pixmapRect.moveCenter(rect().center());
-
-    if (m_autoHide)
-        painter.setOpacity(m_iconOpacity);
-
-    painter.drawPixmap(pixmapRect, m_pixmap);
+       qreal dpr = 1.0;
+#if QT_VERSION >= 0x050000
+       // Consider device/pixel ratio (HiDPI)
+       QWindow * window = this->window()->windowHandle();
+       dpr = window->devicePixelRatio();
+#endif
+       QRect pixmapRect(QPoint(), m_pixmap.size() / dpr);
+       pixmapRect.moveCenter(rect().center());
+       QPixmap pm = m_pixmap;
+
+       QPainter painter(this);
+       if (m_autoHide)
+               painter.setOpacity(m_iconOpacity);
+
+       painter.drawPixmap(pixmapRect, pm);
 }
 
+
 void IconButton::animateShow(bool visible)
 {
-    if (visible) {
-        QPropertyAnimation *animation =
-               new QPropertyAnimation(this, "iconOpacity");
-        animation->setDuration(FADE_TIME);
-        animation->setEndValue(1.0);
-        animation->start(QAbstractAnimation::DeleteWhenStopped);
-    } else {
-        QPropertyAnimation *animation =
-               new QPropertyAnimation(this, "iconOpacity");
-        animation->setDuration(FADE_TIME);
-        animation->setEndValue(0.0);
-        animation->start(QAbstractAnimation::DeleteWhenStopped);
-    }
+       if (visible) {
+               QPropertyAnimation *animation =
+                       new QPropertyAnimation(this, "iconOpacity");
+               animation->setDuration(FADE_TIME);
+               animation->setEndValue(1.0);
+               animation->start(QAbstractAnimation::DeleteWhenStopped);
+       } else {
+               QPropertyAnimation *animation =
+                       new QPropertyAnimation(this, "iconOpacity");
+               animation->setDuration(FADE_TIME);
+               animation->setEndValue(0.0);
+               animation->start(QAbstractAnimation::DeleteWhenStopped);
+       }
 }
 
 } // namespace frontend