File indexing completed on 2023-12-03 05:04:22

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