diff --git a/README.md b/README.md new file mode 100644 index 0000000..7121b99 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# Pytop +Pytop is a Gtk + Python gui to have a custom desktop interface. + +# Notes +Need python 3 + +# TODO +Add file rename functionality. +Attach copy, cut, paste, and delete signals to the controls menu. +Add search functionality to the current directory. +Add a settings file to store values. +Improve icon detection for Steam. diff --git a/bin/pytop-0-0-1-x64.deb b/bin/pytop-0-0-1-x64.deb new file mode 100644 index 0000000..875ada8 Binary files /dev/null and b/bin/pytop-0-0-1-x64.deb differ diff --git a/src/debs/build.sh b/src/debs/build.sh new file mode 100644 index 0000000..48e85d7 --- /dev/null +++ b/src/debs/build.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Fixes ownershp +function main() { + sudo find . -type f -exec chmod 644 {} + + sudo find . -type d -exec chmod 755 {} + + + # Set postrm permissions + for i in `find . -name postrm`; do + sudo chmod 755 "${i}" + done + + # Set pytop permissions + for i in `find . -name pytop`; do + sudo chmod 755 "${i}" + done + + sudo chown -R root:root ./*/ + + builder; + bash ./chownAll.sh +} + +#builds debs +function builder() { + for i in `ls`; do + if [[ -d "${i}" ]]; then + dpkg --build "${i}" + else + echo "Not a dir." + fi + done +} +main; diff --git a/src/debs/chownAll.sh b/src/debs/chownAll.sh new file mode 100644 index 0000000..44bef62 --- /dev/null +++ b/src/debs/chownAll.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +function main() { + sudo chown -R abaddon:abaddon . +} +main; diff --git a/src/debs/pytop-0-0-1-x64/DEBIAN/control b/src/debs/pytop-0-0-1-x64/DEBIAN/control new file mode 100644 index 0000000..e22da34 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/DEBIAN/control @@ -0,0 +1,8 @@ +Package: pytop64 +Version: 0.0-1 +Section: python +Priority: optional +Architecture: amd64 +Depends: ffmpegthumbnailer (>= 2.0.10-0.1) +Maintainer: Maxim Stewart <1itdominator@gmail.com> +Description: Pytop is a custom desktop GUI. diff --git a/src/debs/pytop-0-0-1-x64/DEBIAN/postrm b/src/debs/pytop-0-0-1-x64/DEBIAN/postrm new file mode 100755 index 0000000..4962c4c --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/DEBIAN/postrm @@ -0,0 +1,11 @@ +#!/bin/bash +#postrm (script executed after uninstalling the package) +#set -e + +if [ -f /bin/pytop ]; then + rm /bin/pytop +fi + +if [ -d /opt/Pytop ]; then + rm -rf /opt/Pytop +fi diff --git a/src/debs/pytop-0-0-1-x64/bin/pytop b/src/debs/pytop-0-0-1-x64/bin/pytop new file mode 100755 index 0000000..9f3608f Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/bin/pytop differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/PyTop.py b/src/debs/pytop-0-0-1-x64/opt/Pytop/PyTop.py new file mode 100644 index 0000000..b49dd21 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/PyTop.py @@ -0,0 +1,181 @@ +#!/usr/bin/python3 + +# Gtk Imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') +gi.require_version('WebKit2', '4.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk +from gi.repository import GObject as gobject +from gi.repository import WebKit2 as webkit + + +# Python imports +import os, threading, subprocess, hashlib +from utils import Settings, Icon, FileHandler, Dragging +from os.path import isdir, isfile, join +from threading import Thread +from os import listdir + + +gdk.threads_init() + + +class Main: + def __init__(self): + # Needed for glade file load to work right... + webkit.WebView() + + self.builder = gtk.Builder() + self.filehandler = FileHandler() + self.settings = Settings() + # self.drag = Dragging() + self.settings.attachBuilder(self.builder) + self.builder.connect_signals(self) + + self.currentPath = "" + window = self.settings.createWindow() + self.usrHome = self.settings.returnUserHome() + self.desktopPath = self.settings.returnDesktopPath() + self.ColumnSize = self.settings.returnColumnSize() + self.desktop = self.builder.get_object("Desktop") + + # Add filter to allow only folders to be selected + self.loadProgress = self.builder.get_object("loadProgress") + selectedDirDialog = self.builder.get_object("selectedDirDialog") + filefilter = self.builder.get_object("Folders") + selectedDirDialog.add_filter(filefilter) + selectedDirDialog.set_filename(self.desktopPath) + self.setDir(selectedDirDialog) + + self.webview = self.builder.get_object("webview") + self.settings.setDefaultWebviewSettings(self.webview, self.webview.get_settings()) + self.webview.load_uri(self.settings.returnWebHome()) + + window.fullscreen() + window.show_all() + + + def setDir(self, widget, data=None): + self.currentPath = widget.get_filename() + self.getDirectoryList(self.currentPath) + # Thread(target=self.getDirectoryList, args=(self.currentPath,)).start() + + def getDirectoryList(self, dir): + dirs = ['.', '..'] + files = [] + + for f in listdir(dir): + file = join(dir, f) + if self.settings.isHideHiddenFiles(): + if f.startswith('.'): + continue + + if isfile(file): + files.append(f) + else: + dirs.append(f) + + dirs.sort() + files.sort() + + files = dirs + files + fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files) + tickCount = 0.0 + row = 0 + col = 0 + x = 0 + y = 0 + + self.loadProgress.set_text("Loading...") + self.loadProgress.set_fraction(0.0) + self.clear(self.desktop) + for file in files: + eveBox = Icon().createIcon(dir, file) + # self.drag.connectEvents(self.desktop, eveBox) + eveBox.connect("button_press_event", self.clickManager, (eveBox,)) + eveBox.connect("enter_notify_event", self.settings.mouseOver, ()) + eveBox.connect("leave_notify_event", self.settings.mouseOut, ()) + + gobject.idle_add(self.addToGrid, (self.desktop, eveBox, col, row,)) + tickCount = tickCount + fractionTick + self.loadProgress.set_fraction(tickCount) + + col += 1 + if col == self.ColumnSize: + col = 0 + row += 1 + + self.desktop.show_all() + self.loadProgress.set_text("Finished...") + + def addToGrid(self, args): + args[0].attach(args[1], args[2], args[3], 1, 1) + + def clickManager(self, widget, eve, params): + self.settings.setSelected(params[0]) + if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS: + box = widget.get_children()[0] + children = box.get_children() + fileName = children[1].get_text() + dir = self.currentPath + file = dir + "/" + fileName + + if fileName == ".": + self.getDirectoryList(dir) + elif fileName == "..": + parentDir = os.path.abspath(os.path.join(dir, os.pardir)) + self.currentPath = parentDir + self.getDirectoryList(parentDir) + elif isdir(file): + self.currentPath = file + self.getDirectoryList(file) + # Thread(target=self.getDirectoryList, args=(file,)).start() + else: + self.filehandler.openFile(file) + elif eve.type == gdk.EventType.BUTTON_PRESS and eve.button == 3: + box = widget.get_children()[0] + children = box.get_children() + + popover = self.builder.get_object("controlsWindow") + popover.set_relative_to(children[1]) + popover.set_position(gtk.PositionType.RIGHT) + popover.show_all() + + input = self.builder.get_object("renamerInput") + input.set_text(children[1].get_text()) + + popover.popup() + + + + def showWebview(self, widget): + self.builder.get_object("webViewer").popup() + + def loadHome(self, widget): + self.webview.load_uri(self.settings.returnWebHome()) + + def runSearchWebview(self, widget, data=None): + if data.keyval == 65293: + self.webview.load_uri(widget.get_text().strip()) + + def refreshPage(self, widget, data=None): + self.webview.load_uri(self.webview.get_uri()) + + def setUrlBar(self, widget, data=None): + self.builder.get_object("webviewSearch").set_text(widget.get_uri()) + + + def clear(self, object): + while True: + if object.get_child_at(0,0)!= None: + object.remove_row(0) + else: + break + + +if __name__ == "__main__": + main = Main() + gtk.main() diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/PyTop.glade b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/PyTop.glade new file mode 100644 index 0000000..1c7adfd --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/PyTop.glade @@ -0,0 +1,339 @@ + + + + + + + + inode/directory + + + + False + + + True + False + vertical + + + 300 + 26 + True + True + gtk-edit + + + False + True + 0 + + + + + True + False + + + gtk-copy + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cut + True + True + True + True + True + + + False + True + 1 + + + + + gtk-paste + True + True + True + True + True + + + False + True + 2 + + + + + gtk-delete + True + True + True + 65 + True + True + + + False + True + 3 + + + + + False + True + 1 + + + + + + + True + False + Show Mini Webbrowser + gtk-go-down + 3 + + + False + center + 800 + 600 + desktop + False + center + + + + + + 256 + True + False + vertical + + + True + False + + + True + True + edit-find-symbolic + False + False + + + True + True + 0 + + + + + True + False + select-folder + Folders + Directory Chooser + + + + False + True + 1 + + + + + True + True + True + webDropDown + True + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + + + False + True + 1 + + + + + True + True + in + + + True + False + + + True + False + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 2 + + + + + + + False + True + True + popOutBttn + left + + + True + False + vertical + + + True + False + + + gtk-home + True + True + True + True + True + + + + False + True + 0 + + + + + gtk-refresh + True + True + True + True + True + + + + False + True + 1 + + + + + True + True + edit-find-symbolic + False + False + + + + True + True + 2 + + + + + False + True + 0 + + + + + True + True + + + + + + + False + True + 1 + + + + + + diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/archive.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/archive.png new file mode 100644 index 0000000..7943e4e Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/archive.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/audio.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/audio.png new file mode 100644 index 0000000..c010134 Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/audio.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/bin.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/bin.png new file mode 100644 index 0000000..d6954e3 Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/bin.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/dir.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/dir.png new file mode 100644 index 0000000..a9b5e9f Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/dir.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/doc.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/doc.png new file mode 100644 index 0000000..f838826 Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/doc.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/pdf.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/pdf.png new file mode 100644 index 0000000..9f40122 Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/pdf.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/presentation.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/presentation.png new file mode 100644 index 0000000..3a339af Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/presentation.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/spreadsheet.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/spreadsheet.png new file mode 100644 index 0000000..710efa6 Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/spreadsheet.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/text.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/text.png new file mode 100644 index 0000000..2546fcd Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/text.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/video.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/video.png new file mode 100644 index 0000000..55afa98 Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/video.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/web.png b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/web.png new file mode 100644 index 0000000..17017ce Binary files /dev/null and b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/web.png differ diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/stylesheet.css b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/stylesheet.css new file mode 100644 index 0000000..5a93664 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/resources/stylesheet.css @@ -0,0 +1,13 @@ +viewport, +treeview, +treeview > header, +notebook > stack, +notebook > header { + background-color: rgba(0, 0, 0, 0.24); +} + + +notebook > header { + background-color: rgba(0, 0, 0, 0.24); + border-color: rgba(0, 232, 255, 0.64); +} diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Dragging.py b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Dragging.py new file mode 100644 index 0000000..a0b2856 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Dragging.py @@ -0,0 +1,79 @@ +import os, gi + +gi.require_version('Gdk', '3.0') + +from gi.repository import Gdk +from gi.repository import GObject + + +class Dragging: + def __init__(self): + # higher values make movement more performant + # lower values make movement smoother + self.SENSITIVITY = 1 + self.desktop = None + self.EvMask = Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON1_MOTION_MASK + self.offsetx = 0 + self.offsety = 0 + self.px = 0 + self.py = 0 + self.maxx = 0 + self.maxy = 0 + + def connectEvents(self, desktop, widget): + self.desktop = desktop + widget.set_events(self.EvMask) + widget.connect("button_press_event", self.press_event) + widget.connect("motion_notify_event", self.draggingEvent) + widget.show() + + def press_event(self, w, event): + if event.button == 1: + p = w.get_parent() + # offset == distance of parent widget from edge of screen ... + self.offsetx, self.offsety = p.get_window().get_position() + # plus distance from pointer to edge of widget + self.offsetx += event.x + self.offsety += event.y + # self.maxx, self.maxy both relative to the parent + # note that we're rounding down now so that these max values don't get + # rounded upward later and push the widget off the edge of its parent. + self.maxx = self.RoundDownToMultiple(p.get_allocation().width - w.get_allocation().width, self.SENSITIVITY) + self.maxy = self.RoundDownToMultiple(p.get_allocation().height - w.get_allocation().height, self.SENSITIVITY) + + + def draggingEvent(self, widget, event): + # x_root,x_root relative to screen + # x,y relative to parent (fixed widget) + # self.px,self.py stores previous values of x,y + + # get starting values for x,y + x = event.x_root - self.offsetx + y = event.y_root - self.offsety + # make sure the potential coordinates x,y: + # 1) will not push any part of the widget outside of its parent container + # 2) is a multiple of self.SENSITIVITY + x = self.RoundToNearestMultiple(self.Max(self.Min(x, self.maxx), 0), self.SENSITIVITY) + y = self.RoundToNearestMultiple(self.Max(self.Min(y, self.maxy), 0), self.SENSITIVITY) + if x != self.px or y != self.py: + self.px = x + self.py = y + self.desktop.move(widget, x, y) + + def Min(self, a, b): + if b < a: + return b + return a + + def Max(self, a, b): + if b > a: + return b + return a + + def RoundDownToMultiple(self, i, m): + return i/m*m + + def RoundToNearestMultiple(self, i, m): + if i % m > m / 2: + return (i/m+1)*m + return i/m*m diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/FileHandler.py b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/FileHandler.py new file mode 100644 index 0000000..ac387e0 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/FileHandler.py @@ -0,0 +1,42 @@ + +import subprocess + + +class FileHandler: + def __init__(self): + # 'Filters' + self.office = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx' '.xlm', '.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf') + self.vids = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm') + self.txt = ('.txt', '.text', '.sh', '.cfg', '.conf') + self.music = ('.psf', '.mp3', '.ogg' , '.flac') + self.images = ('.png', '.jpg', '.jpeg', '.gif') + self.pdf = ('.pdf') + + # Args + self.MEDIAPLAYER = "mpv"; + self.IMGVIEWER = "mirage"; + self.MUSICPLAYER = "/opt/deadbeef/bin/deadbeef"; + self.OFFICEPROG = "libreoffice"; + self.TEXTVIEWER = "leafpad"; + self.PDFVIEWER = "evince"; + self.FILEMANAGER = "spacefm"; + self.MPLAYER_WH = " -xy 1600 -geometry 50%:50% "; + self.MPV_WH = " -geometry 50%:50% "; + + + def openFile(self, file): + print("Opening: " + file) + if file.lower().endswith(self.vids): + subprocess.call([self.MEDIAPLAYER, self.MPV_WH, file]) + elif file.lower().endswith(self.music): + subprocess.call([self.MUSICPLAYER, file]) + elif file.lower().endswith(self.images): + subprocess.call([self.IMGVIEWER, file]) + elif file.lower().endswith(self.txt): + subprocess.call([self.TEXTVIEWER, file]) + elif file.lower().endswith(self.pdf): + subprocess.call([self.PDFVIEWER, file]) + elif file.lower().endswith(self.office): + subprocess.call([self.OFFICEPROG, file]) + else: + subprocess.call(['xdg-open', file]) diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Icon.py b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Icon.py new file mode 100644 index 0000000..55debe8 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Icon.py @@ -0,0 +1,96 @@ + +# Gtk Imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gio as gio +from gi.repository import GdkPixbuf + +import os, hashlib +from os.path import isdir, isfile, join + + +class Icon: + def __init__(self): + self.GTK_ORIENTATION = 1 # HORIZONTAL (0) VERTICAL (1) + self.iconImageWxH = [64, 64] + self.iconWxH = [128, -1] + self.iconMargins = 8 + self.usrHome = os.path.expanduser('~') + + + def createIcon(self, dir, file): + fullPathFile = dir + "/" + file + eveBox = gtk.EventBox() + icon = gtk.Box() + label = gtk.Label() + thumbnl = self.defineIconImage(file, fullPathFile) + + label.set_max_width_chars(1) + label.set_ellipsize(3) # ELLIPSIZE_END (3) + label.set_lines(2) + label.set_line_wrap(True) + label.set_line_wrap_mode(2) # WRAP_WORD (0) WRAP_CHAR (1) WRAP_WORD_CHAR (2) + label.set_width_chars(1) + label.set_text(file) + + icon.set_size_request(self.iconWxH[0], self.iconWxH[1]); + icon.set_property('orientation', self.GTK_ORIENTATION) + icon.add(thumbnl) + icon.add(label) + + eveBox.add(icon) + eveBox.show_all() + return eveBox + + def defineIconImage(self, file, fullPathFile): + thumbnl = gtk.Image() + vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm') + imagesList = ('.png', '.jpg', '.jpeg', '.gif') + + if file.lower().endswith(vidsList): + fileHash = hashlib.sha256(str.encode(fullPathFile)).hexdigest() + hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png" + if isfile(hashImgpth) == False: + self.generateThumbnail(fullPathFile, hashImgpth) + + thumbnl = self.createGtkImage(hashImgpth, self.iconImageWxH) + elif file.lower().endswith(imagesList): + thumbnl = self.createGtkImage(fullPathFile, self.iconImageWxH) + else: + thumbPth = self.getSystemThumbnail(fullPathFile, self.iconImageWxH[0]) + thumbnl = self.createGtkImage(thumbPth, self.iconImageWxH) + + return thumbnl + + def getSystemThumbnail(self, filename,size): + final_filename = "" + if os.path.exists(filename): + file = gio.File.new_for_path(filename) + info = file.query_info('standard::icon' , 0 , gio.Cancellable()) + icon = info.get_icon().get_names()[0] + + icon_theme = gtk.IconTheme.get_default() + icon_file = icon_theme.lookup_icon(icon , size , 0) + if icon_file != None: + final_filename = icon_file.get_filename() + + return final_filename + + def generateThumbnail(self, fullPathFile, hashImgpth): + subprocess.call(["ffmpegthumbnailer", "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPathFile, "-o", hashImgpth]) + + def createGtkImage(self, path, wxh): + try: + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale( + filename = path, + width = wxh[0], + height = wxh[1], + preserve_aspect_ratio = True) + return gtk.Image.new_from_pixbuf(pixbuf) + except Exception as e: + print(e) + + return gtk.Image() diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Settings.py b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Settings.py new file mode 100644 index 0000000..a114522 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Settings.py @@ -0,0 +1,154 @@ + +# Gtk Imports +import gi, cairo, os +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk + +class Settings: + def __init__(self): + self.builder = None + self.hoveredFile = None + self.selectedFile = None + + self.DEFAULTCOLOR = gdk.RGBA(0.0, 0.0, 0.0, 0.0) # ~#00000000 + self.MOUSEOVERCOLOR = gdk.RGBA(0.0, 0.9, 1.0, 0.64) # ~#00e8ff + self.SELECTEDCOLOR = gdk.RGBA(0.4, 0.5, 0.1, 0.84) + + self.hideHiddenFiles = True + self.usrHome = os.path.expanduser('~') + self.desktopPath = self.usrHome + "/Desktop" + self.ColumnSize = 10 + self.webHome = 'http://webfm.com/' + + + def attachBuilder(self, builder): + self.builder = builder + self.builder.add_from_file("resources/PyTop.glade") + + def createWindow(self): + # Get window and connect signals + window = self.builder.get_object("Window") + window.connect("delete-event", gtk.main_quit) + self.setWindowData(window) + return window + + def setWindowData(self, window): + screen = window.get_screen() + visual = screen.get_rgba_visual() + if visual != None and screen.is_composited(): + window.set_visual(visual) + + window.set_app_paintable(True) + window.connect("draw", self.area_draw) + monitors = self.getMonitorData(screen) + window.resize(monitors[0].width, monitors[0].height) + + def area_draw(self, widget, cr): + cr.set_source_rgba(0.0, 0.0, 0.0, 0.64) + cr.set_operator(cairo.OPERATOR_SOURCE) + cr.paint() + cr.set_operator(cairo.OPERATOR_OVER) + + def getMonitorData(self, screen): + monitors = [] + for m in range(screen.get_n_monitors()): + monitors.append(screen.get_monitor_geometry(m)) + + for monitor in monitors: + print(str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y)) + + return monitors + + def isHideHiddenFiles(self): + return self.hideHiddenFiles + + def returnUserHome(self): + return self.usrHome + + def returnDesktopPath(self): + return self.usrHome + "/Desktop" + + def returnColumnSize(self): + return self.ColumnSize + + def returnWebHome(self): + return self.webHome + + def mouseOver(self, widget, eve, args): + hand_cursor = gdk.Cursor(gdk.CursorType.HAND2) + self.builder.get_object("Window").get_window().set_cursor(hand_cursor) + if widget != self.selectedFile: + widget.override_background_color(gtk.StateType.NORMAL, self.MOUSEOVERCOLOR) + + def mouseOut(self, widget, eve, args): + watch_cursor = gdk.Cursor(gdk.CursorType.LEFT_PTR) + self.builder.get_object("Window").get_window().set_cursor(watch_cursor) + if widget != self.selectedFile: + widget.override_background_color(gtk.StateType.NORMAL, self.DEFAULTCOLOR) + + def setSelected(self, eveBox): + if self.selectedFile: + self.selectedFile.override_background_color(gtk.StateType.NORMAL, self.DEFAULTCOLOR) + + eveBox.override_background_color(gtk.StateType.NORMAL, self.SELECTEDCOLOR) + self.selectedFile = eveBox + + + + def setDefaultWebviewSettings(self, widget, settings=None): + # Usability + settings.set_property('enable-fullscreen', True) + settings.set_property('print-backgrounds', True) + settings.set_property('enable-frame-flattening', False) + settings.set_property('enable-plugins', True) + settings.set_property('enable-java', False) + settings.set_property('enable-resizable-text-areas', True) + settings.set_property('zoom-text-only', False) + settings.set_property('enable-smooth-scrolling', True) + settings.set_property('enable-back-forward-navigation-gestures', False) + settings.set_property('media-playback-requires-user-gesture', False) + settings.set_property('enable-tabs-to-links', True) + settings.set_property('enable-caret-browsing', False) + + # Security + settings.set_property('user-agent','Mozilla/5.0 (X11; Generic; Linux x86-64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Safari/605.1.15') + settings.set_property('enable-private-browsing', False) + settings.set_property('enable-xss-auditor', True) + settings.set_property('enable-hyperlink-auditing', False) + settings.set_property('enable-site-specific-quirks', True) + settings.set_property('enable-offline-web-application-cache', True) + settings.set_property('enable-page-cache', True) + settings.set_property('allow-modal-dialogs', False) + settings.set_property('enable-html5-local-storage', True) + settings.set_property('enable-html5-database', True) + settings.set_property('allow-file-access-from-file-urls', False) + settings.set_property('allow-universal-access-from-file-urls', False) + settings.set_property('enable-dns-prefetching', False) + + # Media stuff + # settings.set_property('hardware-acceleration-policy', 'on-demand') + settings.set_property('enable-webgl', False) + settings.set_property('enable-webaudio', True) + settings.set_property('enable-accelerated-2d-canvas', True) + settings.set_property('auto-load-images', True) + settings.set_property('enable-media-capabilities', True) + settings.set_property('enable-media-stream', True) + settings.set_property('enable-mediasource', True) + settings.set_property('enable-encrypted-media', True) + settings.set_property('media-playback-allows-inline', True) + + # JS + settings.set_property('enable-javascript', True) + settings.set_property('enable-javascript-markup', True) + settings.set_property('javascript-can-access-clipboard', False) + settings.set_property('javascript-can-open-windows-automatically', False) + + # Debugging + settings.set_property('enable-developer-extras', False) + settings.set_property('enable-write-console-messages-to-stdout', False) + settings.set_property('draw-compositing-indicators', False) + settings.set_property('enable-mock-capture-devices', False) + settings.set_property('enable-spatial-navigation', False) diff --git a/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/__init__.py b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/__init__.py new file mode 100644 index 0000000..d623701 --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/opt/Pytop/utils/__init__.py @@ -0,0 +1,4 @@ +from utils.Dragging import Dragging +from utils.Settings import Settings +from utils.Icon import Icon +from utils.FileHandler import FileHandler diff --git a/src/debs/pytop-0-0-1-x64/usr/share/doc/pytop/copyright b/src/debs/pytop-0-0-1-x64/usr/share/doc/pytop/copyright new file mode 100644 index 0000000..04b188e --- /dev/null +++ b/src/debs/pytop-0-0-1-x64/usr/share/doc/pytop/copyright @@ -0,0 +1,22 @@ +Pytop is copyright 2019 Maxim Stewart. +Pytop is currently developed by ITDominator <1itdominator@gmail.com>. + +License: GPLv2+ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +See /usr/share/common-licenses/GPL-2, or + for the terms of the latest version +of the GNU General Public License. diff --git a/src/versions/pytop-0.0.1/Pytop/PyTop.py b/src/versions/pytop-0.0.1/Pytop/PyTop.py new file mode 100755 index 0000000..b49dd21 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/PyTop.py @@ -0,0 +1,181 @@ +#!/usr/bin/python3 + +# Gtk Imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') +gi.require_version('WebKit2', '4.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk +from gi.repository import GObject as gobject +from gi.repository import WebKit2 as webkit + + +# Python imports +import os, threading, subprocess, hashlib +from utils import Settings, Icon, FileHandler, Dragging +from os.path import isdir, isfile, join +from threading import Thread +from os import listdir + + +gdk.threads_init() + + +class Main: + def __init__(self): + # Needed for glade file load to work right... + webkit.WebView() + + self.builder = gtk.Builder() + self.filehandler = FileHandler() + self.settings = Settings() + # self.drag = Dragging() + self.settings.attachBuilder(self.builder) + self.builder.connect_signals(self) + + self.currentPath = "" + window = self.settings.createWindow() + self.usrHome = self.settings.returnUserHome() + self.desktopPath = self.settings.returnDesktopPath() + self.ColumnSize = self.settings.returnColumnSize() + self.desktop = self.builder.get_object("Desktop") + + # Add filter to allow only folders to be selected + self.loadProgress = self.builder.get_object("loadProgress") + selectedDirDialog = self.builder.get_object("selectedDirDialog") + filefilter = self.builder.get_object("Folders") + selectedDirDialog.add_filter(filefilter) + selectedDirDialog.set_filename(self.desktopPath) + self.setDir(selectedDirDialog) + + self.webview = self.builder.get_object("webview") + self.settings.setDefaultWebviewSettings(self.webview, self.webview.get_settings()) + self.webview.load_uri(self.settings.returnWebHome()) + + window.fullscreen() + window.show_all() + + + def setDir(self, widget, data=None): + self.currentPath = widget.get_filename() + self.getDirectoryList(self.currentPath) + # Thread(target=self.getDirectoryList, args=(self.currentPath,)).start() + + def getDirectoryList(self, dir): + dirs = ['.', '..'] + files = [] + + for f in listdir(dir): + file = join(dir, f) + if self.settings.isHideHiddenFiles(): + if f.startswith('.'): + continue + + if isfile(file): + files.append(f) + else: + dirs.append(f) + + dirs.sort() + files.sort() + + files = dirs + files + fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files) + tickCount = 0.0 + row = 0 + col = 0 + x = 0 + y = 0 + + self.loadProgress.set_text("Loading...") + self.loadProgress.set_fraction(0.0) + self.clear(self.desktop) + for file in files: + eveBox = Icon().createIcon(dir, file) + # self.drag.connectEvents(self.desktop, eveBox) + eveBox.connect("button_press_event", self.clickManager, (eveBox,)) + eveBox.connect("enter_notify_event", self.settings.mouseOver, ()) + eveBox.connect("leave_notify_event", self.settings.mouseOut, ()) + + gobject.idle_add(self.addToGrid, (self.desktop, eveBox, col, row,)) + tickCount = tickCount + fractionTick + self.loadProgress.set_fraction(tickCount) + + col += 1 + if col == self.ColumnSize: + col = 0 + row += 1 + + self.desktop.show_all() + self.loadProgress.set_text("Finished...") + + def addToGrid(self, args): + args[0].attach(args[1], args[2], args[3], 1, 1) + + def clickManager(self, widget, eve, params): + self.settings.setSelected(params[0]) + if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS: + box = widget.get_children()[0] + children = box.get_children() + fileName = children[1].get_text() + dir = self.currentPath + file = dir + "/" + fileName + + if fileName == ".": + self.getDirectoryList(dir) + elif fileName == "..": + parentDir = os.path.abspath(os.path.join(dir, os.pardir)) + self.currentPath = parentDir + self.getDirectoryList(parentDir) + elif isdir(file): + self.currentPath = file + self.getDirectoryList(file) + # Thread(target=self.getDirectoryList, args=(file,)).start() + else: + self.filehandler.openFile(file) + elif eve.type == gdk.EventType.BUTTON_PRESS and eve.button == 3: + box = widget.get_children()[0] + children = box.get_children() + + popover = self.builder.get_object("controlsWindow") + popover.set_relative_to(children[1]) + popover.set_position(gtk.PositionType.RIGHT) + popover.show_all() + + input = self.builder.get_object("renamerInput") + input.set_text(children[1].get_text()) + + popover.popup() + + + + def showWebview(self, widget): + self.builder.get_object("webViewer").popup() + + def loadHome(self, widget): + self.webview.load_uri(self.settings.returnWebHome()) + + def runSearchWebview(self, widget, data=None): + if data.keyval == 65293: + self.webview.load_uri(widget.get_text().strip()) + + def refreshPage(self, widget, data=None): + self.webview.load_uri(self.webview.get_uri()) + + def setUrlBar(self, widget, data=None): + self.builder.get_object("webviewSearch").set_text(widget.get_uri()) + + + def clear(self, object): + while True: + if object.get_child_at(0,0)!= None: + object.remove_row(0) + else: + break + + +if __name__ == "__main__": + main = Main() + gtk.main() diff --git a/src/versions/pytop-0.0.1/Pytop/resources/PyTop.glade b/src/versions/pytop-0.0.1/Pytop/resources/PyTop.glade new file mode 100644 index 0000000..1c7adfd --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/resources/PyTop.glade @@ -0,0 +1,339 @@ + + + + + + + + inode/directory + + + + False + + + True + False + vertical + + + 300 + 26 + True + True + gtk-edit + + + False + True + 0 + + + + + True + False + + + gtk-copy + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cut + True + True + True + True + True + + + False + True + 1 + + + + + gtk-paste + True + True + True + True + True + + + False + True + 2 + + + + + gtk-delete + True + True + True + 65 + True + True + + + False + True + 3 + + + + + False + True + 1 + + + + + + + True + False + Show Mini Webbrowser + gtk-go-down + 3 + + + False + center + 800 + 600 + desktop + False + center + + + + + + 256 + True + False + vertical + + + True + False + + + True + True + edit-find-symbolic + False + False + + + True + True + 0 + + + + + True + False + select-folder + Folders + Directory Chooser + + + + False + True + 1 + + + + + True + True + True + webDropDown + True + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + + + False + True + 1 + + + + + True + True + in + + + True + False + + + True + False + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 2 + + + + + + + False + True + True + popOutBttn + left + + + True + False + vertical + + + True + False + + + gtk-home + True + True + True + True + True + + + + False + True + 0 + + + + + gtk-refresh + True + True + True + True + True + + + + False + True + 1 + + + + + True + True + edit-find-symbolic + False + False + + + + True + True + 2 + + + + + False + True + 0 + + + + + True + True + + + + + + + False + True + 1 + + + + + + diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/archive.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/archive.png new file mode 100644 index 0000000..7943e4e Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/archive.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/audio.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/audio.png new file mode 100644 index 0000000..c010134 Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/audio.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/bin.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/bin.png new file mode 100644 index 0000000..d6954e3 Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/bin.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/dir.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/dir.png new file mode 100644 index 0000000..a9b5e9f Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/dir.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/doc.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/doc.png new file mode 100644 index 0000000..f838826 Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/doc.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/pdf.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/pdf.png new file mode 100644 index 0000000..9f40122 Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/pdf.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/presentation.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/presentation.png new file mode 100644 index 0000000..3a339af Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/presentation.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/spreadsheet.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/spreadsheet.png new file mode 100644 index 0000000..710efa6 Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/spreadsheet.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/text.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/text.png new file mode 100644 index 0000000..2546fcd Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/text.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/video.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/video.png new file mode 100644 index 0000000..55afa98 Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/video.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/icons/web.png b/src/versions/pytop-0.0.1/Pytop/resources/icons/web.png new file mode 100644 index 0000000..17017ce Binary files /dev/null and b/src/versions/pytop-0.0.1/Pytop/resources/icons/web.png differ diff --git a/src/versions/pytop-0.0.1/Pytop/resources/stylesheet.css b/src/versions/pytop-0.0.1/Pytop/resources/stylesheet.css new file mode 100644 index 0000000..5a93664 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/resources/stylesheet.css @@ -0,0 +1,13 @@ +viewport, +treeview, +treeview > header, +notebook > stack, +notebook > header { + background-color: rgba(0, 0, 0, 0.24); +} + + +notebook > header { + background-color: rgba(0, 0, 0, 0.24); + border-color: rgba(0, 232, 255, 0.64); +} diff --git a/src/versions/pytop-0.0.1/Pytop/utils/Dragging.py b/src/versions/pytop-0.0.1/Pytop/utils/Dragging.py new file mode 100644 index 0000000..a0b2856 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/utils/Dragging.py @@ -0,0 +1,79 @@ +import os, gi + +gi.require_version('Gdk', '3.0') + +from gi.repository import Gdk +from gi.repository import GObject + + +class Dragging: + def __init__(self): + # higher values make movement more performant + # lower values make movement smoother + self.SENSITIVITY = 1 + self.desktop = None + self.EvMask = Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON1_MOTION_MASK + self.offsetx = 0 + self.offsety = 0 + self.px = 0 + self.py = 0 + self.maxx = 0 + self.maxy = 0 + + def connectEvents(self, desktop, widget): + self.desktop = desktop + widget.set_events(self.EvMask) + widget.connect("button_press_event", self.press_event) + widget.connect("motion_notify_event", self.draggingEvent) + widget.show() + + def press_event(self, w, event): + if event.button == 1: + p = w.get_parent() + # offset == distance of parent widget from edge of screen ... + self.offsetx, self.offsety = p.get_window().get_position() + # plus distance from pointer to edge of widget + self.offsetx += event.x + self.offsety += event.y + # self.maxx, self.maxy both relative to the parent + # note that we're rounding down now so that these max values don't get + # rounded upward later and push the widget off the edge of its parent. + self.maxx = self.RoundDownToMultiple(p.get_allocation().width - w.get_allocation().width, self.SENSITIVITY) + self.maxy = self.RoundDownToMultiple(p.get_allocation().height - w.get_allocation().height, self.SENSITIVITY) + + + def draggingEvent(self, widget, event): + # x_root,x_root relative to screen + # x,y relative to parent (fixed widget) + # self.px,self.py stores previous values of x,y + + # get starting values for x,y + x = event.x_root - self.offsetx + y = event.y_root - self.offsety + # make sure the potential coordinates x,y: + # 1) will not push any part of the widget outside of its parent container + # 2) is a multiple of self.SENSITIVITY + x = self.RoundToNearestMultiple(self.Max(self.Min(x, self.maxx), 0), self.SENSITIVITY) + y = self.RoundToNearestMultiple(self.Max(self.Min(y, self.maxy), 0), self.SENSITIVITY) + if x != self.px or y != self.py: + self.px = x + self.py = y + self.desktop.move(widget, x, y) + + def Min(self, a, b): + if b < a: + return b + return a + + def Max(self, a, b): + if b > a: + return b + return a + + def RoundDownToMultiple(self, i, m): + return i/m*m + + def RoundToNearestMultiple(self, i, m): + if i % m > m / 2: + return (i/m+1)*m + return i/m*m diff --git a/src/versions/pytop-0.0.1/Pytop/utils/FileHandler.py b/src/versions/pytop-0.0.1/Pytop/utils/FileHandler.py new file mode 100644 index 0000000..ac387e0 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/utils/FileHandler.py @@ -0,0 +1,42 @@ + +import subprocess + + +class FileHandler: + def __init__(self): + # 'Filters' + self.office = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx' '.xlm', '.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf') + self.vids = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm') + self.txt = ('.txt', '.text', '.sh', '.cfg', '.conf') + self.music = ('.psf', '.mp3', '.ogg' , '.flac') + self.images = ('.png', '.jpg', '.jpeg', '.gif') + self.pdf = ('.pdf') + + # Args + self.MEDIAPLAYER = "mpv"; + self.IMGVIEWER = "mirage"; + self.MUSICPLAYER = "/opt/deadbeef/bin/deadbeef"; + self.OFFICEPROG = "libreoffice"; + self.TEXTVIEWER = "leafpad"; + self.PDFVIEWER = "evince"; + self.FILEMANAGER = "spacefm"; + self.MPLAYER_WH = " -xy 1600 -geometry 50%:50% "; + self.MPV_WH = " -geometry 50%:50% "; + + + def openFile(self, file): + print("Opening: " + file) + if file.lower().endswith(self.vids): + subprocess.call([self.MEDIAPLAYER, self.MPV_WH, file]) + elif file.lower().endswith(self.music): + subprocess.call([self.MUSICPLAYER, file]) + elif file.lower().endswith(self.images): + subprocess.call([self.IMGVIEWER, file]) + elif file.lower().endswith(self.txt): + subprocess.call([self.TEXTVIEWER, file]) + elif file.lower().endswith(self.pdf): + subprocess.call([self.PDFVIEWER, file]) + elif file.lower().endswith(self.office): + subprocess.call([self.OFFICEPROG, file]) + else: + subprocess.call(['xdg-open', file]) diff --git a/src/versions/pytop-0.0.1/Pytop/utils/Icon.py b/src/versions/pytop-0.0.1/Pytop/utils/Icon.py new file mode 100644 index 0000000..55debe8 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/utils/Icon.py @@ -0,0 +1,96 @@ + +# Gtk Imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gio as gio +from gi.repository import GdkPixbuf + +import os, hashlib +from os.path import isdir, isfile, join + + +class Icon: + def __init__(self): + self.GTK_ORIENTATION = 1 # HORIZONTAL (0) VERTICAL (1) + self.iconImageWxH = [64, 64] + self.iconWxH = [128, -1] + self.iconMargins = 8 + self.usrHome = os.path.expanduser('~') + + + def createIcon(self, dir, file): + fullPathFile = dir + "/" + file + eveBox = gtk.EventBox() + icon = gtk.Box() + label = gtk.Label() + thumbnl = self.defineIconImage(file, fullPathFile) + + label.set_max_width_chars(1) + label.set_ellipsize(3) # ELLIPSIZE_END (3) + label.set_lines(2) + label.set_line_wrap(True) + label.set_line_wrap_mode(2) # WRAP_WORD (0) WRAP_CHAR (1) WRAP_WORD_CHAR (2) + label.set_width_chars(1) + label.set_text(file) + + icon.set_size_request(self.iconWxH[0], self.iconWxH[1]); + icon.set_property('orientation', self.GTK_ORIENTATION) + icon.add(thumbnl) + icon.add(label) + + eveBox.add(icon) + eveBox.show_all() + return eveBox + + def defineIconImage(self, file, fullPathFile): + thumbnl = gtk.Image() + vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm') + imagesList = ('.png', '.jpg', '.jpeg', '.gif') + + if file.lower().endswith(vidsList): + fileHash = hashlib.sha256(str.encode(fullPathFile)).hexdigest() + hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png" + if isfile(hashImgpth) == False: + self.generateThumbnail(fullPathFile, hashImgpth) + + thumbnl = self.createGtkImage(hashImgpth, self.iconImageWxH) + elif file.lower().endswith(imagesList): + thumbnl = self.createGtkImage(fullPathFile, self.iconImageWxH) + else: + thumbPth = self.getSystemThumbnail(fullPathFile, self.iconImageWxH[0]) + thumbnl = self.createGtkImage(thumbPth, self.iconImageWxH) + + return thumbnl + + def getSystemThumbnail(self, filename,size): + final_filename = "" + if os.path.exists(filename): + file = gio.File.new_for_path(filename) + info = file.query_info('standard::icon' , 0 , gio.Cancellable()) + icon = info.get_icon().get_names()[0] + + icon_theme = gtk.IconTheme.get_default() + icon_file = icon_theme.lookup_icon(icon , size , 0) + if icon_file != None: + final_filename = icon_file.get_filename() + + return final_filename + + def generateThumbnail(self, fullPathFile, hashImgpth): + subprocess.call(["ffmpegthumbnailer", "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPathFile, "-o", hashImgpth]) + + def createGtkImage(self, path, wxh): + try: + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale( + filename = path, + width = wxh[0], + height = wxh[1], + preserve_aspect_ratio = True) + return gtk.Image.new_from_pixbuf(pixbuf) + except Exception as e: + print(e) + + return gtk.Image() diff --git a/src/versions/pytop-0.0.1/Pytop/utils/Settings.py b/src/versions/pytop-0.0.1/Pytop/utils/Settings.py new file mode 100644 index 0000000..a114522 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/utils/Settings.py @@ -0,0 +1,154 @@ + +# Gtk Imports +import gi, cairo, os +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk as gtk +from gi.repository import Gdk as gdk + +class Settings: + def __init__(self): + self.builder = None + self.hoveredFile = None + self.selectedFile = None + + self.DEFAULTCOLOR = gdk.RGBA(0.0, 0.0, 0.0, 0.0) # ~#00000000 + self.MOUSEOVERCOLOR = gdk.RGBA(0.0, 0.9, 1.0, 0.64) # ~#00e8ff + self.SELECTEDCOLOR = gdk.RGBA(0.4, 0.5, 0.1, 0.84) + + self.hideHiddenFiles = True + self.usrHome = os.path.expanduser('~') + self.desktopPath = self.usrHome + "/Desktop" + self.ColumnSize = 10 + self.webHome = 'http://webfm.com/' + + + def attachBuilder(self, builder): + self.builder = builder + self.builder.add_from_file("resources/PyTop.glade") + + def createWindow(self): + # Get window and connect signals + window = self.builder.get_object("Window") + window.connect("delete-event", gtk.main_quit) + self.setWindowData(window) + return window + + def setWindowData(self, window): + screen = window.get_screen() + visual = screen.get_rgba_visual() + if visual != None and screen.is_composited(): + window.set_visual(visual) + + window.set_app_paintable(True) + window.connect("draw", self.area_draw) + monitors = self.getMonitorData(screen) + window.resize(monitors[0].width, monitors[0].height) + + def area_draw(self, widget, cr): + cr.set_source_rgba(0.0, 0.0, 0.0, 0.64) + cr.set_operator(cairo.OPERATOR_SOURCE) + cr.paint() + cr.set_operator(cairo.OPERATOR_OVER) + + def getMonitorData(self, screen): + monitors = [] + for m in range(screen.get_n_monitors()): + monitors.append(screen.get_monitor_geometry(m)) + + for monitor in monitors: + print(str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y)) + + return monitors + + def isHideHiddenFiles(self): + return self.hideHiddenFiles + + def returnUserHome(self): + return self.usrHome + + def returnDesktopPath(self): + return self.usrHome + "/Desktop" + + def returnColumnSize(self): + return self.ColumnSize + + def returnWebHome(self): + return self.webHome + + def mouseOver(self, widget, eve, args): + hand_cursor = gdk.Cursor(gdk.CursorType.HAND2) + self.builder.get_object("Window").get_window().set_cursor(hand_cursor) + if widget != self.selectedFile: + widget.override_background_color(gtk.StateType.NORMAL, self.MOUSEOVERCOLOR) + + def mouseOut(self, widget, eve, args): + watch_cursor = gdk.Cursor(gdk.CursorType.LEFT_PTR) + self.builder.get_object("Window").get_window().set_cursor(watch_cursor) + if widget != self.selectedFile: + widget.override_background_color(gtk.StateType.NORMAL, self.DEFAULTCOLOR) + + def setSelected(self, eveBox): + if self.selectedFile: + self.selectedFile.override_background_color(gtk.StateType.NORMAL, self.DEFAULTCOLOR) + + eveBox.override_background_color(gtk.StateType.NORMAL, self.SELECTEDCOLOR) + self.selectedFile = eveBox + + + + def setDefaultWebviewSettings(self, widget, settings=None): + # Usability + settings.set_property('enable-fullscreen', True) + settings.set_property('print-backgrounds', True) + settings.set_property('enable-frame-flattening', False) + settings.set_property('enable-plugins', True) + settings.set_property('enable-java', False) + settings.set_property('enable-resizable-text-areas', True) + settings.set_property('zoom-text-only', False) + settings.set_property('enable-smooth-scrolling', True) + settings.set_property('enable-back-forward-navigation-gestures', False) + settings.set_property('media-playback-requires-user-gesture', False) + settings.set_property('enable-tabs-to-links', True) + settings.set_property('enable-caret-browsing', False) + + # Security + settings.set_property('user-agent','Mozilla/5.0 (X11; Generic; Linux x86-64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Safari/605.1.15') + settings.set_property('enable-private-browsing', False) + settings.set_property('enable-xss-auditor', True) + settings.set_property('enable-hyperlink-auditing', False) + settings.set_property('enable-site-specific-quirks', True) + settings.set_property('enable-offline-web-application-cache', True) + settings.set_property('enable-page-cache', True) + settings.set_property('allow-modal-dialogs', False) + settings.set_property('enable-html5-local-storage', True) + settings.set_property('enable-html5-database', True) + settings.set_property('allow-file-access-from-file-urls', False) + settings.set_property('allow-universal-access-from-file-urls', False) + settings.set_property('enable-dns-prefetching', False) + + # Media stuff + # settings.set_property('hardware-acceleration-policy', 'on-demand') + settings.set_property('enable-webgl', False) + settings.set_property('enable-webaudio', True) + settings.set_property('enable-accelerated-2d-canvas', True) + settings.set_property('auto-load-images', True) + settings.set_property('enable-media-capabilities', True) + settings.set_property('enable-media-stream', True) + settings.set_property('enable-mediasource', True) + settings.set_property('enable-encrypted-media', True) + settings.set_property('media-playback-allows-inline', True) + + # JS + settings.set_property('enable-javascript', True) + settings.set_property('enable-javascript-markup', True) + settings.set_property('javascript-can-access-clipboard', False) + settings.set_property('javascript-can-open-windows-automatically', False) + + # Debugging + settings.set_property('enable-developer-extras', False) + settings.set_property('enable-write-console-messages-to-stdout', False) + settings.set_property('draw-compositing-indicators', False) + settings.set_property('enable-mock-capture-devices', False) + settings.set_property('enable-spatial-navigation', False) diff --git a/src/versions/pytop-0.0.1/Pytop/utils/__init__.py b/src/versions/pytop-0.0.1/Pytop/utils/__init__.py new file mode 100644 index 0000000..d623701 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop/utils/__init__.py @@ -0,0 +1,4 @@ +from utils.Dragging import Dragging +from utils.Settings import Settings +from utils.Icon import Icon +from utils.FileHandler import FileHandler diff --git a/src/versions/pytop-0.0.1/Pytop_exec_bin.cpp b/src/versions/pytop-0.0.1/Pytop_exec_bin.cpp new file mode 100644 index 0000000..93af3d7 --- /dev/null +++ b/src/versions/pytop-0.0.1/Pytop_exec_bin.cpp @@ -0,0 +1,10 @@ +#include +#include +#include +using namespace std; + +int main() { + chdir("/opt/Pytop/"); + system("python3 PyTop.py"); +return 0; +} diff --git a/src/versions/pytop-0.0.1/compileBin.sh b/src/versions/pytop-0.0.1/compileBin.sh new file mode 100755 index 0000000..a5cbb77 --- /dev/null +++ b/src/versions/pytop-0.0.1/compileBin.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +function main() { + gcc -no-pie -s Pytop_exec_bin.cpp -o pytop +} +main;