File indexing completed on 2024-04-28 08:50:40
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 1998, 1999 Simon Hausmann <hausmann@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 // Own 0008 #include "konqguiclients.h" 0009 0010 // KDE 0011 #include <ktoggleaction.h> 0012 #include "konqdebug.h" 0013 #include <QIcon> 0014 #include <kiconloader.h> 0015 #include <KLocalizedString> 0016 0017 // Local 0018 #include "konqview.h" 0019 #include "konqsettingsxt.h" 0020 #include "konqframe.h" 0021 #include "konqframevisitor.h" 0022 #include "konqframestatusbar.h" 0023 #include "konqviewmanager.h" 0024 #include "pluginmetadatautils.h" 0025 #include "konqutils.h" 0026 0027 PopupMenuGUIClient::PopupMenuGUIClient(const QVector<KPluginMetaData> &embeddingServices, 0028 KonqPopupMenu::ActionGroupMap &actionGroups, 0029 QAction *showMenuBar, QAction *stopFullScreen) 0030 : m_actionCollection(this), 0031 m_embeddingServices(embeddingServices) 0032 { 0033 QList<QAction *> topActions; 0034 if (showMenuBar) { 0035 topActions.append(showMenuBar); 0036 QAction *separator = new QAction(&m_actionCollection); 0037 separator->setSeparator(true); 0038 topActions.append(separator); 0039 } 0040 0041 if (stopFullScreen) { 0042 topActions.append(stopFullScreen); 0043 QAction *separator = new QAction(&m_actionCollection); 0044 separator->setSeparator(true); 0045 topActions.append(separator); 0046 } 0047 0048 if (!embeddingServices.isEmpty()) { 0049 QList<QAction *> previewActions; 0050 if (embeddingServices.count() == 1) { 0051 KPluginMetaData service = embeddingServices.first(); 0052 QAction *act = addEmbeddingPlugin(0, i18n("Preview &in %1", service.name()), service); 0053 previewActions.append(act); 0054 } else if (embeddingServices.count() > 1) { 0055 QVector<KPluginMetaData>::ConstIterator it = embeddingServices.begin(); 0056 const QVector<KPluginMetaData>::ConstIterator end = embeddingServices.end(); 0057 int idx = 0; 0058 for (; it != end; ++it, ++idx) { 0059 QAction *act = addEmbeddingPlugin(idx, (*it).name(), *it); 0060 previewActions.append(act); 0061 } 0062 } 0063 actionGroups.insert(KonqPopupMenu::PreviewActions, previewActions); 0064 } 0065 actionGroups.insert(KonqPopupMenu::TopActions, topActions); 0066 } 0067 0068 PopupMenuGUIClient::~PopupMenuGUIClient() 0069 { 0070 } 0071 0072 QAction *PopupMenuGUIClient::addEmbeddingPlugin(int idx, const QString &name, const KPluginMetaData &plugin) 0073 { 0074 QAction *act = m_actionCollection.addAction(QByteArray::number(idx)); 0075 act->setText(name); 0076 act->setIcon(QIcon::fromTheme(plugin.iconName())); 0077 QObject::connect(act, &QAction::triggered, this, &PopupMenuGUIClient::slotOpenEmbedded); 0078 return act; 0079 } 0080 0081 void PopupMenuGUIClient::slotOpenEmbedded() 0082 { 0083 int idx = sender()->objectName().toInt(); 0084 // This calls KonqMainWindow::slotOpenEmbedded(service) (delayed so that the menu is closed first) 0085 emit openEmbedded(m_embeddingServices.at(idx)); 0086 } 0087 0088 //// 0089 0090 ToggleViewGUIClient::ToggleViewGUIClient(KonqMainWindow *mainWindow) 0091 : QObject(mainWindow) 0092 { 0093 m_mainWindow = mainWindow; 0094 0095 auto filter = [](const KPluginMetaData &md) { 0096 if (!Konq::serviceTypes(md).contains(QStringLiteral("Browser/View"))) { 0097 return false; 0098 } 0099 bool toggable = md.value(QStringLiteral("X-KDE-BrowserView-Toggable"), false); 0100 if (!toggable) { 0101 return false; 0102 } 0103 QString orientation = (QStringLiteral("X-KDE-BrowserView-ToggableView-Orientation"), QString()); 0104 if (!orientation.isEmpty()) { 0105 return false; 0106 } 0107 return true; 0108 }; 0109 QVector<KPluginMetaData> mds = findParts(filter, true); 0110 //TODO KF6: check whether this is still true 0111 //Sometimes there may be duplicates, so remove them 0112 std::sort(mds.begin(), mds.end(), [](const KPluginMetaData &md1, const KPluginMetaData &md2){return md1.pluginId() <= md2.pluginId();}); 0113 auto last = std::unique(mds.begin(), mds.end(), [](const KPluginMetaData &md1, const KPluginMetaData &md2){return md1.pluginId() == md2.pluginId();}); 0114 mds.erase(last, mds.end()); 0115 0116 m_empty = mds.isEmpty(); 0117 if (m_empty) { 0118 return; 0119 } 0120 0121 for (const KPluginMetaData &md : mds) { 0122 QString description = i18n("Show %1", md.name()); 0123 QString name = md.pluginId(); 0124 //qCDebug(KONQUEROR_LOG) << "ToggleViewGUIClient: name=" << name; 0125 KToggleAction *action = new KToggleAction(description, this); 0126 mainWindow->actionCollection()->addAction(name.toLatin1(), action); 0127 0128 // HACK 0129 if (md.iconName() != QLatin1String("unknown")) { 0130 action->setIcon(QIcon::fromTheme(md.iconName())); 0131 } 0132 0133 connect(action, &QAction::toggled, this, &ToggleViewGUIClient::slotToggleView); 0134 0135 m_actions.insert(name, action); 0136 0137 QVariant orientation = md.value(QStringLiteral("X-KDE-BrowserView-ToggableView-Orientation")); 0138 bool horizontal = orientation.toString().toLower() == QLatin1String("horizontal"); 0139 m_mapOrientation.insert(name, horizontal); 0140 } 0141 0142 connect(m_mainWindow, &KonqMainWindow::viewAdded, this, &ToggleViewGUIClient::slotViewAdded); 0143 connect(m_mainWindow, &KonqMainWindow::viewRemoved, this, &ToggleViewGUIClient::slotViewRemoved); 0144 } 0145 0146 ToggleViewGUIClient::~ToggleViewGUIClient() 0147 { 0148 } 0149 0150 QList<QAction *> ToggleViewGUIClient::actions() const 0151 { 0152 return m_actions.values(); 0153 } 0154 0155 void ToggleViewGUIClient::slotToggleView(bool toggle) 0156 { 0157 QString serviceName = sender()->objectName(); 0158 0159 bool horizontal = m_mapOrientation[ serviceName ]; 0160 0161 KonqViewManager *viewManager = m_mainWindow->viewManager(); 0162 0163 if (toggle) { 0164 // Don't crash when doing things too quickly. 0165 if (!m_mainWindow->currentView()) { 0166 return; 0167 } 0168 KonqView *childView = viewManager->splitMainContainer(m_mainWindow->currentView(), 0169 horizontal ? Qt::Vertical : Qt::Horizontal, 0170 QStringLiteral("Browser/View"), 0171 serviceName, 0172 !horizontal /* vertical = make it first */); 0173 0174 QList<int> newSplitterSizes; 0175 0176 if (horizontal) { 0177 newSplitterSizes << 100 << 30; 0178 } else { 0179 newSplitterSizes << 30 << 100; 0180 } 0181 0182 if (!childView || !childView->frame()) { 0183 return; 0184 } 0185 0186 // Toggleviews don't need their statusbar 0187 childView->frame()->statusbar()->hide(); 0188 0189 KonqFrameContainerBase *newContainer = childView->frame()->parentContainer(); 0190 0191 if (newContainer->frameType() == KonqFrameBase::Container) { 0192 static_cast<KonqFrameContainer *>(newContainer)->setSizes(newSplitterSizes); 0193 } 0194 0195 #if 0 // already done by splitWindow 0196 if (m_mainWindow->currentView()) { 0197 QString locBarURL = m_mainWindow->currentView()->url().prettyUrl(); // default one in case it doesn't set it 0198 childView->openUrl(m_mainWindow->currentView()->url(), locBarURL); 0199 } 0200 #endif 0201 0202 // If not passive, set as active :) 0203 if (!childView->isPassiveMode()) { 0204 viewManager->setActivePart(childView->part()); 0205 } 0206 0207 qCDebug(KONQUEROR_LOG) << "ToggleViewGUIClient::slotToggleView setToggleView(true) on " << childView; 0208 childView->setToggleView(true); 0209 0210 m_mainWindow->viewCountChanged(); 0211 0212 } else { 0213 const QList<KonqView *> viewList = KonqViewCollector::collect(m_mainWindow); 0214 for (KonqView *view: viewList) { 0215 if (view->service().pluginId() == serviceName) 0216 // takes care of choosing the new active view, and also calls slotViewRemoved 0217 { 0218 viewManager->removeView(view); 0219 } 0220 } 0221 } 0222 0223 } 0224 0225 void ToggleViewGUIClient::saveConfig(bool add, const QString &serviceName) 0226 { 0227 // This is used on konqueror's startup....... so it's never used, since 0228 // the K menu only contains calls to kfmclient...... 0229 // Well, it could be useful again in the future. 0230 // Currently, the profiles save this info. 0231 QStringList toggableViewsShown = KonqSettings::toggableViewsShown(); 0232 if (add) { 0233 if (!toggableViewsShown.contains(serviceName)) { 0234 toggableViewsShown.append(serviceName); 0235 } 0236 } else { 0237 toggableViewsShown.removeAll(serviceName); 0238 } 0239 KonqSettings::setToggableViewsShown(toggableViewsShown); 0240 } 0241 0242 void ToggleViewGUIClient::slotViewAdded(KonqView *view) 0243 { 0244 QString name = view->service().pluginId(); 0245 0246 QAction *action = m_actions.value(name); 0247 0248 if (action) { 0249 disconnect(action, &QAction::toggled, this, &ToggleViewGUIClient::slotToggleView); 0250 static_cast<KToggleAction *>(action)->setChecked(true); 0251 connect(action, &QAction::toggled, this, &ToggleViewGUIClient::slotToggleView); 0252 0253 saveConfig(true, name); 0254 0255 // KonqView::isToggleView() is not set yet.. so just check for the orientation 0256 0257 #if 0 0258 QVariant vert = view->service()->property("X-KDE-BrowserView-ToggableView-Orientation"); 0259 bool vertical = vert.toString().toLower() == "vertical"; 0260 QVariant nohead = view->service()->property("X-KDE-BrowserView-ToggableView-NoHeader"); 0261 bool noheader = nohead.isValid() ? nohead.toBool() : false; 0262 // if it is a vertical toggle part, turn on the header. 0263 // this works even when konq loads the view from a profile. 0264 if (vertical && (!noheader)) { 0265 view->frame()->header()->setText(view->service()->name()); 0266 view->frame()->header()->setAction(action); 0267 } 0268 #endif 0269 } 0270 } 0271 0272 void ToggleViewGUIClient::slotViewRemoved(KonqView *view) 0273 { 0274 QString name = view->service().pluginId(); 0275 0276 QAction *action = m_actions.value(name); 0277 0278 if (action) { 0279 disconnect(action, &QAction::toggled, this, &ToggleViewGUIClient::slotToggleView); 0280 static_cast<KToggleAction *>(action)->setChecked(false); 0281 connect(action, &QAction::toggled, this, &ToggleViewGUIClient::slotToggleView); 0282 saveConfig(false, name); 0283 } 0284 } 0285