bool CFileItem::IsPVRRecording() const
{
- if (HasPVRRecordingInfoTag()) return true; /// is this enough?
+ if (HasPVRRecordingInfoTag())
+ return true;
+ return false;
+}
+
+bool CFileItem::IsUsablePVRRecording() const
+{
+ if (m_pvrRecordingInfoTag && !m_pvrRecordingInfoTag->IsDeleted())
+ return true;
+ return false;
+}
+
+bool CFileItem::IsDeletedPVRRecording() const
+{
+ if (m_pvrRecordingInfoTag && m_pvrRecordingInfoTag->IsDeleted())
+ return true;
return false;
}
{ // archive
SetIconImage("DefaultFile.png");
}
- else if ( IsPVRRecording() )
+ else if ( IsUsablePVRRecording() )
{
// PVR recording
SetIconImage("DefaultVideo.png");
}
+ else if ( IsDeletedPVRRecording() )
+ {
+ // PVR deleted recording
+ SetIconImage("DefaultVideoDeleted.png");
+ }
else if ( IsAudio() )
{
// audio
bool IsEPG() const;
bool IsPVRChannel() const;
bool IsPVRRecording() const;
+ bool IsUsablePVRRecording() const;
+ bool IsDeletedPVRRecording() const;
bool IsPVRTimer() const;
bool IsType(const char *ext) const;
bool IsVirtualDirectoryRoot() const;
{ "backendchannels", PVR_BACKEND_CHANNELS },
{ "backendtimers", PVR_BACKEND_TIMERS },
{ "backendrecordings", PVR_BACKEND_RECORDINGS },
+ { "backenddeletedrecordings", PVR_BACKEND_DELETED_RECORDINGS },
{ "backendnumber", PVR_BACKEND_NUMBER },
{ "hasepg", PVR_HAS_EPG },
{ "hastxt", PVR_HAS_TXT },
case PVR_BACKEND_CHANNELS:
case PVR_BACKEND_TIMERS:
case PVR_BACKEND_RECORDINGS:
+ case PVR_BACKEND_DELETED_RECORDINGS:
case PVR_BACKEND_NUMBER:
case PVR_TOTAL_DISKSPACE:
case PVR_NEXT_TIMER:
#define PVR_BACKEND_CHANNELS (PVR_STRINGS_START + 12)
#define PVR_BACKEND_TIMERS (PVR_STRINGS_START + 13)
#define PVR_BACKEND_RECORDINGS (PVR_STRINGS_START + 14)
-#define PVR_BACKEND_NUMBER (PVR_STRINGS_START + 15)
-#define PVR_TOTAL_DISKSPACE (PVR_STRINGS_START + 16)
-#define PVR_NEXT_TIMER (PVR_STRINGS_START + 17)
-#define PVR_PLAYING_DURATION (PVR_STRINGS_START + 18)
-#define PVR_PLAYING_TIME (PVR_STRINGS_START + 19)
-#define PVR_PLAYING_PROGRESS (PVR_STRINGS_START + 20)
-#define PVR_ACTUAL_STREAM_CLIENT (PVR_STRINGS_START + 21)
-#define PVR_ACTUAL_STREAM_DEVICE (PVR_STRINGS_START + 22)
-#define PVR_ACTUAL_STREAM_STATUS (PVR_STRINGS_START + 23)
-#define PVR_ACTUAL_STREAM_SIG (PVR_STRINGS_START + 24)
-#define PVR_ACTUAL_STREAM_SNR (PVR_STRINGS_START + 25)
-#define PVR_ACTUAL_STREAM_SIG_PROGR (PVR_STRINGS_START + 26)
-#define PVR_ACTUAL_STREAM_SNR_PROGR (PVR_STRINGS_START + 27)
-#define PVR_ACTUAL_STREAM_BER (PVR_STRINGS_START + 28)
-#define PVR_ACTUAL_STREAM_UNC (PVR_STRINGS_START + 29)
-#define PVR_ACTUAL_STREAM_VIDEO_BR (PVR_STRINGS_START + 30)
-#define PVR_ACTUAL_STREAM_AUDIO_BR (PVR_STRINGS_START + 31)
-#define PVR_ACTUAL_STREAM_DOLBY_BR (PVR_STRINGS_START + 32)
-#define PVR_ACTUAL_STREAM_CRYPTION (PVR_STRINGS_START + 33)
-#define PVR_ACTUAL_STREAM_SERVICE (PVR_STRINGS_START + 34)
-#define PVR_ACTUAL_STREAM_MUX (PVR_STRINGS_START + 35)
-#define PVR_ACTUAL_STREAM_PROVIDER (PVR_STRINGS_START + 36)
-#define PVR_BACKEND_DISKSPACE_PROGR (PVR_STRINGS_START + 37)
+#define PVR_BACKEND_DELETED_RECORDINGS (PVR_STRINGS_START + 15)
+#define PVR_BACKEND_NUMBER (PVR_STRINGS_START + 16)
+#define PVR_TOTAL_DISKSPACE (PVR_STRINGS_START + 17)
+#define PVR_NEXT_TIMER (PVR_STRINGS_START + 18)
+#define PVR_PLAYING_DURATION (PVR_STRINGS_START + 19)
+#define PVR_PLAYING_TIME (PVR_STRINGS_START + 20)
+#define PVR_PLAYING_PROGRESS (PVR_STRINGS_START + 21)
+#define PVR_ACTUAL_STREAM_CLIENT (PVR_STRINGS_START + 22)
+#define PVR_ACTUAL_STREAM_DEVICE (PVR_STRINGS_START + 23)
+#define PVR_ACTUAL_STREAM_STATUS (PVR_STRINGS_START + 24)
+#define PVR_ACTUAL_STREAM_SIG (PVR_STRINGS_START + 25)
+#define PVR_ACTUAL_STREAM_SNR (PVR_STRINGS_START + 26)
+#define PVR_ACTUAL_STREAM_SIG_PROGR (PVR_STRINGS_START + 27)
+#define PVR_ACTUAL_STREAM_SNR_PROGR (PVR_STRINGS_START + 28)
+#define PVR_ACTUAL_STREAM_BER (PVR_STRINGS_START + 29)
+#define PVR_ACTUAL_STREAM_UNC (PVR_STRINGS_START + 30)
+#define PVR_ACTUAL_STREAM_VIDEO_BR (PVR_STRINGS_START + 31)
+#define PVR_ACTUAL_STREAM_AUDIO_BR (PVR_STRINGS_START + 32)
+#define PVR_ACTUAL_STREAM_DOLBY_BR (PVR_STRINGS_START + 33)
+#define PVR_ACTUAL_STREAM_CRYPTION (PVR_STRINGS_START + 34)
+#define PVR_ACTUAL_STREAM_SERVICE (PVR_STRINGS_START + 35)
+#define PVR_ACTUAL_STREAM_MUX (PVR_STRINGS_START + 36)
+#define PVR_ACTUAL_STREAM_PROVIDER (PVR_STRINGS_START + 37)
+#define PVR_BACKEND_DISKSPACE_PROGR (PVR_STRINGS_START + 38)
#define PVR_STRINGS_END PVR_ACTUAL_STREAM_PROVIDER
#define WINDOW_PROPERTY 9993
CONTEXT_BUTTON_MOVIESET_ADD_REMOVE_ITEMS,
CONTEXT_BUTTON_BROWSE_INTO,
CONTEXT_BUTTON_EDIT_SORTTITLE,
+ CONTEXT_BUTTON_UNDELETE,
+ CONTEXT_BUTTON_DELETE_ALL,
CONTEXT_BUTTON_USER1,
CONTEXT_BUTTON_USER2,
CONTEXT_BUTTON_USER3,
// add the recordings dir as needed
if (CPVRDirectory::HasRecordings())
{
- share1.strPath = "pvr://recordings/";
+ share1.strPath = "pvr://recordings/active/";
share1.strName = g_localizeStrings.Get(19017); // TV Recordings
extraShares.push_back(share1);
}
+ if (CPVRDirectory::HasDeletedRecordings())
+ {
+ share1.strPath = "pvr://recordings/deleted/";
+ share1.strName = g_localizeStrings.Get(19108); // Deleted TV Recordings
+ extraShares.push_back(share1);
+ }
}
else if (m_type == "pictures")
{
item->SetLabelPreformated(true);
items.Add(item);
- item.reset(new CFileItem(base + "recordings/", true));
- item->SetLabel(g_localizeStrings.Get(19017));
+ item.reset(new CFileItem(base + "recordings/active/", true));
+ item->SetLabel(g_localizeStrings.Get(19017)); // TV Recordings
+ item->SetLabelPreformated(true);
+ items.Add(item);
+
+ item.reset(new CFileItem(base + "recordings/deleted/", true));
+ item->SetLabel(g_localizeStrings.Get(19108)); // Deleted TV Recordings
item->SetLabelPreformated(true);
items.Add(item);
return g_PVRManager.IsStarted() ?
g_PVRRecordings->GetNumRecordings() > 0 : false;
}
+
+bool CPVRDirectory::HasDeletedRecordings()
+{
+ return g_PVRManager.IsStarted() ?
+ g_PVRRecordings->HasDeletedRecordings() : false;
+}
static bool SupportsWriteFileOperations(const std::string& strPath);
static bool IsLiveTV(const std::string& strPath);
static bool HasRecordings();
+ static bool HasDeletedRecordings();
virtual bool Exists(const CURL& url);
return false;
}
}
- else if (StringUtils::StartsWith(strURL, "pvr://recordings/"))
+ else if (StringUtils::StartsWith(strURL, "pvr://recordings/active"))
{
CFileItemPtr tag = g_PVRRecordings->GetByPath(strURL);
if (tag && tag->HasPVRRecordingInfoTag())
return false;
}
}
+ else if (StringUtils::StartsWith(strURL, "pvr://recordings/deleted/"))
+ {
+ CLog::Log(LOGNOTICE, "PVRFile - Playback of deleted recordings is not possible (%s)", strURL.c_str());
+ return false;
+ }
else
{
CLog::Log(LOGERROR, "%s - invalid path specified %s", __FUNCTION__, strURL.c_str());
if (found != std::string::npos)
newname = newname.substr(found+1);
- if (StringUtils::StartsWith(path, "recordings/") && path[path.size()-1] != '/')
+ if (StringUtils::StartsWith(path, "recordings/active/") && path[path.size()-1] != '/')
{
std::string strURL = url.Get();
CFileItemPtr tag = g_PVRRecordings->GetByPath(strURL);
m_strBackendHost .clear();
m_strBackendTimers .clear();
m_strBackendRecordings .clear();
+ m_strBackendDeletedRecordings .clear();
m_strBackendChannels .clear();
m_iBackendUsedDiskspace = 0;
m_iBackendTotalDiskspace = 0;
case PVR_BACKEND_RECORDINGS:
CharInfoBackendRecordings(strValue);
break;
+ case PVR_BACKEND_DELETED_RECORDINGS:
+ CharInfoBackendDeletedRecordings(strValue);
+ break;
case PVR_BACKEND_NUMBER:
CharInfoBackendNumber(strValue);
break;
strValue = m_strBackendRecordings;
}
+void CPVRGUIInfo::CharInfoBackendDeletedRecordings(std::string &strValue) const
+{
+ if (m_strBackendDeletedRecordings.empty())
+ strValue = g_localizeStrings.Get(13205); /* Unknown */
+ else
+ strValue = m_strBackendDeletedRecordings;
+}
+
void CPVRGUIInfo::CharInfoPlayingClientName(std::string &strValue) const
{
if (m_strPlayingClientName.empty())
std::string strBackendHost;
std::string strBackendTimers;
std::string strBackendRecordings;
+ std::string strBackendDeletedRecordings;
std::string strBackendChannels;
long long iBackendkBUsed(0);
long long iBackendkBTotal(0);
else
strBackendTimers = g_localizeStrings.Get(161);
- int NumRecordings = activeClient->second->GetRecordingsAmount();
+ int NumRecordings = activeClient->second->GetRecordingsAmount(false);
if (NumRecordings >= 0)
strBackendRecordings = StringUtils::Format("%i", NumRecordings);
else
strBackendRecordings = g_localizeStrings.Get(161);
+ int NumDeletedRecordings = activeClient->second->GetRecordingsAmount(true);
+ if (NumDeletedRecordings >= 0)
+ strBackendDeletedRecordings = StringUtils::Format("%i", NumDeletedRecordings);
+ else
+ strBackendDeletedRecordings = g_localizeStrings.Get(161); /* Unavailable */
+
strBackendName = activeClient->second->GetBackendName();
strBackendVersion = activeClient->second->GetBackendVersion();
strBackendHost = activeClient->second->GetConnectionString();
}
CSingleLock lock(m_critSection);
- m_strBackendName = strBackendName;
- m_strBackendVersion = strBackendVersion;
- m_strBackendHost = strBackendHost;
- m_strBackendTimers = strBackendTimers;
- m_strBackendRecordings = strBackendRecordings;
- m_strBackendChannels = strBackendChannels;
- m_iActiveClients = iActiveClients;
- m_iBackendUsedDiskspace = iBackendkBUsed;
- m_iBackendTotalDiskspace = iBackendkBTotal;
+ m_strBackendName = strBackendName;
+ m_strBackendVersion = strBackendVersion;
+ m_strBackendHost = strBackendHost;
+ m_strBackendTimers = strBackendTimers;
+ m_strBackendRecordings = strBackendRecordings;
+ m_strBackendDeletedRecordings = strBackendDeletedRecordings;
+ m_strBackendChannels = strBackendChannels;
+ m_iActiveClients = iActiveClients;
+ m_iBackendUsedDiskspace = iBackendkBUsed;
+ m_iBackendTotalDiskspace = iBackendkBTotal;
}
void CPVRGUIInfo::UpdateTimersCache(void)
void CharInfoBackendChannels(std::string &strValue) const;
void CharInfoBackendTimers(std::string &strValue) const;
void CharInfoBackendRecordings(std::string &strValue) const;
+ void CharInfoBackendDeletedRecordings(std::string &strValue) const;
void CharInfoPlayingClientName(std::string &strValue) const;
void CharInfoEncryption(std::string &strValue) const;
void CharInfoService(std::string &strValue) const;
std::string m_strBackendHost;
std::string m_strBackendTimers;
std::string m_strBackendRecordings;
+ std::string m_strBackendDeletedRecordings;
std::string m_strBackendChannels;
long long m_iBackendUsedDiskspace;
long long m_iBackendTotalDiskspace;
addonRecording.iLifetime = xbmcRecording.m_iLifetime;
addonRecording.iPlayCount = xbmcRecording.m_playCount;
addonRecording.iLastPlayedPosition = (int)xbmcRecording.m_resumePoint.timeInSeconds;
+ addonRecording.bIsDeleted = xbmcRecording.IsDeleted();
strncpy(addonRecording.strDirectory, xbmcRecording.m_strDirectory.c_str(), sizeof(addonRecording.strDirectory) - 1);
strncpy(addonRecording.strStreamURL, xbmcRecording.m_strStreamURL.c_str(), sizeof(addonRecording.strStreamURL) - 1);
strncpy(addonRecording.strIconPath, xbmcRecording.m_strIconPath.c_str(), sizeof(addonRecording.strIconPath) - 1);
addonTimer.iClientIndex = xbmcTimer.m_iClientIndex;
addonTimer.state = xbmcTimer.m_state;
+ addonTimer.iClientIndex = xbmcTimer.m_iClientIndex;
addonTimer.iClientChannelUid = xbmcTimer.m_iClientChannelUid;
strncpy(addonTimer.strTitle, xbmcTimer.m_strTitle.c_str(), sizeof(addonTimer.strTitle) - 1);
strncpy(addonTimer.strDirectory, xbmcTimer.m_strDirectory.c_str(), sizeof(addonTimer.strDirectory) - 1);
hookData.cat = PVR_MENUHOOK_CHANNEL;
WriteClientChannelInfo(*item->GetPVRChannelInfoTag(), hookData.data.channel);
}
- else if (item->IsPVRRecording())
+ else if (item->IsUsablePVRRecording())
{
hookData.cat = PVR_MENUHOOK_RECORDING;
WriteClientRecordingInfo(*item->GetPVRRecordingInfoTag(), hookData.data.recording);
}
+ else if (item->IsDeletedPVRRecording())
+ {
+ hookData.cat = PVR_MENUHOOK_DELETED_RECORDING;
+ WriteClientRecordingInfo(*item->GetPVRRecordingInfoTag(), hookData.data.recording);
+ }
else if (item->IsPVRTimer())
{
hookData.cat = PVR_MENUHOOK_TIMER;
return retVal;
}
-int CPVRClient::GetRecordingsAmount(void)
+int CPVRClient::GetRecordingsAmount(bool deleted)
{
int iReturn(-EINVAL);
- if (m_addonCapabilities.bSupportsRecordings)
+ if (!m_addonCapabilities.bSupportsRecordings || (deleted && !m_addonCapabilities.bSupportsRecordingsUndelete))
+ return iReturn;
+
+ try
{
- try { iReturn = m_pStruct->GetRecordingsAmount(); }
- catch (std::exception &e) { LogException(e, __FUNCTION__); }
+ iReturn = m_pStruct->GetRecordingsAmount(deleted);
+ }
+ catch (std::exception &e)
+ {
+ LogException(e, __FUNCTION__);
}
return iReturn;
}
-PVR_ERROR CPVRClient::GetRecordings(CPVRRecordings *results)
+PVR_ERROR CPVRClient::GetRecordings(CPVRRecordings *results, bool deleted)
{
if (!m_bReadyToUse)
return PVR_ERROR_REJECTED;
- if (!m_addonCapabilities.bSupportsRecordings)
+ if (!m_addonCapabilities.bSupportsRecordings || (deleted && !m_addonCapabilities.bSupportsRecordingsUndelete))
return PVR_ERROR_NOT_IMPLEMENTED;
PVR_ERROR retVal(PVR_ERROR_UNKNOWN);
ADDON_HANDLE_STRUCT handle;
handle.callerAddress = this;
handle.dataAddress = (CPVRRecordings*) results;
- retVal = m_pStruct->GetRecordings(&handle);
+ retVal = m_pStruct->GetRecordings(&handle, deleted);
LogError(retVal, __FUNCTION__);
}
return retVal;
}
+PVR_ERROR CPVRClient::UndeleteRecording(const CPVRRecording &recording)
+{
+ if (!m_bReadyToUse)
+ return PVR_ERROR_REJECTED;
+
+ if (!m_addonCapabilities.bSupportsRecordingsUndelete)
+ return PVR_ERROR_NOT_IMPLEMENTED;
+
+ PVR_ERROR retVal(PVR_ERROR_UNKNOWN);
+ try
+ {
+ PVR_RECORDING tag;
+ WriteClientRecordingInfo(recording, tag);
+
+ retVal = m_pStruct->UndeleteRecording(tag);
+
+ LogError(retVal, __FUNCTION__);
+ }
+ catch (std::exception &e)
+ {
+ LogException(e, __FUNCTION__);
+ }
+
+ return retVal;
+}
+
+PVR_ERROR CPVRClient::DeleteAllRecordingsFromTrash()
+{
+ if (!m_bReadyToUse)
+ return PVR_ERROR_REJECTED;
+
+ if (!m_addonCapabilities.bSupportsRecordingsUndelete)
+ return PVR_ERROR_NOT_IMPLEMENTED;
+
+ PVR_ERROR retVal(PVR_ERROR_UNKNOWN);
+ try
+ {
+ retVal = m_pStruct->DeleteAllRecordingsFromTrash();
+
+ LogError(retVal, __FUNCTION__);
+ }
+ catch (std::exception &e)
+ {
+ LogException(e, __FUNCTION__);
+ }
+
+ return retVal;
+}
+
PVR_ERROR CPVRClient::RenameRecording(const CPVRRecording &recording)
{
if (!m_bReadyToUse)
return m_addonCapabilities.bSupportsRecordings;
}
+bool CPVRClient::SupportsRecordingsUndelete(void) const
+{
+ return m_addonCapabilities.bSupportsRecordingsUndelete;
+}
+
bool CPVRClient::SupportsRecordingFolders(void) const
{
return m_addonCapabilities.bSupportsRecordingFolders;
//@{
/*!
- * @return The total amount of channels on the server or -1 on error.
+ * @param deleted if set return deleted recording
+ * @return The total amount of recordingd on the server or -1 on error.
*/
- int GetRecordingsAmount(void);
+ int GetRecordingsAmount(bool deleted);
/*!
* @brief Request the list of all recordings from the backend.
* @param results The container to add the recordings to.
+ * @param deleted if set return deleted recording
* @return PVR_ERROR_NO_ERROR if the list has been fetched successfully.
*/
- PVR_ERROR GetRecordings(CPVRRecordings *results);
+ PVR_ERROR GetRecordings(CPVRRecordings *results, bool deleted);
/*!
* @brief Delete a recording on the backend.
PVR_ERROR DeleteRecording(const CPVRRecording &recording);
/*!
+ * @brief Undelete a recording on the backend.
+ * @param recording The recording to undelete.
+ * @return PVR_ERROR_NO_ERROR if the recording has been undeleted successfully.
+ */
+ PVR_ERROR UndeleteRecording(const CPVRRecording &recording);
+
+ /*!
+ * @brief Delete all recordings permanent which in the deleted folder on the backend.
+ * @return PVR_ERROR_NO_ERROR if the recordings has been deleted successfully.
+ */
+ PVR_ERROR DeleteAllRecordingsFromTrash();
+
+ /*!
* @brief Rename a recording on the backend.
* @param recording The recording to rename.
* @return PVR_ERROR_NO_ERROR if the recording has been renamed successfully.
bool SupportsLastPlayedPosition(void) const;
bool SupportsRadio(void) const;
bool SupportsRecordings(void) const;
+ bool SupportsRecordingsUndelete(void) const;
bool SupportsRecordingFolders(void) const;
bool SupportsRecordingPlayCount(void) const;
bool SupportsRecordingEdl(void) const;
return error;
}
-PVR_ERROR CPVRClients::GetRecordings(CPVRRecordings *recordings)
+PVR_ERROR CPVRClients::GetRecordings(CPVRRecordings *recordings, bool deleted)
{
PVR_ERROR error(PVR_ERROR_NO_ERROR);
PVR_CLIENTMAP clients;
for (PVR_CLIENTMAP_CITR itrClients = clients.begin(); itrClients != clients.end(); itrClients++)
{
- PVR_ERROR currentError = (*itrClients).second->GetRecordings(recordings);
+ PVR_ERROR currentError = (*itrClients).second->GetRecordings(recordings, deleted);
if (currentError != PVR_ERROR_NOT_IMPLEMENTED &&
currentError != PVR_ERROR_NO_ERROR)
{
return error;
}
+PVR_ERROR CPVRClients::UndeleteRecording(const CPVRRecording &recording)
+{
+ PVR_ERROR error(PVR_ERROR_UNKNOWN);
+
+ if (!recording.IsDeleted())
+ return error;
+
+ PVR_CLIENT client;
+ if (GetConnectedClient(recording.m_iClientId, client))
+ error = client->UndeleteRecording(recording);
+
+ if (error != PVR_ERROR_NO_ERROR)
+ CLog::Log(LOGERROR, "PVR - %s - cannot undelete recording from client '%d': %s",__FUNCTION__, recording.m_iClientId, CPVRClient::ToString(error));
+
+ return error;
+}
+
+PVR_ERROR CPVRClients::DeleteAllRecordingsFromTrash()
+{
+ PVR_ERROR error(PVR_ERROR_NO_ERROR);
+ PVR_CLIENTMAP clients;
+ GetConnectedClients(clients);
+
+ std::vector<PVR_CLIENT> suppClients;
+ for (PVR_CLIENTMAP_CITR itrClients = clients.begin(); itrClients != clients.end(); ++itrClients)
+ {
+ if (itrClients->second->SupportsRecordingsUndelete() && itrClients->second->GetRecordingsAmount(true) > 0)
+ suppClients.push_back(itrClients->second);
+ }
+
+ int selection = 0;
+ if (suppClients.size() > 1)
+ {
+ // have user select client
+ CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
+ pDialog->Reset();
+ pDialog->SetHeading(19292); /* Delete all permanently */
+ pDialog->Add(g_localizeStrings.Get(24032)); /* All Add-ons */
+
+ PVR_CLIENTMAP_CITR itrClients;
+ for (itrClients = clients.begin(); itrClients != clients.end(); ++itrClients)
+ {
+ if (itrClients->second->SupportsRecordingsUndelete() && itrClients->second->GetRecordingsAmount(true) > 0)
+ pDialog->Add(itrClients->second->GetBackendName());
+ }
+ pDialog->DoModal();
+ selection = pDialog->GetSelectedLabel();
+ }
+
+ if (selection == 0)
+ {
+ typedef std::vector<PVR_CLIENT>::const_iterator suppClientsCITR;
+ for (suppClientsCITR itrSuppClients = suppClients.begin(); itrSuppClients != suppClients.end(); ++itrSuppClients)
+ {
+ PVR_ERROR currentError = (*itrSuppClients)->DeleteAllRecordingsFromTrash();
+ if (currentError != PVR_ERROR_NO_ERROR)
+ {
+ CLog::Log(LOGERROR, "PVR - %s - cannot delete all recordings from client '%d': %s",__FUNCTION__, (*itrSuppClients)->GetID(), CPVRClient::ToString(currentError));
+ error = currentError;
+ }
+ }
+ }
+ else if (selection >= 1 && selection <= (int)suppClients.size())
+ {
+ PVR_ERROR currentError = suppClients[selection-1]->DeleteAllRecordingsFromTrash();
+ if (currentError != PVR_ERROR_NO_ERROR)
+ {
+ CLog::Log(LOGERROR, "PVR - %s - cannot delete all recordings from client '%d': %s",__FUNCTION__, suppClients[selection-1]->GetID(), CPVRClient::ToString(currentError));
+ error = currentError;
+ }
+ }
+
+ return error;
+}
+
bool CPVRClients::SetRecordingLastPlayedPosition(const CPVRRecording &recording, int lastplayedposition, PVR_ERROR *error)
{
*error = PVR_ERROR_UNKNOWN;
return GetConnectedClient(iClientId, client) && client->SupportsRecordings();
}
+bool CPVRClients::SupportsRecordingsUndelete(int iClientId) const
+{
+ PVR_CLIENT client;
+ return GetConnectedClient(iClientId, client) && client->SupportsRecordingsUndelete();
+}
+
bool CPVRClients::SupportsRecordingFolders(int iClientId) const
{
PVR_CLIENT client;
bool SupportsRecordings(int iClientId) const;
/*!
+ * @brief Check whether a client supports undelete of recordings.
+ * @param iClientId The id of the client to check.
+ * @return True if the supports undeleted of recordings, false otherwise.
+ */
+ bool SupportsRecordingsUndelete(int iClientId) const;
+
+ /*!
* @brief Get all recordings from clients
* @param recordings Store the recordings in this container.
+ * @param deleted Return deleted recordings
* @return The amount of recordings that were added.
*/
- PVR_ERROR GetRecordings(CPVRRecordings *recordings);
+ PVR_ERROR GetRecordings(CPVRRecordings *recordings, bool deleted);
/*!
* @brief Rename a recordings on the backend.
PVR_ERROR DeleteRecording(const CPVRRecording &recording);
/*!
+ * @brief Undelete a recording from the backend.
+ * @param recording The recording to undelete.
+ * @param error An error if it occured.
+ * @return True if the recording was undeleted successfully, false otherwise.
+ */
+ PVR_ERROR UndeleteRecording(const CPVRRecording &recording);
+
+ /*!
+ * @brief Delete all recordings permanent which in the deleted folder on the backend.
+ * @return PVR_ERROR_NO_ERROR if the recordings has been deleted successfully.
+ */
+ PVR_ERROR DeleteAllRecordingsFromTrash();
+
+ /*!
* @brief Set play count of a recording on the backend.
* @param recording The recording to set the play count.
* @param count Play count.
m_strIconPath = recording.strIconPath;
m_strThumbnailPath = recording.strThumbnailPath;
m_strFanartPath = recording.strFanartPath;
+ m_bIsDeleted = recording.bIsDeleted;
}
bool CPVRRecording::operator ==(const CPVRRecording& right) const
m_strIconPath == right.m_strIconPath &&
m_strThumbnailPath == right.m_strThumbnailPath &&
m_strFanartPath == right.m_strFanartPath &&
- m_iRecordingId == right.m_iRecordingId);
+ m_iRecordingId == right.m_iRecordingId &&
+ m_bIsDeleted == right.m_bIsDeleted);
}
bool CPVRRecording::operator !=(const CPVRRecording& right) const
value["starttime"] = m_recordingTime.IsValid() ? m_recordingTime.GetAsDBDateTime() : "";
value["endtime"] = m_recordingTime.IsValid() ? (m_recordingTime + m_duration).GetAsDBDateTime() : "";
value["recordingid"] = m_iRecordingId;
+ value["deleted"] = m_bIsDeleted;
if (!value.isMember("art"))
value["art"] = CVariant(CVariant::VariantTypeObject);
m_strFanartPath .clear();
m_bGotMetaData = false;
m_iRecordingId = 0;
+ m_bIsDeleted = false;
m_recordingTime.Reset();
CVideoInfoTag::Reset();
return true;
}
+bool CPVRRecording::Undelete(void)
+{
+ PVR_ERROR error = g_PVRClients->UndeleteRecording(*this);
+ if (error != PVR_ERROR_NO_ERROR)
+ {
+ DisplayError(error);
+ return false;
+ }
+
+ return true;
+}
+
bool CPVRRecording::Rename(const std::string &strNewName)
{
m_strTitle = StringUtils::Format("%s", strNewName.c_str());
m_strIconPath = tag.m_strIconPath;
m_strThumbnailPath = tag.m_strThumbnailPath;
m_strFanartPath = tag.m_strFanartPath;
+ m_bIsDeleted = tag.m_bIsDeleted;
if (g_PVRClients->SupportsRecordingPlayCount(m_iClientId))
m_playCount = tag.m_playCount;
strDirectory = StringUtils::Format("%s/", m_strDirectory.c_str());
if (!m_strChannelName.empty())
strChannel = StringUtils::Format(" (%s)", m_strChannelName.c_str());
- m_strFileNameAndPath = StringUtils::Format("pvr://recordings/%s%s, TV%s, %s.pvr", strDirectory.c_str(), strTitle.c_str(), strChannel.c_str(), strDatetime.c_str());
+ m_strFileNameAndPath = StringUtils::Format("pvr://recordings/%s/%s%s, TV%s, %s.pvr", (m_bIsDeleted ? "deleted" : "active"), strDirectory.c_str(), strTitle.c_str(), strChannel.c_str(), strDatetime.c_str());
}
}
bool Delete(void);
/*!
+ * @brief Undelete this recording on the client (if supported).
+ * @return True if it was undeleted successfully, false otherwise.
+ */
+ bool Undelete(void);
+
+ /*!
* @brief Rename this recording on the client (if supported).
* @param strNewName The new name.
* @return True if it was renamed successfully, false otherwise.
*/
void CopyClientInfo(CVideoInfoTag *target) const;
+ /*!
+ * @brief If deleted but can be undeleted it is true
+ */
+ bool IsDeleted() const { return m_bIsDeleted; }
+
private:
CDateTime m_recordingTime; /*!< start time of the recording */
bool m_bGotMetaData;
+ bool m_bIsDeleted; /*!< set if entry is a deleted recording which can be undelete */
void UpdatePath(void);
void DisplayError(PVR_ERROR err) const;
{
CSingleLock lock(m_critSection);
Clear();
- g_PVRClients->GetRecordings(this);
+ g_PVRClients->GetRecordings(this, false);
+ g_PVRClients->GetRecordings(this, true);
}
std::string CPVRRecordings::TrimSlashes(const std::string &strOrig) const
StringUtils::StartsWithNoCase(strUseEntryDirectory, strUseDirectory);
}
-void CPVRRecordings::GetSubDirectories(const std::string &strBase, CFileItemList *results)
+void CPVRRecordings::GetSubDirectories(const std::string &strBase, CFileItemList *results, bool bDeleted)
{
std::string strUseBase = TrimSlashes(strBase);
std::set<CFileItemPtr> unwatchedFolders;
+ std::string strBasePath = bDeleted ? "deleted" : "active";
for (PVR_RECORDINGMAP_CITR it = m_recordings.begin(); it != m_recordings.end(); it++)
{
std::string strFilePath;
if(strUseBase.empty())
- strFilePath = StringUtils::Format("pvr://recordings/%s/", strCurrent.c_str());
+ strFilePath = StringUtils::Format("pvr://recordings/%s/%s/", strBasePath.c_str(), strCurrent.c_str());
else
- strFilePath = StringUtils::Format("pvr://recordings/%s/%s/", strUseBase.c_str(), strCurrent.c_str());
+ strFilePath = StringUtils::Format("pvr://recordings/%s/%s/%s/", strBasePath.c_str(), strUseBase.c_str(), strCurrent.c_str());
CFileItemPtr pFileItem;
if (m_database.IsOpen())
return m_recordings.size();
}
-int CPVRRecordings::GetRecordings(CFileItemList* results)
+bool CPVRRecordings::HasDeletedRecordings()
+{
+ CSingleLock lock(m_critSection);
+ return m_bHasDeleted;
+}
+
+int CPVRRecordings::GetRecordings(CFileItemList* results, bool bDeleted)
{
CSingleLock lock(m_critSection);
+ int iRecCount = 0;
for (PVR_RECORDINGMAP_CITR it = m_recordings.begin(); it != m_recordings.end(); it++)
{
+ if (it->second->IsDeleted() != bDeleted)
+ continue;
+
CFileItemPtr pFileItem(new CFileItem(it->second));
results->Add(pFileItem);
+ iRecCount++;
}
- return m_recordings.size();
+ return iRecCount;
}
bool CPVRRecordings::Delete(const CFileItem& item)
return tag->Delete();
}
+bool CPVRRecordings::Undelete(const CFileItem &item)
+{
+ if (!item.IsDeletedPVRRecording())
+ {
+ CLog::Log(LOGERROR, "CPVRRecordings - %s - cannot undelete file: no valid recording tag", __FUNCTION__);
+ return false;
+ }
+
+ CPVRRecordingPtr tag = item.GetPVRRecordingInfoTag();
+ return tag->Undelete();
+}
+
bool CPVRRecordings::RenameRecording(CFileItem &item, std::string &strNewName)
{
- if (!item.IsPVRRecording())
+ if (!item.IsUsablePVRRecording())
{
CLog::Log(LOGERROR, "CPVRRecordings - %s - cannot rename file: no valid recording tag", __FUNCTION__);
return false;
return tag->Rename(strNewName);
}
+bool CPVRRecordings::DeleteAllRecordingsFromTrash()
+{
+ return g_PVRClients->DeleteAllRecordingsFromTrash();
+}
+
bool CPVRRecordings::SetRecordingsPlayCount(const CFileItemPtr &item, int count)
{
bool bResult = false;
{
strDirectoryPath.erase(0, 10);
+ // Check directory name is for deleted recordings
+ bool bDeleted = StringUtils::StartsWith(strDirectoryPath, "/deleted");
+ strDirectoryPath.erase(0, bDeleted ? 8 : 7);
+
// get the directory structure if in non-flatten mode
if (m_bGroupItems)
- GetSubDirectories(strDirectoryPath, &items);
+ GetSubDirectories(strDirectoryPath, &items, bDeleted);
// get all files of the currrent directory or recursively all files starting at the current directory if in flatten mode
for (PVR_RECORDINGMAP_CITR it = m_recordings.begin(); it != m_recordings.end(); it++)
CPVRRecordingPtr current = it->second;
// skip items that are not members of the target directory
- if (!IsDirectoryMember(strDirectoryPath, current->m_strDirectory))
+ if (!IsDirectoryMember(strDirectoryPath, current->m_strDirectory) || current->IsDeleted() != bDeleted)
continue;
if (m_database.IsOpen())
return false;
}
-void CPVRRecordings::GetAll(CFileItemList &items)
+void CPVRRecordings::GetAll(CFileItemList &items, bool bDeleted)
{
CSingleLock lock(m_critSection);
for (PVR_RECORDINGMAP_CITR it = m_recordings.begin(); it != m_recordings.end(); it++)
{
CPVRRecordingPtr current = it->second;
+ if (current->IsDeleted() != bDeleted)
+ continue;
+
if (m_database.IsOpen())
current->UpdateMetadata(m_database);
if (StringUtils::StartsWith(fileName, "recordings/"))
{
+ // Check directory name is for deleted recordings
+ fileName.erase(0, 11);
+ bool bDeleted = StringUtils::StartsWith(fileName, "deleted/");
+
for (PVR_RECORDINGMAP_CITR it = m_recordings.begin(); it != m_recordings.end(); it++)
{
CPVRRecordingPtr current = it->second;
- if (URIUtils::PathEquals(path, current->m_strFileNameAndPath))
- {
- CFileItemPtr fileItem(new CFileItem(current));
- return fileItem;
- }
+ if (!URIUtils::PathEquals(path, current->m_strFileNameAndPath) || bDeleted != current->IsDeleted())
+ continue;
+
+ CFileItemPtr fileItem(new CFileItem(current));
+ return fileItem;
}
}
void CPVRRecordings::Clear()
{
CSingleLock lock(m_critSection);
+ m_bHasDeleted = false;
m_recordings.clear();
}
{
CSingleLock lock(m_critSection);
+ if (tag->IsDeleted())
+ m_bHasDeleted = true;
+
CPVRRecordingPtr newTag = GetById(tag->m_iClientId, tag->m_strRecordingId);
if (newTag)
{
unsigned int m_iLastId;
bool m_bGroupItems;
CVideoDatabase m_database;
+ bool m_bHasDeleted;
virtual void UpdateFromClients(void);
virtual std::string TrimSlashes(const std::string &strOrig) const;
virtual const std::string GetDirectoryFromPath(const std::string &strPath, const std::string &strBase) const;
virtual bool IsDirectoryMember(const std::string &strDirectory, const std::string &strEntryDirectory) const;
- virtual void GetSubDirectories(const std::string &strBase, CFileItemList *results);
+ virtual void GetSubDirectories(const std::string &strBase, CFileItemList *results, bool bDeleted = false);
/**
* @brief recursively deletes all recordings in the specified directory
void Update(void);
int GetNumRecordings();
- int GetRecordings(CFileItemList* results);
+ bool HasDeletedRecordings();
+ int GetRecordings(CFileItemList* results, bool bDeleted = false);
/**
* Deletes the item in question, be it a directory or a file
* @return whether the item was deleted successfully
*/
bool Delete(const CFileItem &item);
+ bool Undelete(const CFileItem &item);
+ bool DeleteAllRecordingsFromTrash();
bool RenameRecording(CFileItem &item, std::string &strNewName);
bool SetRecordingsPlayCount(const CFileItemPtr &item, int count);
bool GetDirectory(const std::string& strPath, CFileItemList &items);
CFileItemPtr GetByPath(const std::string &path);
CPVRRecordingPtr GetById(int iClientId, const std::string &strRecordingId) const;
- void GetAll(CFileItemList &items);
+ void GetAll(CFileItemList &items, bool bDeleted = false);
CFileItemPtr GetById(unsigned int iId) const;
void SetGroupItems(bool value) { m_bGroupItems = value; };
bool CGUIViewStateWindowPVRRecordings::HideParentDirItems(void)
{
- return (CGUIViewState::HideParentDirItems() || m_items.GetPath() == "pvr://recordings/");
+ return (CGUIViewState::HideParentDirItems() || m_items.GetPath() == "pvr://recordings/active/" || m_items.GetPath() == "pvr://recordings/deleted/");
}
CGUIViewStateWindowPVRGuide::CGUIViewStateWindowPVRGuide(const int windowId, const CFileItemList& items) : CGUIViewStatePVR(windowId, items)
g_PVRClients->ProcessMenuHooks(item->GetEPGInfoTag()->ChannelTag()->ClientID(), PVR_MENUHOOK_EPG, item.get());
else if (item->IsPVRChannel())
g_PVRClients->ProcessMenuHooks(item->GetPVRChannelInfoTag()->ClientID(), PVR_MENUHOOK_CHANNEL, item.get());
- else if (item->IsPVRRecording())
+ else if (item->IsDeletedPVRRecording())
+ g_PVRClients->ProcessMenuHooks(item->GetPVRRecordingInfoTag()->m_iClientId, PVR_MENUHOOK_DELETED_RECORDING, item.get());
+ else if (item->IsUsablePVRRecording())
g_PVRClients->ProcessMenuHooks(item->GetPVRRecordingInfoTag()->m_iClientId, PVR_MENUHOOK_RECORDING, item.get());
else if (item->IsPVRTimer())
g_PVRClients->ProcessMenuHooks(item->GetPVRTimerInfoTag()->m_iClientId, PVR_MENUHOOK_TIMER, item.get());
#define CONTROL_BTNSORTASC 4
#define CONTROL_BTNGROUPITEMS 5
#define CONTROL_BTNSHOWHIDDEN 6
+#define CONTROL_BTNSHOWDELETED 7
#define CONTROL_BTNCHANNELGROUPS 28
#define CONTROL_BTNFILTERCHANNELS 31
using namespace PVR;
CGUIWindowPVRRecordings::CGUIWindowPVRRecordings(bool bRadio) :
- CGUIWindowPVRBase(bRadio, bRadio ? WINDOW_RADIO_RECORDINGS : WINDOW_TV_RECORDINGS, "MyPVRRecordings.xml")
+ CGUIWindowPVRBase(bRadio, bRadio ? WINDOW_RADIO_RECORDINGS : WINDOW_TV_RECORDINGS, "MyPVRRecordings.xml") ,
+ m_bShowDeletedRecordings(false)
{
}
std::string CGUIWindowPVRRecordings::GetDirectoryPath(void)
{
- if (StringUtils::StartsWith(m_vecItems->GetPath(), "pvr://recordings/"))
+ std::string basePath = StringUtils::Format("pvr://recordings/%s/", m_bShowDeletedRecordings ? "deleted" : "active");
+
+ if (StringUtils::StartsWith(m_vecItems->GetPath(), basePath))
return m_vecItems->GetPath();
- return "pvr://recordings/";
+
+ return basePath;
}
std::string CGUIWindowPVRRecordings::GetResumeString(const CFileItem& item)
{
std::string resumeString;
- if (item.IsPVRRecording())
+ if (item.IsUsablePVRRecording())
{
// First try to find the resume position on the back-end, if that fails use video database
return;
CFileItemPtr pItem = m_vecItems->Get(itemNumber);
+ bool isDeletedRecording = false;
+
if (pItem->HasPVRRecordingInfoTag())
{
+ isDeletedRecording = pItem->GetPVRRecordingInfoTag()->IsDeleted();
+
buttons.Add(CONTEXT_BUTTON_INFO, 19053); /* Get Information of this recording */
- buttons.Add(CONTEXT_BUTTON_FIND, 19003); /* Find similar program */
- buttons.Add(CONTEXT_BUTTON_PLAY_ITEM, 12021); /* Play this recording */
- std::string resumeString = GetResumeString(*pItem);
- if (!resumeString.empty())
+ if (!isDeletedRecording)
{
- buttons.Add(CONTEXT_BUTTON_RESUME_ITEM, resumeString);
+ buttons.Add(CONTEXT_BUTTON_FIND, 19003); /* Find similar program */
+ buttons.Add(CONTEXT_BUTTON_PLAY_ITEM, 12021); /* Play this recording */
+ std::string resumeString = GetResumeString(*pItem);
+ if (!resumeString.empty())
+ {
+ buttons.Add(CONTEXT_BUTTON_RESUME_ITEM, resumeString);
+ }
+ }
+ else
+ {
+ buttons.Add(CONTEXT_BUTTON_UNDELETE, 19290); /* Undelete this recording */
+ buttons.Add(CONTEXT_BUTTON_DELETE, 19291); /* Delete this permanently */
+ if (m_vecItems->GetObjectCount() > 1)
+ buttons.Add(CONTEXT_BUTTON_DELETE_ALL, 19292); /* Delete all permanently */
}
}
- if (pItem->m_bIsFolder)
- {
- // Have both options for folders since we don't know whether all childs are watched/unwatched
- buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); /* Mark as UnWatched */
- buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); /* Mark as Watched */
- }
- if (pItem->HasPVRRecordingInfoTag())
+ if (!isDeletedRecording)
{
- if (pItem->GetPVRRecordingInfoTag()->m_playCount > 0)
+ if (pItem->m_bIsFolder)
+ {
+ // Have both options for folders since we don't know whether all childs are watched/unwatched
buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); /* Mark as UnWatched */
- else
buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); /* Mark as Watched */
+ }
+ if (pItem->HasPVRRecordingInfoTag())
+ {
+ if (pItem->GetPVRRecordingInfoTag()->m_playCount > 0)
+ buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); /* Mark as UnWatched */
+ else
+ buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); /* Mark as Watched */
- buttons.Add(CONTEXT_BUTTON_RENAME, 118); /* Rename this recording */
+ buttons.Add(CONTEXT_BUTTON_RENAME, 118); /* Rename this recording */
+ }
+
+ buttons.Add(CONTEXT_BUTTON_DELETE, 117);
}
-
- buttons.Add(CONTEXT_BUTTON_DELETE, 117);
- if (pItem->HasPVRRecordingInfoTag() &&
- g_PVRClients->HasMenuHooks(pItem->GetPVRRecordingInfoTag()->m_iClientId, PVR_MENUHOOK_RECORDING))
- buttons.Add(CONTEXT_BUTTON_MENU_HOOKS, 19195); /* PVR client specific action */
+ if (pItem->HasPVRRecordingInfoTag())
+ {
+ if (!isDeletedRecording && g_PVRClients->HasMenuHooks(pItem->GetPVRRecordingInfoTag()->m_iClientId, PVR_MENUHOOK_RECORDING))
+ buttons.Add(CONTEXT_BUTTON_MENU_HOOKS, 19195); /* PVR client specific action */
+ else if (isDeletedRecording && g_PVRClients->HasMenuHooks(pItem->GetPVRRecordingInfoTag()->m_iClientId, PVR_MENUHOOK_DELETED_RECORDING))
+ buttons.Add(CONTEXT_BUTTON_MENU_HOOKS, 19195); /* PVR client specific action */
+ }
- CGUIWindowPVRBase::GetContextButtons(itemNumber, buttons);
+ if (!isDeletedRecording)
+ CGUIWindowPVRBase::GetContextButtons(itemNumber, buttons);
}
bool CGUIWindowPVRRecordings::OnAction(const CAction &action)
if (action.GetID() == ACTION_PARENT_DIR ||
action.GetID() == ACTION_NAV_BACK)
{
- if (m_vecItems->GetPath() != "pvr://recordings/")
+ if (m_vecItems->GetPath() != "pvr://recordings/active/" && m_vecItems->GetPath() != "pvr://recordings/deleted/")
{
GoParentFolder();
return true;
return OnContextButtonPlay(pItem.get(), button) ||
OnContextButtonRename(pItem.get(), button) ||
OnContextButtonDelete(pItem.get(), button) ||
+ OnContextButtonUndelete(pItem.get(), button) ||
+ OnContextButtonDeleteAll(pItem.get(), button) ||
OnContextButtonInfo(pItem.get(), button) ||
OnContextButtonMarkWatched(pItem, button) ||
CGUIWindowPVRBase::OnContextButton(itemNumber, button);
{
m_thumbLoader.StopThread();
- return CGUIWindowPVRBase::Update(strDirectory);
+ bool bReturn = CGUIWindowPVRBase::Update(strDirectory);
+
+ /* empty list for deleted recordings */
+ if (m_vecItems->GetObjectCount() == 0 && m_bShowDeletedRecordings)
+ {
+ /* show the normal recordings instead */
+ m_bShowDeletedRecordings = false;
+ Update(GetDirectoryPath());
+ }
+
+ return bReturn;
+}
+
+void CGUIWindowPVRRecordings::UpdateButtons(void)
+{
+ CGUIRadioButtonControl *btnShowDeleted = (CGUIRadioButtonControl*) GetControl(CONTROL_BTNSHOWDELETED);
+ if (btnShowDeleted)
+ {
+ btnShowDeleted->SetVisible(g_PVRRecordings->HasDeletedRecordings());
+ btnShowDeleted->SetSelected(m_bShowDeletedRecordings);
+ }
+
+ CGUIWindowPVRBase::UpdateButtons();
+ SET_CONTROL_LABEL(CONTROL_LABEL_HEADER1, m_bShowDeletedRecordings ? g_localizeStrings.Get(19179) : ""); /* Deleted recordings trash */
}
bool CGUIWindowPVRRecordings::OnMessage(CGUIMessage &message)
g_PVRRecordings->SetGroupItems(radioButton->IsSelected());
Refresh(true);
}
+ else if (message.GetSenderId() == CONTROL_BTNSHOWDELETED)
+ {
+ CGUIRadioButtonControl *radioButton = (CGUIRadioButtonControl*) GetControl(CONTROL_BTNSHOWDELETED);
+ if (radioButton)
+ {
+ m_bShowDeletedRecordings = radioButton->IsSelected();
+ Update(GetDirectoryPath());
+ }
+ bReturn = true;
+ }
break;
case GUI_MSG_REFRESH_LIST:
switch(message.GetParam1())
return bReturn;
pDialog->SetHeading(122); // Confirm delete
- pDialog->SetLine(0, item->m_bIsFolder ? 19113 : 19112); // Are you sure?
+ pDialog->SetLine(0, item->m_bIsFolder ? 19113 : item->GetPVRRecordingInfoTag()->IsDeleted() ? 19294 : 19112); // Delete all recordings in this folder? / Delete this recording permanently? / Delete this recording?
pDialog->SetLine(1, "");
pDialog->SetLine(2, item->GetLabel());
pDialog->SetChoice(1, 117); // Delete
m_vecItems->Remove(item);
/* go to the parent folder if we're in a subdirectory and just deleted the last item */
- if (m_vecItems->GetPath() != "pvr://recordings/" && m_vecItems->GetObjectCount() == 0)
+ if (m_vecItems->GetPath() != "pvr://recordings/active/" &&
+ m_vecItems->GetPath() != "pvr://recordings/deleted/" && m_vecItems->GetObjectCount() == 0)
GoParentFolder();
}
return button == CONTEXT_BUTTON_DELETE ? ActionDeleteRecording(item) : false;
}
+bool CGUIWindowPVRRecordings::OnContextButtonUndelete(CFileItem *item, CONTEXT_BUTTON button)
+{
+ bool bReturn = false;
+
+ if (button != CONTEXT_BUTTON_UNDELETE || !item->IsDeletedPVRRecording())
+ return bReturn;
+
+ /* undelete the recording */
+ if (g_PVRRecordings->Undelete(*item))
+ {
+ g_PVRManager.TriggerRecordingsUpdate();
+ bReturn = true;
+
+ /* remove the item from the list immediately, otherwise the
+ item count further down may be wrong */
+ m_vecItems->Remove(item);
+
+ /* go to the parent folder if we're in a subdirectory and just deleted the last item */
+ if (m_vecItems->GetPath() != "pvr://recordings/deleted/" && m_vecItems->GetObjectCount() == 0)
+ GoParentFolder();
+ }
+
+ return bReturn;
+}
+
+bool CGUIWindowPVRRecordings::OnContextButtonDeleteAll(CFileItem *item, CONTEXT_BUTTON button)
+{
+ bool bReturn = false;
+
+ if (button != CONTEXT_BUTTON_DELETE_ALL || !item->IsDeletedPVRRecording())
+ return bReturn;
+
+ /* show a confirmation dialog */
+ CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
+ if (!pDialog)
+ return bReturn;
+
+
+ pDialog->SetHeading(19292); // Delete all permanently
+ pDialog->SetLine(0, 19293); // Delete all recordings permanently?
+ pDialog->SetLine(1, "");
+ pDialog->SetLine(2, "");
+ pDialog->SetChoice(1, 117); // Delete
+
+ /* prompt for the user's confirmation */
+ pDialog->DoModal();
+ if (!pDialog->IsConfirmed())
+ return bReturn;
+
+ /* undelete the recording */
+ if (g_PVRRecordings->DeleteAllRecordingsFromTrash())
+ {
+ g_PVRManager.TriggerRecordingsUpdate();
+ bReturn = true;
+
+ /* remove the item from the list immediately, otherwise the
+ item count further down may be wrong */
+ m_vecItems->Clear();
+
+ /* go to the parent folder if we're in a subdirectory and just deleted the last item */
+ if (m_vecItems->GetPath() != "pvr://recordings/deleted/" && m_vecItems->GetObjectCount() == 0)
+ GoParentFolder();
+ }
+ return bReturn;
+}
+
bool CGUIWindowPVRRecordings::OnContextButtonInfo(CFileItem *item, CONTEXT_BUTTON button)
{
bool bReturn = false;
void GetContextButtons(int itemNumber, CContextButtons &buttons);
bool OnContextButton(int itemNumber, CONTEXT_BUTTON button);
bool Update(const std::string &strDirectory, bool updateFilterPath = true);
+ void UpdateButtons(void);
void UnregisterObservers(void);
void ResetObservers(void);
private:
bool ActionDeleteRecording(CFileItem *item);
bool OnContextButtonDelete(CFileItem *item, CONTEXT_BUTTON button);
+ bool OnContextButtonUndelete(CFileItem *item, CONTEXT_BUTTON button);
+ bool OnContextButtonDeleteAll(CFileItem *item, CONTEXT_BUTTON button);
bool OnContextButtonInfo(CFileItem *item, CONTEXT_BUTTON button);
bool OnContextButtonPlay(CFileItem *item, CONTEXT_BUTTON button);
bool OnContextButtonRename(CFileItem *item, CONTEXT_BUTTON button);
CVideoThumbLoader m_thumbLoader;
CVideoDatabase m_database;
+ bool m_bShowDeletedRecordings;
};
}
if (tag)
m_searchfilter.m_strSearchTerm = "\"" + tag->Title() + "\"";
}
- else if (item.IsPVRRecording())
+ else if (item.IsUsablePVRRecording())
m_searchfilter.m_strSearchTerm = "\"" + item.GetPVRRecordingInfoTag()->m_strTitle + "\"";
else if (item.IsPVRTimer())
m_searchfilter.m_strSearchTerm = "\"" + item.GetPVRTimerInfoTag()->m_strTitle + "\"";
}
CLog::Log(LOGDEBUG, "%s %s", __FUNCTION__, CURL::GetRedacted(item.GetPath()).c_str());
- if (StringUtils::StartsWith(item.GetPath(), "pvr://recordings/"))
+ if (StringUtils::StartsWith(item.GetPath(), "pvr://recordings/active/"))
{
if (!g_PVRManager.IsStarted())
return false;
SetControlLabel(i++, "%s: %s", 19116, PVR_BACKEND_DISKSPACE);
SetControlLabel(i++, "%s: %s", 19019, PVR_BACKEND_CHANNELS);
SetControlLabel(i++, "%s: %s", 19163, PVR_BACKEND_RECORDINGS);
+ SetControlLabel(i++, "%s: %s", 19168, PVR_BACKEND_DELETED_RECORDINGS); // Deleted and recoverable recordings
SetControlLabel(i++, "%s: %s", 19025, PVR_BACKEND_TIMERS);
}