-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First public release of Pygenda. Version 0.2.0.
- Loading branch information
0 parents
commit 82e15d6
Showing
46 changed files
with
10,524 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
Pygenda | ||
======= | ||
Pygenda is a calendar/agenda application written in Python3/GTK3 and | ||
designed for "PDA" devices such as Planet Computers' Gemini. The user | ||
interface is inspired by patterns in the Agenda programs on the Psion | ||
Series 3 and Series 5 range of PDAs. | ||
|
||
**WARNING: This is in-development code, released as a preview for | ||
developers. It will probably corrupt your data.** | ||
|
||
There are currently **lots of missing/incomplete features** as well as | ||
**bugs**. For a list of known issues, see: docs/known_issues.md | ||
|
||
Source code | ||
----------- | ||
Source is available at: https://github.com/semiprime/pygenda | ||
|
||
License | ||
------- | ||
Pygenda 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, version 3. | ||
|
||
Pygenda 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 Pygenda (see COPYING file). If not, see <https://www.gnu.org/licenses/>. | ||
|
||
Run/install | ||
----------- | ||
(See note about dependencies below.) | ||
|
||
To run without installing, cd to the root pygenda directory, and do: | ||
|
||
python3 -m pygenda | ||
|
||
(If you want to run this way using a graphical launcher, set the | ||
working directory in the launcher settings, and use the above command.) | ||
|
||
Better: install the python module with (for example)... | ||
|
||
./setup.py install --user | ||
|
||
(You can uninstall the module with `pip3 uninstall pygenda`.) | ||
|
||
NOTE: Gemian (Debian port for Gemini PDA) doesn't install the Python module | ||
dependencies. I recommend installing these dependencies manually - see | ||
below. The reason for this appears to be old pip/setuptools on Gemian. | ||
You can upgrade these using `pip3 install --upgrade [pip|setuptools]`, | ||
but that won't fix the install because pip3 tries to get a version of | ||
PyGObject that requires a more-recent-than-installed version of glib. | ||
|
||
Then you can run from anywhere with: | ||
|
||
python3 -m pygenda | ||
|
||
There are a few command-line options, which you can view using: | ||
|
||
python3 -m pygenda --help | ||
|
||
For more complete settings, see "Configuration", below. | ||
|
||
Dependencies | ||
------------ | ||
Python3. Version >=3.5 (because Gemini's "Gemian" Linux provides Python 3.5). | ||
|
||
* Install on Debian/Gemian: `sudo apt install python3` | ||
|
||
GTK+3 | ||
|
||
* Install on Debian: `sudo apt install gtk+3` | ||
|
||
Python3 modules: PyGObject3 (for gi), icalendar, python-dateutil | ||
|
||
* Install on Debian: `sudo apt install python3-gi python3-icalendar python3-dateutil` | ||
* Or install them using pip3: `pip3 install pygobject icalendar python-dateutil` | ||
|
||
That should be enough to start Pygenda, but if you want to use a | ||
CalDAV server (recommended for real use) there are some extra | ||
dependencies. See setup details in: docs/CalDAV.md | ||
|
||
Configuration | ||
------------- | ||
Configuration settings go in file: `~/.config/pygenda/pygenda.ini` | ||
|
||
Custom CSS goes in: `~/.config/pygenda/pygenda.css` | ||
|
||
More information: docs/config-examples/README.md | ||
|
||
Quick config on Gemini/other handhelds | ||
-------------------------------------- | ||
If you're running Pygenda on a Gemini or similar PDA, the default font | ||
sizes will probably not be appropriate for the screen size. To fix | ||
this, use the custom CSS provided in docs/config-examples/gemini.css. | ||
The easiest way to do this is to import the gemini.css file from your | ||
own ~/.config/pygenda/pygenda.css file, by adding the line: | ||
|
||
@import "PATH_TO_GEMINI_CSS_FILE"; | ||
|
||
You can then add your own custom CSS after this. (This way, if you | ||
git pull an update to the Pygenda source, then you'll automatically | ||
get any new css rules included in the new version.) | ||
|
||
The "startup/maximized" and "startup/fullscreen" options are also | ||
useful for devices with small screens. See "Configuation" above. | ||
|
||
Usage | ||
----- | ||
See: docs/Usage.md | ||
|
||
Calendar data storage - a CalDAV server is recommended | ||
------------------------------------------------------ | ||
Calendar data can be stored as an ICS file, or via a CalDAV server. | ||
The ICS file is the default, because it works without configuration, | ||
but a CalDAV server is recommended for real use. | ||
|
||
For CalDAV configuration, see: docs/CalDAV.md | ||
|
||
The default ICS file is created in `~/.config/pygenda/pygenda.ics` | ||
but you can change this from the command line or config file. | ||
|
||
Alternatives | ||
------------ | ||
If you want to compare the "competition", the Gemian people also have | ||
an in-development agenda-like app designed for the Gemini/Cosmo. | ||
Details at https://gemian.thinkglobally.org/#Calendar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
NAME = pygenda_clipboard | ||
|
||
SRC = $(NAME).c | ||
TARGET = lib$(NAME).so | ||
|
||
INCLUDE_DIR = /usr/include | ||
|
||
MACHINE = $(shell uname -m) | ||
|
||
ifeq ($(MACHINE), x86_64) | ||
INCLUDE_PLATFORM_DIR = /usr/lib64 | ||
else ifeq ($(MACHINE), aarch64) | ||
INCLUDE_PLATFORM_DIR = /usr/lib/aarch64-linux-gnu | ||
else | ||
INCLUDE_PLATFORM_DIR = /usr/lib | ||
endif | ||
|
||
CC_INCLUDE_DIRS = -I$(INCLUDE_DIR)/gtk-3.0 -I$(INCLUDE_DIR)/glib-2.0 -I$(INCLUDE_PLATFORM_DIR)/glib-2.0/include -I$(INCLUDE_DIR)/pango-1.0 -I$(INCLUDE_DIR)/harfbuzz -I$(INCLUDE_DIR)/cairo -I$(INCLUDE_DIR)/gdk-pixbuf-2.0 -I$(INCLUDE_DIR)/atk-1.0 | ||
|
||
# Targets... | ||
|
||
$(TARGET): $(SRC) | ||
gcc $(CC_INCLUDE_DIRS) -shared -o $(TARGET) -fPIC $(SRC) | ||
strip $(TARGET) | ||
|
||
cp: $(TARGET) | ||
cp $(TARGET) ../pygenda/ | ||
|
||
uninstall: | ||
rm -rf ../pygenda/$(TARGET) | ||
|
||
clean: | ||
rm -rf $(TARGET) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// pygenda_clipboard.c | ||
// | ||
// Small C library to interface Pygenda with GTK clipboard. | ||
// Allows agenda entries to be copied to the clipboard. | ||
// | ||
// Copyright (C) 2022 Matthew Lewis | ||
// | ||
// This file is part of Pygenda. | ||
// | ||
// Pygenda 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, version 3. | ||
// | ||
// Pygenda 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 Pygenda. If not, see <https://www.gnu.org/licenses/>. | ||
// | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <gtk/gtk.h> | ||
|
||
// Constants | ||
|
||
// Enumerated types of clipboard selection data we can store: | ||
#define DATA_TXT_PLAIN (0) | ||
#define DATA_TXT_CALENDAR (1) | ||
// Number of data types | ||
#define LEN_SELECTION_DATA (2) | ||
|
||
// Map requested types (strings) to our enumerated types | ||
GtkTargetEntry target_array[] = { | ||
{"text/plain;charset=utf-8", 0, DATA_TXT_PLAIN}, | ||
{"UTF8_STRING", 0, DATA_TXT_PLAIN}, | ||
{"TEXT", 0, DATA_TXT_PLAIN}, | ||
{"STRING", 0, DATA_TXT_PLAIN}, | ||
{"text/calendar", 0, DATA_TXT_CALENDAR} | ||
}; | ||
|
||
// Macro for length of target_array[] | ||
#define LEN_TARGET_ARRAY (sizeof(target_array)/sizeof(GtkTargetEntry)) | ||
|
||
// We store pointers to our data here: | ||
// Assume this are zero initialised | ||
char *selectionStr[LEN_SELECTION_DATA]; | ||
|
||
// Callback - called when data is requested | ||
// type_idx is set to enumerated value type | ||
void cb_get_fn(GtkClipboard* clipboard, GtkSelectionData* selection_data, guint type_idx, gpointer ptr) { | ||
switch(type_idx) { | ||
case DATA_TXT_PLAIN: | ||
gtk_selection_data_set_text(selection_data, selectionStr[DATA_TXT_PLAIN], -1); | ||
break; | ||
case DATA_TXT_CALENDAR: | ||
gtk_selection_data_set(selection_data, gdk_atom_intern("text/calendar", FALSE),8,selectionStr[type_idx], strlen(selectionStr[type_idx])); | ||
break; | ||
} | ||
} | ||
|
||
// Callback - called when data is no longer needed (e.g. something | ||
// else is copied) | ||
void cb_clear_fn(GtkClipboard* clipboard, gpointer ptr) { | ||
int i=0; | ||
for ( ; i<LEN_SELECTION_DATA ; i++) { | ||
free(selectionStr[i]); | ||
selectionStr[i] = NULL; | ||
} | ||
} | ||
|
||
// exported function used by pygenda | ||
void set_cb(char *txt, char* txtcal) { | ||
// Set callbacks for clipboard | ||
GtkClipboard *cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | ||
gtk_clipboard_set_with_data(cb, target_array, LEN_TARGET_ARRAY, cb_get_fn, cb_clear_fn, NULL); | ||
// cb_clear_fn() should have been called so pointers should be null here | ||
|
||
// Take copies of strings that we own here | ||
selectionStr[DATA_TXT_PLAIN] = malloc(strlen(txt)+1); | ||
strcpy(selectionStr[DATA_TXT_PLAIN],txt); | ||
selectionStr[DATA_TXT_CALENDAR] = malloc(strlen(txtcal)+1); | ||
strcpy(selectionStr[DATA_TXT_CALENDAR],txtcal); | ||
|
||
//gtk_clipboard_store(cb); // This doesn't seem to work?? | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
Pygenda CalDAV use & configuration | ||
================================== | ||
|
||
Data storage | ||
------------ | ||
Agenda data can be stored/accessed as an ICS file or via a CalDAV | ||
server. The ICS file is good for testing, but has a number of | ||
downsides: possible data loss if multiple programs try to write to the | ||
file, slowdown updating large agendas, and some planned features are | ||
only planned for the server. A server should be safer, and probably | ||
makes it easier to synchronise across devices (depending on the | ||
server's storage - maybe try rsync, git, syncEvolution, Outlook CalDav | ||
Synchronizer, vdirsyncer). A CalDAV server is recommended (I've only | ||
tried with a local server - a remote server should theoretically work, | ||
but it might be more practical to periodically sync a local server to | ||
the remote and access the local). | ||
|
||
(The ICS file option was implemented first during development, and | ||
left in because it's useful for testing, or for basic use if you're | ||
aware of the risks.) | ||
|
||
Extra dependencies if using CalDAV server | ||
----------------------------------------- | ||
Python3 modules: caldav | ||
|
||
pip3 install caldav # [there's probably an apt equivalent to this] | ||
|
||
N.B. The Python caldav module has dependencies outside Python: libxml2 | ||
& libxslt development. To install these on Debian/Gemian: | ||
|
||
sudo apt install libxml2-dev libxslt-dev | ||
|
||
Using the Radicale CalDAV server | ||
-------------------------------- | ||
You probably also want to install a CalDAV server. I tested using the | ||
Radicale CalDAV server (v3.0.6). https://radicale.org/ | ||
(Radicale is written in Python, so it fits the ongoing "Python" theme.) | ||
|
||
Install: | ||
|
||
pip3 install radicale | ||
|
||
[I use pip, rather than apt, here because on the Gemini PDA, using apt | ||
gets an older version of Radicale (v1.1.1) while pip gets v3.x. If | ||
you're using a more recent Debian, you might prefer apt.] | ||
|
||
Start Radicale: | ||
|
||
python3 -m radicale --storage-filesystem-folder=~/radicale-data | ||
|
||
[Change that filesystem path if you want.] | ||
|
||
Then go to the web interface in a web browser: http://localhost:5232/ | ||
|
||
Login with your username of choice - remember the username for Pygenda | ||
setup, below. (Note, by default the password is ignored - see the | ||
Radicale documentation for how to edit your radicale config to make | ||
this active - https://radicale.org/). | ||
|
||
Create an agenda (or import an existing one, or sync with a remote one). | ||
|
||
Edit/create your `~/.config/pygenda/pygenda.ini` file. Edit/add: | ||
|
||
[calendar] | ||
caldav_server=http://localhost:5232/ | ||
caldav_username=CALDAV_USERNAME | ||
# Optional: | ||
caldav_password=PASSWORD # Plaintext, so don't reuse your bank password... | ||
caldav_calendar=CALENDAR_NAME # Not needed if there's only one calendar | ||
|
||
If you're happy with Radicale, you can put your settings in | ||
`.config/radicale/config` and run radicale on startup. E.g. in LXQt on | ||
the Gemini, go to LXQT Configuration Center -> Session Settings -> | ||
Autostart, and add the command "`python3 -m radicale`". |
Oops, something went wrong.