From 35383a95cb03a73122ad4c387e8b94def527c6b1 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Thu, 23 Feb 2023 12:42:28 -0600 Subject: [PATCH] Major refactor to match my template project --- README.md | 1 - bin/gwinwrap-0-0-1-x64.deb | Bin 42108 -> 0 bytes bin/gwinwrap-0-0-2-x64.deb | Bin 36032 -> 0 bytes src/debs/{chownAll.sh => chown_all.sh} | 0 src/debs/gwinwrap-0-0-1-x64/DEBIAN/control | 8 - src/debs/gwinwrap-0-0-1-x64/DEBIAN/postrm | 11 - src/debs/gwinwrap-0-0-1-x64/bin/gwinwrap | Bin 6168 -> 0 bytes src/debs/gwinwrap-0-0-1-x64/bin/xwinwrap | Bin 22603 -> 0 bytes .../opt/GWinWrap/GWinWrap.desktop | 9 - .../opt/GWinWrap/__init__.py | 41 - .../opt/GWinWrap/__main__.py | 9 - .../gwinwrap-0-0-1-x64/opt/GWinWrap/gwinwrap | Bin 6168 -> 0 bytes .../opt/GWinWrap/resources/Main_Window.glade | 844 ------------------ .../opt/GWinWrap/resources/icons/GWinWrap.png | Bin 9278 -> 0 bytes .../opt/GWinWrap/resources/icons/folder.png | Bin 4698 -> 0 bytes .../opt/GWinWrap/resources/icons/picture.png | Bin 6591 -> 0 bytes .../opt/GWinWrap/resources/icons/player.png | Bin 6535 -> 0 bytes .../opt/GWinWrap/resources/stylesheet.css | 3 - .../signal_classes/CrossClassSignals.py | 397 -------- .../opt/GWinWrap/signal_classes/__init__.py | 1 - .../GWinWrap/utils/SaveGWinWrapSettings.py | 52 -- .../opt/GWinWrap/utils/SaveStateToXWinWarp.py | 69 -- .../opt/GWinWrap/utils/Settings.py | 74 -- .../opt/GWinWrap/utils/__init__.py | 3 - .../usr/share/doc/gwinwrap/copyright | 22 - src/debs/gwinwrap-0-0-2-x64/DEBIAN/postrm | 12 +- src/debs/gwinwrap-0-0-2-x64/bin/gwinwrap | Bin 6168 -> 519 bytes .../opt/GWinWrap/__builtins__.py | 73 -- .../opt/GWinWrap/__init__.py | 50 -- .../opt/GWinWrap/__main__.py | 39 - .../opt/GWinWrap/signal_classes/Controller.py | 151 ---- .../signal_classes/Controller_Data.py | 102 --- .../GWinWrap/signal_classes/IPCServerMixin.py | 64 -- .../signal_classes/SaveGWinWrapSettings.py | 49 - .../opt/GWinWrap/signal_classes/__init__.py | 9 - .../signal_classes/mixins/DrawAreaMixin.py | 59 -- .../signal_classes/mixins/GridMixin.py | 116 --- .../signal_classes/mixins/ImageViewerMixin.py | 34 - .../opt/GWinWrap/utils/Logger.py | 56 -- .../opt/GWinWrap/utils/Settings.py | 112 --- .../opt/GWinWrap/utils/__init__.py | 2 - src/debs/gwinwrap-0-0-2-x64/opt/gwinwrap.zip | Bin 0 -> 19353 bytes .../usr/share/applications/gwinwrap.desktop | 9 + .../usr/share/gwinwrap/Main_Window.glade | 784 ++++++++-------- .../usr/share/gwinwrap/settings.json | 43 +- src/versions/0.0.1/GWinWrap/GWinWrap.desktop | 9 - src/versions/0.0.1/GWinWrap/__init__.py | 41 - src/versions/0.0.1/GWinWrap/__main__.py | 9 - .../GWinWrap/resources/Main_Window.glade | 844 ------------------ .../GWinWrap/resources/icons/GWinWrap.png | Bin 9278 -> 0 bytes .../0.0.1/GWinWrap/resources/icons/folder.png | Bin 4698 -> 0 bytes .../GWinWrap/resources/icons/picture.png | Bin 6591 -> 0 bytes .../0.0.1/GWinWrap/resources/icons/player.png | Bin 6535 -> 0 bytes .../0.0.1/GWinWrap/resources/stylesheet.css | 3 - .../signal_classes/CrossClassSignals.py | 403 --------- .../0.0.1/GWinWrap/signal_classes/__init__.py | 1 - .../GWinWrap/utils/SaveGWinWrapSettings.py | 52 -- .../GWinWrap/utils/SaveStateToXWinWarp.py | 69 -- src/versions/0.0.1/GWinWrap/utils/Settings.py | 74 -- src/versions/0.0.1/GWinWrap/utils/__init__.py | 3 - src/versions/0.0.1/XWinWrap/Makefile | 20 - src/versions/0.0.1/XWinWrap/xwinwrap.c | 459 ---------- src/versions/0.0.1/compileBin.sh | 6 - src/versions/0.0.1/gwinwrap_exec_bin.cpp | 10 - src/versions/0.0.2/GWinWrap/__builtins__.py | 79 +- src/versions/0.0.2/GWinWrap/__init__.py | 53 +- src/versions/0.0.2/GWinWrap/__main__.py | 30 +- src/versions/0.0.2/GWinWrap/app.py | 40 + src/versions/0.0.2/GWinWrap/core/__init__.py | 3 + .../0.0.2/GWinWrap/core/controller.py | 123 +++ .../0.0.2/GWinWrap/core/controller_data.py | 120 +++ .../mixins/DrawAreaMixin.py | 10 +- .../mixins/GridMixin.py | 55 +- .../mixins/ImageViewerMixin.py | 4 +- .../GWinWrap/core}/mixins/ThumbnailMixin.py | 3 +- .../0.0.2/GWinWrap/core}/mixins/__init__.py | 3 + .../GWinWrap/core/save_state_to_xwinwarp.py} | 38 +- src/versions/0.0.2/GWinWrap/core/window.py | 83 ++ .../GWinWrap/signal_classes/Controller.py | 151 ---- .../signal_classes/Controller_Data.py | 102 --- .../GWinWrap/signal_classes/IPCServerMixin.py | 64 -- .../signal_classes/SaveGWinWrapSettings.py | 49 - .../signal_classes/SaveStateToXWinWarp.py | 68 -- .../0.0.2/GWinWrap/signal_classes/__init__.py | 9 - .../signal_classes/mixins/ThumbnailMixin.py | 56 -- .../signal_classes/mixins/__init__.py | 4 - src/versions/0.0.2/GWinWrap/utils/Logger.py | 56 -- src/versions/0.0.2/GWinWrap/utils/Settings.py | 112 --- src/versions/0.0.2/GWinWrap/utils/__init__.py | 5 +- .../0.0.2/GWinWrap/utils/endpoint_registry.py | 22 + .../0.0.2/GWinWrap/utils/event_system.py | 48 + .../0.0.2/GWinWrap/utils/ipc_server.py | 105 +++ .../0.0.2/GWinWrap/utils/keybindings.py | 128 +++ src/versions/0.0.2/GWinWrap/utils/logger.py | 61 ++ src/versions/0.0.2/GWinWrap/utils/settings.py | 173 ++++ src/versions/0.0.2/compileBin.sh | 6 - src/versions/0.0.2/gwinwrap_exec_bin.cpp | 10 - user_config/bin/gwinwrap | 28 + user_config/usr/applications/gwinwrap.desktop | 9 + .../usr/share/gwinwrap/Main_Window.glade | 784 ++++++++-------- user_config/usr/share/gwinwrap/settings.json | 43 +- 101 files changed, 1939 insertions(+), 6109 deletions(-) delete mode 100644 bin/gwinwrap-0-0-1-x64.deb delete mode 100644 bin/gwinwrap-0-0-2-x64.deb rename src/debs/{chownAll.sh => chown_all.sh} (100%) delete mode 100644 src/debs/gwinwrap-0-0-1-x64/DEBIAN/control delete mode 100755 src/debs/gwinwrap-0-0-1-x64/DEBIAN/postrm delete mode 100755 src/debs/gwinwrap-0-0-1-x64/bin/gwinwrap delete mode 100755 src/debs/gwinwrap-0-0-1-x64/bin/xwinwrap delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/GWinWrap.desktop delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__init__.py delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__main__.py delete mode 100755 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/gwinwrap delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/Main_Window.glade delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/GWinWrap.png delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/folder.png delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/picture.png delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/player.png delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/stylesheet.css delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/CrossClassSignals.py delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/__init__.py delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveGWinWrapSettings.py delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveStateToXWinWarp.py delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/Settings.py delete mode 100644 src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/__init__.py delete mode 100644 src/debs/gwinwrap-0-0-1-x64/usr/share/doc/gwinwrap/copyright delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__builtins__.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__init__.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__main__.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller_Data.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/IPCServerMixin.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveGWinWrapSettings.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/__init__.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/DrawAreaMixin.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/GridMixin.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/ImageViewerMixin.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Logger.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Settings.py delete mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/__init__.py create mode 100644 src/debs/gwinwrap-0-0-2-x64/opt/gwinwrap.zip create mode 100755 src/debs/gwinwrap-0-0-2-x64/usr/share/applications/gwinwrap.desktop delete mode 100644 src/versions/0.0.1/GWinWrap/GWinWrap.desktop delete mode 100644 src/versions/0.0.1/GWinWrap/__init__.py delete mode 100644 src/versions/0.0.1/GWinWrap/__main__.py delete mode 100644 src/versions/0.0.1/GWinWrap/resources/Main_Window.glade delete mode 100644 src/versions/0.0.1/GWinWrap/resources/icons/GWinWrap.png delete mode 100644 src/versions/0.0.1/GWinWrap/resources/icons/folder.png delete mode 100644 src/versions/0.0.1/GWinWrap/resources/icons/picture.png delete mode 100644 src/versions/0.0.1/GWinWrap/resources/icons/player.png delete mode 100644 src/versions/0.0.1/GWinWrap/resources/stylesheet.css delete mode 100644 src/versions/0.0.1/GWinWrap/signal_classes/CrossClassSignals.py delete mode 100644 src/versions/0.0.1/GWinWrap/signal_classes/__init__.py delete mode 100644 src/versions/0.0.1/GWinWrap/utils/SaveGWinWrapSettings.py delete mode 100644 src/versions/0.0.1/GWinWrap/utils/SaveStateToXWinWarp.py delete mode 100644 src/versions/0.0.1/GWinWrap/utils/Settings.py delete mode 100644 src/versions/0.0.1/GWinWrap/utils/__init__.py delete mode 100644 src/versions/0.0.1/XWinWrap/Makefile delete mode 100644 src/versions/0.0.1/XWinWrap/xwinwrap.c delete mode 100755 src/versions/0.0.1/compileBin.sh delete mode 100644 src/versions/0.0.1/gwinwrap_exec_bin.cpp create mode 100644 src/versions/0.0.2/GWinWrap/app.py create mode 100644 src/versions/0.0.2/GWinWrap/core/__init__.py create mode 100644 src/versions/0.0.2/GWinWrap/core/controller.py create mode 100644 src/versions/0.0.2/GWinWrap/core/controller_data.py rename src/versions/0.0.2/GWinWrap/{signal_classes => core}/mixins/DrawAreaMixin.py (93%) rename src/versions/0.0.2/GWinWrap/{signal_classes => core}/mixins/GridMixin.py (72%) rename src/versions/0.0.2/GWinWrap/{signal_classes => core}/mixins/ImageViewerMixin.py (94%) rename src/{debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes => versions/0.0.2/GWinWrap/core}/mixins/ThumbnailMixin.py (99%) rename src/{debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes => versions/0.0.2/GWinWrap/core}/mixins/__init__.py (86%) rename src/{debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveStateToXWinWarp.py => versions/0.0.2/GWinWrap/core/save_state_to_xwinwarp.py} (73%) create mode 100644 src/versions/0.0.2/GWinWrap/core/window.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/Controller.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/__init__.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py delete mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py delete mode 100644 src/versions/0.0.2/GWinWrap/utils/Logger.py delete mode 100644 src/versions/0.0.2/GWinWrap/utils/Settings.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/endpoint_registry.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/event_system.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/ipc_server.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/keybindings.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/logger.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/settings.py delete mode 100755 src/versions/0.0.2/compileBin.sh delete mode 100644 src/versions/0.0.2/gwinwrap_exec_bin.cpp create mode 100755 user_config/bin/gwinwrap create mode 100755 user_config/usr/applications/gwinwrap.desktop diff --git a/README.md b/README.md index f75c6bf..50930d4 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,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 diff --git a/bin/gwinwrap-0-0-1-x64.deb b/bin/gwinwrap-0-0-1-x64.deb deleted file mode 100644 index 3c3e9250f9fc005e7549db042cd0da7b01b5d226..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42108 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 diff --git a/src/debs/chownAll.sh b/src/debs/chown_all.sh similarity index 100% rename from src/debs/chownAll.sh rename to src/debs/chown_all.sh diff --git a/src/debs/gwinwrap-0-0-1-x64/DEBIAN/control b/src/debs/gwinwrap-0-0-1-x64/DEBIAN/control deleted file mode 100644 index a23c389..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/DEBIAN/control +++ /dev/null @@ -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. diff --git a/src/debs/gwinwrap-0-0-1-x64/DEBIAN/postrm b/src/debs/gwinwrap-0-0-1-x64/DEBIAN/postrm deleted file mode 100755 index 0f30ccd..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/DEBIAN/postrm +++ /dev/null @@ -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 diff --git a/src/debs/gwinwrap-0-0-1-x64/bin/gwinwrap b/src/debs/gwinwrap-0-0-1-x64/bin/gwinwrap deleted file mode 100755 index 2166a10f4ace993cb2f69f203ca8b9d829d7ce91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6168 zcmeHLUrbw77(Xq4C)=g!<|=5o>Xvj{xRi~t>i*rr1{Z@1PLL%NN`bQ0(3Z5f2tG`d zZAn#hFD5)0Vxo`62OoGa3SrrNgk+hCei3=deQoW)7$1BvoaUb2 z_wRSkcmCYdd+%GvTbt}Qo8V#>M+9nZg}O9ZwGgKsl`7dhVw2ECrKk|aU@3%4mmWk* zV!TgHGnP_Z0U+``cFW+g>r!BR$}$T^&JeMPd=}`WS*Vwgl~4#(8jy#%Iuxk__DF%z zMR~XhnTIO!RN|?`W1OeN7`0}8tOWNI40{XVl0-nC9_}3*eRA`T>|4F zOB0ODdl`64p^(1?2YF9Yf9uUlipIxCs;C(Z_14$b4E9$Kh9ZfP>Jd+Ub$y){k7|46 zxUqeVZ9dTABu_iXxt2hh0li$U)=P^Okda^iiqacmWD>( zUTv?oAG~M6(Fl2c*rr|naE$naeMuc9DngskyPNb>d5@HEZE?Q1+|RM|9zdVd(IZ1} z`(wLY)Eqmn1Nw~dUrUYmidM>0VVs{a?df@A{8H&0(?ojzb#SG3-hjHiN(Tw`Ao_1E zrlIWo9(C;M<~*piD=o=|ZXom?`vPooP{+tT$78qr!z(}Ty z+2x~#?Xt13YHrK4P?l{$Fn{cDE#x8++dGWp((+jt!R4YVu-LlhC_l_9nyZO{YQr6y+6=Wq;hhx6}J-OY%E!hqt|TV&})DDkM8mjrfW;`Jg3vuXWdw zT!YyM1HLbR*8aeA(wh9EHF@t?^0qg<^+#iT&SpISQ{on`(djPlYu+wzx7Rm! zF`M5VSUTArt)dO~QcZNotZD8HMLJ{tp&BtXY6hc`eX0ft3tMHuK|D+383)}@g4_mp z3UCY%SLOiB$_!u+;36Qdvx_zt-p5#MZ=Mvk5r?gEb4lq%TZserGoIb42kG=441ltB zthM(s_AbQo-rNDY8?G_1AqvIOq&QzJFMFeOOdPE^xO?A@XVHv2%oV5ZIW%|`#|3-i zmf~(m1XS2!VgxVn2LMHb;`q?spg2D$IIgG@g$;`9{USqgUnn*d&v?m8iXKxuUd8QI zTn&l}aS-32l*;>a2Iy1J4(Eu?ZIq1}*qDKh8Q7SCjT!hq%zzu7&txIwXGq4)Jjg;T zZVTyGDgH^)`Ms)=bbc?YAl*stQTYFjh5f&;rlY7&+I57?yPmti()k@{+HUEOKn#}S z76^R)$Ktd=Y$IgIJVVp-F#ng!XAB79XOt2mY$u$j{@Ff7I_J%NczBnE`-jH`Ii4|! zhes!=+bAwY`Y`#){GS28$L4ofPwU%6nD1|HY^C( z{?SN$G;E<6vpmCrSUePs{6+DBFBTZ|BY~u$K@+bx zmVAC4IPbyU=Kd$`x(uHr1Lx1*a`--yK~Nom3+I6O({>#+A*RVNA~oy11;@^OC)t|- z@m^;>pC4{I0QkJ1@Q3E_1UT?sWj^1Z!^G!vhx6w+#?!#Zd!Kc_|Hp{0Qpb3n<>pUj z@j3`Nr_7%!(4}jN_v;lU@l)JzDj(~pJ@&f7|-SL`Fms=@!!G5a|-j=^ezaw{qz6RRhlq9r#YUQWmQ}x zKF|MRkuH6U#D6*yX$krKNibvo%ooMF6-X0$$kH-(KL0cD%^DN3_H7iZ2AHO z{A5YXo%6lZis1F;c-9%e0!MicpZ~9&^c|Gr*5iK*4osE%=l>c0jyg~4$HU?FcpVpj ziy_SC?_eoR3JS+rT6X;0&NXo4@&*0hGttFFLgq34oX2+&-$fm-*FQJA1Om3j`Qzs) sEFL0qKhg*lO$V#u7TMexizP6BSDu~uxyXIzhWe@hJGn-XnaAco0XfC{djJ3c diff --git a/src/debs/gwinwrap-0-0-1-x64/bin/xwinwrap b/src/debs/gwinwrap-0-0-1-x64/bin/xwinwrap deleted file mode 100755 index 26eafd7bd37915f130b67a7db347caa38ddafaf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22603 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 DjE;QH diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/GWinWrap.desktop b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/GWinWrap.desktop deleted file mode 100644 index 543fdb6..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/GWinWrap.desktop +++ /dev/null @@ -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; diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__init__.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__init__.py deleted file mode 100644 index 0beb3ee..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__init__.py +++ /dev/null @@ -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() diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__main__.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__main__.py deleted file mode 100644 index 60c7ea2..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/__main__.py +++ /dev/null @@ -1,9 +0,0 @@ -from __init__ import Main, gtk - - -if __name__ == "__main__": - try: - main = Main() - gtk.main() - except Exception as e: - print(e) diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/gwinwrap b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/gwinwrap deleted file mode 100755 index 2166a10f4ace993cb2f69f203ca8b9d829d7ce91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6168 zcmeHLUrbw77(Xq4C)=g!<|=5o>Xvj{xRi~t>i*rr1{Z@1PLL%NN`bQ0(3Z5f2tG`d zZAn#hFD5)0Vxo`62OoGa3SrrNgk+hCei3=deQoW)7$1BvoaUb2 z_wRSkcmCYdd+%GvTbt}Qo8V#>M+9nZg}O9ZwGgKsl`7dhVw2ECrKk|aU@3%4mmWk* zV!TgHGnP_Z0U+``cFW+g>r!BR$}$T^&JeMPd=}`WS*Vwgl~4#(8jy#%Iuxk__DF%z zMR~XhnTIO!RN|?`W1OeN7`0}8tOWNI40{XVl0-nC9_}3*eRA`T>|4F zOB0ODdl`64p^(1?2YF9Yf9uUlipIxCs;C(Z_14$b4E9$Kh9ZfP>Jd+Ub$y){k7|46 zxUqeVZ9dTABu_iXxt2hh0li$U)=P^Okda^iiqacmWD>( zUTv?oAG~M6(Fl2c*rr|naE$naeMuc9DngskyPNb>d5@HEZE?Q1+|RM|9zdVd(IZ1} z`(wLY)Eqmn1Nw~dUrUYmidM>0VVs{a?df@A{8H&0(?ojzb#SG3-hjHiN(Tw`Ao_1E zrlIWo9(C;M<~*piD=o=|ZXom?`vPooP{+tT$78qr!z(}Ty z+2x~#?Xt13YHrK4P?l{$Fn{cDE#x8++dGWp((+jt!R4YVu-LlhC_l_9nyZO{YQr6y+6=Wq;hhx6}J-OY%E!hqt|TV&})DDkM8mjrfW;`Jg3vuXWdw zT!YyM1HLbR*8aeA(wh9EHF@t?^0qg<^+#iT&SpISQ{on`(djPlYu+wzx7Rm! zF`M5VSUTArt)dO~QcZNotZD8HMLJ{tp&BtXY6hc`eX0ft3tMHuK|D+383)}@g4_mp z3UCY%SLOiB$_!u+;36Qdvx_zt-p5#MZ=Mvk5r?gEb4lq%TZserGoIb42kG=441ltB zthM(s_AbQo-rNDY8?G_1AqvIOq&QzJFMFeOOdPE^xO?A@XVHv2%oV5ZIW%|`#|3-i zmf~(m1XS2!VgxVn2LMHb;`q?spg2D$IIgG@g$;`9{USqgUnn*d&v?m8iXKxuUd8QI zTn&l}aS-32l*;>a2Iy1J4(Eu?ZIq1}*qDKh8Q7SCjT!hq%zzu7&txIwXGq4)Jjg;T zZVTyGDgH^)`Ms)=bbc?YAl*stQTYFjh5f&;rlY7&+I57?yPmti()k@{+HUEOKn#}S z76^R)$Ktd=Y$IgIJVVp-F#ng!XAB79XOt2mY$u$j{@Ff7I_J%NczBnE`-jH`Ii4|! zhes!=+bAwY`Y`#){GS28$L4ofPwU%6nD1|HY^C( z{?SN$G;E<6vpmCrSUePs{6+DBFBTZ|BY~u$K@+bx zmVAC4IPbyU=Kd$`x(uHr1Lx1*a`--yK~Nom3+I6O({>#+A*RVNA~oy11;@^OC)t|- z@m^;>pC4{I0QkJ1@Q3E_1UT?sWj^1Z!^G!vhx6w+#?!#Zd!Kc_|Hp{0Qpb3n<>pUj z@j3`Nr_7%!(4}jN_v;lU@l)JzDj(~pJ@&f7|-SL`Fms=@!!G5a|-j=^ezaw{qz6RRhlq9r#YUQWmQ}x zKF|MRkuH6U#D6*yX$krKNibvo%ooMF6-X0$$kH-(KL0cD%^DN3_H7iZ2AHO z{A5YXo%6lZis1F;c-9%e0!MicpZ~9&^c|Gr*5iK*4osE%=l>c0jyg~4$HU?FcpVpj ziy_SC?_eoR3JS+rT6X;0&NXo4@&*0hGttFFLgq34oX2+&-$fm-*FQJA1Om3j`Qzs) sEFL0qKhg*lO$V#u7TMexizP6BSDu~uxyXIzhWe@hJGn-XnaAco0XfC{djJ3c diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/Main_Window.glade b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/Main_Window.glade deleted file mode 100644 index 495ebfe..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/Main_Window.glade +++ /dev/null @@ -1,844 +0,0 @@ - - - - - - - inode/directory - - - - - - - - - - True - False - gtk-clear - 3 - - - True - False - gtk-quit - 3 - - - True - False - gtk-cancel - 3 - - - True - False - gtk-jump-to - 3 - - - True - False - gtk-save - 3 - - - True - False - gtk-save - 3 - - - True - False - Settings.... - gtk-properties - 3 - - - True - False - gtk-media-play - 3 - - - True - False - gtk-media-stop - 3 - - - 950 - 600 - False - GWinWrap - center - 950 - 600 - icons/GWinWrap.png - center - - - - - - True - False - - - True - False - 15 - 15 - 15 - vertical - - - True - False - 5 - - - True - False - 15 - Note: Double click an image to view the video or image. - - - True - True - 0 - - - - - True - False - Chose Dream Scene / Image Directory - select-folder - False - Folders - Dream Scene / Image Dir - - - - False - True - 1 - - - - - True - True - True - settingsImage - True - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - True - - - False - True - 1 - - - - - True - True - in - - - True - False - - - True - False - vertical - 10 - 10 - True - True - - - 640 - 525 - True - False - Choose Image/Video Directory... - - - - - - 0 - 0 - - - - - - - - - True - True - 2 - - - - - Clear - True - True - True - clearImage - True - - - - False - True - 3 - - - - - True - True - 0 - - - - - 300 - True - False - 10 - 15 - 15 - 15 - False - vertical - - - True - False - vertical - - - Use XScreenSaver - True - True - False - center - 5 - True - - - - False - True - 0 - - - - - True - True - in - - - True - False - True - XScreensaver List - False - - - - - - - - XScreensaves - - - - 0 - - - - - - - - - True - True - 1 - - - - - True - True - 0 - - - - - True - False - False - vertical - - - True - False - vertical - - - True - False - - - True - False - 10 - 10 - Playback Resolutions - - - True - True - 0 - - - - - True - False - 10 - 10 - Position Offset - - - True - True - 1 - - - - - False - True - 0 - - - - - True - False - - - True - False - 3 - - 7680x4320 - 3840x2160 - 2048x1080 - 1920x1080 - 1440x720 - 1600x900 - 1280x720 - 800x600 - - - - True - True - 0 - - - - - True - False - - - True - True - 1 - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - vertical - - - True - False - 10 - 5 - Save Path - - - True - True - 0 - - - - - True - False - 0 - - .animatedBGstarter.sh - .animatedBGstarter2.sh - .animatedBGstarter3.sh - - - - True - True - 1 - - - - - False - True - 1 - - - - - True - False - - - Save - True - True - True - True - True - saveImage - True - - - - 1 - 0 - - - - - (Re)Start - True - True - True - True - True - startImage - True - - - - 0 - 0 - - - - - Stop - True - True - True - True - True - stopImage - True - - - - 0 - 1 - - - - - Close - True - True - True - True - True - closeImage - True - - - - 1 - 1 - - - - - False - True - 2 - - - - - False - False - end - 1 - - - - - False - True - 1 - 1 - - - - - - - 640 - 525 - False - 350 - True - True - helpLabel - bottom - False - - - True - False - vertical - - - True - False - - - True - True - True - Close Demo Window - closePopupImage - True - - - - False - True - end - 0 - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - - - - - True - True - 1 - - - - - - - 640 - 525 - False - True - True - helpLabel - bottom - - - True - False - vertical - - - True - False - bottom - - - Main Image Viewer - True - True - True - openProgImage - True - - - - False - True - 0 - - - - - True - True - True - True - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - True - in - False - - - True - False - - - True - False - gtk-missing-image - 6 - - - - - - - True - True - 1 - - - - - - - 250 - False - button1 - - - True - False - vertical - - - True - False - - - True - False - icons/folder.png - - - False - True - 0 - - - - - 330 - 26 - True - True - Set Custom Default Path - Set Custom Default Path - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - - - True - False - icons/player.png - - - False - True - 0 - - - - - 330 - 26 - True - True - Set Custom Video Player - Set Custom Video Player - - - False - True - 1 - - - - - False - True - 1 - - - - - True - False - - - True - False - icons/picture.png - - - False - True - 0 - - - - - 330 - 26 - True - True - Set Custom Image Viewer - Set Custom Image Viewer - - - False - True - 1 - - - - - False - True - 2 - - - - - Save - True - True - True - saveImag - True - - - - False - True - 3 - - - - - - diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/GWinWrap.png b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/GWinWrap.png deleted file mode 100644 index cdd708d16faef991c910643670ab5cc4abfc605b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9278 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 diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/player.png b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/icons/player.png deleted file mode 100644 index 4f5ebda47ea6229b630a2a3af02fa59e99c678f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6535 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 diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/stylesheet.css b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/stylesheet.css deleted file mode 100644 index 722921b..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/resources/stylesheet.css +++ /dev/null @@ -1,3 +0,0 @@ -window { - -} diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/CrossClassSignals.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/CrossClassSignals.py deleted file mode 100644 index 751f33d..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/CrossClassSignals.py +++ /dev/null @@ -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 = "Note: Double click an image to view the video or image." - self.savedLabel = "Saved settings..." - self.appliedLabel = "Running xwinwrap..." - self.stoppedLabel = "Stopped xwinwrap..." - # 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("" + dirPath.strip(self.usrHome) + "") - 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("" + params[1] + "") - - 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("Nothing saved...") - 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("" + params[1] + "") - - 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("") - - 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) diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/__init__.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/__init__.py deleted file mode 100644 index d2d4cdf..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/signal_classes/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from signal_classes.CrossClassSignals import CrossClassSignals diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveGWinWrapSettings.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveGWinWrapSettings.py deleted file mode 100644 index a26fbb5..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveGWinWrapSettings.py +++ /dev/null @@ -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 diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveStateToXWinWarp.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveStateToXWinWarp.py deleted file mode 100644 index 1e086be..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/SaveStateToXWinWarp.py +++ /dev/null @@ -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; diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/Settings.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/Settings.py deleted file mode 100644 index 1f5479f..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/Settings.py +++ /dev/null @@ -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 diff --git a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/__init__.py b/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/__init__.py deleted file mode 100644 index ca4b01b..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/opt/GWinWrap/utils/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from utils.Settings import Settings -from utils.SaveStateToXWinWarp import SaveStateToXWinWarp -from utils.SaveGWinWrapSettings import SaveGWinWrapSettings diff --git a/src/debs/gwinwrap-0-0-1-x64/usr/share/doc/gwinwrap/copyright b/src/debs/gwinwrap-0-0-1-x64/usr/share/doc/gwinwrap/copyright deleted file mode 100644 index 53b78e8..0000000 --- a/src/debs/gwinwrap-0-0-1-x64/usr/share/doc/gwinwrap/copyright +++ /dev/null @@ -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 - for the terms of the latest version -of the GNU General Public License. diff --git a/src/debs/gwinwrap-0-0-2-x64/DEBIAN/postrm b/src/debs/gwinwrap-0-0-2-x64/DEBIAN/postrm index 5a54f11..60e24bf 100755 --- a/src/debs/gwinwrap-0-0-2-x64/DEBIAN/postrm +++ b/src/debs/gwinwrap-0-0-2-x64/DEBIAN/postrm @@ -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 diff --git a/src/debs/gwinwrap-0-0-2-x64/bin/gwinwrap b/src/debs/gwinwrap-0-0-2-x64/bin/gwinwrap index 2166a10f4ace993cb2f69f203ca8b9d829d7ce91..6b4c244b689ec1e3a1049befa641be251d45d0c0 100755 GIT binary patch literal 519 zcmZXQO-lnY5Qgvh71L}FDl|*4m4YBxyr>7Ehf-`dJKG&tlaS5!!?OR~Bx|i7xlQuS z`%ESq7|o)1}_1FE$vXJuSzJ%q4LHZ xg%E=~4wrT{O%t4LDrjXvj{xRi~t>i*rr1{Z@1PLL%NN`bQ0(3Z5f2tG`d zZAn#hFD5)0Vxo`62OoGa3SrrNgk+hCei3=deQoW)7$1BvoaUb2 z_wRSkcmCYdd+%GvTbt}Qo8V#>M+9nZg}O9ZwGgKsl`7dhVw2ECrKk|aU@3%4mmWk* zV!TgHGnP_Z0U+``cFW+g>r!BR$}$T^&JeMPd=}`WS*Vwgl~4#(8jy#%Iuxk__DF%z zMR~XhnTIO!RN|?`W1OeN7`0}8tOWNI40{XVl0-nC9_}3*eRA`T>|4F zOB0ODdl`64p^(1?2YF9Yf9uUlipIxCs;C(Z_14$b4E9$Kh9ZfP>Jd+Ub$y){k7|46 zxUqeVZ9dTABu_iXxt2hh0li$U)=P^Okda^iiqacmWD>( zUTv?oAG~M6(Fl2c*rr|naE$naeMuc9DngskyPNb>d5@HEZE?Q1+|RM|9zdVd(IZ1} z`(wLY)Eqmn1Nw~dUrUYmidM>0VVs{a?df@A{8H&0(?ojzb#SG3-hjHiN(Tw`Ao_1E zrlIWo9(C;M<~*piD=o=|ZXom?`vPooP{+tT$78qr!z(}Ty z+2x~#?Xt13YHrK4P?l{$Fn{cDE#x8++dGWp((+jt!R4YVu-LlhC_l_9nyZO{YQr6y+6=Wq;hhx6}J-OY%E!hqt|TV&})DDkM8mjrfW;`Jg3vuXWdw zT!YyM1HLbR*8aeA(wh9EHF@t?^0qg<^+#iT&SpISQ{on`(djPlYu+wzx7Rm! zF`M5VSUTArt)dO~QcZNotZD8HMLJ{tp&BtXY6hc`eX0ft3tMHuK|D+383)}@g4_mp z3UCY%SLOiB$_!u+;36Qdvx_zt-p5#MZ=Mvk5r?gEb4lq%TZserGoIb42kG=441ltB zthM(s_AbQo-rNDY8?G_1AqvIOq&QzJFMFeOOdPE^xO?A@XVHv2%oV5ZIW%|`#|3-i zmf~(m1XS2!VgxVn2LMHb;`q?spg2D$IIgG@g$;`9{USqgUnn*d&v?m8iXKxuUd8QI zTn&l}aS-32l*;>a2Iy1J4(Eu?ZIq1}*qDKh8Q7SCjT!hq%zzu7&txIwXGq4)Jjg;T zZVTyGDgH^)`Ms)=bbc?YAl*stQTYFjh5f&;rlY7&+I57?yPmti()k@{+HUEOKn#}S z76^R)$Ktd=Y$IgIJVVp-F#ng!XAB79XOt2mY$u$j{@Ff7I_J%NczBnE`-jH`Ii4|! zhes!=+bAwY`Y`#){GS28$L4ofPwU%6nD1|HY^C( z{?SN$G;E<6vpmCrSUePs{6+DBFBTZ|BY~u$K@+bx zmVAC4IPbyU=Kd$`x(uHr1Lx1*a`--yK~Nom3+I6O({>#+A*RVNA~oy11;@^OC)t|- z@m^;>pC4{I0QkJ1@Q3E_1UT?sWj^1Z!^G!vhx6w+#?!#Zd!Kc_|Hp{0Qpb3n<>pUj z@j3`Nr_7%!(4}jN_v;lU@l)JzDj(~pJ@&f7|-SL`Fms=@!!G5a|-j=^ezaw{qz6RRhlq9r#YUQWmQ}x zKF|MRkuH6U#D6*yX$krKNibvo%ooMF6-X0$$kH-(KL0cD%^DN3_H7iZ2AHO z{A5YXo%6lZis1F;c-9%e0!MicpZ~9&^c|Gr*5iK*4osE%=l>c0jyg~4$HU?FcpVpj ziy_SC?_eoR3JS+rT6X;0&NXo4@&*0hGttFFLgq34oX2+&-$fm-*FQJA1Om3j`Qzs) sEFL0qKhg*lO$V#u7TMexizP6BSDu~uxyXIzhWe@hJGn-XnaAco0XfC{djJ3c diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__builtins__.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__builtins__.py deleted file mode 100644 index 287a5fb..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__builtins__.py +++ /dev/null @@ -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 diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__init__.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__init__.py deleted file mode 100644 index 56356ba..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__init__.py +++ /dev/null @@ -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) diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__main__.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__main__.py deleted file mode 100644 index dc06b1a..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/__main__.py +++ /dev/null @@ -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() diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller.py deleted file mode 100644 index adcb743..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller.py +++ /dev/null @@ -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("Nothing saved...") - 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() diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller_Data.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller_Data.py deleted file mode 100644 index e651a46..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/Controller_Data.py +++ /dev/null @@ -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 = "Note: Double click an image to view the video or image." - self.savedLabel = f"Saved settings..." - self.appliedLabel = f"Running xwinwrap..." - self.stoppedLabel = f"Stopped xwinwrap..." - - # 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) diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/IPCServerMixin.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/IPCServerMixin.py deleted file mode 100644 index be92ace..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/IPCServerMixin.py +++ /dev/null @@ -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)) diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveGWinWrapSettings.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveGWinWrapSettings.py deleted file mode 100644 index 38025a1..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveGWinWrapSettings.py +++ /dev/null @@ -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 diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/__init__.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/__init__.py deleted file mode 100644 index 97a8b3b..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/__init__.py +++ /dev/null @@ -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 diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/DrawAreaMixin.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/DrawAreaMixin.py deleted file mode 100644 index 833d3ae..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/DrawAreaMixin.py +++ /dev/null @@ -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"{file}") - - def run_demo_in_draw_area(self, command): - self.help_label.set_markup("") - - 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() diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/GridMixin.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/GridMixin.py deleted file mode 100644 index 513d7b1..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/GridMixin.py +++ /dev/null @@ -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"{path.strip(self.settings.get_home_path())}") - 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 diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/ImageViewerMixin.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/ImageViewerMixin.py deleted file mode 100644 index e4dd1b6..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/ImageViewerMixin.py +++ /dev/null @@ -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"{file}") diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Logger.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Logger.py deleted file mode 100644 index 06eed47..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Logger.py +++ /dev/null @@ -1,56 +0,0 @@ -# Python imports -import os, logging - -# Application imports - - -class Logger: - def __init__(self, config_path): - self._CONFIG_PATH = config_path - - 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 = self._CONFIG_PATH - file = f"{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 diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Settings.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Settings.py deleted file mode 100644 index 0bf6325..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/Settings.py +++ /dev/null @@ -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(self._CONFIG_PATH).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 diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/__init__.py b/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/__init__.py deleted file mode 100644 index 15fcd01..0000000 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/utils/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .Logger import Logger -from .Settings import Settings diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/gwinwrap.zip b/src/debs/gwinwrap-0-0-2-x64/opt/gwinwrap.zip new file mode 100644 index 0000000000000000000000000000000000000000..40161a22f8e78eab2ef05a4b02c2acadb1a84341 GIT binary patch literal 19353 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 literal 0 HcmV?d00001 diff --git a/src/debs/gwinwrap-0-0-2-x64/usr/share/applications/gwinwrap.desktop b/src/debs/gwinwrap-0-0-2-x64/usr/share/applications/gwinwrap.desktop new file mode 100755 index 0000000..4451f4a --- /dev/null +++ b/src/debs/gwinwrap-0-0-2-x64/usr/share/applications/gwinwrap.desktop @@ -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; diff --git a/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/Main_Window.glade b/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/Main_Window.glade index c6df58f..f26f25a 100644 --- a/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/Main_Window.glade +++ b/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/Main_Window.glade @@ -1,5 +1,5 @@ - + @@ -31,6 +31,11 @@ gtk-cancel 3 + + True + False + gtk-close + True False @@ -68,90 +73,45 @@ gtk-media-stop 3 - - 950 - 600 + + True False - GWinWrap - center - 950 - 600 - usr/share/gwinwrap/icons/gwinwrap.png - center - + True False + 15 + 15 + 15 + vertical True False - 15 - 15 - 15 - vertical + 5 - + True False - 5 - - - True - False - 15 - Note: Double click an image to view the video or image. - - - True - True - 0 - - - - - True - False - Chose Dream Scene / Image Directory - select-folder - False - Folders - Dream Scene / Image Dir - - - - False - True - 1 - - - - - True - True - True - settingsImage - True - - - - False - True - 2 - - + 15 + Note: Double click an image to view the video or image. - False + True True 0 - + True False - True + Chose Dream Scene / Image Directory + select-folder + False + Folders + Dream Scene / Image Dir + False @@ -159,64 +119,191 @@ 1 + + + True + True + True + settingsImage + True + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + True + + + False + True + 1 + + + + + True + True + in + + + True + False + + + + True + False + vertical + 10 + 10 + True + True + + + 640 + 525 + True + False + Choose Image/Video Directory... + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 2 + + + + + Clear + True + True + True + clearImage + True + + + + False + True + 3 + + + + + True + True + 0 + + + + + 300 + True + False + 10 + 15 + 15 + 15 + False + vertical + + + True + False + vertical + + + Use XScreenSaver + True + True + False + center + 5 + True + + + + False + True + 0 + + True True in - + True - False + False + True + XScreensaverStore + False + + + + + - - - True - False - vertical - 10 - 10 - True - True + + XScreensaves - - 640 - 525 - True - False - Choose Image/Video Directory... - - - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - + + + 0 + @@ -226,23 +313,7 @@ True True - 2 - - - - - Clear - True - True - True - clearImage - True - - - - False - True - 3 + 1 @@ -254,14 +325,9 @@ - 300 True False - 10 - 15 - 15 - 15 - False + False vertical @@ -269,15 +335,37 @@ False vertical - - Use XScreenSaver + True - True - False - center - 5 - True - + False + + + True + False + 10 + 10 + Playback Resolutions + + + True + True + 0 + + + + + True + False + 10 + 10 + Position Offset + + + True + True + 1 + + False @@ -286,35 +374,85 @@ - + True - True - in + False - + True - False - True - XScreensaverStore - False - - - - - - - - XScreensaves - - - - 0 - - - - + False + 3 + + 7680x4320 + 3840x2160 + 2048x1080 + 1920x1080 + 1440x720 + 1600x900 + 1280x720 + 800x600 + + + True + True + 0 + + + + True + False + + + True + True + 1 + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + vertical + + + True + False + 10 + 5 + Save Path + + + True + True + 0 + + + + + True + False + 0 + + .animatedBGstarter.sh + .animatedBGstarter2.sh + .animatedBGstarter3.sh + True @@ -324,267 +462,121 @@ - True + False True - 0 + 1 - + + True False - False - vertical - + + Save True - False - vertical - - - True - False - - - True - False - 10 - 10 - Playback Resolutions - - - True - True - 0 - - - - - True - False - 10 - 10 - Position Offset - - - True - True - 1 - - - - - False - True - 0 - - - - - True - False - - - True - False - 3 - - 7680x4320 - 3840x2160 - 2048x1080 - 1920x1080 - 1440x720 - 1600x900 - 1280x720 - 800x600 - - - - True - True - 0 - - - - - True - False - - - True - True - 1 - - - - - False - True - 1 - - + True + True + True + True + saveImage + True + - False - True - 0 + 1 + 0 - + + (Re)Start True - False - vertical - - - True - False - 10 - 5 - Save Path - - - True - True - 0 - - - - - True - False - 0 - - .animatedBGstarter.sh - .animatedBGstarter2.sh - .animatedBGstarter3.sh - - - - True - True - 1 - - + True + True + True + True + startImage + True + - False - True - 1 + 0 + 0 - - + + Stop True - False - - - Save - True - True - True - True - True - saveImage - True - - - - 1 - 0 - - - - - (Re)Start - True - True - True - True - True - startImage - True - - - - 0 - 0 - - - - - Stop - True - True - True - True - True - stopImage - True - - - - 0 - 1 - - - - - Close - True - True - True - True - True - closeImage - True - - - - 1 - 1 - - - - - - - - - - - - - - - - - + True + True + True + True + stopImage + True + - False - True - 2 + 0 + 1 + + + Close + True + True + True + True + True + closeImage + True + + + + 1 + 1 + + + + + + + + + + + + + + + + + False - False - end - 1 + True + 2 False - True - 1 + False + end 1 + + False + True + 1 + 1 + @@ -691,6 +683,7 @@ True True True + closePopupImage2 True @@ -770,6 +763,7 @@ True Set Custom Default Path Set Custom Start Path + True @@ -808,6 +802,7 @@ True Set Custom Video Player Set Custom Video Player + True @@ -846,6 +841,7 @@ True Set Custom Image Viewer Set Custom Image Viewer + False diff --git a/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/settings.json b/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/settings.json index 596ddd2..b373664 100644 --- a/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/settings.json +++ b/src/debs/gwinwrap-0-0-2-x64/usr/share/gwinwrap/settings.json @@ -1,9 +1,36 @@ { - "settings":[ - { - "start_path":"/home/abaddon/LazyShare/Movies-TV-Music/Dream Scenes/Games/Halo", - "default_player":"mpv", - "default_img_viewer":"mirage" - } - ] -} \ No newline at end of file + "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" + } +} diff --git a/src/versions/0.0.1/GWinWrap/GWinWrap.desktop b/src/versions/0.0.1/GWinWrap/GWinWrap.desktop deleted file mode 100644 index 543fdb6..0000000 --- a/src/versions/0.0.1/GWinWrap/GWinWrap.desktop +++ /dev/null @@ -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; diff --git a/src/versions/0.0.1/GWinWrap/__init__.py b/src/versions/0.0.1/GWinWrap/__init__.py deleted file mode 100644 index 0beb3ee..0000000 --- a/src/versions/0.0.1/GWinWrap/__init__.py +++ /dev/null @@ -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() diff --git a/src/versions/0.0.1/GWinWrap/__main__.py b/src/versions/0.0.1/GWinWrap/__main__.py deleted file mode 100644 index 60c7ea2..0000000 --- a/src/versions/0.0.1/GWinWrap/__main__.py +++ /dev/null @@ -1,9 +0,0 @@ -from __init__ import Main, gtk - - -if __name__ == "__main__": - try: - main = Main() - gtk.main() - except Exception as e: - print(e) diff --git a/src/versions/0.0.1/GWinWrap/resources/Main_Window.glade b/src/versions/0.0.1/GWinWrap/resources/Main_Window.glade deleted file mode 100644 index 495ebfe..0000000 --- a/src/versions/0.0.1/GWinWrap/resources/Main_Window.glade +++ /dev/null @@ -1,844 +0,0 @@ - - - - - - - inode/directory - - - - - - - - - - True - False - gtk-clear - 3 - - - True - False - gtk-quit - 3 - - - True - False - gtk-cancel - 3 - - - True - False - gtk-jump-to - 3 - - - True - False - gtk-save - 3 - - - True - False - gtk-save - 3 - - - True - False - Settings.... - gtk-properties - 3 - - - True - False - gtk-media-play - 3 - - - True - False - gtk-media-stop - 3 - - - 950 - 600 - False - GWinWrap - center - 950 - 600 - icons/GWinWrap.png - center - - - - - - True - False - - - True - False - 15 - 15 - 15 - vertical - - - True - False - 5 - - - True - False - 15 - Note: Double click an image to view the video or image. - - - True - True - 0 - - - - - True - False - Chose Dream Scene / Image Directory - select-folder - False - Folders - Dream Scene / Image Dir - - - - False - True - 1 - - - - - True - True - True - settingsImage - True - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - True - - - False - True - 1 - - - - - True - True - in - - - True - False - - - True - False - vertical - 10 - 10 - True - True - - - 640 - 525 - True - False - Choose Image/Video Directory... - - - - - - 0 - 0 - - - - - - - - - True - True - 2 - - - - - Clear - True - True - True - clearImage - True - - - - False - True - 3 - - - - - True - True - 0 - - - - - 300 - True - False - 10 - 15 - 15 - 15 - False - vertical - - - True - False - vertical - - - Use XScreenSaver - True - True - False - center - 5 - True - - - - False - True - 0 - - - - - True - True - in - - - True - False - True - XScreensaver List - False - - - - - - - - XScreensaves - - - - 0 - - - - - - - - - True - True - 1 - - - - - True - True - 0 - - - - - True - False - False - vertical - - - True - False - vertical - - - True - False - - - True - False - 10 - 10 - Playback Resolutions - - - True - True - 0 - - - - - True - False - 10 - 10 - Position Offset - - - True - True - 1 - - - - - False - True - 0 - - - - - True - False - - - True - False - 3 - - 7680x4320 - 3840x2160 - 2048x1080 - 1920x1080 - 1440x720 - 1600x900 - 1280x720 - 800x600 - - - - True - True - 0 - - - - - True - False - - - True - True - 1 - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - vertical - - - True - False - 10 - 5 - Save Path - - - True - True - 0 - - - - - True - False - 0 - - .animatedBGstarter.sh - .animatedBGstarter2.sh - .animatedBGstarter3.sh - - - - True - True - 1 - - - - - False - True - 1 - - - - - True - False - - - Save - True - True - True - True - True - saveImage - True - - - - 1 - 0 - - - - - (Re)Start - True - True - True - True - True - startImage - True - - - - 0 - 0 - - - - - Stop - True - True - True - True - True - stopImage - True - - - - 0 - 1 - - - - - Close - True - True - True - True - True - closeImage - True - - - - 1 - 1 - - - - - False - True - 2 - - - - - False - False - end - 1 - - - - - False - True - 1 - 1 - - - - - - - 640 - 525 - False - 350 - True - True - helpLabel - bottom - False - - - True - False - vertical - - - True - False - - - True - True - True - Close Demo Window - closePopupImage - True - - - - False - True - end - 0 - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - - - - - True - True - 1 - - - - - - - 640 - 525 - False - True - True - helpLabel - bottom - - - True - False - vertical - - - True - False - bottom - - - Main Image Viewer - True - True - True - openProgImage - True - - - - False - True - 0 - - - - - True - True - True - True - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - True - in - False - - - True - False - - - True - False - gtk-missing-image - 6 - - - - - - - True - True - 1 - - - - - - - 250 - False - button1 - - - True - False - vertical - - - True - False - - - True - False - icons/folder.png - - - False - True - 0 - - - - - 330 - 26 - True - True - Set Custom Default Path - Set Custom Default Path - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - - - True - False - icons/player.png - - - False - True - 0 - - - - - 330 - 26 - True - True - Set Custom Video Player - Set Custom Video Player - - - False - True - 1 - - - - - False - True - 1 - - - - - True - False - - - True - False - icons/picture.png - - - False - True - 0 - - - - - 330 - 26 - True - True - Set Custom Image Viewer - Set Custom Image Viewer - - - False - True - 1 - - - - - False - True - 2 - - - - - Save - True - True - True - saveImag - True - - - - False - True - 3 - - - - - - diff --git a/src/versions/0.0.1/GWinWrap/resources/icons/GWinWrap.png b/src/versions/0.0.1/GWinWrap/resources/icons/GWinWrap.png deleted file mode 100644 index cdd708d16faef991c910643670ab5cc4abfc605b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9278 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 diff --git a/src/versions/0.0.1/GWinWrap/resources/icons/player.png b/src/versions/0.0.1/GWinWrap/resources/icons/player.png deleted file mode 100644 index 4f5ebda47ea6229b630a2a3af02fa59e99c678f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6535 zcmV;28F=Q2P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000iMNklQ=&+Uq9sd-ELHL&uKY;i!bsA(aqJ>!&;)G) z1OLoC`lo1MAVD9gvr(V+p<04xJo0&p6@JOIyrH;}1WDbrTD zE)5X8NB=JYq`Z24Ku9?%r5pw@XpG4MND+|)Ac%;YzIUw#1DFNymNiJ#8o~ph5|rkv zHGosd=QEjXPhYiC9h$p1GeIOarqk)sbSB;Jx+x=sFj{M;-9$nNO++k&2!%7o2moMa zV&-7Q*>N1@x~?ar)I@@telLzf`SO%C74!3=9m;XL@=rTTk&K9-FAB z(~bL|Ix*Gr&dC$E*6X!B7iVVfFBTT>tW+vnl;`z6@Ue$ZkBp8<$8m&GO8eiUb`K=0 zfnY#@Sz0%5_7LBli8RH-4MarDEZ7*Kv?8zWiKV3yUOMo@jeY$CQ_SXcUtj-E`UeIM z-FN?o-rBKi_o6k1NeYEd9w08xOsA*berwaI6O*5szHs3&qxA#{p^Vm<;HKaH-AC|$ zVeEb8pTJ-!PeDovV~lZK_t3WYZvXo2ckX#{WOOut^S1YR%|>YF0rKVl{NegHj=cV1 z<#~^m%jG>lo| zfs=+|BaPO*#X{ke7tWu1;@|)6JMVASx!C}8{MZ}L-lw1XIEWs1U3VQJ{zNHcvLHlj zvclaOlffVhDMSS2dH3Yz=N^4w|93}h21_)6-23!X!{u`MbJ=WmunECq*+grdm@01c z2$gPx@xTv0dU1AUsI37`otXMy%5^``P&iCi9aW9u!CDVv!%_+f?(7xL z$*IXd*#GRlZHXZG+QA>Yl}hDT$twT8J$ECU?EwH}GCf#aT*R@XhhvjYUpSA=TW$t} zz$@Ux^-eafa&w+Ec!P(;FY2?7a%bR>ob*I63t|2sML_LGSoaQ@x1+oR8MT{i|guIsh{-^r;d6beOr=$C&5 zj^hH%5K_P}!)OgQ3=#w(B!nP;l?>ZRYCtU8A4Cm+HOvj{iO69LLwR*ns#P32au_qy z7h+<$t{V$U$8|zrWN>tjZ_^Cs6s4aFG1u{Ymno0YWDaqoy;Tv{sq zRyv(ob;{uc?4@gz7#ZA^3^Ag_oLGb~Gqh6h>h)v;)T&hgfaiIMl!80udq%{~B7#%f zMZ4k}ILf=Y$pg@VC@IfFrBXq)T4`f|S`A>1Stx2_YK!awAi#B;>z?+g0Y6}HgOGK> z5WRXG)k+1GN*e=crBDNq&o5wjWCQ~PgJ>p1LD3V<1X2iOdwY@T$#g5r6)(RK0wf4p zY1Ha9lrLYlV8{T8#D{CGQ7)H}o6n(AE<-C-Y+DVoG04r&p})T$4?Oq~1_m3se=(oO zn@0{eA+*FDckV&9uNNCOjKc9tQ4kRvn>HQCfsoSA8pebMY-9k2Qa(5dn>_+Ogb+5o z7*a|AjC$Pz8-q%C^b$f9%KX%msML>)a4w zW|RsAoI86Ko>xb$T17gOfe-@ghlg9Nd+!H-3AgOn*>#oXE0L7y-0n+Wdv9-FABKlF zU~J-*X1m-W!VlltaLfM_xg3dR6vABq0VG*@z6=NI6A=7Dp zHJbF?`3t+60<<0K(bb_}Q>nu+VB>oc5yc*x$@D-eFI*HM1>95$%q9TOp^gm^W`^=S zTsU_Q6E|%}u~0y^H;bjx5|&COxULI9IF%M>DB2tkKcjunq-e>+1LI|W%X*jNfo}Mg**00CV&^lzZ zyIP?RjuhDdgtop|nD&P{eBoU%{nP0kvAqUrcQv1togtih0Wz zgIcYMS`Da_%eZ{$67snm`UeI=R}0;f{FF%7u{pwEfC6JFlyB*vc0{?=W^XL zQFm1ykc1D>6>jDUYZC&1)_(4nj*Q7rtyYl9^t3H2qV2F&15hXa#fcy%1l<4w5ZDNi zBVe@hWeEBawky;o3OgHsR%GCSw%r$L6~8eaKwv4s%zj1^B9uLoPJy{q7rzweloZrG z2tM+AkH;9*%*-^Ne)1n;4bgVQ=DIgM36^oDLK(F2+2W@^`&qnq`*yoP5_5AG@z39U z2FuIKtIGnLCMLjaLYA~?Vgg3%m~{n-8;}M87zPOeX48Bl#O2^ypQ z-i1;~rBZnKBloXro>OxrT16IUKcZQH)?j-qFaX$qi6Dq#Szxu}s#`c~o(6-1Dnfv5 z7P=Z4uG#>>X6afpL4r?sjL=slLqb2G!_96Q^;$K?{%#Bt1pEUg2sd1=H2R$6-Z>|x z4CU2Y6uwclfZx4V5G1Zo2#}EY{V#kO6I(WizneaP9)I`MC%SBaT;FPth~PL9TB(=} zuIu8l&wmMy>)O_sL}mFh{^C#nsCxrQLC{L!CaZk#fUVoM-FOfT%3;GGDZxg^Wbix> zH*MbRr(|XrtrPCB31W?S00A%r5Hnmi1rj1A zSG`_GI+F>@cf;JaKhQP=v^H4CRMy! ze|{Rf_U@T8*uG;&_<1ft?v7Mg+wJSGedVu`TLY1C^z}oy>)v};*Z2%mSpt?su5rM@ zo3JK0ctzx=;pe`yuh9=6fv3Om^%dprSPVH~TA|jiK+{S+`L|!iCqDI?*mc_-7+yb& zY+tXx;Q>Ht4W&G&x(5;huIq$PVtbB22-z|x5!v3KRW|4bvcD1IIxgzX5Q~dK0S!c8w2RQ4kxuWfkoHB%K#*=i)(IJql#~{e1v{QfaB>+UVFQ zz<}q~VGOWTDqPX|q{-PLb;Sgu4-b@RR)*Q%q`cyTQq0i7oXjW|icP%4gf2QeGZVTa zN9AJEa*(23Tdyk+%w#gCRBQf*W4KZjc7visNeY5Cj4LLEQE%y%R}gHohHPVmR;WmM zby=WVt>Vjn{Abv_WeXg~fz}%5-hDS27~3=(u765wERHq?t~K5l{_sz*b=x*bDWSE- z*)wPGH&6Wa>WiVxTekS8EbS4Mo40Q5syd9O!)OQvA;Q7?DpOy(`vXOTar4%#v2aZy zaP186Z2+GMJ}l<*7~ZfUMCRtxq2VNs6ABS+l6HzorBrx5l}e*tuf?uKzaLy@OV)@0 z>AJX7DupRAdV(#OJD4Xp`4SmlYG;6Rv6k4vd<@v?v6CYKDsRN@TW`ajd*2^Eu-!_f z(rK_UO-FE6=K+r6z;zvzm&?d6%;SwChjHd-Ka0us&dHOwW#`U_9t+I{UbS5s{0#vA zx*DM#c<>=S`uGERJox;r$0=XsEh+agEfY!N?CL}x>cYI^1(fInZ20Y*l~;CUX5 z?ZFEn!k3h?BF9|3obQlNLcVy4NS+|B+Q92IK*} zvKj;Q4Ggq!^tCLFg^-9Iw@h_D=XeOfi%|nKdw>FP48Y%a-=thSg~M`~D8vXML@Wa& zEkGppj{`U~Ia}0;9xypu0ANorGB><0DVhL=TMDbXbe!lG_yGWucJ=>za<*9SSPmzRUE@OnzzBd3 z1Grx)^*(0q**Lx_yKDEYsRusx(7Jm*aNmGZnrqbxJFW|(HH4IK9fvYKJwi%JN$E}- z!^T#TYz6VpB-L0e#kR`iq||8Ga5|l)^767i{m!ZCs|R1X{QUm!=IixZt*0kD4d6!r t_5(QIyy~km!2kCl@N+(X?hWw20{|>%TF~k*h3NnQ002ovPDHLkV1kwwJ(d6f diff --git a/src/versions/0.0.1/GWinWrap/resources/stylesheet.css b/src/versions/0.0.1/GWinWrap/resources/stylesheet.css deleted file mode 100644 index 722921b..0000000 --- a/src/versions/0.0.1/GWinWrap/resources/stylesheet.css +++ /dev/null @@ -1,3 +0,0 @@ -window { - -} diff --git a/src/versions/0.0.1/GWinWrap/signal_classes/CrossClassSignals.py b/src/versions/0.0.1/GWinWrap/signal_classes/CrossClassSignals.py deleted file mode 100644 index 6cbbb7e..0000000 --- a/src/versions/0.0.1/GWinWrap/signal_classes/CrossClassSignals.py +++ /dev/null @@ -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 = "Note: Double click an image to view the video or image." - self.savedLabel = "Saved settings..." - self.appliedLabel = "Running xwinwrap..." - self.stoppedLabel = "Stopped xwinwrap..." - # 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("" + dirPath.strip(self.usrHome) + "") - 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("" + params[1] + "") - - 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("Nothing saved...") - 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("" + params[1] + "") - - 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("") - - 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) diff --git a/src/versions/0.0.1/GWinWrap/signal_classes/__init__.py b/src/versions/0.0.1/GWinWrap/signal_classes/__init__.py deleted file mode 100644 index d2d4cdf..0000000 --- a/src/versions/0.0.1/GWinWrap/signal_classes/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from signal_classes.CrossClassSignals import CrossClassSignals diff --git a/src/versions/0.0.1/GWinWrap/utils/SaveGWinWrapSettings.py b/src/versions/0.0.1/GWinWrap/utils/SaveGWinWrapSettings.py deleted file mode 100644 index a26fbb5..0000000 --- a/src/versions/0.0.1/GWinWrap/utils/SaveGWinWrapSettings.py +++ /dev/null @@ -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 diff --git a/src/versions/0.0.1/GWinWrap/utils/SaveStateToXWinWarp.py b/src/versions/0.0.1/GWinWrap/utils/SaveStateToXWinWarp.py deleted file mode 100644 index 1e086be..0000000 --- a/src/versions/0.0.1/GWinWrap/utils/SaveStateToXWinWarp.py +++ /dev/null @@ -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; diff --git a/src/versions/0.0.1/GWinWrap/utils/Settings.py b/src/versions/0.0.1/GWinWrap/utils/Settings.py deleted file mode 100644 index 8ffc52a..0000000 --- a/src/versions/0.0.1/GWinWrap/utils/Settings.py +++ /dev/null @@ -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 diff --git a/src/versions/0.0.1/GWinWrap/utils/__init__.py b/src/versions/0.0.1/GWinWrap/utils/__init__.py deleted file mode 100644 index ca4b01b..0000000 --- a/src/versions/0.0.1/GWinWrap/utils/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from utils.Settings import Settings -from utils.SaveStateToXWinWarp import SaveStateToXWinWarp -from utils.SaveGWinWrapSettings import SaveGWinWrapSettings diff --git a/src/versions/0.0.1/XWinWrap/Makefile b/src/versions/0.0.1/XWinWrap/Makefile deleted file mode 100644 index 4a67078..0000000 --- a/src/versions/0.0.1/XWinWrap/Makefile +++ /dev/null @@ -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/ diff --git a/src/versions/0.0.1/XWinWrap/xwinwrap.c b/src/versions/0.0.1/XWinWrap/xwinwrap.c deleted file mode 100644 index a2daa04..0000000 --- a/src/versions/0.0.1/XWinWrap/xwinwrap.c +++ /dev/null @@ -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 - */ - -/* - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/src/versions/0.0.1/compileBin.sh b/src/versions/0.0.1/compileBin.sh deleted file mode 100755 index fdd8222..0000000 --- a/src/versions/0.0.1/compileBin.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -function main() { - gcc -no-pie -s gwinwrap_exec_bin.cpp -o gwinwrap -} -main; diff --git a/src/versions/0.0.1/gwinwrap_exec_bin.cpp b/src/versions/0.0.1/gwinwrap_exec_bin.cpp deleted file mode 100644 index 81978ec..0000000 --- a/src/versions/0.0.1/gwinwrap_exec_bin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include -using namespace std; - -int main() { - chdir("/opt/GWinWrap/"); - system("python3 ."); -return 0; -} diff --git a/src/versions/0.0.2/GWinWrap/__builtins__.py b/src/versions/0.0.2/GWinWrap/__builtins__.py index 287a5fb..e0cffce 100644 --- a/src/versions/0.0.2/GWinWrap/__builtins__.py +++ b/src/versions/0.0.2/GWinWrap/__builtins__.py @@ -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 diff --git a/src/versions/0.0.2/GWinWrap/__init__.py b/src/versions/0.0.2/GWinWrap/__init__.py index 56356ba..90dc8da 100644 --- a/src/versions/0.0.2/GWinWrap/__init__.py +++ b/src/versions/0.0.2/GWinWrap/__init__.py @@ -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. +""" diff --git a/src/versions/0.0.2/GWinWrap/__main__.py b/src/versions/0.0.2/GWinWrap/__main__.py index dc06b1a..abdc793 100644 --- a/src/versions/0.0.2/GWinWrap/__main__.py +++ b/src/versions/0.0.2/GWinWrap/__main__.py @@ -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() diff --git a/src/versions/0.0.2/GWinWrap/app.py b/src/versions/0.0.2/GWinWrap/app.py new file mode 100644 index 0000000..6880502 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/app.py @@ -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) diff --git a/src/versions/0.0.2/GWinWrap/core/__init__.py b/src/versions/0.0.2/GWinWrap/core/__init__.py new file mode 100644 index 0000000..90cfadc --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/core/__init__.py @@ -0,0 +1,3 @@ +""" + Gtk Bound Signal Module +""" diff --git a/src/versions/0.0.2/GWinWrap/core/controller.py b/src/versions/0.0.2/GWinWrap/core/controller.py new file mode 100644 index 0000000..d80b76a --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/core/controller.py @@ -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) diff --git a/src/versions/0.0.2/GWinWrap/core/controller_data.py b/src/versions/0.0.2/GWinWrap/core/controller_data.py new file mode 100644 index 0000000..c4f62b9 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/core/controller_data.py @@ -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 = "Note: Double click an image to view the video or image." + self.savedLabel = f"Saved settings..." + self.appliedLabel = f"Running xwinwrap..." + self.stoppedLabel = f"Stopped xwinwrap..." + + # 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("Nothing saved...") + return + + self.help_label.set_markup(self.savedLabel) diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/DrawAreaMixin.py b/src/versions/0.0.2/GWinWrap/core/mixins/DrawAreaMixin.py similarity index 93% rename from src/versions/0.0.2/GWinWrap/signal_classes/mixins/DrawAreaMixin.py rename to src/versions/0.0.2/GWinWrap/core/mixins/DrawAreaMixin.py index 833d3ae..4c3f290 100644 --- a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/DrawAreaMixin.py +++ b/src/versions/0.0.2/GWinWrap/core/mixins/DrawAreaMixin.py @@ -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() diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/GridMixin.py b/src/versions/0.0.2/GWinWrap/core/mixins/GridMixin.py similarity index 72% rename from src/versions/0.0.2/GWinWrap/signal_classes/mixins/GridMixin.py rename to src/versions/0.0.2/GWinWrap/core/mixins/GridMixin.py index 513d7b1..a172c3f 100644 --- a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/GridMixin.py +++ b/src/versions/0.0.2/GWinWrap/core/mixins/GridMixin.py @@ -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"{path.strip(self.settings.get_home_path())}") + self.help_label.set_markup(f"{path.strip(settings.get_home_path())}") 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() diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ImageViewerMixin.py b/src/versions/0.0.2/GWinWrap/core/mixins/ImageViewerMixin.py similarity index 94% rename from src/versions/0.0.2/GWinWrap/signal_classes/mixins/ImageViewerMixin.py rename to src/versions/0.0.2/GWinWrap/core/mixins/ImageViewerMixin.py index e4dd1b6..8e7aa08 100644 --- a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ImageViewerMixin.py +++ b/src/versions/0.0.2/GWinWrap/core/mixins/ImageViewerMixin.py @@ -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") diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/ThumbnailMixin.py b/src/versions/0.0.2/GWinWrap/core/mixins/ThumbnailMixin.py similarity index 99% rename from src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/ThumbnailMixin.py rename to src/versions/0.0.2/GWinWrap/core/mixins/ThumbnailMixin.py index e067732..2560e2c 100644 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/ThumbnailMixin.py +++ b/src/versions/0.0.2/GWinWrap/core/mixins/ThumbnailMixin.py @@ -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""" diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/__init__.py b/src/versions/0.0.2/GWinWrap/core/mixins/__init__.py similarity index 86% rename from src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/__init__.py rename to src/versions/0.0.2/GWinWrap/core/mixins/__init__.py index f482286..8509626 100644 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/mixins/__init__.py +++ b/src/versions/0.0.2/GWinWrap/core/mixins/__init__.py @@ -1,3 +1,6 @@ +""" + Mixins Module +""" from .ThumbnailMixin import ThumbnailMixin from .DrawAreaMixin import DrawAreaMixin from .ImageViewerMixin import ImageViewerMixin diff --git a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveStateToXWinWarp.py b/src/versions/0.0.2/GWinWrap/core/save_state_to_xwinwarp.py similarity index 73% rename from src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveStateToXWinWarp.py rename to src/versions/0.0.2/GWinWrap/core/save_state_to_xwinwarp.py index 14ff763..e0e9d23 100644 --- a/src/debs/gwinwrap-0-0-2-x64/opt/GWinWrap/signal_classes/SaveStateToXWinWarp.py +++ b/src/versions/0.0.2/GWinWrap/core/save_state_to_xwinwarp.py @@ -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) ) diff --git a/src/versions/0.0.2/GWinWrap/core/window.py b/src/versions/0.0.2/GWinWrap/core/window.py new file mode 100644 index 0000000..b372a74 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/core/window.py @@ -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() diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/Controller.py b/src/versions/0.0.2/GWinWrap/signal_classes/Controller.py deleted file mode 100644 index adcb743..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/Controller.py +++ /dev/null @@ -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("Nothing saved...") - 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() diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py b/src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py deleted file mode 100644 index e651a46..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py +++ /dev/null @@ -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 = "Note: Double click an image to view the video or image." - self.savedLabel = f"Saved settings..." - self.appliedLabel = f"Running xwinwrap..." - self.stoppedLabel = f"Stopped xwinwrap..." - - # 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) diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py b/src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py deleted file mode 100644 index be92ace..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py +++ /dev/null @@ -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)) diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py b/src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py deleted file mode 100644 index 38025a1..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py +++ /dev/null @@ -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 diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py b/src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py deleted file mode 100644 index 14ff763..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py +++ /dev/null @@ -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; diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/__init__.py b/src/versions/0.0.2/GWinWrap/signal_classes/__init__.py deleted file mode 100644 index 97a8b3b..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/__init__.py +++ /dev/null @@ -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 diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py deleted file mode 100644 index e067732..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py +++ /dev/null @@ -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) diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py deleted file mode 100644 index f482286..0000000 --- a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .ThumbnailMixin import ThumbnailMixin -from .DrawAreaMixin import DrawAreaMixin -from .ImageViewerMixin import ImageViewerMixin -from .GridMixin import GridMixin diff --git a/src/versions/0.0.2/GWinWrap/utils/Logger.py b/src/versions/0.0.2/GWinWrap/utils/Logger.py deleted file mode 100644 index 06eed47..0000000 --- a/src/versions/0.0.2/GWinWrap/utils/Logger.py +++ /dev/null @@ -1,56 +0,0 @@ -# Python imports -import os, logging - -# Application imports - - -class Logger: - def __init__(self, config_path): - self._CONFIG_PATH = config_path - - 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 = self._CONFIG_PATH - file = f"{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 diff --git a/src/versions/0.0.2/GWinWrap/utils/Settings.py b/src/versions/0.0.2/GWinWrap/utils/Settings.py deleted file mode 100644 index 0bf6325..0000000 --- a/src/versions/0.0.2/GWinWrap/utils/Settings.py +++ /dev/null @@ -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(self._CONFIG_PATH).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 diff --git a/src/versions/0.0.2/GWinWrap/utils/__init__.py b/src/versions/0.0.2/GWinWrap/utils/__init__.py index 15fcd01..a8e5edd 100644 --- a/src/versions/0.0.2/GWinWrap/utils/__init__.py +++ b/src/versions/0.0.2/GWinWrap/utils/__init__.py @@ -1,2 +1,3 @@ -from .Logger import Logger -from .Settings import Settings +""" + Utils module +""" diff --git a/src/versions/0.0.2/GWinWrap/utils/endpoint_registry.py b/src/versions/0.0.2/GWinWrap/utils/endpoint_registry.py new file mode 100644 index 0000000..15ffa9e --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/endpoint_registry.py @@ -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 diff --git a/src/versions/0.0.2/GWinWrap/utils/event_system.py b/src/versions/0.0.2/GWinWrap/utils/event_system.py new file mode 100644 index 0000000..b2d4a71 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/event_system.py @@ -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() diff --git a/src/versions/0.0.2/GWinWrap/utils/ipc_server.py b/src/versions/0.0.2/GWinWrap/utils/ipc_server.py new file mode 100644 index 0000000..8226247 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/ipc_server.py @@ -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)) diff --git a/src/versions/0.0.2/GWinWrap/utils/keybindings.py b/src/versions/0.0.2/GWinWrap/utils/keybindings.py new file mode 100644 index 0000000..790c963 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/keybindings.py @@ -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) diff --git a/src/versions/0.0.2/GWinWrap/utils/logger.py b/src/versions/0.0.2/GWinWrap/utils/logger.py new file mode 100644 index 0000000..6ca2add --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/logger.py @@ -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 diff --git a/src/versions/0.0.2/GWinWrap/utils/settings.py b/src/versions/0.0.2/GWinWrap/utils/settings.py new file mode 100644 index 0000000..f0517a4 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/settings.py @@ -0,0 +1,173 @@ +# 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_PATH_CONFIG = f"{self._USR_PATH}/settings.json" + 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._PID_FILE = f"{self._CONFIG_PATH}/{app_name.lower()}.pid" + self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png" + self._CONFIG_FILE = f"{self._CONFIG_PATH}/settings.json" + + if not os.path.exists(self._CONFIG_PATH): + os.mkdir(self._CONFIG_PATH) + + if not os.path.exists(self._CONFIG_FILE): + import shutil + try: + shutil.copyfile(self._USR_PATH_CONFIG, 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" + + + self._logger = Logger(self._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) diff --git a/src/versions/0.0.2/compileBin.sh b/src/versions/0.0.2/compileBin.sh deleted file mode 100755 index fdd8222..0000000 --- a/src/versions/0.0.2/compileBin.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -function main() { - gcc -no-pie -s gwinwrap_exec_bin.cpp -o gwinwrap -} -main; diff --git a/src/versions/0.0.2/gwinwrap_exec_bin.cpp b/src/versions/0.0.2/gwinwrap_exec_bin.cpp deleted file mode 100644 index 81978ec..0000000 --- a/src/versions/0.0.2/gwinwrap_exec_bin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include -using namespace std; - -int main() { - chdir("/opt/GWinWrap/"); - system("python3 ."); -return 0; -} diff --git a/user_config/bin/gwinwrap b/user_config/bin/gwinwrap new file mode 100755 index 0000000..6b4c244 --- /dev/null +++ b/user_config/bin/gwinwrap @@ -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 "$@"; diff --git a/user_config/usr/applications/gwinwrap.desktop b/user_config/usr/applications/gwinwrap.desktop new file mode 100755 index 0000000..4451f4a --- /dev/null +++ b/user_config/usr/applications/gwinwrap.desktop @@ -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; diff --git a/user_config/usr/share/gwinwrap/Main_Window.glade b/user_config/usr/share/gwinwrap/Main_Window.glade index 41e0e23..f26f25a 100644 --- a/user_config/usr/share/gwinwrap/Main_Window.glade +++ b/user_config/usr/share/gwinwrap/Main_Window.glade @@ -1,5 +1,5 @@ - + @@ -31,6 +31,11 @@ gtk-cancel 3 + + True + False + gtk-close + True False @@ -68,90 +73,45 @@ gtk-media-stop 3 - - 950 - 600 + + True False - GWinWrap - center - 950 - 600 - icons/GWinWrap.png - center - + True False + 15 + 15 + 15 + vertical True False - 15 - 15 - 15 - vertical + 5 - + True False - 5 - - - True - False - 15 - Note: Double click an image to view the video or image. - - - True - True - 0 - - - - - True - False - Chose Dream Scene / Image Directory - select-folder - False - Folders - Dream Scene / Image Dir - - - - False - True - 1 - - - - - True - True - True - settingsImage - True - - - - False - True - 2 - - + 15 + Note: Double click an image to view the video or image. - False + True True 0 - + True False - True + Chose Dream Scene / Image Directory + select-folder + False + Folders + Dream Scene / Image Dir + False @@ -159,64 +119,191 @@ 1 + + + True + True + True + settingsImage + True + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + True + + + False + True + 1 + + + + + True + True + in + + + True + False + + + + True + False + vertical + 10 + 10 + True + True + + + 640 + 525 + True + False + Choose Image/Video Directory... + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 2 + + + + + Clear + True + True + True + clearImage + True + + + + False + True + 3 + + + + + True + True + 0 + + + + + 300 + True + False + 10 + 15 + 15 + 15 + False + vertical + + + True + False + vertical + + + Use XScreenSaver + True + True + False + center + 5 + True + + + + False + True + 0 + + True True in - + True - False + False + True + XScreensaverStore + False + + + + + - - - True - False - vertical - 10 - 10 - True - True + + XScreensaves - - 640 - 525 - True - False - Choose Image/Video Directory... - - - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - + + + 0 + @@ -226,23 +313,7 @@ True True - 2 - - - - - Clear - True - True - True - clearImage - True - - - - False - True - 3 + 1 @@ -254,14 +325,9 @@ - 300 True False - 10 - 15 - 15 - 15 - False + False vertical @@ -269,15 +335,37 @@ False vertical - - Use XScreenSaver + True - True - False - center - 5 - True - + False + + + True + False + 10 + 10 + Playback Resolutions + + + True + True + 0 + + + + + True + False + 10 + 10 + Position Offset + + + True + True + 1 + + False @@ -286,35 +374,85 @@ - + True - True - in + False - + True - False - True - XScreensaverStore - False - - - - - - - - XScreensaves - - - - 0 - - - - + False + 3 + + 7680x4320 + 3840x2160 + 2048x1080 + 1920x1080 + 1440x720 + 1600x900 + 1280x720 + 800x600 + + + True + True + 0 + + + + True + False + + + True + True + 1 + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + vertical + + + True + False + 10 + 5 + Save Path + + + True + True + 0 + + + + + True + False + 0 + + .animatedBGstarter.sh + .animatedBGstarter2.sh + .animatedBGstarter3.sh + True @@ -324,267 +462,121 @@ - True + False True - 0 + 1 - + + True False - False - vertical - + + Save True - False - vertical - - - True - False - - - True - False - 10 - 10 - Playback Resolutions - - - True - True - 0 - - - - - True - False - 10 - 10 - Position Offset - - - True - True - 1 - - - - - False - True - 0 - - - - - True - False - - - True - False - 3 - - 7680x4320 - 3840x2160 - 2048x1080 - 1920x1080 - 1440x720 - 1600x900 - 1280x720 - 800x600 - - - - True - True - 0 - - - - - True - False - - - True - True - 1 - - - - - False - True - 1 - - + True + True + True + True + saveImage + True + - False - True - 0 + 1 + 0 - + + (Re)Start True - False - vertical - - - True - False - 10 - 5 - Save Path - - - True - True - 0 - - - - - True - False - 0 - - .animatedBGstarter.sh - .animatedBGstarter2.sh - .animatedBGstarter3.sh - - - - True - True - 1 - - + True + True + True + True + startImage + True + - False - True - 1 + 0 + 0 - - + + Stop True - False - - - Save - True - True - True - True - True - saveImage - True - - - - 1 - 0 - - - - - (Re)Start - True - True - True - True - True - startImage - True - - - - 0 - 0 - - - - - Stop - True - True - True - True - True - stopImage - True - - - - 0 - 1 - - - - - Close - True - True - True - True - True - closeImage - True - - - - 1 - 1 - - - - - - - - - - - - - - - - - + True + True + True + True + stopImage + True + - False - True - 2 + 0 + 1 + + + Close + True + True + True + True + True + closeImage + True + + + + 1 + 1 + + + + + + + + + + + + + + + + + False - False - end - 1 + True + 2 False - True - 1 + False + end 1 + + False + True + 1 + 1 + @@ -691,6 +683,7 @@ True True True + closePopupImage2 True @@ -770,6 +763,7 @@ True Set Custom Default Path Set Custom Start Path + True @@ -808,6 +802,7 @@ True Set Custom Video Player Set Custom Video Player + True @@ -846,6 +841,7 @@ True Set Custom Image Viewer Set Custom Image Viewer + False diff --git a/user_config/usr/share/gwinwrap/settings.json b/user_config/usr/share/gwinwrap/settings.json index 596ddd2..b373664 100644 --- a/user_config/usr/share/gwinwrap/settings.json +++ b/user_config/usr/share/gwinwrap/settings.json @@ -1,9 +1,36 @@ { - "settings":[ - { - "start_path":"/home/abaddon/LazyShare/Movies-TV-Music/Dream Scenes/Games/Halo", - "default_player":"mpv", - "default_img_viewer":"mirage" - } - ] -} \ No newline at end of file + "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" + } +}