File indexing completed on 2024-04-28 05:11:02
0001 /* 0002 This file is part of Akregator. 0003 0004 SPDX-FileCopyrightText: 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0007 */ 0008 0009 #include "mainwindow.h" 0010 #include "akregator_part.h" 0011 #include "akregatorconfig.h" 0012 #include "trayicon.h" 0013 #include <Libkdepim/ProgressManager> 0014 #include <Libkdepim/ProgressStatusBarWidget> 0015 #include <Libkdepim/StatusbarProgressWidget> 0016 #include <PimCommon/BroadcastStatus> 0017 0018 #include <KActionCollection> 0019 #include <KConfig> 0020 #include <KEditToolBar> 0021 #include <KLocalizedString> 0022 #include <KMessageBox> 0023 #include <KPluginFactory> 0024 #include <KPluginMetaData> 0025 #include <KSharedConfig> 0026 #include <KShortcutsDialog> 0027 #include <KSqueezedTextLabel> 0028 #include <KStandardAction> 0029 #include <KToggleFullScreenAction> 0030 #include <KToolBar> 0031 #include <KXMLGUIFactory> 0032 #include <QApplication> 0033 #include <QFontDatabase> 0034 #include <QMenuBar> 0035 #include <QStatusBar> 0036 #include <QTimer> 0037 #include <QToolButton> 0038 0039 using namespace Akregator; 0040 0041 MainWindow::MainWindow(QWidget *parent) 0042 : KParts::MainWindow(parent) 0043 , m_part() 0044 , m_statusLabel(new KSqueezedTextLabel(this)) 0045 { 0046 // set the shell's ui resource file 0047 setXMLFile(QStringLiteral("akregator_shell.rc")); 0048 0049 KStandardAction::keyBindings(this, &MainWindow::optionsConfigureKeys, actionCollection()); // options_configure_keybinding 0050 KStandardAction::configureToolbars(this, &MainWindow::optionsConfigureToolbars, actionCollection()); // options_configure_toolbars 0051 0052 toolBar()->show(); 0053 statusBar()->show(); 0054 0055 const int statH = fontMetrics().height() + 2; 0056 m_statusLabel->setTextFormat(Qt::RichText); 0057 m_statusLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); 0058 m_statusLabel->setMinimumWidth(0); 0059 m_statusLabel->setFixedHeight(statH); 0060 statusBar()->addWidget(m_statusLabel, 1); 0061 0062 KStandardAction::quit(qApp, &QApplication::quit, actionCollection()); 0063 mShowMenuBarAction = KStandardAction::showMenubar(this, &MainWindow::slotToggleMenubar, actionCollection()); 0064 mShowMenuBarAction->setChecked(Settings::showMenuBar()); 0065 slotToggleMenubar(true); 0066 0067 if (menuBar()) { 0068 mHamburgerMenu = KStandardAction::hamburgerMenu(nullptr, nullptr, actionCollection()); 0069 mHamburgerMenu->setShowMenuBarAction(mShowMenuBarAction); 0070 mHamburgerMenu->setMenuBar(menuBar()); 0071 connect(mHamburgerMenu, &KHamburgerMenu::aboutToShowMenu, this, [this]() { 0072 updateHamburgerMenu(); 0073 // Immediately disconnect. We only need to run this once, but on demand. 0074 // NOTE: The nullptr at the end disconnects all connections between 0075 // q and mHamburgerMenu's aboutToShowMenu signal. 0076 disconnect(mHamburgerMenu, &KHamburgerMenu::aboutToShowMenu, this, nullptr); 0077 }); 0078 } 0079 0080 mShowFullScreenAction = KStandardAction::fullScreen(nullptr, nullptr, this, actionCollection()); 0081 actionCollection()->setDefaultShortcut(mShowFullScreenAction, Qt::Key_F11); 0082 connect(mShowFullScreenAction, &QAction::toggled, this, &MainWindow::slotFullScreen); 0083 0084 setStandardToolBarMenuEnabled(true); 0085 createStandardStatusBarAction(); 0086 0087 connect(PimCommon::BroadcastStatus::instance(), &PimCommon::BroadcastStatus::statusMsg, this, &MainWindow::slotSetStatusBarText); 0088 0089 connect(qApp, &QCoreApplication::aboutToQuit, this, &MainWindow::slotOnShutdown); 0090 } 0091 0092 void MainWindow::slotFullScreen(bool t) 0093 { 0094 KToggleFullScreenAction::setFullScreen(this, t); 0095 QMenuBar *mb = menuBar(); 0096 if (t) { 0097 auto b = new QToolButton(mb); 0098 b->setDefaultAction(mShowFullScreenAction); 0099 b->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Ignored)); 0100 b->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0101 mb->setCornerWidget(b, Qt::TopRightCorner); 0102 b->setVisible(true); 0103 b->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 0104 } else { 0105 QWidget *w = mb->cornerWidget(Qt::TopRightCorner); 0106 if (w) { 0107 w->deleteLater(); 0108 } 0109 } 0110 } 0111 0112 void MainWindow::slotToggleMenubar(bool dontShowWarning) 0113 { 0114 if (menuBar()) { 0115 if (mShowMenuBarAction->isChecked()) { 0116 menuBar()->show(); 0117 } else { 0118 if (!dontShowWarning && (!toolBar()->isVisible() || !toolBar()->actions().contains(mHamburgerMenu))) { 0119 const QString accel = mShowMenuBarAction->shortcut().toString(); 0120 KMessageBox::information(this, 0121 i18n("<qt>This will hide the menu bar completely." 0122 " You can show it again by typing %1.</qt>", 0123 accel), 0124 i18nc("@title:window", "Hide menu bar"), 0125 QStringLiteral("HideMenuBarWarning")); 0126 } 0127 menuBar()->hide(); 0128 } 0129 Settings::setShowMenuBar(mShowMenuBarAction->isChecked()); 0130 } 0131 } 0132 0133 void MainWindow::updateHamburgerMenu() 0134 { 0135 auto menu = new QMenu(this); 0136 menu->addAction(actionCollection()->action(KStandardAction::name(KStandardAction::Quit))); 0137 mHamburgerMenu->setMenu(menu); 0138 } 0139 0140 bool MainWindow::loadPart() 0141 { 0142 if (m_part) { 0143 return true; 0144 } 0145 // this routine will find and load our Part. it finds the Part by 0146 // name which is a bad idea usually.. but it's alright in this 0147 // case since our Part is made for this Shell 0148 const KPluginMetaData md(QStringLiteral("akregatorpart")); 0149 const auto result = KPluginFactory::instantiatePlugin<KParts::Part>(md, this); 0150 if (result) { 0151 m_part = static_cast<Akregator::Part *>(result.plugin); 0152 } else { 0153 KMessageBox::error(this, i18n("Could not find the Akregator part; please check your installation.\n%1", result.errorString)); 0154 return false; 0155 } 0156 0157 m_part->setObjectName(QLatin1StringView("akregator_part")); 0158 setCentralWidget(m_part->widget()); 0159 0160 connect(m_part.data(), &Part::setWindowCaption, this, qOverload<const QString &>(&KMainWindow::setCaption)); 0161 0162 createGUI(m_part); 0163 setAutoSaveSettings(); 0164 return true; 0165 } 0166 0167 void MainWindow::setupProgressWidgets() 0168 { 0169 auto progressStatusBarWidget = new KPIM::ProgressStatusBarWidget(statusBar(), this); 0170 m_statusbarProgress = progressStatusBarWidget->littleProgress(); 0171 statusBar()->addPermanentWidget(m_statusbarProgress, 0); 0172 0173 // The progress widget blocks a large part of the status bar, but is empty 0174 // most of the time. Hide it when unused, allowing a longer status label. 0175 m_hideProgressTimer = new QTimer(this); 0176 m_hideProgressTimer->setSingleShot(true); 0177 connect(m_hideProgressTimer, &QTimer::timeout, m_statusbarProgress, &QWidget::hide); 0178 0179 connect(KPIM::ProgressManager::instance(), &KPIM::ProgressManager::progressItemAdded, this, &MainWindow::updateStatusbarProgressVisibility); 0180 connect(KPIM::ProgressManager::instance(), &KPIM::ProgressManager::progressItemCompleted, this, &MainWindow::updateStatusbarProgressVisibility); 0181 m_statusbarProgress->hide(); 0182 } 0183 0184 void MainWindow::updateStatusbarProgressVisibility() 0185 { 0186 if (KPIM::ProgressManager::instance()->isEmpty()) { 0187 m_hideProgressTimer->start(5000); 0188 } else { 0189 m_hideProgressTimer->stop(); 0190 m_statusbarProgress->show(); 0191 } 0192 } 0193 0194 MainWindow::~MainWindow() = default; 0195 0196 void MainWindow::saveProperties(KConfigGroup &config) 0197 { 0198 if (!m_part) { 0199 if (!loadPart()) { 0200 return; 0201 } 0202 } 0203 0204 m_part->saveProperties(config); 0205 config.writeEntry("docked", isHidden()); 0206 } 0207 0208 void MainWindow::readProperties(const KConfigGroup &config) 0209 { 0210 if (!m_part) { 0211 if (!loadPart()) { 0212 return; 0213 } 0214 } 0215 m_part->readProperties(config); 0216 setVisible(!Settings::showTrayIcon() || !config.readEntry("docked", false)); 0217 } 0218 0219 // TODO: move to part? 0220 void MainWindow::optionsConfigureKeys() 0221 { 0222 KShortcutsDialog dlg(this); 0223 0224 dlg.addCollection(actionCollection()); 0225 if (m_part) { 0226 dlg.addCollection(m_part->actionCollection()); 0227 } 0228 0229 if (dlg.configure()) { 0230 if (m_part) { 0231 // FIXME 0232 // m_part->updateQuickSearchLineText(); 0233 } 0234 } 0235 } 0236 0237 // TODO: move to part? 0238 void MainWindow::optionsConfigureToolbars() 0239 { 0240 KConfigGroup grp(KSharedConfig::openConfig().data()->group(autoSaveGroup())); 0241 saveMainWindowSettings(grp); 0242 QPointer<KEditToolBar> dlg = new KEditToolBar(factory()); 0243 connect(dlg.data(), &KEditToolBar::newToolBarConfig, this, &MainWindow::applyNewToolbarConfig); 0244 dlg->exec(); 0245 delete dlg; 0246 } 0247 0248 // TODO: move to part? 0249 void MainWindow::applyNewToolbarConfig() 0250 { 0251 applyMainWindowSettings(KSharedConfig::openConfig()->group(autoSaveGroup())); 0252 } 0253 0254 void MainWindow::slotQuit() 0255 { 0256 qApp->quit(); 0257 } 0258 0259 void MainWindow::slotOnShutdown() 0260 { 0261 delete m_part; 0262 } 0263 0264 bool MainWindow::queryClose() 0265 { 0266 if (qApp->isSavingSession()) { 0267 return true; 0268 } 0269 if (!TrayIcon::getInstance()) { 0270 delete m_part; // delete that here instead of dtor to ensure nested khtmlparts are deleted before singleton objects like KHTMLPageCache 0271 return true; 0272 } 0273 0274 hide(); 0275 return false; 0276 } 0277 0278 void MainWindow::slotClearStatusText() 0279 { 0280 m_statusLabel->setText(QString()); 0281 } 0282 0283 void MainWindow::slotSetStatusBarText(const QString &text) 0284 { 0285 m_statusLabel->setText(text); 0286 } 0287 0288 #include "moc_mainwindow.cpp"