]> git.lyx.org Git - features.git/commitdiff
Add a FancyLineEdit class. This code was taken from QtCreator and modified a little.
authorVincent van Ravesteijn <vfr@lyx.org>
Sun, 5 Jun 2011 17:51:02 +0000 (17:51 +0000)
committerVincent van Ravesteijn <vfr@lyx.org>
Sun, 5 Jun 2011 17:51:02 +0000 (17:51 +0000)
Patch from venom00.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@38957 a592a061-630c-0410-9148-cb99ea01b6c8

src/frontends/qt4/FancyLineEdit.cpp [new file with mode: 0644]
src/frontends/qt4/FancyLineEdit.h [new file with mode: 0644]
src/frontends/qt4/Makefile.am

diff --git a/src/frontends/qt4/FancyLineEdit.cpp b/src/frontends/qt4/FancyLineEdit.cpp
new file mode 100644 (file)
index 0000000..5c48d9f
--- /dev/null
@@ -0,0 +1,305 @@
+/**\r
+ * \file fancylineedit.cpp\r
+ * This file is part of LyX, the document processor.\r
+ * Licence details can be found in the file COPYING.\r
+ *\r
+ * \author Nokia Corporation (qt-info@nokia.com)\r
+ *\r
+ * Full author contact details are available in file CREDITS.\r
+ *\r
+ */\r
+\r
+// Code taken from the Qt Creator project and customized a little\r
+\r
+#include "FancyLineEdit.h"\r
+\r
+#include <QtCore/QEvent>\r
+#include <QtCore/QDebug>\r
+#include <QtCore/QString>\r
+#include <QtCore/QPropertyAnimation>\r
+#include <QtGui/QApplication>\r
+#include <QtGui/QMenu>\r
+#include <QtGui/QMouseEvent>\r
+#include <QtGui/QLabel>\r
+#include <QtGui/QAbstractButton>\r
+#include <QtGui/QPainter>\r
+#include <QtGui/QStyle>\r
+#include <QtGui/QPaintEvent>\r
+\r
+enum { margin = 6 };\r
+\r
+#define ICONBUTTON_HEIGHT 18\r
+#define FADE_TIME 160\r
+\r
+\r
+namespace lyx {\r
+namespace frontend {\r
+\r
+// --------- FancyLineEditPrivate\r
+class FancyLineEditPrivate : public QObject {\r
+public:\r
+    explicit FancyLineEditPrivate(FancyLineEdit *parent);\r
+\r
+    virtual bool eventFilter(QObject *obj, QEvent *event);\r
+\r
+    FancyLineEdit  *m_lineEdit;\r
+    QPixmap m_pixmap[2];\r
+    QMenu *m_menu[2];\r
+    bool m_menuTabFocusTrigger[2];\r
+    IconButton *m_iconbutton[2];\r
+    bool m_iconEnabled[2];\r
+};\r
+\r
+\r
+FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :\r
+    QObject(parent),\r
+    m_lineEdit(parent)\r
+{\r
+    for (int i = 0; i < 2; ++i) {\r
+        m_menu[i] = 0;\r
+        m_menuTabFocusTrigger[i] = false;\r
+        m_iconbutton[i] = new IconButton(parent);\r
+        m_iconbutton[i]->installEventFilter(this);\r
+        m_iconbutton[i]->hide();\r
+        m_iconbutton[i]->setAutoHide(false);\r
+        m_iconEnabled[i] = false;\r
+    }\r
+}\r
+\r
+bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)\r
+{\r
+    int buttonIndex = -1;\r
+    for (int i = 0; i < 2; ++i) {\r
+        if (obj == m_iconbutton[i]) {\r
+            buttonIndex = i;\r
+            break;\r
+        }\r
+    }\r
+    if (buttonIndex == -1)\r
+        return QObject::eventFilter(obj, event);\r
+    switch (event->type()) {\r
+    case QEvent::FocusIn:\r
+        if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {\r
+            m_lineEdit->setFocus();\r
+            m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(\r
+                    m_iconbutton[buttonIndex]->rect().center()));\r
+            return true;\r
+        }\r
+    default:\r
+        break;\r
+    }\r
+    return QObject::eventFilter(obj, event);\r
+}\r
+\r
+\r
+// --------- FancyLineEdit\r
+FancyLineEdit::FancyLineEdit(QWidget *parent) :\r
+    QLineEdit(parent),\r
+    m_d(new FancyLineEditPrivate(this))\r
+{\r
+    ensurePolished();\r
+    updateMargins();\r
+\r
+    connect(this, SIGNAL(textChanged(QString)), this, SLOT(checkButtons(QString)));\r
+    connect(m_d->m_iconbutton[Left], SIGNAL(clicked()), this, SLOT(iconClicked()));\r
+    connect(m_d->m_iconbutton[Right], SIGNAL(clicked()), this, SLOT(iconClicked()));\r
+}\r
+\r
+void FancyLineEdit::checkButtons(const QString &text)\r
+{\r
+    if (m_oldText.isEmpty() || text.isEmpty()) {\r
+        for (int i = 0; i < 2; ++i) {\r
+            if (m_d->m_iconbutton[i]->hasAutoHide())\r
+                m_d->m_iconbutton[i]->animateShow(!text.isEmpty());\r
+        }\r
+        m_oldText = text;\r
+    }\r
+}\r
+\r
+FancyLineEdit::~FancyLineEdit()\r
+{\r
+}\r
+\r
+void FancyLineEdit::setButtonVisible(Side side, bool visible)\r
+{\r
+    m_d->m_iconbutton[side]->setVisible(visible);\r
+    m_d->m_iconEnabled[side] = visible;\r
+    updateMargins();\r
+}\r
+\r
+bool FancyLineEdit::isButtonVisible(Side side) const\r
+{\r
+    return m_d->m_iconEnabled[side];\r
+}\r
+\r
+void FancyLineEdit::iconClicked()\r
+{\r
+    IconButton *button = qobject_cast<IconButton *>(sender());\r
+    int index = -1;\r
+    for (int i = 0; i < 2; ++i)\r
+        if (m_d->m_iconbutton[i] == button)\r
+            index = i;\r
+    if (index == -1)\r
+        return;\r
+    if (m_d->m_menu[index]) {\r
+        m_d->m_menu[index]->exec(QCursor::pos());\r
+    } else {\r
+               buttonClicked((Side)index);\r
+        if (index == Left)\r
+                       leftButtonClicked();\r
+        else if (index == Right)\r
+                       rightButtonClicked();\r
+    }\r
+}\r
+\r
+void FancyLineEdit::updateMargins()\r
+{\r
+    bool leftToRight = (layoutDirection() == Qt::LeftToRight);\r
+    Side realLeft = (leftToRight ? Left : Right);\r
+    Side realRight = (leftToRight ? Right : Left);\r
+\r
+    int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;\r
+    int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;\r
+    // Note KDE does not reserve space for the highlight color\r
+    if (style()->inherits("OxygenStyle")) {\r
+        leftMargin = qMax(24, leftMargin);\r
+        rightMargin = qMax(24, rightMargin);\r
+    }\r
+\r
+    QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,\r
+                     (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);\r
+\r
+    setTextMargins(margins);\r
+}\r
+\r
+void FancyLineEdit::updateButtonPositions()\r
+{\r
+    QRect contentRect = rect();\r
+    for (int i = 0; i < 2; ++i) {\r
+        Side iconpos = (Side)i;\r
+        if (layoutDirection() == Qt::RightToLeft)\r
+            iconpos = (iconpos == Left ? Right : Left);\r
+\r
+        if (iconpos == FancyLineEdit::Right) {\r
+            const int iconoffset = textMargins().right() + 4;\r
+            m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0));\r
+        } else {\r
+            const int iconoffset = textMargins().left() + 4;\r
+            m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0));\r
+        }\r
+    }\r
+}\r
+\r
+void FancyLineEdit::resizeEvent(QResizeEvent *)\r
+{\r
+    updateButtonPositions();\r
+}\r
+\r
+void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)\r
+{\r
+    m_d->m_iconbutton[side]->setPixmap(buttonPixmap);\r
+    updateMargins();\r
+    updateButtonPositions();\r
+    update();\r
+}\r
+\r
+QPixmap FancyLineEdit::buttonPixmap(Side side) const\r
+{\r
+    return m_d->m_pixmap[side];\r
+}\r
+\r
+void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)\r
+{\r
+     m_d->m_menu[side] = buttonMenu;\r
+     m_d->m_iconbutton[side]->setIconOpacity(1.0);\r
+ }\r
+\r
+QMenu *FancyLineEdit::buttonMenu(Side side) const\r
+{\r
+    return  m_d->m_menu[side];\r
+}\r
+\r
+bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const\r
+{\r
+    return m_d->m_menuTabFocusTrigger[side];\r
+}\r
+\r
+void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)\r
+{\r
+    if (m_d->m_menuTabFocusTrigger[side] == v)\r
+        return;\r
+\r
+    m_d->m_menuTabFocusTrigger[side] = v;\r
+    m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);\r
+}\r
+\r
+bool FancyLineEdit::hasAutoHideButton(Side side) const\r
+{\r
+    return m_d->m_iconbutton[side]->hasAutoHide();\r
+}\r
+\r
+void FancyLineEdit::setAutoHideButton(Side side, bool h)\r
+{\r
+    m_d->m_iconbutton[side]->setAutoHide(h);\r
+    if (h)\r
+        m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ?  0.0 : 1.0);\r
+    else\r
+        m_d->m_iconbutton[side]->setIconOpacity(1.0);\r
+}\r
+\r
+void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)\r
+{\r
+    m_d->m_iconbutton[side]->setToolTip(tip);\r
+}\r
+\r
+void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)\r
+{\r
+    m_d->m_iconbutton[side]->setFocusPolicy(policy);\r
+}\r
+\r
+// IconButton - helper class to represent a clickable icon\r
+\r
+IconButton::IconButton(QWidget *parent)\r
+    : QAbstractButton(parent), m_autoHide(false)\r
+{\r
+    setCursor(Qt::ArrowCursor);\r
+    setFocusPolicy(Qt::NoFocus);\r
+}\r
+\r
+void IconButton::paintEvent(QPaintEvent *)\r
+{\r
+    QPainter painter(this);\r
+    // Note isDown should really use the active state but in most styles\r
+    // this has no proper feedback\r
+    QIcon::Mode state = QIcon::Disabled;\r
+    if (isEnabled())\r
+        state = isDown() ? QIcon::Selected : QIcon::Normal;\r
+    QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());\r
+    pixmapRect.moveCenter(rect().center());\r
+\r
+    if (m_autoHide)\r
+        painter.setOpacity(m_iconOpacity);\r
+\r
+    painter.drawPixmap(pixmapRect, m_pixmap);\r
+}\r
+\r
+void IconButton::animateShow(bool visible)\r
+{\r
+    if (visible) {\r
+        QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");\r
+        animation->setDuration(FADE_TIME);\r
+        animation->setEndValue(1.0);\r
+        animation->start(QAbstractAnimation::DeleteWhenStopped);\r
+    } else {\r
+        QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");\r
+        animation->setDuration(FADE_TIME);\r
+        animation->setEndValue(0.0);\r
+        animation->start(QAbstractAnimation::DeleteWhenStopped);\r
+    }\r
+}\r
+\r
+}\r
+\r
+}\r
+\r
+#include "moc_FancyLineEdit.cpp"\r
diff --git a/src/frontends/qt4/FancyLineEdit.h b/src/frontends/qt4/FancyLineEdit.h
new file mode 100644 (file)
index 0000000..dbf216f
--- /dev/null
@@ -0,0 +1,111 @@
+/**\r
+ * \file fancylineedit.h\r
+ * This file is part of LyX, the document processor.\r
+ * Licence details can be found in the file COPYING.\r
+ *\r
+ * \author Nokia Corporation (qt-info@nokia.com)\r
+ *\r
+ * Full author contact details are available in file CREDITS.\r
+ *\r
+ */\r
+\r
+// Code taken from the Qt Creator project and customized a little\r
+\r
+#ifndef FANCYLINEEDIT_H\r
+#define FANCYLINEEDIT_H\r
+\r
+#include <QtGui/QLineEdit>\r
+#include <QtGui/QAbstractButton>\r
+\r
+namespace lyx {\r
+namespace frontend {\r
+\r
+class FancyLineEditPrivate;\r
+\r
+class IconButton: public QAbstractButton\r
+{\r
+       Q_OBJECT\r
+       Q_PROPERTY(float iconOpacity READ iconOpacity WRITE setIconOpacity)\r
+       Q_PROPERTY(bool autoHide READ hasAutoHide WRITE setAutoHide)\r
+       Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)\r
+public:\r
+    explicit IconButton(QWidget *parent = 0);\r
+    void paintEvent(QPaintEvent *event);\r
+    void setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; update(); }\r
+    QPixmap pixmap() const { return m_pixmap; }\r
+    float iconOpacity() { return m_iconOpacity; }\r
+    void setIconOpacity(float value) { m_iconOpacity = value; update(); }\r
+    void animateShow(bool visible);\r
+\r
+    void setAutoHide(bool hide) { m_autoHide = hide; }\r
+    bool hasAutoHide() const { return m_autoHide; }\r
+private:\r
+    float m_iconOpacity;\r
+    bool m_autoHide;\r
+    QPixmap m_pixmap;\r
+};\r
+\r
+\r
+/* A line edit with an embedded pixmap on one side that is connected to\r
+ * a menu. Additionally, it can display a grayed hintText (like "Type Here to")\r
+ * when not focused and empty. When connecting to the changed signals and\r
+ * querying text, one has to be aware that the text is set to that hint\r
+ * text if isShowingHintText() returns true (that is, does not contain\r
+ * valid user input).\r
+ */\r
+class FancyLineEdit : public QLineEdit\r
+{\r
+       Q_DISABLE_COPY(FancyLineEdit)\r
+       Q_OBJECT\r
+       Q_ENUMS(Side)\r
+\r
+public:\r
+    enum Side {Left = 0, Right = 1};\r
+\r
+    explicit FancyLineEdit(QWidget *parent = 0);\r
+    ~FancyLineEdit();\r
+\r
+    QPixmap buttonPixmap(Side side) const;\r
+    void setButtonPixmap(Side side, const QPixmap &pixmap);\r
+\r
+    QMenu *buttonMenu(Side side) const;\r
+    void setButtonMenu(Side side, QMenu *menu);\r
+\r
+    void setButtonVisible(Side side, bool visible);\r
+    bool isButtonVisible(Side side) const;\r
+\r
+    void setButtonToolTip(Side side, const QString &);\r
+    void setButtonFocusPolicy(Side side, Qt::FocusPolicy policy);\r
+\r
+    // Set whether tabbing in will trigger the menu.\r
+    void setMenuTabFocusTrigger(Side side, bool v);\r
+    bool hasMenuTabFocusTrigger(Side side) const;\r
+\r
+    // Set if icon should be hidden when text is empty\r
+    void setAutoHideButton(Side side, bool h);\r
+    bool hasAutoHideButton(Side side) const;\r
+\r
+Q_SIGNALS:\r
+       void buttonClicked(Side side);\r
+    void leftButtonClicked();\r
+    void rightButtonClicked();\r
+\r
+private Q_SLOTS:\r
+    void checkButtons(const QString &);\r
+    void iconClicked();\r
+\r
+protected:\r
+    virtual void resizeEvent(QResizeEvent *e);\r
+\r
+private:\r
+    void updateMargins();\r
+       void updateButtonPositions();\r
+\r
+    FancyLineEditPrivate *m_d;\r
+    QString m_oldText;\r
+};\r
+\r
+}\r
+}\r
+\r
+#endif // FANCYLINEEDIT_H\r
index 299e3ca9e7ab78b18605be770951f589cf9f7380..e1129162701548d3c01db26bfbd6332d35a2128b 100644 (file)
@@ -58,6 +58,7 @@ SOURCEFILES = \
        ColorCache.cpp \
        CustomizedWidgets.cpp \
        EmptyTable.cpp \
+       FancyLineEdit.cpp \
        FileDialog.cpp \
        FindAndReplace.cpp \
        FloatPlacement.cpp \
@@ -173,6 +174,7 @@ MOCHEADER = \
        BulletsModule.h \
        CustomizedWidgets.h \
        EmptyTable.h \
+       FancyLineEdit.h \
        FindAndReplace.h \
        FloatPlacement.h \
        GuiAbout.h \