qtpropertybrowserutils.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  4. ** Contact: http://www.qt-project.org/legal
  5. **
  6. ** This file is part of the Qt Solutions component.
  7. **
  8. ** $QT_BEGIN_LICENSE:BSD$
  9. ** You may use this file under the terms of the BSD license as follows:
  10. **
  11. ** "Redistribution and use in source and binary forms, with or without
  12. ** modification, are permitted provided that the following conditions are
  13. ** met:
  14. ** * Redistributions of source code must retain the above copyright
  15. ** notice, this list of conditions and the following disclaimer.
  16. ** * Redistributions in binary form must reproduce the above copyright
  17. ** notice, this list of conditions and the following disclaimer in
  18. ** the documentation and/or other materials provided with the
  19. ** distribution.
  20. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
  21. ** of its contributors may be used to endorse or promote products derived
  22. ** from this software without specific prior written permission.
  23. **
  24. **
  25. ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26. ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27. ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  28. ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  29. ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  30. ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  31. ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32. ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33. ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34. ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  35. ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  36. **
  37. ** $QT_END_LICENSE$
  38. **
  39. ****************************************************************************/
  40. #pragma execution_character_set("utf-8")
  41. #include "qtpropertybrowserutils_p.h"
  42. #include <QApplication>
  43. #include <QPainter>
  44. #include <QHBoxLayout>
  45. #include <QMouseEvent>
  46. #include <QCheckBox>
  47. #include <QLineEdit>
  48. #include <QMenu>
  49. #include <QStyleOption>
  50. #if QT_VERSION >= 0x040400
  51. QT_BEGIN_NAMESPACE
  52. #endif
  53. QtCursorDatabase::QtCursorDatabase()
  54. {
  55. appendCursor(Qt::ArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Arrow"),
  56. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-arrow.png")));
  57. appendCursor(Qt::UpArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Up Arrow"),
  58. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-uparrow.png")));
  59. appendCursor(Qt::CrossCursor, QCoreApplication::translate("QtCursorDatabase", "Cross"),
  60. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-cross.png")));
  61. appendCursor(Qt::WaitCursor, QCoreApplication::translate("QtCursorDatabase", "Wait"),
  62. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-wait.png")));
  63. appendCursor(Qt::IBeamCursor, QCoreApplication::translate("QtCursorDatabase", "IBeam"),
  64. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-ibeam.png")));
  65. appendCursor(Qt::SizeVerCursor, QCoreApplication::translate("QtCursorDatabase", "Size Vertical"),
  66. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizev.png")));
  67. appendCursor(Qt::SizeHorCursor, QCoreApplication::translate("QtCursorDatabase", "Size Horizontal"),
  68. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeh.png")));
  69. appendCursor(Qt::SizeFDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Backslash"),
  70. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizef.png")));
  71. appendCursor(Qt::SizeBDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Slash"),
  72. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeb.png")));
  73. appendCursor(Qt::SizeAllCursor, QCoreApplication::translate("QtCursorDatabase", "Size All"),
  74. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeall.png")));
  75. appendCursor(Qt::BlankCursor, QCoreApplication::translate("QtCursorDatabase", "Blank"),
  76. QIcon());
  77. appendCursor(Qt::SplitVCursor, QCoreApplication::translate("QtCursorDatabase", "Split Vertical"),
  78. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-vsplit.png")));
  79. appendCursor(Qt::SplitHCursor, QCoreApplication::translate("QtCursorDatabase", "Split Horizontal"),
  80. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hsplit.png")));
  81. appendCursor(Qt::PointingHandCursor, QCoreApplication::translate("QtCursorDatabase", "Pointing Hand"),
  82. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hand.png")));
  83. appendCursor(Qt::ForbiddenCursor, QCoreApplication::translate("QtCursorDatabase", "Forbidden"),
  84. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-forbidden.png")));
  85. appendCursor(Qt::OpenHandCursor, QCoreApplication::translate("QtCursorDatabase", "Open Hand"),
  86. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-openhand.png")));
  87. appendCursor(Qt::ClosedHandCursor, QCoreApplication::translate("QtCursorDatabase", "Closed Hand"),
  88. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-closedhand.png")));
  89. appendCursor(Qt::WhatsThisCursor, QCoreApplication::translate("QtCursorDatabase", "What's This"),
  90. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-whatsthis.png")));
  91. appendCursor(Qt::BusyCursor, QCoreApplication::translate("QtCursorDatabase", "Busy"),
  92. QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-busy.png")));
  93. }
  94. void QtCursorDatabase::clear()
  95. {
  96. m_cursorNames.clear();
  97. m_cursorIcons.clear();
  98. m_valueToCursorShape.clear();
  99. m_cursorShapeToValue.clear();
  100. }
  101. void QtCursorDatabase::appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon)
  102. {
  103. if (m_cursorShapeToValue.contains(shape))
  104. return;
  105. const int value = m_cursorNames.count();
  106. m_cursorNames.append(name);
  107. m_cursorIcons.insert(value, icon);
  108. m_valueToCursorShape.insert(value, shape);
  109. m_cursorShapeToValue.insert(shape, value);
  110. }
  111. QStringList QtCursorDatabase::cursorShapeNames() const
  112. {
  113. return m_cursorNames;
  114. }
  115. QMap<int, QIcon> QtCursorDatabase::cursorShapeIcons() const
  116. {
  117. return m_cursorIcons;
  118. }
  119. QString QtCursorDatabase::cursorToShapeName(const QCursor &cursor) const
  120. {
  121. int val = cursorToValue(cursor);
  122. if (val >= 0)
  123. return m_cursorNames.at(val);
  124. return QString();
  125. }
  126. QIcon QtCursorDatabase::cursorToShapeIcon(const QCursor &cursor) const
  127. {
  128. int val = cursorToValue(cursor);
  129. return m_cursorIcons.value(val);
  130. }
  131. int QtCursorDatabase::cursorToValue(const QCursor &cursor) const
  132. {
  133. #ifndef QT_NO_CURSOR
  134. Qt::CursorShape shape = cursor.shape();
  135. if (m_cursorShapeToValue.contains(shape))
  136. return m_cursorShapeToValue[shape];
  137. #endif
  138. return -1;
  139. }
  140. #ifndef QT_NO_CURSOR
  141. QCursor QtCursorDatabase::valueToCursor(int value) const
  142. {
  143. if (m_valueToCursorShape.contains(value))
  144. return QCursor(m_valueToCursorShape[value]);
  145. return QCursor();
  146. }
  147. #endif
  148. QPixmap QtPropertyBrowserUtils::brushValuePixmap(const QBrush &b)
  149. {
  150. QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
  151. img.fill(0);
  152. QPainter painter(&img);
  153. painter.setCompositionMode(QPainter::CompositionMode_Source);
  154. painter.fillRect(0, 0, img.width(), img.height(), b);
  155. QColor color = b.color();
  156. if (color.alpha() != 255) { // indicate alpha by an inset
  157. QBrush opaqueBrush = b;
  158. color.setAlpha(255);
  159. opaqueBrush.setColor(color);
  160. painter.fillRect(img.width() / 4, img.height() / 4,
  161. img.width() / 2, img.height() / 2, opaqueBrush);
  162. }
  163. painter.end();
  164. return QPixmap::fromImage(img);
  165. }
  166. QIcon QtPropertyBrowserUtils::brushValueIcon(const QBrush &b)
  167. {
  168. return QIcon(brushValuePixmap(b));
  169. }
  170. QString QtPropertyBrowserUtils::colorValueText(const QColor &c)
  171. {
  172. return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2, %3] (%4)")
  173. .arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha());
  174. }
  175. QPixmap QtPropertyBrowserUtils::fontValuePixmap(const QFont &font)
  176. {
  177. QFont f = font;
  178. QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
  179. img.fill(0);
  180. QPainter p(&img);
  181. p.setRenderHint(QPainter::TextAntialiasing, true);
  182. p.setRenderHint(QPainter::Antialiasing, true);
  183. f.setPointSize(13);
  184. p.setFont(f);
  185. QTextOption t;
  186. t.setAlignment(Qt::AlignCenter);
  187. p.drawText(QRect(0, 0, 16, 16), QString(QLatin1Char('A')), t);
  188. return QPixmap::fromImage(img);
  189. }
  190. QIcon QtPropertyBrowserUtils::fontValueIcon(const QFont &f)
  191. {
  192. return QIcon(fontValuePixmap(f));
  193. }
  194. QString QtPropertyBrowserUtils::fontValueText(const QFont &f)
  195. {
  196. return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2]")
  197. .arg(f.family()).arg(f.pointSize());
  198. }
  199. QtBoolEdit::QtBoolEdit(QWidget *parent) :
  200. QWidget(parent),
  201. m_checkBox(new QCheckBox(this)),
  202. m_textVisible(true)
  203. {
  204. QHBoxLayout *lt = new QHBoxLayout;
  205. if (QApplication::layoutDirection() == Qt::LeftToRight)
  206. lt->setContentsMargins(4, 0, 0, 0);
  207. else
  208. lt->setContentsMargins(0, 0, 4, 0);
  209. lt->addWidget(m_checkBox);
  210. setLayout(lt);
  211. connect(m_checkBox, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
  212. setFocusProxy(m_checkBox);
  213. m_checkBox->setText(tr("True"));
  214. }
  215. void QtBoolEdit::setTextVisible(bool textVisible)
  216. {
  217. if (m_textVisible == textVisible)
  218. return;
  219. m_textVisible = textVisible;
  220. if (m_textVisible)
  221. m_checkBox->setText(isChecked() ? tr("True") : tr("False"));
  222. else
  223. m_checkBox->setText(QString());
  224. }
  225. Qt::CheckState QtBoolEdit::checkState() const
  226. {
  227. return m_checkBox->checkState();
  228. }
  229. void QtBoolEdit::setCheckState(Qt::CheckState state)
  230. {
  231. m_checkBox->setCheckState(state);
  232. }
  233. bool QtBoolEdit::isChecked() const
  234. {
  235. return m_checkBox->isChecked();
  236. }
  237. void QtBoolEdit::setChecked(bool c)
  238. {
  239. m_checkBox->setChecked(c);
  240. if (!m_textVisible)
  241. return;
  242. m_checkBox->setText(isChecked() ? tr("True") : tr("False"));
  243. }
  244. bool QtBoolEdit::blockCheckBoxSignals(bool block)
  245. {
  246. return m_checkBox->blockSignals(block);
  247. }
  248. void QtBoolEdit::mousePressEvent(QMouseEvent *event)
  249. {
  250. if (event->buttons() == Qt::LeftButton) {
  251. m_checkBox->click();
  252. event->accept();
  253. } else {
  254. QWidget::mousePressEvent(event);
  255. }
  256. }
  257. void QtBoolEdit::paintEvent(QPaintEvent *)
  258. {
  259. QStyleOption opt;
  260. opt.init(this);
  261. QPainter p(this);
  262. style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
  263. }
  264. QtKeySequenceEdit::QtKeySequenceEdit(QWidget *parent)
  265. : QWidget(parent), m_num(0), m_lineEdit(new QLineEdit(this))
  266. {
  267. QHBoxLayout *layout = new QHBoxLayout(this);
  268. layout->addWidget(m_lineEdit);
  269. layout->setMargin(0);
  270. m_lineEdit->installEventFilter(this);
  271. m_lineEdit->setReadOnly(true);
  272. m_lineEdit->setFocusProxy(this);
  273. setFocusPolicy(m_lineEdit->focusPolicy());
  274. setAttribute(Qt::WA_InputMethodEnabled);
  275. }
  276. bool QtKeySequenceEdit::eventFilter(QObject *o, QEvent *e)
  277. {
  278. if (o == m_lineEdit && e->type() == QEvent::ContextMenu) {
  279. QContextMenuEvent *c = static_cast<QContextMenuEvent *>(e);
  280. QMenu *menu = m_lineEdit->createStandardContextMenu();
  281. const QList<QAction *> actions = menu->actions();
  282. QListIterator<QAction *> itAction(actions);
  283. while (itAction.hasNext()) {
  284. QAction *action = itAction.next();
  285. action->setShortcut(QKeySequence());
  286. QString actionString = action->text();
  287. const int pos = actionString.lastIndexOf(QLatin1Char('\t'));
  288. if (pos > 0)
  289. actionString.remove(pos, actionString.length() - pos);
  290. action->setText(actionString);
  291. }
  292. QAction *actionBefore = 0;
  293. if (actions.count() > 0)
  294. actionBefore = actions[0];
  295. QAction *clearAction = new QAction(tr("Clear Shortcut"), menu);
  296. menu->insertAction(actionBefore, clearAction);
  297. menu->insertSeparator(actionBefore);
  298. clearAction->setEnabled(!m_keySequence.isEmpty());
  299. connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearShortcut()));
  300. menu->exec(c->globalPos());
  301. delete menu;
  302. e->accept();
  303. return true;
  304. }
  305. return QWidget::eventFilter(o, e);
  306. }
  307. void QtKeySequenceEdit::slotClearShortcut()
  308. {
  309. if (m_keySequence.isEmpty())
  310. return;
  311. setKeySequence(QKeySequence());
  312. emit keySequenceChanged(m_keySequence);
  313. }
  314. void QtKeySequenceEdit::handleKeyEvent(QKeyEvent *e)
  315. {
  316. int nextKey = e->key();
  317. if (nextKey == Qt::Key_Control || nextKey == Qt::Key_Shift ||
  318. nextKey == Qt::Key_Meta || nextKey == Qt::Key_Alt ||
  319. nextKey == Qt::Key_Super_L || nextKey == Qt::Key_AltGr)
  320. return;
  321. nextKey |= translateModifiers(e->modifiers(), e->text());
  322. int k0 = m_keySequence[0];
  323. int k1 = m_keySequence[1];
  324. int k2 = m_keySequence[2];
  325. int k3 = m_keySequence[3];
  326. switch (m_num) {
  327. case 0: k0 = nextKey; k1 = 0; k2 = 0; k3 = 0; break;
  328. case 1: k1 = nextKey; k2 = 0; k3 = 0; break;
  329. case 2: k2 = nextKey; k3 = 0; break;
  330. case 3: k3 = nextKey; break;
  331. default: break;
  332. }
  333. ++m_num;
  334. if (m_num > 3)
  335. m_num = 0;
  336. m_keySequence = QKeySequence(k0, k1, k2, k3);
  337. m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText));
  338. e->accept();
  339. emit keySequenceChanged(m_keySequence);
  340. }
  341. void QtKeySequenceEdit::setKeySequence(const QKeySequence &sequence)
  342. {
  343. if (sequence == m_keySequence)
  344. return;
  345. m_num = 0;
  346. m_keySequence = sequence;
  347. m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText));
  348. }
  349. QKeySequence QtKeySequenceEdit::keySequence() const
  350. {
  351. return m_keySequence;
  352. }
  353. int QtKeySequenceEdit::translateModifiers(Qt::KeyboardModifiers state, const QString &text) const
  354. {
  355. int result = 0;
  356. if ((state & Qt::ShiftModifier) && (text.size() == 0 || !text.at(0).isPrint() || text.at(0).isLetter() || text.at(0).isSpace()))
  357. result |= Qt::SHIFT;
  358. if (state & Qt::ControlModifier)
  359. result |= Qt::CTRL;
  360. if (state & Qt::MetaModifier)
  361. result |= Qt::META;
  362. if (state & Qt::AltModifier)
  363. result |= Qt::ALT;
  364. return result;
  365. }
  366. void QtKeySequenceEdit::focusInEvent(QFocusEvent *e)
  367. {
  368. m_lineEdit->event(e);
  369. m_lineEdit->selectAll();
  370. QWidget::focusInEvent(e);
  371. }
  372. void QtKeySequenceEdit::focusOutEvent(QFocusEvent *e)
  373. {
  374. m_num = 0;
  375. m_lineEdit->event(e);
  376. QWidget::focusOutEvent(e);
  377. }
  378. void QtKeySequenceEdit::keyPressEvent(QKeyEvent *e)
  379. {
  380. handleKeyEvent(e);
  381. e->accept();
  382. }
  383. void QtKeySequenceEdit::keyReleaseEvent(QKeyEvent *e)
  384. {
  385. m_lineEdit->event(e);
  386. }
  387. void QtKeySequenceEdit::paintEvent(QPaintEvent *)
  388. {
  389. QStyleOption opt;
  390. opt.init(this);
  391. QPainter p(this);
  392. style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
  393. }
  394. bool QtKeySequenceEdit::event(QEvent *e)
  395. {
  396. if (e->type() == QEvent::Shortcut ||
  397. e->type() == QEvent::ShortcutOverride ||
  398. e->type() == QEvent::KeyRelease) {
  399. e->accept();
  400. return true;
  401. }
  402. return QWidget::event(e);
  403. }
  404. #if QT_VERSION >= 0x040400
  405. QT_END_NAMESPACE
  406. #endif