1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33
34
35 #include "qtpropertybrowserutils_p.h"
36 #include <QtWidgets/QApplication>
37 #include <QtGui/QPainter>
38 #include <QtWidgets/QHBoxLayout>
39 #include <QtGui/QMouseEvent>
40 #include <QtWidgets/QCheckBox>
41 #include <QtWidgets/QLineEdit>
42 #include <QtWidgets/QMenu>
43 #include <QtCore/QLocale>
44 #include <QtWidgets/QStyleOption>
45
46 QT_BEGIN_NAMESPACE
47
QtCursorDatabase()48 QtCursorDatabase::QtCursorDatabase()
49 {
50 Q_INIT_RESOURCE(qtpropertybrowser);
51
52 appendCursor(Qt::ArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Arrow"),
53 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-arrow.png")));
54 appendCursor(Qt::UpArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Up Arrow"),
55 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-uparrow.png")));
56 appendCursor(Qt::CrossCursor, QCoreApplication::translate("QtCursorDatabase", "Cross"),
57 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-cross.png")));
58 appendCursor(Qt::WaitCursor, QCoreApplication::translate("QtCursorDatabase", "Wait"),
59 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-wait.png")));
60 appendCursor(Qt::IBeamCursor, QCoreApplication::translate("QtCursorDatabase", "IBeam"),
61 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-ibeam.png")));
62 appendCursor(Qt::SizeVerCursor, QCoreApplication::translate("QtCursorDatabase", "Size Vertical"),
63 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizev.png")));
64 appendCursor(Qt::SizeHorCursor, QCoreApplication::translate("QtCursorDatabase", "Size Horizontal"),
65 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeh.png")));
66 appendCursor(Qt::SizeFDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Backslash"),
67 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizef.png")));
68 appendCursor(Qt::SizeBDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Slash"),
69 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeb.png")));
70 appendCursor(Qt::SizeAllCursor, QCoreApplication::translate("QtCursorDatabase", "Size All"),
71 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeall.png")));
72 appendCursor(Qt::BlankCursor, QCoreApplication::translate("QtCursorDatabase", "Blank"),
73 QIcon());
74 appendCursor(Qt::SplitVCursor, QCoreApplication::translate("QtCursorDatabase", "Split Vertical"),
75 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-vsplit.png")));
76 appendCursor(Qt::SplitHCursor, QCoreApplication::translate("QtCursorDatabase", "Split Horizontal"),
77 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hsplit.png")));
78 appendCursor(Qt::PointingHandCursor, QCoreApplication::translate("QtCursorDatabase", "Pointing Hand"),
79 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hand.png")));
80 appendCursor(Qt::ForbiddenCursor, QCoreApplication::translate("QtCursorDatabase", "Forbidden"),
81 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-forbidden.png")));
82 appendCursor(Qt::OpenHandCursor, QCoreApplication::translate("QtCursorDatabase", "Open Hand"),
83 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-openhand.png")));
84 appendCursor(Qt::ClosedHandCursor, QCoreApplication::translate("QtCursorDatabase", "Closed Hand"),
85 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-closedhand.png")));
86 appendCursor(Qt::WhatsThisCursor, QCoreApplication::translate("QtCursorDatabase", "What's This"),
87 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-whatsthis.png")));
88 appendCursor(Qt::BusyCursor, QCoreApplication::translate("QtCursorDatabase", "Busy"),
89 QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-busy.png")));
90 }
91
clear()92 void QtCursorDatabase::clear()
93 {
94 m_cursorNames.clear();
95 m_cursorIcons.clear();
96 m_valueToCursorShape.clear();
97 m_cursorShapeToValue.clear();
98 }
99
appendCursor(Qt::CursorShape shape,const QString & name,const QIcon & icon)100 void QtCursorDatabase::appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon)
101 {
102 if (m_cursorShapeToValue.contains(shape))
103 return;
104 const int value = m_cursorNames.count();
105 m_cursorNames.append(name);
106 m_cursorIcons.insert(value, icon);
107 m_valueToCursorShape.insert(value, shape);
108 m_cursorShapeToValue.insert(shape, value);
109 }
110
cursorShapeNames() const111 QStringList QtCursorDatabase::cursorShapeNames() const
112 {
113 return m_cursorNames;
114 }
115
cursorShapeIcons() const116 QMap<int, QIcon> QtCursorDatabase::cursorShapeIcons() const
117 {
118 return m_cursorIcons;
119 }
120
cursorToShapeName(const QCursor & cursor) const121 QString QtCursorDatabase::cursorToShapeName(const QCursor &cursor) const
122 {
123 int val = cursorToValue(cursor);
124 if (val >= 0)
125 return m_cursorNames.at(val);
126 return QString();
127 }
128
cursorToShapeIcon(const QCursor & cursor) const129 QIcon QtCursorDatabase::cursorToShapeIcon(const QCursor &cursor) const
130 {
131 int val = cursorToValue(cursor);
132 return m_cursorIcons.value(val);
133 }
134
cursorToValue(const QCursor & cursor) const135 int QtCursorDatabase::cursorToValue(const QCursor &cursor) const
136 {
137 #ifndef QT_NO_CURSOR
138 Qt::CursorShape shape = cursor.shape();
139 if (m_cursorShapeToValue.contains(shape))
140 return m_cursorShapeToValue[shape];
141 #endif
142 return -1;
143 }
144
145 #ifndef QT_NO_CURSOR
valueToCursor(int value) const146 QCursor QtCursorDatabase::valueToCursor(int value) const
147 {
148 if (m_valueToCursorShape.contains(value))
149 return QCursor(m_valueToCursorShape[value]);
150 return QCursor();
151 }
152 #endif
153
brushValuePixmap(const QBrush & b)154 QPixmap QtPropertyBrowserUtils::brushValuePixmap(const QBrush &b)
155 {
156 QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
157 img.fill(0);
158
159 QPainter painter(&img);
160 painter.setCompositionMode(QPainter::CompositionMode_Source);
161 painter.fillRect(0, 0, img.width(), img.height(), b);
162 QColor color = b.color();
163 if (color.alpha() != 255) { // indicate alpha by an inset
164 QBrush opaqueBrush = b;
165 color.setAlpha(255);
166 opaqueBrush.setColor(color);
167 painter.fillRect(img.width() / 4, img.height() / 4,
168 img.width() / 2, img.height() / 2, opaqueBrush);
169 }
170 painter.end();
171 return QPixmap::fromImage(img);
172 }
173
brushValueIcon(const QBrush & b)174 QIcon QtPropertyBrowserUtils::brushValueIcon(const QBrush &b)
175 {
176 return QIcon(brushValuePixmap(b));
177 }
178
colorValueText(const QColor & c)179 QString QtPropertyBrowserUtils::colorValueText(const QColor &c)
180 {
181 return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2, %3] (%4)")
182 .arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha());
183 }
184
fontValuePixmap(const QFont & font)185 QPixmap QtPropertyBrowserUtils::fontValuePixmap(const QFont &font)
186 {
187 QFont f = font;
188 QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
189 img.fill(0);
190 QPainter p(&img);
191 p.setRenderHint(QPainter::TextAntialiasing, true);
192 p.setRenderHint(QPainter::Antialiasing, true);
193 f.setPointSize(13);
194 p.setFont(f);
195 QTextOption t;
196 t.setAlignment(Qt::AlignCenter);
197 p.drawText(QRect(0, 0, 16, 16), QString(QLatin1Char('A')), t);
198 return QPixmap::fromImage(img);
199 }
200
fontValueIcon(const QFont & f)201 QIcon QtPropertyBrowserUtils::fontValueIcon(const QFont &f)
202 {
203 return QIcon(fontValuePixmap(f));
204 }
205
fontValueText(const QFont & f)206 QString QtPropertyBrowserUtils::fontValueText(const QFont &f)
207 {
208 return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2]")
209 .arg(f.family()).arg(f.pointSize());
210 }
211
trimDecimalZeros(const QChar & point,const QString & text)212 QString QtPropertyBrowserUtils::trimDecimalZeros(const QChar &point, const QString &text)
213 {
214 int idx = text.indexOf(point);
215 if (idx >= 0)
216 {
217 QString corrText(text);
218 while (corrText.endsWith('0'))
219 corrText.chop(1);
220 if (corrText.endsWith(point))
221 corrText.chop(1);
222 return corrText;
223 }
224 else
225 return text;
226 }
227
dateFormat()228 QString QtPropertyBrowserUtils::dateFormat()
229 {
230 QLocale loc;
231 return loc.dateFormat(QLocale::ShortFormat);
232 }
233
timeFormat()234 QString QtPropertyBrowserUtils::timeFormat()
235 {
236 QLocale loc;
237 // ShortFormat is missing seconds on UNIX.
238 return loc.timeFormat(QLocale::LongFormat);
239 }
240
dateTimeFormat()241 QString QtPropertyBrowserUtils::dateTimeFormat()
242 {
243 QString format = dateFormat();
244 format += QLatin1Char(' ');
245 format += timeFormat();
246 return format;
247 }
248
249
QtBoolEdit(QWidget * parent)250 QtBoolEdit::QtBoolEdit(QWidget *parent) :
251 QWidget(parent),
252 m_checkBox(new QCheckBox(this)),
253 m_textVisible(true)
254 {
255 QHBoxLayout *lt = new QHBoxLayout;
256 if (QApplication::layoutDirection() == Qt::LeftToRight)
257 lt->setContentsMargins(4, 0, 0, 0);
258 else
259 lt->setContentsMargins(0, 0, 4, 0);
260 lt->addWidget(m_checkBox);
261 setLayout(lt);
262 connect(m_checkBox, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
263 setFocusProxy(m_checkBox);
264 m_checkBox->setText(tr("True"));
265 }
266
setTextVisible(bool textVisible)267 void QtBoolEdit::setTextVisible(bool textVisible)
268 {
269 if (m_textVisible == textVisible)
270 return;
271
272 m_textVisible = textVisible;
273 if (m_textVisible)
274 m_checkBox->setText(isChecked() ? tr("True") : tr("False"));
275 else
276 m_checkBox->setText(QString());
277 }
278
checkState() const279 Qt::CheckState QtBoolEdit::checkState() const
280 {
281 return m_checkBox->checkState();
282 }
283
setCheckState(Qt::CheckState state)284 void QtBoolEdit::setCheckState(Qt::CheckState state)
285 {
286 m_checkBox->setCheckState(state);
287 }
288
isChecked() const289 bool QtBoolEdit::isChecked() const
290 {
291 return m_checkBox->isChecked();
292 }
293
setChecked(bool c)294 void QtBoolEdit::setChecked(bool c)
295 {
296 m_checkBox->setChecked(c);
297 if (!m_textVisible)
298 return;
299 m_checkBox->setText(isChecked() ? tr("True") : tr("False"));
300 }
301
blockCheckBoxSignals(bool block)302 bool QtBoolEdit::blockCheckBoxSignals(bool block)
303 {
304 return m_checkBox->blockSignals(block);
305 }
306
mousePressEvent(QMouseEvent * event)307 void QtBoolEdit::mousePressEvent(QMouseEvent *event)
308 {
309 if (event->buttons() == Qt::LeftButton) {
310 m_checkBox->click();
311 event->accept();
312 } else {
313 QWidget::mousePressEvent(event);
314 }
315 }
316
paintEvent(QPaintEvent *)317 void QtBoolEdit::paintEvent(QPaintEvent *)
318 {
319 QStyleOption opt;
320 opt.init(this);
321 QPainter p(this);
322 style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
323 }
324
325
326
QtKeySequenceEdit(QWidget * parent)327 QtKeySequenceEdit::QtKeySequenceEdit(QWidget *parent)
328 : QWidget(parent), m_num(0), m_lineEdit(new QLineEdit(this))
329 {
330 QHBoxLayout *layout = new QHBoxLayout(this);
331 layout->addWidget(m_lineEdit);
332 layout->setMargin(0);
333 m_lineEdit->installEventFilter(this);
334 m_lineEdit->setReadOnly(true);
335 m_lineEdit->setFocusProxy(this);
336 setFocusPolicy(m_lineEdit->focusPolicy());
337 setAttribute(Qt::WA_InputMethodEnabled);
338 }
339
eventFilter(QObject * o,QEvent * e)340 bool QtKeySequenceEdit::eventFilter(QObject *o, QEvent *e)
341 {
342 if (o == m_lineEdit && e->type() == QEvent::ContextMenu) {
343 QContextMenuEvent *c = static_cast<QContextMenuEvent *>(e);
344 QMenu *menu = m_lineEdit->createStandardContextMenu();
345 const QList<QAction *> actions = menu->actions();
346 QListIterator<QAction *> itAction(actions);
347 while (itAction.hasNext()) {
348 QAction *action = itAction.next();
349 action->setShortcut(QKeySequence());
350 QString actionString = action->text();
351 const int pos = actionString.lastIndexOf(QLatin1Char('\t'));
352 if (pos > 0)
353 actionString.remove(pos, actionString.length() - pos);
354 action->setText(actionString);
355 }
356 QAction *actionBefore = 0;
357 if (actions.count() > 0)
358 actionBefore = actions[0];
359 QAction *clearAction = new QAction(tr("Clear Shortcut"), menu);
360 menu->insertAction(actionBefore, clearAction);
361 menu->insertSeparator(actionBefore);
362 clearAction->setEnabled(!m_keySequence.isEmpty());
363 connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearShortcut()));
364 menu->exec(c->globalPos());
365 delete menu;
366 e->accept();
367 return true;
368 }
369
370 return QWidget::eventFilter(o, e);
371 }
372
slotClearShortcut()373 void QtKeySequenceEdit::slotClearShortcut()
374 {
375 if (m_keySequence.isEmpty())
376 return;
377 setKeySequence(QKeySequence());
378 emit keySequenceChanged(m_keySequence);
379 }
380
handleKeyEvent(QKeyEvent * e)381 void QtKeySequenceEdit::handleKeyEvent(QKeyEvent *e)
382 {
383 int nextKey = e->key();
384 if (nextKey == Qt::Key_Control || nextKey == Qt::Key_Shift ||
385 nextKey == Qt::Key_Meta || nextKey == Qt::Key_Alt ||
386 nextKey == Qt::Key_Super_L || nextKey == Qt::Key_AltGr)
387 return;
388
389 nextKey |= translateModifiers(e->modifiers(), e->text());
390 int k0 = m_keySequence[0];
391 int k1 = m_keySequence[1];
392 int k2 = m_keySequence[2];
393 int k3 = m_keySequence[3];
394 switch (m_num) {
395 case 0: k0 = nextKey; k1 = 0; k2 = 0; k3 = 0; break;
396 case 1: k1 = nextKey; k2 = 0; k3 = 0; break;
397 case 2: k2 = nextKey; k3 = 0; break;
398 case 3: k3 = nextKey; break;
399 default: break;
400 }
401 ++m_num;
402 if (m_num > 3)
403 m_num = 0;
404 m_keySequence = QKeySequence(k0, k1, k2, k3);
405 m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText));
406 e->accept();
407 emit keySequenceChanged(m_keySequence);
408 }
409
setKeySequence(const QKeySequence & sequence)410 void QtKeySequenceEdit::setKeySequence(const QKeySequence &sequence)
411 {
412 if (sequence == m_keySequence)
413 return;
414 m_num = 0;
415 m_keySequence = sequence;
416 m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText));
417 }
418
keySequence() const419 QKeySequence QtKeySequenceEdit::keySequence() const
420 {
421 return m_keySequence;
422 }
423
translateModifiers(Qt::KeyboardModifiers state,const QString & text) const424 int QtKeySequenceEdit::translateModifiers(Qt::KeyboardModifiers state, const QString &text) const
425 {
426 int result = 0;
427 if ((state & Qt::ShiftModifier) && (text.size() == 0 || !text.at(0).isPrint() || text.at(0).isLetter() || text.at(0).isSpace()))
428 result |= Qt::SHIFT;
429 if (state & Qt::ControlModifier)
430 result |= Qt::CTRL;
431 if (state & Qt::MetaModifier)
432 result |= Qt::META;
433 if (state & Qt::AltModifier)
434 result |= Qt::ALT;
435 return result;
436 }
437
focusInEvent(QFocusEvent * e)438 void QtKeySequenceEdit::focusInEvent(QFocusEvent *e)
439 {
440 m_lineEdit->event(e);
441 m_lineEdit->selectAll();
442 QWidget::focusInEvent(e);
443 }
444
focusOutEvent(QFocusEvent * e)445 void QtKeySequenceEdit::focusOutEvent(QFocusEvent *e)
446 {
447 m_num = 0;
448 m_lineEdit->event(e);
449 QWidget::focusOutEvent(e);
450 }
451
keyPressEvent(QKeyEvent * e)452 void QtKeySequenceEdit::keyPressEvent(QKeyEvent *e)
453 {
454 handleKeyEvent(e);
455 e->accept();
456 }
457
keyReleaseEvent(QKeyEvent * e)458 void QtKeySequenceEdit::keyReleaseEvent(QKeyEvent *e)
459 {
460 m_lineEdit->event(e);
461 }
462
paintEvent(QPaintEvent *)463 void QtKeySequenceEdit::paintEvent(QPaintEvent *)
464 {
465 QStyleOption opt;
466 opt.init(this);
467 QPainter p(this);
468 style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
469 }
470
event(QEvent * e)471 bool QtKeySequenceEdit::event(QEvent *e)
472 {
473 if (e->type() == QEvent::Shortcut ||
474 e->type() == QEvent::ShortcutOverride ||
475 e->type() == QEvent::KeyRelease) {
476 e->accept();
477 return true;
478 }
479 return QWidget::event(e);
480 }
481
482
483 QT_END_NAMESPACE
484