Added src data
This commit is contained in:
parent
eee95b1914
commit
f77db53c7f
1
src/shellfm/__init__.py
Normal file
1
src/shellfm/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .windows import WindowController
|
102
src/shellfm/windows/Launcher.py
Normal file
102
src/shellfm/windows/Launcher.py
Normal file
@ -0,0 +1,102 @@
|
||||
# System import
|
||||
import os, subprocess, threading
|
||||
|
||||
|
||||
# Lib imports
|
||||
|
||||
|
||||
# Apoplication imports
|
||||
|
||||
|
||||
class Launcher:
|
||||
def openFilelocally(self, file):
|
||||
lowerName = file.lower()
|
||||
command = []
|
||||
|
||||
if lowerName.endswith(self.fvideos):
|
||||
command = [self.media_app]
|
||||
|
||||
if "mplayer" in self.media_app:
|
||||
command += self.mplayer_options
|
||||
|
||||
command += [file]
|
||||
elif lowerName.endswith(self.fimages):
|
||||
command = [self.image_app, file]
|
||||
elif lowerName.endswith(self.fmusic):
|
||||
command = [self.music_app, file]
|
||||
elif lowerName.endswith(self.foffice):
|
||||
command = [self.office_app, file]
|
||||
elif lowerName.endswith(self.ftext):
|
||||
command = [self.text_app, file]
|
||||
elif lowerName.endswith(self.fpdf):
|
||||
command = [self.pdf_app, file]
|
||||
else:
|
||||
command = [self.file_manager_app, file]
|
||||
|
||||
self.logger.debug(command)
|
||||
DEVNULL = open(os.devnull, 'w')
|
||||
subprocess.Popen(command, start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
|
||||
|
||||
def remuxVideo(self, hash, file):
|
||||
remux_vid_pth = self.REMUX_FOLDER + "/" + hash + ".mp4"
|
||||
self.logger.debug(remux_vid_pth)
|
||||
|
||||
if not os.path.isfile(remux_vid_pth):
|
||||
self.check_remux_space()
|
||||
|
||||
command = ["ffmpeg", "-i", file, "-hide_banner", "-movflags", "+faststart"]
|
||||
if file.endswith("mkv"):
|
||||
command += ["-codec", "copy", "-strict", "-2"]
|
||||
if file.endswith("avi"):
|
||||
command += ["-c:v", "libx264", "-crf", "21", "-c:a", "aac", "-b:a", "192k", "-ac", "2"]
|
||||
if file.endswith("wmv"):
|
||||
command += ["-c:v", "libx264", "-crf", "23", "-c:a", "aac", "-strict", "-2", "-q:a", "100"]
|
||||
if file.endswith("f4v") or file.endswith("flv"):
|
||||
command += ["-vcodec", "copy"]
|
||||
|
||||
command += [remux_vid_pth]
|
||||
try:
|
||||
proc = subprocess.Popen(command)
|
||||
proc.wait()
|
||||
except Exception as e:
|
||||
self.logger.debug(message)
|
||||
self.logger.debug(e)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def generateVideoThumbnail(self, fullPath, hashImgPth):
|
||||
try:
|
||||
proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPath, "-o", hashImgPth])
|
||||
proc.wait()
|
||||
except Exception as e:
|
||||
self.logger.debug(repr(e))
|
||||
|
||||
|
||||
def check_remux_space(self):
|
||||
limit = self.remux_folder_max_disk_usage
|
||||
try:
|
||||
limit = int(limit)
|
||||
except Exception as e:
|
||||
self.logger.debug(e)
|
||||
return
|
||||
|
||||
usage = self.getRemuxFolderUsage(self.REMUX_FOLDER)
|
||||
if usage > limit:
|
||||
files = os.listdir(self.REMUX_FOLDER)
|
||||
for file in files:
|
||||
fp = os.path.join(self.REMUX_FOLDER, file)
|
||||
os.unlink(fp)
|
||||
|
||||
|
||||
def getRemuxFolderUsage(self, start_path = "."):
|
||||
total_size = 0
|
||||
for dirpath, dirnames, filenames in os.walk(start_path):
|
||||
for f in filenames:
|
||||
fp = os.path.join(dirpath, f)
|
||||
if not os.path.islink(fp): # Skip if it is symbolic link
|
||||
total_size += os.path.getsize(fp)
|
||||
|
||||
return total_size
|
46
src/shellfm/windows/Path.py
Normal file
46
src/shellfm/windows/Path.py
Normal file
@ -0,0 +1,46 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Path:
|
||||
def get_path(self):
|
||||
return "/" + "/".join(self.path)
|
||||
|
||||
def get_path_list(self):
|
||||
return self.path
|
||||
|
||||
def push_to_path(self, dir):
|
||||
self.path.append(dir)
|
||||
self.load_directory()
|
||||
|
||||
def pop_from_path(self):
|
||||
self.path.pop()
|
||||
|
||||
if not self.go_past_home:
|
||||
if self.get_home() not in self.get_path():
|
||||
self.set_to_home()
|
||||
|
||||
self.load_directory()
|
||||
|
||||
|
||||
def set_path(self, path):
|
||||
self.path = list( filter(None, path.replace("\\", "/").split('/')) )
|
||||
self.load_directory()
|
||||
|
||||
def set_path_with_sub_path(self, sub_path):
|
||||
path = os.path.join(self.get_home(), sub_path)
|
||||
self.path = list( filter(None, path.replace("\\", "/").split('/')) )
|
||||
self.load_directory()
|
||||
|
||||
def set_to_home(self):
|
||||
home = os.path.expanduser("~") + self.subpath
|
||||
path = list( filter(None, home.replace("\\", "/").split('/')) )
|
||||
self.path = path
|
||||
self.load_directory()
|
||||
|
||||
def get_home(self):
|
||||
return os.path.expanduser("~") + self.subpath
|
39
src/shellfm/windows/Settings.py
Normal file
39
src/shellfm/windows/Settings.py
Normal file
@ -0,0 +1,39 @@
|
||||
# System import
|
||||
from os import path
|
||||
|
||||
|
||||
# Lib imports
|
||||
|
||||
|
||||
# Apoplication imports
|
||||
|
||||
|
||||
|
||||
class Settings:
|
||||
logger = None
|
||||
ABS_THUMBS_PTH = None # Used for thumbnail generation and is set by passing in
|
||||
REMUX_FOLDER = None # Used for Remuxed files and is set by passing in
|
||||
FFMPG_THUMBNLR = None # Used for thumbnail generator binary and is set by passing in
|
||||
HIDE_HIDDEN_FILES = True
|
||||
lock_folder = True
|
||||
go_past_home = False
|
||||
|
||||
subpath = "/LazyShare" # modify 'home' folder path
|
||||
locked_folders = "Synced Backup::::venv::::flasks".split("::::")
|
||||
mplayer_options = "-quiet -really-quiet -xy 1600 -geometry 50%:50%".split()
|
||||
music_app = "/opt/deadbeef/bin/deadbeef"
|
||||
media_app = "mpv"
|
||||
image_app = "mirage"
|
||||
office_app = "libreoffice"
|
||||
pdf_app = "evince"
|
||||
text_app = "leafpad"
|
||||
file_manager_app = "spacefm"
|
||||
remux_folder_max_disk_usage = "8589934592"
|
||||
|
||||
|
||||
fvideos = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
|
||||
foffice = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx', '.xlm', '.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf')
|
||||
fimages = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
|
||||
ftext = ('.txt', '.text', '.sh', '.cfg', '.conf')
|
||||
fmusic = ('.psf', '.mp3', '.ogg', '.flac', '.m4a')
|
||||
fpdf = ('.pdf')
|
159
src/shellfm/windows/View.py
Normal file
159
src/shellfm/windows/View.py
Normal file
@ -0,0 +1,159 @@
|
||||
# Python imports
|
||||
import hashlib
|
||||
import os
|
||||
from os import listdir
|
||||
from os.path import isdir, isfile, join
|
||||
|
||||
|
||||
# Lib imports
|
||||
|
||||
|
||||
# Application imports
|
||||
from . import Path, Settings, Launcher
|
||||
|
||||
|
||||
class View(Settings, Launcher, Path):
|
||||
def __init__(self):
|
||||
self.files = []
|
||||
self.dirs = []
|
||||
self.vids = []
|
||||
self.images = []
|
||||
self.desktop = []
|
||||
self.ungrouped = []
|
||||
|
||||
self.set_to_home()
|
||||
|
||||
def load_directory(self):
|
||||
path = self.get_path()
|
||||
self.dirs = []
|
||||
self.vids = []
|
||||
self.images = []
|
||||
self.desktop = []
|
||||
self.ungrouped = []
|
||||
self.files = []
|
||||
|
||||
if not isdir(path):
|
||||
self.set_to_home()
|
||||
return ""
|
||||
|
||||
for f in listdir(path):
|
||||
file = join(path, f)
|
||||
if self.HIDE_HIDDEN_FILES:
|
||||
if f.startswith('.'):
|
||||
continue
|
||||
|
||||
if isfile(file):
|
||||
lowerName = file.lower()
|
||||
if lowerName.endswith(self.fvideos):
|
||||
self.vids.append(f)
|
||||
elif lowerName.endswith(self.fimages):
|
||||
self.images.append(f)
|
||||
elif lowerName.endswith((".desktop",)):
|
||||
self.desktop.append(f)
|
||||
else:
|
||||
self.ungrouped.append(f)
|
||||
else:
|
||||
self.dirs.append(f)
|
||||
|
||||
self.dirs.sort()
|
||||
self.vids.sort()
|
||||
self.images.sort()
|
||||
self.desktop.sort()
|
||||
self.ungrouped.sort()
|
||||
|
||||
self.files = self.dirs + self.vids + self.images + self.desktop + self.ungrouped
|
||||
|
||||
def hashText(self, text):
|
||||
return hashlib.sha256(str.encode(text)).hexdigest()[:18]
|
||||
|
||||
def hashSet(self, arry):
|
||||
data = []
|
||||
for arr in arry:
|
||||
data.append([arr, self.hashText(arr)])
|
||||
return data
|
||||
|
||||
def get_path_part_from_hash(self, hash):
|
||||
files = self.get_files()
|
||||
file = None
|
||||
|
||||
for f in files:
|
||||
if hash == f[1]:
|
||||
file = f[0]
|
||||
break
|
||||
|
||||
return file
|
||||
|
||||
def get_files_formatted(self):
|
||||
files = self.hashSet(self.files),
|
||||
dirs = self.hashSet(self.dirs),
|
||||
videos = self.get_videos(),
|
||||
images = self.hashSet(self.images),
|
||||
desktops = self.hashSet(self.desktop),
|
||||
ungrouped = self.hashSet(self.ungrouped)
|
||||
|
||||
return {
|
||||
'path_head': self.get_path(),
|
||||
'list': {
|
||||
'files': files,
|
||||
'dirs': dirs,
|
||||
'videos': videos,
|
||||
'images': images,
|
||||
'desktops': desktops,
|
||||
'ungrouped': ungrouped
|
||||
}
|
||||
}
|
||||
|
||||
def is_folder_locked(self, hash):
|
||||
if self.lock_folder:
|
||||
path_parts = self.get_path().split('/')
|
||||
file = self.get_path_part_from_hash(hash)
|
||||
|
||||
# Insure chilren folders are locked too.
|
||||
lockedFolderInPath = False
|
||||
for folder in self.locked_folders:
|
||||
if folder in path_parts:
|
||||
lockedFolderInPath = True
|
||||
break
|
||||
|
||||
return (file in self.locked_folders or lockedFolderInPath)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def get_current_directory(self):
|
||||
return self.get_path()
|
||||
|
||||
def get_current_sub_path(self):
|
||||
path = self.get_path()
|
||||
home = self.get_home() + "/"
|
||||
return path.replace(home, "")
|
||||
|
||||
def get_dot_dots(self):
|
||||
return self.hashSet(['.', '..'])
|
||||
|
||||
def get_files(self):
|
||||
return self.hashSet(self.files)
|
||||
|
||||
def get_dirs(self):
|
||||
return self.hashSet(self.dirs)
|
||||
|
||||
def get_videos(self):
|
||||
videos_set = self.hashSet(self.vids)
|
||||
current_directory = self.get_current_directory()
|
||||
for video in videos_set:
|
||||
hashImgPth = join(self.ABS_THUMBS_PTH, video[1]) + ".jpg"
|
||||
if not os.path.exists(hashImgPth) :
|
||||
fullPath = join(current_directory, video[0])
|
||||
self.logger.debug(f"Hash Path: {hashImgPth}\nFile Path: {fullPath}")
|
||||
self.generateVideoThumbnail(fullPath, hashImgPth)
|
||||
|
||||
return videos_set
|
||||
|
||||
def get_images(self):
|
||||
return self.hashSet(self.images)
|
||||
|
||||
def get_desktops(self):
|
||||
return self.hashSet(self.desktop)
|
||||
|
||||
def get_ungrouped(self):
|
||||
return self.hashSet(self.ungrouped)
|
22
src/shellfm/windows/Window.py
Normal file
22
src/shellfm/windows/Window.py
Normal file
@ -0,0 +1,22 @@
|
||||
from .import View
|
||||
|
||||
|
||||
class Window:
|
||||
def __init__(self):
|
||||
self.name = ""
|
||||
self.nickname = ""
|
||||
self.id = 0
|
||||
self.views = []
|
||||
|
||||
def create_view(self):
|
||||
view = View()
|
||||
self.views.append(view)
|
||||
|
||||
def pop_view(self):
|
||||
self.views.pop()
|
||||
|
||||
def delete_view(self, index):
|
||||
del self.views[index]
|
||||
|
||||
def get_view(self, index):
|
||||
return self.views[index]
|
67
src/shellfm/windows/WindowController.py
Normal file
67
src/shellfm/windows/WindowController.py
Normal file
@ -0,0 +1,67 @@
|
||||
from . import Window
|
||||
|
||||
|
||||
class WindowController:
|
||||
def __init__(self):
|
||||
self.windows = []
|
||||
self.add_window()
|
||||
|
||||
def get_window(self, win_id):
|
||||
for window in self.windows:
|
||||
if window.id == win_id:
|
||||
return window
|
||||
|
||||
raise("No Window by ID {} found!".format(win_id))
|
||||
|
||||
def get_windows(self):
|
||||
return self.windows
|
||||
|
||||
def add_window(self):
|
||||
window = Window()
|
||||
window.id = len(self.windows) + 1
|
||||
window.name = "window_" + str(window.id)
|
||||
window.create_view()
|
||||
self.windows.append(window)
|
||||
|
||||
def add_view_for_window(self, win_id):
|
||||
for window in self.windows:
|
||||
if window.id == win_id:
|
||||
window.create_view()
|
||||
break
|
||||
|
||||
def pop_window(self):
|
||||
self.windows.pop()
|
||||
|
||||
def delete_window_by_id(self, win_id):
|
||||
i = 0
|
||||
for window in self.windows:
|
||||
if window.id == win_id:
|
||||
self.window.remove(win_id)
|
||||
break
|
||||
i += 1
|
||||
|
||||
def set_window_nickname(self, win_id = None, nickname = ""):
|
||||
for window in self.windows:
|
||||
if window.id == win_id:
|
||||
window.nickname = nickname
|
||||
|
||||
def list_windows(self):
|
||||
for window in self.windows:
|
||||
print("\n[ Window ]")
|
||||
print("ID: " + str(window.id))
|
||||
print("Name: " + window.name)
|
||||
print("Nickname: " + window.nickname)
|
||||
print("View Count: " + str( len(window.views) ))
|
||||
|
||||
|
||||
def list_views_from_window(self, win_id):
|
||||
for window in self.windows:
|
||||
if window.id == win_id:
|
||||
for view in window.views:
|
||||
print(view.files)
|
||||
break
|
||||
|
||||
def return_views_from_window(self, win_id):
|
||||
for window in self.windows:
|
||||
if window.id == win_id:
|
||||
return window.views
|
6
src/shellfm/windows/__init__.py
Normal file
6
src/shellfm/windows/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from .Settings import Settings
|
||||
from .Launcher import Launcher
|
||||
from .Path import Path
|
||||
from .View import View
|
||||
from .Window import Window
|
||||
from .WindowController import WindowController
|
Loading…
Reference in New Issue
Block a user