Initial commit.

This commit is contained in:
Maxim Stewart 2019-06-09 01:24:03 -05:00
parent 6078e87f35
commit b58e538cf3
48 changed files with 1925 additions and 0 deletions

12
README.md Normal file
View File

@ -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.

BIN
bin/pytop-0-0-1-x64.deb Normal file

Binary file not shown.

34
src/debs/build.sh Normal file
View File

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

6
src/debs/chownAll.sh Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
function main() {
sudo chown -R abaddon:abaddon .
}
main;

View File

@ -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.

View File

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

Binary file not shown.

View File

@ -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()

View File

@ -0,0 +1,339 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<requires lib="webkit2gtk" version="2.12"/>
<object class="GtkFileFilter" id="Folders">
<mime-types>
<mime-type>inode/directory</mime-type>
</mime-types>
</object>
<object class="GtkPopover" id="controlsWindow">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkEntry" id="renamerInput">
<property name="width_request">300</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_stock">gtk-edit</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label">gtk-copy</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-cut</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-paste</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="margin_left">65</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="webDropDown">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Show Mini Webbrowser</property>
<property name="stock">gtk-go-down</property>
<property name="icon_size">3</property>
</object>
<object class="GtkWindow" id="Window">
<property name="can_focus">False</property>
<property name="window_position">center</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
<property name="type_hint">desktop</property>
<property name="decorated">False</property>
<property name="gravity">center</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="width_request">256</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkSearchEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton" id="selectedDirDialog">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="action">select-folder</property>
<property name="filter">Folders</property>
<property name="title" translatable="yes">Directory Chooser</property>
<signal name="file-set" handler="setDir" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="popOutBttn">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">webDropDown</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="showWebview" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="loadProgress">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid" id="Desktop">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkPopover" id="webViewer">
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="relative_to">popOutBttn</property>
<property name="position">left</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label">gtk-home</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="loadHome" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="refreshPage" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkSearchEntry" id="webviewSearch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<signal name="key-release-event" handler="runSearchWebview" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="WebKitWebView" id="webview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="load-changed" handler="setUrlBar" swapped="no"/>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -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);
}

View File

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

View File

@ -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])

View File

@ -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()

View File

@ -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)

View File

@ -0,0 +1,4 @@
from utils.Dragging import Dragging
from utils.Settings import Settings
from utils.Icon import Icon
from utils.FileHandler import FileHandler

View File

@ -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
<http://www.gnu.org/copyleft/gpl.txt> for the terms of the latest version
of the GNU General Public License.

View File

@ -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()

View File

@ -0,0 +1,339 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<requires lib="webkit2gtk" version="2.12"/>
<object class="GtkFileFilter" id="Folders">
<mime-types>
<mime-type>inode/directory</mime-type>
</mime-types>
</object>
<object class="GtkPopover" id="controlsWindow">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkEntry" id="renamerInput">
<property name="width_request">300</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_stock">gtk-edit</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label">gtk-copy</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-cut</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-paste</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="margin_left">65</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="webDropDown">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Show Mini Webbrowser</property>
<property name="stock">gtk-go-down</property>
<property name="icon_size">3</property>
</object>
<object class="GtkWindow" id="Window">
<property name="can_focus">False</property>
<property name="window_position">center</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
<property name="type_hint">desktop</property>
<property name="decorated">False</property>
<property name="gravity">center</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="width_request">256</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkSearchEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton" id="selectedDirDialog">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="action">select-folder</property>
<property name="filter">Folders</property>
<property name="title" translatable="yes">Directory Chooser</property>
<signal name="file-set" handler="setDir" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="popOutBttn">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">webDropDown</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="showWebview" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="loadProgress">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid" id="Desktop">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkPopover" id="webViewer">
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="relative_to">popOutBttn</property>
<property name="position">left</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label">gtk-home</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="loadHome" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label">gtk-refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="refreshPage" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkSearchEntry" id="webviewSearch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<signal name="key-release-event" handler="runSearchWebview" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="WebKitWebView" id="webview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="load-changed" handler="setUrlBar" swapped="no"/>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -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);
}

View File

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

View File

@ -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])

View File

@ -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()

View File

@ -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)

View File

@ -0,0 +1,4 @@
from utils.Dragging import Dragging
from utils.Settings import Settings
from utils.Icon import Icon
from utils.FileHandler import FileHandler

View File

@ -0,0 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int main() {
chdir("/opt/Pytop/");
system("python3 PyTop.py");
return 0;
}

View File

@ -0,0 +1,6 @@
#!/bin/bash
function main() {
gcc -no-pie -s Pytop_exec_bin.cpp -o pytop
}
main;