PageRenderTime 224ms CodeModel.GetById 80ms app.highlight 64ms RepoModel.GetById 77ms app.codeStats 0ms

/src/libtomahawk/playlist/topbar/lineedit.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 230 lines | 175 code | 28 blank | 27 comment | 25 complexity | c0d6f82ba1b1f555e2090b7917f29dab MD5 | raw file
  1/**
  2 * Copyright (c) 2008 - 2009, Benjamin C. Meyer  <ben@meyerhome.net>
  3 *
  4 * Redistribution and use in source and binary forms, with or without
  5 * modification, are permitted provided that the following conditions
  6 * are met:
  7 * 1. Redistributions of source code must retain the above copyright
  8 *    notice, this list of conditions and the following disclaimer.
  9 * 2. Redistributions in binary form must reproduce the above copyright
 10 *    notice, this list of conditions and the following disclaimer in the
 11 *    documentation and/or other materials provided with the distribution.
 12 * 3. Neither the name of the Benjamin Meyer nor the names of its contributors
 13 *    may be used to endorse or promote products derived from this software
 14 *    without specific prior written permission.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 26 * SUCH DAMAGE.
 27 */
 28
 29#include "lineedit.h"
 30#include "lineedit_p.h"
 31
 32#include <qevent.h>
 33#include <qlayout.h>
 34#include <qstyleoption.h>
 35#include <qpainter.h>
 36
 37SideWidget::SideWidget(QWidget *parent)
 38    : QWidget(parent)
 39{
 40}
 41
 42bool SideWidget::event(QEvent *event)
 43{
 44    if (event->type() == QEvent::LayoutRequest)
 45        emit sizeHintChanged();
 46    return QWidget::event(event);
 47}
 48
 49LineEdit::LineEdit(QWidget *parent)
 50    : QLineEdit(parent)
 51    , m_leftLayout(0)
 52    , m_rightLayout(0)
 53{
 54    init();
 55}
 56
 57LineEdit::LineEdit(const QString &contents, QWidget *parent)
 58    : QLineEdit(contents, parent)
 59    , m_leftWidget(0)
 60    , m_rightWidget(0)
 61    , m_leftLayout(0)
 62    , m_rightLayout(0)
 63{
 64    init();
 65}
 66
 67void LineEdit::init()
 68{
 69    m_leftWidget = new SideWidget(this);
 70    m_leftWidget->resize(0, 0);
 71    m_leftLayout = new QHBoxLayout(m_leftWidget);
 72    m_leftLayout->setContentsMargins(0, 0, 0, 0);
 73    if (isRightToLeft())
 74        m_leftLayout->setDirection(QBoxLayout::RightToLeft);
 75    else
 76        m_leftLayout->setDirection(QBoxLayout::LeftToRight);
 77    m_leftLayout->setSizeConstraint(QLayout::SetFixedSize);
 78
 79    m_rightWidget = new SideWidget(this);
 80    m_rightWidget->resize(0, 0);
 81    m_rightLayout = new QHBoxLayout(m_rightWidget);
 82    if (isRightToLeft())
 83        m_rightLayout->setDirection(QBoxLayout::RightToLeft);
 84    else
 85        m_rightLayout->setDirection(QBoxLayout::LeftToRight);
 86    m_rightLayout->setContentsMargins(0, 0, 0, 0);
 87
 88    QSpacerItem *horizontalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
 89    m_rightLayout->addItem(horizontalSpacer);
 90
 91    setWidgetSpacing(3);
 92    connect(m_leftWidget, SIGNAL(sizeHintChanged()),
 93            this, SLOT(updateTextMargins()));
 94    connect(m_rightWidget, SIGNAL(sizeHintChanged()),
 95            this, SLOT(updateTextMargins()));
 96}
 97
 98bool LineEdit::event(QEvent *event)
 99{
100    if (event->type() == QEvent::LayoutDirectionChange) {
101        if (isRightToLeft()) {
102            m_leftLayout->setDirection(QBoxLayout::RightToLeft);
103            m_rightLayout->setDirection(QBoxLayout::RightToLeft);
104        } else {
105            m_leftLayout->setDirection(QBoxLayout::LeftToRight);
106            m_rightLayout->setDirection(QBoxLayout::LeftToRight);
107        }
108    }
109    return QLineEdit::event(event);
110}
111
112void LineEdit::addWidget(QWidget *widget, WidgetPosition position)
113{
114    if (!widget)
115        return;
116
117    bool rtl = isRightToLeft();
118    if (rtl)
119        position = (position == LeftSide) ? RightSide : LeftSide;
120    if (position == LeftSide) {
121        m_leftLayout->addWidget(widget);
122    } else {
123        m_rightLayout->insertWidget(1, widget);
124    }
125}
126
127void LineEdit::removeWidget(QWidget *widget)
128{
129    if (!widget)
130        return;
131
132    m_leftLayout->removeWidget(widget);
133    m_rightLayout->removeWidget(widget);
134    widget->hide();
135}
136
137void LineEdit::setWidgetSpacing(int spacing)
138{
139    m_leftLayout->setSpacing(spacing);
140    m_rightLayout->setSpacing(spacing);
141    updateTextMargins();
142}
143
144int LineEdit::widgetSpacing() const
145{
146    return m_leftLayout->spacing();
147}
148
149int LineEdit::textMargin(WidgetPosition position) const
150{
151    int spacing = m_rightLayout->spacing();
152    int w = 0;
153    if (position == LeftSide)
154        w = m_leftWidget->sizeHint().width();
155    else
156        w = m_rightWidget->sizeHint().width();
157    if (w == 0)
158        return 0;
159    return w + spacing * 2;
160}
161
162void LineEdit::updateTextMargins()
163{
164    int left = textMargin(LineEdit::LeftSide);
165    int right = textMargin(LineEdit::RightSide);
166    int top = 0;
167    int bottom = 0;
168    setTextMargins(left, top, right, bottom);
169    updateSideWidgetLocations();
170}
171
172void LineEdit::updateSideWidgetLocations()
173{
174    QStyleOptionFrameV2 opt;
175    initStyleOption(&opt);
176    QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &opt, this);
177    int spacing = m_rightLayout->spacing();
178    textRect.adjust(spacing, 0, -spacing, 0);
179
180    int left = textMargin(LineEdit::LeftSide);
181
182    int midHeight = textRect.center().y() + 1;
183
184    if (m_leftLayout->count() > 0) {
185        int leftHeight = midHeight - m_leftWidget->height() / 2;
186        int leftWidth = m_leftWidget->width();
187        if (leftWidth == 0)
188            leftHeight = midHeight - m_leftWidget->sizeHint().height() / 2;
189        m_leftWidget->move(textRect.x(), leftHeight);
190    }
191    textRect.setX(left);
192    textRect.setY(midHeight - m_rightWidget->sizeHint().height() / 2);
193    textRect.setHeight(m_rightWidget->sizeHint().height());
194    m_rightWidget->setGeometry(textRect);
195}
196
197void LineEdit::resizeEvent(QResizeEvent *event)
198{
199    updateSideWidgetLocations();
200    QLineEdit::resizeEvent(event);
201}
202
203QString LineEdit::inactiveText() const
204{
205    return m_inactiveText;
206}
207
208void LineEdit::setInactiveText(const QString &text)
209{
210    m_inactiveText = text;
211}
212
213void LineEdit::paintEvent(QPaintEvent *event)
214{
215    QLineEdit::paintEvent(event);
216    if (text().isEmpty() && !m_inactiveText.isEmpty() && !hasFocus()) {
217        QStyleOptionFrameV2 panel;
218        initStyleOption(&panel);
219        QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
220        int horizontalMargin = 2;
221        textRect.adjust(horizontalMargin, 0, 0, 0);
222        int left = textMargin(LineEdit::LeftSide);
223        int right = textMargin(LineEdit::RightSide);
224        textRect.adjust(left, 0, -right, 0);
225        QPainter painter(this);
226        painter.setPen(palette().brush(QPalette::Disabled, QPalette::Text).color());
227        painter.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, m_inactiveText);
228    }
229}
230