| File: | builds/wireshark/wireshark/ui/qt/welcome_page.cpp |
| Warning: | line 314, column 10 Value stored to 'collapseLinks' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* welcome_page.cpp |
| 2 | * |
| 3 | * Wireshark - Network traffic analyzer |
| 4 | * By Gerald Combs <[email protected]> |
| 5 | * Copyright 1998 Gerald Combs |
| 6 | * |
| 7 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 8 | */ |
| 9 | |
| 10 | #include "config.h" |
| 11 | |
| 12 | #include <epan/prefs.h> |
| 13 | |
| 14 | #include "ui/recent.h" |
| 15 | #include "ui/urls.h" |
| 16 | |
| 17 | #include <app/application_flavor.h> |
| 18 | |
| 19 | #include "welcome_page.h" |
| 20 | #include <ui_welcome_page.h> |
| 21 | #include <ui/qt/utils/tango_colors.h> |
| 22 | #include <ui/qt/utils/color_utils.h> |
| 23 | #include <ui/qt/utils/qt_ui_utils.h> |
| 24 | #include <ui/qt/models/recentcapturefiles_list_model.h> |
| 25 | #include <ui/qt/utils/workspace_state.h> |
| 26 | #include <ui/qt/widgets/capture_card_widget.h> |
| 27 | |
| 28 | #include "main_application.h" |
| 29 | |
| 30 | #include <QClipboard> |
| 31 | #include <QDesktopServices> |
| 32 | #include <QDir> |
| 33 | #include <QListWidget> |
| 34 | #include <QMenu> |
| 35 | #include <QResizeEvent> |
| 36 | #include <QUrl> |
| 37 | #include <QWidget> |
| 38 | |
| 39 | #ifndef VERSION_FLAVOR"Development Build" |
| 40 | #define VERSION_FLAVOR"Development Build" "" |
| 41 | #endif |
| 42 | |
| 43 | WelcomePage::WelcomePage(QWidget *parent) : |
| 44 | QFrame(parent), |
| 45 | welcome_ui_(new Ui::WelcomePage), |
| 46 | #ifdef Q_OS_MAC |
| 47 | show_in_str_(tr("Show in Finder")), |
| 48 | #else |
| 49 | show_in_str_(tr("Show in Folder")), |
| 50 | #endif |
| 51 | splash_overlay_(NULL__null) |
| 52 | |
| 53 | { |
| 54 | welcome_ui_->setupUi(this); |
| 55 | |
| 56 | setContentsMargins(0, 0, 0, 0); |
| 57 | setAccessibleName(tr("Welcome page")); |
| 58 | setAccessibleDescription(tr("The %1 welcome page provides access to recent files, capture interfaces, and learning resources.").arg(mainApp->applicationName())); |
| 59 | |
| 60 | welcome_ui_->tipsSectionCard->setVisible(true); |
| 61 | |
| 62 | updateStyleSheets(); |
| 63 | applySidebarPreferences(); |
| 64 | |
| 65 | /* Handle Recent Capture Files List */ |
| 66 | // In welcome_page.cpp or wherever the list is created |
| 67 | auto *model = new RecentCaptureFilesListModel(this); |
| 68 | auto *proxyModel = new RecentCaptureFilesReverseProxyModel(this); |
| 69 | proxyModel->setSourceModel(model); |
| 70 | |
| 71 | welcome_ui_->openFileSectionRecentList->setVisible(true); |
| 72 | welcome_ui_->openFileSectionRecentList->setModel(proxyModel); |
| 73 | welcome_ui_->openFileSectionRecentList->setItemDelegate(new RecentCaptureFilesDelegate(welcome_ui_->openFileSectionRecentList)); |
| 74 | welcome_ui_->openFileSectionRecentList->setContextMenuPolicy(Qt::CustomContextMenu); |
| 75 | welcome_ui_->openFileSectionRecentList->setAccessibleName(tr("Recent capture files")); |
| 76 | welcome_ui_->openFileSectionRecentList->setAccessibleDescription(tr("List of recently opened capture files. Double-click or press Enter to open.")); |
| 77 | connect(welcome_ui_->openFileSectionRecentList, &QListView::activated, |
| 78 | this, [this]() { |
| 79 | QModelIndex index = welcome_ui_->openFileSectionRecentList->currentIndex(); |
| 80 | if (index.isValid()) { |
| 81 | QString cfile = index.data(RecentCaptureFilesListModel::FilenameRole).toString(); |
| 82 | emit recentFileActivated(cfile); |
| 83 | } |
| 84 | }); |
| 85 | connect(welcome_ui_->openFileSectionRecentList, &QListView::customContextMenuRequested, |
| 86 | this, &WelcomePage::showCaptureFilesContextMenu); |
| 87 | |
| 88 | if (WorkspaceState::instance()->recentCaptureFiles().size() > 0) { |
| 89 | welcome_ui_->openFileSectionLabel->setVisible(true); |
| 90 | welcome_ui_->openFileSectionRecentList->setVisible(true); |
| 91 | } else { |
| 92 | welcome_ui_->openFileSectionLabel->setVisible(false); |
| 93 | welcome_ui_->openFileSectionRecentList->setVisible(false); |
| 94 | } |
| 95 | |
| 96 | #ifdef Q_OS_MAC |
| 97 | welcome_ui_->openFileSectionRecentList->setAttribute(Qt::WA_MacShowFocusRect, false); |
| 98 | #endif |
| 99 | |
| 100 | welcome_ui_->openFileSectionRecentList->setTextElideMode(Qt::ElideLeft); |
| 101 | |
| 102 | connect(mainApp, &MainApplication::appInitialized, this, &WelcomePage::appInitialized); |
| 103 | connect(mainApp, &MainApplication::preferencesChanged, this, &WelcomePage::applySidebarPreferences); |
| 104 | |
| 105 | // "Capture" header click opens Capture Options dialog |
| 106 | if (auto *captureHeader = welcome_ui_->captureSectionCard->findChild<ClickableLabel*>(QStringLiteral("captureHeader")(QString(QtPrivate::qMakeStringPrivate(u"" "captureHeader"))))) { |
| 107 | connect(captureHeader, &ClickableLabel::clicked, this, []() { |
| 108 | mainApp->doTriggerMenuItem(MainApplication::CaptureOptionsDialog); |
| 109 | }); |
| 110 | } |
| 111 | |
| 112 | splash_overlay_ = new SplashOverlay(this); |
| 113 | } |
| 114 | |
| 115 | WelcomePage::~WelcomePage() |
| 116 | { |
| 117 | delete welcome_ui_; |
| 118 | } |
| 119 | |
| 120 | InterfaceFrame *WelcomePage::getInterfaceFrame() |
| 121 | { |
| 122 | return welcome_ui_->captureSectionCard->interfaceFrame(); |
| 123 | } |
| 124 | |
| 125 | CaptureCardWidget *WelcomePage::captureCard() |
| 126 | { |
| 127 | return welcome_ui_->captureSectionCard; |
| 128 | } |
| 129 | |
| 130 | const QString WelcomePage::captureFilter() |
| 131 | { |
| 132 | return welcome_ui_->captureSectionCard->captureFilter(); |
| 133 | } |
| 134 | |
| 135 | void WelcomePage::setCaptureFilter(const QString capture_filter) |
| 136 | { |
| 137 | welcome_ui_->captureSectionCard->setCaptureFilter(capture_filter); |
| 138 | } |
| 139 | |
| 140 | void WelcomePage::setCaptureFilterText(const QString capture_filter) |
| 141 | { |
| 142 | welcome_ui_->captureSectionCard->setCaptureFilterText(capture_filter); |
| 143 | } |
| 144 | |
| 145 | void WelcomePage::interfaceSelected() |
| 146 | { |
| 147 | welcome_ui_->captureSectionCard->interfaceSelected(); |
| 148 | } |
| 149 | |
| 150 | void WelcomePage::appInitialized() |
| 151 | { |
| 152 | applySidebarPreferences(); |
| 153 | |
| 154 | splash_overlay_->fadeOut(); |
| 155 | splash_overlay_ = NULL__null; |
| 156 | welcome_ui_->tipsSectionCard->startRotation(); |
| 157 | |
| 158 | // Ensure sidebar layout adapts to the restored window size. |
| 159 | // resizeEvent may have fired before the layout was finalized. |
| 160 | updateSidebarLayout(); |
| 161 | } |
| 162 | |
| 163 | void WelcomePage::applySidebarPreferences() |
| 164 | { |
| 165 | // There are slides that will be shown EVEN if the section card is set hidden through the preferences. |
| 166 | // hasVisibleSlides() checks if there are any slides that should be shown, as well as the user's preferences. |
| 167 | bool slidesAreVisible = welcome_ui_->tipsSectionCard->hasVisibleSlides(); |
| 168 | |
| 169 | welcome_ui_->tipsSectionCard->setSlideTypeVisible(BannerEvents, recent.gui_welcome_page_sidebar_tips_events); |
| 170 | welcome_ui_->tipsSectionCard->setSlideTypeVisible(BannerSponsorship, recent.gui_welcome_page_sidebar_tips_sponsorship); |
| 171 | welcome_ui_->tipsSectionCard->setSlideTypeVisible(BannerTips, recent.gui_welcome_page_sidebar_tips_tips); |
| 172 | welcome_ui_->tipsSectionCard->setAutoAdvanceInterval(recent.gui_welcome_page_sidebar_tips_interval); |
| 173 | welcome_ui_->tipsSectionCard->setVisible(slidesAreVisible); |
| 174 | |
| 175 | welcome_ui_->learnSectionCard->setVisible(recent.gui_welcome_page_sidebar_learn_visible); |
| 176 | |
| 177 | // Hide the entire sidebar container when all sidebar widgets are disabled, |
| 178 | // so the main content area can expand to fill the full window width. |
| 179 | bool sidebar_visible = slidesAreVisible || recent.gui_welcome_page_sidebar_learn_visible; |
| 180 | welcome_ui_->sidebarContainer->setVisible(sidebar_visible); |
| 181 | } |
| 182 | |
| 183 | bool WelcomePage::event(QEvent *event) |
| 184 | { |
| 185 | switch (event->type()) { |
| 186 | case QEvent::ApplicationPaletteChange: |
| 187 | { |
| 188 | updateStyleSheets(); |
| 189 | break; |
| 190 | } |
| 191 | case QEvent::LanguageChange: |
| 192 | { |
| 193 | welcome_ui_->retranslateUi(this); |
| 194 | break; |
| 195 | } |
| 196 | default: |
| 197 | break; |
| 198 | |
| 199 | } |
| 200 | return QFrame::event(event); |
| 201 | } |
| 202 | |
| 203 | void WelcomePage::resizeEvent(QResizeEvent *event) |
| 204 | { |
| 205 | if (splash_overlay_) |
| 206 | splash_overlay_->resize(event->size()); |
| 207 | |
| 208 | QFrame::resizeEvent(event); |
| 209 | |
| 210 | updateSidebarLayout(); |
| 211 | } |
| 212 | |
| 213 | void WelcomePage::showEvent(QShowEvent *event) |
| 214 | { |
| 215 | QFrame::showEvent(event); |
| 216 | |
| 217 | // The final window geometry may not be known until the widget is shown |
| 218 | // (especially on macOS with restored window positions). Ensure the |
| 219 | // sidebar layout adapts to the actual available space. |
| 220 | updateSidebarLayout(); |
| 221 | } |
| 222 | |
| 223 | /* |
| 224 | * Adapts the sidebar widget states to the available vertical space. |
| 225 | * |
| 226 | * The sidebar contains two widgets stacked vertically with spacing between |
| 227 | * them: the InfoBannerWidget (tips/sponsors) and the LearnCardWidget (docs |
| 228 | * links + action buttons). Both support a compact mode to reduce their |
| 229 | * height when the window is small. |
| 230 | * |
| 231 | * Collapse order (as the window shrinks): |
| 232 | * 1. LearnCardWidget links collapse (vertical list -> horizontal row) |
| 233 | * 2. InfoBannerWidget compacts (hides illustration and body text) |
| 234 | * |
| 235 | * Expand order (as the window grows) is the reverse: |
| 236 | * 1. InfoBannerWidget expands back to full |
| 237 | * 2. LearnCardWidget links expand back to vertical |
| 238 | * |
| 239 | * All size values are queried from the widgets and layout, not hardcoded: |
| 240 | * - tipsFull: InfoBannerWidget::sizeHint().height() |
| 241 | * Always returns the full preferred height (360) regardless |
| 242 | * of compact state. This is stable because sizeHint() |
| 243 | * reports what the widget *wants*, while compact mode is |
| 244 | * enforced via setMaximumHeight(). |
| 245 | * - learnMax: LearnCardWidget::maximumHeight() (from .ui: 240) |
| 246 | * - learnMin: LearnCardWidget::minimumHeight() (from .ui: 110) |
| 247 | * - spacing: sidebarLayout->spacing() (from .ui: 16) |
| 248 | * |
| 249 | * Hysteresis (kHysteresis = 20px): |
| 250 | * Without hysteresis, at the exact collapse threshold the layout |
| 251 | * oscillates: collapsing a widget frees space, which satisfies the |
| 252 | * expand threshold, which expands, which exceeds the threshold again. |
| 253 | * On each resize event this cycle repeats, causing visible flickering. |
| 254 | * |
| 255 | * Hysteresis adds a dead zone between collapse and expand thresholds. |
| 256 | * A widget collapses at threshold T but only re-expands at T + 20. |
| 257 | * In the 20px gap, the current state is preserved. |
| 258 | * |
| 259 | * The value 20px was chosen empirically: it must be large enough that |
| 260 | * the layout geometry change from collapsing/expanding a widget (which |
| 261 | * can shift available height by a few pixels due to rounding, spacing, |
| 262 | * and platform differences) doesn't cross back over the threshold. In |
| 263 | * practice, resize events during a user drag arrive ~8-12px apart, so |
| 264 | * 20px ensures at least one stable frame at the boundary. A larger |
| 265 | * value would delay the transition visibly; a smaller one risks not |
| 266 | * fully suppressing the oscillation on high-DPI displays where pixel |
| 267 | * increments are coarser. |
| 268 | * |
| 269 | * Decision zones (with current widget sizes): |
| 270 | * |
| 271 | * available >= 636 (linksExpandAt) |
| 272 | * -> full tips + expanded links |
| 273 | * |
| 274 | * available >= 506 (tipsExpandAt) and < 636 |
| 275 | * -> full tips + collapsed links |
| 276 | * (between 616-635: hysteresis zone for links -- keeps current state |
| 277 | * if already expanded, won't re-expand if collapsed) |
| 278 | * |
| 279 | * available >= 486 (tipsCompactAt) and < 506 |
| 280 | * -> hysteresis zone for tips -- keeps current tips state, |
| 281 | * links forced collapsed |
| 282 | * |
| 283 | * available < 486 (tipsCompactAt) |
| 284 | * -> compact tips + collapsed links |
| 285 | * |
| 286 | * Called from: resizeEvent(), showEvent(), appInitialized(), and |
| 287 | * indirectly via updateGeometry() when the welcome header banner |
| 288 | * visibility changes. |
| 289 | */ |
| 290 | void WelcomePage::updateSidebarLayout() |
| 291 | { |
| 292 | int available = welcome_ui_->sidebarContainer->height(); |
| 293 | if (available <= 0) |
| 294 | return; |
| 295 | |
| 296 | static const int kHysteresis = 20; |
| 297 | |
| 298 | int spacing = welcome_ui_->sidebarLayout->spacing(); |
| 299 | int tipsFull = welcome_ui_->tipsSectionCard->sizeHint().height(); |
| 300 | int learnMax = welcome_ui_->learnSectionCard->maximumHeight(); |
| 301 | int learnMin = welcome_ui_->learnSectionCard->minimumHeight(); |
| 302 | |
| 303 | // Collapse threshold: the minimum available height to show this state. |
| 304 | // Expand threshold: collapse + hysteresis -- prevents oscillation. |
| 305 | |
| 306 | // Level 1: links collapse when full tips + expanded learn don't fit. |
| 307 | int linksCollapseAt = tipsFull + spacing + learnMax; |
| 308 | int linksExpandAt = linksCollapseAt + kHysteresis; |
| 309 | |
| 310 | // Level 2: tips compact when full tips + collapsed learn don't fit. |
| 311 | int tipsCompactAt = tipsFull + spacing + learnMin; |
| 312 | int tipsExpandAt = tipsCompactAt + kHysteresis; |
| 313 | |
| 314 | bool collapseLinks = welcome_ui_->learnSectionCard->isLinksCollapsed(); |
Value stored to 'collapseLinks' during its initialization is never read | |
| 315 | bool compactTips = welcome_ui_->tipsSectionCard->isCompactMode(); |
| 316 | |
| 317 | if (available >= linksExpandAt) { |
| 318 | collapseLinks = false; |
| 319 | compactTips = false; |
| 320 | } else if (available >= tipsExpandAt) { |
| 321 | collapseLinks = true; |
| 322 | compactTips = false; |
| 323 | } else if (available >= tipsCompactAt) { |
| 324 | collapseLinks = true; |
| 325 | // tips state preserved (hysteresis zone) |
| 326 | } else { |
| 327 | collapseLinks = true; |
| 328 | compactTips = true; |
| 329 | } |
| 330 | |
| 331 | welcome_ui_->learnSectionCard->setLinksCollapsed(collapseLinks); |
| 332 | welcome_ui_->tipsSectionCard->setCompactMode(compactTips); |
| 333 | } |
| 334 | |
| 335 | void WelcomePage::showCaptureFilesContextMenu(QPoint pos) |
| 336 | { |
| 337 | QModelIndex index = welcome_ui_->openFileSectionRecentList->indexAt(pos); |
| 338 | if (!index.isValid()) return; |
| 339 | |
| 340 | QMenu *recent_ctx_menu = new QMenu(this); |
| 341 | recent_ctx_menu->setAttribute(Qt::WA_DeleteOnClose); |
| 342 | |
| 343 | QModelIndex sourceIndex = static_cast<QSortFilterProxyModel*>(welcome_ui_->openFileSectionRecentList->model())->mapToSource(index); |
| 344 | RecentCaptureFilesListModel *model = static_cast<RecentCaptureFilesListModel*>( |
| 345 | static_cast<QSortFilterProxyModel*>(welcome_ui_->openFileSectionRecentList->model())->sourceModel()); |
| 346 | |
| 347 | QString filePath = model->data(sourceIndex, RecentCaptureFilesListModel::FilenameRole).toString(); |
| 348 | bool accessible = model->data(sourceIndex, RecentCaptureFilesListModel::AccessibleRole).toBool(); |
| 349 | |
| 350 | QAction *show_action = recent_ctx_menu->addAction(show_in_str_); |
| 351 | show_action->setEnabled(accessible); |
| 352 | connect(show_action, &QAction::triggered, this, [filePath]{ desktop_show_in_folder(filePath); }); |
| 353 | |
| 354 | QAction *copy_action = recent_ctx_menu->addAction(tr("Copy file path")); |
| 355 | connect(copy_action, &QAction::triggered, this, [filePath]{ mainApp->clipboard()->setText(filePath); }); |
| 356 | |
| 357 | recent_ctx_menu->addSeparator(); |
| 358 | |
| 359 | QAction *remove_action = recent_ctx_menu->addAction(tr("Remove from list")); |
| 360 | connect(remove_action, &QAction::triggered, this, [filePath]{ |
| 361 | WorkspaceState::instance()->removeRecentCaptureFile(filePath); |
| 362 | }); |
| 363 | |
| 364 | recent_ctx_menu->popup(welcome_ui_->openFileSectionRecentList->viewport()->mapToGlobal(pos)); |
| 365 | } |
| 366 | |
| 367 | void WelcomePage::updateStyleSheets() |
| 368 | { |
| 369 | QString welcome_ss = QStringLiteral((QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 370 | "WelcomePage {"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 371 | " padding: 0;"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 372 | " }"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 373 | "WelcomePage, QAbstractItemView {"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 374 | " background-color: palette(base);"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 375 | " color: palette(text);"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 376 | " }"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 377 | "QAbstractItemView {"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 378 | " border: 0;"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 379 | "}"(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))) |
| 380 | )(QString(QtPrivate::qMakeStringPrivate(u"" "WelcomePage {" " padding: 0;" " }" "WelcomePage, QAbstractItemView {" " background-color: palette(base);" " color: palette(text);" " }" "QAbstractItemView {" " border: 0;" "}"))); |
| 381 | #if !defined(Q_OS_WIN) |
| 382 | welcome_ss += QStringLiteral((QString(QtPrivate::qMakeStringPrivate(u"" "QAbstractItemView:item:hover {" " background-color: %1;" " color: palette(text);" "}"))) |
| 383 | "QAbstractItemView:item:hover {"(QString(QtPrivate::qMakeStringPrivate(u"" "QAbstractItemView:item:hover {" " background-color: %1;" " color: palette(text);" "}"))) |
| 384 | " background-color: %1;"(QString(QtPrivate::qMakeStringPrivate(u"" "QAbstractItemView:item:hover {" " background-color: %1;" " color: palette(text);" "}"))) |
| 385 | " color: palette(text);"(QString(QtPrivate::qMakeStringPrivate(u"" "QAbstractItemView:item:hover {" " background-color: %1;" " color: palette(text);" "}"))) |
| 386 | "}"(QString(QtPrivate::qMakeStringPrivate(u"" "QAbstractItemView:item:hover {" " background-color: %1;" " color: palette(text);" "}"))) |
| 387 | )(QString(QtPrivate::qMakeStringPrivate(u"" "QAbstractItemView:item:hover {" " background-color: %1;" " color: palette(text);" "}"))) |
| 388 | .arg(ColorUtils::hoverBackground().name(QColor::HexArgb)); |
| 389 | #endif |
| 390 | setStyleSheet(welcome_ss); |
| 391 | |
| 392 | QString title_button_ss = QStringLiteral((QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 393 | "QLabel {"(QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 394 | " color: %1;"(QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 395 | "}"(QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 396 | "QLabel::hover {"(QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 397 | " color: %2;"(QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 398 | "}"(QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 399 | )(QString(QtPrivate::qMakeStringPrivate(u"" "QLabel {" " color: %1;" "}" "QLabel::hover {" " color: %2;" "}"))) |
| 400 | .arg(QColor(tango_aluminium_4).name()) // Text color |
| 401 | .arg(QColor(tango_sky_blue_4).name()); // Hover color |
| 402 | |
| 403 | welcome_ui_->openFileSectionLabel->setStyleSheet(title_button_ss); |
| 404 | |
| 405 | welcome_ui_->openFileSectionRecentList->setStyleSheet( |
| 406 | "QListView::item {" |
| 407 | " padding-top: 0.2em;" |
| 408 | " padding-bottom: 0.2em;" |
| 409 | "}" |
| 410 | "QListView::item::first {" |
| 411 | " padding-top: 0;" |
| 412 | "}" |
| 413 | "QListView::item::last {" |
| 414 | " padding-bottom: 0;" |
| 415 | "}" |
| 416 | ); |
| 417 | |
| 418 | /* LearnCardWidget and CaptureCardWidget manage their own stylesheets */ |
| 419 | } |
| 420 | |
| 421 | void WelcomePage::on_openFileSectionLabel_clicked() |
| 422 | { |
| 423 | mainApp->doTriggerMenuItem(MainApplication::FileOpenDialog); |
| 424 | } |