File indexing completed on 2024-05-05 05:00:08

0001 /*
0002     Add here all general options - those that apply to both web browsing and filemanagement mode
0003 
0004     SPDX-FileCopyrightText: 1998 Sven Radej
0005     SPDX-FileCopyrightText: 1998 David Faure
0006     SPDX-FileCopyrightText: 2001 Waldo Bastian <bastian@kde.org>
0007     SPDX-FileCopyrightText: 2007 Nick Shaforostoff <shafff@ukr.net>
0008 */
0009 
0010 // Own
0011 #include "generalopts.h"
0012 
0013 // Qt
0014 #include <QDBusConnection>
0015 #include <QDBusMessage>
0016 #include <QComboBox>
0017 #include <QFormLayout>
0018 #include <QGroupBox>
0019 #include <QLineEdit>
0020 #include <QLabel>
0021 #include <QStandardPaths>
0022 #include <QUrl>
0023 
0024 // KDE
0025 #include <kbuildsycocaprogressdialog.h>
0026 #include <KConfigGroup>
0027 #include <KSharedConfig>
0028 #include <KMessageWidget>
0029 #include <KParts/PartLoader>
0030 #include <KLocalizedString>
0031 
0032 // Keep in sync with konqueror.kcfg
0033 static const char DEFAULT_STARTPAGE[] = "konq:konqueror";
0034 static const char DEFAULT_HOMEPAGE[] = "https://www.kde.org/";
0035 // Keep in sync with the order in the combo
0036 enum StartPage { ShowAboutPage, ShowStartUrlPage, ShowBlankPage, ShowBookmarksPage };
0037 
0038 //-----------------------------------------------------------------------------
0039 
0040 KKonqGeneralOptions::KKonqGeneralOptions(QObject *parent, const KPluginMetaData &md, const QVariantList &)
0041     : KCModule(parent, md), m_emptyStartUrlWarning(new KMessageWidget(widget()))
0042 {
0043     m_pConfig = KSharedConfig::openConfig(QStringLiteral("konquerorrc"), KConfig::NoGlobals);
0044     QVBoxLayout *lay = new QVBoxLayout(widget());
0045     lay->setContentsMargins(0, 0, 0, 0);
0046 
0047     addHomeUrlWidgets(lay);
0048     setNeedsSave(false);
0049 }
0050 
0051 void KKonqGeneralOptions::addHomeUrlWidgets(QVBoxLayout *lay)
0052 {
0053     QFormLayout *formLayout = new QFormLayout;
0054     lay->addLayout(formLayout);
0055 
0056     m_emptyStartUrlWarning->setText(i18nc("The user chose to use a custom start page but left the corresponding field empty", "Please, insert the custom start page"));
0057     m_emptyStartUrlWarning->setMessageType(KMessageWidget::Warning);
0058     m_emptyStartUrlWarning->setIcon(QIcon::fromTheme("dialog-warning"));
0059     m_emptyStartUrlWarning->hide();
0060     formLayout->addRow(m_emptyStartUrlWarning);
0061 
0062     QLabel *startLabel = new QLabel(i18nc("@label:listbox", "When a new &Tab is created"), widget());
0063 
0064     QWidget *containerWidget = new QWidget(widget());
0065     QHBoxLayout *hboxLayout = new QHBoxLayout(containerWidget);
0066     hboxLayout->setContentsMargins(0, 0, 0, 0);
0067     formLayout->addRow(startLabel, containerWidget);
0068 
0069     m_startCombo = new QComboBox(widget());
0070     m_startCombo->setEditable(false);
0071     m_startCombo->addItem(i18nc("@item:inlistbox", "Show Introduction Page"), ShowAboutPage);
0072     m_startCombo->addItem(i18nc("@item:inlistbox", "Show My Start Page"), ShowStartUrlPage);
0073     m_startCombo->addItem(i18nc("@item:inlistbox", "Show Blank Page"), ShowBlankPage);
0074     m_startCombo->addItem(i18nc("@item:inlistbox", "Show My Bookmarks"), ShowBookmarksPage);
0075     startLabel->setBuddy(m_startCombo);
0076     connect(m_startCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KKonqGeneralOptions::slotChanged);
0077     hboxLayout->addWidget(m_startCombo);
0078 
0079     startURL = new QLineEdit(widget());
0080     startURL->setWindowTitle(i18nc("@title:window", "Select Start Page"));
0081     hboxLayout->addWidget(startURL);
0082     connect(startURL, &QLineEdit::textChanged, this, &KKonqGeneralOptions::displayEmpytStartPageWarningIfNeeded);
0083     connect(startURL, &QLineEdit::textChanged, this, &KKonqGeneralOptions::slotChanged);
0084 
0085     QString startstr = i18n("This is the URL of the web page "
0086                            "Konqueror will show when starting.");
0087     startURL->setToolTip(startstr);
0088     connect(m_startCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int idx) {
0089             startURL->setVisible(idx == ShowStartUrlPage);
0090             displayEmpytStartPageWarningIfNeeded();
0091             });
0092     startURL->hide();
0093 
0094     ////
0095 
0096     QLabel *label = new QLabel(i18n("Home page:"), widget());
0097 
0098     homeURL = new QLineEdit(widget());
0099     homeURL->setWindowTitle(i18nc("@title:window", "Select Home Page"));
0100     formLayout->addRow(label, homeURL);
0101     connect(homeURL, &QLineEdit::textChanged, this, &KKonqGeneralOptions::slotChanged);
0102     label->setBuddy(homeURL);
0103 
0104     QString homestr = i18n("This is the URL of the web page where "
0105                            "Konqueror will jump to when "
0106                            "the \"Home\" button is pressed.");
0107     label->setToolTip(homestr);
0108     homeURL->setToolTip(homestr);
0109 
0110     ////
0111 
0112     QLabel *webLabel = new QLabel(i18n("Default web browser engine:"), widget());
0113 
0114     m_webEngineCombo = new QComboBox(widget());
0115     m_webEngineCombo->setEditable(false);
0116     m_webEngineCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
0117     formLayout->addRow(webLabel, m_webEngineCombo);
0118     webLabel->setBuddy(m_webEngineCombo);
0119     connect(m_webEngineCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KKonqGeneralOptions::slotChanged);
0120 
0121     QLabel *splitLabel = new QLabel(i18n("When splitting a view"));
0122     m_splitBehaviour = new QComboBox(widget());
0123     //Keep items order in sync with KonqMainWindow::SplitBehaviour
0124     m_splitBehaviour->addItems({
0125         i18n("Always duplicate current view"),
0126         i18n("Duplicate current view only for local files")
0127     });
0128     splitLabel->setBuddy(m_splitBehaviour);
0129     formLayout->addRow(splitLabel, m_splitBehaviour);
0130     connect(m_splitBehaviour, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KKonqGeneralOptions::slotChanged);
0131 
0132     m_restoreLastState = new QCheckBox(i18n("When starting up, restore state from last time"), widget());
0133     connect(m_restoreLastState, &QCheckBox::stateChanged, this, &KKonqGeneralOptions::slotChanged);
0134     formLayout->addRow(m_restoreLastState);
0135 }
0136 
0137 KKonqGeneralOptions::~KKonqGeneralOptions()
0138 {
0139 }
0140 
0141 void KKonqGeneralOptions::displayEmpytStartPageWarningIfNeeded()
0142 {
0143     if (startURL->isVisible() && startURL->text().isEmpty()) {
0144         m_emptyStartUrlWarning->animatedShow();
0145     } else if (m_emptyStartUrlWarning->isVisible()) {
0146         m_emptyStartUrlWarning->animatedHide();
0147     }
0148 }
0149 
0150 static StartPage urlToStartPageEnum(const QString &startUrl)
0151 {
0152     if (startUrl == QLatin1String("konq:blank")) {
0153         return ShowBlankPage;
0154     }
0155     if (startUrl == QLatin1String("konq:") || startUrl == QLatin1String("konq:konqueror")) {
0156         return ShowAboutPage;
0157     }
0158     if (startUrl == QLatin1String("bookmarks:") || startUrl == QLatin1String("bookmarks:/")) {
0159         return ShowBookmarksPage;
0160     }
0161     return ShowStartUrlPage;
0162 }
0163 
0164 static QString startPageEnumToUrl(StartPage startPage)
0165 {
0166     switch (startPage) {
0167         case ShowBlankPage:
0168             return QStringLiteral("konq:blank");
0169         case ShowAboutPage:
0170             return QStringLiteral("konq:konqueror");
0171         case ShowBookmarksPage:
0172             return QStringLiteral("bookmarks:/");
0173         case ShowStartUrlPage:
0174             return QString();
0175     }
0176     return QString();
0177 }
0178 
0179 void KKonqGeneralOptions::load()
0180 {
0181     KConfigGroup userSettings(m_pConfig, "UserSettings");
0182     const QUrl homeUrl(QUrl(userSettings.readEntry("HomeURL", DEFAULT_HOMEPAGE)));
0183     const QUrl startUrl(QUrl(userSettings.readEntry("StartURL", DEFAULT_STARTPAGE)));
0184     homeURL->setText(homeUrl.toString());
0185     startURL->setText(startUrl.toString());
0186     const StartPage startPage = urlToStartPageEnum(startUrl.toString());
0187     const int startComboIndex = m_startCombo->findData(startPage);
0188     Q_ASSERT(startComboIndex != -1);
0189     m_startCombo->setCurrentIndex(startComboIndex);
0190 
0191     const bool alwaysDuplicateWhenSplitting = userSettings.readEntry("AlwaysDuplicatePageWhenSplittingView", true);
0192     m_splitBehaviour->setCurrentIndex(alwaysDuplicateWhenSplitting ? 0 : 1);
0193 
0194     const bool restoreLastState = userSettings.readEntry(QStringLiteral("RestoreLastState"), false);
0195     m_restoreLastState->setChecked(restoreLastState);
0196 
0197     m_webEngineCombo->clear();
0198     // ## Well, the problem with using the trader to find the available parts, is that if a user
0199     // removed a part in keditfiletype text/html, it won't be in the list anymore. Oh well.
0200     QVector<KPluginMetaData> allParts = KParts::PartLoader::partsForMimeType(QStringLiteral("text/html"));
0201     QVector<KPluginMetaData> partOfferList;
0202     auto filter = [](const KPluginMetaData &md){
0203         return !md.mimeTypes().contains(QStringLiteral("text/plain"));
0204     };
0205     std::copy_if(allParts.constBegin(), allParts.constEnd(), std::back_inserter(partOfferList), filter);
0206 
0207     //We need to remove duplicates caused by having parts with both plugin metadata and .desktop files being returned twice by KParts::PartLoader::partsForMimeType
0208     //TODO: remove this when this doesn't happen anymore (KF6?)
0209     std::sort(partOfferList.begin(), partOfferList.end(), [](const KPluginMetaData &md1, const KPluginMetaData &md2){return md1.pluginId() == md2.pluginId();});
0210     auto unique = std::unique(partOfferList.begin(), partOfferList.end(), [](const KPluginMetaData &md1, const KPluginMetaData &md2){return md1.pluginId() == md2.pluginId();});
0211     partOfferList.erase(unique, partOfferList.end());
0212     for (const KPluginMetaData &md : partOfferList) {
0213         m_webEngineCombo->addItem(QIcon::fromTheme(md.iconName()), md.name(), md.pluginId());
0214     }
0215     KCModule::load();
0216 }
0217 
0218 void KKonqGeneralOptions::defaults()
0219 {
0220     homeURL->setText(QUrl(DEFAULT_HOMEPAGE).toString());
0221     startURL->setText(QUrl(DEFAULT_STARTPAGE).toString());
0222     m_splitBehaviour->setCurrentIndex(0);
0223     m_restoreLastState->setChecked(false);
0224 
0225     bool old = m_pConfig->readDefaults();
0226     m_pConfig->setReadDefaults(true);
0227     load();
0228     m_pConfig->setReadDefaults(old);
0229 #if QT_VERSION_MAJOR > 5
0230     setRepresentsDefaults(true);
0231 #endif
0232 }
0233 
0234 void KKonqGeneralOptions::save()
0235 {
0236     KConfigGroup userSettings(m_pConfig, "UserSettings");
0237     const int startComboIndex = m_startCombo->currentIndex();
0238     const StartPage choice = static_cast<StartPage>(m_startCombo->itemData(startComboIndex).toInt());
0239     QString startUrl(startPageEnumToUrl(static_cast<StartPage>(choice)));
0240     if (startUrl.isEmpty()) {
0241         startUrl = startURL->text();
0242     }
0243     userSettings.writeEntry("StartURL", startUrl);
0244     userSettings.writeEntry("HomeURL", homeURL->text());
0245     userSettings.writeEntry("AlwaysDuplicatePageWhenSplittingView", m_splitBehaviour->currentIndex() == 0);
0246     userSettings.writeEntry("RestoreLastState", m_restoreLastState->isChecked());
0247 
0248     if (m_webEngineCombo->currentIndex() > 0) {
0249         // The user changed the preferred web engine, save into mimeapps.list.
0250         const QString preferredWebEngine = m_webEngineCombo->itemData(m_webEngineCombo->currentIndex()).toString();
0251         //qCDebug(KONQUEROR_LOG) << "preferredWebEngine=" << preferredWebEngine;
0252 
0253         KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::ConfigLocation);
0254         KConfigGroup addedServices(profile, "Added KDE Service Associations");
0255         for (const QString &mimeType: QStringList() << "text/html" << "application/xhtml+xml" << "application/xml") {
0256             QStringList services = addedServices.readXdgListEntry(mimeType);
0257             services.removeAll(preferredWebEngine);
0258             services.prepend(preferredWebEngine); // make it the preferred one
0259             addedServices.writeXdgListEntry(mimeType, services);
0260         }
0261         profile->sync();
0262 
0263         // kbuildsycoca is the one reading mimeapps.list, so we need to run it now
0264         KBuildSycocaProgressDialog::rebuildKSycoca(widget());
0265     }
0266     m_pConfig->sync();
0267 
0268     // Send signal to all konqueror instances
0269     QDBusMessage message =
0270         QDBusMessage::createSignal(QStringLiteral("/KonqMain"), QStringLiteral("org.kde.Konqueror.Main"), QStringLiteral("reparseConfiguration"));
0271     QDBusConnection::sessionBus().send(message);
0272     KCModule::save();
0273 }
0274 
0275 void KKonqGeneralOptions::slotChanged()
0276 {
0277     setNeedsSave(true);
0278 }
0279