mirror of
https://github.com/ellmau/nixos.git
synced 2025-12-19 09:29:36 +01:00
Various fixes, local-overlay added, added one local package to local overlay
Signed-off-by: Stefan Ellmauthaler <stefan.ellmauthaler@tu-dresden.de>
This commit is contained in:
parent
be87a34a34
commit
eeed4387a2
@ -2,7 +2,7 @@
|
||||
# your system. Help is available in the configuration.nix(5) man page
|
||||
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||
|
||||
{ pkgs, name, flakes, ... }:
|
||||
{ pkgs, name, flakes, flakeOutputs, ... }:
|
||||
{ config, pkgs, ...}:
|
||||
{
|
||||
imports =
|
||||
@ -54,7 +54,7 @@
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
|
||||
nixpkgs.overlays = [ flakes.emacs-overlay.overlay ];
|
||||
nixpkgs.overlays = [ flakes.emacs-overlay.overlay flakeOutputs.overlay ];
|
||||
|
||||
# Enable the X11 windowing system.
|
||||
services.xserver.enable = true;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
extraModules = if args ? extraModules then args.extraModules else [ ];
|
||||
extraOverlays = if args ? extraOverlays then args.extraOverlays else [ ];
|
||||
pkgs = flakes.nixpkgs;
|
||||
configuration = import ./configuration.nix {inherit extraOverlays system pkgs name flakes;} ;
|
||||
configuration = import ./configuration.nix {inherit extraOverlays system pkgs name flakes flakeOutputs;} ;
|
||||
in
|
||||
{
|
||||
inherit name;
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
outputs = {self, ...}@inputs:
|
||||
let outputs = rec {
|
||||
overlay = import ./local-overlay;
|
||||
nixosConfigurations = import self {
|
||||
flakes = inputs;
|
||||
flakeOutputs = outputs;
|
||||
|
||||
4
local-overlay/default.nix
Normal file
4
local-overlay/default.nix
Normal file
@ -0,0 +1,4 @@
|
||||
final: prev:
|
||||
{
|
||||
tray-calendar = final.callPackage ./pkgs/tray-calendar {};
|
||||
}
|
||||
29
local-overlay/pkgs/tray-calendar/default.nix
Normal file
29
local-overlay/pkgs/tray-calendar/default.nix
Normal file
@ -0,0 +1,29 @@
|
||||
{ stdenv
|
||||
, python3
|
||||
, gtk3
|
||||
, gobject-introspection
|
||||
, wrapGAppsHook
|
||||
, lib
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "tray-calendar";
|
||||
version = "0.9";
|
||||
src = ./traycalendar.py;
|
||||
|
||||
buildInputs = [
|
||||
(python3.withPackages (pyPkgs: with pyPkgs; [
|
||||
pygobject3
|
||||
]))
|
||||
gtk3
|
||||
gobject-introspection
|
||||
];
|
||||
nativeBuildInputs = [ wrapGAppsHook ];
|
||||
|
||||
dontUnpack = true;
|
||||
installPhase = "install -m755 -D $src $out/bin/traycalendar";
|
||||
meta = {
|
||||
license = lib.licenses.gpl3Only;
|
||||
homepage = "https://github.com/vifon/TrayCalendar";
|
||||
};
|
||||
}
|
||||
215
local-overlay/pkgs/tray-calendar/traycalendar.py
Executable file
215
local-overlay/pkgs/tray-calendar/traycalendar.py
Executable file
@ -0,0 +1,215 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Copyright (C) 2015-2018 Wojciech Siewierski #
|
||||
# #
|
||||
# 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 3 #
|
||||
# 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, see <http://www.gnu.org/licenses/>. #
|
||||
########################################################################
|
||||
|
||||
|
||||
import functools
|
||||
import glob
|
||||
import os.path
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from os import getenv
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk, Gdk
|
||||
|
||||
|
||||
DEFAULT_ORG_DIRECTORY = os.path.join(getenv('HOME'), "org")
|
||||
ORG_GLOB = '*.org'
|
||||
ORG_ARCHIVE_SUFFIX = '_archive.org'
|
||||
|
||||
|
||||
def org_agenda_files(directory):
|
||||
org_abs = functools.partial(os.path.join, directory)
|
||||
agenda_files_path = org_abs('.agenda-files')
|
||||
try:
|
||||
with open(agenda_files_path) as agenda_files:
|
||||
yield from (org_abs(f.rstrip('\n')) for f in agenda_files)
|
||||
except FileNotFoundError:
|
||||
for filename in glob.iglob(os.path.join(directory, ORG_GLOB)):
|
||||
if not filename.endswith(ORG_ARCHIVE_SUFFIX):
|
||||
yield filename
|
||||
|
||||
|
||||
def scan_org_for_events(org_directories):
|
||||
"""Search the org files for the calendar events.
|
||||
|
||||
Scans the passed directories for the .org files and saves the events
|
||||
found there into a multilevel dict of lists: events[year][month][day]
|
||||
|
||||
The returned dict uses defaultdict so *do not* rely on the
|
||||
KeyError exception etc.! Check if the element exists with
|
||||
.get(key) before accessing it!
|
||||
|
||||
"""
|
||||
|
||||
def year_dict():
|
||||
return defaultdict(month_dict)
|
||||
def month_dict():
|
||||
return defaultdict(day_dict)
|
||||
def day_dict():
|
||||
return defaultdict(event_list)
|
||||
def event_list():
|
||||
return list()
|
||||
|
||||
events = year_dict()
|
||||
for org_directory in org_directories:
|
||||
for filename in org_agenda_files(org_directory):
|
||||
with open(filename, "r") as filehandle:
|
||||
last_heading = None
|
||||
for line in filehandle:
|
||||
heading_match = re.search(r'^\*+\s+(.*)', line)
|
||||
if heading_match:
|
||||
last_heading = heading_match.group(1)
|
||||
# strip the tags
|
||||
last_heading = re.sub(r'\s*\S*$', last_heading, '')
|
||||
match = re.search(r'<(\d{4})-(\d{2})-(\d{2}).*?>', line)
|
||||
if match:
|
||||
year, month, day = [ int(field) for field in match.group(1,2,3) ]
|
||||
month -= 1 # months are indexed from 0 in Gtk.Calendar
|
||||
events[year][month][day].append(last_heading)
|
||||
return events
|
||||
|
||||
class CalendarWindow(object):
|
||||
|
||||
def __init__(self, org_directories):
|
||||
self.window = Gtk.Window()
|
||||
self.window.set_wmclass("traycalendar", "TrayCalendar")
|
||||
|
||||
self.window.set_resizable(False)
|
||||
self.window.set_decorated(False)
|
||||
self.window.set_gravity(Gdk.Gravity.STATIC)
|
||||
|
||||
window_width = 300
|
||||
|
||||
# Set the window geometry.
|
||||
geometry = Gdk.Geometry()
|
||||
geometry.min_width = window_width
|
||||
geometry.max_width = window_width
|
||||
geometry.base_width = window_width
|
||||
self.window.set_geometry_hints(
|
||||
None, geometry,
|
||||
Gdk.WindowHints.MIN_SIZE |
|
||||
Gdk.WindowHints.MAX_SIZE |
|
||||
Gdk.WindowHints.BASE_SIZE)
|
||||
|
||||
# Create the listview for the calendar events.
|
||||
list_model = Gtk.ListStore(str)
|
||||
list_view = Gtk.TreeView(list_model)
|
||||
list_column = Gtk.TreeViewColumn("Events", Gtk.CellRendererText(), text=0)
|
||||
list_column.set_fixed_width(window_width)
|
||||
list_view.append_column(list_column)
|
||||
|
||||
# Create the calendar widget.
|
||||
calendar = Gtk.Calendar()
|
||||
self.calendar_events = scan_org_for_events(org_directories)
|
||||
calendar.connect('month-changed', self.mark_calendar_events)
|
||||
calendar.connect('day-selected', self.display_event_list, list_model)
|
||||
self.mark_calendar_events(calendar)
|
||||
self.display_event_list(calendar, list_model)
|
||||
|
||||
close_button = Gtk.Button("Close")
|
||||
close_button.connect('clicked', lambda event: self.window.destroy())
|
||||
|
||||
vbox = Gtk.VBox()
|
||||
vbox.add(close_button)
|
||||
vbox.add(calendar)
|
||||
vbox.add(list_view)
|
||||
|
||||
self.window.add(vbox)
|
||||
|
||||
rootwin = self.window.get_screen().get_root_window()
|
||||
# get_pointer is deprecated but using Gdk.Device.get_position
|
||||
# is not viable here: we have no access to the pointing device.
|
||||
screen, x, y, mask = rootwin.get_pointer()
|
||||
x -= window_width
|
||||
# Show the window right beside the cursor.
|
||||
self.window.move(x,y)
|
||||
|
||||
self.window.show_all()
|
||||
|
||||
def mark_calendar_events(self, calendar):
|
||||
"""Update the days with calendar events list for the selected month."""
|
||||
year, month, day = calendar.get_date()
|
||||
calendar.freeze_notify()
|
||||
calendar.clear_marks()
|
||||
for day in self.calendar_events[year][month]:
|
||||
calendar.mark_day(day)
|
||||
calendar.thaw_notify()
|
||||
|
||||
def display_event_list(self, calendar, event_list):
|
||||
"""Update the calendar event list for the selected day."""
|
||||
year, month, day = calendar.get_date()
|
||||
event_list.clear()
|
||||
|
||||
# get(day) used instead of [day] because we use defaultdict
|
||||
# and it would create a new element.
|
||||
events = self.calendar_events[year][month].get(day)
|
||||
if events:
|
||||
for event in events:
|
||||
event_list.append([event])
|
||||
|
||||
|
||||
def tray_mode(org_directories):
|
||||
def on_left_click(event):
|
||||
window = CalendarWindow(org_directories)
|
||||
def on_right_click(button, time, data):
|
||||
Gtk.main_quit()
|
||||
statusicon = Gtk.StatusIcon()
|
||||
statusicon.set_from_icon_name('x-office-calendar')
|
||||
statusicon.connect('activate', on_left_click)
|
||||
statusicon.connect('popup-menu', on_right_click)
|
||||
Gtk.main()
|
||||
|
||||
def window_mode(org_directories):
|
||||
window = CalendarWindow(org_directories)
|
||||
window.window.connect('destroy', Gtk.main_quit)
|
||||
Gtk.main()
|
||||
|
||||
def main(argv=None):
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--no-tray",
|
||||
help="Show the calendar windows immediately and quit after it's closed.",
|
||||
action='store_true',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--org-directory", "-d",
|
||||
help="Directories to search for *.org; default: ~/org/.",
|
||||
action='append',
|
||||
dest='org_directories',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.org_directories:
|
||||
args.org_directories = [DEFAULT_ORG_DIRECTORY]
|
||||
|
||||
if args.no_tray:
|
||||
window_mode(args.org_directories)
|
||||
else:
|
||||
tray_mode(args.org_directories)
|
||||
|
||||
if __name__ == "__main__":
|
||||
from sys import argv
|
||||
|
||||
# workaround for a pygobject bug
|
||||
import signal
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
main(argv)
|
||||
@ -233,7 +233,7 @@
|
||||
#format-prefix-foreground = foreground_altcol;
|
||||
format-underline = "#0a6cf5";
|
||||
|
||||
label = "%date% %time%";
|
||||
label = "%{A1:${pkgs.tray-calendar}/bin/traycalendar --no-tray:}%{A} %date% %time%";
|
||||
};
|
||||
"module/battery" = {
|
||||
type = "internal/battery";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user