Added taskbar

This commit is contained in:
Maxim Stewart 2019-09-28 19:14:32 -05:00
parent 79ed46f889
commit 1f43632928
8 changed files with 384 additions and 15 deletions

View File

@ -1,6 +1,9 @@
# Pytop
Pytop is a Gtk + Python gui to have a custom desktop interface.
# Updates
Added task bar.
# Notes
```sudo apt-get install python3 wget steamcmd```

Binary file not shown.

View File

@ -15,12 +15,12 @@ from setproctitle import setproctitle
# Application imports
from utils import Settings
from signal_classes import CrossClassSignals, GridSignals
from signal_classes import CrossClassSignals, GridSignals, TaskbarSignals
class Main:
setproctitle('Pytop')
def __init__(self):
setproctitle('Pytop')
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
faulthandler.enable() # For better debug info
@ -31,7 +31,8 @@ class Main:
# Gets the methods from the classes and sets to handler.
# Then, builder connects to any signals it needs.
classes = [CrossClassSignals(settings),
GridSignals(settings)]
GridSignals(settings),
TaskbarSignals(settings)]
handlers = {}
for c in classes:

View File

@ -67,7 +67,7 @@
<property name="can_focus">True</property>
<property name="margin">6</property>
<property name="selection_mode">multiple</property>
<property name="columns">6</property>
<property name="item_width">72</property>
</object>
</child>
</object>
@ -79,6 +79,62 @@
<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="GtkButtonBox" id="taskBarButtons">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">start</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="taskBarWorkspaces">
<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>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
@ -87,6 +143,134 @@
<property name="can_focus">False</property>
<property name="stock">gtk-new</property>
</object>
<object class="GtkPopover" id="taskbarMenu">
<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">Minimize</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="toggleMinimize" 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">Maximize</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="toggleMaximize" 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">Move</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="startMoveWindow" 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">Resixze</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="startResizeWindow" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton">
<property name="label" translatable="yes">Always On Top</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="setTopState" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton">
<property name="label" translatable="yes">Always Below</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="setBelowState" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkCheckButton">
<property name="label" translatable="yes">Always On Visible Workspace</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="setWorkspacePin" 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">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="closeAppWindow" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">7</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="trashImage">
<property name="visible">True</property>
<property name="can_focus">False</property>

View File

@ -0,0 +1,181 @@
# 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
# Python imports
import threading
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class MouseButtons:
LEFT_BUTTON = 1
RIGHT_BUTTON = 3
class TaskbarSignals:
def __init__(self, settings):
self.settings = settings
self.builder = self.settings.returnBuilder()
self.taskBarButtons = self.builder.get_object('taskBarButtons')
self.taskbarMenu = self.builder.get_object('taskbarMenu')
self.SCREEN = wnck.Screen.get_default()
self.actv_workspace_num = None
self.window = None
self.SCREEN.force_update() # (Re)populate screen windows list
self.refreashTaskbar()
self.setScreenSignals()
self.setPagerWidget()
def refreashTaskbar(self):
workspace = self.SCREEN.get_active_workspace()
self.actv_workspace_num = workspace.get_number()
windows = self.SCREEN.get_windows()
for w in windows:
if workspace and w.get_workspace():
wnum = w.get_workspace().get_number()
if not w.is_skip_pager() and not w.is_skip_tasklist() and wnum == self.actv_workspace_num:
btn = self.createWinBttn(w)
self.setupSignals(btn, w)
self.taskBarButtons.add(btn)
def setupSignals(self, btn, win):
btn.connect("button-press-event", self.clickEvent, (win))
def setScreenSignals(self):
self.SCREEN.connect("active-workspace-changed", self.activeWorkspaceChanged)
# self.SCREEN.connect("application-opened", self.applicationOpened)
# self.SCREEN.connect("application-closed", self.applicationClosed)
self.SCREEN.connect("window-opened", self.windowOpened)
self.SCREEN.connect("window-closed", self.windowClosed)
def createWinBttn(self, w):
btn = gtk.Button(label=w.get_name(), always_show_image=True)
img = gtk.Image()
img.set_from_pixbuf( w.get_icon() ) # w.get_mini_icon() or w.get_icon()
btn.set_image(img)
btn.show()
return btn
def clickEvent(self, widget, e, window):
if e.type == gdk.EventType.BUTTON_PRESS and e.button == MouseButtons.LEFT_BUTTON:
if not window.is_minimized():
window.minimize()
else:
window.activate(1)
if e.type == gdk.EventType.BUTTON_PRESS and e.button == MouseButtons.RIGHT_BUTTON:
self.window = window
self.taskbarMenu.set_relative_to(widget)
self.taskbarMenu.popup()
def setPagerWidget(self):
pager = wnck.Pager()
self.builder.get_object('taskBarWorkspaces').add(pager)
# ---- Screen Events ----
# NOTE: This is the worst way of doing this and kids die when these are run.
# We need to filter actions and more like add/remove buttons than just
# clearing everything. I'm sorry to all the families hurt by this....
def activeWorkspaceChanged(self, screen, workspace):
self.clearChildren(self.taskBarButtons)
self.SCREEN = screen
self.SCREEN.force_update() # (Re)populate screen windows list
self.refreashTaskbar()
def windowOpened(self, screen, window):
self.SCREEN.force_update() # (Re)populate screen windows list
btn = self.createWinBttn(window)
self.setupSignals(btn, window)
self.taskBarButtons.add(btn)
def windowClosed(self, screen, window):
self.clearChildren(self.taskBarButtons)
self.SCREEN.force_update() # (Re)populate screen windows list
self.refreashTaskbar()
def clearChildren(self, parent):
children = parent.get_children();
for child in parent:
child.destroy()
# ---- Taskbar Button Events ----
def toggleMinimize(self, widget, data=None):
if not self.window.is_minimized():
self.window.minimize()
widget.set_label("Unminimize")
else:
self.window.activate(1)
widget.set_label("Minimize")
def toggleMaximize(self, widget, data=None):
if not self.window.is_maximized():
self.window.maximize()
widget.set_label("Unmaximize")
else:
self.window.unmaximize()
widget.set_label("Maximize")
def startMoveWindow(self, widget, data=None):
self.window.keyboard_move()
def startResizeWindow(self, widget, data=None):
self.window.keyboard_size()
def setTopState(self, widget):
if not self.window.is_above():
self.window.make_above()
else:
self.window.unmake_above()
def setBelowState(self, widget):
if not self.window.is_above():
self.window.make_below()
else:
self.window.unmake_below()
def setWorkspacePin(self, widget):
if not self.window.is_pinned():
self.window.pin()
else:
self.window.unpin()
def closeAppWindow(self, widget, data=None):
self.window.close(1)
# WINDOW_SIGNALS
# print(w.get_icon())
# w.get_name()
# w.get_icon()
# w.get_mini_icon()
# w.make_above()
# w. pin()
# w. get_state() # https://lazka.github.io/pgi-docs/Wnck-3.0/flags.html#Wnck.WindowState
# w.get_workspace()
# w.set_workspace(workspace)
# w.close()
# w.is_above()
# w.is_active()
# w.is_below()
# w.is_fullscreen()
# w.is_maximized()
# w.is_minimized()
# w.is_pinned()
# w.is_sticky()

View File

@ -1,2 +1,3 @@
from signal_classes.CrossClassSignals import CrossClassSignals
from signal_classes.GridSignals import GridSignals
from signal_classes.TaskbarSignals import TaskbarSignals

View File

@ -35,24 +35,22 @@ class FileHandler:
self.TRASHINFOFOLDER = settings.returnTrshInfoPth()
@threaded
def openFile(self, file):
print("Opening: " + file)
if file.lower().endswith(self.vids):
subprocess.Popen([self.MEDIAPLAYER, self.MPV_WH, file])
subprocess.Popen([self.MEDIAPLAYER, self.MPV_WH, file], stdout=subprocess.PIPE)
elif file.lower().endswith(self.music):
subprocess.Popen([self.MUSICPLAYER, file])
subprocess.Popen([self.MUSICPLAYER, file], stdout=subprocess.PIPE)
elif file.lower().endswith(self.images):
subprocess.Popen([self.IMGVIEWER, file])
subprocess.Popen([self.IMGVIEWER, file], stdout=subprocess.PIPE)
elif file.lower().endswith(self.txt):
subprocess.Popen([self.TEXTVIEWER, file])
subprocess.Popen([self.TEXTVIEWER, file], stdout=subprocess.PIPE)
elif file.lower().endswith(self.pdf):
subprocess.Popen([self.PDFVIEWER, file])
subprocess.Popen([self.PDFVIEWER, file], stdout=subprocess.PIPE)
elif file.lower().endswith(self.office):
subprocess.Popen([self.OFFICEPROG, file])
subprocess.Popen([self.OFFICEPROG, file], stdout=subprocess.PIPE)
else:
subprocess.Popen(['xdg-open', file])
subprocess.Popen(['xdg-open', file], stdout=subprocess.PIPE)
def create(self, name, type):

View File

@ -50,7 +50,7 @@ class Grid:
self.grid.connect("item-activated", self.iconDblLeftClick)
self.grid.connect("button_release_event", self.iconSingleClick, (self.grid,))
# @threaded
def setNewDirectory(self, path):
self.currentPath = path
dirPaths = ['.', '..']
@ -112,7 +112,8 @@ class Grid:
for dataSet in self.toWorkPool:
self.store.append([dataSet[0].get_pixbuf(), dataSet[1]])
self.toWorkPool.clear()
self.toWorkPool.clear()
if len(self.store) == len(files): # Processed all files
return False
else: # Check again when idle