From a5ef8739dbb9c1ca2855b7e687db291b92858205 Mon Sep 17 00:00:00 2001 From: Kevin Alberts Date: Tue, 6 Jun 2017 00:15:28 +0200 Subject: [PATCH] Base theme, built on a class-based model. 9 workspaces based on function, basic system tray with cpu monitor, battery monitor and update indicator. Built-in multi-monitor support. --- .gitignore | 1 + config.py | 94 ++++++++ kuro/base.py | 145 +++++++++++++ kuro/config.py | 58 +++++ .../battery/battery-caution-charging.png | Bin 0 -> 2035 bytes kuro/resources/battery/battery-caution.png | Bin 0 -> 1461 bytes .../battery/battery-full-charged.png | Bin 0 -> 2077 bytes .../battery/battery-full-charging.png | Bin 0 -> 2014 bytes kuro/resources/battery/battery-full.png | Bin 0 -> 1399 bytes .../battery/battery-good-charging.png | Bin 0 -> 2129 bytes kuro/resources/battery/battery-good.png | Bin 0 -> 1371 bytes .../battery/battery-low-charging.png | Bin 0 -> 2057 bytes kuro/resources/battery/battery-low.png | Bin 0 -> 1433 bytes kuro/resources/battery/battery-missing.png | Bin 0 -> 2221 bytes kuro/theme.py | 201 ++++++++++++++++++ kuro/utils.py | 50 +++++ 16 files changed, 549 insertions(+) create mode 100644 config.py create mode 100644 kuro/base.py create mode 100644 kuro/config.py create mode 100644 kuro/resources/battery/battery-caution-charging.png create mode 100644 kuro/resources/battery/battery-caution.png create mode 100644 kuro/resources/battery/battery-full-charged.png create mode 100644 kuro/resources/battery/battery-full-charging.png create mode 100644 kuro/resources/battery/battery-full.png create mode 100644 kuro/resources/battery/battery-good-charging.png create mode 100644 kuro/resources/battery/battery-good.png create mode 100644 kuro/resources/battery/battery-low-charging.png create mode 100644 kuro/resources/battery/battery-low.png create mode 100644 kuro/resources/battery/battery-missing.png create mode 100644 kuro/theme.py create mode 100644 kuro/utils.py diff --git a/.gitignore b/.gitignore index c01ebd2..9322969 100644 --- a/.gitignore +++ b/.gitignore @@ -139,3 +139,4 @@ ENV/ # Rope project settings .ropeproject +.idea diff --git a/config.py b/config.py new file mode 100644 index 0000000..45cd90a --- /dev/null +++ b/config.py @@ -0,0 +1,94 @@ +# Copyright (c) 2010 Aldo Cortesi +# Copyright (c) 2010, 2014 dequis +# Copyright (c) 2012 Randall Ma +# Copyright (c) 2012-2014 Tycho Andersen +# Copyright (c) 2012 Craig Barnes +# Copyright (c) 2013 horsik +# Copyright (c) 2013 Tao Sauvage +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Import Theme +from libqtile import hook + +try: + from kuro.theme import Kuro + Theme = Kuro() +except ImportError: + from kuro.base import BaseTheme + Kuro = None + Theme = BaseTheme() + +# Import theme configuration +try: + from kuro.config import Config +except ImportError: + try: + from kuro.baseconfig import BaseConfig as Config + except ImportError: + Config = None + raise ImportError("Could not load theme Config or BaseConfig!") + +# Initialize the Theme +Theme.initialize() + +# Hook theme into all hooks we know of +hook.subscribe.startup_once(Theme.callback_startup_once) +hook.subscribe.startup(Theme.callback_startup) +hook.subscribe.startup_complete(Theme.callback_startup_complete) +hook.subscribe.setgroup(Theme.callback_setgroup) +hook.subscribe.addgroup(Theme.callback_addgroup) +hook.subscribe.delgroup(Theme.callback_delgroup) +hook.subscribe.changegroup(Theme.callback_changegroup) +hook.subscribe.focus_change(Theme.callback_focus_change) +hook.subscribe.float_change(Theme.callback_float_change) +hook.subscribe.group_window_add(Theme.callback_group_window_add) +hook.subscribe.window_name_change(Theme.callback_window_name_change) +hook.subscribe.client_new(Theme.callback_client_new) +hook.subscribe.client_managed(Theme.callback_client_managed) +hook.subscribe.client_killed(Theme.callback_client_killed) +hook.subscribe.client_state_changed(Theme.callback_client_state_changed) +hook.subscribe.client_type_changed(Theme.callback_client_type_changed) +hook.subscribe.client_focus(Theme.callback_client_focus) +hook.subscribe.client_mouse_enter(Theme.callback_client_mouse_enter) +hook.subscribe.client_name_updated(Theme.callback_client_name_updated) +hook.subscribe.client_urgent_hint_changed(Theme.callback_client_urgent_hint_changed) +hook.subscribe.layout_change(Theme.callback_layout_change) +hook.subscribe.net_wm_icon_change(Theme.callback_net_wm_icon_change) +hook.subscribe.selection_notify(Theme.callback_selection_notify) +hook.subscribe.selection_change(Theme.callback_selection_change) +hook.subscribe.screen_change(Theme.callback_screen_change) +hook.subscribe.current_screen_change(Theme.callback_current_screen_change) + +# Initialize variables from theme +keys = Theme.keys +groups = Theme.groups +layouts = Theme.layouts +widget_defaults = Theme.widget_defaults +screens = Theme.screens +dgroups_key_binder = Theme.dgroups_key_binder +dgroups_app_rules = Theme.dgroups_app_rules +main = Theme.main +follow_mouse_focus = Theme.follow_mouse_focus +bring_front_click = Theme.bring_front_click +cursor_warp = Theme.cursor_warp +floating_layout = Theme.floating_layout +auto_fullscreen = Theme.auto_fullscreen +focus_on_window_activation = Theme.focus_on_window_activation +extentions = Theme.extensions diff --git a/kuro/base.py b/kuro/base.py new file mode 100644 index 0000000..cf8b7bf --- /dev/null +++ b/kuro/base.py @@ -0,0 +1,145 @@ +from libqtile import layout as libqtile_layout + + +class BaseConfig: + @classmethod + def get(cls, key, default): + if hasattr(cls, key): + return cls.__dict__[key] + else: + return default + + +class BaseTheme: + # Changing variables initialized by function + keys = None + groups = None + layouts = None + widget_defaults = None + screens = None + + # 'Static' variables + dgroups_key_binder = None + dgroups_app_rules = [] + main = None + follow_mouse_focus = True + bring_front_click = False + cursor_warp = False + floating_layout = libqtile_layout.Floating() + auto_fullscreen = True + focus_on_window_activation = "smart" + extensions = [] + + # XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this + # string besides java UI toolkits; you can see several discussions on the + # mailing lists, github issues, and other WM documentation that suggest setting + # this string if your java app doesn't work correctly. We may as well just lie + # and say that we're a working one by default. + # + # We choose LG3D to maximize irony: it is a 3D non-reparenting WM written in + # java that happens to be on java's whitelist. + wmname = "LG3D" + + def initialize(self): + self.widget_defaults = self.init_widget_defaults() + self.keys = self.init_keys() + self.groups = self.init_groups() + self.layouts = self.init_layouts() + self.screens = self.init_screens() + + def init_keys(self): + return [] + + def init_groups(self): + return [] + + def init_layouts(self): + return [] + + def init_widget_defaults(self): + return {} + + def init_screens(self): + return [] + + def init_mouse(self): + return [] + + # Callbacks + def callback_startup_once(self, *args, **kwargs): + pass + + def callback_startup(self, *args, **kwargs): + pass + + def callback_startup_complete(self, *args, **kwargs): + pass + + def callback_setgroup(self, *args, **kwargs): + pass + + def callback_addgroup(self, *args, **kwargs): + pass + + def callback_delgroup(self, *args, **kwargs): + pass + + def callback_changegroup(self, *args, **kwargs): + pass + + def callback_focus_change(self, *args, **kwargs): + pass + + def callback_float_change(self, *args, **kwargs): + pass + + def callback_group_window_add(self, *args, **kwargs): + pass + + def callback_window_name_change(self, *args, **kwargs): + pass + + def callback_client_new(self, *args, **kwargs): + pass + + def callback_client_managed(self, *args, **kwargs): + pass + + def callback_client_killed(self, *args, **kwargs): + pass + + def callback_client_state_changed(self, *args, **kwargs): + pass + + def callback_client_type_changed(self, *args, **kwargs): + pass + + def callback_client_focus(self, *args, **kwargs): + pass + + def callback_client_mouse_enter(self, *args, **kwargs): + pass + + def callback_client_name_updated(self, *args, **kwargs): + pass + + def callback_client_urgent_hint_changed(self, *args, **kwargs): + pass + + def callback_layout_change(self, *args, **kwargs): + pass + + def callback_net_wm_icon_change(self, *args, **kwargs): + pass + + def callback_selection_notify(self, *args, **kwargs): + pass + + def callback_selection_change(self, *args, **kwargs): + pass + + def callback_screen_change(self, *args, **kwargs): + pass + + def callback_current_screen_change(self, *args, **kwargs): + pass diff --git a/kuro/config.py b/kuro/config.py new file mode 100644 index 0000000..3c36627 --- /dev/null +++ b/kuro/config.py @@ -0,0 +1,58 @@ +from kuro.base import BaseConfig + + +# Config variables used in the main configuration +class Config(BaseConfig): + # Show debug messages + debug = True + + # Default Applications + app_terminal = "terminator" + + # Images + desktop_bg = "/home/kevin/Pictures/wallpapers/desktop.png" + + # Fonts + font_default = "Noto Sans" + font_topbar = "Noto Sans" + font_clock = "Noto Sans" + font_titlebar = "Noto Sans" + font_groupbox = "FontAwesome" + + # Font sizes + fontsize_default = 11 + fontsize_topbar = 11 + fontsize_clock = 11 + fontsize_titlebar = 11 + fontsize_groupbox = 15 + + # Sizes + width_border = 1 + margin_layout = 4 + width_groupbox_border = 1 + height_groupbox = 24 + margin_groupbox = 0 + width_spacer = 1 + padding_spacer = 4 + + # Variables + bool_groupbox_disable_drag = True + bool_groupbox_rounded_borders = True + + # Colours + colour_border_normal = "#333333" + colour_border_focus = "#ffffff" + colour_groupbox_border_normal = "#333333" + colour_groupbox_border_focus = "#aaaaaa" + colour_groupbox_icon_active = "#ffffff" + colour_groupbox_icon_inactive = "#777777" + colour_spacer_background = "#777777" + + # Battery variables + battery_theme_path = "/home/kevin/.config/qtile/kuro/resources/battery" + battery_update_delay = 2 + + # CheckUpdates variables + updates_display_format = "{updates}" + updates_execute_command = "terminator -e 'echo Updating\ via\ yaourt\ -Sayu...; yaourt -Sayu'" + updates_colour_available = '#f4d742' diff --git a/kuro/resources/battery/battery-caution-charging.png b/kuro/resources/battery/battery-caution-charging.png new file mode 100644 index 0000000000000000000000000000000000000000..30efa9121e314fb9ea7812f930387649b718ee55 GIT binary patch literal 2035 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 P00000NkvXXu0mjf*}$ia literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-full-charged.png b/kuro/resources/battery/battery-full-charged.png new file mode 100644 index 0000000000000000000000000000000000000000..34467405dc66dc7e27c032713e7ccb0af8882e9b GIT binary patch literal 2077 zcmV+&2;%pNP)%ckWC(wA(H&tsq;(1yd6iUsP62 zHeyzHjUmb!bxAZDUnIVe>_N88dnJ*gs_3Z6DLl*eCW`jpC^;aVbe4d50&l)LrR%* zU3d1(nKM5iLEfRf2?K7Rc8R}UXP{2M7{>`A>W5kg>^X5r+?lRr9o z^yr^~yUmV7r2sv^^HWn(zaJPF_~awx`_ORj-o5vC?b`J^a6@aIZPcdne8+)4$8okw zDG3ZBfbaXPtgImAn#UHL{>7F2Zs>33s!plpt%LP{M`t;;R`1;3x z#?l>+T(;Qp_`0-1N~x++fs_y;DTJt6b4v>dcV4eg*m7T4P!xTQ?@D^aX1=uJ4Mw-V zM9LW?m&=h)OOpNifyQsdvzGsb3m1NvNF?&U?|Y|CojN@}K7LaOv8c5!LOVV{>(an& z+P?-_)D(S%pOcs}$>%=yI(uK-&tUH`Uf#pYdo1Ob%Hu1g+aJH#w3?EoRY$R%J9mB; zg6#0vv113v$H(^rd0-jZ5kRe$wIGYZx%OR&@?r0muko4D*VxiOLcuGN&*!;+?|xms zcE@jp)p4o^%49O-|4q}}3_JrY(6#_;?9i$+QxrVOC;ImBg*^w^Hn~p=X+myv+nm_{NV2``)aMp<#J@RSr(V)n3{Wse_cC=pI9R1n8X|r zaMbk{+zM@2fJT=rKm)P3LC-T5$$kqB(9Y4-5VMVjbD8*m;~ji{9-fb~1^bFtFk#vA953BJfcm&y79;Q)gIL_ej0;RlAdEnG zO?_q>KCjgBcU`wU=j`n4ov?fOXxx?$=p;^ueYMiKu3K94f0>$DU9{5|qj#HuUE1m9 zi*C*#oTGM^$HvCa0eGHQym;~AKM8J&b7B3uqQHYG5cHkDKg-1VUvqu&3dFtDMJJo@ zG_*gjZejsrV`IMpd;$$Kz&zlF^$ne1<$a(kCqfTs0cf-#SW>rHGG^)BZeSwH+*RwAT3$<>9xPMY)&Iba0IOFL(Jy;$YhaG(M(`#@J> zgQ;OW{b5JBx)~QZu^?uL#?|UfuNO*d22;Zu9|rgBc$M=rr}1+VV;$k|Q9?(oAr8LyeV(2#WOI^8i*@rbXLr>CcH5IDf5FGnjc2=jnDF)=Z*u(04uDeEp6J1w;r zt{Yt{=UG@-@FylFCJ17FzVY&_UyfS95U_Li?%n$j960dJp`oFziA18O^SyX<$mMd` zxw*NSvuDr#VRCZvJa8453ok)yQTu&B64(NK6xdGip@iM2<6{gTNCP*4+rS;IwcD(5 zqc21pf{Vix&_nQ*$diNu!JFVTaKAF^YlJ!h07@?pY@Xn6gaBXb*7;>a0iGs2X}i1O z=n4=ufvC|HAZh|pqboqv1foV)fT#&XjjjMu6Nnm5y#W6QCwOL!i=-j{00000NkvXX Hu0mjf<=f?? literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-full-charging.png b/kuro/resources/battery/battery-full-charging.png new file mode 100644 index 0000000000000000000000000000000000000000..03262cd4b860d919a50216c0a64ab1139f882681 GIT binary patch literal 2014 zcmah~hf~v87yX42A`%i2k)l!-AwonJ2!RDdqzFVnNQjUH23=~FYN$#T#DWV5NEDDJ z(xO2Vnk@p0L@{DSq)1p5kN{G5V~Eszzx@Ng*)#8+Gw;rvx%2MKefO%ThcjGJQxO0F zxT}jJ5mfxY0fU0fpq~8%id>w%t2YcpDlGU4c;6B0LWu+AmwyAY5?n+8lN#|(zVW1( z(D(Nf3)S^Liw(H&A(2!Q&1fEF1rIpo__7@sv-Lzz)h5P^fPgv1J9s1# zwu5|VmlwfhpI}OXb=3SoL6|UpV$>{KTc1_x_`{ImCA?iK+UgYH%r6piV>Gx?kZ5z$ zuK(mI>P@i_6lre- z^hlOJONaW)u~HS7+;IwBEFni1u+aDJQ^%HSoeQ>8H&z!jWM6p^@)FmypbOZwSx$;1 zJ#BuN*-4>KA8opP@FMad+AnS8OLx`M_+!!TOt+^d1Ce-S*GI8foZ+Zf*!!TdBj&4U zP5PG4mnwIq5Sqq}PR2=vkSn;Vm~l4xgQg?A$J7(8c80S5X>r6u^tD(krTi(}<0a7= z7jmVscX$ZU2J)w@y4x4Iy{WhuT*_)>QdHC;r=B`pd2bnV0pFFey}8!n)9kO2=ct!= zE4gwn5DWTL5btKCN&uI_I}-SO^I=DaWOB0iTG_~ao1bk@0%ORi*v%j*kaIp^Zmcb0 zFh3XyIKXt7+zb5rN5V0MOoTS>e&F*|YpsHpn9k1`XgKO7@6GV=sV{4ynR$AMHGI~^ zM^>-UW%WZ7X(-vYImNaz$olZDdRN7qEUe1a;EMI914F>2GbrG@S#rRL2ATZP&7g;c zK4EBJ5MRYlnjI#Oa7~qtvLRcVbCQTY5=zx}F21ZID#gC&?s8yf`j$EHroW%cK{aGU zWOQH1Rg(x>rBB*3YfqOMc#%u`r)i)3O^>({T0f3l$4Zc1G9i49s&1M%^{OZ+#3e{aaEEXSu5AV zEuNU-aJbgbGc_ot@faKZ-fRMCCC1+DV@IlXAps4JDSjlO-V>FKOW&OB4{h1UWA9}7 zF8ulGmCFZHrGk2DRQA%|itoz}EWlQr(0xInd;K(>Kg0PLNpC?%=xOGq+hH&VKeqQ9 z=h7Oh_c)zFoG;+dv{bZ^_zm5m@d06$mX>gO2tVzS*$>hX{2;&uDzt&01@-#oR8Wxi3 zB@OWR-^V#G{w6;oo*#K2tr2i;5O458!pn|h+y~7{|9HmXY-zg|B?hs4duK$L)eVIT zE+QDmIFt@v)h>d70bC z42%2R42r38M{R6Us;h10Ml6_K!lk8XMS!{GC(z8m$bS3H!o9XHn0=j4XZA7Da+eZx zXHZbkxAF1un(SzB20_@#;OmG#SK-pumD&a;x!rGl%yp{x5dwi=nfBP<9(i$cbo3St z{6_d$%Fyg#uf$6pTc9mN{&e*zkz%GrCRcr!hKyHEcg~rzDxZ4fsDm7(`1>!Md)MFE zh?nh>u1e{U@Eb%<<)}mrshD%WudmOH$7a8rs@Z})DYaa`2P7gA^bK-?@uPT6PrvO931xMKU0a%hfKs; zy%lYW+uGV@lzP4vm~==++xPEs`kRJQ)jXnhEpI;XpHN;)RiTPK3i#Ei&|?lfSzu)Y(tHPKr_Dyg~E-xy1L~u^Af_r z?~|$xBP}PemRRiPT1%ik&3bHeDNv!B+1%XxnjPs&mlw3Bthb==J?IqDf+?1#e0+So z%0=SgiHvpH2U)y~>C=Y~S9=~1h>^;l zmc_HvVc%Y?rQrd*QkQzB)$iJbSZ1^>R~;Y#?SMXT7gZNkFz%P8JL$0a#S=g}E*cjW zJML-2b{_<^%YD+AKi&X<&PCJ4q0OsX$6=WRn=*IzABO*+TT$BtaZu=^!(CDTkDs5D b-A1eg{ZW*oTsH;oV!+kO!?D@^bk_d>CdR?! literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-full.png b/kuro/resources/battery/battery-full.png new file mode 100644 index 0000000000000000000000000000000000000000..81831c87ff8ed71bafb411b7a75961df687ee7da GIT binary patch literal 1399 zcmV--1&I2IP)X3AlVm2HI@4ljEc6cpt&9tCC0z(Y zrC2uwtDtrvh#QA)3U0b^A*IXiDpEIvsY67B7DTbOb)l;+gi^s4WZFVI(@E_}Cz)jC zCHEc|FUe#wFO$?{=Dyf`@JRCRdC7Obd+xa>=UycuJj;mKCSV&q0c;bnjh+Cu3D`zY z0NVs?qbGoE0=Cf;z%~Kf=m}t(fNew@H7KQ2xxL#&GC)aM{F|%l?UYgukOBsP80&}> zQj~xqkOQ(JqSrHCC4f@O1%}U@IrI9lW5+&ECX=I%<0LkeZik_@F68t1nF|*#e0Ji* ziC=)nBH}f&uL@9h`R%7qpMG;$MNqKD?uPzpt+^1-STq3q%yE^FIPa>PPwK>)&v5;Sz&;V{CO&8^OPA zh}PVEa*5dWDDNFQUf&!6B1$P06bIHUakZllaO1&chV~>#Zgq%6RlRvAU`j%KAj*w9 zmw8uz@>I_@6~H8OIDK*4eg_rK{v!g*1&vAO*6?qJrUHP%82?AYyej&%Rr><0iS#0f z2qw(E2c$eg>j;oiN|k^m5vdwA^?=IA%hL(F>8S9m=YRF;)sGU1#FFQE%jeFWJ3low zbx$evSVT(DN(>Mwe{tA7z~@@;!DC}%?}MKmo;r2v=+xBIL0}1Z0<8#OR<1B(h39Ib zxm>RL-f^7mz;i%`mIV;O7zw=x7$aq_jYq27<^a)3UeGiM`mW_)VTNfC1Dc_E5Hxg+ z2S~saXol8S0n-JmKsi@=+COY9cz_^X-~lTDskx zzu{Ml3zhc&-6~Mee{yp2OTfb)`5Z6@a0+1Jx zrAlK*v8o>q3YqGdx- zN(ms@Y&JJAFfdRt$So`~l-$LqZ+t;47TW;&?W0&MGB-CzZejJ_N6s$>tXlW$QR@L7 zP@JBgzB@iX{!*<`Hk&1z&9+TcZE{(8dV2aUegJH^Ia<5-zXasd>2x}i$#`08j4>U( zwALGX)&5Qdnz8FanJ2-@pIhkt0Xm9vKrsC`APMXMUI2FCACz!|9t<%&APd|B9smzTB;Uw5 z=!8fdzi^lW`teVRbQ6mBJHc7tpW3W12x|lYP)bGcN4{&%2mxO021p|W3h*qU+eWwJ z=m}t(fNk^yuuZ@=dIH!cU>iLFY!k4Jo&dH9*v2z2z`w%NW3g^nWdi^J002ovPDHLk FV1j+Ygp~jQ literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-good-charging.png b/kuro/resources/battery/battery-good-charging.png new file mode 100644 index 0000000000000000000000000000000000000000..2a8e115903e2e0cf67e2f5ec98cf443d42ec7359 GIT binary patch literal 2129 zcmV-X2(I^uP)Co*oJ+*~e&EJEA6 z>B=FEA+(`cl&%uG$Rdy|x+o#b>;feXq~IV-OCcAG3nfW6DZQj=!Zo?R4)JyUkZiqU zNi(C-STm;!S-#`R=;2uMToZjDgwFXj=lj2N&VSDN&k#x}K4w_VCSW$&0+>y}Y_tV1 zn}FG93t%<@v(Xm7YyxJZEr8hs%tl)Pvk90Dwps-tglyLzHjz{SCEDOIm+0*XAq)Ty z05;( zn>YUsAX#lnXa#TqIQHhvo4@+~{;>n(+cIP_nQu;>JUIzqnNlhk*=Xmt4S>&XxA!TE zg7SbULzZRaayckU&FN$s7>0q@>jlSgyUOi$dmjKF%D&YVzz%@pIL@Q0>P}%MlPNuW z_H2EAetuaL#X{5BS3xWmTc4Sk`Kl4yP$=ZTeEITECnhF7?da&RSITWRn+E`gvTuf9 zft~qp0btSh@{1QQRyQ{{pPxQ`TC`fNs=+f_f=DFt?aa)~zZ>yhr{u^ z$;ru|>8dRNEQAnZ6bIg0;kAEd28JTZ4mx63em&xhxbYrMX572_Y5$j@PeW&+GZuLtOzZ z77GP{W;!oPl0^^%CYelf48zd={(i}Bx9?|kRk+c83(%@aUn-SIHk)O$*(@86$8D;r z_6LK(PhP!x^$!3T9UT>$(M}BkJcN)E0Etq%V^ntp><6V%i3ozgq|<3@I-TYUg@V7U ztLwAj;o*LUVO)hm0f|JyE{Y=GtTy%hpFDZ;8;8Ro$+BF$ckkYx!{P7>AtX&HEdebO zAeYNAJkPVSSj;8}g4^fwecIF0Gt6&*%5uMm6Y1@W{x>FM;yz@Ybzc7sBE2 z=Kv%CS)hpm@I225g22S%aW0d|*gYQ4j{<=}sIRZDV|&hn=Z!mBQ50fW@d42D*S5(p zOaMR!fCQQ$fFwzlY&Ofjd-u+oN~Ji4VM5*A-KV;`x&pE+v!Wgrby9z6KV)me9Q}<9iao zX0xe&zh6Fn{CIw7XlN&tQ%Y-!pePCvMX}R}TqF`P{12rR#bOaW&#TMJ%PVtpbKlI) z&VISJwzdi&iL&E)XnMaMei$zzfKsVM78e&?Z{NPH z+dCDf1wo*ZNF@34<;(xf&dz=rjYcE*E^=2K=K%%jL@U_Vx;+qoYz+SC`b;*(rB+cFGQiBLN`Nh|^l=dwFVV>I(oU z7K^2)PoF-+cY*>qKmjtDjJUS8_BNePM?D@-uD7?BKXKy3E~kAyU&-ZiDcdK*s>8e% z^!%r$rv3;(M!DyC0C8wm4Z|R)4}SXv$8jphaZ#t!85tWJtL5~*VbFmxfd6fO7XXNq zQmIne@)6*6yOn`~fda!Y36^DPE1cG%3jZwt>mQU7^Z9&U0O|dZ8WE8xq=(p~Gm9@-Hg1K3(x zT3Q|-AOE4&D4)-x8CjfWuP*hlw6wI0asaG)IjX(;mjH;<)6>(5L_$^+1*)nx^`j_C zOF!Cn5{ZO7Jv}{*@|rIhyTAK#lm!q3FcJ!dK0kNv+%JN`V4uU`aP7Y@4i1GvLD<;X zh&+1q=x+-P3y%RT0@$b|LG{qTAK(Pg4WJjmAj&UFa7KUp9z#a?;IslD3Lr))t(tN- zdPBsHa^lbfz=iU)(_z9E$~VDz0PnQBJ|ny*0I+k_#NiOXBZTr~HrfK1O~7ol1u&a{*=P%3HUYEo(F^c@@|3}5{^^!l00000NkvXX Hu0mjf$+zqm literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-good.png b/kuro/resources/battery/battery-good.png new file mode 100644 index 0000000000000000000000000000000000000000..5883885f492a2ec51bfa23219ba8beb5a735f0e9 GIT binary patch literal 1371 zcmV-h1*H0kP)oQw&CG9}P)c!@snKnKZmI(4Hb6I30dyOno2mf1 z4bV+h0Nn=YrYeAL19VdrK(_(9@fE8OLWpd=*F>^_9aZKrSGd~=Aq*f4Gyt{iBho2l z2gm?PAfc3!`!(JpfDpnDyfQX6cD291|88Af-Rp*7gpSqRBSuP@PNh;S)6>(R-??+= zM_^qkWfp6n7a;5MEu*8O*9Qg$zLHYbdNo-hgupP2%=q~D$HT+J-vj>^n-Wd|>VeA( z3k%;iH#c{lpuNY&#>U2@D_5>WfF-5Wi$ZOj^E&{X3kHL2Qc7%xurW=O&CN}u+;=)@ z!!QgQ8yoTa{d=AVgTXf79QM1F6d(xr{eFMgvaI~Wjb~5z<+po0-nfsno*udJZtmXZ z(@OhvbaXV|x^?Tl?(Xilo0^(}x#xjEAPo4i->o1%$j|>8pvFDQzdxEp*5Bie%iuFA zHSIwBTxo|`Ean>;8u~R93VjlZMBaB**8nv_2vH~wytKqQM;~B4{SBROLDPBgoy>w5 zJ3yaWV106O^1+Q8H{1g3OGyD5&#&VTK|>>m6W9_dr8X<=BZQ~{LJuE4{KIX3DM|`} z0ENB15~p`n%vq)mEr2@)Sk`WFEDWcXeFO*#A$EW*rBuFANe{@qy!5C5b8~Yag+ie% z(=@jyCMLd~nVDG@LaZyLcAyLal=7AbxIMVNz5PS5cZVY*BfT>-GuMDE;5n4z0m>eI zuX;c-nauxh7)A@w1jH#@fb8fi3zP>1C{SkrzTCc`WDt}pTP(oi0u-Wj49JeYbyfwi z)UFqJfl3c-WqE*gmOQ|zpb!Gd?kaF51Sqx&{2x4^(DW!f2zu26QmGUGN-0)WR-Ry= z8&vLSTviaYly^M9J<3y4Qx5>Px3_oZ=jVUI&K9S0^<_-~FYg1Url!6GOze?Q0&74j zS6?s)I`e^+@_Y<1fxokV(?CiowUw(Z?=X}tUZ6-2%m6C~N{Q76E@4^Ao|poWNaVti zFN1C2n>;l~Nu|IzfuyJqB5;6iKET)8+k5lSJ3)60cr|>LmOv}9wJ+FK%LlNnVlGzN zVQ_G;y|1tDGb!aei9{m*yqudYU$&tVLMT8b5{YC(LqkKZ!RGTcb#P&QR0jX#-8jZ)}rj!!PvW~P!DUY={egqqUv$OYOvDgp5U%+ZE3F^lEeLx-X z8gK!)g#Dp}zfi|hj0q%wW#BRJL@AXj*0|6YB0=oLVHl{#zIO5w8SInp@d z0zm$%$&ZJ>5duu-1xPUp3UHS2+UOoRRRMGxpqr`yx((1xRRG-v=%y-wZUb~v6+pKE dx;gU#{0B|I1kda#GOz#u002ovPDHLkV1gHgbs7Kw literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-low-charging.png b/kuro/resources/battery/battery-low-charging.png new file mode 100644 index 0000000000000000000000000000000000000000..0f3962a42798d7dceb9ea326a90d7a75c60e0c36 GIT binary patch literal 2057 zcmah~i8tH%7XPKOgj)JgEm~r$7;9TfHI!It8A%#iOAK0SnG#DSc4BX7Vkz38rL>lg zMo3eNTH5l&zO{nb`i!yFQV~T%Ugi&Y=iPJe=X35o_ndp~z2EcsK0qU{iHpjM0stUx zXKRJwv-v*`5#r;Yfnl?J61a!3bB6FO4&r;CAB%+Ay4~ZG$v+O-^3Aj7C*>lnT_c=A z{30T6h2H@pBO`SKad+?e+zP#;8xrncyaAU70O52yD+}kSr|U(i0ENl3-R&sVKsC2K zAAA9W#LSeo^q5w!a6>pOmkoG^2O{Jx1Hj7pB~sxG<(xAyFy*Qo?DLmN`NpS5FpT82 zbgou@KJM{O9gV5w#C+>JnM=>R?Z8H!RwGk<^!D|Xmffhdasl7JDQQ1oOc(O$&-Uw|+a zrFo-Bz4jvU#BJd%%9Y3s?jCoa-5%EDG3R&s-%XV8mWSoAawz0(wxa0)=Sz(XPZVmY zS)fosl|u(^A7LAD&)!F@jBd(U*RPL%l0raEr)$o(#{O_I!cFfTCsGygA{0>t>_-IHlZR9a;H7 zU+lf7-Zw(*OnkjYGjN9|0%-DvH@W|CpEqrS-oe2ZDFK4! zWQ_Z_`GOn4JHLrf(ED%5RBWuumc!g3%DM=KFt9t<7XPy<*H%pc3c7JSI}f*e*&>icg^;fook^gQ3oKm^FFpiAvgh(L!T(1R;@#pL~` zE6dB|8PcwB@gx6+30DmbPpYT-!Yb6gi^Uj=;bPrk<5nskw&9x_o145nMy{%o;uS)_ zMrL{1!aH(bKx*3;GMRjI2JMnz6fz6HVra+_0Yo~4hOPNq@rf$&&+B<|{%p>YpXKjI1#Wd-NYFbpS+}=3D%HA&Dfu#%c@+UWu3*)bDqNp4bc6 zoNY~TE2Jbtzu6AE7p+j?K7eb@TC$@MU4GBLLTYkiqR#J)8`k7mgI4Bt+1w`Yh{0fZ zH+lG7Cg0TxKtNb34@R_|%k#&rr#XS>EPj)&E^C)x3Z}Yg-|BnaSp~nItEbUM>CnPE zU%yAmn-ajGhCMhLxFA#tfk9V|79NnIG{F2x%15fT&PZU#RwC3M_vwJ3;uixTLMgS6 zG*CyjiHUeT$GYZyKIVQo#NtG6lZUQ!R##ip*8B&hlB^qAmn9vM3L;vzH_l;jrax1B2(zzvOmxb+tv9%+Lrs7DI!B zgG2rOaShGQ^4&(Nk%plX07|pqzRhw20R(Ktv}Q8bX2P#57?WSMF&RMcaJ{RxyhO%Q zDLi^qI{-wSUVcseBjLq%BVN5a4dX8DEwl5+f9OvO4bWd`B|7B!@G5c4mj9aGUSN)o zOQD5P?lbb6)u3c3acMu?K%O)>Fo4$y&^d4~dHR$q1Bj*}Ru=mnQw=tS>QaQ%9@*gt zgxw)jso9~wO0Me%BMYjF)!Val+18_;o}Rg5Ic4K;7tO{?>2eau2Op?Td`)mGTui(g zx3?8iEm=gpzXA);5jqJ2?}aS72td*H6|0{dSzlMZzfjisa&a>~Bcn@N1KA10iFlW( zz>u1bPWEXyK}myYiBq80*X`d-%_r$ZBpn?k=n;R_DCd`}x6hR($?xp$oCl<(rGK`V ziA#uy#W}-d%6oiAXPHbU!O+ua9q<(zG8f}jD%5D&30GSRB4t)y? z3v*x2^)9i8O<20D&s+r>olY0S13`OX&R34x0;y=2jC}=$Rt_t+`Ha*%OuE~s7kv4Z zv%N$bLb-bEweOjP!|v-^L<``BkB?93Q?vL3|CE#zOTMB}+07G|t*-wy_dZ%Wk-PW3 zR3(>j56A*$oh2;!Sa&5_)l+6Mm*jxYW`>jXSv*w%eBX5V4c~x{pPjgxncA_79YG+!|Ap*X bg{`Yl-EJF<_h2CZ+Xn2ckyf<`@8tgiyh_%c literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-low.png b/kuro/resources/battery/battery-low.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb007d22d7023eb6d67e6b381b69924c57c024b GIT binary patch literal 1433 zcmV;K1!nq*P)V1a)SfcLNBNi ziApR*v{DbKr$iibKxz*hP?ST3daFcBq=HgKMyOINA#tJQQi%(cO9hSup+O~S+$Jem z$9C2k4~Mmlv$Y-9>+Zy=KWSxaXFUG*-9!P&Yk-ncvxvjlp4?u zyf!yC_iay4&tVVsJ~LKVSAQQE7>EM*lu{ez>XeS}HlQmM3iU}Tu{(r~Wm&ARuOnsE z;iL`2Fxaza55Zt?+xbu^)CY87U)zobgn(c$80^gDa>bKts}Hzy`x0w^Un95msBV#q z5Bc@{6~3;!fhr6R4)&ZrefpiDp`o|BySqb$^KETyoj?%#+REaG;`sLgKIdJI|2$1+ z<`M@Ff!{?!eDs)=^H=z({uU||kH`II&z}7y91edRjYi*f6#D?55JHrT15c#5(z_3k zUiyYNUx&Tj5HRW&d9astAYOk9RS5tq)6>&8PMkR5G@vRw8t`KK3XvdmN5ChXwV#3z zS*6svixw&(gzy33yLa#Y=G4CvI~pLso?GQ$7bnGnH09cWCn9|gkolttsA52;5Mm3+ zD5Z*(cI*L4fy&v38%qzT&iY3x#3aU5NJdY)MP*^m9qa{DHazOALNy&!lSWg zJ-{mioOgLKnVI>x5-J42EU;MDl31YQ0LX===mF7abbrIs zVB4XSWdEFEBL#jJ5A-UBuSdC|M@L6Lky5^Gnr88QEjwHOd_^UMP=GQ`GuhG6(NU=I*i2(Z4)fCc z-w_A|>K54!$Kz)>UUvgk$Y!%FFE1B!eu1RD7_cqxJ1Ok}7Lc8vpTBqH$dNZnE19NA zsk8O6ExUNY{QUeq>;PDCbF_4;BLk#ju~;mTNLW%za=BbX4=Lp{Jxc#4kw{pvSS*H} z^E2fyfBWXBALs@82L}g_4G#~0(A(SF7Y>Kp-QNrENT<^qOG``luV24@Egp~m0Q>h`Oj00000NkvXXu0mjfsf2?Q literal 0 HcmV?d00001 diff --git a/kuro/resources/battery/battery-missing.png b/kuro/resources/battery/battery-missing.png new file mode 100644 index 0000000000000000000000000000000000000000..a87a68e17d14a918f6003baa522fa7bcc694dd49 GIT binary patch literal 2221 zcmai0`8U*!7ygW~%peT1%Tl347)#ljm@t%V2}7nvO3J>zm>J}2Xe?P$DA|h;Z?-}b z(})tXjxm<8@7s{|o&JLFJ?FX4xz9QG{&0V|&yBOPG(E;G!3_YwF_an7hQ)}#fN-*M ziHGkfi`e~*P<9YjghSkjtQzWL=IGBN-M;{>x}})2MDc(t4gt2_?g7EK{q6$6!NIB? zUY`Eg+dg+yz5VWGE$d4F0OTwRdD$)`d&w#6DthMlk+kciXcD_1gx5^SEQIK0QJ}dX zQ%cEvGhB5o7uqi$1NB%S7yLqDhc#z=+~=MdWK~Psd7AgyvD2!G6_9I zp4Xb7LYOGRgU$S;Dxrrx&BPffgeoP}0p>zh6271`h1Z(DpNJEQ4a`1;6!zw?&q6v2 zn|+b3AT!Qnc3F@d@}ucENEYw`-oweQR?#z11X2Q6uzabz)fOKgFT@!=4ww2ihcyq5 zk&DmkmT3AU=4?lvlES-wcPK1!@Ez_JR!q@xfA3W05)%_+0vwPkUtqBNlV~1Hf@N_B z>z?FDpAhR1Dy|?rSa|Q!54D5Q$M!ksRpkqj@j_ zi^WP3yeMoCWz(=LPXSC`Wo6~k*q7)?w#P^ZkglGdHzF|yMSd=P0e5D#Ujzk=kSd2{ znd|^3P;P~`C(>_%egy{wjY1eQd^{!ksFZ0JAlyr+@0A&HWPn@yQKQSo%UU$a^`a4S z7YJ*K>!I;G;vBZN>B}lATmAA+?<8Uc4&^GF!S))xdkXaTcyBcK%GrCM*K`;4Ol49xf|v;C_ofJwk~yb zbQ~Qtop(0(8{~N$r=DzI9N}hb$(olhoA+#(My)ld#8T1F$$asaO<_A!`&;_XLtmb* zK{@$2HFI~oYz6oW?Ov?+54i*^qRuDmu)>egDzS2TyA$i(PhN215~5jN38$J3G2x zyt2Hz$D28O5`dnd_P9}a-Cj^FQ4V4wfS0sR6 zGy6EyQBfpyQCP%!?$^-jiTtFu^%qtgGBZ1#UwV*x4~_`$*4W*x;QU_~g6~tD*^2ZW z8~GemgX~VcKXx*?Zi=2p>Ig5G-pGC zYYHn??2F&s%~NT$HYzr5CntP;Pof#6rEda>AFOLb^DXl!wR+=6^#hQ-#6;(^-j?1*5vP1x~&OKTI|WML=Mu*cAasD zYySMps{+;$1@ez4WX|c|Ne2s7IF)(wZ5iN(+1(`Wwp`aQ` zcdD{imnOrVT*dCA`w{@iV&_CU)ENHYjj87jP&FzX-s{>uu)QfBJswhHo<0MIkk&r? zZ*0xbTF`j^w}%_yDTj)las7LXL1YEI+QqFW+xk6JK%_*JGqQAq6`X)qEw#71+xM7X z?cmhE-;e?6ZEvcS_ zEj~4B677|1lOhTq>0GYcLQ|GHnx3A%giw7W#%NChe0CQvr;hohe;`&|G2(QO^@>#T`jFbxEOC(Nl6LQ?&i&Jgu`_?2%CwC$uu)u zM#>M48Euk*;Q7ZukjBQwgVU!^Q}?-8%{$7HD)x7RqwE{_5BW{|fGXhOnX_kyZ`#`jDJd%} zn^p`cs^V1)4eFfBU$9I^FGJPkBSt&xh&z-jy{>f`4BNpGKnMi}=Oj4UHH}zwz2Z~| zWhNFx3H+vp?W`Xh!*~;CWp(&cL8pvxiyty&5xA7QvHO~y*4tcB5TMiGK@aBm=acLN t*YEiauh~YfJ3K1=H1U7Dce@cd;^H-+h5{4)#jMu?KwYs!mK$NB{sTgt8vFnN literal 0 HcmV?d00001 diff --git a/kuro/theme.py b/kuro/theme.py new file mode 100644 index 0000000..671f208 --- /dev/null +++ b/kuro/theme.py @@ -0,0 +1,201 @@ +import logging +import os + +from libqtile.config import Key, Screen, Group, Drag, Click +from libqtile.command import lazy +from libqtile import layout, bar, widget + +# Import theme util functions +from kuro import utils + +# Import variables +from kuro.base import BaseTheme + +try: + from kuro.config import Config +except ImportError: + try: + from kuro.baseconfig import BaseConfig as Config + except ImportError: + Config = None + raise ImportError("Could not load theme Config or BaseConfig!") + +# Initialize logging +log = logging.getLogger(__name__) + + +class Kuro(BaseTheme): + # Shorthand for modifier key + mod = Config.get("modifier", "mod4") + + # Show debug messages + debug = Config.get('debug', False) + + def initialize(self): + log.debug("Initializing Kuro Theme...") + + super(Kuro, self).initialize() + + # Update keys with keys for groups + self.update_keys() + + def init_keys(self): + log.debug("Initializing keys") + + return [ + # Switch between windows in current stack pane + Key([self.mod], "k", lazy.layout.down()), + Key([self.mod], "j", lazy.layout.up()), + + # Move windows up or down in current stack + Key([self.mod, "control"], "k", lazy.layout.shuffle_down()), + Key([self.mod, "control"], "j", lazy.layout.shuffle_up()), + + # Switch window focus to other pane(s) of stack + Key([self.mod], "space", lazy.layout.next()), + + # Swap panes of split stack + Key([self.mod, "shift"], "space", lazy.layout.rotate()), + + # Toggle between split and unsplit sides of stack. + # Split = all windows displayed + # Unsplit = 1 window displayed, like Max layout, but still with + # multiple stack panes + Key([self.mod, "shift"], "Return", lazy.layout.toggle_split()), + Key([self.mod], "Return", lazy.spawn(Config.get('app_terminal', "xterm"))), + + # Toggle between different layouts as defined below + Key([self.mod], "Tab", lazy.next_layout()), + Key([self.mod], "w", lazy.window.kill()), + + Key([self.mod, "control"], "r", lazy.restart()), + Key([self.mod, "control"], "q", lazy.shutdown()), + Key([self.mod], "r", lazy.spawncmd()), + # Key([self.mod, "shift"], "e", self.evaluate()), + ] + + def init_groups(self): + log.debug("Initializing groups") + + # http://fontawesome.io/cheatsheet + return [Group(i) for i in ""] + + def init_layouts(self): + log.debug("Initializing layouts") + + return [ + layout.Matrix(columns=2, + border_focus=Config.get('colour_border_focus', "#ffffff"), + border_normal=Config.get('colour_border_normal', "#777777"), + border_width=Config.get('width_border', "1"), + margin=Config.get('margin_layout', "0"), + ), + layout.Max(), + layout.Stack(num_stacks=2) + ] + + def init_widget_defaults(self): + log.debug("Initializing widget_defaults") + + return { + "font": Config.get('font_default', "Sans"), + "fontsize": Config.get('fontsize_default', 16), + "padding": 3, + } + + def init_screens(self): + log.debug("Initializing screens") + + num_screens = utils.get_screen_count() + + screens = [] + for x in range(num_screens): + widgets = [] + widgets.extend([ + utils.bar_separator(Config), + widget.GroupBox( + active=Config.get('colour_groupbox_icon_active', '#ffffff'), + borderwidth=Config.get('width_groupbox_border', 1), + disable_drag=Config.get('bool_groupbox_disable_drag', False), + font=Config.get('font_groupbox', 'Arial'), + fontsize=Config.get('fontsize_groupbox', 15), + highlight_color=Config.get("colour_groupbox_border_normal", '#444444'), + inactive=Config.get('colour_groupbox_icon_inactive', '#444444'), + rounded=Config.get('bool_groupbox_rounded_borders', True), + this_current_screen_border=Config.get('colour_groupbox_border_focus', '#ffffff'), + this_screen_border=Config.get('colour_groupbox_border_focus', '#ffffff'), + margin=Config.get('margin_groupbox', 0) + ), + utils.bar_separator(Config), + widget.Prompt(**self.widget_defaults), + + widget.WindowName(**self.widget_defaults), + + widget.CPUGraph( + width=25, + border_color="#000000", + border_width=0, + line_width=1, + samples=10, + ), + widget.BatteryIcon( + battery_name=Config.get('battery_name', 'BAT0'), + energy_full_file=Config.get('battery_energy_full_file', 'charge_full'), + energy_now_file=Config.get('battery_energy_now_file', 'charge_now'), + theme_path=Config.get('battery_theme_path', '/home/docs/checkouts/readthedocs.org/user_builds/qtile/checkouts/latest/libqtile/resources/battery-icons'), + update_delay=Config.get('battery_update_delay', 30) + ), + ]) + + # Systray only on first screen + if x == 0: + widgets.append(widget.Systray(**self.widget_defaults)) + + widgets.extend([ + utils.bar_separator(Config), + widget.Clock(format="%a %d %b, %H:%M", **self.widget_defaults), + utils.CheckUpdatesYaourt( + colour_no_updates=Config.get('updates_colour_none', '#ffffff'), + colour_have_updates=Config.get('updates_colour_available', '#ff0000'), + display_format=Config.get('updates_display_format', 'Updates: {updates}'), + execute=Config.get('updates_execute_command', None), + **self.widget_defaults + ), + widget.TextBox("#{}".format(x), name="default", **self.widget_defaults), + ]) + screens.append(Screen(top=bar.Bar( + widgets=widgets, + size=Config.get('height_groupbox', 30) + ))) + + return screens + + def init_mouse(self): + log.debug("Initializing mouse") + + # Drag floating layouts. + return [ + Drag([self.mod], "Button1", lazy.window.set_position_floating(), + start=lazy.window.get_position()), + Drag([self.mod], "Button3", lazy.window.set_size_floating(), + start=lazy.window.get_size()), + Click([self.mod], "Button2", lazy.window.bring_to_front()) + ] + + def update_keys(self): + log.debug("Updating keys") + + for i, g in enumerate(self.groups): + # mod1 + number = switch to group + self.keys.append( + Key([self.mod], str(i + 1), lazy.group[g.name].toscreen()) + ) + + # mod1 + shift + number = switch to & move focused window to group + self.keys.append( + Key([self.mod, "shift"], str(i + 1), lazy.window.togroup(g.name)) + ) + + def callback_startup(self): + utils.execute("sleep 3") + utils.execute_once("nitrogen --restore") diff --git a/kuro/utils.py b/kuro/utils.py new file mode 100644 index 0000000..ad58367 --- /dev/null +++ b/kuro/utils.py @@ -0,0 +1,50 @@ +import re +import subprocess +from libqtile import widget, bar +from libqtile.widget.check_updates import CheckUpdates + + +def is_running(process): + s = subprocess.Popen(["ps", "axuw"], stdout=subprocess.PIPE) + for x in s.stdout: + if re.search(process, x.decode('utf-8')): + return True + return False + + +def execute(process): + return subprocess.Popen(process.split()) + + +def execute_once(process): + if not is_running(process): + return subprocess.Popen(process.split()) + + +def get_screen_count(): + try: + output = subprocess.check_output("xrandr -q".split()).decode('utf-8') + output = [x for x in output.split("\n") if " connected" in x] + except subprocess.CalledProcessError: + return 1 + + if output: + return len(output) + else: + return 1 + + +def bar_separator(config): + return widget.Sep(foreground=config.get('colour_spacer_background', '#777777'), + linewidth=config.get('width_spacer', 1), + padding=config.get('padding_spacer', 4), + ) + + +class CheckUpdatesYaourt(CheckUpdates): + def __init__(self, **config): + super(CheckUpdatesYaourt, self).__init__(**config) + # Override command and output with yaourt command + self.cmd = "yaourt -Qua".split() + self.subtr = 0 +