File indexing completed on 2025-04-27 03:58:32
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2013-04-29 0007 * Description : digiKam XML GUI window 0008 * 0009 * SPDX-FileCopyrightText: 2013-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "dxmlguiwindow_p.h" 0016 0017 namespace Digikam 0018 { 0019 0020 DXmlGuiWindow::DXmlGuiWindow(QWidget* const parent, Qt::WindowFlags f) 0021 : KXmlGuiWindow(parent, f), 0022 m_winLoaded (false), 0023 m_maximized (false), 0024 d (new Private) 0025 { 0026 m_animLogo = nullptr; 0027 0028 installEventFilter(this); 0029 } 0030 0031 DXmlGuiWindow::~DXmlGuiWindow() 0032 { 0033 delete d; 0034 } 0035 0036 void DXmlGuiWindow::setConfigGroupName(const QString& name) 0037 { 0038 d->configGroupName = name; 0039 } 0040 0041 QString DXmlGuiWindow::configGroupName() const 0042 { 0043 return d->configGroupName; 0044 } 0045 0046 void DXmlGuiWindow::showEvent(QShowEvent* e) 0047 { 0048 KXmlGuiWindow::showEvent(e); 0049 0050 restoreWindowSize(); 0051 } 0052 0053 void DXmlGuiWindow::closeEvent(QCloseEvent* e) 0054 { 0055 checkFullScreenBeforeClosing(); 0056 0057 if (!testAttribute(Qt::WA_DeleteOnClose)) 0058 { 0059 0060 #ifdef Q_OS_WIN 0061 0062 m_maximized = (windowState() & 0063 Qt::WindowMaximized); 0064 0065 #endif 0066 0067 e->ignore(); 0068 return; 0069 } 0070 0071 saveWindowSize(); 0072 0073 KXmlGuiWindow::closeEvent(e); 0074 } 0075 0076 bool DXmlGuiWindow::slotClose() 0077 { 0078 checkFullScreenBeforeClosing(); 0079 0080 return close(); 0081 } 0082 0083 void DXmlGuiWindow::slotShowMenuBar() 0084 { 0085 menuBar()->setVisible(d->showMenuBarAction->isChecked()); 0086 } 0087 0088 void DXmlGuiWindow::slotShowStatusBar() 0089 { 0090 statusBar()->setVisible(d->showStatusBarAction->isChecked()); 0091 } 0092 0093 void DXmlGuiWindow::slotConfNotifications() 0094 { 0095 0096 #ifdef HAVE_KNOTIFYCONFIG 0097 0098 QDialog* const dialog = new QDialog(this); 0099 dialog->setWindowTitle(i18n("Configure Notifications")); 0100 0101 KNotifyConfigWidget* const w = new KNotifyConfigWidget(dialog); 0102 0103 QDialogButtonBox* const buttonBox = new QDialogButtonBox(dialog); 0104 buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel| QDialogButtonBox::Help); 0105 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); 0106 0107 QVBoxLayout* const layout = new QVBoxLayout(dialog); 0108 layout->addWidget(w); 0109 layout->addWidget(buttonBox); 0110 0111 connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), 0112 w, SLOT(save())); 0113 0114 connect(buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), 0115 w, SLOT(save())); 0116 0117 connect(buttonBox->button(QDialogButtonBox::Help), &QPushButton::clicked, 0118 this, []() 0119 { 0120 openOnlineDocumentation(QLatin1String("setup_application"), QLatin1String("notifications_settings")); 0121 } 0122 ); 0123 0124 connect(w, SIGNAL(changed(bool)), 0125 buttonBox->button(QDialogButtonBox::Apply), SLOT(setEnabled(bool))); 0126 0127 connect(buttonBox, SIGNAL(accepted()), 0128 dialog, SLOT(accept())); 0129 0130 connect(buttonBox, SIGNAL(rejected()), 0131 dialog, SLOT(reject())); 0132 0133 w->setApplication(QString()); 0134 dialog->setAttribute(Qt::WA_DeleteOnClose); 0135 dialog->show(); 0136 0137 #endif 0138 0139 } 0140 0141 void DXmlGuiWindow::editKeyboardShortcuts(KActionCollection* const extraac, const QString& actitle) 0142 { 0143 KShortcutsDialog dialog(KShortcutsEditor::AllActions, 0144 KShortcutsEditor::LetterShortcutsAllowed, this); 0145 dialog.addCollection(actionCollection(), i18nc("general keyboard shortcuts", "General")); 0146 0147 QDialogButtonBox* const btnbox = dialog.findChild<QDialogButtonBox*>(); 0148 0149 if (btnbox) 0150 { 0151 btnbox->setStandardButtons(btnbox->standardButtons() | QDialogButtonBox::Help); 0152 0153 connect(btnbox->button(QDialogButtonBox::Help), &QPushButton::clicked, 0154 this, []() 0155 { 0156 openOnlineDocumentation(QLatin1String("setup_application"), QLatin1String("shortcuts_settings")); 0157 } 0158 ); 0159 } 0160 0161 if (extraac) 0162 { 0163 dialog.addCollection(extraac, actitle); 0164 } 0165 0166 dialog.configure(); 0167 } 0168 0169 bool DXmlGuiWindow::eventFilter(QObject* obj, QEvent* ev) 0170 { 0171 if (obj == this) 0172 { 0173 if (ev && (ev->type() == QEvent::HoverMove) && fullScreenIsActive()) 0174 { 0175 // We will handle a stand alone FullScreen button action on top/right corner of screen 0176 // only if managed window tool bar is hidden, and if we switched already in Full Screen mode. 0177 0178 KToolBar* const mainbar = mainToolBar(); 0179 0180 if (mainbar) 0181 { 0182 if (((d->fsOptions & FS_TOOLBARS) && d->fullScreenHideToolBars) || !mainbar->isVisible()) 0183 { 0184 QHoverEvent* const mev = dynamic_cast<QHoverEvent*>(ev); 0185 0186 if (mev) 0187 { 0188 0189 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0190 0191 QPoint pos(mev->position().toPoint()); 0192 0193 #else 0194 0195 QPoint pos(mev->pos()); 0196 0197 #endif 0198 0199 QRect desktopRect = windowHandle()->screen()->geometry(); 0200 0201 QRect sizeRect(QPoint(0, 0), d->fullScreenBtn->size()); 0202 QRect topLeft, topRight; 0203 QRect topRightLarger; 0204 0205 desktopRect = QRect(desktopRect.y(), desktopRect.y(), desktopRect.width(), desktopRect.height()); 0206 topLeft = sizeRect; 0207 topRight = sizeRect; 0208 0209 topLeft.moveTo(desktopRect.x(), desktopRect.y()); 0210 topRight.moveTo(desktopRect.x() + desktopRect.width() - sizeRect.width() - 1, topLeft.y()); 0211 0212 topRightLarger = topRight.adjusted(-25, 0, 0, 10); 0213 0214 if (topRightLarger.contains(pos)) 0215 { 0216 d->fullScreenBtn->move(topRight.topLeft()); 0217 d->fullScreenBtn->show(); 0218 } 0219 else 0220 { 0221 d->fullScreenBtn->hide(); 0222 } 0223 0224 return false; 0225 } 0226 } 0227 } 0228 } 0229 } 0230 0231 // pass the event on to the parent class 0232 0233 return QObject::eventFilter(obj, ev); 0234 } 0235 0236 void DXmlGuiWindow::keyPressEvent(QKeyEvent* e) 0237 { 0238 if (e->key() == Qt::Key_Escape) 0239 { 0240 if (fullScreenIsActive()) 0241 { 0242 d->fullScreenAction->activate(QAction::Trigger); 0243 } 0244 } 0245 } 0246 0247 void DXmlGuiWindow::showSideBars(bool visible) 0248 { 0249 Q_UNUSED(visible); 0250 } 0251 0252 void DXmlGuiWindow::showThumbBar(bool visible) 0253 { 0254 Q_UNUSED(visible); 0255 } 0256 0257 bool DXmlGuiWindow::thumbbarVisibility() const 0258 { 0259 return true; 0260 } 0261 0262 void DXmlGuiWindow::slotHelpContents() 0263 { 0264 openOnlineDocumentation(d->handbookSection); 0265 } 0266 0267 void DXmlGuiWindow::unminimizeAndActivateWindow() 0268 { 0269 if (isMinimized()) 0270 { 0271 setWindowState(windowState() & ~Qt::WindowMinimized); 0272 } 0273 0274 #ifdef Q_OS_WIN 0275 0276 if (m_maximized) 0277 { 0278 setWindowState(windowState() | Qt::WindowMaximized); 0279 } 0280 0281 #endif 0282 0283 setWindowState(windowState() | Qt::WindowActive); 0284 raise(); 0285 } 0286 0287 bool DXmlGuiWindow::restoreWindowSize(QWindow* const win, const KConfigGroup& group) 0288 { 0289 0290 #ifdef Q_OS_WIN 0291 0292 int w = group.readEntry(QLatin1String("DK Width"), win->width()); 0293 int h = group.readEntry(QLatin1String("DK Height"), win->height()); 0294 int x = group.readEntry(QLatin1String("DK PositionX"), win->geometry().x()); 0295 int y = group.readEntry(QLatin1String("DK PositionY"), win->geometry().y()); 0296 bool max = group.readEntry(QLatin1String("DK Maximized"), (bool)(win->windowState() & 0297 Qt::WindowMaximized)); 0298 0299 if (win->screen()->availableVirtualGeometry().contains(QRect(x, y, w, h))) 0300 { 0301 win->setPosition(x, y); 0302 } 0303 0304 if (max) 0305 { 0306 // we don't use showMaximized() because it also calls 0307 // setVisible() it would create an infinite loop. 0308 0309 win->setWindowState(Qt::WindowMaximized); 0310 } 0311 else 0312 { 0313 win->resize(w, h); 0314 } 0315 0316 return max; 0317 0318 #else 0319 0320 KWindowConfig::restoreWindowSize(win, group); 0321 0322 return false; 0323 0324 #endif 0325 0326 } 0327 0328 void DXmlGuiWindow::saveWindowSize(QWindow* const win, KConfigGroup& group) 0329 { 0330 0331 #ifdef Q_OS_WIN 0332 0333 group.writeEntry(QLatin1String("DK Width"), win->width()); 0334 group.writeEntry(QLatin1String("DK Height"), win->height()); 0335 group.writeEntry(QLatin1String("DK PositionX"), win->geometry().x()); 0336 group.writeEntry(QLatin1String("DK PositionY"), win->geometry().y()); 0337 group.writeEntry(QLatin1String("DK Maximized"), (bool)(win->windowState() & 0338 Qt::WindowMaximized)); 0339 0340 #else 0341 0342 KWindowConfig::saveWindowSize(win, group); 0343 0344 #endif 0345 0346 } 0347 0348 void DXmlGuiWindow::restoreWindowSize() 0349 { 0350 0351 #ifdef Q_OS_WIN 0352 0353 if (!m_winLoaded) 0354 { 0355 winId(); 0356 0357 m_winLoaded = true; 0358 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0359 KConfigGroup group = config->group(configGroupName()); 0360 m_maximized = restoreWindowSize(windowHandle(), group); 0361 } 0362 0363 #endif 0364 0365 } 0366 0367 void DXmlGuiWindow::saveWindowSize() 0368 { 0369 0370 #ifdef Q_OS_WIN 0371 0372 if (m_maximized) 0373 { 0374 windowHandle()->setWindowState(Qt::WindowMaximized); 0375 } 0376 0377 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0378 KConfigGroup group = config->group(configGroupName()); 0379 0380 saveWindowSize(windowHandle(), group); 0381 0382 #endif 0383 0384 } 0385 0386 void DXmlGuiWindow::setGoodDefaultWindowSize(QWindow* const win) 0387 { 0388 QScreen* const screen = win->screen(); 0389 QRect srect = screen->availableGeometry(); 0390 int height = qRound(log10(srect.height() / 60) * 600); 0391 int width = qRound(log10(srect.width() / 80) * 800); 0392 0393 win->resize(width > srect.width() ? srect.width() : width, 0394 height > srect.height() ? srect.height() : height); 0395 } 0396 0397 void DXmlGuiWindow::slotRawCameraList() 0398 { 0399 showRawCameraList(); 0400 } 0401 0402 void DXmlGuiWindow::slotSolidHardwareList() 0403 { 0404 SolidHardwareDlg* const dlg = new SolidHardwareDlg(qApp->activeWindow()); 0405 (void)dlg->exec(); 0406 } 0407 0408 void DXmlGuiWindow::slotDonateMoney() 0409 { 0410 QUrl url(QLatin1String("https://www.digikam.org/donate/")); 0411 0412 #ifdef HAVE_QWEBENGINE 0413 0414 WebBrowserDlg* const browser = new WebBrowserDlg(url, qApp->activeWindow()); 0415 browser->show(); 0416 0417 #else 0418 0419 QDesktopServices::openUrl(url); 0420 0421 #endif 0422 0423 } 0424 0425 void DXmlGuiWindow::slotRecipesBook() 0426 { 0427 QUrl url(QLatin1String("https://www.digikam.org/recipes_book/")); 0428 0429 #ifdef HAVE_QWEBENGINE 0430 0431 WebBrowserDlg* const browser = new WebBrowserDlg(url, qApp->activeWindow()); 0432 browser->show(); 0433 0434 #else 0435 0436 QDesktopServices::openUrl(url); 0437 0438 #endif 0439 0440 } 0441 0442 void DXmlGuiWindow::slotContribute() 0443 { 0444 QUrl url(QLatin1String("https://www.digikam.org/contribute/")); 0445 0446 #ifdef HAVE_QWEBENGINE 0447 0448 WebBrowserDlg* const browser = new WebBrowserDlg(url, qApp->activeWindow()); 0449 browser->show(); 0450 0451 #else 0452 0453 QDesktopServices::openUrl(url); 0454 0455 #endif 0456 0457 } 0458 0459 void DXmlGuiWindow::setupIconTheme() 0460 { 0461 // Let QStandardPaths handle this, it will look for app local stuff 0462 // this means e.g. for mac: "<APPDIR>/../Resources" and for win: "<APPDIR>/data". 0463 0464 bool hasBreeze = false; 0465 const QString breezeIcons = QStandardPaths::locate(QStandardPaths::AppDataLocation, 0466 QLatin1String("breeze.rcc")); 0467 0468 if (!breezeIcons.isEmpty() && QFile::exists(breezeIcons)) 0469 { 0470 qCDebug(DIGIKAM_WIDGETS_LOG) << "Breeze icons resource file found"; 0471 QResource::registerResource(breezeIcons); 0472 hasBreeze = true; 0473 } 0474 0475 bool hasBreezeDark = false; 0476 const QString breezeDarkIcons = QStandardPaths::locate(QStandardPaths::AppDataLocation, 0477 QLatin1String("breeze-dark.rcc")); 0478 0479 if (!breezeDarkIcons.isEmpty() && QFile::exists(breezeDarkIcons)) 0480 { 0481 qCDebug(DIGIKAM_WIDGETS_LOG) << "Breeze-dark icons resource file found"; 0482 QResource::registerResource(breezeDarkIcons); 0483 hasBreezeDark = true; 0484 } 0485 0486 if (hasBreeze || hasBreezeDark) 0487 { 0488 // Tell Qt about the theme 0489 0490 QIcon::setThemeSearchPaths(QStringList() << QLatin1String(":/icons")); 0491 0492 const QStringList iconsDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, 0493 QLatin1String("icons"), 0494 QStandardPaths::LocateDirectory); 0495 0496 if (!iconsDirs.isEmpty()) 0497 { 0498 QIcon::setThemeSearchPaths(QStringList() << QIcon::themeSearchPaths() << iconsDirs); 0499 } 0500 0501 if (hasBreeze) 0502 { 0503 QIcon::setThemeName(QLatin1String("breeze")); 0504 } 0505 else if (hasBreezeDark) 0506 { 0507 QIcon::setThemeName(QLatin1String("breeze-dark")); 0508 } 0509 } 0510 else 0511 { 0512 qCDebug(DIGIKAM_WIDGETS_LOG) << "Use installed icons"; 0513 } 0514 } 0515 0516 } // namespace Digikam 0517 0518 #include "moc_dxmlguiwindow.cpp"