File indexing completed on 2024-10-13 04:31:31

0001 /*
0002     smb4kbookmarkmenu  -  Bookmark menu
0003 
0004     SPDX-FileCopyrightText: 2011-2023 Alexander Reinholdt <alexander.reinholdt@kdemail.net>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 // application specific includes
0009 #include "smb4kbookmarkmenu.h"
0010 #include "core/smb4kbookmark.h"
0011 #include "core/smb4kbookmarkhandler.h"
0012 #include "core/smb4kglobal.h"
0013 #include "core/smb4kmounter.h"
0014 #include "core/smb4ksettings.h"
0015 #include "core/smb4kshare.h"
0016 
0017 // Qt includes
0018 #include <QDebug>
0019 #include <QMap>
0020 #include <QMapIterator>
0021 #include <QMenu>
0022 
0023 // KDE includes
0024 #include <KIconLoader>
0025 #include <KLocalizedString>
0026 
0027 using namespace Smb4KGlobal;
0028 
0029 Smb4KBookmarkMenu::Smb4KBookmarkMenu(int type, QObject *parent)
0030     : KActionMenu(KDE::icon(QStringLiteral("folder-favorites")), i18n("Bookmarks"), parent)
0031 {
0032     m_categories = new QActionGroup(menu());
0033     m_bookmarks = new QActionGroup(menu());
0034     m_mountActions = new QActionGroup(menu());
0035 
0036     m_editBookmarks = new QAction(KDE::icon(QStringLiteral("bookmarks-organize")), i18n("&Edit Bookmarks"), menu());
0037     m_editBookmarks->setEnabled(!Smb4KBookmarkHandler::self()->bookmarkList().isEmpty());
0038     connect(m_editBookmarks, SIGNAL(triggered(bool)), SLOT(slotEditActionTriggered(bool)));
0039     addAction(m_editBookmarks);
0040 
0041     if (type == MainWindow) {
0042         m_addBookmark = new QAction(KDE::icon(QStringLiteral("bookmark-new")), i18n("Add &Bookmark"), menu());
0043         m_addBookmark->setEnabled(false);
0044         connect(m_addBookmark, SIGNAL(triggered(bool)), SLOT(slotAddActionTriggered(bool)));
0045         addAction(m_addBookmark);
0046     } else {
0047         m_addBookmark = nullptr;
0048     }
0049 
0050     m_toplevelMount = new QAction(KDE::icon(QStringLiteral("media-mount")), i18n("Mount Bookmarks"), menu());
0051     addAction(m_toplevelMount);
0052     m_mountActions->addAction(m_toplevelMount);
0053 
0054     m_separator = addSeparator();
0055     m_separator->setVisible(!Smb4KBookmarkHandler::self()->bookmarkList().isEmpty());
0056 
0057     loadBookmarks();
0058     adjustMountActions();
0059 
0060     connect(Smb4KBookmarkHandler::self(), &Smb4KBookmarkHandler::updated, this, &Smb4KBookmarkMenu::loadBookmarks);
0061     connect(Smb4KMounter::self(), &Smb4KMounter::mounted, this, &Smb4KBookmarkMenu::slotEnableBookmark);
0062     connect(Smb4KMounter::self(), &Smb4KMounter::unmounted, this, &Smb4KBookmarkMenu::slotEnableBookmark);
0063     connect(m_bookmarks, &QActionGroup::triggered, this, &Smb4KBookmarkMenu::slotBookmarkActionTriggered);
0064     connect(m_mountActions, &QActionGroup::triggered, this, &Smb4KBookmarkMenu::slotMountActionTriggered);
0065 }
0066 
0067 Smb4KBookmarkMenu::~Smb4KBookmarkMenu()
0068 {
0069 }
0070 
0071 void Smb4KBookmarkMenu::refreshMenu()
0072 {
0073     loadBookmarks();
0074 }
0075 
0076 void Smb4KBookmarkMenu::loadBookmarks()
0077 {
0078     while (!m_categories->actions().isEmpty()) {
0079         QAction *category = m_categories->actions().takeFirst();
0080         removeAction(category);
0081         delete category;
0082     }
0083 
0084     while (!m_bookmarks->actions().isEmpty()) {
0085         QAction *bookmark = m_bookmarks->actions().takeFirst();
0086         removeAction(bookmark);
0087         delete bookmark;
0088     }
0089 
0090     QStringList categories = Smb4KBookmarkHandler::self()->categoryList();
0091     categories.sort();
0092 
0093     KActionMenu *categoryMenu = nullptr;
0094     QMap<QString, QAction *> topLevelActions;
0095 
0096     for (const QString &category : qAsConst(categories)) {
0097         if (!category.isEmpty()) {
0098             categoryMenu = new KActionMenu(category, menu());
0099             categoryMenu->setIcon(KDE::icon(QStringLiteral("folder-favorites")));
0100 
0101             addAction(categoryMenu);
0102             m_categories->addAction(categoryMenu);
0103 
0104             topLevelActions[QStringLiteral("00_") + category] = categoryMenu;
0105 
0106             QAction *categoryMount = new QAction(KDE::icon(QStringLiteral("media-mount")), i18n("Mount Bookmarks"), categoryMenu->menu());
0107             categoryMount->setData(category);
0108 
0109             categoryMenu->addAction(categoryMount);
0110             m_mountActions->addAction(categoryMount);
0111 
0112             categoryMenu->addSeparator();
0113         } else {
0114             categoryMenu = this;
0115         }
0116 
0117         QMap<QString, QAction *> actionMap;
0118         QList<BookmarkPtr> categoryBookmarks = Smb4KBookmarkHandler::self()->bookmarkList(category);
0119 
0120         for (const BookmarkPtr &bookmark : qAsConst(categoryBookmarks)) {
0121             QAction *bookmarkAction = new QAction(categoryMenu->menu());
0122             bookmarkAction->setIcon(bookmark->icon());
0123 
0124             QString displayName;
0125 
0126             if (Smb4KSettings::showCustomBookmarkLabel() && !bookmark->label().isEmpty()) {
0127                 displayName = bookmark->label();
0128             } else {
0129                 displayName = bookmark->displayString();
0130             }
0131 
0132             bookmarkAction->setText(displayName);
0133 
0134             QVariant variant = QVariant::fromValue(*bookmark.data());
0135             bookmarkAction->setData(variant);
0136 
0137             m_bookmarks->addAction(bookmarkAction);
0138 
0139             QList<SharePtr> mountedShares = findShareByUrl(bookmark->url());
0140 
0141             if (!mountedShares.isEmpty()) {
0142                 for (const SharePtr &share : qAsConst(mountedShares)) {
0143                     if (!share->isForeign()) {
0144                         bookmarkAction->setEnabled(false);
0145                         break;
0146                     }
0147                 }
0148             }
0149 
0150             if (!category.isEmpty()) {
0151                 actionMap[displayName] = bookmarkAction;
0152             } else {
0153                 topLevelActions[QStringLiteral("01_") + displayName] = bookmarkAction;
0154             }
0155         }
0156 
0157         QMapIterator<QString, QAction *> it(actionMap);
0158 
0159         while (it.hasNext()) {
0160             it.next();
0161             if (!category.isEmpty()) {
0162                 categoryMenu->addAction(it.value());
0163             }
0164         }
0165     }
0166 
0167     QMapIterator<QString, QAction *> it(topLevelActions);
0168 
0169     while (it.hasNext()) {
0170         QAction *action = it.next().value();
0171         addAction(action);
0172     }
0173 
0174     adjustMountActions();
0175 
0176     m_editBookmarks->setEnabled(!Smb4KBookmarkHandler::self()->bookmarkList().isEmpty());
0177     m_separator->setVisible(!Smb4KBookmarkHandler::self()->bookmarkList().isEmpty());
0178 
0179     menu()->update();
0180 }
0181 
0182 void Smb4KBookmarkMenu::setBookmarkActionEnabled(bool enable)
0183 {
0184     m_addBookmark->setEnabled(enable);
0185 }
0186 
0187 void Smb4KBookmarkMenu::adjustMountActions()
0188 {
0189     QList<BookmarkPtr> toplevelBookmarks = Smb4KBookmarkHandler::self()->bookmarkList(QStringLiteral(""));
0190 
0191     if (!toplevelBookmarks.isEmpty()) {
0192         int mountedBookmarks = 0;
0193 
0194         for (const BookmarkPtr &bookmark : qAsConst(toplevelBookmarks)) {
0195             QList<SharePtr> mountedShares = findShareByUrl(bookmark->url());
0196 
0197             for (const SharePtr &share : qAsConst(mountedShares)) {
0198                 if (!share->isForeign()) {
0199                     mountedBookmarks++;
0200                     break;
0201                 }
0202             }
0203         }
0204 
0205         m_toplevelMount->setVisible(true);
0206         m_toplevelMount->setEnabled(mountedBookmarks != toplevelBookmarks.size());
0207     } else {
0208         m_toplevelMount->setVisible(false);
0209         m_toplevelMount->setEnabled(false);
0210     }
0211 
0212     QList<QAction *> allMountActions = m_mountActions->actions();
0213     QStringList allCategories = Smb4KBookmarkHandler::self()->categoryList();
0214     int mountedBookmarks = 0;
0215 
0216     for (const QString &category : qAsConst(allCategories)) {
0217         QList<BookmarkPtr> bookmarks = Smb4KBookmarkHandler::self()->bookmarkList(category);
0218 
0219         for (const BookmarkPtr &bookmark : bookmarks) {
0220             QList<SharePtr> mountedShares = findShareByUrl(bookmark->url());
0221 
0222             if (!mountedShares.isEmpty()) {
0223                 for (const SharePtr &share : qAsConst(mountedShares)) {
0224                     if (!share->isForeign()) {
0225                         mountedBookmarks++;
0226                         break;
0227                     }
0228                 }
0229             }
0230         }
0231 
0232         for (QAction *action : allMountActions) {
0233             if (action->data().toString() == category) {
0234                 action->setEnabled(bookmarks.size() != mountedBookmarks);
0235                 break;
0236             }
0237         }
0238 
0239         mountedBookmarks = 0;
0240     }
0241 }
0242 
0243 /////////////////////////////////////////////////////////////////////////////
0244 // SLOT IMPLEMENTATIONS
0245 /////////////////////////////////////////////////////////////////////////////
0246 
0247 void Smb4KBookmarkMenu::slotEditActionTriggered(bool checked)
0248 {
0249     Q_UNUSED(checked);
0250 
0251     QPointer<Smb4KBookmarkEditor> bookmarkEditor = new Smb4KBookmarkEditor(menu());
0252     bookmarkEditor->open();
0253 }
0254 
0255 void Smb4KBookmarkMenu::slotAddActionTriggered(bool /*checked*/)
0256 {
0257     Q_EMIT addBookmark();
0258 }
0259 
0260 void Smb4KBookmarkMenu::slotMountActionTriggered(QAction *action)
0261 {
0262     QList<BookmarkPtr> bookmarks;
0263 
0264     if (action == m_toplevelMount) {
0265         bookmarks = Smb4KBookmarkHandler::self()->bookmarkList(QStringLiteral(""));
0266     } else {
0267         bookmarks = Smb4KBookmarkHandler::self()->bookmarkList(action->data().toString());
0268     }
0269 
0270     QList<SharePtr> mounts;
0271 
0272     for (const BookmarkPtr &bookmark : qAsConst(bookmarks)) {
0273         SharePtr share = SharePtr(new Smb4KShare());
0274         share->setUrl(bookmark->url());
0275         share->setWorkgroupName(bookmark->workgroupName());
0276         share->setHostIpAddress(bookmark->hostIpAddress());
0277         mounts << share;
0278     }
0279 
0280     Smb4KMounter::self()->mountShares(mounts);
0281 
0282     while (!mounts.isEmpty()) {
0283         mounts.takeFirst().clear();
0284     }
0285 }
0286 
0287 void Smb4KBookmarkMenu::slotBookmarkActionTriggered(QAction *action)
0288 {
0289     Smb4KBookmark bookmark = action->data().value<Smb4KBookmark>();
0290 
0291     SharePtr share = SharePtr(new Smb4KShare());
0292     share->setUrl(bookmark.url());
0293     share->setWorkgroupName(bookmark.workgroupName());
0294     share->setHostIpAddress(bookmark.hostIpAddress());
0295 
0296     Smb4KMounter::self()->mountShare(share);
0297 
0298     share.clear();
0299 }
0300 
0301 void Smb4KBookmarkMenu::slotEnableBookmark(const SharePtr &share)
0302 {
0303     if (!share->isForeign() && !m_bookmarks->actions().isEmpty()) {
0304         QList<QAction *> actions = m_bookmarks->actions();
0305 
0306         for (QAction *a : qAsConst(actions)) {
0307             QUrl bookmarkUrl = a->data().value<Smb4KBookmark>().url();
0308 
0309             if (share->url().matches(bookmarkUrl, QUrl::RemoveUserInfo | QUrl::RemovePort)) {
0310                 a->setEnabled(!share->isMounted());
0311                 break;
0312             }
0313         }
0314 
0315         adjustMountActions();
0316     }
0317 }