Compare commits

..

3 Commits

Author SHA1 Message Date
5e3eec9611 Updated README; improved settings setup 2023-09-29 17:24:16 -05:00
35383a95cb Major refactor to match my template project 2023-02-23 12:42:28 -06:00
7fcdc950fc Fixed bugs 2022-01-24 00:31:27 -06:00
103 changed files with 1947 additions and 6118 deletions

View File

@@ -1,13 +1,15 @@
# GWinWrap
GWinWrap is a Gtk with Python gui to select videos for XWinWrap, images for Nitrogen Wallpaper Manager, and gifs for Gifsicle.
It includes the XWinWrap binary and source code for Shantanu Goel's version of XWinWrap.
GWinWrap is a Python application with a Gtk UI to select videos, gifs (or other images), or an xscreensaver as your desktop wallpaper/background.
This includes the XWinWrap binary and source code from Shantanu Goel's version of XWinWrap.
# Notes
* Need python 2+
* Need PyGObject
* When you first run the application and save settings for a screen, you need to chmod 744 the new file(s) in your $HOME directory.
* Need PyGObject and Gtk
* A settings file per screen is generated.
# Install
` sudo pacman -Sy mpv gifsicle nitrogen xscreensaver `
# Images
![1 Default view starting out. ](images/pic1.png)
@@ -19,7 +21,6 @@ It includes the XWinWrap binary and source code for Shantanu Goel's version of X
# TODO
* Better/automatic screen detection.
* Run chmod against newly created launch scripts.
# Credit

Binary file not shown.

Binary file not shown.

2
requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
PyGObject
setproctitle

View File

@@ -1,8 +0,0 @@
Package: gwinwrap64
Version: 0.0-1
Section: python
Priority: optional
Architecture: amd64
Depends: ffmpegthumbnailer (>= 2.0.10-0.1), mplayer (>=2.0-728-g2c378c7-4), gifsicle (>=1.86-1), nitrogen (>=1.5.2-2), xscreensaver (>=5.36-1ubuntu1), xscreensaver-gl (>=5.36-1ubuntu1), xscreensaver-gl-extra (>=5.36-1ubuntu1), xscreensaver-screensaver-dizzy (>=0.3-3), xscreensaver-screensaver-bsod (>=5.36-1ubuntu1), xscreensaver-data (>=5.36-1ubuntu1), xscreensaver-data-extra (>=5.36-1ubuntu1), xscreensaver-screensaver-webcollage (>=5.36-1ubuntu1)
Maintainer: Maxim Stewart <1itdominator@gmail.com>
Description: GWinWrap is a GUI to handle setting XWinWrap options.

View File

@@ -1,11 +0,0 @@
#!/bin/bash
#postrm (script executed after uninstalling the package)
#set -e
if [ -f /bin/xwinwrap ]; then
rm /bin/xwinwrap
fi
if [ -d /opt/GWinWrap ]; then
rm -rf /opt/GWinWrap
fi

View File

@@ -1,9 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Name=GWinWrap
Comment=Glade gui with python controls for XWinWrap
Exec=gwinwrap
Icon=/opt/GWinWrap/resources/icons/GWinWrap.png
Terminal=false
Type=Application
Categories=Accessories;System;Settings;

View File

@@ -1,41 +0,0 @@
#!/usr/bin/python3
# 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
# Python imports
import inspect
from setproctitle import setproctitle
# Application imports
from utils import Settings
from signal_classes import CrossClassSignals
class Main:
def __init__(self):
setproctitle('GWinWrap')
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
faulthandler.enable() # For better debug info
settings = Settings()
builder = settings.returnBuilder()
# Gets the methods from the classes and sets to handler.
# Then, builder connects to any signals it needs.
classes = [CrossClassSignals(settings)]
handlers = {}
for c in classes:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
builder.connect_signals(handlers)
window = settings.createWindow()
window.show()

View File

@@ -1,9 +0,0 @@
from __init__ import Main, gtk
if __name__ == "__main__":
try:
main = Main()
gtk.main()
except Exception as e:
print(e)

View File

@@ -1,844 +0,0 @@
<?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="GtkListStore" id="XScreensaver List">
<columns>
<!-- column-name XScreensavers -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkImage" id="clearImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="closeImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-quit</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="closePopupImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-cancel</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="openProgImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-jump-to</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="saveImag">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="saveImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="settingsImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Settings....</property>
<property name="stock">gtk-properties</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="startImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-play</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="stopImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-stop</property>
<property name="icon_size">3</property>
</object>
<object class="GtkWindow" id="Main_Window">
<property name="width_request">950</property>
<property name="height_request">600</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">GWinWrap</property>
<property name="window_position">center</property>
<property name="default_width">950</property>
<property name="default_height">600</property>
<property name="icon">icons/GWinWrap.png</property>
<property name="gravity">center</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox" id="box1">
<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="margin_left">15</property>
<property name="margin_top">15</property>
<property name="margin_bottom">15</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">5</property>
<child>
<object class="GtkLabel" id="helpLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">15</property>
<property name="label" translatable="yes">Note: Double click an image to view the video or image.</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton" id="selectedDirDialog">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Chose Dream Scene / Image Directory</property>
<property name="action">select-folder</property>
<property name="create_folders">False</property>
<property name="filter">Folders</property>
<property name="title" translatable="yes">Dream Scene / Image Dir</property>
<signal name="file-set" handler="setNewDir" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">settingsImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="popSttingsWindow" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="loadProgress">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_text">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid" id="imageGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="row_spacing">10</property>
<property name="column_spacing">10</property>
<property name="row_homogeneous">True</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkLabel" id="gridLabel">
<property name="width_request">640</property>
<property name="height_request">525</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Choose Image/Video Directory...</property>
<attributes>
<attribute name="font-desc" value="Times New Roman, 28"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</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">Clear</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">clearImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="clearSelection" 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">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="width_request">300</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">15</property>
<property name="margin_top">15</property>
<property name="margin_bottom">15</property>
<property name="hexpand">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="useXScrnList">
<property name="label" translatable="yes">Use XScreenSaver</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">center</property>
<property name="margin_bottom">5</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="toggleXscreenUsageField" swapped="no"/>
</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="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="xScreenSvrList">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="model">XScreensaver List</property>
<property name="headers_visible">False</property>
<signal name="button-press-event" handler="previewXscreen" swapped="no"/>
<signal name="cursor-changed" handler="passXScreenVal" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="listColumn">
<property name="title" translatable="yes">XScreensaves</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</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">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="vexpand">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="label" translatable="yes">Playback Resolutions</property>
</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">10</property>
<property name="margin_bottom">10</property>
<property name="label" translatable="yes">Position Offset</property>
</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="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkComboBoxText" id="playbackResolution">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="active">3</property>
<items>
<item translatable="yes">7680x4320</item>
<item translatable="yes">3840x2160</item>
<item translatable="yes">2048x1080</item>
<item translatable="yes">1920x1080</item>
<item translatable="yes">1440x720</item>
<item translatable="yes">1600x900</item>
<item translatable="yes">1280x720</item>
<item translatable="yes">800x600</item>
</items>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="posOffset">
<property name="visible">True</property>
<property name="can_focus">False</property>
</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">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="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">10</property>
<property name="margin_bottom">5</property>
<property name="label" translatable="yes">Save Path</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="saveLoc">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="active">0</property>
<items>
<item translatable="yes">.animatedBGstarter.sh</item>
<item translatable="yes">.animatedBGstarter2.sh</item>
<item translatable="yes">.animatedBGstarter3.sh</item>
</items>
</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">1</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">saveImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="saveToFile" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">(Re)Start</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">startImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="applySttngs" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Stop</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">stopImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="killXWinWrp" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">closeImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="closeProgram" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</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">False</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">1</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkPopover" id="demoPreviewPopWindow">
<property name="width_request">640</property>
<property name="height_request">525</property>
<property name="can_focus">False</property>
<property name="margin_right">350</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="relative_to">helpLabel</property>
<property name="position">bottom</property>
<property name="modal">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="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Close Demo Window</property>
<property name="image">closePopupImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="closeDemoWindow" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</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="GtkAspectFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkDrawingArea" id="demoPreview">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</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="GtkPopover" id="previewWindow">
<property name="width_request">640</property>
<property name="height_request">525</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="relative_to">helpLabel</property>
<property name="position">bottom</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButtonBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="baseline_position">bottom</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Main Image Viewer</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">openProgImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="openMainImageViewer" 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="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="closePopup" swapped="no"/>
</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">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<property name="overlay_scrolling">False</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="previewImg">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
<property name="icon_size">6</property>
</object>
</child>
</object>
</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="GtkPopover" id="settingsWindow">
<property name="width_request">250</property>
<property name="can_focus">False</property>
<property name="relative_to">button1</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixbuf">icons/folder.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="customDefaultPath">
<property name="width_request">330</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Set Custom Default Path</property>
<property name="placeholder_text" translatable="yes">Set Custom Default Path</property>
</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">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixbuf">icons/player.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="customVideoPlyr">
<property name="width_request">330</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Set Custom Video Player</property>
<property name="placeholder_text" translatable="yes">Set Custom Video Player</property>
</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">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixbuf">icons/picture.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="customImgVwr">
<property name="width_request">330</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Set Custom Image Viewer</property>
<property name="placeholder_text" translatable="yes">Set Custom Image Viewer</property>
</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>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">saveImag</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="saveToSettingsFile" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -1,397 +0,0 @@
# 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
# Python imports
import threading, subprocess, signal, os, sys, re, hashlib, time
from os import listdir
from os.path import isfile, join
# Application imports
from utils import SaveStateToXWinWarp, SaveGWinWrapSettings
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class CrossClassSignals:
def __init__(self, settings):
self.settings = settings
self.builder = self.settings.returnBuilder()
self.WINDOW = self.builder.get_object("Main_Window").get_window()
self.stateSaver = SaveStateToXWinWarp()
self.sttngsSver = SaveGWinWrapSettings()
# Add filter to allow only folders to be selected
dialog = self.builder.get_object("selectedDirDialog")
filefilter = self.builder.get_object("Folders")
dialog.add_filter(filefilter)
# Get reference to remove and add it back...
self.gridLabel = self.builder.get_object("gridLabel")
self.focusedImg = gtk.Image()
self.usrHome = os.path.expanduser('~')
self.xScreenVal = None
self.toSavePath = None # Global file path and type for saving to file
self.applyType = 1 # 1 is XWinWrap and 2 is Nitrogen
self.loadProgress = self.builder.get_object("loadProgress")
self.helpLabel = self.builder.get_object("helpLabel")
self.defaultLabel = "<span>Note: Double click an image to view the video or image.</span>"
self.savedLabel = "<span foreground=\"#88cc27\">Saved settings...</span>"
self.appliedLabel = "<span foreground=\"#88cc27\">Running xwinwrap...</span>"
self.stoppedLabel = "<span foreground=\"#88cc27\">Stopped xwinwrap...</span>"
# foreground=\"#ffa800\"
# foreground=\"#88cc27\"
# foreground=\"#ff0000\"
# Fill list xscreensaver
self.xscrPth = "/usr/lib/xscreensaver/"
xscreenList = self.builder.get_object("XScreensaver List")
list = [f for f in listdir(self.xscrPth) if isfile(join(self.xscrPth, f))]
list.sort()
for file in list:
xscreenList.append((file,))
self.selectedImg = None # EventBox holder
self.defPath = None
self.player = None
self.imgVwr = None
self.demoAreaPid = None
self.setPosData()
self.retrieveSettings()
def setNewDir(self, widget, data=None):
dir = widget.get_filename()
threading.Thread(target=self.newDir, args=(dir,)).start()
@threaded
def newDir(self, dir):
imageGrid = self.builder.get_object("imageGrid")
dirPath = dir
list = [f for f in listdir(dirPath) if isfile(join(dirPath, f))]
files = []
row = 0
col = 0
for file in list:
if file.lower().endswith(('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm', '.png', '.jpg', '.jpeg', '.gif')):
files.append(file)
fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files)
tickCount = 0.0
self.clear()
imageGrid.remove_column(0)
self.loadProgress.set_text("Loading...")
self.loadProgress.set_fraction(0.0)
self.helpLabel.set_markup("<span foreground=\"#b30ec2\">" + dirPath.strip(self.usrHome) + "</span>")
for file in files:
fullPathFile = dirPath + "/" + file
eveBox = gtk.EventBox()
thumbnl = gtk.Image()
if file.lower().endswith(('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')):
fileHash = hashlib.sha256(str.encode(fullPathFile)).hexdigest()
hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png"
if isfile(hashImgpth) == False:
self.generateThumbnail(fullPathFile, hashImgpth)
thumbnl = self.createGtkImage(hashImgpth, [310, 310])
eveBox.connect("button_press_event", self.runMplayerProcess, (fullPathFile, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouseOver, ())
eveBox.connect("leave_notify_event", self.mouseOut, ())
elif file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
thumbnl = self.createGtkImage(fullPathFile, [310, 310])
eveBox.connect("button_press_event", self.runImageViewerProcess, (fullPathFile, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouseOver, ())
eveBox.connect("leave_notify_event", self.mouseOut, ())
else:
print("Not a video or image file.")
continue
glib.idle_add(self.preGridSetup, (eveBox, thumbnl, ))
glib.idle_add(self.addToGrid, (imageGrid, eveBox, col, row,))
tickCount = tickCount + fractionTick
self.loadProgress.set_fraction(tickCount)
col += 1
if col == 2:
col = 0
row += 1
self.loadProgress.set_text("Finished...")
def preGridSetup(self, args):
args[0].show()
args[1].show()
args[0].add(args[1])
def addToGrid(self, args):
args[0].attach(args[1], args[2], args[3], 1, 1)
def generateThumbnail(self, fullPathFile, hashImgpth):
# Stream duration
command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPathFile]
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", fullPathFile]
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", fullPathFile]
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", fullPathFile]
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, "-i", fullPathFile, "-an", "-vframes", "1", "-s", "320x180", "-q:v", "2", hashImgpth]
subprocess.call(command)
def createGtkImage(self, path, wxh):
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
filename = path,
width = wxh[0],
height = wxh[1],
preserve_aspect_ratio = True)
return gtk.Image.new_from_pixbuf(pixbuf)
except Exception as e:
print(e)
return gtk.Image()
def openMainImageViewer(self, widget):
subprocess.call([self.imgVwr, self.toSavePath])
def runImageViewerProcess(self, widget, eve, params):
self.setSelected(params[2])
if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS:
previewWindow = self.builder.get_object("previewWindow")
previewImg = self.builder.get_object("previewImg")
previewImg.set_from_file(params[0])
previewWindow.show_all()
previewWindow.popup()
self.toSavePath = params[0]
self.applyType = 2
self.helpLabel.set_markup("<span foreground=\"#e0cc64\">" + params[1] + "</span>")
def setSelected(self, eveBox):
if self.selectedImg:
col = gdk.RGBA(0.0, 0.0, 0.0, 0.0)
self.selectedImg.override_background_color(gtk.StateType.NORMAL, col)
col = gdk.RGBA(0.9, 0.7, 0.4, 0.74)
eveBox.override_background_color(gtk.StateType.NORMAL, col)
self.selectedImg = eveBox
def closePopup(self, widget):
self.builder.get_object("previewWindow").popdown()
def mouseOver(self, widget, eve, args):
hand_cursor = gdk.Cursor(gdk.CursorType.HAND2)
self.builder.get_object("Main_Window").get_window().set_cursor(hand_cursor)
def mouseOut(self, widget, eve, args):
watch_cursor = gdk.Cursor(gdk.CursorType.LEFT_PTR)
self.builder.get_object("Main_Window").get_window().set_cursor(watch_cursor)
def toggleXscreenUsageField(self, widget, data=None):
useXscreenSaver = self.builder.get_object("useXScrnList")
if useXscreenSaver.get_active():
self.builder.get_object("xScreenSvrList").set_sensitive(True)
else:
self.builder.get_object("xScreenSvrList").set_sensitive(False)
def popSttingsWindow(self, widget):
self.builder.get_object("settingsWindow").popup()
def saveToSettingsFile(self, widget):
self.defPath = self.builder.get_object("customDefaultPath").get_text().strip()
self.player = self.builder.get_object("customVideoPlyr").get_text().strip()
self.imgVwr = self.builder.get_object("customImgVwr").get_text().strip()
self.sttngsSver.saveSettings(self.defPath, self.player, self.imgVwr)
def retrieveSettings(self):
data = self.sttngsSver.retrieveSettings()
self.defPath = data[0]
self.player = data[1]
self.imgVwr = data[2]
self.builder.get_object("customDefaultPath").set_text(self.defPath)
self.builder.get_object("customVideoPlyr").set_text(self.player)
self.builder.get_object("customImgVwr").set_text(self.imgVwr)
self.builder.get_object("selectedDirDialog").set_filename(self.defPath)
if self.defPath:
self.newDir(self.defPath)
def saveToFile(self, widget, data=None):
saveLoc = self.builder.get_object("saveLoc").get_active_text()
useXscreenSaver = self.builder.get_object("useXScrnList").get_active()
plyBckRes = self.builder.get_object("playbackResolution")
offset4Res = self.builder.get_object("posOffset")
resolution = plyBckRes.get_active_text() + offset4Res.get_active_text()
self.applyType = self.stateSaver.saveToFile(self.toSavePath, resolution,
saveLoc, useXscreenSaver, self.xScreenVal, self.player)
if self.applyType == -1:
self.helpLabel.set_markup("<span foreground=\"#e0cc64\">Nothing saved...</span>")
return
self.helpLabel.set_markup(self.savedLabel)
def applySttngs(self, widget, data=None):
os.system("killall xwinwrap &")
if self.applyType == 1:
files = os.listdir(self.usrHome)
for file in files:
fPath = self.usrHome + "/" + file
if os.path.isfile(fPath) and "animatedBGstarter" in file:
os.system("bash -c '~/" + file + "' &")
elif self.applyType == 2:
os.system("nitrogen --restore &")
else:
os.system("nitrogen --restore &")
self.helpLabel.set_markup(self.appliedLabel)
def killXWinWrp(self, widget, data=None):
os.system("killall xwinwrap &")
self.helpLabel.set_markup(self.stoppedLabel)
def passXScreenVal(self, widget):
xSvrListStore = self.builder.get_object("XScreensaver List")
row = widget.get_cursor()
path = gtk.TreePath(row.path)
treeiter = xSvrListStore.get_iter(path[0])
self.xScreenVal = xSvrListStore.get_value(treeiter, 0)
def runMplayerProcess(self, widget, eve, params):
self.setSelected(params[2])
video = params[0]
if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS:
if self.player == "mplayer":
xid = self.getXID()
command = [self.player, video, "-slave", "-wid", str(xid), "-really-quiet", "-ao", "null", "-loop", "0"]
self.runDemoToDrawArea(command)
else:
subprocess.call([self.player, video, "-really-quiet", "-ao", "null", "-loop", "0"])
self.toSavePath = params[0]
self.applyType = 1
self.helpLabel.set_markup("<span foreground=\"#e0cc64\">" + params[1] + "</span>")
def previewXscreen(self, widget, eve):
if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS:
demoXscrnSaver = self.xscrPth + self.xScreenVal
xid = self.getXID()
command = [demoXscrnSaver, "-window-id", str(xid)]
self.runDemoToDrawArea(command)
def getXID(self):
# Must be actualized before getting window
demoWindowPopup = self.builder.get_object("demoPreviewPopWindow")
if demoWindowPopup.get_visible() == False:
demoWindowPopup.show_all()
demoWindowPopup.popup()
demoPreview = self.builder.get_object("demoPreview")
drwWindow = demoPreview.get_window()
return drwWindow.get_xid()
def runDemoToDrawArea(self, command):
self.helpLabel.set_markup("<span foreground=\"#e0cc64\"></span>")
if self.demoAreaPid:
os.kill(self.demoAreaPid, signal.SIGTERM) #or signal.SIGKILL
self.demoAreaPid = None
time.sleep(.800) # 800 mili-seconds to ensure first process dead
process = subprocess.Popen(command)
self.demoAreaPid = process.pid
def closeDemoWindow(self, widget, data=None):
os.kill(self.demoAreaPid, signal.SIGTERM) #or signal.SIGKILL
self.demoAreaPid = None
time.sleep(.200)
self.builder.get_object("demoPreviewPopWindow").popdown()
def clearSelection(self, widget, data=None):
self.clear()
def clear(self):
imageGrid = self.builder.get_object("imageGrid")
while True:
if imageGrid.get_child_at(0,0)!= None:
imageGrid.remove_row(0)
else:
break
imageGrid.attach(self.gridLabel, 0, 0, 1, 1)
self.builder.get_object("xScreenSvrList").set_sensitive(False)
self.builder.get_object("useXScrnList").set_active(False)
self.helpLabel.set_markup(self.defaultLabel)
self.loadProgress.set_text("")
self.loadProgress.set_fraction(0.0)
self.toSavePath = None
self.xScreenVal = None
self.applyType = 1 # Default to XWinWrap
def setPosData(self):
monitors = self.settings.getMonitorData()
posOff = self.builder.get_object("posOffset")
for monitor in monitors:
if monitor.x >= 0 and monitor.y >= 0:
posOff.append_text("+" + str(monitor.x) + "+" + str(monitor.y))
elif monitor.x <= 0 and monitor.y <= 0:
posOff.append_text(str(monitor.x) + str(monitor.y))
elif monitor.x >= 0 and monitor.y <= 0:
posOff.append_text("+" + str(monitor.x) + str(monitor.y))
elif monitor.x <= 0 and monitor.y >= 0:
posOff.append_text(str(monitor.x) + "+" + str(monitor.y))
posOff.set_active(0)
def closeProgram(self, widget, data=None):
sys.exit(0)

View File

@@ -1 +0,0 @@
from signal_classes.CrossClassSignals import CrossClassSignals

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env python
import os, json
class SaveGWinWrapSettings:
def __init__(self):
configFolder = os.path.expanduser('~') + "/.config/gwinwrap/"
self.configFile = configFolder + "settings.ini"
if os.path.isdir(configFolder) == False:
os.mkdir(configFolder)
if os.path.isfile(self.configFile) == False:
open(self.configFile, 'a').close()
def saveSettings(self, defPath, player, imgVwr):
data = {}
data['gwinwrap_settings'] = []
data['gwinwrap_settings'].append({
'defPath' : defPath,
'player' : player,
'imgvwr' : imgVwr
})
with open(self.configFile, 'w') as outfile:
json.dump(data, outfile)
def retrieveSettings(self):
returnData = []
with open(self.configFile) as infile:
try:
data = json.load(infile)
for obj in data['gwinwrap_settings']:
returnData = [obj['defPath'], obj['player'], obj['imgvwr']]
except Exception as e:
returnData = ['', 'mplayer', 'xdg-open']
if returnData[0] == '':
returnData[0] = ''
if returnData[1] == '':
returnData[1] = 'mplayer'
if returnData[2] == '':
returnData[2] = 'xdg-open'
return returnData

View File

@@ -1,69 +0,0 @@
#!/usr/bin/env python
import os
class SaveStateToXWinWarp:
def __init__(self):
self.fileWriter = None
self.toSavePath = None
self.useXSvrn = None
self.xScreenVal = None
self.sveFileLoc = None
self.resolution = None
self.player = None
def saveToFile(self, toSavePath, resolution,
saveLoc, useXSvrn, xScreenVal, player):
self.toSavePath = toSavePath
self.useXSvrn = useXSvrn
self.xScreenVal = xScreenVal
self.resolution = resolution
self.player = player
userPth = os.path.expanduser('~')
# Saves to file with selected and needed settings
if toSavePath:
if toSavePath.lower().endswith(('.png', '.jpg', '.jpeg')):
self.sveFileLoc = userPth + "/" + ".config/nitrogen/bg-saved.cfg"
else:
self.sveFileLoc = userPth + "/" + saveLoc
elif useXSvrn and xScreenVal:
self.sveFileLoc = userPth + "/" + saveLoc
else:
return -1
if self.sveFileLoc:
self.fileWriter = open(self.sveFileLoc, "w")
return self.startSave()
def startSave(self):
applyType = 1
output = None
# XSCREENSAVER
if self.useXSvrn:
output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- /usr/lib/xscreensaver/" + self.xScreenVal + " -window-id WID -root";
# GIF
elif self.toSavePath.lower().endswith(('.gif')):
output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- gifview -a -w WID " + self.toSavePath;
# Standard images using nitrogen
elif self.toSavePath.lower().endswith(('.png', 'jpg', '.jpeg')):
output = "[xin_0] \nfile=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000\n\n[xin_1] \nfile=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000";
applyType = 2;
# VIDEO
else:
output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- " + self.player + " -wid WID -really-quiet -ao null -loop 0 '" + self.toSavePath + "'";
pass
try:
if self.fileWriter:
self.fileWriter.write(output)
self.fileWriter.close()
except Exception as e:
print(":: Write failed! ::")
print(e)
return applyType;

View File

@@ -1,74 +0,0 @@
# 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
# Application imports
class Settings:
def __init__(self):
self.builder = gtk.Builder()
self.builder.add_from_file("resources/Main_Window.glade")
# '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')
def createWindow(self):
# Get window and connect signals
window = self.builder.get_object("Main_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('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)
def getMonitorData(self):
screen = self.builder.get_object("Main_Window").get_screen()
monitors = []
for m in range(screen.get_n_monitors()):
monitors.append(screen.get_monitor_geometry(m))
for monitor in monitors:
print(str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y))
return monitors
def returnBuilder(self): return self.builder
# 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

View File

@@ -1,3 +0,0 @@
from utils.Settings import Settings
from utils.SaveStateToXWinWarp import SaveStateToXWinWarp
from utils.SaveGWinWrapSettings import SaveGWinWrapSettings

View File

@@ -1,22 +0,0 @@
GWinWrap is copyright 2016, 2017 Maxim Stewart.
GWinWrap is currently developed by ITDominator <1itdominator@gmail.com>.
License: GPLv2+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
See /usr/share/common-licenses/GPL-2, or
<http://www.gnu.org/copyleft/gpl.txt> for the terms of the latest version
of the GNU General Public License.

View File

@@ -6,8 +6,16 @@ if [ -f /bin/xwinwrap ]; then
rm /bin/xwinwrap
fi
if [ -d /opt/GWinWrap ]; then
rm -rf /opt/GWinWrap
if [ -f /bin/gwinwrap ]; then
rm /bin/gwinwrap
fi
if [ -f /usr/share/applications/gwinwrap.desktop ]; then
rm /usr/share/applications/gwinwrap.desktop
fi
if [ -f /opt/gwinwrap.zip ]; then
rm /opt/gwinwrap.zip
fi
if [ -d /usr/share/gwinwrap ]; then

View File

@@ -1,73 +0,0 @@
import builtins
# Python imports
import builtins
# Lib imports
# Application imports
from signal_classes import IPCServerMixin
class Builtins(IPCServerMixin):
"""Docstring for __builtins__ extender"""
def __init__(self):
# NOTE: The format used is list of [type, target, data]
# Where data may be any kind of data
self._gui_events = []
self._fm_events = []
self.is_ipc_alive = False
self.ipc_authkey = b'GWinWrap-ipc'
self.ipc_address = '127.0.0.1'
self.ipc_port = 8888
self.ipc_timeout = 15.0
# Makeshift fake "events" type system FIFO
def _pop_gui_event(self):
if len(self._gui_events) > 0:
return self._gui_events.pop(0)
return None
def _pop_fm_event(self):
if len(self._fm_events) > 0:
return self._fm_events.pop(0)
return None
def push_gui_event(self, event):
if len(event) == 3:
self._gui_events.append(event)
return None
raise Exception("Invald event format! Please do: [type, target, data]")
def push_fm_event(self, event):
if len(event) == 3:
self._fm_events.append(event)
return None
raise Exception("Invald event format! Please do: [type, target, data]")
def read_gui_event(self):
return self._gui_events[0]
def read_fm_event(self):
return self._fm_events[0]
def consume_gui_event(self):
return self._pop_gui_event()
def consume_fm_event(self):
return self._pop_fm_event()
# NOTE: Just reminding myself we can add to builtins two different ways...
# __builtins__.update({"event_system": Builtins()})
builtins.app_name = "GWinWrap"
builtins.event_system = Builtins()
builtins.event_sleep_time = 0.2
builtins.debug = False
builtins.trace_debug = False

View File

@@ -1,50 +0,0 @@
# Python imports
import os, inspect, time
# Lib imports
# Application imports
from utils import Settings
from signal_classes import Controller
from __builtins__ import Builtins
class Main(Builtins):
def __init__(self, args, unknownargs):
if not debug:
event_system.create_ipc_server()
time.sleep(0.2)
if not trace_debug:
if not event_system.is_ipc_alive:
if unknownargs:
for arg in unknownargs:
if os.path.isdir(arg):
message = f"FILE|{arg}"
event_system.send_ipc_message(message)
raise Exception("IPC Server Exists: Will send data to it and close...")
settings = Settings()
settings.create_window()
controller = Controller(settings, args, unknownargs)
if not controller:
raise Exception("Controller exited and doesn't exist...")
# Gets the methods from the classes and sets to handler.
# Then, builder from settings will connect to any signals it needs.
classes = [controller]
handlers = {}
for c in classes:
methods = None
try:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
except Exception as e:
print(repr(e))
settings.get_builder().connect_signals(handlers)

View File

@@ -1,39 +0,0 @@
#!/usr/bin/python3
# Python imports
import argparse, faulthandler, traceback
from setproctitle import setproctitle
import tracemalloc
tracemalloc.start()
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from __init__ import Main
if __name__ == "__main__":
try:
# import web_pdb
# web_pdb.set_trace()
setproctitle('GWinWrap')
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, unknownargs = parser.parse_known_args()
Main(args, unknownargs)
Gtk.main()
except Exception as e:
traceback.print_exc()
quit()

View File

@@ -1,151 +0,0 @@
# Python imports
import threading, signal, subprocess, inspect, os, time
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk, GLib, Gdk
# Application imports
from .mixins import *
from . import Controller_Data
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class Controller(ThumbnailMixin, ImageViewerMixin, DrawAreaMixin, GridMixin, Controller_Data):
def __init__(self, _settings, args, unknownargs):
self.setup_controller_data(_settings)
self.window.show()
self.retrieve_settings()
def tear_down(self, widget=None, eve=None):
event_system.send_ipc_message("close server")
if self.demo_area_pid:
self.close_demo_popup()
self.close_image_popup()
time.sleep(event_sleep_time)
Gtk.main_quit()
def close_program(self, widget, data=None):
self.tear_down()
@threaded
def gui_event_observer(self):
while True:
time.sleep(event_sleep_time)
event = event_system.consume_gui_event()
if event:
try:
type, target, data = event
method = getattr(self.__class__, type)
GLib.idle_add(method, (self, data,))
except Exception as e:
print(repr(e))
def apply_settings(self, widget, data=None):
os.system("killall xwinwrap &")
user_home = self.settings.get_home_path()
if self.apply_type == 1:
files = os.listdir(user_home)
for file in files:
fPath = f"{user_home}/{file}"
if os.path.isfile(fPath) and "animatedBGstarter" in file:
os.system(f"bash -c '~/{file}' &")
elif self.apply_type == 2:
os.system("nitrogen --restore &")
else:
os.system("nitrogen --restore &")
self.help_label.set_markup(self.appliedLabel)
def save_to_settings_file(self, widget):
self.start_path = self.builder.get_object("customStartPath").get_text().strip()
self.default_player = self.builder.get_object("customVideoPlayer").get_text().strip()
self.default_img_viewer = self.builder.get_object("customImgViewer").get_text().strip()
self.settings_saver.save_settings(self.start_path, self.default_player, self.default_img_viewer)
def save_to_file(self, widget, data=None):
save_location = self.builder.get_object("saveLoc").get_active_text()
use_xscreensvr = self.builder.get_object("useXScrnList").get_active()
playBackRes = self.builder.get_object("playbackResolution")
monitorOffset = self.builder.get_object("monitorOffsetData")
resolution = playBackRes.get_active_text() + monitorOffset.get_active_text()
self.apply_type = self.state_saver.save_to_file(self.to_be_background, resolution, save_location, use_xscreensvr, self.xscreen_value, self.default_player)
if self.apply_type == -1:
self.help_label.set_markup("<span foreground='#e0cc64'>Nothing saved...</span>")
return
self.help_label.set_markup(self.savedLabel)
def toggle_xscreen_list(self, widget, data=None):
use_xscreensvr = self.builder.get_object("useXScrnList")
if use_xscreensvr.get_active():
self.builder.get_object("xScreenSvrList").set_sensitive(True)
else:
self.builder.get_object("xScreenSvrList").set_sensitive(False)
def show_settings_popup(self, widget):
self.builder.get_object("settingsWindow").popup()
def preview_xscreensaver(self, widget, eve):
if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
demoXscrnSaver = self.xscreensavers + self.xscreen_value
xid = self.getXID()
command = [demoXscrnSaver, "-window-id", str(xid)]
self.run_demo_in_draw_area(command)
def pass_xscreen_value(self, widget):
row = widget.get_cursor()
path = Gtk.TreePath(row.path)
treeiter = self.xscreen_store.get_iter(path[0])
self.xscreen_value = self.xscreen_store.get_value(treeiter, 0)
def kill_xwinwrap(self, widget, data=None):
os.system("killall xwinwrap &")
self.help_label.set_markup(self.stoppedLabel)
def set_selected_eve_box(self, eveBox):
if self.selected_eve_box:
color = Gdk.RGBA(0.0, 0.0, 0.0, 0.0)
self.selected_eve_box.override_background_color(Gtk.StateType.NORMAL, color)
color = Gdk.RGBA(0.9, 0.7, 0.4, 0.74)
eveBox.override_background_color(Gtk.StateType.NORMAL, color)
self.selected_eve_box = eveBox
def mouse_over(self, widget, eve, args):
hand_cursor = Gdk.Cursor(Gdk.CursorType.HAND2)
self.window.get_window().set_cursor(hand_cursor)
def mouse_out(self, widget, eve, args):
watch_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
self.window.get_window().set_cursor(watch_cursor)
def get_clipboard_data(self):
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE)
retcode = proc.wait()
data = proc.stdout.read()
return data.decode("utf-8").strip()
def set_clipboard_data(self, data):
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
proc.stdin.write(data)
proc.stdin.close()
retcode = proc.wait()

View File

@@ -1,102 +0,0 @@
# Python imports
import signal
from os import listdir
from os.path import isfile, join
# Lib imports
from gi.repository import GLib
# Application imports
from . import SaveStateToXWinWarp, SaveGWinWrapSettings
class Controller_Data:
def has_method(self, obj, name):
return callable(getattr(obj, name, None))
def setup_controller_data(self, _settings):
self.settings = _settings
self.state_saver = SaveStateToXWinWarp(_settings)
self.settings_saver = SaveGWinWrapSettings(_settings)
self.builder = self.settings.get_builder()
self.window = self.settings.get_main_window()
self.logger = self.settings.get_logger()
self.home_path = self.settings.get_home_path()
self.success_color = self.settings.get_success_color()
self.warning_color = self.settings.get_warning_color()
self.error_color = self.settings.get_error_color()
self.image_grid = self.builder.get_object("imageGrid")
self.grid_label = self.builder.get_object("gridLabel")
self.help_label = self.builder.get_object("helpLabel")
self.xscreen_store = self.builder.get_object("XScreensaverStore")
self.defaultLabel = "<span>Note: Double click an image to view the video or image.</span>"
self.savedLabel = f"<span foreground='{self.success_color}'>Saved settings...</span>"
self.appliedLabel = f"<span foreground='{self.success_color}'>Running xwinwrap...</span>"
self.stoppedLabel = f"<span foreground='{self.success_color}'>Stopped xwinwrap...</span>"
# Add filter to allow only folders to be selected
dialog = self.builder.get_object("selectedDirDialog")
file_filter = self.builder.get_object("Folders")
dialog.add_filter(file_filter)
self.xscreensavers = self.settings.get_xscreensavers()
list = [f for f in listdir(self.xscreensavers) if isfile(join(self.xscreensavers , f))]
list.sort()
for file in list:
self.xscreen_store.append((file,))
self.selected_eve_box = None
self.start_path = None
self.default_player = None
self.default_img_viewer = None
self.demo_area_pid = None
self.apply_type = 1 # 1 is XWinWrap and 2 is Nitrogen
self.xscreen_value = None
self.to_be_background = None # Global file path and type for saving to file
self.window.connect("delete-event", self.tear_down)
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.tear_down)
self.set_monitor_offset_data()
self.retrieve_settings()
def set_monitor_offset_data(self):
monitors = self.settings.get_monitor_data()
monitorOffsetData = self.builder.get_object("monitorOffsetData")
for monitor in monitors:
if monitor.x >= 0 and monitor.y >= 0:
monitorOffsetData.append_text("+" + str(monitor.x) + "+" + str(monitor.y))
elif monitor.x <= 0 and monitor.y <= 0:
monitorOffsetData.append_text(str(monitor.x) + str(monitor.y))
elif monitor.x >= 0 and monitor.y <= 0:
monitorOffsetData.append_text("+" + str(monitor.x) + str(monitor.y))
elif monitor.x <= 0 and monitor.y >= 0:
monitorOffsetData.append_text(str(monitor.x) + "+" + str(monitor.y))
monitorOffsetData.set_active(0)
def retrieve_settings(self):
data = self.settings_saver.retrieve_settings()
self.start_path = data[0]
self.default_player = data[1]
self.default_img_viewer = data[2]
self.builder.get_object("customStartPath").set_text(self.start_path)
self.builder.get_object("customVideoPlayer").set_text(self.default_player)
self.builder.get_object("customImgViewer").set_text(self.default_img_viewer)
self.builder.get_object("selectedDirDialog").set_filename(self.start_path)
if self.start_path:
self.load_path(None, self.start_path)

View File

@@ -1,64 +0,0 @@
# Python imports
import threading, socket, time
from multiprocessing.connection import Listener, Client
# Lib imports
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper
class IPCServerMixin:
@threaded
def create_ipc_server(self):
listener = Listener((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey)
self.is_ipc_alive = True
while True:
conn = listener.accept()
start_time = time.time()
print(f"New Connection: {listener.last_accepted}")
while True:
msg = conn.recv()
if debug:
print(msg)
if "FILE|" in msg:
file = msg.split("FILE|")[1].strip()
if file:
event_system.push_gui_event(["create_tab_from_ipc", None, file])
conn.close()
break
if msg == 'close connection':
conn.close()
break
if msg == 'close server':
conn.close()
break
# NOTE: Not perfect but insures we don't lockup the connection for too long.
end_time = time.time()
if (end - start) > self.ipc_timeout:
conn.close()
listener.close()
def send_ipc_message(self, message="Empty Data..."):
try:
conn = Client((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey)
conn.send(message)
conn.send('close connection')
except Exception as e:
print(repr(e))

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env python
import os, json
class SaveGWinWrapSettings:
def __init__(self, settings):
self.config_file = settings.get_config_file()
if os.path.isfile(self.config_file) == False:
open(self.config_file, 'a').close()
def save_settings(self, start_path, default_player, default_img_viewer):
data = {}
data['settings'] = []
data['settings'].append({
'start_path': start_path,
'default_player': default_player,
'default_img_viewer': default_img_viewer
})
with open(self.config_file, 'w') as outfile:
json.dump(data, outfile, separators=(',', ':'), indent=4)
def retrieve_settings(self):
data = []
with open(self.config_file) as infile:
try:
_data = json.load(infile)
for obj in _data['settings']:
data = [obj['start_path'], obj['default_player'], obj['default_img_viewer']]
except Exception as e:
print(repr(e))
data = ['', 'mplayer', 'xdg-open']
if data[0] == '':
data[0] = ''
if data[1] == '':
data[1] = 'mplayer'
if data[2] == '':
data[2] = 'xdg-open'
return data

View File

@@ -1,9 +0,0 @@
"""
Gtk Bound Signal Module
"""
from .mixins import *
from .SaveStateToXWinWarp import SaveStateToXWinWarp
from .SaveGWinWrapSettings import SaveGWinWrapSettings
from .IPCServerMixin import IPCServerMixin
from .Controller_Data import Controller_Data
from .Controller import Controller

View File

@@ -1,59 +0,0 @@
# Python imports
import os, subprocess, signal, time
# Gtk imports
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
# Application imports
class DrawAreaMixin:
"""docstring for DrawAreaMixin"""
def close_demo_popup(self, widget=None, data=None):
os.kill(self.demo_area_pid, signal.SIGTERM) #or signal.SIGKILL
self.demo_area_pid = None
time.sleep(.200)
self.builder.get_object("demoPreviewPopWindow").popdown()
def run_mplayer_process(self, widget, eve, params):
video, file, eveBox = params
self.set_selected_eve_box(eveBox)
if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
if self.default_player == "mplayer":
xid = self.getXID()
command = [self.default_player, video, "-slave", "-wid", str(xid), "-really-quiet", "-ao", "null", "-loop", "0"]
self.run_demo_in_draw_area(command)
else:
subprocess.call([self.default_player, video, "-really-quiet", "-ao", "null", "-loop", "0"])
self.to_be_background = video
self.applyType = 1
self.help_label.set_markup(f"<span foreground='#e0cc64'>{file}</span>")
def run_demo_in_draw_area(self, command):
self.help_label.set_markup("<span foreground='#e0cc64'></span>")
if self.demo_area_pid:
os.kill(self.demo_area_pid, signal.SIGTERM) #or signal.SIGKILL
self.demo_area_pid = None
time.sleep(.800) # 800 mili-seconds to ensure first process dead
process = subprocess.Popen(command)
self.demo_area_pid = process.pid
def getXID(self):
# Must be actualized before getting window
popup = self.builder.get_object("demoPreviewPopWindow")
if popup.get_visible() == False:
popup.show_all()
popup.popup()
preview = self.builder.get_object("demoPreview")
window = preview.get_window()
return window.get_xid()

View File

@@ -1,116 +0,0 @@
# Python imports
import threading, hashlib
from os import listdir
from os.path import isfile, join
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class GridMixin:
"""docstring for GridMixin."""
def set_new_path(self, widget, data=None):
dir = widget.get_filename()
self.load_path(None, dir)
def load_path(self, widget=None, dir=''):
path = dir
list = [f for f in listdir(path) if isfile(join(path, f))]
files = []
row = 0
col = 0
for file in list:
if file.lower().endswith(self.settings.get_vids_filter() + \
self.settings.get_images_filter()):
files.append(file)
# fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files)
# tickCount = 0.0
self.clear()
self.image_grid.remove_column(0)
# self.loadProgress.set_text("Loading...")
# self.loadProgress.set_fraction(0.0)
self.help_label.set_markup(f"<span foreground='#b30ec2'>{path.strip(self.settings.get_home_path())}</span>")
for file in files:
self.porocess_file(path, file, col, row)
col += 1
if col == 2:
col = 0
row += 1
# self.loadProgress.set_text("Finished...")
@threaded
def porocess_file(self, path, file, col, row):
fPath = f"{path}/{file}"
eveBox = Gtk.EventBox()
thumbnl = Gtk.Image()
if file.lower().endswith(self.settings.get_vids_filter()):
fileHash = hashlib.sha256(str.encode(fPath)).hexdigest()
hashImgPath = f"{self.settings.get_home_path()}/.thumbnails/normal/{fileHash}.png"
if isfile(hashImgPath) == False:
self.generate_thumbnail(fPath, hashImgPath)
thumbnl = self.create_gtk_image(hashImgPath, [310, 310])
eveBox.connect("button_press_event", self.run_mplayer_process, (fPath, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouse_over, ())
eveBox.connect("leave_notify_event", self.mouse_out, ())
elif file.lower().endswith(self.settings.get_images_filter()):
thumbnl = self.create_gtk_image(fPath, [310, 310])
eveBox.connect("button_press_event", self.run_image_viewer_process, (fPath, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouse_over, ())
eveBox.connect("leave_notify_event", self.mouse_out, ())
else:
print("Not a video or image file.")
return
GLib.idle_add(self.pre_grid_setup, (eveBox, thumbnl, ))
GLib.idle_add(self.add_to_grid, (self.image_grid, eveBox, col, row,))
# tickCount = tickCount + fractionTick
# self.loadProgress.set_fraction(tickCount)
def pre_grid_setup(self, args):
args[0].show()
args[1].show()
args[0].add(args[1])
def add_to_grid(self, args):
args[0].attach(args[1], args[2], args[3], 1, 1)
def clear_selection(self, widget, data=None):
self.clear()
def clear(self):
while True:
if self.image_grid.get_child_at(0,0)!= None:
self.image_grid.remove_row(0)
else:
break
self.image_grid.attach(self.grid_label, 0, 0, 1, 1)
self.builder.get_object("xScreenSvrList").set_sensitive(False)
self.builder.get_object("useXScrnList").set_active(False)
self.help_label.set_markup(self.defaultLabel)
# self.loadProgress.set_text("")
# self.loadProgress.set_fraction(0.0)
self.xscreen_value = None
self.to_be_background = None
self.apply_type = 1

View File

@@ -1,34 +0,0 @@
# Python imports
import subprocess
# Gtk imports
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
# Application imports
class ImageViewerMixin:
"""docstring for ImageViewerMixin"""
def close_image_popup(self, widget=None):
self.builder.get_object("previewWindow").popdown()
def open_main_image_viewer(self, widget):
subprocess.call([self.default_img_viewer, self.to_be_background])
def run_image_viewer_process(self, widget, eve, params):
image, file, eveBox = params
self.set_selected(eveBox)
if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
previewWindow = self.builder.get_object("previewWindow")
previewImg = self.builder.get_object("previewImg")
previewImg.set_from_file(image)
previewWindow.show_all()
previewWindow.popup()
self.to_be_background = image
self.apply_type = 2
self.help_label.set_markup(f"<span foreground='#e0cc64'>{file}</span>")

View File

@@ -1,56 +0,0 @@
# Python imports
import os, logging
# Application imports
class Logger:
def __init__(self):
pass
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)
log.setLevel(globalLogLvl)
# 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 = "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

View File

@@ -1,112 +0,0 @@
# Python imports
import os
# Gtk imports
import gi, cairo
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
# Application imports
from . import Logger
class Settings:
def __init__(self):
self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__))
self._USER_HOME = os.path.expanduser('~')
self._CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}"
self._GLADE_FILE = f"{self._CONFIG_PATH}/Main_Window.glade"
self._CSS_FILE = f"{self._CONFIG_PATH}/stylesheet.css"
self._DEFAULT_ICONS = f"{self._CONFIG_PATH}/icons"
self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png"
self._USR_PATH = f"/usr/share/{app_name.lower()}"
self._CONFIG_FILE = f"{self._CONFIG_PATH}/settings.json"
self._XSCREEN_SAVERS = "/usr/lib/xscreensaver/"
self._logger = Logger().get_logger()
self._builder = Gtk.Builder()
self._main_window = None
# '_filters'
self._vids_filter = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
self._images_filter = ('.png', '.jpg', '.jpeg', '.gif')
self._success_color = "#88cc27"
self._warning_color = "#ffa800"
self._error_color = "#ff0000"
if not os.path.exists(self._GLADE_FILE):
self._GLADE_FILE = f"{self._USR_PATH}/Main_Window.glade"
if not os.path.exists(self._CSS_FILE):
self._CSS_FILE = f"{self._USR_PATH}/stylesheet.css"
if not os.path.exists(self._WINDOW_ICON):
self._WINDOW_ICON = f"{self._USR_PATH}/icons/{app_name.lower()}.png"
if not os.path.exists(self._DEFAULT_ICONS):
self.DEFAULT_ICONS = f"{self._USR_PATH}/icons"
self._builder.add_from_file(self._GLADE_FILE)
def create_window(self):
# Get window and connect signals
self._main_window = self._builder.get_object("Main_Window")
self.set_window_data()
def set_window_data(self):
self._main_window.set_icon_from_file(self._WINDOW_ICON)
screen = self._main_window.get_screen()
visual = screen.get_rgba_visual()
if visual != None and screen.is_composited():
self._main_window.set_visual(visual)
self._main_window.set_app_paintable(True)
self._main_window.connect("draw", self.draw_area)
# bind css file
cssProvider = Gtk.CssProvider()
cssProvider.load_from_path(self._CSS_FILE)
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
def get_monitor_data(self):
screen = self._builder.get_object("Main_Window").get_screen()
monitors = []
for m in range(screen.get_n_monitors()):
monitors.append(screen.get_monitor_geometry(m))
for monitor in monitors:
print("{}x{}|{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y))
return monitors
def draw_area(self, widget, cr):
cr.set_source_rgba(0, 0, 0, 0.54)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
def get_builder(self): return self._builder
def get_logger(self): return self._logger
def get_main_window(self): return self._main_window
def get_home_path(self): return self._USER_HOME
def get_config_file(self): return self._CONFIG_FILE
def get_xscreensavers(self): return self._XSCREEN_SAVERS
# Filter returns
def get_vids_filter(self): return self._vids_filter
def get_images_filter(self): return self._images_filter
def get_success_color(self): return self._success_color
def get_warning_color(self): return self._warning_color
def get_error_color(self): return self._error_color

View File

@@ -1,6 +0,0 @@
"""
Utils module
"""
from .Logger import Logger
from .Settings import Settings

Binary file not shown.

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Encoding=UTF-8
Name=GWinWrap
Comment=Glade GUI with python controls for XWinWrap
Exec=/bin/gwinwrap %f
Icon=/usr/share/gwinwrap/icons/gwinwrap.png
Terminal=false
Type=Application
Categories=Accessories;System;Settings;

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkFileFilter" id="Folders">
@@ -31,6 +31,11 @@
<property name="stock">gtk-cancel</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="closePopupImage2">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="stock">gtk-close</property>
</object>
<object class="GtkImage" id="openProgImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -68,90 +73,45 @@
<property name="stock">gtk-media-stop</property>
<property name="icon_size">3</property>
</object>
<object class="GtkWindow" id="Main_Window">
<property name="width-request">950</property>
<property name="height-request">600</property>
<object class="GtkBox" id="core_widget">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="title" translatable="yes">GWinWrap</property>
<property name="window-position">center</property>
<property name="default-width">950</property>
<property name="default-height">600</property>
<property name="icon">usr/share/gwinwrap/icons/gwinwrap.png</property>
<property name="gravity">center</property>
<child>
<object class="GtkBox" id="box1">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">15</property>
<property name="margin-top">15</property>
<property name="margin-bottom">15</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">15</property>
<property name="margin-top">15</property>
<property name="margin-bottom">15</property>
<property name="orientation">vertical</property>
<property name="margin-bottom">5</property>
<child>
<object class="GtkBox">
<object class="GtkLabel" id="helpLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">5</property>
<child>
<object class="GtkLabel" id="helpLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-right">15</property>
<property name="label" translatable="yes">Note: Double click an image to view the video or image.</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton" id="selectedDirDialog">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Chose Dream Scene / Image Directory</property>
<property name="action">select-folder</property>
<property name="create-folders">False</property>
<property name="filter">Folders</property>
<property name="title" translatable="yes">Dream Scene / Image Dir</property>
<signal name="file-set" handler="set_new_path" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="image">settingsImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="show_settings_popup" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<property name="margin-right">15</property>
<property name="label" translatable="yes">Note: Double click an image to view the video or image.</property>
</object>
<packing>
<property name="expand">False</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="loadProgress">
<object class="GtkFileChooserButton" id="selectedDirDialog">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="show-text">True</property>
<property name="tooltip-text" translatable="yes">Chose Dream Scene / Image Directory</property>
<property name="action">select-folder</property>
<property name="create-folders">False</property>
<property name="filter">Folders</property>
<property name="title" translatable="yes">Dream Scene / Image Dir</property>
<signal name="file-set" handler="set_new_path" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -159,64 +119,191 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="image">settingsImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="show_settings_popup" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="loadProgress">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="show-text">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<!-- n-columns=3 n-rows=3 -->
<object class="GtkGrid" id="imageGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<property name="row-homogeneous">True</property>
<property name="column-homogeneous">True</property>
<child>
<object class="GtkLabel" id="gridLabel">
<property name="width-request">640</property>
<property name="height-request">525</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Choose Image/Video Directory...</property>
<attributes>
<attribute name="font-desc" value="Times New Roman, 28"/>
</attributes>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Clear</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="image">clearImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="clear_selection" 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">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="width-request">300</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">10</property>
<property name="margin-right">15</property>
<property name="margin-top">15</property>
<property name="margin-bottom">15</property>
<property name="hexpand">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="useXScrnList">
<property name="label" translatable="yes">Use XScreenSaver</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">center</property>
<property name="margin-bottom">5</property>
<property name="draw-indicator">True</property>
<signal name="toggled" handler="toggle_xscreen_list" swapped="no"/>
</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="shadow-type">in</property>
<child>
<object class="GtkViewport">
<object class="GtkTreeView" id="xScreenSvrList">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="model">XScreensaverStore</property>
<property name="headers-visible">False</property>
<signal name="button-press-event" handler="preview_xscreensaver" swapped="no"/>
<signal name="cursor-changed" handler="pass_xscreen_value" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<!-- n-columns=3 n-rows=3 -->
<object class="GtkGrid" id="imageGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<property name="row-homogeneous">True</property>
<property name="column-homogeneous">True</property>
<object class="GtkTreeViewColumn" id="listColumn">
<property name="title" translatable="yes">XScreensaves</property>
<child>
<object class="GtkLabel" id="gridLabel">
<property name="width-request">640</property>
<property name="height-request">525</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Choose Image/Video Directory...</property>
<attributes>
<attribute name="font-desc" value="Times New Roman, 28"/>
</attributes>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
@@ -226,23 +313,7 @@
<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">Clear</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="image">clearImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="clear_selection" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
<property name="position">1</property>
</packing>
</child>
</object>
@@ -254,14 +325,9 @@
</child>
<child>
<object class="GtkBox">
<property name="width-request">300</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">10</property>
<property name="margin-right">15</property>
<property name="margin-top">15</property>
<property name="margin-bottom">15</property>
<property name="hexpand">False</property>
<property name="vexpand">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
@@ -269,15 +335,37 @@
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="useXScrnList">
<property name="label" translatable="yes">Use XScreenSaver</property>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">center</property>
<property name="margin-bottom">5</property>
<property name="draw-indicator">True</property>
<signal name="toggled" handler="toggle_xscreen_list" swapped="no"/>
<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">10</property>
<property name="margin-bottom">10</property>
<property name="label" translatable="yes">Playback Resolutions</property>
</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">10</property>
<property name="margin-bottom">10</property>
<property name="label" translatable="yes">Position Offset</property>
</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>
@@ -286,35 +374,85 @@
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<property name="can-focus">False</property>
<child>
<object class="GtkTreeView" id="xScreenSvrList">
<object class="GtkComboBoxText" id="playbackResolution">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="model">XScreensaverStore</property>
<property name="headers-visible">False</property>
<signal name="button-press-event" handler="preview_xscreensaver" swapped="no"/>
<signal name="cursor-changed" handler="pass_xscreen_value" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="listColumn">
<property name="title" translatable="yes">XScreensaves</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<property name="can-focus">False</property>
<property name="active">3</property>
<items>
<item translatable="yes">7680x4320</item>
<item translatable="yes">3840x2160</item>
<item translatable="yes">2048x1080</item>
<item translatable="yes">1920x1080</item>
<item translatable="yes">1440x720</item>
<item translatable="yes">1600x900</item>
<item translatable="yes">1280x720</item>
<item translatable="yes">800x600</item>
</items>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="monitorOffsetData">
<property name="visible">True</property>
<property name="can-focus">False</property>
</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">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="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">10</property>
<property name="margin-bottom">5</property>
<property name="label" translatable="yes">Save Path</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="saveLoc">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="active">0</property>
<items>
<item translatable="yes">.animatedBGstarter.sh</item>
<item translatable="yes">.animatedBGstarter2.sh</item>
<item translatable="yes">.animatedBGstarter3.sh</item>
</items>
</object>
<packing>
<property name="expand">True</property>
@@ -324,267 +462,121 @@
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<!-- n-columns=3 n-rows=3 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<object class="GtkButton">
<property name="label" translatable="yes">Save</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="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="label" translatable="yes">Playback Resolutions</property>
</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">10</property>
<property name="margin-bottom">10</property>
<property name="label" translatable="yes">Position Offset</property>
</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="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkComboBoxText" id="playbackResolution">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="active">3</property>
<items>
<item translatable="yes">7680x4320</item>
<item translatable="yes">3840x2160</item>
<item translatable="yes">2048x1080</item>
<item translatable="yes">1920x1080</item>
<item translatable="yes">1440x720</item>
<item translatable="yes">1600x900</item>
<item translatable="yes">1280x720</item>
<item translatable="yes">800x600</item>
</items>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="monitorOffsetData">
<property name="visible">True</property>
<property name="can-focus">False</property>
</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">1</property>
</packing>
</child>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">saveImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="save_to_file" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<object class="GtkButton">
<property name="label" translatable="yes">(Re)Start</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">10</property>
<property name="margin-bottom">5</property>
<property name="label" translatable="yes">Save Path</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="saveLoc">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="active">0</property>
<items>
<item translatable="yes">.animatedBGstarter.sh</item>
<item translatable="yes">.animatedBGstarter2.sh</item>
<item translatable="yes">.animatedBGstarter3.sh</item>
</items>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">startImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="apply_settings" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<!-- n-columns=3 n-rows=3 -->
<object class="GtkGrid">
<object class="GtkButton">
<property name="label" translatable="yes">Stop</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">saveImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="save_to_file" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">(Re)Start</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">startImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="apply_settings" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Stop</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">stopImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="kill_xwinwrap" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">closeImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="close_program" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">stopImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="kill_xwinwrap" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">closeImage</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="close_program" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack-type">end</property>
<property name="position">1</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="padding">1</property>
<property name="fill">False</property>
<property name="pack-type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">1</property>
<property name="position">1</property>
</packing>
</child>
</object>
<object class="GtkPopover" id="demoPreviewPopWindow">
@@ -691,6 +683,7 @@
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="image">closePopupImage2</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="close_image_popup" swapped="no"/>
</object>
@@ -770,6 +763,7 @@
<property name="can-focus">True</property>
<property name="tooltip-text" translatable="yes">Set Custom Default Path</property>
<property name="placeholder-text" translatable="yes">Set Custom Start Path</property>
<signal name="changed" handler="update_start_path" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
@@ -808,6 +802,7 @@
<property name="can-focus">True</property>
<property name="tooltip-text" translatable="yes">Set Custom Video Player</property>
<property name="placeholder-text" translatable="yes">Set Custom Video Player</property>
<signal name="changed" handler="update_default_player" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
@@ -846,6 +841,7 @@
<property name="can-focus">True</property>
<property name="tooltip-text" translatable="yes">Set Custom Image Viewer</property>
<property name="placeholder-text" translatable="yes">Set Custom Image Viewer</property>
<signal name="changed" handler="update_default_img_viewer" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>

View File

@@ -1,9 +1,36 @@
{
"settings":[
{
"start_path":"/home/abaddon/LazyShare/Movies-TV-Music/Dream Scenes/Games/Halo",
"default_player":"mpv",
"default_img_viewer":"mirage"
}
]
}
"config":{
"start_path":"",
"xscreensaver_path":"/usr/lib/xscreensaver/",
"default_player":"mpv",
"default_img_viewer":"mirage"
},
"filters":{
"videos":[
".mkv",
".mp4",
".webm",
".avi",
".mov",
".m4v",
".mpg",
".mpeg",
".wmv",
".flv"
],
"images":[
".png",
".jpg",
".jpeg",
".gif",
".ico",
".tga",
".webp"
]
},
"theming":{
"success_color":"#88cc27",
"warning_color":"#ffa800",
"error_color":"#ff0000"
}
}

View File

@@ -1,9 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Name=GWinWrap
Comment=Glade gui with python controls for XWinWrap
Exec=gwinwrap
Icon=/opt/GWinWrap/resources/icons/GWinWrap.png
Terminal=false
Type=Application
Categories=Accessories;System;Settings;

View File

@@ -1,41 +0,0 @@
#!/usr/bin/python3
# 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
# Python imports
import inspect
from setproctitle import setproctitle
# Application imports
from utils import Settings
from signal_classes import CrossClassSignals
class Main:
def __init__(self):
setproctitle('GWinWrap')
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
faulthandler.enable() # For better debug info
settings = Settings()
builder = settings.returnBuilder()
# Gets the methods from the classes and sets to handler.
# Then, builder connects to any signals it needs.
classes = [CrossClassSignals(settings)]
handlers = {}
for c in classes:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
builder.connect_signals(handlers)
window = settings.createWindow()
window.show()

View File

@@ -1,9 +0,0 @@
from __init__ import Main, gtk
if __name__ == "__main__":
try:
main = Main()
gtk.main()
except Exception as e:
print(e)

View File

@@ -1,844 +0,0 @@
<?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="GtkListStore" id="XScreensaver List">
<columns>
<!-- column-name XScreensavers -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkImage" id="clearImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="closeImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-quit</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="closePopupImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-cancel</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="openProgImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-jump-to</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="saveImag">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="saveImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="settingsImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Settings....</property>
<property name="stock">gtk-properties</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="startImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-play</property>
<property name="icon_size">3</property>
</object>
<object class="GtkImage" id="stopImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-stop</property>
<property name="icon_size">3</property>
</object>
<object class="GtkWindow" id="Main_Window">
<property name="width_request">950</property>
<property name="height_request">600</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">GWinWrap</property>
<property name="window_position">center</property>
<property name="default_width">950</property>
<property name="default_height">600</property>
<property name="icon">icons/GWinWrap.png</property>
<property name="gravity">center</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox" id="box1">
<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="margin_left">15</property>
<property name="margin_top">15</property>
<property name="margin_bottom">15</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">5</property>
<child>
<object class="GtkLabel" id="helpLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">15</property>
<property name="label" translatable="yes">Note: Double click an image to view the video or image.</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton" id="selectedDirDialog">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Chose Dream Scene / Image Directory</property>
<property name="action">select-folder</property>
<property name="create_folders">False</property>
<property name="filter">Folders</property>
<property name="title" translatable="yes">Dream Scene / Image Dir</property>
<signal name="file-set" handler="setNewDir" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">settingsImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="popSttingsWindow" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="loadProgress">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_text">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid" id="imageGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="row_spacing">10</property>
<property name="column_spacing">10</property>
<property name="row_homogeneous">True</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkLabel" id="gridLabel">
<property name="width_request">640</property>
<property name="height_request">525</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Choose Image/Video Directory...</property>
<attributes>
<attribute name="font-desc" value="Times New Roman, 28"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</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">Clear</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">clearImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="clearSelection" 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">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="width_request">300</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">15</property>
<property name="margin_top">15</property>
<property name="margin_bottom">15</property>
<property name="hexpand">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="useXScrnList">
<property name="label" translatable="yes">Use XScreenSaver</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">center</property>
<property name="margin_bottom">5</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="toggleXscreenUsageField" swapped="no"/>
</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="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="xScreenSvrList">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="model">XScreensaver List</property>
<property name="headers_visible">False</property>
<signal name="button-press-event" handler="previewXscreen" swapped="no"/>
<signal name="cursor-changed" handler="passXScreenVal" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="listColumn">
<property name="title" translatable="yes">XScreensaves</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</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">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="vexpand">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="label" translatable="yes">Playback Resolutions</property>
</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">10</property>
<property name="margin_bottom">10</property>
<property name="label" translatable="yes">Position Offset</property>
</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="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkComboBoxText" id="playbackResolution">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="active">3</property>
<items>
<item translatable="yes">7680x4320</item>
<item translatable="yes">3840x2160</item>
<item translatable="yes">2048x1080</item>
<item translatable="yes">1920x1080</item>
<item translatable="yes">1440x720</item>
<item translatable="yes">1600x900</item>
<item translatable="yes">1280x720</item>
<item translatable="yes">800x600</item>
</items>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="posOffset">
<property name="visible">True</property>
<property name="can_focus">False</property>
</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">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="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">10</property>
<property name="margin_bottom">5</property>
<property name="label" translatable="yes">Save Path</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="saveLoc">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="active">0</property>
<items>
<item translatable="yes">.animatedBGstarter.sh</item>
<item translatable="yes">.animatedBGstarter2.sh</item>
<item translatable="yes">.animatedBGstarter3.sh</item>
</items>
</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">1</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">saveImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="saveToFile" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">(Re)Start</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">startImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="applySttngs" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Stop</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">stopImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="killXWinWrp" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="image">closeImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="closeProgram" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</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">False</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">1</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkPopover" id="demoPreviewPopWindow">
<property name="width_request">640</property>
<property name="height_request">525</property>
<property name="can_focus">False</property>
<property name="margin_right">350</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="relative_to">helpLabel</property>
<property name="position">bottom</property>
<property name="modal">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="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Close Demo Window</property>
<property name="image">closePopupImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="closeDemoWindow" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</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="GtkAspectFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkDrawingArea" id="demoPreview">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</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="GtkPopover" id="previewWindow">
<property name="width_request">640</property>
<property name="height_request">525</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="relative_to">helpLabel</property>
<property name="position">bottom</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButtonBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="baseline_position">bottom</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Main Image Viewer</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">openProgImage</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="openMainImageViewer" 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="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="closePopup" swapped="no"/>
</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">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<property name="overlay_scrolling">False</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="previewImg">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
<property name="icon_size">6</property>
</object>
</child>
</object>
</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="GtkPopover" id="settingsWindow">
<property name="width_request">250</property>
<property name="can_focus">False</property>
<property name="relative_to">button1</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixbuf">icons/folder.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="customDefaultPath">
<property name="width_request">330</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Set Custom Default Path</property>
<property name="placeholder_text" translatable="yes">Set Custom Default Path</property>
</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">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixbuf">icons/player.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="customVideoPlyr">
<property name="width_request">330</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Set Custom Video Player</property>
<property name="placeholder_text" translatable="yes">Set Custom Video Player</property>
</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">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixbuf">icons/picture.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="customImgVwr">
<property name="width_request">330</property>
<property name="height_request">26</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Set Custom Image Viewer</property>
<property name="placeholder_text" translatable="yes">Set Custom Image Viewer</property>
</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>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">saveImag</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="saveToSettingsFile" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -1,3 +0,0 @@
window {
}

View File

@@ -1,403 +0,0 @@
# 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
# Python imports
import threading, subprocess, signal, os, sys, re, hashlib, time
from os import listdir
from os.path import isfile, join
# Application imports
from utils import SaveStateToXWinWarp, SaveGWinWrapSettings
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class CrossClassSignals:
def __init__(self, settings):
self.settings = settings
self.builder = self.settings.returnBuilder()
self.WINDOW = self.builder.get_object("Main_Window").get_window()
self.stateSaver = SaveStateToXWinWarp()
self.sttngsSver = SaveGWinWrapSettings()
# Add filter to allow only folders to be selected
dialog = self.builder.get_object("selectedDirDialog")
filefilter = self.builder.get_object("Folders")
dialog.add_filter(filefilter)
# Get reference to remove and add it back...
self.gridLabel = self.builder.get_object("gridLabel")
self.focusedImg = gtk.Image()
self.usrHome = os.path.expanduser('~')
self.xScreenVal = None
self.toSavePath = None # Global file path and type for saving to file
self.applyType = 1 # 1 is XWinWrap and 2 is Nitrogen
self.loadProgress = self.builder.get_object("loadProgress")
self.helpLabel = self.builder.get_object("helpLabel")
self.defaultLabel = "<span>Note: Double click an image to view the video or image.</span>"
self.savedLabel = "<span foreground=\"#88cc27\">Saved settings...</span>"
self.appliedLabel = "<span foreground=\"#88cc27\">Running xwinwrap...</span>"
self.stoppedLabel = "<span foreground=\"#88cc27\">Stopped xwinwrap...</span>"
# foreground=\"#ffa800\"
# foreground=\"#88cc27\"
# foreground=\"#ff0000\"
# Fill list xscreensaver
self.xscrPth = "/usr/lib/xscreensaver/"
xscreenList = self.builder.get_object("XScreensaver List")
list = [f for f in listdir(self.xscrPth) if isfile(join(self.xscrPth, f))]
list.sort()
for file in list:
xscreenList.append((file,))
self.selectedImg = None # EventBox holder
self.defPath = None
self.player = None
self.imgVwr = None
self.demoAreaPid = None
self.setPosData()
self.retrieveSettings()
def setNewDir(self, widget, data=None):
dir = widget.get_filename()
threading.Thread(target=self.newDir, args=(dir,)).start()
def newDir(self, dir):
imageGrid = self.builder.get_object("imageGrid")
dirPath = dir
list = [f for f in listdir(dirPath) if isfile(join(dirPath, f))]
files = []
row = 0
col = 0
for file in list:
if file.lower().endswith(('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm', '.png', '.jpg', '.jpeg', '.gif')):
files.append(file)
# fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files)
# tickCount = 0.0
self.clear()
imageGrid.remove_column(0)
self.loadProgress.set_text("Loading...")
self.loadProgress.set_fraction(0.0)
self.helpLabel.set_markup("<span foreground=\"#b30ec2\">" + dirPath.strip(self.usrHome) + "</span>")
for file in files:
self.porocess_file(imageGrid, dirPath, file, col, row)
col += 1
if col == 2:
col = 0
row += 1
self.loadProgress.set_text("Finished...")
@threaded
def porocess_file(self, imageGrid, dirPath, file, col, row):
fullPathFile = dirPath + "/" + file
eveBox = gtk.EventBox()
thumbnl = gtk.Image()
if file.lower().endswith(('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')):
fileHash = hashlib.sha256(str.encode(fullPathFile)).hexdigest()
hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png"
if isfile(hashImgpth) == False:
self.generateThumbnail(fullPathFile, hashImgpth)
thumbnl = self.createGtkImage(hashImgpth, [310, 310])
eveBox.connect("button_press_event", self.runMplayerProcess, (fullPathFile, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouseOver, ())
eveBox.connect("leave_notify_event", self.mouseOut, ())
elif file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
thumbnl = self.createGtkImage(fullPathFile, [310, 310])
eveBox.connect("button_press_event", self.runImageViewerProcess, (fullPathFile, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouseOver, ())
eveBox.connect("leave_notify_event", self.mouseOut, ())
else:
print("Not a video or image file.")
return
glib.idle_add(self.preGridSetup, (eveBox, thumbnl, ))
glib.idle_add(self.addToGrid, (imageGrid, eveBox, col, row,))
# tickCount = tickCount + fractionTick
# self.loadProgress.set_fraction(tickCount)
def preGridSetup(self, args):
args[0].show()
args[1].show()
args[0].add(args[1])
def addToGrid(self, args):
args[0].attach(args[1], args[2], args[3], 1, 1)
def generateThumbnail(self, fullPathFile, hashImgpth):
# Stream duration
command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPathFile]
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", fullPathFile]
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", fullPathFile]
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", fullPathFile]
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, "-i", fullPathFile, "-an", "-vframes", "1", "-s", "320x180", "-q:v", "2", hashImgpth]
subprocess.call(command)
def createGtkImage(self, path, wxh):
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
filename = path,
width = wxh[0],
height = wxh[1],
preserve_aspect_ratio = True)
return gtk.Image.new_from_pixbuf(pixbuf)
except Exception as e:
print(e)
return gtk.Image()
def openMainImageViewer(self, widget):
subprocess.call([self.imgVwr, self.toSavePath])
def runImageViewerProcess(self, widget, eve, params):
self.setSelected(params[2])
if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS:
previewWindow = self.builder.get_object("previewWindow")
previewImg = self.builder.get_object("previewImg")
previewImg.set_from_file(params[0])
previewWindow.show_all()
previewWindow.popup()
self.toSavePath = params[0]
self.applyType = 2
self.helpLabel.set_markup("<span foreground=\"#e0cc64\">" + params[1] + "</span>")
def setSelected(self, eveBox):
if self.selectedImg:
col = gdk.RGBA(0.0, 0.0, 0.0, 0.0)
self.selectedImg.override_background_color(gtk.StateType.NORMAL, col)
col = gdk.RGBA(0.9, 0.7, 0.4, 0.74)
eveBox.override_background_color(gtk.StateType.NORMAL, col)
self.selectedImg = eveBox
def closePopup(self, widget):
self.builder.get_object("previewWindow").popdown()
def mouseOver(self, widget, eve, args):
hand_cursor = gdk.Cursor(gdk.CursorType.HAND2)
self.builder.get_object("Main_Window").get_window().set_cursor(hand_cursor)
def mouseOut(self, widget, eve, args):
watch_cursor = gdk.Cursor(gdk.CursorType.LEFT_PTR)
self.builder.get_object("Main_Window").get_window().set_cursor(watch_cursor)
def toggleXscreenUsageField(self, widget, data=None):
useXscreenSaver = self.builder.get_object("useXScrnList")
if useXscreenSaver.get_active():
self.builder.get_object("xScreenSvrList").set_sensitive(True)
else:
self.builder.get_object("xScreenSvrList").set_sensitive(False)
def popSttingsWindow(self, widget):
self.builder.get_object("settingsWindow").popup()
def saveToSettingsFile(self, widget):
self.defPath = self.builder.get_object("customDefaultPath").get_text().strip()
self.player = self.builder.get_object("customVideoPlyr").get_text().strip()
self.imgVwr = self.builder.get_object("customImgVwr").get_text().strip()
self.sttngsSver.saveSettings(self.defPath, self.player, self.imgVwr)
def retrieveSettings(self):
data = self.sttngsSver.retrieveSettings()
self.defPath = data[0]
self.player = data[1]
self.imgVwr = data[2]
self.builder.get_object("customDefaultPath").set_text(self.defPath)
self.builder.get_object("customVideoPlyr").set_text(self.player)
self.builder.get_object("customImgVwr").set_text(self.imgVwr)
self.builder.get_object("selectedDirDialog").set_filename(self.defPath)
if self.defPath:
self.newDir(self.defPath)
def saveToFile(self, widget, data=None):
saveLoc = self.builder.get_object("saveLoc").get_active_text()
useXscreenSaver = self.builder.get_object("useXScrnList").get_active()
plyBckRes = self.builder.get_object("playbackResolution")
offset4Res = self.builder.get_object("posOffset")
resolution = plyBckRes.get_active_text() + offset4Res.get_active_text()
self.applyType = self.stateSaver.saveToFile(self.toSavePath, resolution,
saveLoc, useXscreenSaver, self.xScreenVal, self.player)
if self.applyType == -1:
self.helpLabel.set_markup("<span foreground=\"#e0cc64\">Nothing saved...</span>")
return
self.helpLabel.set_markup(self.savedLabel)
def applySttngs(self, widget, data=None):
os.system("killall xwinwrap &")
if self.applyType == 1:
files = os.listdir(self.usrHome)
for file in files:
fPath = self.usrHome + "/" + file
if os.path.isfile(fPath) and "animatedBGstarter" in file:
os.system("bash -c '~/" + file + "' &")
elif self.applyType == 2:
os.system("nitrogen --restore &")
else:
os.system("nitrogen --restore &")
self.helpLabel.set_markup(self.appliedLabel)
def killXWinWrp(self, widget, data=None):
os.system("killall xwinwrap &")
self.helpLabel.set_markup(self.stoppedLabel)
def passXScreenVal(self, widget):
xSvrListStore = self.builder.get_object("XScreensaver List")
row = widget.get_cursor()
path = gtk.TreePath(row.path)
treeiter = xSvrListStore.get_iter(path[0])
self.xScreenVal = xSvrListStore.get_value(treeiter, 0)
def runMplayerProcess(self, widget, eve, params):
self.setSelected(params[2])
video = params[0]
if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS:
if self.player == "mplayer":
xid = self.getXID()
command = [self.player, video, "-slave", "-wid", str(xid), "-really-quiet", "-ao", "null", "-loop", "0"]
self.runDemoToDrawArea(command)
else:
subprocess.call([self.player, video, "-really-quiet", "-ao", "null", "-loop", "0"])
self.toSavePath = params[0]
self.applyType = 1
self.helpLabel.set_markup("<span foreground=\"#e0cc64\">" + params[1] + "</span>")
def previewXscreen(self, widget, eve):
if eve.type == gdk.EventType.DOUBLE_BUTTON_PRESS:
demoXscrnSaver = self.xscrPth + self.xScreenVal
xid = self.getXID()
command = [demoXscrnSaver, "-window-id", str(xid)]
self.runDemoToDrawArea(command)
def getXID(self):
# Must be actualized before getting window
demoWindowPopup = self.builder.get_object("demoPreviewPopWindow")
if demoWindowPopup.get_visible() == False:
demoWindowPopup.show_all()
demoWindowPopup.popup()
demoPreview = self.builder.get_object("demoPreview")
drwWindow = demoPreview.get_window()
return drwWindow.get_xid()
def runDemoToDrawArea(self, command):
self.helpLabel.set_markup("<span foreground=\"#e0cc64\"></span>")
if self.demoAreaPid:
os.kill(self.demoAreaPid, signal.SIGTERM) #or signal.SIGKILL
self.demoAreaPid = None
time.sleep(.800) # 800 mili-seconds to ensure first process dead
process = subprocess.Popen(command)
self.demoAreaPid = process.pid
def closeDemoWindow(self, widget, data=None):
os.kill(self.demoAreaPid, signal.SIGTERM) #or signal.SIGKILL
self.demoAreaPid = None
time.sleep(.200)
self.builder.get_object("demoPreviewPopWindow").popdown()
def clearSelection(self, widget, data=None):
self.clear()
def clear(self):
imageGrid = self.builder.get_object("imageGrid")
while True:
if imageGrid.get_child_at(0,0)!= None:
imageGrid.remove_row(0)
else:
break
imageGrid.attach(self.gridLabel, 0, 0, 1, 1)
self.builder.get_object("xScreenSvrList").set_sensitive(False)
self.builder.get_object("useXScrnList").set_active(False)
self.helpLabel.set_markup(self.defaultLabel)
self.loadProgress.set_text("")
self.loadProgress.set_fraction(0.0)
self.toSavePath = None
self.xScreenVal = None
self.applyType = 1 # Default to XWinWrap
def setPosData(self):
monitors = self.settings.getMonitorData()
posOff = self.builder.get_object("posOffset")
for monitor in monitors:
if monitor.x >= 0 and monitor.y >= 0:
posOff.append_text("+" + str(monitor.x) + "+" + str(monitor.y))
elif monitor.x <= 0 and monitor.y <= 0:
posOff.append_text(str(monitor.x) + str(monitor.y))
elif monitor.x >= 0 and monitor.y <= 0:
posOff.append_text("+" + str(monitor.x) + str(monitor.y))
elif monitor.x <= 0 and monitor.y >= 0:
posOff.append_text(str(monitor.x) + "+" + str(monitor.y))
posOff.set_active(0)
def closeProgram(self, widget, data=None):
sys.exit(0)

View File

@@ -1 +0,0 @@
from signal_classes.CrossClassSignals import CrossClassSignals

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env python
import os, json
class SaveGWinWrapSettings:
def __init__(self):
configFolder = os.path.expanduser('~') + "/.config/gwinwrap/"
self.configFile = configFolder + "settings.ini"
if os.path.isdir(configFolder) == False:
os.mkdir(configFolder)
if os.path.isfile(self.configFile) == False:
open(self.configFile, 'a').close()
def saveSettings(self, defPath, player, imgVwr):
data = {}
data['gwinwrap_settings'] = []
data['gwinwrap_settings'].append({
'defPath' : defPath,
'player' : player,
'imgvwr' : imgVwr
})
with open(self.configFile, 'w') as outfile:
json.dump(data, outfile)
def retrieveSettings(self):
returnData = []
with open(self.configFile) as infile:
try:
data = json.load(infile)
for obj in data['gwinwrap_settings']:
returnData = [obj['defPath'], obj['player'], obj['imgvwr']]
except Exception as e:
returnData = ['', 'mplayer', 'xdg-open']
if returnData[0] == '':
returnData[0] = ''
if returnData[1] == '':
returnData[1] = 'mplayer'
if returnData[2] == '':
returnData[2] = 'xdg-open'
return returnData

View File

@@ -1,69 +0,0 @@
#!/usr/bin/env python
import os
class SaveStateToXWinWarp:
def __init__(self):
self.fileWriter = None
self.toSavePath = None
self.useXSvrn = None
self.xScreenVal = None
self.sveFileLoc = None
self.resolution = None
self.player = None
def saveToFile(self, toSavePath, resolution,
saveLoc, useXSvrn, xScreenVal, player):
self.toSavePath = toSavePath
self.useXSvrn = useXSvrn
self.xScreenVal = xScreenVal
self.resolution = resolution
self.player = player
userPth = os.path.expanduser('~')
# Saves to file with selected and needed settings
if toSavePath:
if toSavePath.lower().endswith(('.png', '.jpg', '.jpeg')):
self.sveFileLoc = userPth + "/" + ".config/nitrogen/bg-saved.cfg"
else:
self.sveFileLoc = userPth + "/" + saveLoc
elif useXSvrn and xScreenVal:
self.sveFileLoc = userPth + "/" + saveLoc
else:
return -1
if self.sveFileLoc:
self.fileWriter = open(self.sveFileLoc, "w")
return self.startSave()
def startSave(self):
applyType = 1
output = None
# XSCREENSAVER
if self.useXSvrn:
output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- /usr/lib/xscreensaver/" + self.xScreenVal + " -window-id WID -root";
# GIF
elif self.toSavePath.lower().endswith(('.gif')):
output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- gifview -a -w WID " + self.toSavePath;
# Standard images using nitrogen
elif self.toSavePath.lower().endswith(('.png', 'jpg', '.jpeg')):
output = "[xin_0] \nfile=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000\n\n[xin_1] \nfile=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000";
applyType = 2;
# VIDEO
else:
output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- " + self.player + " -wid WID -really-quiet -ao null -loop 0 '" + self.toSavePath + "'";
pass
try:
if self.fileWriter:
self.fileWriter.write(output)
self.fileWriter.close()
except Exception as e:
print(":: Write failed! ::")
print(e)
return applyType;

View File

@@ -1,74 +0,0 @@
# 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
# Application imports
class Settings:
def __init__(self):
self.builder = gtk.Builder()
self.builder.add_from_file("resources/Main_Window.glade")
# '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')
def createWindow(self):
# Get window and connect signals
window = self.builder.get_object("Main_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('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)
def getMonitorData(self):
screen = self.builder.get_object("Main_Window").get_screen()
monitors = []
for m in range(screen.get_n_monitors()):
monitors.append(screen.get_monitor_geometry(m))
for monitor in monitors:
print("{}x{}+{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y))
return monitors
def returnBuilder(self): return self.builder
# 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

View File

@@ -1,3 +0,0 @@
from utils.Settings import Settings
from utils.SaveStateToXWinWarp import SaveStateToXWinWarp
from utils.SaveGWinWrapSettings import SaveGWinWrapSettings

View File

@@ -1,20 +0,0 @@
all: all64 all32
all64:
gcc -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -lX11 -lXext -lXrender xwinwrap.c -o xwinwrap
-mkdir x86_64
mv ./xwinwrap ./x86_64
all32:
gcc -m32 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -lX11 -lXext -lXrender xwinwrap.c -o xwinwrap
-mkdir i386
mv ./xwinwrap ./i386
install64:
cp x86_64/xwinwrap /usr/bin
install32:
cp i386/xwinwrap /usr/bin
clean:
-rm -rf x86_64/ i386/

View File

@@ -1,459 +0,0 @@
/*
* Copyright © 2005 Novell, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Novell, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
* Novell, Inc. makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: David Reveman <davidr@novell.com>
*/
/*
* Modified by: Shantanu Goel
* Tech Blog: http://tech.shantanugoel.com
* Blog: http://blog.shantanugoel.com
* Home Page: http://tech.shantanugoel.com/projects/linux/shantz-xwinwrap
*
* Changelog:
* 15-Jan-09: 1. Fixed the bug where XFetchName returning a NULL for "name"
* resulted in a crash.
* 2. Provided an option to specify the desktop window name.
* 3. Added debug messages
*
* 24-Aug-08: 1. Fixed the geometry option (-g) so that it works
* 2. Added override option (-ov), for seamless integration with
* desktop like a background in non-fullscreen modes
* 3. Added shape option (-sh), to create non-rectangular windows.
* Currently supporting circlular and triangular windows
*/
/*
* Modified by: Maxim Stewart
* Tech Blog: https://www.itdominator.com/
*
* Changelog:
* 3-March-19: 1. Cleaned up code formatting.
* 2. Removed unused DEBUG_MSG reference.
* 3. Moved functions to a more reasonable order.
* 4. Compile dev library list 32 & 64 bit:
* # 32
* sudo apt install libxext-dev:i386 libxrender-dev:i386 libc6-dev-i386
*
* # 64
* sudo apt install libxext-dev libxrender-dev libc6-dev
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/Xrender.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#define WIDTH 512
#define HEIGHT 384
#define OPAQUE 0xffffffff
#define NAME "xwinwrap"
#define VERSION "0.3"
#define DESKTOP_WINDOW_NAME_MAX_SIZE 25
#define DEFAULT_DESKTOP_WINDOW_NAME "Desktop"
#define DEBUG_MSG(x) if(debug) { fprintf(stderr, x); }
typedef enum {
SHAPE_RECT = 0,
SHAPE_CIRCLE,
SHAPE_TRIG,
} win_shape;
static pid_t pid = 0;
static char **childArgv = 0;
static int nChildArgv = 0;
int debug = 0;
char desktop_window_name[DESKTOP_WINDOW_NAME_MAX_SIZE];
static int addArguments(char **argv, int n) {
char **newArgv;
int i;
newArgv = realloc (childArgv, sizeof (char *) * (nChildArgv + n));
if (!newArgv)
return 0;
for (i = 0; i < n; i++)
newArgv[nChildArgv + i] = argv[i];
childArgv = newArgv;
nChildArgv += n;
return n;
}
static void setWindowOpacity(Display *dpy, Window win, unsigned int opacity) {
CARD32 o;
o = opacity;
XChangeProperty (dpy, win, XInternAtom (dpy, "_NET_WM_WINDOW_OPACITY", 0),
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *) &o, 1);
}
static Visual * findArgbVisual(Display *dpy, int scr) {
XVisualInfo *xvi;
XVisualInfo template;
int nvi;
int i;
XRenderPictFormat *format;
Visual *visual;
template.screen = scr;
template.depth = 32;
template.class = TrueColor;
xvi = XGetVisualInfo (dpy,
VisualScreenMask |
VisualDepthMask |
VisualClassMask,
&template,
&nvi);
if (!xvi)
return 0;
visual = 0;
for (i = 0; i < nvi; i++) {
format = XRenderFindVisualFormat (dpy, xvi[i].visual);
if (format->type == PictTypeDirect && format->direct.alphaMask) {
visual = xvi[i].visual;
break;
}
}
XFree (xvi);
return visual;
}
static Window find_desktop_window(Display *display, int screen,
Window *root, Window *p_desktop) {
int i;
unsigned int n;
Window win = *root;
Window troot, parent, *children;
char *name;
int status;
int width = DisplayWidth(display, screen);
int height = DisplayHeight(display, screen);
XWindowAttributes attrs;
XQueryTree(display, *root, &troot, &parent, &children, &n);
for (i = 0; i < (int) n; i++) {
status = XFetchName(display, children[i], &name);
status |= XGetWindowAttributes(display, children[i], &attrs);
if ((status != 0) && (NULL != name)) {
if( (attrs.map_state != 0) && (attrs.width == width) &&
(attrs.height == height) && (!strcmp(name, desktop_window_name)) ) {
win = children[i];
XFree(children);
XFree(name);
*p_desktop = win;
return win;
}
if(name)
XFree(name);
}
}
DEBUG_MSG("Desktop Window Not found\n");
return 0;
}
static void usage (void) {
fprintf(stderr, "%s v%s- Modified by Shantanu Goel. Visit http://tech.shantanugoel.com for updates, queries and feature requests\n", NAME, VERSION);
fprintf (stderr, "\nUsage: %s [-g {w}x{h}+{x}+{y}] [-ni] [-argb] [-fs] [-s] [-st] [-sp] [-a] "
"[-b] [-nf] [-o OPACITY] [-sh SHAPE] [-ov]-- COMMAND ARG1...\n", NAME);
fprintf (stderr, "Options:\n \
-g - Specify Geometry (w=width, h=height, x=x-coord, y=y-coord. ex: -g 640x480+100+100)\n \
-ni - Ignore Input\n \
-d - Desktop Window Hack. Provide name of the \"Desktop\" window as parameter \
-argb - RGB\n \
-fs - Full Screen\n \
-s - Sticky\n \
-st - Skip Taskbar\n \
-sp - Skip Pager\n \
-a - Above\n \
-b - Below\n \
-nf - No Focus\n \
-o - Opacity value between 0 to 1 (ex: -o 0.20)\n \
-sh - Shape of window (choose between rectangle, circle or triangle. Default is rectangle)\n \
-ov - Set override_redirect flag (For seamless desktop background integration in non-fullscreenmode)\n \
-debug - Enable debug messages\n");
}
static void sigHandler (int sig) { kill(pid, sig); }
int main (int argc, char **argv) {
Display *dpy;
Window win;
Window root;
Window p_desktop = 0;
int screen;
XSizeHints xsh;
XWMHints xwmh;
char widArg[256];
char *widArgv[] = { widArg };
char *endArg = NULL;
int i;
int status = 0;
unsigned int opacity = OPAQUE;
int x = 0;
int y = 0;
unsigned int width = WIDTH;
unsigned int height = HEIGHT;
int argb = 0;
int fullscreen = 0;
int noInput = 0;
int noFocus = 0;
Atom state[256];
int nState = 0;
int override = 0;
win_shape shape = SHAPE_RECT;
Pixmap mask;
GC mask_gc;
XGCValues xgcv;
dpy = XOpenDisplay (NULL);
if (!dpy) {
fprintf (stderr, "%s: Error: couldn't open display\n", argv[0]);
return 1;
}
screen = DefaultScreen (dpy);
root = RootWindow (dpy, screen);
strcpy(desktop_window_name, DEFAULT_DESKTOP_WINDOW_NAME);
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-g") == 0) {
if (++i < argc)
XParseGeometry (argv[i], &x, &y, &width, &height);
} else if (strcmp(argv[i], "-ni") == 0) {
noInput = 1;
} else if (strcmp(argv[i], "-d") == 0) {
++i;
strcpy(desktop_window_name, argv[i]);
} else if (strcmp(argv[i], "-argb") == 0) {
argb = 1;
} else if (strcmp(argv[i], "-fs") == 0) {
state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_FULLSCREEN", 0);
fullscreen = 1;
} else if (strcmp(argv[i], "-s") == 0) {
state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_STICKY", 0);
} else if (strcmp(argv[i], "-st") == 0) {
state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_SKIP_TASKBAR", 0);
} else if (strcmp(argv[i], "-sp") == 0) {
state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_SKIP_PAGER", 0);
} else if (strcmp(argv[i], "-a") == 0) {
state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_ABOVE", 0);
} else if (strcmp(argv[i], "-b") == 0) {
state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_BELOW", 0);
} else if (strcmp(argv[i], "-nf") == 0) {
noFocus = 1;
} else if (strcmp(argv[i], "-o") == 0) {
if (++i < argc)
opacity = (unsigned int) (atof (argv[i]) * OPAQUE);
} else if (strcmp(argv[i], "-sh") == 0) {
if (++i < argc) {
if(strcasecmp(argv[i], "circle") == 0) {
shape = SHAPE_CIRCLE;
} else if(strcasecmp(argv[i], "triangle") == 0) {
shape = SHAPE_TRIG;
}
}
} else if (strcmp(argv[i], "-ov") == 0) {
override = 1;
} else if (strcmp(argv[i], "-debug") == 0) {
debug = 1;
} else if (strcmp(argv[i], "--") == 0) {
break;
} else {
usage ();
return 1;
}
}
for (i = i + 1; i < argc; i++) {
if (strcmp(argv[i], "WID") == 0)
addArguments (widArgv, 1);
else
addArguments (&argv[i], 1);
}
if (!nChildArgv) {
fprintf (stderr, "%s: Error: couldn't create command line\n", argv[0]);
usage ();
return 1;
}
addArguments (&endArg, 1);
if (fullscreen) {
xsh.flags = PSize | PPosition;
xsh.width = DisplayWidth (dpy, screen);
xsh.height = DisplayHeight (dpy, screen);
} else {
xsh.flags = PSize;
xsh.width = width;
xsh.height = height;
}
xwmh.flags = InputHint;
xwmh.input = !noFocus;
if (argb) {
XSetWindowAttributes attr;
Visual *visual;
visual = findArgbVisual (dpy, screen);
if (!visual) {
fprintf (stderr, "%s: Error: couldn't find argb visual\n", argv[0]);
return 1;
}
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap (dpy, root, visual, AllocNone);
win = XCreateWindow (dpy, root, 0, 0, xsh.width, xsh.height, 0, 32,
InputOutput, visual,
CWBackPixel | CWBorderPixel | CWColormap, &attr);
} else {
XSetWindowAttributes attr;
attr.override_redirect = override;
if( override && find_desktop_window(dpy, screen, &root, &p_desktop) ) {
win = XCreateWindow (dpy, p_desktop, x, y, xsh.width, xsh.height, 0,
CopyFromParent, InputOutput, CopyFromParent,
CWOverrideRedirect, &attr);
} else {
win = XCreateWindow (dpy, root, x, y, xsh.width, xsh.height, 0,
CopyFromParent, InputOutput, CopyFromParent,
CWOverrideRedirect, &attr);
}
}
XSetWMProperties (dpy, win, NULL, NULL, argv, argc, &xsh, &xwmh, NULL);
if (opacity != OPAQUE)
setWindowOpacity (dpy, win, opacity);
if (noInput) {
Region region;
region = XCreateRegion ();
if (region) {
XShapeCombineRegion (dpy, win, ShapeInput, 0, 0, region, ShapeSet);
XDestroyRegion (region);
}
}
if (nState)
XChangeProperty (dpy, win, XInternAtom (dpy, "_NET_WM_STATE", 0),
XA_ATOM, 32, PropModeReplace, (unsigned char *) state, nState);
if (shape) {
mask = XCreatePixmap(dpy, win, width, height, 1);
mask_gc = XCreateGC(dpy, mask, 0, &xgcv);
switch(shape) {
//Nothing special to be done if it's a rectangle
case SHAPE_CIRCLE:
/* fill mask */
XSetForeground(dpy, mask_gc, 0);
XFillRectangle(dpy, mask, mask_gc, 0, 0, width, height);
XSetForeground(dpy, mask_gc, 1);
XFillArc(dpy, mask, mask_gc, 0, 0, width, height, 0, 23040);
break;
case SHAPE_TRIG:
{
XPoint points[3] = { {0, height},
{width/2, 0},
{width, height} };
XSetForeground(dpy, mask_gc, 0);
XFillRectangle(dpy, mask, mask_gc, 0, 0, width, height);
XSetForeground(dpy, mask_gc, 1);
XFillPolygon(dpy, mask, mask_gc, points, 3, Complex, CoordModeOrigin);
}
break;
default:
break;
}
/* combine */
XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, mask, ShapeSet);
}
XMapWindow (dpy, win);
if(p_desktop == 0)
XLowerWindow(dpy, win);
XSync (dpy, win);
sprintf (widArg, "0x%x", (int) win);
pid = fork ();
switch (pid) {
case -1:
perror ("fork");
return 1;
case 0:
execvp (childArgv[0], childArgv);
perror (childArgv[0]);
exit (2);
break;
default:
break;
}
signal (SIGTERM, sigHandler);
signal (SIGINT, sigHandler);
for (;;) {
if (waitpid (pid, &status, 0) != -1) {
if (WIFEXITED (status))
fprintf (stderr, "%s died, exit status %d\n", childArgv[0],
WEXITSTATUS (status));
break;
}
}
XDestroyWindow (dpy, win);
XCloseDisplay (dpy);
return 0;
}

View File

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

View File

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

View File

@@ -1,73 +1,42 @@
import builtins
# Python imports
import builtins
import threading
# Lib imports
# Application imports
from signal_classes import IPCServerMixin
from utils.event_system import EventSystem
from utils.endpoint_registry import EndpointRegistry
from utils.keybindings import Keybindings
from utils.settings import Settings
class Builtins(IPCServerMixin):
"""Docstring for __builtins__ extender"""
def __init__(self):
# NOTE: The format used is list of [type, target, data]
# Where data may be any kind of data
self._gui_events = []
self._fm_events = []
self.is_ipc_alive = False
self.ipc_authkey = b'GWinWrap-ipc'
self.ipc_address = '127.0.0.1'
self.ipc_port = 8888
self.ipc_timeout = 15.0
# NOTE: Threads WILL NOT die with parent's destruction.
def threaded_wrapper(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
return wrapper
# Makeshift fake "events" type system FIFO
def _pop_gui_event(self):
if len(self._gui_events) > 0:
return self._gui_events.pop(0)
return None
# NOTE: Threads WILL die with parent's destruction.
def daemon_threaded_wrapper(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper
def _pop_fm_event(self):
if len(self._fm_events) > 0:
return self._fm_events.pop(0)
return None
def push_gui_event(self, event):
if len(event) == 3:
self._gui_events.append(event)
return None
raise Exception("Invald event format! Please do: [type, target, data]")
def push_fm_event(self, event):
if len(event) == 3:
self._fm_events.append(event)
return None
raise Exception("Invald event format! Please do: [type, target, data]")
def read_gui_event(self):
return self._gui_events[0]
def read_fm_event(self):
return self._fm_events[0]
def consume_gui_event(self):
return self._pop_gui_event()
def consume_fm_event(self):
return self._pop_fm_event()
# NOTE: Just reminding myself we can add to builtins two different ways...
# __builtins__.update({"event_system": Builtins()})
builtins.app_name = "GWinWrap"
builtins.event_system = Builtins()
builtins.event_sleep_time = 0.2
builtins.debug = False
builtins.trace_debug = False
builtins.keybindings = Keybindings()
builtins.event_system = EventSystem()
builtins.endpoint_registry = EndpointRegistry()
builtins.settings = Settings()
builtins.logger = settings.get_logger()
builtins.threaded = threaded_wrapper
builtins.daemon_threaded = daemon_threaded_wrapper
builtins.event_sleep_time = 0.05

View File

@@ -1,50 +1,3 @@
# Python imports
import os, inspect, time
# Lib imports
# Application imports
from utils import Settings
from signal_classes import Controller
from __builtins__ import Builtins
class Main(Builtins):
def __init__(self, args, unknownargs):
if not debug:
event_system.create_ipc_server()
time.sleep(0.2)
if not trace_debug:
if not event_system.is_ipc_alive:
if unknownargs:
for arg in unknownargs:
if os.path.isdir(arg):
message = f"FILE|{arg}"
event_system.send_ipc_message(message)
raise Exception("IPC Server Exists: Will send data to it and close...")
settings = Settings()
settings.create_window()
controller = Controller(settings, args, unknownargs)
if not controller:
raise Exception("Controller exited and doesn't exist...")
# Gets the methods from the classes and sets to handler.
# Then, builder from settings will connect to any signals it needs.
classes = [controller]
handlers = {}
for c in classes:
methods = None
try:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
except Exception as e:
print(repr(e))
settings.get_builder().connect_signals(handlers)
"""
Start of package.
"""

View File

@@ -1,38 +1,50 @@
#!/usr/bin/python3
# Python imports
import argparse, faulthandler, traceback
import argparse
import faulthandler
import traceback
from setproctitle import setproctitle
import tracemalloc
tracemalloc.start()
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from __init__ import Main
from __builtins__ import *
from app import Application
if __name__ == "__main__":
try:
# import web_pdb
# web_pdb.set_trace()
''' Set process title, get arguments, and create GTK main thread. '''
setproctitle('GWinWrap')
try:
setproctitle(f'{app_name}')
faulthandler.enable() # For better debug info
parser = argparse.ArgumentParser()
# Add long and short arguments
parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.")
parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.")
parser.add_argument("--file", "-f", default="default", help="JUST SOME FILE ARG.")
# Read arguments (If any...)
args, unknownargs = parser.parse_known_args()
Main(args, unknownargs)
if args.debug == "true":
settings.set_debug(True)
if args.trace_debug == "true":
settings.set_trace_debug(True)
settings.do_dirty_start_check()
Application(args, unknownargs)
Gtk.main()
except Exception as e:
traceback.print_exc()

View File

@@ -0,0 +1,40 @@
# Python imports
import os
import time
# Lib imports
# Application imports
from utils.ipc_server import IPCServer
from core.window import Window
class AppLaunchException(Exception):
...
class ControllerStartExceptiom(Exception):
...
class Application(IPCServer):
''' Create Settings and Controller classes. Bind signal to Builder. Inherit from Builtins to bind global methods and classes.'''
def __init__(self, args, unknownargs):
super(Application, self).__init__()
if not settings.is_trace_debug():
try:
self.create_ipc_listener()
except Exception:
...
if not self.is_ipc_alive:
for arg in unknownargs + [args.new_tab,]:
if os.path.isdir(arg):
message = f"FILE|{arg}"
self.send_ipc_message(message)
raise AppLaunchException(f"{app_name} IPC Server Exists: Will send path(s) to it and close...")
Window(args, unknownargs)

View File

@@ -0,0 +1,3 @@
"""
Gtk Bound Signal Module
"""

View File

@@ -0,0 +1,123 @@
# Python imports
import os
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import Gdk
# Application imports
from .mixins import *
from .controller_data import Controller_Data
class Controller(ThumbnailMixin, ImageViewerMixin, DrawAreaMixin, GridMixin, Controller_Data):
def __init__(self, args, unknownargs, _window):
self.window = _window
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_glade_file()
self.setup_controller_data()
self.retrieve_settings()
def _setup_styling(self):
...
def _setup_signals(self):
...
def _subscribe_to_events(self):
event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
def handle_file_from_ipc(self, path: str) -> None:
print(f"Path From IPC: {path}")
def _load_glade_file(self):
self.builder = Gtk.Builder()
self.builder.add_from_file(settings.get_glade_file())
settings.set_builder(self.builder)
self.core_widget = self.builder.get_object("core_widget")
settings.register_signals_to_builder([self, self.core_widget])
def get_core_widget(self):
return self.core_widget
def tear_down(self, widget=None, eve=None):
if self.demo_area_pid:
self.close_demo_popup()
self.close_image_popup()
def close_program(self, widget, data=None):
event_system.emit("close_gwinwrap")
def apply_settings(self, widget, data=None):
os.system("killall xwinwrap &")
user_home = settings.get_home_path()
if self.apply_type == 1:
files = os.listdir(user_home)
for file in files:
fPath = f"{user_home}/{file}"
if os.path.isfile(fPath) and "animatedBGstarter" in file:
os.system(f"bash -c '~/{file}' &")
else:
os.system("nitrogen --restore &")
self.help_label.set_markup(self.appliedLabel)
def toggle_xscreen_list(self, widget=None, eve=None):
use_xscreensvr = self.builder.get_object("useXScrnList")
if use_xscreensvr.get_active():
self.builder.get_object("xScreenSvrList").set_sensitive(True)
else:
self.builder.get_object("xScreenSvrList").set_sensitive(False)
def show_settings_popup(self, widget):
self.builder.get_object("settingsWindow").popup()
def preview_xscreensaver(self, widget, eve):
if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
demoXscrnSaver = self.xscreensavers + self.xscreen_value
xid = self.getXID()
command = [demoXscrnSaver, "-window-id", str(xid)]
self.run_demo_in_draw_area(command)
def pass_xscreen_value(self, widget):
row = widget.get_cursor()
path = Gtk.TreePath(row.path)
treeiter = self.xscreen_store.get_iter(path[0])
self.xscreen_value = self.xscreen_store.get_value(treeiter, 0)
def kill_xwinwrap(self, widget, data=None):
os.system("killall xwinwrap &")
self.help_label.set_markup(self.stoppedLabel)
def set_selected_eve_box(self, eveBox):
if self.selected_eve_box:
color = Gdk.RGBA(0.0, 0.0, 0.0, 0.0)
self.selected_eve_box.override_background_color(Gtk.StateType.NORMAL, color)
color = Gdk.RGBA(0.9, 0.7, 0.4, 0.74)
eveBox.override_background_color(Gtk.StateType.NORMAL, color)
self.selected_eve_box = eveBox
def mouse_over(self, widget, eve, args):
hand_cursor = Gdk.Cursor(Gdk.CursorType.HAND2)
self.window.get_window().set_cursor(hand_cursor)
def mouse_out(self, widget, eve, args):
watch_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
self.window.get_window().set_cursor(watch_cursor)

View File

@@ -0,0 +1,120 @@
# Python imports
from os import listdir
from os.path import isfile
from os.path import join
# Lib imports
from gi.repository import GLib
# Application imports
from .save_state_to_xwinwarp import SaveStateToXWinWarp
class Controller_Data:
def has_method(self, obj, name):
return callable(getattr(obj, name, None))
def setup_controller_data(self):
self.state_saver = SaveStateToXWinWarp()
self.logger = settings.get_logger()
self.home_path = settings.get_home_path()
self.success_color = settings.get_success_color()
self.warning_color = settings.get_warning_color()
self.error_color = settings.get_error_color()
self.vids_filter = settings.get_vids_filter()
self.imgs_filter = settings.get_images_filter()
self.image_grid = self.builder.get_object("imageGrid")
self.grid_label = self.builder.get_object("gridLabel")
self.help_label = self.builder.get_object("helpLabel")
self.xscreen_store = self.builder.get_object("XScreensaverStore")
self.defaultLabel = "<span>Note: Double click an image to view the video or image.</span>"
self.savedLabel = f"<span foreground='{self.success_color}'>Saved settings...</span>"
self.appliedLabel = f"<span foreground='{self.success_color}'>Running xwinwrap...</span>"
self.stoppedLabel = f"<span foreground='{self.success_color}'>Stopped xwinwrap...</span>"
# Add filter to allow only folders to be selected
dialog = self.builder.get_object("selectedDirDialog")
file_filter = self.builder.get_object("Folders")
dialog.add_filter(file_filter)
self.xscreensavers = settings.get_xscreensavers()
list = [f for f in listdir(self.xscreensavers) if isfile(join(self.xscreensavers , f))]
list.sort()
for file in list:
self.xscreen_store.append((file,))
self.selected_eve_box = None
self.start_path = None
self.default_player = None
self.default_img_viewer = None
self.demo_area_pid = None
self.apply_type = 1 # 1 is XWinWrap and 2 is Nitrogen
self.xscreen_value = None
self.to_be_background = None # Global file path and type for saving to file
self.set_monitor_offset_data()
self.retrieve_settings()
def retrieve_settings(self):
self.start_path = settings.get_start_path()
self.default_player = settings.get_default_player()
self.default_img_viewer = settings.get_default_img_viewer()
self.builder.get_object("customStartPath").set_text(self.start_path)
self.builder.get_object("customVideoPlayer").set_text(self.default_player)
self.builder.get_object("customImgViewer").set_text(self.default_img_viewer)
self.builder.get_object("selectedDirDialog").set_filename(self.start_path)
if self.start_path:
self.load_path(None, self.start_path)
def set_monitor_offset_data(self):
monitors = settings.get_monitor_data(self.window)
monitorOffsetData = self.builder.get_object("monitorOffsetData")
for monitor in monitors:
if monitor.x >= 0 and monitor.y >= 0:
monitorOffsetData.append_text("+" + str(monitor.x) + "+" + str(monitor.y))
elif monitor.x <= 0 and monitor.y <= 0:
monitorOffsetData.append_text(str(monitor.x) + str(monitor.y))
elif monitor.x >= 0 and monitor.y <= 0:
monitorOffsetData.append_text("+" + str(monitor.x) + str(monitor.y))
elif monitor.x <= 0 and monitor.y >= 0:
monitorOffsetData.append_text(str(monitor.x) + "+" + str(monitor.y))
monitorOffsetData.set_active(0)
def save_to_settings_file(self, widget=None):
settings.save_settings()
def update_start_path(self, widget=None, eve=None):
start_path = self.builder.get_object("customStartPath").get_text().strip()
settings.set_start_path(start_path)
def update_default_player(self, widget=None, eve=None):
default_player = self.builder.get_object("customVideoPlayer").get_text().strip()
settings.set_default_player(default_player)
def update_default_img_viewer(self, widget=None, eve=None):
default_img_viewer = self.builder.get_object("customImgViewer").get_text().strip()
settings.set_default_img_viewer(default_img_viewer)
def save_to_file(self, widget=None, eve=None):
save_location = self.builder.get_object("saveLoc").get_active_text()
use_xscreensvr = self.builder.get_object("useXScrnList").get_active()
playBackRes = self.builder.get_object("playbackResolution")
monitorOffset = self.builder.get_object("monitorOffsetData")
resolution = playBackRes.get_active_text() + monitorOffset.get_active_text()
self.apply_type = self.state_saver.save_to_file(self.to_be_background, resolution, save_location, use_xscreensvr, self.xscreen_value, self.default_player)
if self.apply_type == -1:
self.help_label.set_markup("<span foreground='#e0cc64'>Nothing saved...</span>")
return
self.help_label.set_markup(self.savedLabel)

View File

@@ -1,7 +1,10 @@
# Python imports
import os, subprocess, signal, time
import os
import subprocess
import signal
import time
# Gtk imports
# Lib imports
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
@@ -9,11 +12,12 @@ from gi.repository import Gdk
# Application imports
class DrawAreaMixin:
"""docstring for DrawAreaMixin"""
def close_demo_popup(self, widget=None, data=None):
os.kill(self.demo_area_pid, signal.SIGTERM) #or signal.SIGKILL
os.kill(self.demo_area_pid, signal.SIGTERM) # or signal.SIGKILL
self.demo_area_pid = None
time.sleep(.200)
self.builder.get_object("demoPreviewPopWindow").popdown()

View File

@@ -1,26 +1,19 @@
# Python imports
import threading, hashlib
import hashlib
from os import listdir
from os.path import isfile, join
from os.path import isfile
from os.path import join
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
from gi.repository import Gtk
from gi.repository import GLib
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class GridMixin:
"""docstring for GridMixin."""
@@ -36,8 +29,8 @@ class GridMixin:
col = 0
for file in list:
if file.lower().endswith(self.settings.get_vids_filter() + \
self.settings.get_images_filter()):
if file.lower().endswith(settings.get_vids_filter() + \
settings.get_images_filter()):
files.append(file)
# fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files)
@@ -46,7 +39,7 @@ class GridMixin:
self.image_grid.remove_column(0)
# self.loadProgress.set_text("Loading...")
# self.loadProgress.set_fraction(0.0)
self.help_label.set_markup(f"<span foreground='#b30ec2'>{path.strip(self.settings.get_home_path())}</span>")
self.help_label.set_markup(f"<span foreground='#b30ec2'>{path.strip(settings.get_home_path())}</span>")
for file in files:
self.porocess_file(path, file, col, row)
@@ -59,13 +52,13 @@ class GridMixin:
@threaded
def porocess_file(self, path, file, col, row):
fPath = f"{path}/{file}"
eveBox = Gtk.EventBox()
thumbnl = Gtk.Image()
fPath = f"{path}/{file}"
eveBox = Gtk.EventBox()
thumbnl = Gtk.Image()
if file.lower().endswith(self.settings.get_vids_filter()):
fileHash = hashlib.sha256(str.encode(fPath)).hexdigest()
hashImgPath = f"{self.settings.get_home_path()}/.thumbnails/normal/{fileHash}.png"
if file.lower().endswith(self.vids_filter):
fileHash = self.fast_hash(str.encode(fPath))
hashImgPath = f"{settings.get_home_path()}/.thumbnails/normal/{fileHash}.png"
if isfile(hashImgPath) == False:
self.generate_thumbnail(fPath, hashImgPath)
@@ -73,7 +66,7 @@ class GridMixin:
eveBox.connect("button_press_event", self.run_mplayer_process, (fPath, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouse_over, ())
eveBox.connect("leave_notify_event", self.mouse_out, ())
elif file.lower().endswith(self.settings.get_images_filter()):
elif file.lower().endswith(self.imgs_filter):
thumbnl = self.create_gtk_image(fPath, [310, 310])
eveBox.connect("button_press_event", self.run_image_viewer_process, (fPath, file, eveBox,))
eveBox.connect("enter_notify_event", self.mouse_over, ())
@@ -82,7 +75,7 @@ class GridMixin:
print("Not a video or image file.")
return
GLib.idle_add(self.pre_grid_setup, (eveBox, thumbnl, ))
self.pre_grid_setup((eveBox, thumbnl,))
GLib.idle_add(self.add_to_grid, (self.image_grid, eveBox, col, row,))
# tickCount = tickCount + fractionTick
# self.loadProgress.set_fraction(tickCount)
@@ -114,3 +107,19 @@ class GridMixin:
self.xscreen_value = None
self.to_be_background = None
self.apply_type = 1
def fast_hash(self, filename, hash_factory=hashlib.md5, chunk_num_blocks=128, i=1):
h = hash_factory()
with open(filename,'rb') as f:
f.seek(0, 2)
mid = int(f.tell() / 2)
f.seek(mid, 0)
while chunk := f.read(chunk_num_blocks*h.block_size):
h.update(chunk)
if (i == 12):
break
i += 1
return h.hexdigest()

View File

@@ -1,7 +1,7 @@
# Python imports
import subprocess
# Gtk imports
# Lib imports
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
@@ -20,7 +20,7 @@ class ImageViewerMixin:
def run_image_viewer_process(self, widget, eve, params):
image, file, eveBox = params
self.set_selected(eveBox)
self.set_selected_eve_box(eveBox)
if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
previewWindow = self.builder.get_object("previewWindow")

View File

@@ -1,7 +1,7 @@
# Python imports
import subprocess
# Gtk imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
@@ -10,6 +10,7 @@ from gi.repository import GdkPixbuf
# Application imports
class ThumbnailMixin:
"""docstring for ThumbnailMixin"""

View File

@@ -1,3 +1,6 @@
"""
Mixins Module
"""
from .ThumbnailMixin import ThumbnailMixin
from .DrawAreaMixin import DrawAreaMixin
from .ImageViewerMixin import ImageViewerMixin

View File

@@ -1,13 +1,21 @@
# Python imports
import os
import subprocess
# Lib imports
# Application imports
class SaveStateToXWinWarp:
def __init__(self, _settings):
self.settings = _settings
self.user_home = self.settings.get_home_path()
def __init__(self):
self.user_home = settings.get_home_path()
self._file_writer = None
self._to_be_background = None
self._use_xscreensvr = None
self._xscreen_value = None
self._xscreen_value = None
self._save_file_target = None
self._resolution = None
self._player = None
@@ -24,7 +32,7 @@ class SaveStateToXWinWarp:
# Saves to file with selected and needed settings
if to_be_background:
if to_be_background.lower().endswith(self.settings.get_images_filter()):
if to_be_background.lower().endswith(settings.get_images_filter()):
self._save_file_target = f"{self.user_home}/.config/nitrogen/bg-saved.cfg"
else:
self._save_file_target = f"{self.user_home}/{save_location}"
@@ -48,15 +56,21 @@ class SaveStateToXWinWarp:
# GIF
elif self._to_be_background.lower().endswith(('.gif')):
output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- gifview -a -w WID {self._to_be_background}";
# Standard images using nitrogen
# Standard images using nitrogen
elif self._to_be_background.lower().endswith(('.png', 'jpg', '.jpeg')):
output = f"[xin_0] \nfile={self._to_be_background}\nmode=0 \nbgcolor=#000000\n\n[xin_1] \nfile={self._to_be_background}\nmode=0 \nbgcolor=#000000";
applyType = 2;
# VIDEO
else:
output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- {self._player} -wid WID -really-quiet -ao null -loop 0 '{self._to_be_background}'";
pass
self.write_to_launch_file(output)
self.set_as_executable()
return applyType;
def write_to_launch_file(self, output):
try:
if self._file_writer:
self._file_writer.write(output)
@@ -65,4 +79,12 @@ class SaveStateToXWinWarp:
print(":: Write failed! ::")
print(e)
return applyType;
def set_as_executable(self):
os.access(self._save_file_target, os.X_OK)
try:
command = ["chmod", "764", self._save_file_target]
with subprocess.Popen(command, stdout=subprocess.PIPE) as proc:
result = proc.stdout.read().decode("UTF-8").strip()
except Exception as e:
print(f"Couldn't chmod\nFile: {properties.file_uri}")
print( repr(e) )

View File

@@ -0,0 +1,83 @@
# Python imports
import time
import signal
# Lib imports
import gi
import cairo
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib
# Application imports
from core.controller import Controller
class Window(Gtk.ApplicationWindow):
"""docstring for Window."""
def __init__(self, args, unknownargs):
super(Window, self).__init__()
self.controller = None
self._set_window_data()
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets(args, unknownargs)
self.show_all()
def _setup_styling(self):
self.set_default_size(950, 600)
self.set_title(f"{app_name}")
self.set_icon_from_file( settings.get_window_icon() )
self.set_gravity(5) # 5 = CENTER
self.set_position(1) # 1 = CENTER, 4 = CENTER_ALWAYS
def _setup_signals(self):
self.connect("delete-event", self._tear_down)
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._tear_down)
def _subscribe_to_events(self):
event_system.subscribe("close_gwinwrap", self._tear_down)
def _load_widgets(self, args, unknownargs):
self.controller = Controller(args, unknownargs, self)
self.add( self.controller.get_core_widget() )
def _set_window_data(self) -> None:
screen = self.get_screen()
visual = screen.get_rgba_visual()
if visual != None and screen.is_composited():
self.set_visual(visual)
self.set_app_paintable(True)
self.connect("draw", self._area_draw)
# bind css file
cssProvider = Gtk.CssProvider()
cssProvider.load_from_path( settings.get_css_file() )
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
def _area_draw(self, widget: Gtk.ApplicationWindow, cr: cairo.Context) -> None:
cr.set_source_rgba(0, 0, 0, 0.54)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
def _tear_down(self, widget=None, eve=None):
self.controller.tear_down()
settings.clear_pid()
time.sleep(event_sleep_time)
Gtk.main_quit()

View File

@@ -1,151 +0,0 @@
# Python imports
import threading, signal, subprocess, inspect, os, time
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk, GLib, Gdk
# Application imports
from .mixins import *
from . import Controller_Data
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class Controller(ThumbnailMixin, ImageViewerMixin, DrawAreaMixin, GridMixin, Controller_Data):
def __init__(self, _settings, args, unknownargs):
self.setup_controller_data(_settings)
self.window.show()
self.retrieve_settings()
def tear_down(self, widget=None, eve=None):
event_system.send_ipc_message("close server")
if self.demo_area_pid:
self.close_demo_popup()
self.close_image_popup()
time.sleep(event_sleep_time)
Gtk.main_quit()
def close_program(self, widget, data=None):
self.tear_down()
@threaded
def gui_event_observer(self):
while True:
time.sleep(event_sleep_time)
event = event_system.consume_gui_event()
if event:
try:
type, target, data = event
method = getattr(self.__class__, type)
GLib.idle_add(method, (self, data,))
except Exception as e:
print(repr(e))
def apply_settings(self, widget, data=None):
os.system("killall xwinwrap &")
user_home = self.settings.get_home_path()
if self.apply_type == 1:
files = os.listdir(user_home)
for file in files:
fPath = f"{user_home}/{file}"
if os.path.isfile(fPath) and "animatedBGstarter" in file:
os.system(f"bash -c '~/{file}' &")
elif self.apply_type == 2:
os.system("nitrogen --restore &")
else:
os.system("nitrogen --restore &")
self.help_label.set_markup(self.appliedLabel)
def save_to_settings_file(self, widget):
self.start_path = self.builder.get_object("customStartPath").get_text().strip()
self.default_player = self.builder.get_object("customVideoPlayer").get_text().strip()
self.default_img_viewer = self.builder.get_object("customImgViewer").get_text().strip()
self.settings_saver.save_settings(self.start_path, self.default_player, self.default_img_viewer)
def save_to_file(self, widget, data=None):
save_location = self.builder.get_object("saveLoc").get_active_text()
use_xscreensvr = self.builder.get_object("useXScrnList").get_active()
playBackRes = self.builder.get_object("playbackResolution")
monitorOffset = self.builder.get_object("monitorOffsetData")
resolution = playBackRes.get_active_text() + monitorOffset.get_active_text()
self.apply_type = self.state_saver.save_to_file(self.to_be_background, resolution, save_location, use_xscreensvr, self.xscreen_value, self.default_player)
if self.apply_type == -1:
self.help_label.set_markup("<span foreground='#e0cc64'>Nothing saved...</span>")
return
self.help_label.set_markup(self.savedLabel)
def toggle_xscreen_list(self, widget, data=None):
use_xscreensvr = self.builder.get_object("useXScrnList")
if use_xscreensvr.get_active():
self.builder.get_object("xScreenSvrList").set_sensitive(True)
else:
self.builder.get_object("xScreenSvrList").set_sensitive(False)
def show_settings_popup(self, widget):
self.builder.get_object("settingsWindow").popup()
def preview_xscreensaver(self, widget, eve):
if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
demoXscrnSaver = self.xscreensavers + self.xscreen_value
xid = self.getXID()
command = [demoXscrnSaver, "-window-id", str(xid)]
self.run_demo_in_draw_area(command)
def pass_xscreen_value(self, widget):
row = widget.get_cursor()
path = Gtk.TreePath(row.path)
treeiter = self.xscreen_store.get_iter(path[0])
self.xscreen_value = self.xscreen_store.get_value(treeiter, 0)
def kill_xwinwrap(self, widget, data=None):
os.system("killall xwinwrap &")
self.help_label.set_markup(self.stoppedLabel)
def set_selected_eve_box(self, eveBox):
if self.selected_eve_box:
color = Gdk.RGBA(0.0, 0.0, 0.0, 0.0)
self.selected_eve_box.override_background_color(Gtk.StateType.NORMAL, color)
color = Gdk.RGBA(0.9, 0.7, 0.4, 0.74)
eveBox.override_background_color(Gtk.StateType.NORMAL, color)
self.selected_eve_box = eveBox
def mouse_over(self, widget, eve, args):
hand_cursor = Gdk.Cursor(Gdk.CursorType.HAND2)
self.window.get_window().set_cursor(hand_cursor)
def mouse_out(self, widget, eve, args):
watch_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
self.window.get_window().set_cursor(watch_cursor)
def get_clipboard_data(self):
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE)
retcode = proc.wait()
data = proc.stdout.read()
return data.decode("utf-8").strip()
def set_clipboard_data(self, data):
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
proc.stdin.write(data)
proc.stdin.close()
retcode = proc.wait()

View File

@@ -1,102 +0,0 @@
# Python imports
import signal
from os import listdir
from os.path import isfile, join
# Lib imports
from gi.repository import GLib
# Application imports
from . import SaveStateToXWinWarp, SaveGWinWrapSettings
class Controller_Data:
def has_method(self, obj, name):
return callable(getattr(obj, name, None))
def setup_controller_data(self, _settings):
self.settings = _settings
self.state_saver = SaveStateToXWinWarp(_settings)
self.settings_saver = SaveGWinWrapSettings(_settings)
self.builder = self.settings.get_builder()
self.window = self.settings.get_main_window()
self.logger = self.settings.get_logger()
self.home_path = self.settings.get_home_path()
self.success_color = self.settings.get_success_color()
self.warning_color = self.settings.get_warning_color()
self.error_color = self.settings.get_error_color()
self.image_grid = self.builder.get_object("imageGrid")
self.grid_label = self.builder.get_object("gridLabel")
self.help_label = self.builder.get_object("helpLabel")
self.xscreen_store = self.builder.get_object("XScreensaverStore")
self.defaultLabel = "<span>Note: Double click an image to view the video or image.</span>"
self.savedLabel = f"<span foreground='{self.success_color}'>Saved settings...</span>"
self.appliedLabel = f"<span foreground='{self.success_color}'>Running xwinwrap...</span>"
self.stoppedLabel = f"<span foreground='{self.success_color}'>Stopped xwinwrap...</span>"
# Add filter to allow only folders to be selected
dialog = self.builder.get_object("selectedDirDialog")
file_filter = self.builder.get_object("Folders")
dialog.add_filter(file_filter)
self.xscreensavers = self.settings.get_xscreensavers()
list = [f for f in listdir(self.xscreensavers) if isfile(join(self.xscreensavers , f))]
list.sort()
for file in list:
self.xscreen_store.append((file,))
self.selected_eve_box = None
self.start_path = None
self.default_player = None
self.default_img_viewer = None
self.demo_area_pid = None
self.apply_type = 1 # 1 is XWinWrap and 2 is Nitrogen
self.xscreen_value = None
self.to_be_background = None # Global file path and type for saving to file
self.window.connect("delete-event", self.tear_down)
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.tear_down)
self.set_monitor_offset_data()
self.retrieve_settings()
def set_monitor_offset_data(self):
monitors = self.settings.get_monitor_data()
monitorOffsetData = self.builder.get_object("monitorOffsetData")
for monitor in monitors:
if monitor.x >= 0 and monitor.y >= 0:
monitorOffsetData.append_text("+" + str(monitor.x) + "+" + str(monitor.y))
elif monitor.x <= 0 and monitor.y <= 0:
monitorOffsetData.append_text(str(monitor.x) + str(monitor.y))
elif monitor.x >= 0 and monitor.y <= 0:
monitorOffsetData.append_text("+" + str(monitor.x) + str(monitor.y))
elif monitor.x <= 0 and monitor.y >= 0:
monitorOffsetData.append_text(str(monitor.x) + "+" + str(monitor.y))
monitorOffsetData.set_active(0)
def retrieve_settings(self):
data = self.settings_saver.retrieve_settings()
self.start_path = data[0]
self.default_player = data[1]
self.default_img_viewer = data[2]
self.builder.get_object("customStartPath").set_text(self.start_path)
self.builder.get_object("customVideoPlayer").set_text(self.default_player)
self.builder.get_object("customImgViewer").set_text(self.default_img_viewer)
self.builder.get_object("selectedDirDialog").set_filename(self.start_path)
if self.start_path:
self.load_path(None, self.start_path)

View File

@@ -1,64 +0,0 @@
# Python imports
import threading, socket, time
from multiprocessing.connection import Listener, Client
# Lib imports
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper
class IPCServerMixin:
@threaded
def create_ipc_server(self):
listener = Listener((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey)
self.is_ipc_alive = True
while True:
conn = listener.accept()
start_time = time.time()
print(f"New Connection: {listener.last_accepted}")
while True:
msg = conn.recv()
if debug:
print(msg)
if "FILE|" in msg:
file = msg.split("FILE|")[1].strip()
if file:
event_system.push_gui_event(["create_tab_from_ipc", None, file])
conn.close()
break
if msg == 'close connection':
conn.close()
break
if msg == 'close server':
conn.close()
break
# NOTE: Not perfect but insures we don't lockup the connection for too long.
end_time = time.time()
if (end - start) > self.ipc_timeout:
conn.close()
listener.close()
def send_ipc_message(self, message="Empty Data..."):
try:
conn = Client((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey)
conn.send(message)
conn.send('close connection')
except Exception as e:
print(repr(e))

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env python
import os, json
class SaveGWinWrapSettings:
def __init__(self, settings):
self.config_file = settings.get_config_file()
if os.path.isfile(self.config_file) == False:
open(self.config_file, 'a').close()
def save_settings(self, start_path, default_player, default_img_viewer):
data = {}
data['settings'] = []
data['settings'].append({
'start_path': start_path,
'default_player': default_player,
'default_img_viewer': default_img_viewer
})
with open(self.config_file, 'w') as outfile:
json.dump(data, outfile, separators=(',', ':'), indent=4)
def retrieve_settings(self):
data = []
with open(self.config_file) as infile:
try:
_data = json.load(infile)
for obj in _data['settings']:
data = [obj['start_path'], obj['default_player'], obj['default_img_viewer']]
except Exception as e:
print(repr(e))
data = ['', 'mplayer', 'xdg-open']
if data[0] == '':
data[0] = ''
if data[1] == '':
data[1] = 'mplayer'
if data[2] == '':
data[2] = 'xdg-open'
return data

View File

@@ -1,68 +0,0 @@
class SaveStateToXWinWarp:
def __init__(self, _settings):
self.settings = _settings
self.user_home = self.settings.get_home_path()
self._file_writer = None
self._to_be_background = None
self._use_xscreensvr = None
self._xscreen_value = None
self._save_file_target = None
self._resolution = None
self._player = None
def save_to_file(self, to_be_background, resolution, save_location,
use_xscreensvr, xscreen_value, player):
self._to_be_background = to_be_background
self._use_xscreensvr = use_xscreensvr
self._xscreen_value = xscreen_value
self._resolution = resolution
self._player = player
# Saves to file with selected and needed settings
if to_be_background:
if to_be_background.lower().endswith(self.settings.get_images_filter()):
self._save_file_target = f"{self.user_home}/.config/nitrogen/bg-saved.cfg"
else:
self._save_file_target = f"{self.user_home}/{save_location}"
elif use_xscreensvr and xscreen_value:
self._save_file_target = f"{self.user_home}/{save_location}"
else:
return -1
if self._save_file_target:
self._file_writer = open(self._save_file_target, "w")
return self.save()
def save(self):
applyType = 1
output = None
# XSCREENSAVER
if self._use_xscreensvr:
output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- /usr/lib/xscreensaver/{self._xscreen_value} -window-id WID -root";
# GIF
elif self._to_be_background.lower().endswith(('.gif')):
output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- gifview -a -w WID {self._to_be_background}";
# Standard images using nitrogen
elif self._to_be_background.lower().endswith(('.png', 'jpg', '.jpeg')):
output = f"[xin_0] \nfile={self._to_be_background}\nmode=0 \nbgcolor=#000000\n\n[xin_1] \nfile={self._to_be_background}\nmode=0 \nbgcolor=#000000";
applyType = 2;
# VIDEO
else:
output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- {self._player} -wid WID -really-quiet -ao null -loop 0 '{self._to_be_background}'";
pass
try:
if self._file_writer:
self._file_writer.write(output)
self._file_writer.close()
except Exception as e:
print(":: Write failed! ::")
print(e)
return applyType;

View File

@@ -1,9 +0,0 @@
"""
Gtk Bound Signal Module
"""
from .mixins import *
from .SaveStateToXWinWarp import SaveStateToXWinWarp
from .SaveGWinWrapSettings import SaveGWinWrapSettings
from .IPCServerMixin import IPCServerMixin
from .Controller_Data import Controller_Data
from .Controller import Controller

View File

@@ -1,56 +0,0 @@
# Python imports
import subprocess
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GdkPixbuf
# Application imports
class ThumbnailMixin:
"""docstring for ThumbnailMixin"""
def create_gtk_image(self, path, wxh):
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
filename = path,
width = wxh[0],
height = wxh[1],
preserve_aspect_ratio = True)
return Gtk.Image.new_from_pixbuf(pixbuf)
except Exception as e:
print(repr(e))
return Gtk.Image()
def generate_thumbnail(self, fullPathFile, hashImgpth):
# Stream duration
command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPathFile]
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", fullPathFile]
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", fullPathFile]
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", fullPathFile]
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, "-i", fullPathFile, "-an", "-vframes", "1", "-s", "320x180", "-q:v", "2", hashImgpth]
subprocess.call(command)

View File

@@ -1,4 +0,0 @@
from .ThumbnailMixin import ThumbnailMixin
from .DrawAreaMixin import DrawAreaMixin
from .ImageViewerMixin import ImageViewerMixin
from .GridMixin import GridMixin

View File

@@ -1,56 +0,0 @@
# Python imports
import os, logging
# Application imports
class Logger:
def __init__(self):
pass
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)
log.setLevel(globalLogLvl)
# 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 = "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

View File

@@ -1,112 +0,0 @@
# Python imports
import os
# Gtk imports
import gi, cairo
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
# Application imports
from . import Logger
class Settings:
def __init__(self):
self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__))
self._USER_HOME = os.path.expanduser('~')
self._CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}"
self._GLADE_FILE = f"{self._CONFIG_PATH}/Main_Window.glade"
self._CSS_FILE = f"{self._CONFIG_PATH}/stylesheet.css"
self._DEFAULT_ICONS = f"{self._CONFIG_PATH}/icons"
self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png"
self._USR_PATH = f"/usr/share/{app_name.lower()}"
self._CONFIG_FILE = f"{self._CONFIG_PATH}/settings.json"
self._XSCREEN_SAVERS = "/usr/lib/xscreensaver/"
self._logger = Logger().get_logger()
self._builder = Gtk.Builder()
self._main_window = None
# '_filters'
self._vids_filter = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
self._images_filter = ('.png', '.jpg', '.jpeg', '.gif')
self._success_color = "#88cc27"
self._warning_color = "#ffa800"
self._error_color = "#ff0000"
if not os.path.exists(self._GLADE_FILE):
self._GLADE_FILE = f"{self._USR_PATH}/Main_Window.glade"
if not os.path.exists(self._CSS_FILE):
self._CSS_FILE = f"{self._USR_PATH}/stylesheet.css"
if not os.path.exists(self._WINDOW_ICON):
self._WINDOW_ICON = f"{self._USR_PATH}/icons/{app_name.lower()}.png"
if not os.path.exists(self._DEFAULT_ICONS):
self.DEFAULT_ICONS = f"{self._USR_PATH}/icons"
self._builder.add_from_file(self._GLADE_FILE)
def create_window(self):
# Get window and connect signals
self._main_window = self._builder.get_object("Main_Window")
self.set_window_data()
def set_window_data(self):
self._main_window.set_icon_from_file(self._WINDOW_ICON)
screen = self._main_window.get_screen()
visual = screen.get_rgba_visual()
if visual != None and screen.is_composited():
self._main_window.set_visual(visual)
self._main_window.set_app_paintable(True)
self._main_window.connect("draw", self.draw_area)
# bind css file
cssProvider = Gtk.CssProvider()
cssProvider.load_from_path(self._CSS_FILE)
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
def get_monitor_data(self):
screen = self._builder.get_object("Main_Window").get_screen()
monitors = []
for m in range(screen.get_n_monitors()):
monitors.append(screen.get_monitor_geometry(m))
for monitor in monitors:
print("{}x{}|{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y))
return monitors
def draw_area(self, widget, cr):
cr.set_source_rgba(0, 0, 0, 0.54)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
def get_builder(self): return self._builder
def get_logger(self): return self._logger
def get_main_window(self): return self._main_window
def get_home_path(self): return self._USER_HOME
def get_config_file(self): return self._CONFIG_FILE
def get_xscreensavers(self): return self._XSCREEN_SAVERS
# Filter returns
def get_vids_filter(self): return self._vids_filter
def get_images_filter(self): return self._images_filter
def get_success_color(self): return self._success_color
def get_warning_color(self): return self._warning_color
def get_error_color(self): return self._error_color

View File

@@ -1,6 +1,3 @@
"""
Utils module
"""
from .Logger import Logger
from .Settings import Settings

View File

@@ -0,0 +1,22 @@
# Python imports
# Lib imports
# Application imports
class EndpointRegistry():
def __init__(self):
self._endpoints = {}
def register(self, rule, **options):
def decorator(f):
self._endpoints[rule] = f
return f
return decorator
def get_endpoints(self):
return self._endpoints

View File

@@ -0,0 +1,48 @@
# Python imports
from collections import defaultdict
# Lib imports
# Application imports
class EventSystem:
""" Create event system. """
def __init__(self):
self.subscribers = defaultdict(list)
def subscribe(self, event_type, fn):
self.subscribers[event_type].append(fn)
def unsubscribe(self, event_type, fn):
self.subscribers[event_type].remove(fn)
def unsubscribe_all(self, event_type):
self.subscribers.pop(event_type, None)
def emit(self, event_type, data = None):
if event_type in self.subscribers:
for fn in self.subscribers[event_type]:
if data:
if hasattr(data, '__iter__') and not type(data) is str:
fn(*data)
else:
fn(data)
else:
fn()
def emit_and_await(self, event_type, data = None):
""" NOTE: Should be used when signal has only one listener and vis-a-vis """
if event_type in self.subscribers:
for fn in self.subscribers[event_type]:
if data:
if hasattr(data, '__iter__') and not type(data) is str:
return fn(*data)
else:
return fn(data)
else:
return fn()

View File

@@ -0,0 +1,105 @@
# Python imports
import os
import threading
import time
from multiprocessing.connection import Client
from multiprocessing.connection import Listener
# Lib imports
# Application imports
class IPCServer:
""" Create a listener so that other {app_name} instances send requests back to existing instance. """
def __init__(self, ipc_address: str = '127.0.0.1', conn_type: str = "socket"):
self.is_ipc_alive = False
self._ipc_port = 4848
self._ipc_address = ipc_address
self._conn_type = conn_type
self._ipc_authkey = b'' + bytes(f'{app_name}-ipc', 'utf-8')
self._ipc_timeout = 15.0
if conn_type == "socket":
self._ipc_address = f'/tmp/{app_name}-ipc.sock'
elif conn_type == "full_network":
self._ipc_address = '0.0.0.0'
elif conn_type == "full_network_unsecured":
self._ipc_authkey = None
self._ipc_address = '0.0.0.0'
elif conn_type == "local_network_unsecured":
self._ipc_authkey = None
self._subscribe_to_events()
def _subscribe_to_events(self):
event_system.subscribe("post_file_to_ipc", self.send_ipc_message)
def create_ipc_listener(self) -> None:
if self._conn_type == "socket":
if os.path.exists(self._ipc_address) and settings.is_dirty_start():
os.unlink(self._ipc_address)
listener = Listener(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey)
elif "unsecured" not in self._conn_type:
listener = Listener((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey)
else:
listener = Listener((self._ipc_address, self._ipc_port))
self.is_ipc_alive = True
self._run_ipc_loop(listener)
@daemon_threaded
def _run_ipc_loop(self, listener) -> None:
while True:
conn = listener.accept()
start_time = time.perf_counter()
self._handle_ipc_message(conn, start_time)
listener.close()
def _handle_ipc_message(self, conn, start_time) -> None:
while True:
msg = conn.recv()
if settings.is_debug():
print(msg)
if "FILE|" in msg:
file = msg.split("FILE|")[1].strip()
if file:
event_system.emit("handle_file_from_ipc", file)
conn.close()
break
if msg in ['close connection', 'close server']:
conn.close()
break
# NOTE: Not perfect but insures we don't lock up the connection for too long.
end_time = time.perf_counter()
if (end_time - start_time) > self._ipc_timeout:
conn.close()
break
def send_ipc_message(self, message: str = "Empty Data...") -> None:
try:
if self._conn_type == "socket":
conn = Client(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey)
elif "unsecured" not in self._conn_type:
conn = Client((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey)
else:
conn = Client((self._ipc_address, self._ipc_port))
conn.send(message)
conn.close()
except ConnectionRefusedError as e:
print("Connection refused...")
except Exception as e:
print(repr(e))

View File

@@ -0,0 +1,128 @@
# Python imports
import re
# Lib imports
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
# Application imports
def err(log = ""):
"""Print an error message"""
print(log)
class KeymapError(Exception):
"""Custom exception for errors in keybinding configurations"""
MODIFIER = re.compile('<([^<]+)>')
class Keybindings:
"""Class to handle loading and lookup of Terminator keybindings"""
modifiers = {
'ctrl': Gdk.ModifierType.CONTROL_MASK,
'control': Gdk.ModifierType.CONTROL_MASK,
'primary': Gdk.ModifierType.CONTROL_MASK,
'shift': Gdk.ModifierType.SHIFT_MASK,
'alt': Gdk.ModifierType.MOD1_MASK,
'super': Gdk.ModifierType.SUPER_MASK,
'hyper': Gdk.ModifierType.HYPER_MASK,
'mod2': Gdk.ModifierType.MOD2_MASK
}
empty = {}
keys = None
_masks = None
_lookup = None
def __init__(self):
self.keymap = Gdk.Keymap.get_default()
self.configure({})
def configure(self, bindings):
"""Accept new bindings and reconfigure with them"""
self.keys = bindings
self.reload()
def reload(self):
"""Parse bindings and mangle into an appropriate form"""
self._lookup = {}
self._masks = 0
for action, bindings in list(self.keys.items()):
if isinstance(bindings, list):
bindings = (*bindings,)
elif not isinstance(bindings, tuple):
bindings = (bindings,)
for binding in bindings:
if not binding or binding == "None":
continue
try:
keyval, mask = self._parsebinding(binding)
# Does much the same, but with poorer error handling.
#keyval, mask = Gtk.accelerator_parse(binding)
except KeymapError as e:
err ("keybinding reload failed to parse binding '%s': %s" % (binding, e))
else:
if mask & Gdk.ModifierType.SHIFT_MASK:
if keyval == Gdk.KEY_Tab:
keyval = Gdk.KEY_ISO_Left_Tab
mask &= ~Gdk.ModifierType.SHIFT_MASK
else:
keyvals = Gdk.keyval_convert_case(keyval)
if keyvals[0] != keyvals[1]:
keyval = keyvals[1]
mask &= ~Gdk.ModifierType.SHIFT_MASK
else:
keyval = Gdk.keyval_to_lower(keyval)
self._lookup.setdefault(mask, {})
self._lookup[mask][keyval] = action
self._masks |= mask
def _parsebinding(self, binding):
"""Parse an individual binding using Gtk's binding function"""
mask = 0
modifiers = re.findall(MODIFIER, binding)
if modifiers:
for modifier in modifiers:
mask |= self._lookup_modifier(modifier)
key = re.sub(MODIFIER, '', binding)
if key == '':
raise KeymapError('No key found!')
keyval = Gdk.keyval_from_name(key)
if keyval == 0:
raise KeymapError("Key '%s' is unrecognised..." % key)
return (keyval, mask)
def _lookup_modifier(self, modifier):
"""Map modifier names to gtk values"""
try:
return self.modifiers[modifier.lower()]
except KeyError:
raise KeymapError("Unhandled modifier '<%s>'" % modifier)
def lookup(self, event):
"""Translate a keyboard event into a mapped key"""
try:
_found, keyval, _egp, _lvl, consumed = self.keymap.translate_keyboard_state(
event.hardware_keycode,
Gdk.ModifierType(event.get_state() & ~Gdk.ModifierType.LOCK_MASK),
event.group)
except TypeError:
err ("Keybinding lookup failed to translate keyboard event: %s" % dir(event))
return None
mask = (event.get_state() & ~consumed) & self._masks
return self._lookup.get(mask, self.empty).get(keyval, None)

View File

@@ -0,0 +1,61 @@
# Python imports
import os
import logging
# Lib imports
# Application imports
class Logger:
"""
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
"""
def __init__(self, config_path: str, _ch_log_lvl = logging.CRITICAL, _fh_log_lvl = logging.INFO):
self._CONFIG_PATH = config_path
self.global_lvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels
self.ch_log_lvl = _ch_log_lvl # Prety much the only one we ever change
self.fh_log_lvl = _fh_log_lvl
def get_logger(self, loggerName: str = "NO_LOGGER_NAME_PASSED", createFile: bool = True) -> logging.Logger:
log = logging.getLogger(loggerName)
log.setLevel(self.global_lvl)
# 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=self.ch_log_lvl)
ch.setFormatter(cFormatter)
log.addHandler(ch)
if createFile:
folder = self._CONFIG_PATH
file = f"{folder}/application.log"
if not os.path.exists(folder):
os.mkdir(folder)
fh = logging.FileHandler(file)
fh.setLevel(level=self.fh_log_lvl)
fh.setFormatter(fFormatter)
log.addHandler(fh)
return log

View File

@@ -0,0 +1,176 @@
# Python imports
import os
import json
import inspect
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from .logger import Logger
class Settings:
def __init__(self):
self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__))
self._USER_HOME = os.path.expanduser('~')
self._USR_PATH = f"/usr/share/{app_name.lower()}"
self._USR_CONFIG_FILE = f"{self._USR_PATH}/settings.json"
self._HOME_CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}"
self._DEFAULT_ICONS = f"{self._HOME_CONFIG_PATH}/icons"
self._CONFIG_FILE = f"{self._HOME_CONFIG_PATH}/settings.json"
self._GLADE_FILE = f"{self._HOME_CONFIG_PATH}/Main_Window.glade"
self._CSS_FILE = f"{self._HOME_CONFIG_PATH}/stylesheet.css"
self._PID_FILE = f"{self._HOME_CONFIG_PATH}/{app_name.lower()}.pid"
self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png"
if not os.path.exists(self._HOME_CONFIG_PATH):
os.mkdir(self._HOME_CONFIG_PATH)
if not os.path.exists(self._CONFIG_FILE):
import shutil
try:
shutil.copyfile(self._USR_CONFIG_FILE, self._CONFIG_FILE)
except Exception as e:
raise
if not os.path.exists(self._GLADE_FILE):
self._GLADE_FILE = f"{self._USR_PATH}/Main_Window.glade"
if not os.path.exists(self._CSS_FILE):
self._CSS_FILE = f"{self._USR_PATH}/stylesheet.css"
if not os.path.exists(self._DEFAULT_ICONS):
self.DEFAULT_ICONS = f"{self._USR_PATH}/icons"
if not os.path.exists(self._WINDOW_ICON):
self._WINDOW_ICON = f"{self.DEFAULT_ICONS}/{app_name.lower()}.png"
thumbnail_path = f"{self._USER_HOME}/.thumbnails/normal"
if not os.path.exists(thumbnail_path):
os.system(f"mkdir -p '{thumbnail_path}'")
self._logger = Logger(self._HOME_CONFIG_PATH).get_logger()
self._builder = Gtk.Builder()
self._builder.add_from_file(self._GLADE_FILE)
self._debug = False
self._trace_debug = False
self._dirty_start = False
self._settings = None
self._config = None
self._theming = None
self.load_settings()
def is_trace_debug(self) -> str: return self._trace_debug
def is_debug(self) -> str: return self._debug
def is_dirty_start(self) -> bool: return self._dirty_start
def clear_pid(self): self._clean_pid()
def do_dirty_start_check(self):
if not os.path.exists(self._PID_FILE):
self._write_new_pid()
else:
with open(self._PID_FILE, "r") as _pid:
pid = _pid.readline().strip()
if pid not in ("", None):
self._check_alive_status(int(pid))
else:
self._write_new_pid()
""" Check For the existence of a unix pid. """
def _check_alive_status(self, pid):
print(f"PID Found: {pid}")
try:
os.kill(pid, 0)
except OSError:
print(f"{app_name} is starting dirty...")
self._dirty_start = True
self._write_new_pid()
return
print("PID is alive... Let downstream errors (sans debug args) handle app closure propigation.")
def _write_new_pid(self):
pid = os.getpid()
self._write_pid(pid)
def _clean_pid(self):
os.unlink(self._PID_FILE)
def _write_pid(self, pid):
with open(self._PID_FILE, "w") as _pid:
_pid.write(f"{pid}")
def register_signals_to_builder(self, classes=None):
handlers = {}
for c in classes:
methods = None
try:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
except Exception as e:
print(repr(e))
self._builder.connect_signals(handlers)
def get_monitor_data(self, window):
screen = window.get_screen()
monitors = []
for m in range(screen.get_n_monitors()):
monitors.append(screen.get_monitor_geometry(m))
for monitor in monitors:
print("{}x{}|{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y))
return monitors
def get_builder(self) -> any: return self._builder
def get_config_file(self) -> str: return self._CONFIG_FILE
def get_glade_file(self) -> str: return self._GLADE_FILE
def get_logger(self) -> Logger: return self._logger
def get_icon_theme(self) -> str: return self._ICON_THEME
def get_css_file(self) -> str: return self._CSS_FILE
def get_window_icon(self) -> str: return self._WINDOW_ICON
def get_home_path(self) -> str: return self._USER_HOME
def get_success_color(self) -> str: return self._theming["success_color"]
def get_warning_color(self) -> str: return self._theming["warning_color"]
def get_error_color(self) -> str: return self._theming["error_color"]
def get_xscreensavers(self) -> str: return self._config["xscreensaver_path"]
def get_start_path(self) -> str: return self._config["start_path"]
def get_default_player(self) -> str: return self._config["default_player"]
def get_default_img_viewer(self) -> str: return self._config["default_img_viewer"]
def get_vids_filter(self) -> tuple: return tuple(self._settings["filters"]["videos"])
def get_images_filter(self) -> tuple: return tuple(self._settings["filters"]["images"])
def set_builder(self, builder): self._builder = builder
def set_start_path(self, path): self._config["start_path"] = path
def set_default_player(self, player): self._config["default_player"] = player
def set_default_img_viewer(self, viewer): self._config["default_img_viewer"] = viewer
def set_trace_debug(self, trace_debug):
self._trace_debug = trace_debug
def set_debug(self, debug):
self._debug = debug
def load_settings(self):
with open(self._CONFIG_FILE) as f:
self._settings = json.load(f)
self._config = self._settings["config"]
self._theming = self._settings["theming"]
def save_settings(self):
with open(self._CONFIG_FILE, 'w') as outfile:
json.dump(self._settings, outfile, separators=(',', ':'), indent=4)

View File

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

View File

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

28
user_config/bin/gwinwrap Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
# . CONFIG.sh
# 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() {
call_path=`pwd`
path=""
if [[ ! "${1::1}" == /* ]]; then
path="${call_path}/${1}"
else
path="${1}"
fi
if [ ! -d "${path}" ]; then
echo "GWinWrap: Path given not a directory..."
exit 1
fi
cd "/opt/"
python ./gwinwrap.zip "${path}"
}
main "$@";

Some files were not shown because too many files have changed in this diff Show More