Added debs builder
12
src/clear_pycache_dirs.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
# set -o xtrace ## To debug scripts
|
||||
# set -o errexit ## To exit on error
|
||||
# set -o errunset ## To exit if a variable is referenced but not set
|
||||
|
||||
|
||||
function main() {
|
||||
find . -name "__pycache__" -exec rm -rf $1 {} \;
|
||||
find . -name "*.pyc" -exec rm -rf $1 {} \;
|
||||
}
|
||||
main
|
34
src/debs/build.sh
Normal 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
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
function main() {
|
||||
sudo chown -R abaddon:abaddon .
|
||||
}
|
||||
main;
|
8
src/debs/pytop-0-0-1-x64/DEBIAN/control
Normal file
@ -0,0 +1,8 @@
|
||||
Package: pytop64
|
||||
Version: 0.0-1
|
||||
Section: python
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
Depends: python3, wget, steamcmd, ffmpegthumbnailer (>= 2.0.10-0.1), gir1.2-wnck-1.0
|
||||
Maintainer: Maxim Stewart <1itdominator@gmail.com>
|
||||
Description: Pytop is a custom desktop GUI.
|
11
src/debs/pytop-0-0-1-x64/DEBIAN/postrm
Executable 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
|
BIN
src/debs/pytop-0-0-1-x64/bin/pytop
Executable file
73
src/debs/pytop-0-0-1-x64/opt/Pytop/__init__.py
Normal file
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
# Python imports
|
||||
import inspect
|
||||
|
||||
from setproctitle import setproctitle
|
||||
|
||||
# Gtk imports
|
||||
import gi, faulthandler, signal
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk as gtk
|
||||
from gi.repository import Gdk as gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from utils import Settings
|
||||
from signal_classes import Signals
|
||||
|
||||
|
||||
class Main:
|
||||
def __init__(self, args):
|
||||
setproctitle('Pytop')
|
||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
|
||||
faulthandler.enable() # For better debug info
|
||||
|
||||
builder = gtk.Builder()
|
||||
settings = Settings()
|
||||
settings.attachBuilder(builder)
|
||||
self.connectBuilder(settings, builder)
|
||||
|
||||
window = settings.createWindow()
|
||||
window.fullscreen()
|
||||
window.show()
|
||||
|
||||
monitors = settings.returnMonitorsInfo()
|
||||
i = 1
|
||||
if len(monitors) > 1:
|
||||
for mon in monitors[1:]:
|
||||
subBuilder = gtk.Builder()
|
||||
subSettings = Settings(i)
|
||||
subSettings.attachBuilder(subBuilder)
|
||||
self.connectBuilder(subSettings, subBuilder)
|
||||
|
||||
win = subSettings.createWindow()
|
||||
win.set_default_size(mon.width, mon.height)
|
||||
win.set_size_request(mon.width, mon.height)
|
||||
win.set_resizable(False)
|
||||
win.move(mon.x, mon.y)
|
||||
|
||||
win.show()
|
||||
i += 1
|
||||
|
||||
|
||||
def connectBuilder(self, settings, builder):
|
||||
# Gets the methods from the classes and sets to handler.
|
||||
# Then, builder connects to any signals it needs.
|
||||
classes = [Signals(settings)]
|
||||
|
||||
handlers = {}
|
||||
for c in classes:
|
||||
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
||||
handlers.update(methods)
|
||||
|
||||
builder.connect_signals(handlers)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main = Main()
|
||||
gtk.main()
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
35
src/debs/pytop-0-0-1-x64/opt/Pytop/__main__.py
Normal file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
|
||||
# Python imports
|
||||
import argparse
|
||||
import pdb # For trace debugging
|
||||
from setproctitle import setproctitle
|
||||
|
||||
# Gtk imports
|
||||
import gi, faulthandler, signal
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk as gtk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from __init__ import Main
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# pdb.set_trace()
|
||||
setproctitle('Pytop')
|
||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
|
||||
faulthandler.enable() # For better debug info
|
||||
parser = argparse.ArgumentParser()
|
||||
# Add long and short arguments
|
||||
parser.add_argument("--file", "-f", default="default", help="JUST SOME FILE ARG.")
|
||||
|
||||
# Read arguments (If any...)
|
||||
args = parser.parse_args()
|
||||
main = Main(args)
|
||||
gtk.main()
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
849
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/Main_Window.glade
Normal file
@ -0,0 +1,849 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkFileFilter" id="Folders">
|
||||
<mime-types>
|
||||
<mime-type>inode/directory</mime-type>
|
||||
</mime-types>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="brushSizeProp">
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="value">1</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
<signal name="value-changed" handler="onBrushSizeChange" swapped="no"/>
|
||||
</object>
|
||||
<object class="GtkImage" id="createImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-new</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="menuImage">
|
||||
<property name="width_request">64</property>
|
||||
<property name="height_request">64</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="pixbuf">start_menu_icons/start_menu_icon2_32x32.png</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="Window">
|
||||
<property name="can_focus">False</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" id="box1">
|
||||
<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="GtkButton" id="progMenu">
|
||||
<property name="label" translatable="yes">Menu</property>
|
||||
<property name="width_request">64</property>
|
||||
<property name="height_request">64</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="image">menuImage</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="toggleProgramMenu" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="center">
|
||||
<object class="GtkButtonBox" id="taskBarWorkspacesVer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">start</property>
|
||||
<signal name="button-release-event" handler="showSystemStats" swapped="no"/>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="center">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFileChooserButton" id="selectDirDialog">
|
||||
<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="setNewDirectory" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</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="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<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="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkIconView" id="Desktop">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin">6</property>
|
||||
<property name="selection_mode">multiple</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width_request">180</property>
|
||||
<property name="height_request">64</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<property name="max_content_width">225</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="taskBarButtonsVer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="height_request">64</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="vscrollbar_policy">never</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="GtkBox" id="taskBarButtonsHor">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox" id="taskBarWorkspacesHor">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">start</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="timeLabelEveBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="above_child">True</property>
|
||||
<signal name="button-release-event" handler="toggleCalPopover" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkLabel" id="timeLabel">
|
||||
<property name="width_request">126</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="track_visited_links">False</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="1.5"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
</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">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkPopover" id="calendarPopup">
|
||||
<property name="width_request">420</property>
|
||||
<property name="height_request">225</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="relative_to">timeLabelEveBox</property>
|
||||
<property name="modal">False</property>
|
||||
<child>
|
||||
<object class="GtkCalendar" id="calendarWid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="year">2020</property>
|
||||
<property name="month">3</property>
|
||||
<property name="day">22</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkPopover" id="systemStats">
|
||||
<property name="width_request">500</property>
|
||||
<property name="height_request">0</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="relative_to">taskBarWorkspacesVer</property>
|
||||
<property name="position">bottom</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="brushColorProp">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_alpha">True</property>
|
||||
<property name="rgba">rgb(138,226,52)</property>
|
||||
<signal name="color-set" handler="onColorSet" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="drawArea">
|
||||
<property name="height_request">60</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="configure-event" handler="onConfigure" swapped="no"/>
|
||||
<signal name="draw" handler="onDraw" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">brushSizeProp</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkApplicationWindow" id="menuWindow">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">400</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">4</property>
|
||||
<property name="window_position">mouse</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="skip_pager_hint">True</property>
|
||||
<property name="decorated">False</property>
|
||||
<property name="deletable">False</property>
|
||||
<property name="gravity">center</property>
|
||||
<property name="has_resize_grip">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="searchProgramsEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="has_focus">True</property>
|
||||
<property name="has_default">True</property>
|
||||
<property name="receives_default">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="search-changed" handler="searchForEntry" swapped="no"/>
|
||||
</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="GtkButtonBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="layout_style">start</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Accessories</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Multimedia</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Graphics</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Game</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Office</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Development</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Internet</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Settings</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">System</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Wine</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Other</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="setListGroup" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">10</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="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="hscrollbar_policy">never</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="programListBttns">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="row_homogeneous">True</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>
|
||||
<style>
|
||||
<class name="menu_scroller"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="trashImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="pixbuf">icons/trash.png</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="iconControlsWindow">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">splashscreen</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="skip_pager_hint">True</property>
|
||||
<property name="decorated">False</property>
|
||||
<property name="deletable">False</property>
|
||||
<property name="gravity">center</property>
|
||||
<signal name="focus-out-event" handler="closePopup" swapped="no"/>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="width_request">500</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="filenameInput">
|
||||
<property name="width_request">500</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>
|
||||
<signal name="key-release-event" handler="rename" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="iconsButtonBox">
|
||||
<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="tooltip_text" translatable="yes">Copy...</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="copy" 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-cut</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Cut...</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="cut" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="center">
|
||||
<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="tooltip_text" translatable="yes">Delete...</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="delete" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Trash</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Move to Trash...</property>
|
||||
<property name="image">trashImage</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="trash" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</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>
|
||||
<child>
|
||||
<object class="GtkBox" id="menuButtonBox">
|
||||
<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="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">15</property>
|
||||
<property name="label" translatable="yes">Folder</property>
|
||||
<attributes>
|
||||
<attribute name="size" value="12000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">15</property>
|
||||
<property name="label" translatable="yes">File</property>
|
||||
<attributes>
|
||||
<attribute name="size" value="12000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</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="GtkSwitch" id="createSwitch">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">File/Folder</property>
|
||||
<property name="active">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" translatable="yes">Create</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Create File/Folder...</property>
|
||||
<property name="image">createImage</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="create" swapped="no"/>
|
||||
</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-paste</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Paste...</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="paste" swapped="no"/>
|
||||
</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">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/archive.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/audio.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/bin.png
Normal file
After Width: | Height: | Size: 858 B |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/dir.png
Normal file
After Width: | Height: | Size: 850 B |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/doc.png
Normal file
After Width: | Height: | Size: 702 B |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/pdf.png
Normal file
After Width: | Height: | Size: 925 B |
After Width: | Height: | Size: 882 B |
After Width: | Height: | Size: 707 B |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/text.png
Normal file
After Width: | Height: | Size: 798 B |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/trash.png
Normal file
After Width: | Height: | Size: 989 B |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/video.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/icons/web.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 15 KiB |
96
src/debs/pytop-0-0-1-x64/opt/Pytop/resources/stylesheet.css
Normal file
@ -0,0 +1,96 @@
|
||||
/* Menu css properties */
|
||||
.menu_scroller label {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
|
||||
/* Grid css properties */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
box,
|
||||
iconview {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
treeview,
|
||||
treeview.view {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
cell {
|
||||
margin: 0em;
|
||||
padding: 0em;
|
||||
/* float: left; */
|
||||
}
|
||||
|
||||
cell:focus {
|
||||
outline-style: solid;
|
||||
outline-color: rgba(0, 232, 255, 0.64);
|
||||
}
|
||||
|
||||
|
||||
/* Ivonview and children default color */
|
||||
.view {
|
||||
background-color: rgba(0, 0, 0, 0.22);
|
||||
color: #ebebeb;
|
||||
}
|
||||
|
||||
|
||||
/* Hover over color when not selected */
|
||||
.view:hover {
|
||||
box-shadow: inset 0 0 0 9999px alpha(rgba(0, 232, 255, 0.64), 0.54);
|
||||
}
|
||||
|
||||
/* Handles the icon selection hover and selected hover color. */
|
||||
.view:selected,
|
||||
.view:selected:hover {
|
||||
box-shadow: inset 0 0 0 9999px rgba(15, 134, 13, 0.49);
|
||||
}
|
||||
|
||||
/* Rubberband coloring */
|
||||
.rubberband,
|
||||
rubberband,
|
||||
flowbox rubberband,
|
||||
treeview.view rubberband,
|
||||
.content-view rubberband,
|
||||
.content-view .rubberband,
|
||||
XfdesktopIconView.view .rubberband {
|
||||
border: 1px solid #6c6c6c;
|
||||
background-color: rgba(21, 158, 167, 0.57);
|
||||
}
|
||||
|
||||
XfdesktopIconView.view:active {
|
||||
background-color: rgba(172, 102, 21, 1);
|
||||
}
|
||||
|
||||
|
||||
XfdesktopIconView.view {
|
||||
border-radius: 4px;
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
|
||||
}
|
||||
|
||||
XfdesktopIconView.view:active {
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
XfdesktopIconView.view .rubberband {
|
||||
border-radius: 0;
|
||||
}
|
89
src/debs/pytop-0-0-1-x64/opt/Pytop/signal_classes/Signals.py
Normal file
@ -0,0 +1,89 @@
|
||||
# Python imports
|
||||
from datetime import datetime
|
||||
import os
|
||||
|
||||
# Gtk imports
|
||||
|
||||
|
||||
# Application imports
|
||||
from .mixins import CPUDrawMixin, MainMenuMixin, TaskbarMixin, GridMixin
|
||||
from widgets import Grid
|
||||
from widgets import Icon
|
||||
from utils import FileHandler
|
||||
|
||||
|
||||
|
||||
class Signals(CPUDrawMixin, MainMenuMixin, TaskbarMixin, GridMixin):
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
self.builder = self.settings.returnBuilder()
|
||||
|
||||
self.timeLabel = self.builder.get_object("timeLabel")
|
||||
self.drawArea = self.builder.get_object("drawArea")
|
||||
self.brushSizeProp = self.builder.get_object("brushSizeProp")
|
||||
self.brushColorProp = self.builder.get_object("brushColorProp")
|
||||
|
||||
# Menu bar setup - Note: Must be before setting clock
|
||||
self.orientation = 1 # 0 = horizontal, 1 = vertical
|
||||
self.setPagerWidget()
|
||||
self.setTasklistWidget()
|
||||
|
||||
# Must be after pager and task list inits
|
||||
self.displayclock()
|
||||
self.startClock()
|
||||
|
||||
# CPUDrawMixin Parts
|
||||
self.cpu_percents = []
|
||||
self.doDrawBackground = False
|
||||
self.isDrawing = False
|
||||
self.surface = None
|
||||
self.aw = None # Draw area width
|
||||
self.ah = None # Draw area height
|
||||
self.xStep = None # For x-axis 60 sec steps
|
||||
self.yStep = None # For y-axis %s
|
||||
|
||||
rgba = self.brushColorProp.get_rgba()
|
||||
self.brushColorVal = [rgba.red, rgba.green, rgba.blue, rgba.alpha]
|
||||
self.brushSizeVal = self.brushSizeProp.get_value()
|
||||
self.updateSpeed = 100 # 1 sec = 1000ms
|
||||
|
||||
self.good = [0.53, 0.8, 0.15, 1.0]
|
||||
self.warning = [1.0, 0.66, 0.0, 1.0]
|
||||
self.danger = [1.0, 0.0, 0.0, 1.0]
|
||||
|
||||
|
||||
# GridMixin Parts
|
||||
self.filehandler = FileHandler(settings)
|
||||
|
||||
self.builder = self.settings.returnBuilder()
|
||||
self.gridObj = self.builder.get_object("Desktop")
|
||||
selectDirDialog = self.builder.get_object("selectDirDialog")
|
||||
filefilter = self.builder.get_object("Folders")
|
||||
|
||||
self.currentPath = self.settings.returnSettings()[0]
|
||||
self.copyCutArry = []
|
||||
self.selectedFiles = []
|
||||
self.gridClss = Grid(self.gridObj, self.settings)
|
||||
self.pasteType = 1 # copy == 1 and cut == 2
|
||||
|
||||
|
||||
# Add filter to allow only folders to be selected
|
||||
selectDirDialog.add_filter(filefilter)
|
||||
selectDirDialog.set_filename(self.currentPath)
|
||||
self.setNewDirectory(selectDirDialog)
|
||||
|
||||
|
||||
# Program Menu Parts
|
||||
self.menuWindow = self.builder.get_object("menuWindow")
|
||||
self.menuWindow.set_keep_above(True);
|
||||
self.showIcons = False
|
||||
|
||||
self.iconFactory = Icon(self.settings)
|
||||
self.grpDefault = "Accessories"
|
||||
self.progGroup = self.grpDefault
|
||||
HOME_APPS = os.path.expanduser('~') + "/.local/share/applications/"
|
||||
paths = ["/opt/", "/usr/share/applications/", HOME_APPS]
|
||||
self.menuData = self.getDesktopFilesInfo(paths)
|
||||
self.desktopObjs = []
|
||||
self.getSubgroup()
|
||||
self.generateListView()
|
@ -0,0 +1,4 @@
|
||||
from .mixins import CPUDrawMixin
|
||||
from .mixins import TaskbarMixin
|
||||
from .mixins import GridMixin
|
||||
from signal_classes.Signals import Signals
|
@ -0,0 +1,129 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
|
||||
# Python Imports
|
||||
from __future__ import division
|
||||
import cairo, psutil
|
||||
|
||||
|
||||
# GTK Imports
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class CPUDrawMixin:
|
||||
# Note: y-axis on draw area goes from top to bottom when increasing.
|
||||
# Need to do the math such that you subtract from max height to start from bottom to go up
|
||||
# self.linePoints.append([1 * xStep, ah - (23 * yStep)]) # 23%
|
||||
# self.linePoints.append([2 * xStep, ah - (60 * yStep)]) # 60%
|
||||
# self.drawPointLine()
|
||||
# del self.linePoints[0:1]
|
||||
# self.linePoints.append([3 * xStep, ah - (44 * yStep)]) # 44%
|
||||
def updateCPUPoints(self):
|
||||
# Clears screen when enough points exist and unshifts the
|
||||
# first point to keep fixed range
|
||||
self.drawBackground(self.brush, self.aw, self.ah)
|
||||
del self.cpu_percents[0:1]
|
||||
|
||||
precent = psutil.cpu_percent()
|
||||
self.cpu_percents.append(precent)
|
||||
self.drawPointLine() # Will re-draw every point
|
||||
self.drawArea.queue_draw()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def drawPointLine(self):
|
||||
self.brush.set_line_width(self.brushSizeVal)
|
||||
self.brush.set_line_cap(1) # 0 = BUTT, 1 = ROUND, 2 = SQUARE
|
||||
|
||||
oldX = 0.0
|
||||
oldP = 0.0
|
||||
i = 1
|
||||
for p in self.cpu_percents:
|
||||
# set color depending on usage...
|
||||
rgba = self.brushColorVal
|
||||
if p > 50.0:
|
||||
rgba = self.warning
|
||||
if p > 85.0:
|
||||
rgba = self.danger
|
||||
|
||||
self.brush.set_source_rgba(rgba[0], rgba[1], rgba[2], rgba[3])
|
||||
|
||||
# Movbe to prev. point if any
|
||||
if oldP is not 0.0 and oldX is not 0.0:
|
||||
x = oldX
|
||||
y = float(self.ah) - (oldP * self.yStep)
|
||||
self.brush.move_to(x, y)
|
||||
|
||||
# Draw line to the new point from old point
|
||||
x2 = i * self.xStep
|
||||
y2 = float(self.ah) - (p * self.yStep)
|
||||
self.brush.line_to(x2, y2)
|
||||
self.brush.stroke()
|
||||
|
||||
# Collect info to use as prev. pint
|
||||
oldX = x2
|
||||
oldP = p
|
||||
i += 1
|
||||
|
||||
|
||||
def onConfigure(self, area, eve, data = None):
|
||||
aw = area.get_allocated_width()
|
||||
ah = area.get_allocated_height()
|
||||
self.aw = aw
|
||||
self.ah = ah
|
||||
self.xStep = aw / 200 # For x-axis
|
||||
self.yStep = ah / 100 # For y-axis %s
|
||||
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, aw, ah)
|
||||
self.brush = cairo.Context(self.surface)
|
||||
|
||||
self.drawBackground(self.brush, aw, ah)
|
||||
if not self.isDrawing:
|
||||
self.fillCPUPercents()
|
||||
self.startCPUGraph()
|
||||
self.isDrawing = True
|
||||
|
||||
return False
|
||||
|
||||
# Fill with y bank with 50%s
|
||||
def fillCPUPercents(self):
|
||||
self.cpu_percents = [50.0] * 198
|
||||
|
||||
|
||||
# Draw background white
|
||||
def drawBackground(self, brush, aw, ah):
|
||||
brush.rectangle(0, 0, aw, ah) # x, y, width, height
|
||||
brush.set_source_rgba(1, 1, 1, 1.0) # x, y, width, height
|
||||
|
||||
if not self.doDrawBackground: # If transparent or white
|
||||
self.brush.set_operator(0);
|
||||
|
||||
brush.fill()
|
||||
self.brush.set_operator(1); # reset the brush after filling bg...
|
||||
|
||||
|
||||
# Starting graph generation
|
||||
def startCPUGraph(self):
|
||||
GObject.timeout_add(self.updateSpeed, self.updateCPUPoints)
|
||||
|
||||
|
||||
def onDraw(self, area, brush):
|
||||
if self.surface is not None:
|
||||
brush.set_source_surface(self.surface, 0.0, 0.0)
|
||||
brush.paint()
|
||||
else:
|
||||
print("No surface info...")
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def onColorSet(self, widget):
|
||||
rgba = widget.get_rgba()
|
||||
self.brushColorVal = [rgba.red, rgba.green, rgba.blue, rgba.alpha]
|
||||
|
||||
def onBrushSizeChange(self, widget):
|
||||
self.brushSizeVal = self.brushSizeProp.get_value()
|
@ -0,0 +1,77 @@
|
||||
# Gtk imports
|
||||
|
||||
# Python imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class GridMixin:
|
||||
# Calls the Grid widget class' method
|
||||
def setNewDirectory(self, widget, data=None):
|
||||
newPath = widget.get_filename()
|
||||
self.gridClss.setNewDirectory(newPath)
|
||||
self.settings.saveSettings(newPath)
|
||||
|
||||
|
||||
# File control events
|
||||
def create(self, wdget):
|
||||
self.currentPath = self.gridClss.returnCurrentPath()
|
||||
fileName = self.builder.get_object("filenameInput").get_text().strip()
|
||||
type = self.builder.get_object("createSwitch").get_state()
|
||||
|
||||
if fileName != "":
|
||||
fileName = self.currentPath + "/" + fileName
|
||||
status = self.filehandler.create(fileName, type)
|
||||
if status == 0:
|
||||
self.gridClss.setNewDirectory(self.currentPath)
|
||||
|
||||
def copy(self, widget):
|
||||
self.pasteType = 1
|
||||
self.copyCutArry = self.gridClss.returnSelectedFiles()
|
||||
|
||||
def cut(self, widget):
|
||||
self.pasteType = 2
|
||||
self.copyCutArry = self.gridClss.returnSelectedFiles()
|
||||
|
||||
def paste(self, widget):
|
||||
self.currentPath = self.gridClss.returnCurrentPath()
|
||||
status = self.filehandler.paste(self.copyCutArry, self.currentPath, self.pasteType)
|
||||
|
||||
if status == 0:
|
||||
self.gridClss.setNewDirectory(self.currentPath)
|
||||
if self.pasteType == 2: # cut == 2
|
||||
self.copyCutArry = []
|
||||
|
||||
def delete(self, widget):
|
||||
self.getGridInfo()
|
||||
status = self.filehandler.delete(self.selectedFiles)
|
||||
|
||||
if status == 0:
|
||||
self.selectedFiles = []
|
||||
self.gridClss.setNewDirectory(self.currentPath)
|
||||
|
||||
def trash(self, widget):
|
||||
self.getGridInfo()
|
||||
status = self.filehandler.trash(self.selectedFiles)
|
||||
|
||||
if status == 0:
|
||||
self.selectedFiles = []
|
||||
self.gridClss.setNewDirectory(self.currentPath)
|
||||
|
||||
def rename(self, widget, data):
|
||||
if data.keyval == 65293: # Enter key press
|
||||
self.getGridInfo()
|
||||
file = widget.get_text();
|
||||
if len(self.selectedFiles) == 1:
|
||||
newName = self.currentPath + "/" + file
|
||||
print("Old Name: " + self.selectedFiles[0])
|
||||
print("New Name: " + newName.strip())
|
||||
|
||||
status = self.filehandler.rename(self.selectedFiles[0], newName.strip())
|
||||
if status == 0:
|
||||
self.selectedFiles = [newName]
|
||||
self.gridClss.setNewDirectory(self.currentPath)
|
||||
|
||||
def getGridInfo(self):
|
||||
self.selectedFiles = self.gridClss.returnSelectedFiles()
|
||||
self.currentPath = self.gridClss.returnCurrentPath()
|
@ -0,0 +1,290 @@
|
||||
# Python imports
|
||||
import subprocess
|
||||
import threading
|
||||
import os
|
||||
import json
|
||||
|
||||
from os.path import isdir, isfile, join
|
||||
from os import listdir
|
||||
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk as gtk
|
||||
from gi.repository import GLib as glib
|
||||
from xdg.DesktopEntry import DesktopEntry
|
||||
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
|
||||
def threaded(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
|
||||
return wrapper
|
||||
|
||||
|
||||
class MainMenuMixin:
|
||||
def toggleProgramMenu(self, widget):
|
||||
pos = self.menuWindow.get_position()
|
||||
posX = pos[0] + 32
|
||||
posY = pos[1] + 72
|
||||
if self.menuWindow.get_visible() == False:
|
||||
self.menuWindow.move(posX, posY)
|
||||
glib.idle_add(self.menuWindow.show_all)
|
||||
else:
|
||||
glib.idle_add(self.menuWindow.hide)
|
||||
|
||||
|
||||
def setListGroup(self, widget):
|
||||
self.progGroup = widget.get_label().strip()
|
||||
self.getSubgroup(self.progGroup)
|
||||
self.generateListView()
|
||||
|
||||
|
||||
def searchForEntry(self, widget, data=None):
|
||||
self.progGroup = "[ Search ]"
|
||||
query = widget.get_text().strip()
|
||||
if not query:
|
||||
self.progGroup = self.grpDefault
|
||||
self.getSubgroup()
|
||||
self.generateListView()
|
||||
return
|
||||
|
||||
self.getSubgroup(query)
|
||||
self.generateListView()
|
||||
|
||||
|
||||
@threaded
|
||||
def generateListView(self):
|
||||
widget = self.builder.get_object("programListBttns")
|
||||
|
||||
# Should have this as a useful method...But, I don't want to import Glib everywhere
|
||||
children = widget.get_children()
|
||||
for child in children:
|
||||
glib.idle_add(widget.remove, (child))
|
||||
|
||||
for obj in self.desktopObjs:
|
||||
title = obj[0]
|
||||
dirPath = obj[1]
|
||||
if self.showIcons:
|
||||
image = self.iconFactory.parseDesktopFiles(dirPath) # .get_pixbuf()
|
||||
self.addToProgramListView(widget, title, image)
|
||||
else:
|
||||
self.addToProgramListViewAsText(widget, title)
|
||||
|
||||
|
||||
@threaded
|
||||
def addToProgramListView(self, widget, title, icon):
|
||||
button = gtk.Button(label=title)
|
||||
button.set_image(icon)
|
||||
button.connect("clicked", self.executeProgram)
|
||||
|
||||
children = button.get_children()
|
||||
alignment1 = children[0]
|
||||
box = alignment1.get_children()[0]
|
||||
label = box.get_children()[1]
|
||||
|
||||
alignment1.set(0.0, 0.0, 0.0, 0.0)
|
||||
label.set_halign(1)
|
||||
label.set_line_wrap(True)
|
||||
label.set_max_width_chars(38)
|
||||
label.set_size_request(640, 64)
|
||||
|
||||
button.show_all()
|
||||
glib.idle_add(widget.add, (button))
|
||||
|
||||
@threaded
|
||||
def addToProgramListViewAsText(self, widget, title):
|
||||
button = gtk.Button(label=title)
|
||||
button.connect("clicked", self.executeProgram)
|
||||
|
||||
children = button.get_children()
|
||||
label = children[0]
|
||||
|
||||
label.set_halign(1)
|
||||
label.set_line_wrap(True)
|
||||
label.set_max_width_chars(38)
|
||||
label.set_size_request(640, 64)
|
||||
|
||||
button.show_all()
|
||||
glib.idle_add(widget.add, (button))
|
||||
|
||||
|
||||
def executeProgram(self, widget):
|
||||
"""
|
||||
# TODO:
|
||||
Need to refactor and pull out the sub loop that is used in both cases...
|
||||
"""
|
||||
entry = widget.get_label().strip()
|
||||
group = self.progGroup
|
||||
|
||||
parts = entry.split("||")
|
||||
program = parts[0].strip()
|
||||
comment = parts[1].strip()
|
||||
|
||||
if "[ Search ]" in group:
|
||||
gkeys = self.menuData.keys()
|
||||
for gkey in gkeys:
|
||||
for opt in self.menuData[gkey]:
|
||||
if program in opt["title"]:
|
||||
keys = opt.keys()
|
||||
if comment in opt["comment"] or comment in opt["fileName"]:
|
||||
DEVNULL = open(os.devnull, 'w')
|
||||
execFailed = False
|
||||
try:
|
||||
command = opt["tryExec"].split("%")[0]
|
||||
# self.logger.debug(command)
|
||||
subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
|
||||
break
|
||||
except Exception as e:
|
||||
execFailed = True
|
||||
|
||||
if execFailed:
|
||||
try:
|
||||
if "exec" in keys and len(opt["exec"]):
|
||||
command = opt["exec"].split("%")[0]
|
||||
# self.logger.debug(command)
|
||||
subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
|
||||
break
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
||||
# self.logger.debug(e)
|
||||
else:
|
||||
for opt in self.menuData[group]:
|
||||
if program in opt["title"]:
|
||||
keys = opt.keys()
|
||||
if comment in opt["comment"] or comment in opt["fileName"]:
|
||||
DEVNULL = open(os.devnull, 'w')
|
||||
execFailed = False
|
||||
try:
|
||||
command = opt["tryExec"].split("%")[0]
|
||||
# self.logger.debug(command)
|
||||
subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
|
||||
except Exception as e:
|
||||
execFailed = True
|
||||
|
||||
if execFailed:
|
||||
try:
|
||||
if "exec" in keys and len(opt["exec"]):
|
||||
command = opt["exec"].split("%")[0]
|
||||
# self.logger.debug(command)
|
||||
subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
||||
# self.logger.debug(e)
|
||||
|
||||
|
||||
# Supoport methods
|
||||
def getDesktopFilesInfo(self, paths):
|
||||
menuObjs = {
|
||||
"Accessories": [],
|
||||
"Multimedia": [],
|
||||
"Graphics": [],
|
||||
"Game": [],
|
||||
"Office": [],
|
||||
"Development": [],
|
||||
"Internet": [],
|
||||
"Settings": [],
|
||||
"System": [],
|
||||
"Wine": [],
|
||||
"Other": []
|
||||
}
|
||||
|
||||
for path in paths:
|
||||
if not "/opt/" in path:
|
||||
self.listAndUpdateDesktopFiles(path, menuObjs);
|
||||
else:
|
||||
for folder in listdir(path):
|
||||
try:
|
||||
fPath = path + folder + "/"
|
||||
self.listAndUpdateDesktopFiles(fPath, menuObjs);
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
||||
|
||||
return menuObjs
|
||||
|
||||
def listAndUpdateDesktopFiles(self, path, menuObjs):
|
||||
for f in listdir(path):
|
||||
fPath = path + f
|
||||
if isfile(fPath) and f.endswith(".desktop"):
|
||||
xdgObj = DesktopEntry(fPath)
|
||||
|
||||
title = xdgObj.getName()
|
||||
groups = xdgObj.getCategories()
|
||||
comment = xdgObj.getComment()
|
||||
icon = xdgObj.getIcon()
|
||||
mainExec = xdgObj.getExec()
|
||||
tryExec = xdgObj.getTryExec()
|
||||
|
||||
group = ""
|
||||
if "Accessories" in groups or "Utility" in groups:
|
||||
group = "Accessories"
|
||||
elif "Multimedia" in groups or "Video" in groups or "Audio" in groups:
|
||||
group = "Multimedia"
|
||||
elif "Development" in groups:
|
||||
group = "Development"
|
||||
elif "Game" in groups:
|
||||
group = "Game"
|
||||
elif "Internet" in groups or "Network" in groups:
|
||||
group = "Internet"
|
||||
elif "Graphics" in groups:
|
||||
group = "Graphics"
|
||||
elif "Office" in groups:
|
||||
group = "Office"
|
||||
elif "System" in groups:
|
||||
group = "System"
|
||||
elif "Settings" in groups:
|
||||
group = "Settings"
|
||||
elif "Wine" in groups:
|
||||
group = "Wine"
|
||||
else:
|
||||
group = "Other"
|
||||
|
||||
menuObjs[group].append( {"title": title, "groups": groups,
|
||||
"comment": comment, "exec": mainExec,
|
||||
"tryExec": tryExec, "fileName": f,
|
||||
"filePath": fPath, "icon": icon})
|
||||
|
||||
|
||||
def getSubgroup(self, query = ""):
|
||||
"""
|
||||
Need to refactor and pull out the sub logic that is used in both cases...
|
||||
"""
|
||||
group = self.progGroup
|
||||
self.desktopObjs.clear()
|
||||
if "[ Search ]" in group:
|
||||
gkeys = self.menuData.keys()
|
||||
for gkey in gkeys:
|
||||
for opt in self.menuData[gkey]:
|
||||
keys = opt.keys()
|
||||
|
||||
if "comment" in keys and len(opt["comment"]) > 0 :
|
||||
if query.lower() in opt["comment"].lower():
|
||||
title = opt["title"] + " || " + opt["comment"]
|
||||
fPath = opt["filePath"]
|
||||
self.desktopObjs.append([title, fPath])
|
||||
continue
|
||||
|
||||
if query.lower() in opt["title"].lower() or \
|
||||
query.lower() in opt["fileName"].lower():
|
||||
title = opt["title"] + " || " + opt["fileName"].replace(".desktop", "")
|
||||
fPath = opt["filePath"]
|
||||
self.desktopObjs.append([title, fPath])
|
||||
else:
|
||||
for opt in self.menuData[group]:
|
||||
keys = opt.keys()
|
||||
if "comment" in keys and len(opt["comment"]) > 0 :
|
||||
title = opt["title"] + " || " + opt["comment"]
|
||||
fPath = opt["filePath"]
|
||||
self.desktopObjs.append([title, fPath])
|
||||
else:
|
||||
title = opt["title"] + " || " + opt["fileName"].replace(".desktop", "")
|
||||
fPath = opt["filePath"]
|
||||
self.desktopObjs.append([title, fPath])
|
||||
|
||||
return self.desktopObjs
|
@ -0,0 +1,90 @@
|
||||
# Python imports
|
||||
import threading
|
||||
from datetime import datetime
|
||||
|
||||
# Gtk imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
gi.require_version('Wnck', '3.0')
|
||||
|
||||
from gi.repository import Wnck as wnck
|
||||
from gi.repository import Gtk as gtk
|
||||
from gi.repository import Gdk as gdk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class MouseButton:
|
||||
LEFT_BUTTON = 1
|
||||
MIDDLE_BUTTON = 2
|
||||
RIGHT_BUTTON = 3
|
||||
|
||||
|
||||
class TaskbarMixin:
|
||||
def toggleCalPopover(self, widget, eve):
|
||||
calendarPopup = self.builder.get_object('calendarPopup')
|
||||
if (calendarPopup.get_visible() == False):
|
||||
calendarWid = self.builder.get_object('calendarWid')
|
||||
now = datetime.now()
|
||||
timeStr = now.strftime("%m/%d/%Y")
|
||||
parts = timeStr.split("/")
|
||||
month = int(parts[0]) - 1
|
||||
day = int(parts[1])
|
||||
year = int(parts[2])
|
||||
calendarWid.select_day(day)
|
||||
calendarWid.select_month(month, year)
|
||||
calendarPopup.popup()
|
||||
else:
|
||||
calendarPopup.popdown()
|
||||
|
||||
|
||||
def showSystemStats(self, widget, eve):
|
||||
if eve.type == gdk.EventType.BUTTON_RELEASE and eve.button == MouseButton.RIGHT_BUTTON:
|
||||
self.builder.get_object('systemStats').popup()
|
||||
|
||||
def setPagerWidget(self):
|
||||
pager = wnck.Pager()
|
||||
|
||||
if self.orientation == 0:
|
||||
self.builder.get_object('taskBarWorkspacesHor').add(pager)
|
||||
else:
|
||||
self.builder.get_object('taskBarWorkspacesVer').add(pager)
|
||||
|
||||
pager.show()
|
||||
|
||||
|
||||
def setTasklistWidget(self):
|
||||
tasklist = wnck.Tasklist()
|
||||
tasklist.set_scroll_enabled(False)
|
||||
tasklist.set_button_relief(2) # 0 = normal relief, 2 = no relief
|
||||
tasklist.set_grouping(1) # 0 = mever group, 1 auto group, 2 = always group
|
||||
|
||||
tasklist.set_orientation(self.orientation)
|
||||
if self.orientation == 0:
|
||||
self.builder.get_object('taskBarButtonsHor').add(tasklist)
|
||||
else:
|
||||
self.builder.get_object('taskBarButtonsVer').add(tasklist)
|
||||
|
||||
tasklist.show()
|
||||
|
||||
|
||||
# Displays Timer
|
||||
def displayclock(self):
|
||||
now = datetime.now()
|
||||
hms = now.strftime("%I:%M %p")
|
||||
mdy = now.strftime("%m/%d/%Y")
|
||||
timeStr = hms + "\n" + mdy
|
||||
self.timeLabel.set_label(timeStr)
|
||||
return True
|
||||
|
||||
# Starting or clock
|
||||
def startClock(self):
|
||||
GObject.timeout_add(59000, self.displayclock)
|
||||
|
||||
|
||||
def closePopup(self, widget, data=None):
|
||||
widget.hide()
|
@ -0,0 +1,4 @@
|
||||
from .MainMenuMixin import MainMenuMixin
|
||||
from .TaskbarMixin import TaskbarMixin
|
||||
from .CPUDrawMixin import CPUDrawMixin
|
||||
from .GridMixin import GridMixin
|
85
src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Dragging.py
Normal file
@ -0,0 +1,85 @@
|
||||
# Gtk imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gdk', '3.0')
|
||||
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GObject
|
||||
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
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
|
162
src/debs/pytop-0-0-1-x64/opt/Pytop/utils/FileHandler.py
Normal file
@ -0,0 +1,162 @@
|
||||
# Gtk imports
|
||||
|
||||
# Python imports
|
||||
import os, shutil, subprocess, threading
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
def threaded(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
|
||||
return wrapper
|
||||
|
||||
class FileHandler:
|
||||
def __init__(self, settings):
|
||||
# 'Filters'
|
||||
self.office = settings.returnOfficeFilter()
|
||||
self.vids = settings.returnVidsFilter()
|
||||
self.txt = settings.returnTextFilter()
|
||||
self.music = settings.returnMusicFilter()
|
||||
self.images = settings.returnImagesFilter()
|
||||
self.pdf = settings.returnPdfFilter()
|
||||
|
||||
# Args
|
||||
self.MEDIAPLAYER = settings.returnMediaProg()
|
||||
self.IMGVIEWER = settings.returnImgVwrProg()
|
||||
self.MUSICPLAYER = settings.returnMusicProg()
|
||||
self.OFFICEPROG = settings.returnOfficeProg()
|
||||
self.TEXTVIEWER = settings.returnTextProg()
|
||||
self.PDFVIEWER = settings.returnPdfProg()
|
||||
self.FILEMANAGER = settings.returnFileMngrProg()
|
||||
self.MPLAYER_WH = settings.returnMplyrWH()
|
||||
self.MPV_WH = settings.returnMpvWHProg()
|
||||
self.TRASHFILESFOLDER = settings.returnTrshFilesPth()
|
||||
self.TRASHINFOFOLDER = settings.returnTrshInfoPth()
|
||||
|
||||
|
||||
def openFile(self, file):
|
||||
print("Opening: " + file)
|
||||
DEVNULL = open(os.devnull, 'w')
|
||||
|
||||
if file.lower().endswith(self.vids):
|
||||
subprocess.Popen([self.MEDIAPLAYER, self.MPV_WH, file], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
elif file.lower().endswith(self.music):
|
||||
subprocess.Popen([self.MUSICPLAYER, file], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
elif file.lower().endswith(self.images):
|
||||
subprocess.Popen([self.IMGVIEWER, file], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
elif file.lower().endswith(self.txt):
|
||||
subprocess.Popen([self.TEXTVIEWER, file], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
elif file.lower().endswith(self.pdf):
|
||||
subprocess.Popen([self.PDFVIEWER, file], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
elif file.lower().endswith(self.office):
|
||||
subprocess.Popen([self.OFFICEPROG, file], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
else:
|
||||
subprocess.Popen(['xdg-open', file], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
|
||||
|
||||
|
||||
def create(self, name, type):
|
||||
try:
|
||||
if type == True: # Create File
|
||||
open(name, 'w')
|
||||
else: # Create Folder
|
||||
os.mkdir(name)
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
def paste(self, files, toPath, pasteType):
|
||||
try:
|
||||
for file in files:
|
||||
parts = file.split("/")
|
||||
toBePath = toPath + "/" + parts[len(parts) - 1] # Used to check for duplicates
|
||||
finalForm = file + self.dedupPathIter(toBePath)
|
||||
isDuplicate = finalForm != file
|
||||
|
||||
if isDuplicate:
|
||||
os.rename(file, finalForm)
|
||||
|
||||
if pasteType == 1: # copy paste = 1
|
||||
shutil.copy2(finalForm, toPath)
|
||||
if isDuplicate:
|
||||
os.rename(finalForm, file) # Rename back after copy completes
|
||||
if pasteType == 2: # cut paste = 2
|
||||
shutil.move(finalForm, toPath)
|
||||
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
def delete(self, toDeleteFiles):
|
||||
try:
|
||||
print("Deleting...")
|
||||
for file in toDeleteFiles:
|
||||
print(file)
|
||||
if os.path.exists(file):
|
||||
if os.path.isfile(file):
|
||||
os.remove(file)
|
||||
elif os.path.isdir(file):
|
||||
shutil.rmtree(file)
|
||||
else:
|
||||
print("The folder/file does not exist")
|
||||
return 1
|
||||
except Exception as e:
|
||||
print("An error occured deleting the file:")
|
||||
print( repr(e) )
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
def trash(self, toTrashFiles):
|
||||
try:
|
||||
print("Moving to Trash...")
|
||||
for file in toTrashFiles:
|
||||
print(file)
|
||||
if os.path.exists(file):
|
||||
parts = file.split("/")
|
||||
toBeTrashPath = self.TRASHFILESFOLDER + parts[len(parts) - 1]
|
||||
finalForm = file + self.dedupPathIter(toBeTrashPath)
|
||||
|
||||
if finalForm != file:
|
||||
os.rename(file, finalForm)
|
||||
|
||||
shutil.move(finalForm, self.TRASHFILESFOLDER)
|
||||
else:
|
||||
print("The folder/file does not exist")
|
||||
return 1
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
def rename(self, oldFileName, newFileName):
|
||||
try:
|
||||
if os.path.exists(oldFileName):
|
||||
print("Renaming...")
|
||||
print(oldFileName + " --> " + newFileName)
|
||||
os.rename(oldFileName, newFileName)
|
||||
else:
|
||||
print("The folder/file does not exist")
|
||||
return 1
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def dedupPathIter(self, toBeTrashPath):
|
||||
duplicateFix = ""
|
||||
i = 0
|
||||
|
||||
if os.path.exists(toBeTrashPath):
|
||||
while os.path.exists(toBeTrashPath + duplicateFix) == True:
|
||||
i+=1
|
||||
duplicateFix = "-" + str(i)
|
||||
|
||||
return duplicateFix
|
55
src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Logger.py
Normal file
@ -0,0 +1,55 @@
|
||||
# Python imports
|
||||
import os, logging
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self):
|
||||
self.USER_HOME = os.path.expanduser("~")
|
||||
|
||||
def get_logger(self, loggerName = "NO_LOGGER_NAME_PASSED", createFile = True):
|
||||
"""
|
||||
Create a new logging object and return it.
|
||||
:note:
|
||||
NOSET # Don't know the actual log level of this... (defaulting or literally none?)
|
||||
Log Levels (From least to most)
|
||||
Type Value
|
||||
CRITICAL 50
|
||||
ERROR 40
|
||||
WARNING 30
|
||||
INFO 20
|
||||
DEBUG 10
|
||||
:param loggerName: Sets the name of the logger object. (Used in log lines)
|
||||
:param createFile: Whether we create a log file or just pump to terminal
|
||||
|
||||
:return: the logging object we created
|
||||
"""
|
||||
|
||||
globalLogLvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels
|
||||
chLogLevel = logging.CRITICAL # Prety musch the only one we change ever
|
||||
fhLogLevel = logging.DEBUG
|
||||
log = logging.getLogger(loggerName)
|
||||
|
||||
# Set our log output styles
|
||||
fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S')
|
||||
cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s')
|
||||
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(level=chLogLevel)
|
||||
ch.setFormatter(cFormatter)
|
||||
log.addHandler(ch)
|
||||
|
||||
if createFile:
|
||||
folder = self.USER_HOME + ".config/pytop/logs"
|
||||
file = folder + "/application.log"
|
||||
|
||||
if not os.path.exists(folder):
|
||||
os.mkdir(folder)
|
||||
|
||||
fh = logging.FileHandler(file)
|
||||
fh.setLevel(level=fhLogLevel)
|
||||
fh.setFormatter(fFormatter)
|
||||
log.addHandler(fh)
|
||||
|
||||
return log
|
180
src/debs/pytop-0-0-1-x64/opt/Pytop/utils/Settings.py
Normal file
@ -0,0 +1,180 @@
|
||||
# Gtk imports
|
||||
import gi, cairo
|
||||
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
|
||||
|
||||
# Python imports
|
||||
import os, json
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Settings:
|
||||
def __init__(self, monIndex = 0):
|
||||
self.builder = None
|
||||
self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + "/"
|
||||
|
||||
# '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')
|
||||
|
||||
self.hideHiddenFiles = True
|
||||
self.ColumnSize = 8
|
||||
self.usrHome = os.path.expanduser('~')
|
||||
self.desktopPath = self.usrHome + "/Desktop"
|
||||
self.iconContainerWxH = [128, 128]
|
||||
self.systemIconImageWxH = [56, 56]
|
||||
self.viIconWxH = [256, 128]
|
||||
self.monitors = 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.TRASHFOLDER = os.path.expanduser('~') + "/.local/share/Trash/"
|
||||
self.TRASHFILESFOLDER = self.TRASHFOLDER + "files/"
|
||||
self.TRASHINFOFOLDER = self.TRASHFOLDER + "info/"
|
||||
self.THUMB_GENERATOR = "ffmpegthumbnailer"
|
||||
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% ";
|
||||
self.GTK_ORIENTATION = 1 # HORIZONTAL (0) VERTICAL (1)
|
||||
|
||||
configFolder = os.path.expanduser('~') + "/.config/pytop/"
|
||||
self.configFile = configFolder + "mon_" + str(monIndex) + "_settings.ini"
|
||||
|
||||
if os.path.isdir(configFolder) == False:
|
||||
os.mkdir(configFolder)
|
||||
|
||||
if os.path.isdir(self.TRASHFOLDER) == False:
|
||||
os.mkdir(TRASHFILESFOLDER)
|
||||
os.mkdir(TRASHINFOFOLDER)
|
||||
|
||||
if os.path.isdir(self.TRASHFILESFOLDER) == False:
|
||||
os.mkdir(TRASHFILESFOLDER)
|
||||
|
||||
if os.path.isdir(self.TRASHINFOFOLDER) == False:
|
||||
os.mkdir(TRASHINFOFOLDER)
|
||||
|
||||
if os.path.isfile(self.configFile) == False:
|
||||
open(self.configFile, 'a').close()
|
||||
self.saveSettings(self.desktopPath)
|
||||
|
||||
|
||||
def attachBuilder(self, builder):
|
||||
self.builder = builder
|
||||
self.builder.add_from_file(self.SCRIPT_PTH + "../resources/Main_Window.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)
|
||||
|
||||
# bind css file
|
||||
cssProvider = gtk.CssProvider()
|
||||
cssProvider.load_from_path(self.SCRIPT_PTH + '../resources/stylesheet.css')
|
||||
screen = gdk.Screen.get_default()
|
||||
styleContext = gtk.StyleContext()
|
||||
styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||
|
||||
window.set_app_paintable(True)
|
||||
self.monitors = self.getMonitorData(screen)
|
||||
window.resize(self.monitors[0].width, self.monitors[0].height)
|
||||
|
||||
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) + "+" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y))
|
||||
|
||||
return monitors
|
||||
|
||||
|
||||
def returnMonitorsInfo(self):
|
||||
return self.monitors
|
||||
|
||||
|
||||
def saveSettings(self, startPath):
|
||||
data = {}
|
||||
data['pytop_settings'] = []
|
||||
|
||||
data['pytop_settings'].append({
|
||||
'startPath' : startPath
|
||||
})
|
||||
|
||||
with open(self.configFile, 'w') as outfile:
|
||||
json.dump(data, outfile)
|
||||
|
||||
|
||||
def returnSettings(self):
|
||||
returnData = []
|
||||
|
||||
with open(self.configFile) as infile:
|
||||
try:
|
||||
data = json.load(infile)
|
||||
for obj in data['pytop_settings']:
|
||||
returnData = [obj['startPath']]
|
||||
except Exception as e:
|
||||
returnData = ['~/Desktop/']
|
||||
|
||||
|
||||
if returnData[0] == '':
|
||||
returnData[0] = '~/Desktop/'
|
||||
|
||||
return returnData
|
||||
|
||||
|
||||
def returnBuilder(self): return self.builder
|
||||
def returnUserHome(self): return self.usrHome
|
||||
def returnDesktopPath(self): return self.usrHome + "/Desktop"
|
||||
def returnColumnSize(self): return self.ColumnSize
|
||||
def returnContainerWH(self): return self.iconContainerWxH
|
||||
def returnSystemIconImageWH(self): return self.systemIconImageWxH
|
||||
def returnVIIconWH(self): return self.viIconWxH
|
||||
def isHideHiddenFiles(self): return self.hideHiddenFiles
|
||||
|
||||
# Filter returns
|
||||
def returnOfficeFilter(self): return self.office
|
||||
def returnVidsFilter(self): return self.vids
|
||||
def returnTextFilter(self): return self.txt
|
||||
def returnMusicFilter(self): return self.music
|
||||
def returnImagesFilter(self): return self.images
|
||||
def returnPdfFilter(self): return self.pdf
|
||||
|
||||
def returnIconImagePos(self): return self.GTK_ORIENTATION
|
||||
def getThumbnailGenerator(self): return self.THUMB_GENERATOR
|
||||
def returnMediaProg(self): return self.MEDIAPLAYER
|
||||
def returnImgVwrProg(self): return self.IMGVIEWER
|
||||
def returnMusicProg(self): return self.MUSICPLAYER
|
||||
def returnOfficeProg(self): return self.OFFICEPROG
|
||||
def returnTextProg(self): return self.TEXTVIEWER
|
||||
def returnPdfProg(self): return self.PDFVIEWER
|
||||
def returnFileMngrProg(self): return self.FILEMANAGER
|
||||
def returnMplyrWH(self): return self.MPLAYER_WH
|
||||
def returnMpvWHProg(self): return self.MPV_WH
|
||||
def returnTrshFilesPth(self): return self.TRASHFILESFOLDER
|
||||
def returnTrshInfoPth(self): return self.TRASHINFOFOLDER
|
4
src/debs/pytop-0-0-1-x64/opt/Pytop/utils/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from utils.Dragging import Dragging
|
||||
from .Logger import Logger
|
||||
from utils.FileHandler import FileHandler
|
||||
from utils.Settings import Settings
|
209
src/debs/pytop-0-0-1-x64/opt/Pytop/widgets/Grid.py
Normal file
@ -0,0 +1,209 @@
|
||||
# Python imports
|
||||
import os, threading, time
|
||||
from os.path import isdir, isfile, join
|
||||
from os import listdir
|
||||
|
||||
|
||||
# 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 Gdk as gdk
|
||||
from gi.repository import GLib as glib
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
|
||||
# Application imports
|
||||
from .Icon import Icon
|
||||
from utils.FileHandler import FileHandler
|
||||
|
||||
|
||||
def threaded(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
|
||||
return wrapper
|
||||
|
||||
|
||||
class Grid:
|
||||
def __init__(self, grid, settings):
|
||||
self.grid = grid
|
||||
self.settings = settings
|
||||
self.fileHandler = FileHandler(self.settings)
|
||||
|
||||
self.store = gtk.ListStore(GdkPixbuf.Pixbuf, str)
|
||||
self.usrHome = settings.returnUserHome()
|
||||
self.hideHiddenFiles = settings.isHideHiddenFiles()
|
||||
self.builder = settings.returnBuilder()
|
||||
self.ColumnSize = settings.returnColumnSize()
|
||||
self.vidsFilter = settings.returnVidsFilter()
|
||||
self.imagesFilter = settings.returnImagesFilter()
|
||||
self.iconFactory = Icon(settings)
|
||||
self.selectedFiles = []
|
||||
self.currentPath = ""
|
||||
|
||||
self.grid.set_model(self.store)
|
||||
self.grid.set_pixbuf_column(0)
|
||||
self.grid.set_text_column(1)
|
||||
self.grid.connect("item-activated", self.iconDblLeftClick)
|
||||
self.grid.connect("button_release_event", self.iconSingleClick, (self.grid,))
|
||||
|
||||
def setNewDirectory(self, path):
|
||||
self.store.clear()
|
||||
self.currentPath = path
|
||||
dirPaths = ['.', '..']
|
||||
vids = []
|
||||
images = []
|
||||
desktop = []
|
||||
files = []
|
||||
|
||||
for f in listdir(path):
|
||||
file = join(path, f)
|
||||
if self.hideHiddenFiles:
|
||||
if f.startswith('.'):
|
||||
continue
|
||||
|
||||
if isfile(file):
|
||||
lowerName = file.lower()
|
||||
|
||||
if lowerName.endswith(self.vidsFilter):
|
||||
vids.append(f)
|
||||
elif lowerName.endswith(self.imagesFilter):
|
||||
images.append(f)
|
||||
elif lowerName.endswith((".desktop",)):
|
||||
desktop.append(f)
|
||||
else:
|
||||
files.append(f)
|
||||
else:
|
||||
dirPaths.append(f)
|
||||
|
||||
dirPaths.sort()
|
||||
vids.sort()
|
||||
images.sort()
|
||||
desktop.sort()
|
||||
files.sort()
|
||||
|
||||
files = dirPaths + vids + images + desktop + files
|
||||
self.generateGridIcons(path, files)
|
||||
self.fillVideoIcons(path, vids, len(dirPaths))
|
||||
|
||||
|
||||
@threaded
|
||||
def generateGridIcons(self, dirPath, files):
|
||||
for file in files:
|
||||
image = self.iconFactory.createIcon(dirPath, file).get_pixbuf()
|
||||
glib.idle_add(self.addToGrid, (image, file,))
|
||||
|
||||
|
||||
@threaded
|
||||
def fillVideoIcons(self, dirPath, files, start):
|
||||
model = self.grid.get_model()
|
||||
|
||||
# Wait till we have a proper index...
|
||||
while len(self.store) < (start + 1):
|
||||
time.sleep(.650)
|
||||
|
||||
i = start
|
||||
for file in files:
|
||||
self.updateGrid(model, dirPath, file, i)
|
||||
i += 1
|
||||
|
||||
@threaded
|
||||
def updateGrid(self, model, dirPath, file, i):
|
||||
try:
|
||||
image = self.iconFactory.createThumbnail(dirPath, file).get_pixbuf()
|
||||
iter = model.get_iter_from_string(str(i))
|
||||
glib.idle_add(self.replaceInGrid, (iter, image,))
|
||||
except Exception as e:
|
||||
# Errors seem to happen when fillVideoIcons index wait check is to low
|
||||
print("widgets/Grid.py sinking errors on updateGrid method...")
|
||||
|
||||
def addToGrid(self, dataSet):
|
||||
self.store.append([dataSet[0], dataSet[1]])
|
||||
|
||||
def replaceInGrid(self, dataSet):
|
||||
# Iter, row column, new pixbuf...
|
||||
self.store.set_value(dataSet[0], 0 , dataSet[1])
|
||||
|
||||
|
||||
def iconDblLeftClick(self, widget, item):
|
||||
try:
|
||||
model = widget.get_model()
|
||||
fileName = model[item][1]
|
||||
dir = self.currentPath
|
||||
file = dir + "/" + fileName
|
||||
|
||||
if fileName == ".":
|
||||
self.setNewDirectory(dir)
|
||||
elif fileName == "..":
|
||||
parentDir = os.path.abspath(os.path.join(dir, os.pardir))
|
||||
self.currentPath = parentDir
|
||||
self.setNewDirectory(parentDir)
|
||||
self.settings.saveSettings(parentDir)
|
||||
elif isdir(file):
|
||||
self.currentPath = file
|
||||
self.setNewDirectory(self.currentPath)
|
||||
self.settings.saveSettings(self.currentPath)
|
||||
elif isfile(file):
|
||||
self.fileHandler.openFile(file)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def iconSingleClick(self, widget, eve, rclicked_icon):
|
||||
try:
|
||||
if eve.type == gdk.EventType.BUTTON_RELEASE and eve.button == 1:
|
||||
self.selectedFiles.clear()
|
||||
items = widget.get_selected_items()
|
||||
model = widget.get_model()
|
||||
dir = self.currentPath
|
||||
|
||||
for item in items:
|
||||
fileName = model[item][1]
|
||||
|
||||
if fileName != "." and fileName != "..":
|
||||
file = dir + "/" + fileName
|
||||
self.selectedFiles.append(file) # Used for return to caller
|
||||
|
||||
elif eve.type == gdk.EventType.BUTTON_RELEASE and eve.button == 3:
|
||||
input = self.builder.get_object("filenameInput")
|
||||
controls = self.builder.get_object("iconControlsWindow")
|
||||
iconsButtonBox = self.builder.get_object("iconsButtonBox")
|
||||
menuButtonBox = self.builder.get_object("menuButtonBox")
|
||||
|
||||
|
||||
if len(self.selectedFiles) == 1:
|
||||
parts = self.selectedFiles[0].split("/")
|
||||
input.set_text(parts[len(parts) - 1])
|
||||
input.show()
|
||||
iconsButtonBox.show()
|
||||
menuButtonBox.hide()
|
||||
controls.show()
|
||||
elif len(self.selectedFiles) > 1:
|
||||
input.set_text("")
|
||||
input.hide()
|
||||
menuButtonBox.hide()
|
||||
iconsButtonBox.show()
|
||||
controls.show()
|
||||
else:
|
||||
input.set_text("")
|
||||
input.show()
|
||||
menuButtonBox.show()
|
||||
iconsButtonBox.hide()
|
||||
controls.show()
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def returnSelectedFiles(self):
|
||||
# NOTE: Just returning selectedFiles looks like it returns a "pointer"
|
||||
# to the children. This means we lose the list if any left click occures
|
||||
# in this class.
|
||||
files = []
|
||||
for file in self.selectedFiles:
|
||||
files.append(file)
|
||||
return files
|
||||
|
||||
def returnCurrentPath(self):
|
||||
currentPath = self.currentPath
|
||||
return currentPath
|
228
src/debs/pytop-0-0-1-x64/opt/Pytop/widgets/Icon.py
Normal file
@ -0,0 +1,228 @@
|
||||
# Python Imports
|
||||
import os, subprocess, hashlib, threading
|
||||
from os.path import isdir, isfile, join
|
||||
|
||||
|
||||
# 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 xdg.DesktopEntry import DesktopEntry
|
||||
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
|
||||
def threaded(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
|
||||
return wrapper
|
||||
|
||||
class Icon:
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
self.thubnailGen = settings.getThumbnailGenerator()
|
||||
self.vidsList = settings.returnVidsFilter()
|
||||
self.imagesList = settings.returnImagesFilter()
|
||||
self.GTK_ORIENTATION = settings.returnIconImagePos()
|
||||
self.usrHome = settings.returnUserHome()
|
||||
self.iconContainerWH = settings.returnContainerWH()
|
||||
self.systemIconImageWH = settings.returnSystemIconImageWH()
|
||||
self.viIconWH = settings.returnVIIconWH()
|
||||
self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + "/"
|
||||
self.INTERNAL_ICON_PTH = self.SCRIPT_PTH + "../resources/icons/text.png"
|
||||
|
||||
|
||||
def createIcon(self, dir, file):
|
||||
fullPath = dir + "/" + file
|
||||
return self.getIconImage(file, fullPath)
|
||||
|
||||
def createThumbnail(self, dir, file):
|
||||
fullPath = dir + "/" + file
|
||||
try:
|
||||
# Video thumbnail
|
||||
if file.lower().endswith(self.vidsList):
|
||||
fileHash = hashlib.sha256(str.encode(fullPath)).hexdigest()
|
||||
hashImgPth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png"
|
||||
|
||||
if isfile(hashImgPth) == False:
|
||||
self.generateVideoThumbnail(fullPath, hashImgPth)
|
||||
|
||||
thumbnl = self.createScaledImage(hashImgPth, self.viIconWH)
|
||||
if thumbnl == None: # If no icon whatsoever, return internal default
|
||||
thumbnl = gtk.Image.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png")
|
||||
|
||||
return thumbnl
|
||||
except Exception as e:
|
||||
print("Thumbnail generation issue:")
|
||||
print( repr(e) )
|
||||
return gtk.Image.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png")
|
||||
|
||||
|
||||
def getIconImage(self, file, fullPath):
|
||||
try:
|
||||
thumbnl = None
|
||||
|
||||
# Video icon
|
||||
if file.lower().endswith(self.vidsList):
|
||||
thumbnl = gtk.Image.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png")
|
||||
# Image Icon
|
||||
elif file.lower().endswith(self.imagesList):
|
||||
thumbnl = self.createScaledImage(fullPath, self.viIconWH)
|
||||
# .desktop file parsing
|
||||
elif fullPath.lower().endswith( ('.desktop',) ):
|
||||
thumbnl = self.parseDesktopFiles(fullPath)
|
||||
# System icons
|
||||
else:
|
||||
thumbnl = self.getSystemThumbnail(fullPath, self.systemIconImageWH[0])
|
||||
|
||||
if thumbnl == None: # If no icon whatsoever, return internal default
|
||||
thumbnl = gtk.Image.new_from_file(self.INTERNAL_ICON_PTH)
|
||||
|
||||
return thumbnl
|
||||
except Exception as e:
|
||||
print("Icon generation issue:")
|
||||
print( repr(e) )
|
||||
return gtk.Image.new_from_file(self.INTERNAL_ICON_PTH)
|
||||
|
||||
def parseDesktopFiles(self, fullPath):
|
||||
try:
|
||||
xdgObj = DesktopEntry(fullPath)
|
||||
icon = xdgObj.getIcon()
|
||||
altIconPath = ""
|
||||
|
||||
if "steam" in icon:
|
||||
steamIconsDir = self.usrHome + "/.thumbnails/steam_icons/"
|
||||
name = xdgObj.getName()
|
||||
fileHash = hashlib.sha256(str.encode(name)).hexdigest()
|
||||
|
||||
if isdir(steamIconsDir) == False:
|
||||
os.mkdir(steamIconsDir)
|
||||
|
||||
hashImgPth = steamIconsDir + fileHash + ".jpg"
|
||||
if isfile(hashImgPth) == True:
|
||||
# Use video sizes since headers are bigger
|
||||
return self.createScaledImage(hashImgPth, self.viIconWH)
|
||||
|
||||
execStr = xdgObj.getExec()
|
||||
parts = execStr.split("steam://rungameid/")
|
||||
id = parts[len(parts) - 1]
|
||||
imageLink = "https://steamcdn-a.akamaihd.net/steam/apps/" + id + "/header.jpg"
|
||||
proc = subprocess.Popen(["wget", "-O", hashImgPth, imageLink])
|
||||
proc.wait()
|
||||
|
||||
# Use video thumbnail sizes since headers are bigger
|
||||
return self.createScaledImage(hashImgPth, self.viIconWH)
|
||||
elif os.path.exists(icon):
|
||||
return self.createScaledImage(icon, self.systemIconImageWH)
|
||||
else:
|
||||
iconsDirs = ["/usr/share/pixmaps", "/usr/share/icons", self.usrHome + "/.icons" ,]
|
||||
altIconPath = ""
|
||||
|
||||
for iconsDir in iconsDirs:
|
||||
altIconPath = self.traverseIconsFolder(iconsDir, icon)
|
||||
if altIconPath is not "":
|
||||
break
|
||||
|
||||
return self.createScaledImage(altIconPath, self.systemIconImageWH)
|
||||
except Exception as e:
|
||||
print(".desktop icon generation issue:")
|
||||
print( repr(e) )
|
||||
return None
|
||||
|
||||
|
||||
def traverseIconsFolder(self, path, icon):
|
||||
altIconPath = ""
|
||||
|
||||
for (dirpath, dirnames, filenames) in os.walk(path):
|
||||
for file in filenames:
|
||||
appNM = "application-x-" + icon
|
||||
if icon in file or appNM in file:
|
||||
altIconPath = dirpath + "/" + file
|
||||
break
|
||||
|
||||
return altIconPath
|
||||
|
||||
|
||||
def getSystemThumbnail(self, filename, size):
|
||||
try:
|
||||
if os.path.exists(filename):
|
||||
gioFile = gio.File.new_for_path(filename)
|
||||
info = gioFile.query_info('standard::icon' , 0, gio.Cancellable())
|
||||
icon = info.get_icon().get_names()[0]
|
||||
iconTheme = gtk.IconTheme.get_default()
|
||||
iconData = iconTheme.lookup_icon(icon , size , 0)
|
||||
if iconData:
|
||||
iconPath = iconData.get_filename()
|
||||
return gtk.Image.new_from_file(iconPath) # This seems to cause a lot of core dump issues...
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
print("system icon generation issue:")
|
||||
print( repr(e) )
|
||||
return None
|
||||
|
||||
|
||||
def createScaledImage(self, path, wxh):
|
||||
try:
|
||||
pixbuf = gtk.Image.new_from_file(path).get_pixbuf()
|
||||
scaledPixBuf = pixbuf.scale_simple(wxh[0], wxh[1], 2) # 2 = BILINEAR and is best by default
|
||||
return gtk.Image.new_from_pixbuf(scaledPixBuf)
|
||||
except Exception as e:
|
||||
print("Image Scaling Issue:")
|
||||
print( repr(e) )
|
||||
return None
|
||||
|
||||
def createFromFile(self, path):
|
||||
try:
|
||||
return gtk.Image.new_from_file(path)
|
||||
except Exception as e:
|
||||
print("Image from file Issue:")
|
||||
print( repr(e) )
|
||||
return None
|
||||
|
||||
def returnGenericIcon(self):
|
||||
return gtk.Image.new_from_file(self.INTERNAL_ICON_PTH)
|
||||
|
||||
|
||||
def generateVideoThumbnail(self, fullPath, hashImgPth):
|
||||
proc = None
|
||||
try:
|
||||
# Stream duration
|
||||
command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPath]
|
||||
data = subprocess.run(command, stdout=subprocess.PIPE)
|
||||
duration = data.stdout.decode('utf-8')
|
||||
|
||||
# Format (container) duration
|
||||
if "N/A" in duration:
|
||||
command = ["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPath]
|
||||
data = subprocess.run(command , stdout=subprocess.PIPE)
|
||||
duration = data.stdout.decode('utf-8')
|
||||
|
||||
# Stream duration type: image2
|
||||
if "N/A" in duration:
|
||||
command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-f", "image2", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPath]
|
||||
data = subprocess.run(command, stdout=subprocess.PIPE)
|
||||
duration = data.stdout.decode('utf-8')
|
||||
|
||||
# Format (container) duration type: image2
|
||||
if "N/A" in duration:
|
||||
command = ["ffprobe", "-v", "error", "-f", "image2", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPath]
|
||||
data = subprocess.run(command , stdout=subprocess.PIPE)
|
||||
duration = data.stdout.decode('utf-8')
|
||||
|
||||
# Get frame roughly 35% through video
|
||||
grabTime = str( int( float( duration.split(".")[0] ) * 0.35) )
|
||||
command = ["ffmpeg", "-ss", grabTime, "-an", "-i", fullPath, "-s", "320x180", "-vframes", "1", hashImgPth]
|
||||
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||
proc.wait()
|
||||
except Exception as e:
|
||||
print("Video thumbnail generation issue in thread:")
|
||||
print( repr(e) )
|
2
src/debs/pytop-0-0-1-x64/opt/Pytop/widgets/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from widgets.Grid import Grid
|
||||
from widgets.Icon import Icon
|
22
src/debs/pytop-0-0-1-x64/usr/share/doc/pytop/copyright
Normal 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.
|