diff --git a/src/plugins/help/CMakeLists.txt b/src/plugins/help/CMakeLists.txt
index 05d2b81152a..41dac7e5622 100644
--- a/src/plugins/help/CMakeLists.txt
+++ b/src/plugins/help/CMakeLists.txt
@@ -17,6 +17,7 @@ add_qtc_plugin(Help
helpviewer.cpp helpviewer.h
helpwidget.cpp helpwidget.h
localhelpmanager.cpp localhelpmanager.h
+ offline-dark.css
openpagesmanager.cpp openpagesmanager.h
openpagesswitcher.cpp openpagesswitcher.h
openpageswidget.cpp openpageswidget.h
diff --git a/src/plugins/help/help.qrc b/src/plugins/help/help.qrc
index b00e06409b4..84b6776caaa 100644
--- a/src/plugins/help/help.qrc
+++ b/src/plugins/help/help.qrc
@@ -8,5 +8,6 @@
images/mode_help_mask@2x.png
images/macos_touchbar_help.png
images/macos_touchbar_help@2x.png
+ offline-dark.css
diff --git a/src/plugins/help/litehtmlhelpviewer.cpp b/src/plugins/help/litehtmlhelpviewer.cpp
index 0e8a9939017..f966c018f92 100644
--- a/src/plugins/help/litehtmlhelpviewer.cpp
+++ b/src/plugins/help/litehtmlhelpviewer.cpp
@@ -9,8 +9,10 @@
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -24,15 +26,55 @@ using namespace Help::Internal;
const int kMaxHistoryItems = 20;
-static QByteArray getData(const QUrl &url)
+static void setLight(QWidget *widget)
{
- // TODO: this is just a hack for Qt documentation
+ QPalette p = widget->palette();
+ p.setColor(QPalette::Base, Qt::white);
+ p.setColor(QPalette::Text, Qt::black);
+ widget->setPalette(p);
+}
+
+static void setPaletteFromTheme(QWidget *widget)
+{
+ if (Utils::creatorTheme())
+ widget->setPalette(Utils::creatorTheme()->palette());
+}
+
+static bool isDarkTheme()
+{
+ return Utils::creatorTheme() && Utils::creatorTheme()->flag(Utils::Theme::DarkUserInterface);
+}
+
+static QByteArray getData(const QUrl &url, QWidget *widget)
+{
+ // This is a hack for Qt documentation,
// which decides to use a simpler CSS if the viewer does not have JavaScript
- // which was a hack to decide if we are viewing in QTextBrowser or QtWebEngine et al
+ // which was a hack to decide if we are viewing in QTextBrowser or QtWebEngine et al.
+ // Force it to use the "normal" offline CSS even without JavaScript, since litehtml can
+ // handle that, and inject a dark themed CSS into Qt documentation for dark Qt Creator themes
QUrl actualUrl = url;
QString path = url.path(QUrl::FullyEncoded);
static const char simpleCss[] = "/offline-simple.css";
if (path.endsWith(simpleCss)) {
+ if (isDarkTheme()) {
+ // check if dark CSS is shipped with documentation
+ QString darkPath = path;
+ darkPath.replace(simpleCss, "/offline-dark.css");
+ actualUrl.setPath(darkPath);
+ LocalHelpManager::HelpData data = LocalHelpManager::helpData(actualUrl);
+ if (!data.resolvedUrl.isValid() || data.data.isEmpty()) {
+ // fallback
+ QFile css(":/help/offline-dark.css");
+ if (css.open(QIODevice::ReadOnly))
+ data.data = css.readAll();
+ }
+ if (!data.data.isEmpty()) {
+ // we found the dark style
+ // set background dark (by using theme palette)
+ setPaletteFromTheme(widget);
+ return data.data;
+ }
+ }
path.replace(simpleCss, "/offline.css");
actualUrl.setPath(path);
}
@@ -44,7 +86,7 @@ LiteHtmlHelpViewer::LiteHtmlHelpViewer(QWidget *parent)
: HelpViewer(parent)
, m_viewer(new QLiteHtmlWidget)
{
- m_viewer->setResourceHandler([](const QUrl &url) { return getData(url); });
+ m_viewer->setResourceHandler([this](const QUrl &url) { return getData(url, this); });
m_viewer->setFrameStyle(QFrame::NoFrame);
m_viewer->viewport()->installEventFilter(this);
connect(m_viewer, &QLiteHtmlWidget::linkClicked, this, [this](const QUrl &url) {
@@ -113,6 +155,8 @@ void LiteHtmlHelpViewer::setSource(const QUrl &url)
void LiteHtmlHelpViewer::setHtml(const QString &html)
{
+ // We control the html, so use theme palette
+ setPaletteFromTheme(this);
m_viewer->setUrl({"about:invalid"});
m_viewer->setHtml(html);
}
@@ -252,8 +296,12 @@ void LiteHtmlHelpViewer::setSourceInternal(const QUrl &url, std::optional v
QUrl newUrlWithoutFragment = url;
newUrlWithoutFragment.setFragment({});
m_viewer->setUrl(url);
- if (currentUrlWithoutFragment != newUrlWithoutFragment)
- m_viewer->setHtml(QString::fromUtf8(getData(url)));
+ if (currentUrlWithoutFragment != newUrlWithoutFragment) {
+ // We do not expect the documentation to support dark themes, so start with light palette.
+ // We override this if we find Qt's dark style
+ setLight(this);
+ m_viewer->setHtml(QString::fromUtf8(getData(url, this)));
+ }
if (vscroll)
m_viewer->verticalScrollBar()->setValue(*vscroll);
else
diff --git a/src/plugins/help/offline-dark.css b/src/plugins/help/offline-dark.css
new file mode 100644
index 00000000000..559811b5295
--- /dev/null
+++ b/src/plugins/help/offline-dark.css
@@ -0,0 +1,770 @@
+body {
+ font: normal 400 14px/1.2 Arial;
+ margin-top: 50px;
+ font-family: Arial, Helvetica;
+ text-align: left;
+ margin-left: 5px;
+ margin-right: 5px;
+ background-color: #2E2F30;
+ color: #d0d0d0
+}
+
+p {
+ line-height: 20px
+}
+
+img {
+ margin-left: 0px;
+ max-width: 800px;
+ height: auto;
+ filter: brightness(85%);
+}
+
+.content .border img {
+ box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
+}
+
+.content .border .player {
+ box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
+}
+
+.content .indexboxcont li {
+ font: normal bold 13px/1 Verdana
+ }
+
+.content .normallist li {
+ font: normal 13px/1 Verdana
+ }
+
+.descr {
+ margin-top: 35px;
+ margin-bottom: 45px;
+ margin-left: 5px;
+ text-align: left;
+ vertical-align: top;
+}
+
+.name {
+ max-width: 75%;
+ font-weight: 100;
+}
+
+tt {
+ text-align: left
+}
+
+/*
+-----------
+links
+-----------
+*/
+
+a:link {
+ color: #9a9ef9;
+ text-decoration: none;
+ text-align: left;
+}
+
+a.qa-mark:target:before {
+ content: "***";
+ color: #ff0000;
+}
+
+a:hover {
+ color: #9a9ef9;
+ text-decoration:underline;
+ text-align: left;
+}
+
+a:visited {
+ color: #9a9ef9;
+ text-align: left;
+}
+
+a:visited:hover {
+ color: #9a9ef9;
+ text-align: left;
+}
+
+/*
+-----------
+offline viewing: HTML links display an icon
+-----------
+*/
+
+a[href*="http://"]::before,
+a[href*="ftp://"]::before,
+a[href*="https://"]::before {
+ content: url(../images/ico_out.png);
+ padding-right: 5px;
+}
+
+.video a {
+ background: none;
+}
+
+.flags {
+ text-decoration: none;
+ text-height: 24px;
+}
+
+.flags:target {
+ background-color: #FFFFD6;
+}
+
+/*
+-------------------------------
+NOTE styles
+-------------------------------
+*/
+.admonition {
+ padding: 5px 0 5px 40px;
+ border: #404142 1px solid;
+}
+
+.admonition.note, .admonition.important {
+ background: #353637 3px 6px no-repeat url(../images/ico_note.png);
+}
+
+.admonition.warning {
+ background: #353637 3px 6px no-repeat url(../images/ico_note_attention.png);
+}
+/*
+-------------------------------
+Top navigation
+-------------------------------
+*/
+
+.qtref {
+ display: block;
+ position: relative;
+ height: 15px;
+ z-index: 1;
+ font-size: 11px;
+ padding-right: 10px;
+ float: right;
+}
+
+.naviNextPrevious {
+ clear: both;
+ display: block;
+ position: relative;
+ text-align: right;
+ top: -30px;
+ float: right;
+ height: 20px;
+ z-index: 1;
+ padding-right: 10px;
+ padding-top: 2px;
+ vertical-align: top;
+ margin: 0px;
+}
+
+.naviNextPrevious > a:first-child {
+ background-image: url(../images/btn_prev.png);
+ background-repeat: no-repeat;
+ background-position: left;
+ padding-left: 20px;
+ height: 20px;
+ padding-left: 20px;
+ }
+
+.naviNextPrevious > a:last-child {
+ background-image: url(../images/btn_next.png);
+ background-repeat: no-repeat;
+ background-position: right;
+ padding-right: 20px;
+ height: 20px;
+ margin-left: 30px;
+ }
+
+.naviSeparator { display: none }
+/*
+-----------
+footer and license
+-----------
+*/
+
+.footer {
+ text-align: left;
+ padding-top: 45px;
+ padding-left: 5px;
+ margin-top: 45px;
+ margin-bottom: 45px;
+ font-size: 10px;
+ border-top: 1px solid #404142;
+}
+
+.footer p {
+ line-height: 14px;
+ font-size: 11px;
+ padding: 0;
+ margin: 0;
+}
+
+.footer a[href*="http://"], a[href*="ftp://"], a[href*="https://"] {
+ font-weight: bold;
+}
+
+.footerNavi {
+ width: auto;
+ text-align: right;
+ margin-top: 50px;
+ z-index: 1;
+}
+
+.navigationbar {
+ display: block;
+ position: relative;
+ border-top: 1px solid #404142;
+ border-bottom: 1px solid #404142;
+ background-color: #353637;
+ z-index: 1;
+ height: 20px;
+ padding-left: 7px;
+ margin: 0px;
+ padding-top: 2px;
+ margin-left: -5px;
+ margin-right: -5px;
+}
+
+.navigationbar .first {
+ background: url(../images/home.png);
+ background-position: left;
+ background-repeat: no-repeat;
+ padding-left: 20px;
+ }
+
+.navigationbar ul {
+ margin: 0px;
+ padding: 0px;
+ }
+
+ .navigationbar ul li {
+ list-style-type: none;
+ padding-top: 2px;
+ padding-left: 4px;
+ margin: 0;
+ height: 20px;
+ }
+
+.navigationbar li {
+ float: left
+ }
+
+ .navigationbar li a, .navigationbar td a {
+ display: block;
+ text-decoration: none;
+ background: url(../images/arrow_bc.png);
+ background-repeat: no-repeat;
+ background-position: right;
+ padding-right: 17px;
+ }
+
+table.buildversion {
+ float: right;
+ margin-top: -18px !important;
+}
+
+.navigationbar table {
+ border-radius: 0;
+ border: 0 none;
+ background-color: #F2F2F2;
+ margin: 0;
+}
+
+.navigationbar table td {
+ padding: 0;
+ border: 0 none;
+}
+
+#buildversion {
+ font-style: italic;
+ float: right;
+ margin-right: 5px;
+}
+
+#buildversion a {
+ background: none;
+}
+
+/*
+
+/* table of content
+no display
+*/
+
+/*
+-----------
+headers
+-----------
+*/
+
+@media screen {
+ .title {
+ color: #d0d0d0;
+ font-size: 20px;
+ font-weight: normal;
+ left: 0;
+ padding-bottom: 15px;
+ padding-left: 10px;
+ padding-top: 15px;
+ position: absolute;
+ right: 0;
+ top: 0;
+ background-color: #2E2F30;
+ border-bottom: 1px #404142 solid;
+ font-weight: bold;
+ margin-left: 0px;
+ margin-right: 0px;
+ }
+ .subtitle, .small-subtitle {
+ display: block;
+ clear: left;
+ }
+}
+
+h1 {
+ margin: 0
+}
+
+h2, p.h2 {
+ font: 500 16px/1.2 Arial;
+ font-weight: 100;
+ background-color: #353637;
+ padding: 4px;
+ margin-bottom: 15px;
+ margin-top: 30px;
+ border-top: #404142 1px solid;
+ border-bottom: #404142 1px solid;
+ max-width: 99%;
+}
+
+h2:target {
+ background-color: #F2F3D4;
+}
+
+h3 {
+ font: 500 14px/1.2 Arial;
+ font-weight: 100;
+ text-decoration: underline;
+ margin-bottom: 15px;
+ margin-top: 30px;
+}
+
+h3.fn, span.fn {
+ border-width: 1px;
+ border-style: solid;
+ border-color: #404142;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ background-color: #353637;
+ word-spacing: 3px;
+ padding: 5px 5px;
+ text-decoration: none;
+ font-weight: bold;
+ max-width: 75%;
+ font-size: 14px;
+ margin: 0px;
+ margin-top: 30px;
+}
+.fngroup h3.fngroupitem {
+ margin-bottom: 5px;
+}
+h3.fn code {
+ float: right;
+}
+h3.fn:target {
+ background-color: #F6F6D6;
+}
+
+.name {
+ color: #d0d0d0
+}
+
+.type {
+ color: #a4a6a8
+}
+
+/*
+-----------------
+table styles
+-----------------
+*/
+
+.table img {
+ border: none;
+ margin-left: 0px;
+ -moz-box-shadow: 0px 0px 0px #2E2F30;
+ -webkit-box-shadow: 0px 0px 0px #2E2F30;
+ box-shadow: 0px 0px 0px #2E2F30;
+}
+
+/* table with border alternative colors*/
+
+table, pre, .LegaleseLeft {
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ background-color: #353637;
+ border: 1px solid #404142;
+ border-collapse: separate;
+ margin-bottom: 25px;
+ margin-left: 15px;
+ font-size: 12px;
+ line-height: 1.2;
+}
+
+ table tr.even {
+ background-color: #2E2F30;
+ color: #a4a6a8;
+ }
+
+ table tr.odd {
+ background-color: #353637;
+ color: #a4a6a8;
+ }
+
+ table tr:target {
+ background-color: #F6F6D6;
+ }
+
+ table thead {
+ text-align: left;
+ padding-left: 20px;
+ background-color: #2E2F30;
+ border-left: none;
+ border-right: none;
+ }
+
+ table thead th {
+ padding-top: 5px;
+ padding-left: 10px;
+ padding-bottom: 5px;
+ border-bottom: 2px solid #404142;
+ padding-right: 10px;
+ }
+
+ table th {
+ text-align: left;
+ padding-left: 20px;
+ }
+
+ table td {
+ padding: 3px 15px 3px 20px;
+ border-bottom: #404142 dotted 1px;
+ }
+
+ table p {
+ margin: 0px
+ }
+
+.LegaleseLeft {
+ font-family: monospace;
+ white-space: pre-wrap;
+}
+/* table bodless & white*/
+
+.borderless {
+ border-radius: 0px 0px 0px 0px;
+ background-color: #2E2F30;
+ border: 1px solid #2E2F30;
+}
+
+.borderless tr {
+ background-color: #2E2F30;
+ color: #d0d0d0;
+ }
+
+.borderless td {
+ border: none;
+ border-bottom: #2E2F30 dotted 1px;
+ }
+
+/*
+-----------
+List
+-----------
+*/
+
+ul {
+ margin-top: 10px;
+}
+
+li {
+ margin-bottom: 10px;
+ padding-left: 8px;
+ list-style: outside;
+ text-align: left;
+}
+
+ ul > li {
+ list-style-type: square;
+ }
+
+ol {
+ margin: 10px;
+ padding: 0;
+}
+
+ol.A > li {
+ list-style-type: upper-alpha;
+}
+
+ol.a > li{
+ list-style-type: lower-alpha;
+}
+
+ol > li {
+ margin-left: 30px;
+ padding-left: 8px;
+ list-style-type: decimal;
+}
+
+ol.A > li {
+ list-style-type: upper-alpha;
+}
+
+ol.a > li {
+ list-style-type: lower-alpha;
+}
+
+ol.i > li {
+ list-style-type: lower-roman;
+}
+
+ol.I > li {
+ list-style-type: upper-roman;
+}
+
+.centerAlign {
+ text-align: left
+}
+
+.cpp, .LegaleseLeft {
+ display: block;
+ margin: 10px;
+ overflow: auto;
+ padding: 20px 20px 20px 20px;
+}
+
+.js {
+ display: block;
+ margin: 10px;
+ overflow: auto;
+ padding: 20px 20px 20px 20px;
+}
+
+.memItemLeft {
+ padding-right: 3px
+}
+
+.memItemRight {
+ padding: 3px 15px 3px 0
+}
+
+.qml {
+ display: block;
+ margin: 10px;
+ overflow: auto;
+ padding: 20px 20px 20px 20px;
+}
+
+.qmlextra {
+ padding-left: 5px;
+ float: right;
+ color: #254117;
+}
+
+.rightAlign {
+ padding: 3px 5px 3px 10px;
+ text-align: right;
+}
+
+.qmldoc {
+ margin-left: 15px
+}
+
+.flowList {
+ padding: 25px
+}
+.flowList dd {
+ display: inline-block;
+ margin-left: 10px;
+ width: 255px;
+ line-height: 1.15em;
+ overflow-x: hidden;
+ text-overflow: ellipsis
+}
+.alphaChar {
+ font-size: 2em;
+ position: relative
+}
+/*
+-----------
+Content table
+-----------
+*/
+
+@media screen {
+ .toc {
+ float: right;
+ clear: right;
+ vertical-align: top;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ background: #353637;
+ background-position: top;
+ background-repeat: repeat-x;
+ border: 1px solid #404142;
+ padding-left: 5px;
+ padding-bottom: 10px;
+ height: auto;
+ width: 200px;
+ text-align: left;
+ margin-left: 20px;
+ margin-top: 5px;
+ }
+}
+
+
+.toc h3 {
+ text-decoration: none
+}
+
+.toc h3 {
+ font: 500 14px/1.2 Arial;
+ font-weight: 100;
+ padding: 0px;
+ margin: 0px;
+ padding-top: 5px;
+ padding-left: 5px;
+}
+
+.toc ul {
+ padding-left: 10px;
+ padding-right: 5px;
+}
+
+.toc ul li {
+ margin-left: 15px;
+ marker-offset: 0px;
+ margin-bottom: 8px;
+ padding-left: 0px;
+ }
+
+.toc .level1 {
+ border: none
+}
+
+.toc .level2 {
+ border: none;
+ margin-left: 25px;
+}
+
+.level3 {
+ border: none;
+ margin-left: 30px;
+}
+
+.clearfix {
+ clear: both
+}
+
+/*
+-----------
+Landing page
+-----------
+*/
+
+.col-group {
+ white-space: nowrap;
+ vertical-align: top;
+}
+
+
+.landing h2 {
+ background-color: transparent;
+ border: none;
+ margin-bottom: 0px;
+ font-size: 18px;
+}
+
+.landing a, .landing li {
+ font-size: 13px;
+ font-weight: bold !important;
+}
+
+.col-1 {
+ display: inline-block;
+ white-space: normal;
+ width: 70%;
+ height: 100%;
+ float: left;
+}
+
+.col-2 {
+ display: inline-block;
+ white-space: normal;
+ width: 20%;
+ margin-left: 5%;
+ position: relative;
+ top: -20px;
+}
+
+.col-1 h1 {
+ margin: 20px 0 0 0;
+ }
+
+.col-1 h2 {
+ font-size: 18px;
+ font-weight: bold !important;
+}
+
+.landingicons {
+ display: inline-block;
+ width: 100%;
+}
+
+.icons1of3 {
+ display: inline-block;
+ width: 33.3333%;
+ float: left;
+}
+
+.icons1of3 h2, .doc-column h2 {
+ font-size: 15px;
+ margin: 0px;
+ padding: 0px;
+}
+
+div.multi-column {
+ position: relative;
+}
+
+div.multi-column div {
+ display: -moz-inline-box;
+ display: inline-block;
+ vertical-align: top;
+ margin-top: 1em;
+ margin-right: 4em;
+ width: 24em;
+}
+
+.mainContent .video {
+ width:40%;
+ max-width:640px;
+ margin: 15px 0 0 15px;
+ position:relative;
+ display:table
+}
+
+.mainContent .video iframe {
+ width:100%;
+ height:100%;
+ position:absolute;
+ top:0;
+ left:0
+}