File indexing completed on 2024-05-19 04:58:50

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com>
0004 *
0005 * This program is free software: you can redistribute it and/or modify
0006 * it under the terms of the GNU General Public License as published by
0007 * the Free Software Foundation, either version 3 of the License, or
0008 * (at your option) any later version.
0009 *
0010 * This program is distributed in the hope that it will be useful,
0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 * GNU General Public License for more details.
0014 *
0015 * You should have received a copy of the GNU General Public License
0016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 * ============================================================ */
0018 #include "locationbar.h"
0019 #include "browserwindow.h"
0020 #include "tabbedwebview.h"
0021 #include "mainapplication.h"
0022 #include "webpage.h"
0023 #include "tabwidget.h"
0024 #include "bookmarksicon.h"
0025 #include "bookmarks.h"
0026 #include "bookmarkitem.h"
0027 #include "bookmarkstoolbar.h"
0028 #include "siteicon.h"
0029 #include "goicon.h"
0030 #include "downicon.h"
0031 #include "qztools.h"
0032 #include "iconprovider.h"
0033 #include "qzsettings.h"
0034 #include "colors.h"
0035 #include "autofillicon.h"
0036 #include "completer/locationcompleter.h"
0037 #include "zoomlabel.h"
0038 
0039 #include <QTimer>
0040 #include <QMimeData>
0041 #include <QCompleter>
0042 #include <QStringListModel>
0043 #include <QContextMenuEvent>
0044 #include <QStyleOptionFrame>
0045 
0046 LocationBar::LocationBar(QWidget *parent)
0047     : LineEdit(parent)
0048     , m_window(nullptr)
0049     , m_webView(nullptr)
0050     , m_holdingAlt(false)
0051     , m_oldTextLength(0)
0052     , m_currentTextLength(0)
0053     , m_loadProgress(0)
0054     , m_progressVisible(false)
0055 {
0056     setObjectName("locationbar");
0057     setDragEnabled(true);
0058 
0059     // Disable KDE QLineEdit transitions, it breaks with setText() && home()
0060     setProperty("_kde_no_animations", QVariant(true));
0061 
0062     m_bookmarkIcon = new BookmarksIcon(this);
0063     m_goIcon = new GoIcon(this);
0064     m_siteIcon = new SiteIcon(this);
0065     m_autofillIcon = new AutoFillIcon(this);
0066     auto* down = new DownIcon(this);
0067     m_zoomlabel = new ZoomLabel(this);
0068 
0069     addWidget(m_siteIcon, LineEdit::LeftSide);
0070     addWidget(m_zoomlabel, LineEdit::RightSide);
0071     addWidget(m_autofillIcon, LineEdit::RightSide);
0072     addWidget(m_bookmarkIcon, LineEdit::RightSide);
0073     addWidget(m_goIcon, LineEdit::RightSide);
0074     addWidget(down, LineEdit::RightSide);
0075 
0076     m_completer = new LocationCompleter(this);
0077     m_completer->setLocationBar(this);
0078     connect(m_completer, &LocationCompleter::showCompletion, this, &LocationBar::showCompletion);
0079     connect(m_completer, &LocationCompleter::showDomainCompletion, this, &LocationBar::showDomainCompletion);
0080     connect(m_completer, &LocationCompleter::clearCompletion, this, &LocationBar::clearCompletion);
0081     connect(m_completer, &LocationCompleter::loadRequested, this, &LocationBar::loadRequest);
0082     connect(m_completer, &LocationCompleter::popupClosed, this, &LocationBar::updateSiteIcon);
0083 
0084     m_domainCompleterModel = new QStringListModel(this);
0085     auto* domainCompleter = new QCompleter(this);
0086     domainCompleter->setCompletionMode(QCompleter::InlineCompletion);
0087     domainCompleter->setModel(m_domainCompleterModel);
0088     setCompleter(domainCompleter);
0089 
0090     m_progressTimer = new QTimer(this);
0091     m_progressTimer->setInterval(700);
0092     m_progressTimer->setSingleShot(true);
0093     connect(m_progressTimer, &QTimer::timeout, this, &LocationBar::hideProgress);
0094 
0095     editAction(PasteAndGo)->setText(tr("Paste And &Go"));
0096     editAction(PasteAndGo)->setIcon(QIcon::fromTheme(QSL("edit-paste")));
0097     connect(editAction(PasteAndGo), &QAction::triggered, this, &LocationBar::pasteAndGo);
0098 
0099     connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEdited(QString)));
0100     connect(m_goIcon, &ClickableLabel::clicked, this, &LocationBar::requestLoadUrl);
0101     connect(down, &ClickableLabel::clicked, m_completer, &LocationCompleter::showMostVisited);
0102     connect(mApp->searchEnginesManager(), &SearchEnginesManager::activeEngineChanged, this, &LocationBar::updatePlaceHolderText);
0103     connect(mApp->searchEnginesManager(), &SearchEnginesManager::defaultEngineChanged, this, &LocationBar::updatePlaceHolderText);
0104     connect(mApp, &MainApplication::settingsReloaded, this, &LocationBar::loadSettings);
0105 
0106     loadSettings();
0107 
0108     updateSiteIcon();
0109 
0110     // Hide icons by default
0111     m_goIcon->setVisible(qzSettings->alwaysShowGoIcon);
0112     m_autofillIcon->hide();
0113 
0114     QTimer::singleShot(0, this, &LocationBar::updatePlaceHolderText);
0115 }
0116 
0117 BrowserWindow *LocationBar::browserWindow() const
0118 {
0119     return m_window;
0120 }
0121 
0122 void LocationBar::setBrowserWindow(BrowserWindow *window)
0123 {
0124     m_window = window;
0125     m_completer->setMainWindow(m_window);
0126     m_siteIcon->setBrowserWindow(m_window);
0127 }
0128 
0129 TabbedWebView* LocationBar::webView() const
0130 {
0131     return m_webView;
0132 }
0133 
0134 void LocationBar::setWebView(TabbedWebView* view)
0135 {
0136     m_webView = view;
0137 
0138     m_bookmarkIcon->setWebView(m_webView);
0139     m_siteIcon->setWebView(m_webView);
0140     m_zoomlabel->setWebView(m_webView);
0141     m_autofillIcon->setWebView(m_webView);
0142 
0143     connect(m_webView, &QWebEngineView::loadStarted, this, &LocationBar::loadStarted);
0144     connect(m_webView, &QWebEngineView::loadProgress, this, &LocationBar::loadProgress);
0145     connect(m_webView, &QWebEngineView::loadFinished, this, &LocationBar::loadFinished);
0146     connect(m_webView, &QWebEngineView::urlChanged, this, &LocationBar::showUrl);
0147     connect(m_webView, &WebView::privacyChanged, this, &LocationBar::setPrivacyState);
0148 }
0149 
0150 void LocationBar::setText(const QString &text)
0151 {
0152     m_oldTextLength = text.length();
0153     m_currentTextLength = m_oldTextLength;
0154 
0155     LineEdit::setText(text);
0156 
0157     refreshTextFormat();
0158 }
0159 
0160 void LocationBar::updatePlaceHolderText()
0161 {
0162     if (qzSettings->searchFromAddressBar) {
0163         setPlaceholderText(tr("Enter address or search with %1").arg(searchEngine().name));
0164     } else
0165         setPlaceholderText(tr("Enter address"));
0166 }
0167 
0168 void LocationBar::showCompletion(const QString &completion, bool completeDomain)
0169 {
0170     LineEdit::setText(completion);
0171 
0172     // Move cursor to the end
0173     end(false);
0174 
0175     if (completeDomain) {
0176         completer()->complete();
0177     }
0178 
0179     updateSiteIcon();
0180 }
0181 
0182 void LocationBar::clearCompletion()
0183 {
0184     m_webView->setFocus();
0185     showUrl(m_webView->url());
0186 }
0187 
0188 void LocationBar::showDomainCompletion(const QString &completion)
0189 {
0190     m_domainCompleterModel->setStringList(QStringList() << completion);
0191 
0192     // We need to manually force the completion because model is updated asynchronously
0193     // But only force completion when the user actually added new text
0194     if (!completion.isEmpty() && m_oldTextLength < m_currentTextLength)
0195         completer()->complete();
0196 }
0197 
0198 QString LocationBar::convertUrlToText(const QUrl &url)
0199 {
0200     // It was most probably entered by user, so don't urlencode it
0201     // Also don't urlencode JavaScript code
0202     if (url.scheme().isEmpty() || url.scheme() == QL1S("javascript")) {
0203         return QUrl::fromPercentEncoding(url.toEncoded());
0204     }
0205 
0206     QString stringUrl = QzTools::urlEncodeQueryString(url);
0207 
0208     if (stringUrl == QL1S("falkon:speeddial") || stringUrl == QL1S("about:blank")) {
0209         stringUrl.clear();
0210     }
0211 
0212     return stringUrl;
0213 }
0214 
0215 SearchEnginesManager::Engine LocationBar::searchEngine()
0216 {
0217     if (!qzSettings->searchFromAddressBar) {
0218         return {};
0219     } else if (qzSettings->searchWithDefaultEngine) {
0220         return mApp->searchEnginesManager()->defaultEngine();
0221     } else {
0222         return mApp->searchEnginesManager()->activeEngine();
0223     }
0224 }
0225 
0226 LocationBar::LoadAction LocationBar::loadAction(const QString &text)
0227 {
0228     LoadAction action;
0229 
0230     const QString &t = text.trimmed();
0231 
0232     if (t.isEmpty()) {
0233         return action;
0234     }
0235 
0236     // Check for Search Engine shortcut
0237     const int firstSpacePos = t.indexOf(QLatin1Char(' '));
0238     if (qzSettings->searchFromAddressBar && firstSpacePos != -1) {
0239         const QString shortcut = t.left(firstSpacePos);
0240         const QString searchedString = t.mid(firstSpacePos).trimmed();
0241 
0242         SearchEngine en = mApp->searchEnginesManager()->engineForShortcut(shortcut);
0243         if (en.isValid()) {
0244             action.type = LoadAction::Search;
0245             action.searchEngine = en;
0246             action.loadRequest = mApp->searchEnginesManager()->searchResult(en, searchedString);
0247             return action;
0248         }
0249     }
0250 
0251     // Check for Bookmark keyword
0252     const QList<BookmarkItem*> items = mApp->bookmarks()->searchKeyword(t);
0253     if (!items.isEmpty()) {
0254         BookmarkItem* item = items.at(0);
0255         action.type = LoadAction::Bookmark;
0256         action.bookmark = item;
0257         action.loadRequest.setUrl(item->url());
0258         return action;
0259     }
0260 
0261     if (!qzSettings->searchFromAddressBar) {
0262         const QUrl &guessedUrl = QUrl::fromUserInput(t);
0263         if (guessedUrl.isValid()) {
0264             action.type = LoadAction::Url;
0265             action.loadRequest = guessedUrl;
0266         }
0267         return action;
0268     }
0269 
0270     // Check for one word search
0271     if (t != QL1S("localhost")
0272             && !QzTools::containsSpace(t)
0273             && !t.contains(QL1C('.'))
0274             && !t.contains(QL1C(':'))
0275             && !t.contains(QL1C('/'))
0276        ) {
0277         action.type = LoadAction::Search;
0278         action.searchEngine = searchEngine();
0279         action.loadRequest = mApp->searchEnginesManager()->searchResult(searchEngine(), t);
0280         return action;
0281     }
0282 
0283     // Otherwise load as url
0284     const QUrl guessedUrl = QUrl::fromUserInput(t);
0285     if (guessedUrl.isValid()) {
0286         // Always allow javascript: to be loaded
0287         const bool forceLoad = guessedUrl.scheme() == QL1S("javascript");
0288         // Only allow spaces in query
0289         if (forceLoad || !QzTools::containsSpace(t) || !QzTools::containsSpace(guessedUrl.toString(QUrl::RemoveQuery))) {
0290             // Only allow supported schemes
0291             if (forceLoad || WebPage::supportedSchemes().contains(guessedUrl.scheme())) {
0292                 action.type = LoadAction::Url;
0293                 action.loadRequest = guessedUrl;
0294                 return action;
0295             }
0296         }
0297     }
0298 
0299     // Search when creating url failed
0300     action.type = LoadAction::Search;
0301     action.searchEngine = searchEngine();
0302     action.loadRequest = mApp->searchEnginesManager()->searchResult(searchEngine(), t);
0303     return action;
0304 }
0305 
0306 void LocationBar::refreshTextFormat()
0307 {
0308     if (!m_webView) {
0309         return;
0310     }
0311 
0312     TextFormat textFormat;
0313     const QString hostName = m_webView->url().isEmpty() ? QUrl(text()).host() : m_webView->url().host();
0314 
0315     if (!hostName.isEmpty()) {
0316         const int hostPos = text().indexOf(hostName);
0317 
0318         if (hostPos > 0) {
0319             QTextCharFormat format;
0320             format.setForeground(Colors::mid(palette().color(QPalette::Base), palette().color(QPalette::Text), 1, 1));
0321 
0322             QTextLayout::FormatRange schemePart;
0323             schemePart.start = 0;
0324             schemePart.length = hostPos;
0325             schemePart.format = format;
0326 
0327             QTextLayout::FormatRange hostPart;
0328             hostPart.start = hostPos;
0329             hostPart.length = hostName.size();
0330 
0331             QTextLayout::FormatRange remainingPart;
0332             remainingPart.start = hostPos + hostName.size();
0333             remainingPart.length = text().size() - remainingPart.start;
0334             remainingPart.format = format;
0335 
0336             textFormat.append(schemePart);
0337             textFormat.append(hostPart);
0338             textFormat.append(remainingPart);
0339         }
0340     }
0341 
0342     setTextFormat(textFormat);
0343 }
0344 
0345 void LocationBar::requestLoadUrl()
0346 {
0347     loadRequest(loadAction(text()).loadRequest);
0348     updateSiteIcon();
0349 }
0350 
0351 void LocationBar::textEdited(const QString &text)
0352 {
0353     m_oldTextLength = m_currentTextLength;
0354     m_currentTextLength = text.length();
0355 
0356     if (!text.isEmpty()) {
0357         m_completer->complete(text);
0358         m_siteIcon->setIcon(QIcon::fromTheme(QSL("edit-find"), QIcon(QSL(":icons/menu/search-icon.svg"))));
0359     }
0360     else {
0361         m_completer->closePopup();
0362     }
0363 
0364     setGoIconVisible(true);
0365 }
0366 
0367 void LocationBar::setGoIconVisible(bool state)
0368 {
0369     if (state) {
0370         m_bookmarkIcon->hide();
0371         m_zoomlabel->hide();
0372         m_goIcon->show();
0373     }
0374     else {
0375         m_bookmarkIcon->show();
0376         m_zoomlabel->requestShow();
0377 
0378         if (!qzSettings->alwaysShowGoIcon) {
0379             m_goIcon->hide();
0380         }
0381     }
0382 
0383     updateTextMargins();
0384 }
0385 
0386 void LocationBar::showUrl(const QUrl &url)
0387 {
0388     if (hasFocus() || url.isEmpty()) {
0389         return;
0390     }
0391 
0392     const QString stringUrl = convertUrlToText(url);
0393 
0394     if (text() == stringUrl) {
0395         home(false);
0396         refreshTextFormat();
0397         return;
0398     }
0399 
0400     // Set converted url as text
0401     setText(stringUrl);
0402 
0403     // Move cursor to the start
0404     home(false);
0405 
0406     m_bookmarkIcon->checkBookmark(url);
0407 }
0408 
0409 void LocationBar::loadRequest(const LoadRequest &request)
0410 {
0411     if (!m_webView->webTab()->isRestored()) {
0412         return;
0413     }
0414 
0415     const QString urlString = convertUrlToText(request.url());
0416 
0417     m_completer->closePopup();
0418     m_webView->setFocus();
0419 
0420     if (urlString != text()) {
0421         setText(urlString);
0422     }
0423 
0424     m_webView->userLoadAction(request);
0425 }
0426 
0427 void LocationBar::updateSiteIcon()
0428 {
0429     if (m_completer->isVisible()) {
0430         m_siteIcon->setIcon(QIcon::fromTheme(QSL("edit-find"), QIcon(QSL(":icons/menu/search-icon.svg"))));
0431     } else {
0432         QIcon icon = IconProvider::emptyWebIcon();
0433         if (property("secured").toBool()) {
0434             icon = QIcon::fromTheme(QSL("document-encrypted"), icon);
0435         }
0436         m_siteIcon->setIcon(QIcon(icon.pixmap(16)));
0437     }
0438 }
0439 
0440 void LocationBar::setPrivacyState(bool state)
0441 {
0442     m_siteIcon->setProperty("secured", QVariant(state));
0443     m_siteIcon->style()->unpolish(m_siteIcon);
0444     m_siteIcon->style()->polish(m_siteIcon);
0445 
0446     setProperty("secured", QVariant(state));
0447     style()->unpolish(this);
0448     style()->polish(this);
0449 
0450     updateSiteIcon();
0451 }
0452 
0453 void LocationBar::pasteAndGo()
0454 {
0455     clear();
0456     paste();
0457     requestLoadUrl();
0458 }
0459 
0460 void LocationBar::contextMenuEvent(QContextMenuEvent* event)
0461 {
0462     QMenu* menu = createContextMenu();
0463     menu->setAttribute(Qt::WA_DeleteOnClose);
0464 
0465     // Prevent choosing first option with double rightclick
0466     QPoint pos = event->globalPos();
0467     pos.setY(pos.y() + 1);
0468     menu->popup(pos);
0469 }
0470 
0471 void LocationBar::showEvent(QShowEvent* event)
0472 {
0473     LineEdit::showEvent(event);
0474 
0475     refreshTextFormat();
0476 }
0477 
0478 void LocationBar::focusInEvent(QFocusEvent* event)
0479 {
0480     if (m_webView) {
0481         const QString stringUrl = convertUrlToText(m_webView->url());
0482 
0483         // Text has been edited, let's show go button
0484         if (stringUrl != text()) {
0485             setGoIconVisible(true);
0486         }
0487     }
0488 
0489     clearTextFormat();
0490     LineEdit::focusInEvent(event);
0491 
0492     if (m_window && Settings().value(QSL("Browser-View-Settings/instantBookmarksToolbar")).toBool()) {
0493         m_window->bookmarksToolbar()->show();
0494     }
0495 }
0496 
0497 void LocationBar::focusOutEvent(QFocusEvent* event)
0498 {
0499     // Context menu or completer popup were opened
0500     // Let's block focusOutEvent to trick QLineEdit and paint cursor properly
0501     if (event->reason() == Qt::PopupFocusReason) {
0502         return;
0503     }
0504 
0505     LineEdit::focusOutEvent(event);
0506 
0507     setGoIconVisible(false);
0508 
0509     if (text().trimmed().isEmpty()) {
0510         clear();
0511     }
0512 
0513     refreshTextFormat();
0514 
0515     if (m_window && Settings().value(QSL("Browser-View-Settings/instantBookmarksToolbar")).toBool()) {
0516         m_window->bookmarksToolbar()->hide();
0517     }
0518 }
0519 
0520 void LocationBar::dropEvent(QDropEvent* event)
0521 {
0522     if (event->mimeData()->hasUrls()) {
0523         const QUrl dropUrl = event->mimeData()->urls().at(0);
0524         if (WebView::isUrlValid(dropUrl)) {
0525             setText(dropUrl.toString());
0526             loadRequest(dropUrl);
0527 
0528             QFocusEvent event(QFocusEvent::FocusOut);
0529             LineEdit::focusOutEvent(&event);
0530             return;
0531         }
0532     }
0533     else if (event->mimeData()->hasText()) {
0534         const QString dropText = event->mimeData()->text().trimmed();
0535         const QUrl dropUrl = QUrl(dropText);
0536         if (WebView::isUrlValid(dropUrl)) {
0537             setText(dropUrl.toString());
0538             loadRequest(dropUrl);
0539 
0540             QFocusEvent event(QFocusEvent::FocusOut);
0541             LineEdit::focusOutEvent(&event);
0542             return;
0543         } else {
0544             setText(dropText);
0545             setFocus();
0546             return;
0547         }
0548     }
0549 
0550     LineEdit::dropEvent(event);
0551 }
0552 
0553 void LocationBar::keyPressEvent(QKeyEvent* event)
0554 {
0555     switch (event->key()) {
0556     case Qt::Key_V:
0557         if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
0558             pasteAndGo();
0559             event->accept();
0560             return;
0561         }
0562         break;
0563 
0564     case Qt::Key_Down:
0565         m_completer->complete(text());
0566         break;
0567 
0568     case Qt::Key_Left:
0569         m_completer->closePopup();
0570         break;
0571 
0572     case Qt::Key_Escape:
0573         m_webView->setFocus();
0574         showUrl(m_webView->url());
0575         event->accept();
0576         break;
0577 
0578     case Qt::Key_Alt:
0579         m_holdingAlt = true;
0580         break;
0581 
0582     case Qt::Key_Return:
0583     case Qt::Key_Enter:
0584         switch (event->modifiers()) {
0585         case Qt::ControlModifier:
0586             if (!text().endsWith(QL1S(".com")))
0587                 setText(text().append(QL1S(".com")));
0588             requestLoadUrl();
0589             m_holdingAlt = false;
0590             break;
0591 
0592         case Qt::AltModifier:
0593             m_completer->closePopup();
0594             if (m_window) {
0595                 m_window->tabWidget()->addView(loadAction(text()).loadRequest);
0596             }
0597             m_holdingAlt = false;
0598             break;
0599 
0600         default:
0601             requestLoadUrl();
0602             m_holdingAlt = false;
0603         }
0604 
0605         break;
0606 
0607     case Qt::Key_0:
0608     case Qt::Key_1:
0609     case Qt::Key_2:
0610     case Qt::Key_3:
0611     case Qt::Key_4:
0612     case Qt::Key_5:
0613     case Qt::Key_6:
0614     case Qt::Key_7:
0615     case Qt::Key_8:
0616     case Qt::Key_9:
0617         if (event->modifiers() & Qt::AltModifier || event->modifiers() & Qt::ControlModifier) {
0618             event->ignore();
0619             m_holdingAlt = false;
0620             return;
0621         }
0622         break;
0623 
0624     default:
0625         m_holdingAlt = false;
0626     }
0627 
0628     LineEdit::keyPressEvent(event);
0629 }
0630 
0631 void LocationBar::loadStarted()
0632 {
0633     m_progressVisible = true;
0634     m_progressTimer->stop();
0635     m_autofillIcon->hide();
0636 }
0637 
0638 void LocationBar::loadProgress(int progress)
0639 {
0640     if (qzSettings->showLoadingProgress) {
0641         m_loadProgress = progress;
0642         update();
0643     }
0644 }
0645 
0646 void LocationBar::loadFinished()
0647 {
0648     if (qzSettings->showLoadingProgress) {
0649         m_progressTimer->start();
0650     }
0651 
0652     auto* page = qobject_cast<WebPage*>(m_webView->page());
0653 
0654     if (page && !page->autoFillUsernames().isEmpty()) {
0655         m_autofillIcon->setUsernames(page->autoFillUsernames());
0656         m_autofillIcon->show();
0657     }
0658 }
0659 
0660 void LocationBar::loadSettings()
0661 {
0662     Settings settings;
0663     settings.beginGroup(QSL("AddressBar"));
0664     m_progressStyle = static_cast<ProgressStyle>(settings.value(QSL("ProgressStyle"), 0).toInt());
0665     bool customColor = settings.value(QSL("UseCustomProgressColor"), false).toBool();
0666     m_progressColor = customColor ? settings.value(QSL("CustomProgressColor"), palette().color(QPalette::Highlight)).value<QColor>() : QColor();
0667     settings.endGroup();
0668 }
0669 
0670 void LocationBar::hideProgress()
0671 {
0672     if (qzSettings->showLoadingProgress) {
0673         m_progressVisible = false;
0674         update();
0675     }
0676 }
0677 
0678 void LocationBar::paintEvent(QPaintEvent* event)
0679 {
0680     LineEdit::paintEvent(event);
0681 
0682     // Show loading progress
0683     if (qzSettings->showLoadingProgress && m_progressVisible) {
0684         QStyleOptionFrame option;
0685         initStyleOption(&option);
0686 
0687         QMargins margins = textMargins();
0688 
0689         QRect contentsRect = style()->subElementRect(QStyle::SE_LineEditContents, &option, this);
0690         contentsRect.adjust(
0691             margins.left(), margins.top(), -margins.right(), -margins.bottom()
0692         );
0693 
0694         QColor bg = m_progressColor;
0695         if (!bg.isValid() || bg.alpha() == 0) {
0696             bg = Colors::mid(palette().color(QPalette::Base), palette().color(QPalette::Text), m_progressStyle > 0 ? 4 : 8, 1);
0697         }
0698 
0699         QPainter p(this);
0700         p.setBrush(QBrush(bg));
0701 
0702         // We are painting over text, make sure the text stays visible
0703         p.setOpacity(0.5);
0704 
0705         QPen outlinePen(bg.darker(110), 0.8);
0706         p.setPen(outlinePen);
0707 
0708         switch (m_progressStyle) {
0709         case ProgressFilled: {
0710             QRect bar = contentsRect.adjusted(0, 1, 0, -1);
0711             bar.setWidth(bar.width() * m_loadProgress / 100);
0712             const int roundness = bar.height() / 4.0;
0713             p.drawRoundedRect(bar, roundness, roundness);
0714             break;
0715         }
0716         case ProgressBottom: {
0717             outlinePen.setWidthF(0.3);
0718             outlinePen.setColor(outlinePen.color().darker(130));
0719             p.setPen(outlinePen);
0720             QRect bar(contentsRect.x(), contentsRect.bottom() - 3,
0721                       contentsRect.width() * m_loadProgress / 100.0, 3);
0722             p.drawRoundedRect(bar, 1, 1);
0723             break;
0724         }
0725         case ProgressTop: {
0726             outlinePen.setWidthF(0.3);
0727             outlinePen.setColor(outlinePen.color().darker(130));
0728             p.setPen(outlinePen);
0729             QRect bar(contentsRect.x(), contentsRect.top() + 1, contentsRect.width() * m_loadProgress / 100.0, 3);
0730             p.drawRoundedRect(bar, 1, 1);
0731             break;
0732         }
0733         default:
0734             break;
0735         }
0736     }
0737 }