File indexing completed on 2024-04-28 17:06:08

0001 /*
0002     SPDX-FileCopyrightText: 2004 Csaba Karai <krusader@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "kgprotocols.h"
0009 #include "../Archive/krarchandler.h"
0010 #include "../icon.h"
0011 #include "../krglobal.h"
0012 #include "../krservices.h"
0013 
0014 // QtCore
0015 #include <QMimeDatabase>
0016 #include <QMimeType>
0017 // QtWidgets
0018 #include <QGridLayout>
0019 #include <QHeaderView>
0020 #include <QVBoxLayout>
0021 
0022 #include <KConfigCore/KSharedConfig>
0023 #include <KI18n/KLocalizedString>
0024 #include <KIOCore/KProtocolManager>
0025 
0026 KgProtocols::KgProtocols(bool first, QWidget *parent)
0027     : KonfiguratorPage(first, parent)
0028 {
0029     auto *KgProtocolsLayout = new QGridLayout(this);
0030     KgProtocolsLayout->setSpacing(6);
0031 
0032     //  -------------------------- LINK VIEW ----------------------------------
0033 
0034     QGroupBox *linkGrp = createFrame(i18n("Links"), this);
0035     QGridLayout *linkGrid = createGridLayout(linkGrp);
0036 
0037     QStringList labels;
0038     labels << i18n("Defined Links");
0039 
0040     linkList = new KrTreeWidget(linkGrp);
0041     linkList->setHeaderLabels(labels);
0042     linkList->setRootIsDecorated(true);
0043 
0044     linkGrid->addWidget(linkList, 0, 0);
0045     KgProtocolsLayout->addWidget(linkGrp, 0, 0, 2, 1);
0046 
0047     //  -------------------------- BUTTONS ----------------------------------
0048 
0049     QWidget *vbox1Widget = new QWidget(this);
0050     auto *vbox1 = new QVBoxLayout(vbox1Widget);
0051 
0052     addSpacer(vbox1);
0053     btnAddProtocol = new QPushButton(vbox1Widget);
0054     btnAddProtocol->setIcon(Icon("arrow-left"));
0055     btnAddProtocol->setWhatsThis(i18n("Add protocol to the link list."));
0056     vbox1->addWidget(btnAddProtocol);
0057 
0058     btnRemoveProtocol = new QPushButton(vbox1Widget);
0059     btnRemoveProtocol->setIcon(Icon("arrow-right"));
0060     btnRemoveProtocol->setWhatsThis(i18n("Remove protocol from the link list."));
0061     vbox1->addWidget(btnRemoveProtocol);
0062     addSpacer(vbox1);
0063 
0064     KgProtocolsLayout->addWidget(vbox1Widget, 0, 1);
0065 
0066     QWidget *vbox2Widget = new QWidget(this);
0067     auto *vbox2 = new QVBoxLayout(vbox2Widget);
0068 
0069     addSpacer(vbox2);
0070     btnAddMime = new QPushButton(vbox2Widget);
0071     btnAddMime->setIcon(Icon("arrow-left"));
0072     btnAddMime->setWhatsThis(i18n("Add MIME to the selected protocol on the link list."));
0073     vbox2->addWidget(btnAddMime);
0074 
0075     btnRemoveMime = new QPushButton(vbox2Widget);
0076     btnRemoveMime->setIcon(Icon("arrow-right"));
0077     btnRemoveMime->setWhatsThis(i18n("Remove MIME from the link list."));
0078     vbox2->addWidget(btnRemoveMime);
0079     addSpacer(vbox2);
0080 
0081     KgProtocolsLayout->addWidget(vbox2Widget, 1, 1);
0082 
0083     //  -------------------------- PROTOCOLS LISTBOX ----------------------------------
0084 
0085     QGroupBox *protocolGrp = createFrame(i18n("Protocols"), this);
0086     QGridLayout *protocolGrid = createGridLayout(protocolGrp);
0087 
0088     protocolList = new KrListWidget(protocolGrp);
0089     loadProtocols();
0090     protocolGrid->addWidget(protocolList, 0, 0);
0091 
0092     KgProtocolsLayout->addWidget(protocolGrp, 0, 2);
0093 
0094     //  -------------------------- MIMES LISTBOX ----------------------------------
0095 
0096     QGroupBox *mimeGrp = createFrame(i18n("MIMEs"), this);
0097     QGridLayout *mimeGrid = createGridLayout(mimeGrp);
0098 
0099     mimeList = new KrListWidget(mimeGrp);
0100     loadMimes();
0101     mimeGrid->addWidget(mimeList, 0, 0);
0102 
0103     KgProtocolsLayout->addWidget(mimeGrp, 1, 2);
0104 
0105     //  -------------------------- CONNECT TABLE ----------------------------------
0106 
0107     connect(protocolList, &KrListWidget::itemSelectionChanged, this, &KgProtocols::slotDisableButtons);
0108     connect(linkList, &KrTreeWidget::itemSelectionChanged, this, &KgProtocols::slotDisableButtons);
0109     connect(mimeList, &KrListWidget::itemSelectionChanged, this, &KgProtocols::slotDisableButtons);
0110     connect(linkList, &KrTreeWidget::currentItemChanged, this, &KgProtocols::slotDisableButtons);
0111     connect(btnAddProtocol, &QPushButton::clicked, this, &KgProtocols::slotAddProtocol);
0112     connect(btnRemoveProtocol, &QPushButton::clicked, this, &KgProtocols::slotRemoveProtocol);
0113     connect(btnAddMime, &QPushButton::clicked, this, &KgProtocols::slotAddMime);
0114     connect(btnRemoveMime, &QPushButton::clicked, this, &KgProtocols::slotRemoveMime);
0115 
0116     loadInitialValues();
0117     slotDisableButtons();
0118 }
0119 
0120 void KgProtocols::addSpacer(QBoxLayout *layout)
0121 {
0122     layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
0123 }
0124 
0125 void KgProtocols::loadProtocols()
0126 {
0127     QStringList protocols = KProtocolInfo::protocols();
0128     protocols.sort();
0129 
0130     foreach (const QString &protocol, protocols) {
0131         QUrl u;
0132         u.setScheme(protocol);
0133         if (KProtocolManager::inputType(u) == KProtocolInfo::T_FILESYSTEM) {
0134             protocolList->addItem(protocol);
0135         }
0136     }
0137 }
0138 
0139 void KgProtocols::loadMimes()
0140 {
0141     QMimeDatabase db;
0142     QList<QMimeType> mimes = db.allMimeTypes();
0143 
0144     for (QList<QMimeType>::const_iterator it = mimes.constBegin(); it != mimes.constEnd(); ++it)
0145         mimeList->addItem((*it).name());
0146 
0147     mimeList->sortItems();
0148 }
0149 
0150 void KgProtocols::slotDisableButtons()
0151 {
0152     btnAddProtocol->setEnabled(protocolList->selectedItems().count() != 0);
0153     QTreeWidgetItem *listViewItem = linkList->currentItem();
0154     bool isProtocolSelected = (listViewItem == nullptr ? false : listViewItem->parent() == nullptr);
0155     btnRemoveProtocol->setEnabled(isProtocolSelected);
0156     btnAddMime->setEnabled(listViewItem != nullptr && mimeList->selectedItems().count() != 0);
0157     btnRemoveMime->setEnabled(listViewItem == nullptr ? false : listViewItem->parent() != nullptr);
0158 
0159     if (linkList->currentItem() == nullptr && linkList->topLevelItemCount() != 0)
0160         linkList->setCurrentItem(linkList->topLevelItem(0));
0161 
0162     QList<QTreeWidgetItem *> list = linkList->selectedItems();
0163     if (list.count() == 0 && linkList->currentItem() != nullptr)
0164         linkList->currentItem()->setSelected(true);
0165 }
0166 
0167 void KgProtocols::slotAddProtocol()
0168 {
0169     QList<QListWidgetItem *> list = protocolList->selectedItems();
0170 
0171     if (list.count() > 0) {
0172         addProtocol(list[0]->text(), true);
0173         slotDisableButtons();
0174         emit sigChanged();
0175     }
0176 }
0177 
0178 void KgProtocols::addProtocol(const QString &name, bool changeCurrent)
0179 {
0180     QList<QListWidgetItem *> list = protocolList->findItems(name, Qt::MatchExactly);
0181     if (list.count() > 0) {
0182         delete list[0];
0183         auto *listViewItem = new QTreeWidgetItem(linkList);
0184         listViewItem->setText(0, name);
0185         QString iconName = KProtocolInfo::icon(name);
0186         if (iconName.isEmpty())
0187             iconName = "go-next-view";
0188         listViewItem->setIcon(0, Icon(iconName));
0189 
0190         if (changeCurrent)
0191             linkList->setCurrentItem(listViewItem);
0192     }
0193 }
0194 
0195 void KgProtocols::slotRemoveProtocol()
0196 {
0197     QTreeWidgetItem *item = linkList->currentItem();
0198     if (item) {
0199         removeProtocol(item->text(0));
0200         slotDisableButtons();
0201         emit sigChanged();
0202     }
0203 }
0204 
0205 void KgProtocols::removeProtocol(const QString &name)
0206 {
0207     QList<QTreeWidgetItem *> itemList = linkList->findItems(name, Qt::MatchExactly, 0);
0208 
0209     if (itemList.count()) {
0210         QTreeWidgetItem *item = itemList[0];
0211 
0212         while (item->childCount() != 0)
0213             removeMime(item->child(0)->text(0));
0214 
0215         linkList->takeTopLevelItem(linkList->indexOfTopLevelItem(item));
0216         protocolList->addItem(name);
0217         protocolList->sortItems();
0218     }
0219 }
0220 
0221 void KgProtocols::slotAddMime()
0222 {
0223     QList<QListWidgetItem *> list = mimeList->selectedItems();
0224     if (list.count() > 0 && linkList->currentItem() != nullptr) {
0225         QTreeWidgetItem *itemToAdd = linkList->currentItem();
0226         if (itemToAdd->parent())
0227             itemToAdd = itemToAdd->parent();
0228 
0229         addMime(list[0]->text(), itemToAdd->text(0));
0230         slotDisableButtons();
0231         emit sigChanged();
0232     }
0233 }
0234 
0235 void KgProtocols::addMime(QString name, const QString &protocol)
0236 {
0237     QList<QListWidgetItem *> list = mimeList->findItems(name, Qt::MatchExactly);
0238 
0239     QList<QTreeWidgetItem *> itemList = linkList->findItems(protocol, Qt::MatchExactly | Qt::MatchRecursive, 0);
0240 
0241     QTreeWidgetItem *currentListItem = nullptr;
0242     if (itemList.count() != 0)
0243         currentListItem = itemList[0];
0244 
0245     if (list.count() > 0 && currentListItem && currentListItem->parent() == nullptr) {
0246         delete list[0];
0247         auto *listViewItem = new QTreeWidgetItem(currentListItem);
0248         listViewItem->setText(0, name);
0249         listViewItem->setIcon(0, Icon(name.replace(QLatin1Char('/'), QLatin1Char('-')), Icon("unknown")));
0250         linkList->expandItem(currentListItem);
0251     }
0252 }
0253 
0254 void KgProtocols::slotRemoveMime()
0255 {
0256     QTreeWidgetItem *item = linkList->currentItem();
0257     if (item) {
0258         removeMime(item->text(0));
0259         slotDisableButtons();
0260         emit sigChanged();
0261     }
0262 }
0263 
0264 void KgProtocols::removeMime(const QString &name)
0265 {
0266     QList<QTreeWidgetItem *> itemList = linkList->findItems(name, Qt::MatchExactly | Qt::MatchRecursive, 0);
0267 
0268     QTreeWidgetItem *currentMimeItem = nullptr;
0269     if (itemList.count() != 0)
0270         currentMimeItem = itemList[0];
0271 
0272     if (currentMimeItem && currentMimeItem->parent() != nullptr) {
0273         mimeList->addItem(currentMimeItem->text(0));
0274         mimeList->sortItems();
0275         currentMimeItem->parent()->removeChild(currentMimeItem);
0276     }
0277 }
0278 
0279 void KgProtocols::loadInitialValues()
0280 {
0281     if (linkList->model()->rowCount() > 0)
0282         while (linkList->topLevelItemCount() != 0)
0283             removeProtocol(linkList->topLevelItem(0)->text(0));
0284 
0285     KConfigGroup group(krConfig, "Protocols");
0286     QStringList protList = group.readEntry("Handled Protocols", QStringList());
0287 
0288     for (auto &it : protList) {
0289         addProtocol(it);
0290 
0291         QStringList mimes = group.readEntry(QString("Mimes For %1").arg(it), QStringList());
0292 
0293         for (auto &mime : mimes)
0294             addMime(mime, it);
0295     }
0296 
0297     if (linkList->topLevelItemCount() != 0)
0298         linkList->setCurrentItem(linkList->topLevelItem(0));
0299     slotDisableButtons();
0300     linkList->expandAll();
0301     emit sigChanged();
0302 }
0303 
0304 void KgProtocols::setDefaults()
0305 {
0306     while (linkList->topLevelItemCount() != 0)
0307         removeProtocol(linkList->topLevelItem(0)->text(0));
0308 
0309     slotDisableButtons();
0310 
0311     if (isChanged())
0312         emit sigChanged();
0313 }
0314 
0315 bool KgProtocols::isChanged()
0316 {
0317     KConfigGroup group(krConfig, "Protocols");
0318     QStringList protList = group.readEntry("Handled Protocols", QStringList());
0319 
0320     if ((int)protList.count() != linkList->topLevelItemCount())
0321         return true;
0322 
0323     for (int i = 0; i != linkList->topLevelItemCount(); i++) {
0324         QTreeWidgetItem *item = linkList->topLevelItem(i);
0325 
0326         if (!protList.contains(item->text(0)))
0327             return true;
0328 
0329         QStringList mimes = group.readEntry(QString("Mimes For %1").arg(item->text(0)), QStringList());
0330 
0331         if ((int)mimes.count() != item->childCount())
0332             return true;
0333 
0334         for (int j = 0; j != item->childCount(); j++) {
0335             QTreeWidgetItem *children = item->child(j);
0336 
0337             if (!mimes.contains(children->text(0)))
0338                 return true;
0339         }
0340     }
0341 
0342     return false;
0343 }
0344 
0345 bool KgProtocols::apply()
0346 {
0347     KConfigGroup group(krConfig, "Protocols");
0348 
0349     QStringList protocolList;
0350 
0351     for (int i = 0; i != linkList->topLevelItemCount(); i++) {
0352         QTreeWidgetItem *item = linkList->topLevelItem(i);
0353 
0354         protocolList.append(item->text(0));
0355 
0356         QStringList mimes;
0357 
0358         for (int j = 0; j != item->childCount(); j++) {
0359             QTreeWidgetItem *children = item->child(j);
0360 
0361             mimes.append(children->text(0));
0362         }
0363         group.writeEntry(QString("Mimes For %1").arg(item->text(0)), mimes);
0364     }
0365     group.writeEntry("Handled Protocols", protocolList);
0366     krConfig->sync();
0367 
0368     KrArcHandler::clearProtocolCache();
0369 
0370     emit sigChanged();
0371     return false;
0372 }
0373 
0374 void KgProtocols::init()
0375 {
0376 }