1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2015 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 **************************************************************************/
19 
20 #include "ColorWidget.h"
21 #include "LineEditWidget.h"
22 #include "../core/ThemesManager.h"
23 
24 #include <QtGui/QClipboard>
25 #include <QtGui/QMouseEvent>
26 #include <QtGui/QPainter>
27 #include <QtWidgets/QApplication>
28 #include <QtWidgets/QColorDialog>
29 #include <QtWidgets/QHBoxLayout>
30 #include <QtWidgets/QMenu>
31 
32 namespace Otter
33 {
34 
ColorWidget(QWidget * parent)35 ColorWidget::ColorWidget(QWidget *parent) : QWidget(parent),
36 	m_lineEditWidget(new LineEditWidget(this))
37 {
38 	QHBoxLayout *layout(new QHBoxLayout(this));
39 	layout->addWidget(m_lineEditWidget);
40 	layout->setContentsMargins((m_lineEditWidget->height() + 2), 0, 0, 0);
41 
42 	setLayout(layout);
43 	setFocusPolicy(Qt::StrongFocus);
44 	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
45 	setColor(QColor());
46 
47 	connect(m_lineEditWidget, &LineEditWidget::textChanged, this, &ColorWidget::updateColor);
48 }
49 
changeEvent(QEvent * event)50 void ColorWidget::changeEvent(QEvent *event)
51 {
52 	QWidget::changeEvent(event);
53 
54 	if (event->type() == QEvent::LanguageChange && !m_color.isValid())
55 	{
56 		setToolTip(tr("Invalid"));
57 	}
58 }
59 
paintEvent(QPaintEvent * event)60 void ColorWidget::paintEvent(QPaintEvent *event)
61 {
62 	Q_UNUSED(event)
63 
64 	QPainter painter(this);
65 	painter.setRenderHints(QPainter::Antialiasing);
66 
67 	drawThumbnail(&painter, m_color, palette(), m_buttonRectangle);
68 }
69 
resizeEvent(QResizeEvent * event)70 void ColorWidget::resizeEvent(QResizeEvent *event)
71 {
72 	QWidget::resizeEvent(event);
73 
74 	layout()->setContentsMargins((m_lineEditWidget->height() + 2), 0, 0, 0);
75 
76 	m_buttonRectangle = rect();
77 
78 	if (isLeftToRight())
79 	{
80 		m_buttonRectangle.setRight(m_lineEditWidget->height());
81 	}
82 	else
83 	{
84 		m_buttonRectangle.setLeft(m_buttonRectangle.right() - m_lineEditWidget->height());
85 	}
86 
87 	m_buttonRectangle.adjust(2, 2, -2, -2);
88 }
89 
focusInEvent(QFocusEvent * event)90 void ColorWidget::focusInEvent(QFocusEvent *event)
91 {
92 	QWidget::focusInEvent(event);
93 
94 	m_lineEditWidget->setFocus();
95 }
96 
mouseReleaseEvent(QMouseEvent * event)97 void ColorWidget::mouseReleaseEvent(QMouseEvent *event)
98 {
99 	QWidget::mouseReleaseEvent(event);
100 
101 	if (event->button() == Qt::LeftButton && m_buttonRectangle.contains(event->pos()))
102 	{
103 		QMenu menu(this);
104 		menu.addAction(tr("Select Color…"), this, &ColorWidget::selectColor);
105 		menu.addAction(tr("Copy Color"), this, [&]()
106 		{
107 			QApplication::clipboard()->setText(m_color.name((m_color.alpha() < 255) ? QColor::HexArgb : QColor::HexRgb).toUpper());
108 		});
109 		menu.addSeparator();
110 		menu.addAction(ThemesManager::createIcon(QLatin1String("edit-clear")), tr("Clear"), this, [&]()
111 		{
112 			setColor(QColor());
113 		});
114 
115 		menu.exec(mapToGlobal(isLeftToRight() ? m_buttonRectangle.bottomLeft() : m_buttonRectangle.bottomRight()));
116 	}
117 }
118 
selectColor()119 void ColorWidget::selectColor()
120 {
121 	QColorDialog dialog(this);
122 	dialog.setOption(QColorDialog::ShowAlphaChannel);
123 	dialog.setCurrentColor(m_color);
124 
125 	if (dialog.exec() == QDialog::Accepted)
126 	{
127 		setColor(dialog.currentColor());
128 	}
129 }
130 
drawThumbnail(QPainter * painter,const QColor & color,const QPalette & palette,const QRect & rectangle)131 void ColorWidget::drawThumbnail(QPainter *painter, const QColor &color, const QPalette &palette, const QRect &rectangle)
132 {
133 	painter->save();
134 
135 	if (color.alpha() < 255)
136 	{
137 		QPixmap pixmap(10, 10);
138 		pixmap.fill(Qt::white);
139 
140 		QPainter pixmapPainter(&pixmap);
141 		pixmapPainter.setBrush(Qt::gray);
142 		pixmapPainter.setPen(Qt::NoPen);
143 		pixmapPainter.drawRect(0, 0, 5, 5);
144 		pixmapPainter.drawRect(5, 5, 5, 5);
145 		pixmapPainter.end();
146 
147 		painter->setBrush(pixmap);
148 		painter->setPen(Qt::NoPen);
149 		painter->drawRoundedRect(rectangle, 2, 2);
150 	}
151 
152 	painter->setBrush(color);
153 	painter->setPen(palette.color(QPalette::Button));
154 	painter->drawRoundedRect(rectangle, 2, 2);
155 	painter->restore();
156 }
157 
setColor(const QString & color)158 void ColorWidget::setColor(const QString &color)
159 {
160 	setColor(color.isEmpty() ? QColor() : QColor(color));
161 }
162 
setColor(const QColor & color)163 void ColorWidget::setColor(const QColor &color)
164 {
165 	if (color != m_color)
166 	{
167 		const QString text(color.isValid() ? color.name((color.alpha() < 255) ? QColor::HexArgb : QColor::HexRgb).toUpper() : QString());
168 
169 		if (!m_lineEditWidget->hasFocus())
170 		{
171 			m_lineEditWidget->setText(text);
172 		}
173 
174 		setToolTip(text.isEmpty() ? tr("Invalid") : text);
175 		update();
176 
177 		m_color = color;
178 
179 		emit colorChanged(color);
180 	}
181 }
182 
updateColor(const QString & text)183 void ColorWidget::updateColor(const QString &text)
184 {
185 	if (QColor::isValidColor(text))
186 	{
187 		setColor(text);
188 	}
189 }
190 
getColor() const191 QColor ColorWidget::getColor() const
192 {
193 	return m_color;
194 }
195 
196 }
197