From 9a10c0676e88bcbbd16f613d9dd9eedf71095b21 Mon Sep 17 00:00:00 2001
From: Kai Sommerfeld <kai.sommerfeld@gmx.com>
Date: Thu, 22 Sep 2022 15:04:46 +0200
Subject: [PVR] Refactor CPVRGUIActions step 2: Move recording related actions
 to own class.

---
 xbmc/pvr/guilib/CMakeLists.txt              |   2 +
 xbmc/pvr/guilib/PVRGUIActions.cpp           | 333 +------------------------
 xbmc/pvr/guilib/PVRGUIActions.h             |  79 +-----
 xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp | 362 ++++++++++++++++++++++++++++
 xbmc/pvr/guilib/PVRGUIActionsRecordings.h   | 106 ++++++++
 5 files changed, 483 insertions(+), 399 deletions(-)
 create mode 100644 xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp
 create mode 100644 xbmc/pvr/guilib/PVRGUIActionsRecordings.h

diff --git a/xbmc/pvr/guilib/CMakeLists.txt b/xbmc/pvr/guilib/CMakeLists.txt
index c035324329..9bf165ee0f 100644
--- a/xbmc/pvr/guilib/CMakeLists.txt
+++ b/xbmc/pvr/guilib/CMakeLists.txt
@@ -2,6 +2,7 @@ set(SOURCES GUIEPGGridContainer.cpp
             GUIEPGGridContainerModel.cpp
             PVRGUIActionListener.cpp
             PVRGUIActions.cpp
+            PVRGUIActionsRecordings.cpp
             PVRGUIActionsTimers.cpp
             PVRGUIChannelIconUpdater.cpp
             PVRGUIChannelNavigator.cpp
@@ -11,6 +12,7 @@ set(HEADERS GUIEPGGridContainer.h
             GUIEPGGridContainerModel.h
             PVRGUIActionListener.h
             PVRGUIActions.h
+            PVRGUIActionsRecordings.h
             PVRGUIActionsTimers.h
             PVRGUIChannelIconUpdater.h
             PVRGUIChannelNavigator.h
diff --git a/xbmc/pvr/guilib/PVRGUIActions.cpp b/xbmc/pvr/guilib/PVRGUIActions.cpp
index 8100faeae1..a8028fa194 100644
--- a/xbmc/pvr/guilib/PVRGUIActions.cpp
+++ b/xbmc/pvr/guilib/PVRGUIActions.cpp
@@ -10,10 +10,8 @@
 
 #include "FileItem.h"
 #include "ServiceBroker.h"
-#include "Util.h"
 #include "application/ApplicationEnums.h"
 #include "cores/DataCacheCore.h"
-#include "dialogs/GUIDialogBusy.h"
 #include "dialogs/GUIDialogKaiToast.h"
 #include "dialogs/GUIDialogNumeric.h"
 #include "dialogs/GUIDialogProgress.h"
@@ -45,8 +43,6 @@
 #include "pvr/channels/PVRChannelGroupsContainer.h"
 #include "pvr/dialogs/GUIDialogPVRChannelGuide.h"
 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
-#include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
-#include "pvr/dialogs/GUIDialogPVRRecordingSettings.h"
 #include "pvr/epg/EpgContainer.h"
 #include "pvr/epg/EpgDatabase.h"
 #include "pvr/epg/EpgInfoTag.h"
@@ -59,7 +55,6 @@
 #include "pvr/windows/GUIWindowPVRSearch.h"
 #include "settings/MediaSettings.h"
 #include "settings/Settings.h"
-#include "threads/IRunnable.h"
 #include "utils/StringUtils.h"
 #include "utils/URIUtils.h"
 #include "utils/Variant.h"
@@ -71,7 +66,6 @@
 #include <iterator>
 #include <memory>
 #include <mutex>
-#include <numeric>
 #include <string>
 #include <utility>
 #include <vector>
@@ -101,155 +95,16 @@ PVR::CGUIWindowPVRSearchBase* GetSearchWindow(bool bRadio)
 
 namespace PVR
 {
-  class AsyncRecordingAction : private IRunnable
-  {
-  public:
-    bool Execute(const CFileItemPtr& item);
-
-  protected:
-    AsyncRecordingAction() = default;
-
-  private:
-    // IRunnable implementation
-    void Run() override;
-
-    // the worker function
-    virtual bool DoRun(const CFileItemPtr& item) = 0;
-
-    CFileItemPtr m_item;
-    bool m_bSuccess = false;
-  };
-
-  bool AsyncRecordingAction::Execute(const CFileItemPtr& item)
-  {
-    m_item = item;
-    CGUIDialogBusy::Wait(this, 100, false);
-    return m_bSuccess;
-  }
-
-  void AsyncRecordingAction::Run()
-  {
-    m_bSuccess = DoRun(m_item);
-
-    if (m_bSuccess)
-      CServiceBroker::GetPVRManager().TriggerRecordingsUpdate();
-  }
-
-  class AsyncRenameRecording : public AsyncRecordingAction
-  {
-  public:
-    explicit AsyncRenameRecording(const std::string& strNewName) : m_strNewName(strNewName) {}
-
-  private:
-    bool DoRun(const std::shared_ptr<CFileItem>& item) override
-    {
-      if (item->IsUsablePVRRecording())
-      {
-        return item->GetPVRRecordingInfoTag()->Rename(m_strNewName);
-      }
-      else
-      {
-        CLog::LogF(LOGERROR, "Cannot rename item '{}': no valid recording tag", item->GetPath());
-        return false;
-      }
-    }
-    std::string m_strNewName;
-  };
-
-  class AsyncDeleteRecording : public AsyncRecordingAction
-  {
-  public:
-    explicit AsyncDeleteRecording(bool bWatchedOnly = false) : m_bWatchedOnly(bWatchedOnly) {}
-
-  private:
-    bool DoRun(const std::shared_ptr<CFileItem>& item) override
-    {
-      CFileItemList items;
-      if (item->m_bIsFolder)
-      {
-        CUtil::GetRecursiveListing(item->GetPath(), items, "", XFILE::DIR_FLAG_NO_FILE_INFO);
-      }
-      else
-      {
-        items.Add(item);
-      }
-
-      return std::accumulate(
-          items.cbegin(), items.cend(), true, [this](bool success, const auto& itemToDelete) {
-            return (itemToDelete->IsPVRRecording() &&
-                    (!m_bWatchedOnly ||
-                     itemToDelete->GetPVRRecordingInfoTag()->GetPlayCount() > 0) &&
-                    !itemToDelete->GetPVRRecordingInfoTag()->Delete())
-                       ? false
-                       : success;
-          });
-    }
-    bool m_bWatchedOnly = false;
-  };
-
-  class AsyncEmptyRecordingsTrash : public AsyncRecordingAction
-  {
-  private:
-    bool DoRun(const std::shared_ptr<CFileItem>& item) override
-    {
-      return CServiceBroker::GetPVRManager().Clients()->DeleteAllRecordingsFromTrash() == PVR_ERROR_NO_ERROR;
-    }
-  };
-
-  class AsyncUndeleteRecording : public AsyncRecordingAction
-  {
-  private:
-    bool DoRun(const std::shared_ptr<CFileItem>& item) override
-    {
-      if (item->IsDeletedPVRRecording())
-      {
-        return item->GetPVRRecordingInfoTag()->Undelete();
-      }
-      else
-      {
-        CLog::LogF(LOGERROR, "Cannot undelete item '{}': no valid recording tag", item->GetPath());
-        return false;
-      }
-    }
-  };
-
-  class AsyncSetRecordingPlayCount : public AsyncRecordingAction
-  {
-  private:
-    bool DoRun(const CFileItemPtr& item) override
-    {
-      const std::shared_ptr<CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(*item);
-      if (client)
-      {
-        const std::shared_ptr<CPVRRecording> recording = item->GetPVRRecordingInfoTag();
-        return client->SetRecordingPlayCount(*recording, recording->GetLocalPlayCount()) == PVR_ERROR_NO_ERROR;
-      }
-      return false;
-    }
-  };
-
-  class AsyncSetRecordingLifetime : public AsyncRecordingAction
-  {
-  private:
-    bool DoRun(const CFileItemPtr& item) override
-    {
-      const std::shared_ptr<CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(*item);
-      if (client)
-        return client->SetRecordingLifetime(*item->GetPVRRecordingInfoTag()) == PVR_ERROR_NO_ERROR;
-      return false;
-    }
-  };
-
-  CPVRGUIActions::CPVRGUIActions()
-    : m_settings({CSettings::SETTING_LOOKANDFEEL_STARTUPACTION,
-                  CSettings::SETTING_PVRMANAGER_PRESELECTPLAYINGCHANNEL,
-                  CSettings::SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH,
-                  CSettings::SETTING_PVRPLAYBACK_SWITCHTOFULLSCREENCHANNELTYPES,
-                  CSettings::SETTING_PVRPARENTAL_PIN, CSettings::SETTING_PVRPARENTAL_ENABLED,
-                  CSettings::SETTING_PVRPOWERMANAGEMENT_DAILYWAKEUPTIME,
-                  CSettings::SETTING_PVRPOWERMANAGEMENT_BACKENDIDLETIME})
-  {
-  }
+CPVRGUIActions::CPVRGUIActions()
+  : m_settings({CSettings::SETTING_LOOKANDFEEL_STARTUPACTION,
+                CSettings::SETTING_PVRMANAGER_PRESELECTPLAYINGCHANNEL,
+                CSettings::SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH,
+                CSettings::SETTING_PVRPLAYBACK_SWITCHTOFULLSCREENCHANNELTYPES,
+                CSettings::SETTING_PVRPARENTAL_PIN, CSettings::SETTING_PVRPARENTAL_ENABLED,
+                CSettings::SETTING_PVRPOWERMANAGEMENT_DAILYWAKEUPTIME,
+                CSettings::SETTING_PVRPOWERMANAGEMENT_BACKENDIDLETIME})
+{
+}
 
   bool CPVRGUIActions::ShowEPGInfo(const CFileItemPtr& item) const
   {
@@ -294,27 +149,6 @@ namespace PVR
     return true;
   }
 
-
-  bool CPVRGUIActions::ShowRecordingInfo(const CFileItemPtr& item) const
-  {
-    if (!item->IsPVRRecording())
-    {
-      CLog::LogF(LOGERROR, "No recording!");
-      return false;
-    }
-
-    CGUIDialogPVRRecordingInfo* pDlgInfo = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogPVRRecordingInfo>(WINDOW_DIALOG_PVR_RECORDING_INFO);
-    if (!pDlgInfo)
-    {
-      CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_PVR_RECORDING_INFO!");
-      return false;
-    }
-
-    pDlgInfo->SetRecording(item.get());
-    pDlgInfo->Open();
-    return true;
-  }
-
   bool CPVRGUIActions::FindSimilar(const std::shared_ptr<CFileItem>& item) const
   {
     CGUIWindowPVRSearchBase* windowSearch = GetSearchWindow(CPVRItem(item).IsRadio());
@@ -348,151 +182,6 @@ namespace PVR
     return true;
   };
 
-  bool CPVRGUIActions::EditRecording(const CFileItemPtr& item) const
-  {
-    const std::shared_ptr<CPVRRecording> recording = CPVRItem(item).GetRecording();
-    if (!recording)
-    {
-      CLog::LogF(LOGERROR, "No recording!");
-      return false;
-    }
-
-    std::shared_ptr<CPVRRecording> origRecording(new CPVRRecording);
-    origRecording->Update(*recording,
-                          *CServiceBroker::GetPVRManager().GetClient(recording->m_iClientId));
-
-    if (!ShowRecordingSettings(recording))
-      return false;
-
-    if (origRecording->m_strTitle != recording->m_strTitle)
-    {
-      if (!AsyncRenameRecording(recording->m_strTitle).Execute(item))
-        CLog::LogF(LOGERROR, "Renaming recording failed!");
-    }
-
-    if (origRecording->GetLocalPlayCount() != recording->GetLocalPlayCount())
-    {
-      if (!AsyncSetRecordingPlayCount().Execute(item))
-        CLog::LogF(LOGERROR, "Setting recording playcount failed!");
-    }
-
-    if (origRecording->m_iLifetime != recording->m_iLifetime)
-    {
-      if (!AsyncSetRecordingLifetime().Execute(item))
-        CLog::LogF(LOGERROR, "Setting recording lifetime failed!");
-    }
-
-    return true;
-  }
-
-  bool CPVRGUIActions::CanEditRecording(const CFileItem& item) const
-  {
-    return CGUIDialogPVRRecordingSettings::CanEditRecording(item);
-  }
-
-  bool CPVRGUIActions::DeleteRecording(const CFileItemPtr& item) const
-  {
-    if ((!item->IsPVRRecording() && !item->m_bIsFolder) || item->IsParentFolder())
-      return false;
-
-    if (!ConfirmDeleteRecording(item))
-      return false;
-
-    if (!AsyncDeleteRecording().Execute(item))
-    {
-      HELPERS::ShowOKDialogText(CVariant{257}, CVariant{19111}); // "Error", "PVR backend error. Check the log for more information about this message."
-      return false;
-    }
-
-    return true;
-  }
-
-  bool CPVRGUIActions::ConfirmDeleteRecording(const CFileItemPtr& item) const
-  {
-    return CGUIDialogYesNo::ShowAndGetInput(CVariant{122}, // "Confirm delete"
-                                            item->m_bIsFolder
-                                              ? CVariant{19113} // "Delete all recordings in this folder?"
-                                              : item->GetPVRRecordingInfoTag()->IsDeleted()
-                                                ? CVariant{19294}  // "Remove this deleted recording from trash? This operation cannot be reverted."
-                                                : CVariant{19112}, // "Delete this recording?"
-                                            CVariant{""},
-                                            CVariant{item->GetLabel()});
-  }
-
-  bool CPVRGUIActions::DeleteWatchedRecordings(const std::shared_ptr<CFileItem>& item) const
-  {
-    if (!item->m_bIsFolder || item->IsParentFolder())
-      return false;
-
-    if (!ConfirmDeleteWatchedRecordings(item))
-      return false;
-
-    if (!AsyncDeleteRecording(true).Execute(item))
-    {
-      HELPERS::ShowOKDialogText(
-          CVariant{257},
-          CVariant{
-              19111}); // "Error", "PVR backend error. Check the log for more information about this message."
-      return false;
-    }
-
-    return true;
-  }
-
-  bool CPVRGUIActions::ConfirmDeleteWatchedRecordings(const std::shared_ptr<CFileItem>& item) const
-  {
-    return CGUIDialogYesNo::ShowAndGetInput(
-        CVariant{122}, // "Confirm delete"
-        CVariant{19328}, // "Delete all watched recordings in this folder?"
-        CVariant{""}, CVariant{item->GetLabel()});
-  }
-
-  bool CPVRGUIActions::DeleteAllRecordingsFromTrash() const
-  {
-    if (!ConfirmDeleteAllRecordingsFromTrash())
-      return false;
-
-    if (!AsyncEmptyRecordingsTrash().Execute(CFileItemPtr()))
-      return false;
-
-    return true;
-  }
-
-  bool CPVRGUIActions::ConfirmDeleteAllRecordingsFromTrash() const
-  {
-    return CGUIDialogYesNo::ShowAndGetInput(CVariant{19292},  // "Delete all permanently"
-                                            CVariant{19293}); // "Remove all deleted recordings from trash? This operation cannot be reverted."
-  }
-
-  bool CPVRGUIActions::UndeleteRecording(const CFileItemPtr& item) const
-  {
-    if (!item->IsDeletedPVRRecording())
-      return false;
-
-    if (!AsyncUndeleteRecording().Execute(item))
-    {
-      HELPERS::ShowOKDialogText(CVariant{257}, CVariant{19111}); // "Error", "PVR backend error. Check the log for more information about this message."
-      return false;
-    }
-
-    return true;
-  }
-
-  bool CPVRGUIActions::ShowRecordingSettings(const std::shared_ptr<CPVRRecording>& recording) const
-  {
-    CGUIDialogPVRRecordingSettings* pDlgInfo = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogPVRRecordingSettings>(WINDOW_DIALOG_PVR_RECORDING_SETTING);
-    if (!pDlgInfo)
-    {
-      CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_PVR_RECORDING_SETTING!");
-      return false;
-    }
-
-    pDlgInfo->SetRecording(recording);
-    pDlgInfo->Open();
-
-    return pDlgInfo->IsConfirmed();
-  }
-
   std::string CPVRGUIActions::GetResumeLabel(const CFileItem& item) const
   {
     std::string resumeString;
@@ -1943,4 +1632,4 @@ namespace PVR
     }
   }
 
-} // namespace PVR
+  } // namespace PVR
diff --git a/xbmc/pvr/guilib/PVRGUIActions.h b/xbmc/pvr/guilib/PVRGUIActions.h
index a8de211662..8f6b18cb87 100644
--- a/xbmc/pvr/guilib/PVRGUIActions.h
+++ b/xbmc/pvr/guilib/PVRGUIActions.h
@@ -9,6 +9,7 @@
 #pragma once
 
 #include "pvr/PVRChannelNumberInputHandler.h"
+#include "pvr/guilib/PVRGUIActionsRecordings.h"
 #include "pvr/guilib/PVRGUIActionsTimers.h"
 #include "pvr/guilib/PVRGUIChannelNavigator.h"
 #include "pvr/settings/PVRSettings.h"
@@ -40,7 +41,6 @@ namespace PVR
 
   class CPVRChannel;
   class CPVRChannelGroupMember;
-  class CPVRRecording;
   class CPVRStreamProperties;
   class CPVRTimerInfoTag;
 
@@ -65,7 +65,7 @@ namespace PVR
     void SwitchToPreviousChannel();
   };
 
-  class CPVRGUIActions : public CPVRGUIActionsTimers
+  class CPVRGUIActions : public CPVRGUIActionsRecordings, public CPVRGUIActionsTimers
   {
   public:
     CPVRGUIActions();
@@ -92,54 +92,6 @@ namespace PVR
      */
     bool FindSimilar(const std::shared_ptr<CFileItem>& item) const;
 
-    /*!
-     * @brief Open a dialog with information for a given recording.
-     * @param item containing a recording.
-     * @return true on success, false otherwise.
-     */
-    bool ShowRecordingInfo(const std::shared_ptr<CFileItem>& item) const;
-
-    /*!
-     * @brief Open the recording settings dialog to edit a recording.
-     * @param item containing the recording to edit.
-     * @return true on success, false otherwise.
-     */
-    bool EditRecording(const std::shared_ptr<CFileItem>& item) const;
-
-    /*!
-     * @brief Check if any recording settings can be edited.
-     * @param item containing the recording to edit.
-     * @return true on success, false otherwise.
-     */
-    bool CanEditRecording(const CFileItem& item) const;
-
-    /*!
-     * @brief Delete a recording, always showing a confirmation dialog.
-     * @param item containing a recording to delete.
-     * @return true, if the recording was deleted successfully, false otherwise.
-     */
-    bool DeleteRecording(const std::shared_ptr<CFileItem>& item) const;
-
-    /*!
-     * @brief Delete all watched recordings contained in the given folder, always showing a confirmation dialog.
-     * @param item containing a recording folder containing the items to delete.
-     * @return true, if the recordings were deleted successfully, false otherwise.
-     */
-    bool DeleteWatchedRecordings(const std::shared_ptr<CFileItem>& item) const;
-
-    /*!
-     * @brief Delete all recordings from trash, always showing a confirmation dialog.
-     * @return true, if the recordings were permanently deleted successfully, false otherwise.
-     */
-    bool DeleteAllRecordingsFromTrash() const;
-
-    /*!
-     * @brief Undelete a recording.
-     * @param item containing a recording to undelete.
-     * @return true, if the recording was undeleted successfully, false otherwise.
-     */
-    bool UndeleteRecording(const std::shared_ptr<CFileItem>& item) const;
-
     /*!
      * @brief Get a localized resume play label, if the given item can be resumed.
      * @param item containing a recording or an epg tag.
@@ -368,33 +320,6 @@ namespace PVR
     CPVRGUIActions(const CPVRGUIActions&) = delete;
     CPVRGUIActions const& operator=(CPVRGUIActions const&) = delete;
 
-    /*!
-     * @brief Open a dialog to confirm to delete a recording.
-     * @param item the recording to delete.
-     * @return true, to proceed with delete, false otherwise.
-     */
-    bool ConfirmDeleteRecording(const std::shared_ptr<CFileItem>& item) const;
-
-    /*!
-     * @brief Open a dialog to confirm delete all watched recordings contained in the given folder.
-     * @param item containing a recording folder containing the items to delete.
-     * @return true, to proceed with delete, false otherwise.
-     */
-    bool ConfirmDeleteWatchedRecordings(const std::shared_ptr<CFileItem>& item) const;
-
-    /*!
-     * @brief Open a dialog to confirm to permanently remove all deleted recordings.
-     * @return true, to proceed with delete, false otherwise.
-     */
-    bool ConfirmDeleteAllRecordingsFromTrash() const;
-
-    /*!
-     * @brief Open the recording settings dialog.
-     * @param recording containing the recording the settings shall be displayed for.
-     * @return true, if the dialog was ended successfully, false otherwise.
-     */
-    bool ShowRecordingSettings(const std::shared_ptr<CPVRRecording>& recording) const;
-
     /*!
      * @brief Check whether resume play is possible for a given item, display "resume from ..."/"play from start" context menu in case.
      * @param item containing a recording or an epg tag.
diff --git a/xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp b/xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp
new file mode 100644
index 0000000000..90d804f8c8
--- /dev/null
+++ b/xbmc/pvr/guilib/PVRGUIActionsRecordings.cpp
@@ -0,0 +1,362 @@
+/*
+ *  Copyright (C) 2016-2018 Team Kodi
+ *  This file is part of Kodi - https://kodi.tv
+ *
+ *  SPDX-License-Identifier: GPL-2.0-or-later
+ *  See LICENSES/README.md for more information.
+ */
+
+#include "PVRGUIActionsRecordings.h"
+
+#include "FileItem.h"
+#include "ServiceBroker.h"
+#include "Util.h"
+#include "dialogs/GUIDialogBusy.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "filesystem/IDirectory.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/WindowIDs.h"
+#include "messaging/helpers/DialogOKHelper.h"
+#include "pvr/PVRItem.h"
+#include "pvr/PVRManager.h"
+#include "pvr/addons/PVRClient.h"
+#include "pvr/addons/PVRClients.h"
+#include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
+#include "pvr/dialogs/GUIDialogPVRRecordingSettings.h"
+#include "pvr/recordings/PVRRecording.h"
+#include "settings/Settings.h"
+#include "threads/IRunnable.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+#include <memory>
+#include <numeric>
+#include <string>
+
+using namespace PVR;
+using namespace KODI::MESSAGING;
+
+namespace
+{
+class AsyncRecordingAction : private IRunnable
+{
+public:
+  bool Execute(const CFileItemPtr& item);
+
+protected:
+  AsyncRecordingAction() = default;
+
+private:
+  // IRunnable implementation
+  void Run() override;
+
+  // the worker function
+  virtual bool DoRun(const CFileItemPtr& item) = 0;
+
+  CFileItemPtr m_item;
+  bool m_bSuccess = false;
+};
+
+bool AsyncRecordingAction::Execute(const CFileItemPtr& item)
+{
+  m_item = item;
+  CGUIDialogBusy::Wait(this, 100, false);
+  return m_bSuccess;
+}
+
+void AsyncRecordingAction::Run()
+{
+  m_bSuccess = DoRun(m_item);
+
+  if (m_bSuccess)
+    CServiceBroker::GetPVRManager().TriggerRecordingsUpdate();
+}
+
+class AsyncRenameRecording : public AsyncRecordingAction
+{
+public:
+  explicit AsyncRenameRecording(const std::string& strNewName) : m_strNewName(strNewName) {}
+
+private:
+  bool DoRun(const std::shared_ptr<CFileItem>& item) override
+  {
+    if (item->IsUsablePVRRecording())
+    {
+      return item->GetPVRRecordingInfoTag()->Rename(m_strNewName);
+    }
+    else
+    {
+      CLog::LogF(LOGERROR, "Cannot rename item '{}': no valid recording tag", item->GetPath());
+      return false;
+    }
+  }
+  std::string m_strNewName;
+};
+
+class AsyncDeleteRecording : public AsyncRecordingAction
+{
+public:
+  explicit AsyncDeleteRecording(bool bWatchedOnly = false) : m_bWatchedOnly(bWatchedOnly) {}
+
+private:
+  bool DoRun(const std::shared_ptr<CFileItem>& item) override
+  {
+    CFileItemList items;
+    if (item->m_bIsFolder)
+    {
+      CUtil::GetRecursiveListing(item->GetPath(), items, "", XFILE::DIR_FLAG_NO_FILE_INFO);
+    }
+    else
+    {
+      items.Add(item);
+    }
+
+    return std::accumulate(
+        items.cbegin(), items.cend(), true, [this](bool success, const auto& itemToDelete) {
+          return (itemToDelete->IsPVRRecording() &&
+                  (!m_bWatchedOnly || itemToDelete->GetPVRRecordingInfoTag()->GetPlayCount() > 0) &&
+                  !itemToDelete->GetPVRRecordingInfoTag()->Delete())
+                     ? false
+                     : success;
+        });
+  }
+  bool m_bWatchedOnly = false;
+};
+
+class AsyncEmptyRecordingsTrash : public AsyncRecordingAction
+{
+private:
+  bool DoRun(const std::shared_ptr<CFileItem>& item) override
+  {
+    return CServiceBroker::GetPVRManager().Clients()->DeleteAllRecordingsFromTrash() ==
+           PVR_ERROR_NO_ERROR;
+  }
+};
+
+class AsyncUndeleteRecording : public AsyncRecordingAction
+{
+private:
+  bool DoRun(const std::shared_ptr<CFileItem>& item) override
+  {
+    if (item->IsDeletedPVRRecording())
+    {
+      return item->GetPVRRecordingInfoTag()->Undelete();
+    }
+    else
+    {
+      CLog::LogF(LOGERROR, "Cannot undelete item '{}': no valid recording tag", item->GetPath());
+      return false;
+    }
+  }
+};
+
+class AsyncSetRecordingPlayCount : public AsyncRecordingAction
+{
+private:
+  bool DoRun(const CFileItemPtr& item) override
+  {
+    const std::shared_ptr<CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(*item);
+    if (client)
+    {
+      const std::shared_ptr<CPVRRecording> recording = item->GetPVRRecordingInfoTag();
+      return client->SetRecordingPlayCount(*recording, recording->GetLocalPlayCount()) ==
+             PVR_ERROR_NO_ERROR;
+    }
+    return false;
+  }
+};
+
+class AsyncSetRecordingLifetime : public AsyncRecordingAction
+{
+private:
+  bool DoRun(const CFileItemPtr& item) override
+  {
+    const std::shared_ptr<CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(*item);
+    if (client)
+      return client->SetRecordingLifetime(*item->GetPVRRecordingInfoTag()) == PVR_ERROR_NO_ERROR;
+    return false;
+  }
+};
+
+} // unnamed namespace
+
+bool CPVRGUIActionsRecordings::ShowRecordingInfo(const CFileItemPtr& item) const
+{
+  if (!item->IsPVRRecording())
+  {
+    CLog::LogF(LOGERROR, "No recording!");
+    return false;
+  }
+
+  CGUIDialogPVRRecordingInfo* pDlgInfo =
+      CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogPVRRecordingInfo>(
+          WINDOW_DIALOG_PVR_RECORDING_INFO);
+  if (!pDlgInfo)
+  {
+    CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_PVR_RECORDING_INFO!");
+    return false;
+  }
+
+  pDlgInfo->SetRecording(item.get());
+  pDlgInfo->Open();
+  return true;
+}
+
+bool CPVRGUIActionsRecordings::EditRecording(const CFileItemPtr& item) const
+{
+  const std::shared_ptr<CPVRRecording> recording = CPVRItem(item).GetRecording();
+  if (!recording)
+  {
+    CLog::LogF(LOGERROR, "No recording!");
+    return false;
+  }
+
+  std::shared_ptr<CPVRRecording> origRecording(new CPVRRecording);
+  origRecording->Update(*recording,
+                        *CServiceBroker::GetPVRManager().GetClient(recording->m_iClientId));
+
+  if (!ShowRecordingSettings(recording))
+    return false;
+
+  if (origRecording->m_strTitle != recording->m_strTitle)
+  {
+    if (!AsyncRenameRecording(recording->m_strTitle).Execute(item))
+      CLog::LogF(LOGERROR, "Renaming recording failed!");
+  }
+
+  if (origRecording->GetLocalPlayCount() != recording->GetLocalPlayCount())
+  {
+    if (!AsyncSetRecordingPlayCount().Execute(item))
+      CLog::LogF(LOGERROR, "Setting recording playcount failed!");
+  }
+
+  if (origRecording->m_iLifetime != recording->m_iLifetime)
+  {
+    if (!AsyncSetRecordingLifetime().Execute(item))
+      CLog::LogF(LOGERROR, "Setting recording lifetime failed!");
+  }
+
+  return true;
+}
+
+bool CPVRGUIActionsRecordings::CanEditRecording(const CFileItem& item) const
+{
+  return CGUIDialogPVRRecordingSettings::CanEditRecording(item);
+}
+
+bool CPVRGUIActionsRecordings::DeleteRecording(const CFileItemPtr& item) const
+{
+  if ((!item->IsPVRRecording() && !item->m_bIsFolder) || item->IsParentFolder())
+    return false;
+
+  if (!ConfirmDeleteRecording(item))
+    return false;
+
+  if (!AsyncDeleteRecording().Execute(item))
+  {
+    HELPERS::ShowOKDialogText(
+        CVariant{257},
+        CVariant{
+            19111}); // "Error", "PVR backend error. Check the log for more information about this message."
+    return false;
+  }
+
+  return true;
+}
+
+bool CPVRGUIActionsRecordings::ConfirmDeleteRecording(const CFileItemPtr& item) const
+{
+  return CGUIDialogYesNo::ShowAndGetInput(
+      CVariant{122}, // "Confirm delete"
+      item->m_bIsFolder
+          ? CVariant{19113} // "Delete all recordings in this folder?"
+          : item->GetPVRRecordingInfoTag()->IsDeleted()
+                ? CVariant{19294}
+                // "Remove this deleted recording from trash? This operation cannot be reverted."
+                : CVariant{19112}, // "Delete this recording?"
+      CVariant{""}, CVariant{item->GetLabel()});
+}
+
+bool CPVRGUIActionsRecordings::DeleteWatchedRecordings(const std::shared_ptr<CFileItem>& item) const
+{
+  if (!item->m_bIsFolder || item->IsParentFolder())
+    return false;
+
+  if (!ConfirmDeleteWatchedRecordings(item))
+    return false;
+
+  if (!AsyncDeleteRecording(true).Execute(item))
+  {
+    HELPERS::ShowOKDialogText(
+        CVariant{257},
+        CVariant{
+            19111}); // "Error", "PVR backend error. Check the log for more information about this message."
+    return false;
+  }
+
+  return true;
+}
+
+bool CPVRGUIActionsRecordings::ConfirmDeleteWatchedRecordings(
+    const std::shared_ptr<CFileItem>& item) const
+{
+  return CGUIDialogYesNo::ShowAndGetInput(
+      CVariant{122}, // "Confirm delete"
+      CVariant{19328}, // "Delete all watched recordings in this folder?"
+      CVariant{""}, CVariant{item->GetLabel()});
+}
+
+bool CPVRGUIActionsRecordings::DeleteAllRecordingsFromTrash() const
+{
+  if (!ConfirmDeleteAllRecordingsFromTrash())
+    return false;
+
+  if (!AsyncEmptyRecordingsTrash().Execute(CFileItemPtr()))
+    return false;
+
+  return true;
+}
+
+bool CPVRGUIActionsRecordings::ConfirmDeleteAllRecordingsFromTrash() const
+{
+  return CGUIDialogYesNo::ShowAndGetInput(
+      CVariant{19292}, // "Delete all permanently"
+      CVariant{
+          19293}); // "Remove all deleted recordings from trash? This operation cannot be reverted."
+}
+
+bool CPVRGUIActionsRecordings::UndeleteRecording(const CFileItemPtr& item) const
+{
+  if (!item->IsDeletedPVRRecording())
+    return false;
+
+  if (!AsyncUndeleteRecording().Execute(item))
+  {
+    HELPERS::ShowOKDialogText(
+        CVariant{257},
+        CVariant{
+            19111}); // "Error", "PVR backend error. Check the log for more information about this message."
+    return false;
+  }
+
+  return true;
+}
+
+bool CPVRGUIActionsRecordings::ShowRecordingSettings(
+    const std::shared_ptr<CPVRRecording>& recording) const
+{
+  CGUIDialogPVRRecordingSettings* pDlgInfo =
+      CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogPVRRecordingSettings>(
+          WINDOW_DIALOG_PVR_RECORDING_SETTING);
+  if (!pDlgInfo)
+  {
+    CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_PVR_RECORDING_SETTING!");
+    return false;
+  }
+
+  pDlgInfo->SetRecording(recording);
+  pDlgInfo->Open();
+
+  return pDlgInfo->IsConfirmed();
+}
diff --git a/xbmc/pvr/guilib/PVRGUIActionsRecordings.h b/xbmc/pvr/guilib/PVRGUIActionsRecordings.h
new file mode 100644
index 0000000000..ad76c2b6e2
--- /dev/null
+++ b/xbmc/pvr/guilib/PVRGUIActionsRecordings.h
@@ -0,0 +1,106 @@
+/*
+ *  Copyright (C) 2016-2018 Team Kodi
+ *  This file is part of Kodi - https://kodi.tv
+ *
+ *  SPDX-License-Identifier: GPL-2.0-or-later
+ *  See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include <memory>
+
+class CFileItem;
+
+namespace PVR
+{
+class CPVRRecording;
+
+class CPVRGUIActionsRecordings
+{
+public:
+  CPVRGUIActionsRecordings() = default;
+  virtual ~CPVRGUIActionsRecordings() = default;
+
+  /*!
+   * @brief Open a dialog with information for a given recording.
+   * @param item containing a recording.
+   * @return true on success, false otherwise.
+   */
+  bool ShowRecordingInfo(const std::shared_ptr<CFileItem>& item) const;
+
+  /*!
+   * @brief Open the recording settings dialog to edit a recording.
+   * @param item containing the recording to edit.
+   * @return true on success, false otherwise.
+   */
+  bool EditRecording(const std::shared_ptr<CFileItem>& item) const;
+
+  /*!
+   * @brief Check if any recording settings can be edited.
+   * @param item containing the recording to edit.
+   * @return true on success, false otherwise.
+   */
+  bool CanEditRecording(const CFileItem& item) const;
+
+  /*!
+   * @brief Delete a recording, always showing a confirmation dialog.
+   * @param item containing a recording to delete.
+   * @return true, if the recording was deleted successfully, false otherwise.
+   */
+  bool DeleteRecording(const std::shared_ptr<CFileItem>& item) const;
+
+  /*!
+   * @brief Delete all watched recordings contained in the given folder, always showing a
+   * confirmation dialog.
+   * @param item containing a recording folder containing the items to delete.
+   * @return true, if the recordings were deleted successfully, false otherwise.
+   */
+  bool DeleteWatchedRecordings(const std::shared_ptr<CFileItem>& item) const;
+
+  /*!
+   * @brief Delete all recordings from trash, always showing a confirmation dialog.
+   * @return true, if the recordings were permanently deleted successfully, false otherwise.
+   */
+  bool DeleteAllRecordingsFromTrash() const;
+
+  /*!
+   * @brief Undelete a recording.
+   * @param item containing a recording to undelete.
+   * @return true, if the recording was undeleted successfully, false otherwise.
+   */
+  bool UndeleteRecording(const std::shared_ptr<CFileItem>& item) const;
+
+private:
+  CPVRGUIActionsRecordings(const CPVRGUIActionsRecordings&) = delete;
+  CPVRGUIActionsRecordings const& operator=(CPVRGUIActionsRecordings const&) = delete;
+
+  /*!
+   * @brief Open a dialog to confirm to delete a recording.
+   * @param item the recording to delete.
+   * @return true, to proceed with delete, false otherwise.
+   */
+  bool ConfirmDeleteRecording(const std::shared_ptr<CFileItem>& item) const;
+
+  /*!
+   * @brief Open a dialog to confirm delete all watched recordings contained in the given folder.
+   * @param item containing a recording folder containing the items to delete.
+   * @return true, to proceed with delete, false otherwise.
+   */
+  bool ConfirmDeleteWatchedRecordings(const std::shared_ptr<CFileItem>& item) const;
+
+  /*!
+   * @brief Open a dialog to confirm to permanently remove all deleted recordings.
+     * @return true, to proceed with delete, false otherwise.
+   */
+  bool ConfirmDeleteAllRecordingsFromTrash() const;
+
+  /*!
+   * @brief Open the recording settings dialog.
+   * @param recording containing the recording the settings shall be displayed for.
+   * @return true, if the dialog was ended successfully, false otherwise.
+   */
+  bool ShowRecordingSettings(const std::shared_ptr<CPVRRecording>& recording) const;
+};
+
+} // namespace PVR
-- 
cgit v1.2.3