Skip to content

Commit

Permalink
[MovieSelection]
Browse files Browse the repository at this point in the history
* improve delete

* Translation Update
  • Loading branch information
jbleyel committed Jan 29, 2025
1 parent b2b47c8 commit f2bc8cb
Show file tree
Hide file tree
Showing 51 changed files with 1,475 additions and 691 deletions.
22 changes: 11 additions & 11 deletions data/setup.xml
Original file line number Diff line number Diff line change
Expand Up @@ -517,10 +517,10 @@
<item level="2" text="Enable core dumps *" description="Core dumps are helpful for developers in case of a FATAL SIGNAL crash in the C++ code. Typical core dump size is 110 MB so adjust maximum space used and choose proper location.">config.crash.coredump</item>
</setup>
<setup key="MovieSelection" title="Movie List Settings" showOpenWebif="1">
<item level="0" text="Use 'Trash' in movie list" description="When enabled, deleted recordings are moved to the trash can, instead of being deleted immediately.">config.usage.movielist_trashcan</item>
<item level="0" text="Purge 'Trash' after (days)" description="Configure the number of days after which items are automatically removed from the trash can.">config.usage.movielist_trashcan_days</item>
<item level="0" text="Clean network 'Trash'" description="When enabled, network trash cans are probed for cleaning.">config.usage.movielist_trashcan_network_clean</item>
<item level="0" text="Space to reserve for recordings (GB)" description="Configure the minimum amount of disk space to be available for recordings. When the amount of space drops below this value, deleted items will be removed from the trash can.">config.usage.movielist_trashcan_reserve</item>
<item level="0" text="Use 'Trash' in movie list" description="When enabled, deleted recordings are moved to the trashcan, instead of being deleted immediately.">config.usage.movielist_trashcan</item>
<item level="0" text="Purge 'Trash' after (days)" description="Configure the number of days after which items are automatically removed from the trashcan.">config.usage.movielist_trashcan_days</item>
<item level="0" text="Clean network 'Trash'" description="When enabled, network trashcans are probed for cleaning.">config.usage.movielist_trashcan_network_clean</item>
<item level="0" text="Space to reserve for recordings (GB)" description="Configure the minimum amount of disk space to be available for recordings. When the amount of space drops below this value, deleted items will be removed from the trashcan.">config.usage.movielist_trashcan_reserve</item>
<item level="0" text="Background delete option" description="Configure on which devices the background delete option should be used.">config.misc.erase_flags</item>
<item level="0" text="Background delete speed" description="Configure the speed of the background deletion process. Lower speed will consume less hard disk drive performance.">config.misc.erase_speed</item>
<item level="0" text="Font size" description="This allows you change the font size relative to skin size, so 1 increases by 1 point size, and -1 decreases by 1 point size.">config.movielist.fontsize</item>
Expand Down Expand Up @@ -633,10 +633,10 @@
<item level="2" text="Time jump multiplier for fast backward" description="Defines the jump distance for backward jumps. The value is multiplied by the rewind speed, e.g. -4x. Values significantly lower than 2s may not work with all media files.">config.seek.withjumps_backwards_ms</item>
<item level="2" text="Time jump repeat interval for fast forward/backward" description="Defines how fast the time jumps are repeated. Values lower than 500ms may be problematic with NAS.">config.seek.withjumps_repeat_ms</item>
<item level="2" text="Time jump avoid zero step size" description="Avoid getting stuck (at the expense of some stuttering) when the jump time is smaller than the time between I-frames.">config.seek.withjumps_avoid_zero</item>
<item level="1" text="Use 'Trash' in movie list" description="When enabled, deleted recordings are moved to the trash can, instead of being deleted immediately.">config.usage.movielist_trashcan</item>
<item level="1" text="Purge 'Trash' after (days)" description="Configure the number of days after which items are automatically removed from the trash can.">config.usage.movielist_trashcan_days</item>
<item level="1" text="Clean network 'Trash'" description="When enabled, network trash cans are probed for cleaning.">config.usage.movielist_trashcan_network_clean</item>
<item level="1" text="Space to reserve for recordings (GB)" description="Configure the minimum amount of disk space to be available for recordings. When the amount of space drops below this value, deleted items will be removed from the trash can.">config.usage.movielist_trashcan_reserve</item>
<item level="1" text="Use 'Trash' in movie list" description="When enabled, deleted recordings are moved to the trashcan, instead of being deleted immediately.">config.usage.movielist_trashcan</item>
<item level="1" text="Purge 'Trash' after (days)" description="Configure the number of days after which items are automatically removed from the trashcan.">config.usage.movielist_trashcan_days</item>
<item level="1" text="Clean network 'Trash'" description="When enabled, network trashcans are probed for cleaning.">config.usage.movielist_trashcan_network_clean</item>
<item level="1" text="Space to reserve for recordings (GB)" description="Configure the minimum amount of disk space to be available for recordings. When the amount of space drops below this value, deleted items will be removed from the trashcan.">config.usage.movielist_trashcan_reserve</item>
<item level="2" text="Background delete option" description="Configure on which devices the background delete option should be used.">config.misc.erase_flags</item>
<item level="2" text="Background delete speed" description="Configure the speed of the background deletion process. Lower speed will consume less hard disk drive performance.">config.misc.erase_speed</item>
</setup>
Expand Down Expand Up @@ -687,9 +687,9 @@
<item level="2" text="Limit character set for recording filenames" description="Limit the characters that can be used in recording filenames to (7 bit) ASCII. This ensures compatibility with operating systems or file systems with limited character sets.">config.recording.ascii_filenames</item>
<item level="2" text="Composition of the recording filenames" description="Configure how recording filenames are constructed. Standard: Date Time - Channel - Title Very very short: Title Very short: Title - Date Time Short with time: Date Time - Title Short: Date - Title Long: Date Time - Channel - Title - Info">config.recording.filename_composition</item>
<item level="2" text="Remove completed timers after" description="Configure the number of days old timers are kept before they are automatically removed from the timer list.">config.recording.keep_timers</item>
<item level="1" text="Purge 'Trash' after (days)" description="Configure the number of days after which items are automatically removed from the trash can.">config.usage.movielist_trashcan_days</item>
<item level="1" text="Clean network 'Trash'" description="When enabled, network trash cans are probed for cleaning.">config.usage.movielist_trashcan_network_clean</item>
<item level="1" text="Space to reserve for recordings (GB)" description="Configure the minimum amount of disk space to be available for recordings. When the amount of space drops below this value, deleted items will be removed from the trash can.">config.usage.movielist_trashcan_reserve</item>
<item level="1" text="Purge 'Trash' after (days)" description="Configure the number of days after which items are automatically removed from the trashcan.">config.usage.movielist_trashcan_days</item>
<item level="1" text="Clean network 'Trash'" description="When enabled, network trashcans are probed for cleaning.">config.usage.movielist_trashcan_network_clean</item>
<item level="1" text="Space to reserve for recordings (GB)" description="Configure the minimum amount of disk space to be available for recordings. When the amount of space drops below this value, deleted items will be removed from the trashcan.">config.usage.movielist_trashcan_reserve</item>
<item level="2" text="Background delete option" description="Configure on which devices the background delete option should be used.">config.misc.erase_flags</item>
<item level="2" text="Background delete speed" description="Configure the speed of the background deletion process. Lower speed will consume less hard disk drive performance.">config.misc.erase_speed</item>
<item level="2" text="Always include ECM in recordings" description="Always include ECM messages in recordings. This overrides the individual timer settings globally. It allows recordings to be always decrypted afterwards (sometimes called offline decoding), if supported by your receiver.">config.recording.always_ecm</item>
Expand Down
2 changes: 1 addition & 1 deletion lib/python/Screens/InfoBar.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ def leavePlayerConfirmed(self, answer):
return
except Exception as e:
print("[InfoBar] Failed to move to .Trash folder:", e)
msg = _("Cannot move to trash can") + "\n" + str(e) + "\n"
msg = _("Can't move to trashcan!") + "\n" + str(e) + "\n"
info = serviceHandler.info(ref)
name = info and info.getName(ref) or _("this recording")
msg += _("Do you really want to delete '%s'?") % name
Expand Down
2 changes: 1 addition & 1 deletion lib/python/Screens/LocationBox.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ def addRemoveBookmark(self):
self["bookmarklist"].setList(self.bookmarksList)
self.updateState()
else: # Remove bookmark.
self.session.openWithCallback(boundFunction(self.removeBookmarkCallback, current), MessageBox, _("Do you really want to remove your bookmark for '%s'?") % current)
self.session.openWithCallback(boundFunction(self.removeBookmarkCallback, current), MessageBox, _("Do you really want to remove the bookmark for '%s'?") % current)

def removeBookmarkCallback(self, bookmark, answer):
if answer and bookmark in self.bookmarksList:
Expand Down
126 changes: 50 additions & 76 deletions lib/python/Screens/MovieSelection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,7 @@ def reloadWithDelay(self):
if config.usage.setup_level.index >= 2: # Expert+.
title += config.movielist.last_videodir.value
if self.selected_tags:
title += " - {",".join(self.selected_tags)}"
title += " - {", ".join(self.selected_tags)}"
self.setTitle(title)
self.displayMovieOffStatus()
self.displaySortStatus()
Expand Down Expand Up @@ -1186,7 +1186,7 @@ def gotFilename(self, res, selItem=None):
ref.setPath(currentDir)
self.reloadList(home=True, sel=ref)
else:
self.session.open(MessageBox, _("Directory %s does not exist.") % res, type=MessageBox.TYPE_ERROR, timeout=5, windowTitle=self.getTitle())
self.session.open(MessageBox, _("Error: Directory '%s' does not exist!") % res, type=MessageBox.TYPE_ERROR, timeout=5, windowTitle=self.getTitle())

def showAll(self):
self.selected_tags_ele = None
Expand Down Expand Up @@ -1285,7 +1285,7 @@ def do_addbookmark(self):
if path in config.movielist.videodirs.value:
if len(path) > 40:
path = f"...{path[-40:]}"
self.session.openWithCallback(self.removeBookmark, MessageBox, _("Do you really want to remove your bookmark for '%s'?") % path, windowTitle=self.getTitle())
self.session.openWithCallback(self.removeBookmark, MessageBox, _("Do you really want to remove the bookmark for '%s'?") % path, windowTitle=self.getTitle())
else:
config.movielist.videodirs.value += [path]
config.movielist.videodirs.save()
Expand Down Expand Up @@ -1529,85 +1529,64 @@ def delete(self, *args):
item = self.getCurrentSelection()
current = item[0]
info = item[1]
cur_path = realpath(current.getPath())
if not exists(cur_path): # File does not exist.
currentPath = realpath(current.getPath())
if not exists(currentPath): # File does not exist.
return
st = stat(cur_path)
name = info and info.getName(current) or _("this recording")
are_you_sure = ""
pathtest = info and info.getName(current)
if not pathtest:
st = stat(currentPath)
name = info and info.getName(current)
if not name:
return
if item and isTrashFolder(item[0]): # Red button to empty trashcan.
self.purgeAll()
return
areYouSure = ""
if current.flags & eServiceReference.mustDescent:
files = 0
subdirs = 0
if TRASHCAN not in cur_path and config.usage.movielist_trashcan.value:
for file in listdir(currentPath):
if file not in (".", ".."):
if isdir(join(currentPath, file)):
subdirs += 1
else:
files += 1
preamble = f"{_("'%s' contains %d file(s) and %d sub-directories.\n") % (split(split(name)[0])[1], files, subdirs)}\n\n" if files or subdirs else ""
if TRASHCAN not in currentPath and config.usage.movielist_trashcan.value:
if isFolder(item):
are_you_sure = _("Do you really want to move to trashcan ?")
# areYouSure = _("Do you really want to move '%s' to the trashcan?") % name
areYouSure = _("Do you really want to move to trashcan ?")
else:
args = True
if args:
trash = createTrashcan(cur_path)
trash = createTrashcan(currentPath)
if trash:
moveServiceFiles(current, trash, name, allowCopy=True)
self["list"].removeService(current)
self.showActionFeedback(_("Deleted") + " " + name)
self.showActionFeedback(f"{_("Deleted")} {name}")
return
else:
msg = _("Cannot move to trash can") + "\n"
are_you_sure = _("Do you really want to delete %s ?") % name
for fn in listdir(cur_path):
if (fn != ".") and (fn != ".."):
ffn = join(cur_path, fn)
if isdir(ffn):
subdirs += 1
else:
files += 1
if files or subdirs:
folder_filename = split(split(name)[0])[1]
self.session.openWithCallback(self.delete, MessageBox, _("'%s' contains %d file(s) and %d sub-directories.\n") % (folder_filename, files, subdirs) + are_you_sure, windowTitle=self.getTitle())
return
else:
self.session.openWithCallback(self.delete, MessageBox, are_you_sure, windowTitle=self.getTitle())
return
msg = f"{_("Can't move to trashcan!")}\n\n"
self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, windowTitle=self.getTitle())
return
areYouSure = _("Do you really want to delete '%s'?") % name
self.session.openWithCallback(self.delete, MessageBox, f"{preamble}{areYouSure}", windowTitle=self.getTitle())
return
else:
if TRASHCAN in cur_path:
are_you_sure = _("Do you really want to permanently remove from trash can ?")
if TRASHCAN in currentPath:
preamble = ""
areYouSure = _("Do you really want to permanently remove '%s' from the trashcan?" % name)
else:
are_you_sure = _("Do you really want to delete ?")
areYouSure = _("Do you really want to delete '%s'?") % name
if args:
try:
msg = ""
deleteFiles(cur_path, name)
deleteFiles(currentPath, name)
self["list"].removeService(current)
self.showActionFeedback(f"{_("Deleted")} {name}")
return
except Exception as err:
print(f"[MovieSelection] Error: Weird error moving to trash! ({str(err)})")
print(f"[MovieSelection] Error: Weird error moving to trashcan! ({str(err)})")
msg = f"{_("Cannot delete file")}\n{str(err)}\n"
return
for fn in listdir(cur_path):
if (fn != ".") and (fn != ".."):
ffn = join(cur_path, fn)
if isdir(ffn):
subdirs += 1
else:
files += 1
if files or subdirs:
folder_filename = split(split(name)[0])[1]
self.session.openWithCallback(self.delete, MessageBox, _("'%s' contains %d file(s) and %d sub-directories.\n") % (folder_filename, files, subdirs) + are_you_sure, windowTitle=self.getTitle())
else:
try:
rmdir(cur_path)
except OSError as err:
print(f"[MovieSelection] Error {err.errno}: Failed delete '{cur_path}'! ({err.strerror})")
self.session.open(MessageBox, f"{_("Delete failed!")}\n{str(err)}", MessageBox.TYPE_ERROR, windowTitle=self.getTitle())
else:
self["list"].removeService(current)
self.showActionFeedback(f"{_("Deleted")} {name}")
self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, windowTitle=self.getTitle())
return
self.session.openWithCallback(self.delete, MessageBox, f"{preamble}{areYouSure}", windowTitle=self.getTitle())
else:
if not args:
rec_filename = split(current.getPath())[1]
Expand All @@ -1624,12 +1603,12 @@ def delete(self, *args):
]
self.session.openWithCallback(self.onTimerChoice, ChoiceBox, title=f"{_("Recording in progress!")}\n{name}", list=choices)
return
if time() - st.st_mtime < 5 and not args:
are_you_sure = _("Do you really want to delete ?")
self.session.openWithCallback(self.delete, MessageBox, _("File appears to be busy.\n") + are_you_sure, windowTitle=self.getTitle())
if int(time()) - st.st_mtime < 5 and not args:
areYouSure = _("Do you really want to delete?")
self.session.openWithCallback(self.delete, MessageBox, f"{_("File appears to be busy!\n")}\n{areYouSure}", windowTitle=self.getTitle())
return
if TRASHCAN not in cur_path and config.usage.movielist_trashcan.value:
trash = createTrashcan(cur_path)
if TRASHCAN not in currentPath and config.usage.movielist_trashcan.value:
trash = createTrashcan(currentPath)
if trash:
moveServiceFiles(current, trash, name, allowCopy=True)
self["list"].removeService(current)
Expand All @@ -1638,15 +1617,15 @@ def delete(self, *args):
self.showActionFeedback(f"{_("Deleted")} {name}")
return
else:
msg = f"{_("Cannot move to trash can")}\n"
are_you_sure = _("Do you really want to delete %s ?") % name
msg = f"{_("Can't move to trashcan!")}\n\n"
areYouSure = _("Do you really want to delete '%s'?") % name
else:
if TRASHCAN in cur_path:
are_you_sure = _("Do you really want to permanently remove '%s' from trash can ?") % name
if TRASHCAN in currentPath:
areYouSure = _("Do you really want to permanently remove '%s' from the trashcan?") % name
else:
are_you_sure = _("Do you really want to delete %s ?") % name
areYouSure = _("Do you really want to delete '%s'?") % name
msg = ""
self.session.openWithCallback(self.deleteConfirmed, MessageBox, msg + are_you_sure, windowTitle=self.getTitle())
self.session.openWithCallback(self.deleteConfirmed, MessageBox, f"{msg}{areYouSure}", windowTitle=self.getTitle())

def deleteConfirmed(self, confirmed):
if not confirmed:
Expand Down Expand Up @@ -1675,14 +1654,9 @@ def deleteConfirmed(self, confirmed):

def purgeAll(self):
recordings = self.session.nav.getRecordings(False, pNavigation.isRealRecording)
next_rec_time = -1
if not recordings:
next_rec_time = self.session.nav.RecordTimer.getNextRecordingTime()
if recordings or (next_rec_time > 0 and (next_rec_time - time()) < 120):
msg = f"\n{_("Recording(s) are in progress or coming up in few seconds!")}"
else:
msg = ""
self.session.openWithCallback(self.purgeConfirmed, MessageBox, _("Permanently delete all recordings in the trash can?") + msg, windowTitle=self.getTitle())
nextRecordingTime = -1 if recordings else self.session.nav.RecordTimer.getNextRecordingTime()
msg = f"\n\n{_("Recording(s) are in progress or coming up in few seconds!")}" if recordings or (nextRecordingTime > 0 and (nextRecordingTime - int(time())) < 120) else ""
self.session.openWithCallback(self.purgeConfirmed, MessageBox, f"{_("Permanently delete all recordings in the trashcan?")}{msg}", windowTitle=self.getTitle())

def purgeConfirmed(self, confirmed):
if not confirmed:
Expand Down
Loading

0 comments on commit f2bc8cb

Please sign in to comment.