File indexing completed on 2024-04-21 15:42:53

0001 /***************************************************************************
0002     smb4kbookmarkmenu  -  Bookmark menu
0003                              -------------------
0004     begin                : Sat Apr 02 2011
0005     copyright            : (C) 2011-2019 by Alexander Reinholdt
0006     email                : alexander.reinholdt@kdemail.net
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *   This program is free software; you can redistribute it and/or modify  *
0011  *   it under the terms of the GNU General Public License as published by  *
0012  *   the Free Software Foundation; either version 2 of the License, or     *
0013  *   (at your option) any later version.                                   *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful, but   *
0016  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
0018  *   General Public License for more details.                              *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program; if not, write to the                         *
0022  *   Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston,*
0023  *   MA 02110-1335, USA                                                    *
0024  ***************************************************************************/
0025 
0026 #ifdef HAVE_CONFIG_H
0027 #include <config.h>
0028 #endif
0029 
0030 // application specific includes
0031 #include "smb4kbookmarkmenu.h"
0032 #include "core/smb4kbookmark.h"
0033 #include "core/smb4kshare.h"
0034 #include "core/smb4kbookmarkhandler.h"
0035 #include "core/smb4kmounter.h"
0036 #include "core/smb4ksettings.h"
0037 #include "core/smb4kglobal.h"
0038 
0039 // Qt includes
0040 #include <QDebug>
0041 #include <QMenu>
0042 #include <QLatin1String>
0043 
0044 // KDE includes
0045 #include <KIconThemes/KIconLoader>
0046 #include <KI18n/KLocalizedString>
0047 
0048 using namespace Smb4KGlobal;
0049 
0050 
0051 Smb4KBookmarkMenu::Smb4KBookmarkMenu(int type, QWidget *parentWidget, QObject *parent)
0052 : KActionMenu(KDE::icon("folder-favorites"), i18n("Bookmarks"), parent), m_type(type),
0053   m_parent_widget(parentWidget)
0054 {
0055   //
0056   // Set up the action group for the actions
0057   //
0058   m_actions = new QActionGroup(menu());
0059 
0060   // 
0061   // Set up the action group for the bookmarks
0062   // 
0063   m_bookmarks = new QActionGroup(menu());
0064 
0065   // Set up the menu
0066   setupMenu();
0067 
0068   // Connections
0069   connect(Smb4KBookmarkHandler::self(), SIGNAL(updated()), SLOT(slotBookmarksUpdated()));
0070   connect(Smb4KMounter::self(), SIGNAL(mounted(SharePtr)), SLOT(slotEnableBookmark(SharePtr)));
0071   connect(Smb4KMounter::self(), SIGNAL(unmounted(SharePtr)), SLOT(slotEnableBookmark(SharePtr)));
0072   connect(m_actions, SIGNAL(triggered(QAction*)), SLOT(slotGroupActionTriggered(QAction*)));
0073   connect(m_bookmarks, SIGNAL(triggered(QAction*)), SLOT(slotBookmarkActionTriggered(QAction*)));
0074 }
0075 
0076 
0077 Smb4KBookmarkMenu::~Smb4KBookmarkMenu()
0078 {
0079 }
0080 
0081 
0082 void Smb4KBookmarkMenu::refreshMenu()
0083 {
0084   //
0085   // Delete all entries from the menu
0086   //
0087   while (!menu()->actions().isEmpty())
0088   {
0089     QAction *action = menu()->actions().takeFirst();
0090     removeAction(action);
0091     delete action;
0092   }
0093   
0094   //
0095   // Clear the rest of the menu
0096   //
0097   if (!menu()->isEmpty())
0098   {
0099     menu()->clear();
0100   }
0101   
0102   //
0103   // Set up the menu
0104   //
0105   setupMenu();
0106   
0107   //
0108   // Make sure the correct menu entries are shown
0109   //
0110   menu()->update();
0111 }
0112 
0113 
0114 void Smb4KBookmarkMenu::setBookmarkActionEnabled(bool enable)
0115 {
0116   QAction *action = menu()->findChild<QAction *>("add_action");
0117     
0118   if (action)
0119   {
0120     action->setEnabled(enable);
0121   }
0122 }
0123 
0124 
0125 void Smb4KBookmarkMenu::setupMenu()
0126 {
0127   //
0128   // Depending on the type chosen, some global actions need to be inserted
0129   // into the menu. These actions are always enabled.
0130   //
0131   switch (m_type)
0132   {
0133     case MainWindow:
0134     {
0135       QAction *editBookmarksAction = new QAction(KDE::icon("bookmarks-organize"), i18n("&Edit Bookmarks"), menu());
0136       editBookmarksAction->setObjectName("edit_action");
0137       QMap<QString,QVariant> editInfo;
0138       editInfo["type"] = "edit";
0139       editBookmarksAction->setData(editInfo);
0140       connect(editBookmarksAction, SIGNAL(triggered(bool)), SLOT(slotEditActionTriggered(bool)));
0141       addAction(editBookmarksAction);
0142       m_actions->addAction(editBookmarksAction);
0143       
0144       QAction *addBookmarkAction = new QAction(KDE::icon("bookmark-new"), i18n("Add &Bookmark"), menu());
0145       addBookmarkAction->setObjectName("add_action");
0146       QMap<QString,QVariant> addInfo;
0147       addInfo["type"] = "add";
0148       addBookmarkAction->setData(addInfo);
0149       addBookmarkAction->setEnabled(false);
0150       connect(addBookmarkAction, SIGNAL(triggered(bool)), SLOT(slotAddActionTriggered(bool)));
0151       addAction(addBookmarkAction);
0152       m_actions->addAction(addBookmarkAction);
0153       
0154       break;
0155     }
0156     case SystemTray:
0157     {
0158       QAction *editBookmarksAction = new QAction(KDE::icon("bookmarks-organize"), i18n("&Edit Bookmarks"), menu());
0159       editBookmarksAction->setObjectName("edit_action");
0160       QMap<QString,QVariant> editInfo;
0161       editInfo["type"] = "edit";
0162       editBookmarksAction->setData(editInfo);
0163       connect(editBookmarksAction, SIGNAL(triggered(bool)), SLOT(slotEditActionTriggered(bool)));
0164       addAction(editBookmarksAction);
0165       m_actions->addAction(editBookmarksAction);
0166       
0167       break;      
0168     }
0169     default:
0170     {
0171       break;
0172     }
0173   }
0174   
0175   //
0176   // Get the list of groups
0177   //
0178   QStringList allGroups = Smb4KBookmarkHandler::self()->groupsList();
0179   allGroups.sort();
0180   
0181   //
0182   // Insert a toplevel mount action, if necessary. Crucial for this is that there are 
0183   // no (non-empty) groups defined. Enable it if not all toplevel bookmarks are mounted.
0184   //
0185   if (allGroups.isEmpty() || (allGroups.size() == 1 && allGroups.first().isEmpty()))
0186   {
0187     QAction *toplevelMount = new QAction(KDE::icon("media-mount"), i18n("Mount All Bookmarks"), menu());
0188     toplevelMount->setObjectName("toplevel_mount");
0189     QMap<QString,QVariant> mountInfo;
0190     mountInfo["type"] = "toplevel_mount";
0191     toplevelMount->setData(mountInfo);
0192     connect(toplevelMount, SIGNAL(triggered(bool)), SLOT(slotToplevelMountActionTriggered(bool)));
0193     addAction(toplevelMount);
0194     m_actions->addAction(toplevelMount);
0195     
0196     QList<BookmarkPtr> bookmarks = Smb4KBookmarkHandler::self()->bookmarksList();
0197     int mountedBookmarks = 0;
0198     
0199     for (const BookmarkPtr &bookmark : bookmarks)
0200     {
0201       QList<SharePtr> mountedShares = findShareByUrl(bookmark->url());
0202       
0203       if (!mountedShares.isEmpty())
0204       {
0205         for (const SharePtr &share : mountedShares)
0206         {
0207           if (!share->isForeign())
0208           {
0209             mountedBookmarks++;
0210             break;
0211           }
0212           else
0213           {
0214             continue;
0215           }
0216         }
0217       }
0218     }
0219     
0220     toplevelMount->setEnabled(mountedBookmarks != bookmarks.size());
0221   }
0222   
0223   //
0224   // Add a separator
0225   //
0226   addSeparator();
0227   
0228   //
0229   // Now add the groups and their bookmarks
0230   //
0231   for (const QString &group : allGroups)
0232   {
0233     if (!group.isEmpty())
0234     {
0235       // Group menu entry
0236       KActionMenu *bookmarkGroupMenu = new KActionMenu(group, menu());
0237       bookmarkGroupMenu->setIcon(KDE::icon("folder-favorites"));
0238       QMap<QString,QVariant> menuInfo;
0239       menuInfo["type"] = "group_menu";
0240       menuInfo["group"] = group;
0241       bookmarkGroupMenu->setData(menuInfo);
0242       addAction(bookmarkGroupMenu);
0243       
0244       // Mount action for the group
0245       QAction *bookmarkGroupMount = new QAction(KDE::icon("media-mount"), i18n("Mount All Bookmarks"), bookmarkGroupMenu->menu());
0246       QMap<QString,QVariant> groupMountInfo;
0247       groupMountInfo["type"] = "group_mount";
0248       groupMountInfo["group"] = group;
0249       bookmarkGroupMount->setData(groupMountInfo);
0250       bookmarkGroupMenu->addAction(bookmarkGroupMount);
0251       m_actions->addAction(bookmarkGroupMount);
0252       
0253       // Get the list of bookmarks belonging to this group.
0254       // Use it to decide whether the group mount action should be enabled 
0255       // (only if not all bookmarks belonging to this group are mounted) and
0256       // to sort the bookmarks.      
0257       QList<BookmarkPtr> bookmarks = Smb4KBookmarkHandler::self()->bookmarksList(group);
0258       QStringList sortedBookmarks;
0259       int mountedBookmarks = 0;
0260       
0261       for (const BookmarkPtr &bookmark : bookmarks)
0262       {
0263         QAction *bookmarkAction = 0;
0264         
0265         if (Smb4KSettings::showCustomBookmarkLabel() && !bookmark->label().isEmpty())
0266         {
0267           bookmarkAction = new QAction(bookmark->icon(), bookmark->label(), bookmarkGroupMenu->menu());
0268           bookmarkAction->setObjectName(bookmark->url().toDisplayString());
0269           QMap<QString,QVariant> bookmarkInfo;
0270           bookmarkInfo["type"] = "bookmark";
0271           bookmarkInfo["group"] = group;
0272           bookmarkInfo["url"] = bookmark->url();
0273           bookmarkInfo["text"] = bookmark->label();
0274           bookmarkAction->setData(bookmarkInfo);
0275           m_bookmarks->addAction(bookmarkAction);
0276           sortedBookmarks << bookmark->label();
0277         }
0278         else
0279         {
0280           bookmarkAction = new QAction(bookmark->icon(), bookmark->displayString(), bookmarkGroupMenu->menu());
0281           bookmarkAction->setObjectName(bookmark->url().toDisplayString());
0282           QMap<QString,QVariant> bookmarkInfo;
0283           bookmarkInfo["type"] = "bookmark";
0284           bookmarkInfo["group"] = group;
0285           bookmarkInfo["url"] = bookmark->url();
0286           bookmarkInfo["text"] = bookmark->displayString();
0287           bookmarkAction->setData(bookmarkInfo);
0288           m_bookmarks->addAction(bookmarkAction);
0289           sortedBookmarks << bookmark->displayString();
0290         }
0291         
0292         QList<SharePtr> mountedShares = findShareByUrl(bookmark->url());
0293         
0294         if (!mountedShares.isEmpty())
0295         {
0296           for (const SharePtr &share : mountedShares)
0297           {
0298             if (!share->isForeign())
0299             {
0300               bookmarkAction->setEnabled(false);
0301               mountedBookmarks++;
0302               break;
0303             }
0304             else
0305             {
0306               continue;
0307             }
0308           }
0309         }
0310       }
0311       
0312       bookmarkGroupMount->setEnabled(mountedBookmarks != bookmarks.size());
0313       sortedBookmarks.sort();
0314       
0315       // Add a separator
0316       bookmarkGroupMenu->addSeparator();
0317       
0318       // Insert the sorted bookmarks into the group menu
0319       QList<QAction *> actions = m_bookmarks->actions();
0320       
0321       for (const QString &b : sortedBookmarks)
0322       {
0323         for (QAction *a : actions)
0324         {
0325           if (a->text() == b)
0326           {
0327             bookmarkGroupMenu->addAction(a);
0328             break;
0329           }
0330           else
0331           {
0332             continue;
0333           }
0334         }
0335       }
0336     }
0337   }
0338   
0339   //
0340   // Add all bookmarks that have no group
0341   // Sort the bookmarks before.  
0342   //
0343   QList<BookmarkPtr> bookmarks = Smb4KBookmarkHandler::self()->bookmarksList("");
0344   QStringList sortedBookmarks;
0345   
0346   for (const BookmarkPtr &bookmark : bookmarks)
0347   {
0348     QAction *bookmarkAction = 0;
0349         
0350     if (Smb4KSettings::showCustomBookmarkLabel() && !bookmark->label().isEmpty())
0351     {
0352       bookmarkAction = new QAction(bookmark->icon(), bookmark->label(), menu());
0353       bookmarkAction->setObjectName(bookmark->url().toDisplayString());
0354       QMap<QString,QVariant> bookmarkInfo;
0355       bookmarkInfo["type"] = "bookmark";
0356       bookmarkInfo["group"] = "";
0357       bookmarkInfo["url"] = bookmark->url();
0358       bookmarkInfo["text"] = bookmark->label();
0359       bookmarkAction->setData(bookmarkInfo);
0360       m_bookmarks->addAction(bookmarkAction);
0361       sortedBookmarks << bookmark->label();
0362     }
0363     else
0364     {
0365       bookmarkAction = new QAction(bookmark->icon(), bookmark->displayString(), menu());
0366       bookmarkAction->setObjectName(bookmark->url().toDisplayString());
0367       QMap<QString,QVariant> bookmarkInfo;
0368       bookmarkInfo["type"] = "bookmark";
0369       bookmarkInfo["group"] = "";
0370       bookmarkInfo["url"] = bookmark->url();
0371       bookmarkInfo["text"] = bookmark->displayString();
0372       bookmarkAction->setData(bookmarkInfo);
0373       m_bookmarks->addAction(bookmarkAction);
0374       sortedBookmarks << bookmark->displayString();
0375     }
0376         
0377     QList<SharePtr> mountedShares = findShareByUrl(bookmark->url());
0378         
0379     if (!mountedShares.isEmpty())
0380     {
0381       for (const SharePtr &share : mountedShares)
0382       {
0383         if (!share->isForeign())
0384         {
0385           bookmarkAction->setEnabled(false);
0386           break;
0387         }
0388         else
0389         {
0390           continue;
0391         }
0392       }
0393     }
0394   }
0395   
0396   sortedBookmarks.sort();
0397   
0398   QList<QAction *> actions = m_bookmarks->actions();
0399       
0400   for (const QString &b : sortedBookmarks)
0401   {
0402     for (QAction *a : actions)
0403     {
0404       if (a->data().toMap().value("text").toString() == b)
0405       {
0406         addAction(a);
0407         break;
0408       }
0409       else
0410       {
0411         continue;
0412       }
0413     }
0414   }
0415 }
0416 
0417 
0418 /////////////////////////////////////////////////////////////////////////////
0419 // SLOT IMPLEMENTATIONS
0420 /////////////////////////////////////////////////////////////////////////////
0421 
0422 void Smb4KBookmarkMenu::slotEditActionTriggered(bool /*checked*/)
0423 {
0424   Smb4KBookmarkHandler::self()->editBookmarks();
0425 }
0426 
0427 
0428 void Smb4KBookmarkMenu::slotAddActionTriggered(bool /*checked*/)
0429 {
0430   emit addBookmark();
0431 }
0432 
0433 
0434 void Smb4KBookmarkMenu::slotToplevelMountActionTriggered(bool /*checked*/)
0435 {
0436   //
0437   // Mount all top level bookmarks.
0438   // This slot will only be called if there are no groups defined.
0439   //
0440   QList<BookmarkPtr> bookmarks = Smb4KBookmarkHandler::self()->bookmarksList();
0441   QList<SharePtr> mounts;
0442 
0443   for (const BookmarkPtr &bookmark : bookmarks)
0444   {
0445     // FIXME: Check if the bookmarked share has already been mounted.
0446     SharePtr share = SharePtr(new Smb4KShare());
0447     share->setHostName(bookmark->hostName());
0448     share->setShareName(bookmark->shareName());
0449     share->setWorkgroupName(bookmark->workgroupName());
0450     share->setHostIpAddress(bookmark->hostIpAddress());
0451     share->setLogin(bookmark->login());
0452     mounts << share;
0453   }
0454 
0455   Smb4KMounter::self()->mountShares(mounts);
0456 
0457   while (!mounts.isEmpty())
0458   {
0459     mounts.takeFirst().clear();
0460   }
0461 }
0462 
0463 
0464 void Smb4KBookmarkMenu::slotGroupActionTriggered(QAction *action)
0465 {
0466   if (action->data().toMap().value("type").toString() == "group_mount")
0467   {
0468     //
0469     // Mount all bookmarks of one group
0470     //
0471     QList<BookmarkPtr> bookmarks = Smb4KBookmarkHandler::self()->bookmarksList(action->data().toMap().value("group").toString());
0472     QList<SharePtr> mounts;
0473 
0474     for (const BookmarkPtr &bookmark : bookmarks)
0475     {
0476       // FIXME: Check if the bookmarked share has already been mounted.
0477       SharePtr share = SharePtr(new Smb4KShare());
0478       share->setHostName(bookmark->hostName());
0479       share->setShareName(bookmark->shareName());
0480       share->setWorkgroupName(bookmark->workgroupName());
0481       share->setHostIpAddress(bookmark->hostIpAddress());
0482       share->setLogin(bookmark->login());
0483       mounts << share;
0484     }
0485 
0486     Smb4KMounter::self()->mountShares(mounts);
0487 
0488     while (!mounts.isEmpty())
0489     {
0490       mounts.takeFirst().clear();
0491     }
0492   }
0493 }
0494 
0495 
0496 void Smb4KBookmarkMenu::slotBookmarkActionTriggered(QAction *action)
0497 {
0498   QMap<QString,QVariant> info = action->data().toMap();
0499   QString bookmarkGroup = info.value("group").toString();
0500   QUrl url = info.value("url").toUrl();
0501   
0502   BookmarkPtr bookmark = Smb4KBookmarkHandler::self()->findBookmarkByUrl(url);
0503 
0504   if (bookmark && bookmarkGroup == bookmark->groupName())
0505   {
0506     SharePtr share = SharePtr(new Smb4KShare());
0507     share->setHostName(bookmark->hostName());
0508     share->setShareName(bookmark->shareName());
0509     share->setWorkgroupName(bookmark->workgroupName());
0510     share->setHostIpAddress(bookmark->hostIpAddress());
0511     share->setLogin(bookmark->login());
0512     Smb4KMounter::self()->mountShare(share);
0513     share.clear();
0514   }
0515 }
0516 
0517 
0518 void Smb4KBookmarkMenu::slotBookmarksUpdated()
0519 {
0520   refreshMenu();
0521 }
0522 
0523 
0524 void Smb4KBookmarkMenu::slotEnableBookmark(const SharePtr &share)
0525 {
0526   if (!share->isForeign() && !m_bookmarks->actions().isEmpty())
0527   {
0528     //
0529     // Enable or disable the bookmark
0530     //
0531     QList<QAction *> actions = m_bookmarks->actions();
0532     QString bookmarkGroup;
0533     
0534     for (QAction *a : actions)
0535     {
0536       QUrl bookmarkUrl = a->data().toMap().value("url").toUrl();
0537       
0538       if (share->url().matches(bookmarkUrl, QUrl::RemoveUserInfo|QUrl::RemovePort))
0539       {
0540         a->setEnabled(!share->isMounted());
0541         bookmarkGroup = a->data().toMap().value("group").toString();
0542         break;
0543       }
0544     }
0545     
0546     //
0547     // Check if all bookmarks belonging to this group are 
0548     // mounted. Enable the respective mount action if necessary.
0549     //
0550     bool allMounted = true;
0551       
0552     for (QAction *a : actions)
0553     {
0554       if (a->data().toMap().value("group").toString() == bookmarkGroup && a->isEnabled())
0555       {
0556         allMounted = false;
0557         break;
0558       }
0559       else
0560       {
0561         continue;
0562       }
0563     }
0564       
0565     QList<QAction *> allActions = m_actions->actions();
0566       
0567     for (QAction *a : allActions)
0568     {
0569       if (a->data().toMap().value("type").toString() == "toplevel_mount" && bookmarkGroup.isEmpty())
0570       {
0571         a->setEnabled(!allMounted);
0572         break;
0573       }
0574       else if (a->data().toMap().value("type").toString() == "group_mount" &&
0575                a->data().toMap().value("group").toString() == bookmarkGroup)
0576       {
0577         a->setEnabled(!allMounted);
0578         break;
0579       }
0580       else
0581       {
0582         continue;
0583       }
0584     }
0585   }
0586 }
0587