PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/examples/widgets/gallery/widgetgallery.cpp

https://gitlab.com/f3822/qtbase
C++ | 474 lines | 359 code | 65 blank | 50 comment | 11 complexity | 79c6a863e5920be196a1b60be4754681 MD5 | raw file
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2020 The Qt Company Ltd.
  4. ** Contact: https://www.qt.io/licensing/
  5. **
  6. ** This file is part of the examples of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:BSD$
  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 https://www.qt.io/terms-conditions. For further
  15. ** information use the contact form at https://www.qt.io/contact-us.
  16. **
  17. ** BSD License Usage
  18. ** Alternatively, you may use this file under the terms of the BSD license
  19. ** as follows:
  20. **
  21. ** "Redistribution and use in source and binary forms, with or without
  22. ** modification, are permitted provided that the following conditions are
  23. ** met:
  24. ** * Redistributions of source code must retain the above copyright
  25. ** notice, this list of conditions and the following disclaimer.
  26. ** * Redistributions in binary form must reproduce the above copyright
  27. ** notice, this list of conditions and the following disclaimer in
  28. ** the documentation and/or other materials provided with the
  29. ** distribution.
  30. ** * Neither the name of The Qt Company Ltd nor the names of its
  31. ** contributors may be used to endorse or promote products derived
  32. ** from this software without specific prior written permission.
  33. **
  34. **
  35. ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  36. ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  37. ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  38. ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  39. ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  42. ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  43. ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  44. ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  45. ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  46. **
  47. ** $QT_END_LICENSE$
  48. **
  49. ****************************************************************************/
  50. #include "widgetgallery.h"
  51. #include <QApplication>
  52. #include <QCheckBox>
  53. #include <QComboBox>
  54. #include <QCommandLinkButton>
  55. #include <QDateTimeEdit>
  56. #include <QDial>
  57. #include <QDialogButtonBox>
  58. #include <QFileSystemModel>
  59. #include <QGridLayout>
  60. #include <QGroupBox>
  61. #include <QMenu>
  62. #include <QLabel>
  63. #include <QLineEdit>
  64. #include <QListWidget>
  65. #include <QPlainTextEdit>
  66. #include <QProgressBar>
  67. #include <QPushButton>
  68. #include <QRadioButton>
  69. #include <QScrollBar>
  70. #include <QShortcut>
  71. #include <QSpinBox>
  72. #include <QStandardItemModel>
  73. #include <QStyle>
  74. #include <QStyleFactory>
  75. #include <QTextBrowser>
  76. #include <QTreeView>
  77. #include <QTableWidget>
  78. #include <QTextEdit>
  79. #include <QToolBox>
  80. #include <QToolButton>
  81. #include <QIcon>
  82. #include <QDesktopServices>
  83. #include <QScreen>
  84. #include <QWindow>
  85. #include <QDebug>
  86. #include <QLibraryInfo>
  87. #include <QSysInfo>
  88. #include <QTextStream>
  89. #include <QTimer>
  90. static inline QString className(const QObject *o)
  91. {
  92. return QString::fromUtf8(o->metaObject()->className());
  93. }
  94. static inline void setClassNameToolTip(QWidget *w)
  95. {
  96. w->setToolTip(className(w));
  97. }
  98. static QString helpUrl(const QString &page)
  99. {
  100. QString result;
  101. QTextStream(&result) << "https://doc.qt.io/qt-" << QT_VERSION_MAJOR
  102. << '/' << page << ".html";
  103. return result;
  104. }
  105. static inline QString helpUrl(const QWidget *w)
  106. {
  107. return helpUrl(className(w).toLower());
  108. }
  109. static void launchHelp(const QWidget *w)
  110. {
  111. QDesktopServices::openUrl(helpUrl(w));
  112. }
  113. static void launchModuleHelp()
  114. {
  115. QDesktopServices::openUrl(helpUrl(QLatin1String("qtwidgets-index")));
  116. }
  117. template <class Widget>
  118. Widget *createWidget(const char *name, QWidget *parent = nullptr)
  119. {
  120. auto result = new Widget(parent);
  121. result->setObjectName(QLatin1String(name));
  122. setClassNameToolTip(result);
  123. return result;
  124. }
  125. template <class Widget, class Parameter>
  126. Widget *createWidget1(const Parameter &p1, const char *name, QWidget *parent = nullptr)
  127. {
  128. auto result = new Widget(p1, parent);
  129. result->setObjectName(QLatin1String(name));
  130. setClassNameToolTip(result);
  131. return result;
  132. }
  133. QTextStream &operator<<(QTextStream &str, const QRect &r)
  134. {
  135. str << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y()
  136. << Qt::noforcesign;
  137. return str;
  138. }
  139. static QString highDpiScaleFactorRoundingPolicy()
  140. {
  141. QString result;
  142. QDebug(&result) << QGuiApplication::highDpiScaleFactorRoundingPolicy();
  143. if (result.endsWith(QLatin1Char(')')))
  144. result.chop(1);
  145. const int lastSep = result.lastIndexOf(QLatin1String("::"));
  146. if (lastSep != -1)
  147. result.remove(0, lastSep + 2);
  148. return result;
  149. }
  150. WidgetGallery::WidgetGallery(QWidget *parent)
  151. : QDialog(parent)
  152. , progressBar(createProgressBar())
  153. {
  154. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  155. auto styleComboBox = createWidget<QComboBox>("styleComboBox");
  156. const QString defaultStyleName = QApplication::style()->objectName();
  157. QStringList styleNames = QStyleFactory::keys();
  158. for (int i = 1, size = styleNames.size(); i < size; ++i) {
  159. if (defaultStyleName.compare(styleNames.at(i), Qt::CaseInsensitive) == 0) {
  160. styleNames.swapItemsAt(0, i);
  161. break;
  162. }
  163. }
  164. styleComboBox->addItems(styleNames);
  165. auto styleLabel = createWidget1<QLabel>(tr("&Style:"), "styleLabel");
  166. styleLabel->setBuddy(styleComboBox);
  167. auto helpLabel = createWidget1<QLabel>(tr("Press F1 over a widget to see Documentation"), "helpLabel");
  168. auto disableWidgetsCheckBox = createWidget1<QCheckBox>(tr("&Disable widgets"), "disableWidgetsCheckBox");
  169. auto buttonsGroupBox = createButtonsGroupBox();
  170. auto itemViewTabWidget = createItemViewTabWidget();
  171. auto simpleInputWidgetsGroupBox = createSimpleInputWidgetsGroupBox();
  172. auto textToolBox = createTextToolBox();
  173. connect(styleComboBox, &QComboBox::textActivated,
  174. this, &WidgetGallery::changeStyle);
  175. connect(disableWidgetsCheckBox, &QCheckBox::toggled,
  176. buttonsGroupBox, &QWidget::setDisabled);
  177. connect(disableWidgetsCheckBox, &QCheckBox::toggled,
  178. textToolBox, &QWidget::setDisabled);
  179. connect(disableWidgetsCheckBox, &QCheckBox::toggled,
  180. itemViewTabWidget, &QWidget::setDisabled);
  181. connect(disableWidgetsCheckBox, &QCheckBox::toggled,
  182. simpleInputWidgetsGroupBox, &QWidget::setDisabled);
  183. auto topLayout = new QHBoxLayout;
  184. topLayout->addWidget(styleLabel);
  185. topLayout->addWidget(styleComboBox);
  186. topLayout->addStretch(1);
  187. topLayout->addWidget(helpLabel);
  188. topLayout->addStretch(1);
  189. topLayout->addWidget(disableWidgetsCheckBox);
  190. auto dialogButtonBox = createWidget1<QDialogButtonBox>(QDialogButtonBox::Help | QDialogButtonBox::Close,
  191. "dialogButtonBox");
  192. connect(dialogButtonBox, &QDialogButtonBox::helpRequested, this, launchModuleHelp);
  193. connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
  194. auto mainLayout = new QGridLayout(this);
  195. mainLayout->addLayout(topLayout, 0, 0, 1, 2);
  196. mainLayout->addWidget(buttonsGroupBox, 1, 0);
  197. mainLayout->addWidget(simpleInputWidgetsGroupBox, 1, 1);
  198. mainLayout->addWidget(itemViewTabWidget, 2, 0);
  199. mainLayout->addWidget(textToolBox, 2, 1);
  200. mainLayout->addWidget(progressBar, 3, 0, 1, 2);
  201. mainLayout->addWidget(dialogButtonBox, 4, 0, 1, 2);
  202. setWindowTitle(tr("Widget Gallery Qt %1").arg(QT_VERSION_STR));
  203. new QShortcut(QKeySequence::HelpContents, this, this, &WidgetGallery::helpOnCurrentWidget);
  204. }
  205. void WidgetGallery::setVisible(bool visible)
  206. {
  207. QDialog::setVisible(visible);
  208. if (visible) {
  209. connect(windowHandle(), &QWindow::screenChanged, this, &WidgetGallery::updateSystemInfo);
  210. updateSystemInfo();
  211. }
  212. }
  213. void WidgetGallery::changeStyle(const QString &styleName)
  214. {
  215. QApplication::setStyle(QStyleFactory::create(styleName));
  216. }
  217. void WidgetGallery::advanceProgressBar()
  218. {
  219. int curVal = progressBar->value();
  220. int maxVal = progressBar->maximum();
  221. progressBar->setValue(curVal + (maxVal - curVal) / 100);
  222. }
  223. QGroupBox *WidgetGallery::createButtonsGroupBox()
  224. {
  225. auto result = createWidget1<QGroupBox>(tr("Buttons"), "buttonsGroupBox");
  226. auto defaultPushButton = createWidget1<QPushButton>(tr("Default Push Button"), "defaultPushButton");
  227. defaultPushButton->setDefault(true);
  228. auto togglePushButton = createWidget1<QPushButton>(tr("Toggle Push Button"), "togglePushButton");
  229. togglePushButton->setCheckable(true);
  230. togglePushButton->setChecked(true);
  231. auto flatPushButton = createWidget1<QPushButton>(tr("Flat Push Button"), "flatPushButton");
  232. flatPushButton->setFlat(true);
  233. auto toolButton = createWidget<QToolButton>("toolButton");
  234. toolButton->setText(tr("Tool Button"));
  235. auto menuToolButton = createWidget<QToolButton>("menuButton");
  236. menuToolButton->setText(tr("Menu Button"));
  237. auto toolMenu = new QMenu(menuToolButton);
  238. menuToolButton->setPopupMode(QToolButton::InstantPopup);
  239. toolMenu->addAction("Option");
  240. toolMenu->addSeparator();
  241. auto action = toolMenu->addAction("Checkable Option");
  242. action->setCheckable(true);
  243. menuToolButton->setMenu(toolMenu);
  244. auto toolLayout = new QHBoxLayout;
  245. toolLayout->addWidget(toolButton);
  246. toolLayout->addWidget(menuToolButton);
  247. auto commandLinkButton = createWidget1<QCommandLinkButton>(tr("Command Link Button"), "commandLinkButton");
  248. commandLinkButton->setDescription(tr("Description"));
  249. auto buttonLayout = new QVBoxLayout;
  250. buttonLayout->addWidget(defaultPushButton);
  251. buttonLayout->addWidget(togglePushButton);
  252. buttonLayout->addWidget(flatPushButton);
  253. buttonLayout->addLayout(toolLayout);
  254. buttonLayout->addWidget(commandLinkButton);
  255. buttonLayout->addStretch(1);
  256. auto radioButton1 = createWidget1<QRadioButton>(tr("Radio button 1"), "radioButton1");
  257. auto radioButton2 = createWidget1<QRadioButton>(tr("Radio button 2"), "radioButton2");
  258. auto radioButton3 = createWidget1<QRadioButton>(tr("Radio button 3"), "radioButton3");
  259. radioButton1->setChecked(true);
  260. auto checkBox = createWidget1<QCheckBox>(tr("Tri-state check box"), "checkBox");
  261. checkBox->setTristate(true);
  262. checkBox->setCheckState(Qt::PartiallyChecked);
  263. auto checkableLayout = new QVBoxLayout;
  264. checkableLayout->addWidget(radioButton1);
  265. checkableLayout->addWidget(radioButton2);
  266. checkableLayout->addWidget(radioButton3);
  267. checkableLayout->addWidget(checkBox);
  268. checkableLayout->addStretch(1);
  269. auto mainLayout = new QHBoxLayout(result);
  270. mainLayout->addLayout(buttonLayout);
  271. mainLayout->addLayout(checkableLayout);
  272. mainLayout->addStretch();
  273. return result;
  274. }
  275. static QWidget *embedIntoHBoxLayout(QWidget *w, int margin = 5)
  276. {
  277. auto result = new QWidget;
  278. auto layout = new QHBoxLayout(result);
  279. layout->setContentsMargins(margin, margin, margin, margin);
  280. layout->addWidget(w);
  281. return result;
  282. }
  283. QToolBox *WidgetGallery::createTextToolBox()
  284. {
  285. auto result = createWidget<QToolBox>("toolBox");
  286. const QString plainText = tr("Twinkle, twinkle, little star,\n"
  287. "How I wonder what you are.\n"
  288. "Up above the world so high,\n"
  289. "Like a diamond in the sky.\n"
  290. "Twinkle, twinkle, little star,\n"
  291. "How I wonder what you are!\n");
  292. // Create centered/italic HTML rich text
  293. QString richText = QLatin1String("<html><head/><body><i>");
  294. for (const auto &line : QStringView{ plainText }.split(QLatin1Char('\n')))
  295. richText += QString::fromLatin1("<center>%1</center>").arg(line);
  296. richText += QLatin1String("</i></body></html>");
  297. auto textEdit = createWidget1<QTextEdit>(richText, "textEdit");
  298. auto plainTextEdit = createWidget1<QPlainTextEdit>(plainText, "plainTextEdit");
  299. systemInfoTextBrowser = createWidget<QTextBrowser>("systemInfoTextBrowser");
  300. result->addItem(embedIntoHBoxLayout(textEdit), tr("Text Edit"));
  301. result->addItem(embedIntoHBoxLayout(plainTextEdit), tr("Plain Text Edit"));
  302. result->addItem(embedIntoHBoxLayout(systemInfoTextBrowser), tr("Text Browser"));
  303. return result;
  304. }
  305. QTabWidget *WidgetGallery::createItemViewTabWidget()
  306. {
  307. auto result = createWidget<QTabWidget>("bottomLeftTabWidget");
  308. result->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
  309. auto treeView = createWidget<QTreeView>("treeView");
  310. auto fileSystemModel = new QFileSystemModel(treeView);
  311. fileSystemModel->setRootPath(QDir::rootPath());
  312. treeView->setModel(fileSystemModel);
  313. auto tableWidget = createWidget<QTableWidget>("tableWidget");
  314. tableWidget->setRowCount(10);
  315. tableWidget->setColumnCount(10);
  316. auto listModel = new QStandardItemModel(0, 1, result);
  317. listModel->appendRow(new QStandardItem(QIcon(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-128.png")),
  318. tr("Directory")));
  319. listModel->appendRow(new QStandardItem(QIcon(QLatin1String(":/qt-project.org/styles/commonstyle/images/computer-32.png")),
  320. tr("Computer")));
  321. auto listView = createWidget<QListView>("listView");
  322. listView->setModel(listModel);
  323. auto iconModeListView = createWidget<QListView>("iconModeListView");
  324. iconModeListView->setViewMode(QListView::IconMode);
  325. iconModeListView->setModel(listModel);
  326. result->addTab(embedIntoHBoxLayout(treeView), tr("&Tree View"));
  327. result->addTab(embedIntoHBoxLayout(tableWidget), tr("T&able"));
  328. result->addTab(embedIntoHBoxLayout(listView), tr("&List"));
  329. result->addTab(embedIntoHBoxLayout(iconModeListView), tr("&Icon Mode List"));
  330. return result;
  331. }
  332. QGroupBox *WidgetGallery::createSimpleInputWidgetsGroupBox()
  333. {
  334. auto result = createWidget1<QGroupBox>(tr("Simple Input Widgets"), "bottomRightGroupBox");
  335. result->setCheckable(true);
  336. result->setChecked(true);
  337. auto lineEdit = createWidget1<QLineEdit>("s3cRe7", "lineEdit");
  338. lineEdit->setClearButtonEnabled(true);
  339. lineEdit->setEchoMode(QLineEdit::Password);
  340. auto spinBox = createWidget<QSpinBox>("spinBox", result);
  341. spinBox->setValue(50);
  342. auto dateTimeEdit = createWidget<QDateTimeEdit>("dateTimeEdit", result);
  343. dateTimeEdit->setDateTime(QDateTime::currentDateTime());
  344. auto slider = createWidget<QSlider>("slider", result);
  345. slider->setOrientation(Qt::Horizontal);
  346. slider->setValue(40);
  347. auto scrollBar = createWidget<QScrollBar>("scrollBar", result);
  348. scrollBar->setOrientation(Qt::Horizontal);
  349. setClassNameToolTip(scrollBar);
  350. scrollBar->setValue(60);
  351. auto dial = createWidget<QDial>("dial", result);
  352. dial->setValue(30);
  353. dial->setNotchesVisible(true);
  354. auto layout = new QGridLayout(result);
  355. layout->addWidget(lineEdit, 0, 0, 1, 2);
  356. layout->addWidget(spinBox, 1, 0, 1, 2);
  357. layout->addWidget(dateTimeEdit, 2, 0, 1, 2);
  358. layout->addWidget(slider, 3, 0);
  359. layout->addWidget(scrollBar, 4, 0);
  360. layout->addWidget(dial, 3, 1, 2, 1);
  361. layout->setRowStretch(5, 1);
  362. return result;
  363. }
  364. QProgressBar *WidgetGallery::createProgressBar()
  365. {
  366. auto result = createWidget<QProgressBar>("progressBar");
  367. result->setRange(0, 10000);
  368. result->setValue(0);
  369. auto timer = new QTimer(this);
  370. connect(timer, &QTimer::timeout, this, &WidgetGallery::advanceProgressBar);
  371. timer->start(1000);
  372. return result;
  373. }
  374. void WidgetGallery::updateSystemInfo()
  375. {
  376. QString systemInfo;
  377. QTextStream str(&systemInfo);
  378. str << "<html><head/><body><h3>Build</h3><p>" << QLibraryInfo::build() << "</p>"
  379. << "<h3>Operating System</h3><p>" << QSysInfo::prettyProductName() << "</p>"
  380. << "<h3>Screens</h3><p>High DPI scale factor rounding policy: "
  381. << highDpiScaleFactorRoundingPolicy() << "</p><ol>";
  382. const auto screens = QGuiApplication::screens();
  383. for (auto screen : screens) {
  384. const bool current = screen == this->screen();
  385. str << "<li>";
  386. if (current)
  387. str << "<i>";
  388. str << '"' << screen->name() << "\" " << screen->geometry() << ", "
  389. << screen->logicalDotsPerInchX() << "DPI, DPR="
  390. << screen->devicePixelRatio();
  391. if (current)
  392. str << "</i>";
  393. str << "</li>";
  394. }
  395. str << "</ol></body></html>";
  396. systemInfoTextBrowser->setHtml(systemInfo);
  397. }
  398. void WidgetGallery::helpOnCurrentWidget()
  399. {
  400. // Skip over internal widgets
  401. for (auto w = QApplication::widgetAt(QCursor::pos(screen())); w; w = w->parentWidget()) {
  402. const QString name = w->objectName();
  403. if (!name.isEmpty() && !name.startsWith(QLatin1String("qt_"))) {
  404. launchHelp(w);
  405. break;
  406. }
  407. }
  408. }