1 /* This file is part of the KDE project
2 SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
3 SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8 #include "konqbookmarkmenu.h"
9 #include "kbookmarkowner.h"
10 #include "kbookmarkaction.h"
11
12 #include <QMenu>
13 #include <QFile>
14
15 #include <kconfig.h>
16 #include <ksharedconfig.h>
17 #include <kconfiggroup.h>
18 #include <kactioncollection.h>
19 #include <kstringhandler.h>
20
21 #include "kbookmarkimporter.h"
22 #include "kbookmarkimporter_opera.h"
23 #include "kbookmarkimporter_ie.h"
24 #include "kbookmarkmanager.h"
25 #include "konqbookmarkmenu_p.h"
26 #include "konqpixmapprovider.h"
27
28 using namespace Konqueror;
29
KImportedBookmarkMenu(KBookmarkManager * mgr,KBookmarkOwner * owner,QMenu * parentMenu,const QString & type,const QString & location)30 KImportedBookmarkMenu::KImportedBookmarkMenu(KBookmarkManager *mgr,
31 KBookmarkOwner *owner, QMenu *parentMenu,
32 const QString &type, const QString &location)
33 : KBookmarkMenu(mgr, owner, parentMenu, QString()), m_type(type), m_location(location)
34 {
35 connect(parentMenu, &QMenu::aboutToShow, this, &KImportedBookmarkMenu::slotNSLoad);
36 }
37
KImportedBookmarkMenu(KBookmarkManager * mgr,KBookmarkOwner * owner,QMenu * parentMenu)38 KImportedBookmarkMenu::KImportedBookmarkMenu(KBookmarkManager *mgr,
39 KBookmarkOwner *owner, QMenu *parentMenu)
40 : KBookmarkMenu(mgr, owner, parentMenu, QString()), m_type(QString()), m_location(QString())
41 {
42 }
43
~KImportedBookmarkMenu()44 KImportedBookmarkMenu::~KImportedBookmarkMenu()
45 {
46 }
47
refill()48 void KImportedBookmarkMenu::refill()
49 {
50 }
51
clear()52 void KImportedBookmarkMenu::clear()
53 {
54 }
55
slotNSLoad()56 void KImportedBookmarkMenu::slotNSLoad()
57 {
58 // qCDebug(KBOOKMARKS_LOG)<<"**** slotNSLoad ****"<<m_type<<" "<<m_location;
59 // only fill menu once
60 disconnect(parentMenu(), &QMenu::aboutToShow, nullptr, nullptr);
61
62 // not NSImporter, but kept old name for BC reasons
63 KBookmarkMenuImporter importer(manager(), this);
64 importer.openBookmarks(m_location, m_type);
65 }
66
67 /********************************************************************/
68
openBookmarks(const QString & location,const QString & type)69 void KBookmarkMenuImporter::openBookmarks(const QString &location, const QString &type)
70 {
71 mstack.push(m_menu);
72
73 KBookmarkImporterBase *importer = KBookmarkImporterBase::factory(type);
74 if (!importer) {
75 return;
76 }
77 importer->setFilename(location);
78 connectToImporter(*importer);
79 importer->parse();
80
81 delete importer;
82 }
83
connectToImporter(const QObject & importer)84 void KBookmarkMenuImporter::connectToImporter(const QObject &importer)
85 {
86 connect(&importer, SIGNAL(newBookmark(QString,QString,QString)),
87 SLOT(newBookmark(QString,QString,QString)));
88 connect(&importer, SIGNAL(newFolder(QString,bool,QString)),
89 SLOT(newFolder(QString,bool,QString)));
90 connect(&importer, SIGNAL(newSeparator()), SLOT(newSeparator()));
91 connect(&importer, SIGNAL(endFolder()), SLOT(endFolder()));
92 }
93
newBookmark(const QString & text,const QString & url,const QString &)94 void KBookmarkMenuImporter::newBookmark(const QString &text, const QString &url, const QString &)
95 {
96 KBookmark bm = KBookmark::standaloneBookmark(text, QUrl(url), QStringLiteral("html"));
97 QAction *action = new KBookmarkAction(bm, mstack.top()->owner(), this);
98 mstack.top()->parentMenu()->addAction(action);
99 mstack.top()->m_actions.append(action);
100 }
101
newFolder(const QString & text,bool,const QString &)102 void KBookmarkMenuImporter::newFolder(const QString &text, bool, const QString &)
103 {
104 QString _text = KStringHandler::csqueeze(text).replace(QLatin1Char('&'), QLatin1String("&&"));
105 KActionMenu *actionMenu = new KImportedBookmarkActionMenu(QIcon::fromTheme(QStringLiteral("folder")), _text, this);
106 mstack.top()->parentMenu()->addAction(actionMenu);
107 mstack.top()->m_actions.append(actionMenu);
108 KImportedBookmarkMenu *subMenu = new KImportedBookmarkMenu(m_pManager, m_menu->owner(), actionMenu->menu());
109 mstack.top()->m_lstSubMenus.append(subMenu);
110
111 mstack.push(subMenu);
112 }
113
newSeparator()114 void KBookmarkMenuImporter::newSeparator()
115 {
116 mstack.top()->parentMenu()->addSeparator();
117 }
118
endFolder()119 void KBookmarkMenuImporter::endFolder()
120 {
121 mstack.pop();
122 }
123
124 /********************************************************************/
125
KonqBookmarkContextMenu(const KBookmark & bm,KBookmarkManager * mgr,KBookmarkOwner * owner)126 KonqBookmarkContextMenu::KonqBookmarkContextMenu(const KBookmark &bm, KBookmarkManager *mgr, KBookmarkOwner *owner)
127 : KBookmarkContextMenu(bm, mgr, owner)
128 {
129 }
130
~KonqBookmarkContextMenu()131 KonqBookmarkContextMenu::~KonqBookmarkContextMenu()
132 {
133 }
134
addActions()135 void KonqBookmarkContextMenu::addActions()
136 {
137 KConfigGroup config = KSharedConfig::openConfig(QStringLiteral("kbookmarkrc"), KConfig::NoGlobals)->group("Bookmarks");
138 bool filteredToolbar = config.readEntry("FilteredToolbar", false);
139
140 if (bookmark().isGroup()) {
141 addOpenFolderInTabs();
142 addBookmark();
143
144 if (filteredToolbar) {
145 QString text = bookmark().showInToolbar() ? tr("Hide in toolbar") : tr("Show in toolbar");
146 addAction(text, this, &KonqBookmarkContextMenu::toggleShowInToolbar);
147 }
148
149 addFolderActions();
150 } else {
151 if (owner()) {
152 addAction(QIcon::fromTheme(QStringLiteral("window-new")), tr("Open in New Window"), this, &KonqBookmarkContextMenu::openInNewWindow);
153 addAction(QIcon::fromTheme(QStringLiteral("tab-new")), tr("Open in New Tab"), this, &KonqBookmarkContextMenu::openInNewTab);
154 }
155 addBookmark();
156
157 if (filteredToolbar) {
158 QString text = bookmark().showInToolbar() ? tr("Hide in toolbar") : tr("Show in toolbar");
159 addAction(text, this, &KonqBookmarkContextMenu::toggleShowInToolbar);
160 }
161
162 addBookmarkActions();
163 }
164 }
165
toggleShowInToolbar()166 void KonqBookmarkContextMenu::toggleShowInToolbar()
167 {
168 bookmark().setShowInToolbar(!bookmark().showInToolbar());
169 manager()->emitChanged(bookmark().parentGroup());
170 }
171
openInNewTab()172 void KonqBookmarkContextMenu::openInNewTab()
173 {
174 owner()->openInNewTab(bookmark());
175 }
176
openInNewWindow()177 void KonqBookmarkContextMenu::openInNewWindow()
178 {
179 owner()->openInNewWindow(bookmark());
180 }
181
182 /******************************/
183 /******************************/
184 /******************************/
185
fillDynamicBookmarks()186 void KonqBookmarkMenu::fillDynamicBookmarks()
187 {
188 if (isDirty()
189 && KBookmarkManager::userBookmarksManager()->path() == manager()->path()) {
190 bool haveSep = false;
191
192 const QStringList keys = KonqBookmarkMenu::dynamicBookmarksList();
193 for (QStringList::const_iterator it = keys.begin(); it != keys.end(); ++it) {
194 DynMenuInfo info;
195 info = showDynamicBookmarks((*it));
196
197 if (!info.show || !QFile::exists(info.location)) {
198 continue;
199 }
200
201 if (!haveSep) {
202 parentMenu()->addSeparator();
203 haveSep = true;
204 }
205
206 KActionMenu *actionMenu;
207 actionMenu = new KActionMenu(QIcon::fromTheme(info.type), info.name, this);
208 m_actionCollection->addAction(QStringLiteral("kbookmarkmenu"), actionMenu);
209
210 parentMenu()->addAction(actionMenu);
211 m_actions.append(actionMenu);
212
213 KImportedBookmarkMenu *subMenu =
214 new KImportedBookmarkMenu(manager(), owner(), actionMenu->menu(),
215 info.type, info.location);
216 m_lstSubMenus.append(subMenu);
217 }
218 }
219 }
220
refill()221 void KonqBookmarkMenu::refill()
222 {
223 if (isRoot()) {
224 addActions();
225 }
226 fillDynamicBookmarks();
227 fillBookmarks();
228 if (!isRoot()) {
229 addActions();
230 }
231 }
232
actionForBookmark(const KBookmark & _bm)233 QAction *KonqBookmarkMenu::actionForBookmark(const KBookmark &_bm)
234 {
235 //We need a non-const copy of it
236 KBookmark bm(_bm);
237 if (bm.isGroup()) {
238 // qCDebug(KBOOKMARKS_LOG) << "Creating Konq bookmark submenu named " << bm.text();
239 KBookmarkActionMenu *actionMenu = new KBookmarkActionMenu(bm, this);
240 m_actionCollection->addAction(QStringLiteral("kbookmarkmenu"), actionMenu);
241 m_actions.append(actionMenu);
242
243 KBookmarkMenu *subMenu = new KonqBookmarkMenu(manager(), owner(), actionMenu, bm.address());
244
245 m_lstSubMenus.append(subMenu);
246 return actionMenu;
247 } else if (bm.isSeparator()) {
248 return KBookmarkMenu::actionForBookmark(bm);
249 } else {
250 // qCDebug(KBOOKMARKS_LOG) << "Creating Konq bookmark action named " << bm.text();
251 QUrl host = bm.url().adjusted(QUrl::RemovePath | QUrl::RemoveQuery);
252 bm.setIcon(KonqPixmapProvider::self()->iconNameFor(host));
253 KBookmarkAction *action = new KBookmarkAction(bm, owner(), this);
254 connect(KonqPixmapProvider::self(), &KonqPixmapProvider::changed, action, [host, action]() {
255 action->setIcon(KonqPixmapProvider::self()->iconForUrl(host));
256 });
257 KonqPixmapProvider::self()->downloadHostIcon(host);
258 m_actionCollection->addAction(action->objectName(), action);
259 m_actions.append(action);
260 return action;
261 }
262 }
263
showDynamicBookmarks(const QString & id)264 KonqBookmarkMenu::DynMenuInfo KonqBookmarkMenu::showDynamicBookmarks(const QString &id)
265 {
266 KConfig bookmarkrc(QStringLiteral("kbookmarkrc"), KConfig::NoGlobals);
267 KConfigGroup config(&bookmarkrc, "Bookmarks");
268
269 DynMenuInfo info;
270 info.show = false;
271 info.d = nullptr;
272
273 if (!config.hasKey("DynamicMenus")) {
274 const QString dynamicMenuGroupId = QLatin1String("DynamicMenu-") + id;
275 if (bookmarkrc.hasGroup(dynamicMenuGroupId)) {
276 KConfigGroup dynGroup(&bookmarkrc, dynamicMenuGroupId);
277 info.show = dynGroup.readEntry("Show", false);
278 info.location = dynGroup.readPathEntry("Location", QString());
279 info.type = dynGroup.readEntry("Type");
280 info.name = dynGroup.readEntry("Name");
281 }
282 }
283 return info;
284 }
285
dynamicBookmarksList()286 QStringList KonqBookmarkMenu::dynamicBookmarksList()
287 {
288 KConfigGroup config = KSharedConfig::openConfig(QStringLiteral("kbookmarkrc"), KConfig::NoGlobals)->group("Bookmarks");
289
290 QStringList mlist;
291 if (config.hasKey("DynamicMenus")) {
292 mlist = config.readEntry("DynamicMenus", QStringList());
293 }
294
295 return mlist;
296 }
297
setDynamicBookmarks(const QString & id,const DynMenuInfo & newMenu)298 void KonqBookmarkMenu::setDynamicBookmarks(const QString &id, const DynMenuInfo &newMenu)
299 {
300 KSharedConfig::Ptr kbookmarkrc = KSharedConfig::openConfig(QStringLiteral("kbookmarkrc"), KConfig::NoGlobals);
301 KConfigGroup dynConfig = kbookmarkrc->group(QLatin1String("DynamicMenu-") + id);
302
303 // add group unconditionally
304 dynConfig.writeEntry("Show", newMenu.show);
305 dynConfig.writePathEntry("Location", newMenu.location);
306 dynConfig.writeEntry("Type", newMenu.type);
307 dynConfig.writeEntry("Name", newMenu.name);
308
309 QStringList elist;
310 KConfigGroup config = kbookmarkrc->group("Bookmarks");
311 if (config.hasKey("DynamicMenus")) {
312 elist = config.readEntry("DynamicMenus", QStringList());
313 }
314
315 // make sure list includes type
316 if (!elist.contains(id)) {
317 elist << id;
318 config.writeEntry("DynamicMenus", elist);
319 }
320
321 config.sync();
322 }
323
contextMenu(QAction * action)324 QMenu *KonqBookmarkMenu::contextMenu(QAction *action)
325 {
326 KBookmarkActionInterface *act = dynamic_cast<KBookmarkActionInterface *>(action);
327 if (!act) {
328 return nullptr;
329 }
330 return new KonqBookmarkContextMenu(act->bookmark(), manager(), owner());
331 }
332
333 #include "moc_konqbookmarkmenu.cpp"
334