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 @@
+
+
+
+
+
+
+
+
+ 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;