Skip to content

Commit

Permalink
Add Geany-Themes page with theme preview
Browse files Browse the repository at this point in the history
The themes in the preview list are loaded from the Geany-Themes
repository on Github on the fly (but cached for one hour).
  • Loading branch information
eht16 committed Jun 30, 2019
1 parent 0be9605 commit 6684928
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 7 deletions.
2 changes: 1 addition & 1 deletion geany/templates/home.html
Expand Up @@ -151,7 +151,7 @@ <h2 class="text-center">Great Community</h2>
<h2 class="text-center">Easily Customizable</h2>
<p>
Many parts of Geany are heavily customizable like color themes
(<a href="https://github.com/geany/geany-themes">Geany Themes project</a>) or
(<a href="{% url "page" "download/themes" %}">Geany Themes</a>) or
adding new filetypes.
</p>
<p>
Expand Down
10 changes: 10 additions & 0 deletions page_content/download/themes.md
@@ -0,0 +1,10 @@
## Geany Themes

Geany-Themes is a collection of color schemes for Geany, either written originally by the Geany community or ported from color schemes for other editors.
These schemes are compatible with Geany 1.22 and greater.

To use one the themes below, download the configuration file and save it to the folder `colorschemes` in your Geany configuration directory (usually `~/.config/geany/colorschemes/`).

For more information and detailed configuration instructions, see https://github.com/geany/geany-themes.


8 changes: 5 additions & 3 deletions static_docs/github_client.py
Expand Up @@ -30,9 +30,11 @@ class GitHubApiClient:
""""""

# ----------------------------------------------------------------------
def get_file_contents(self, filename):
url_parameters = dict(user=GITHUB_USER,
repository=GITHUB_REPOSITORY,
def get_file_contents(self, filename, user=None, repository=None):
user = user or GITHUB_USER
repository = repository or GITHUB_REPOSITORY
url_parameters = dict(user=user,
repository=repository,
filename=filename)
url = 'https://api.github.com/repos/%(user)s/%(repository)s/contents/%(filename)s' % \
url_parameters
Expand Down
63 changes: 63 additions & 0 deletions static_docs/templates/pages/download/themes.html
@@ -0,0 +1,63 @@
{% extends "pages/richtextpage.html" %}

{% load mezzanine_tags pages_tags static %}

{% block extra_css %}
<link rel="stylesheet" href="{% static "mezzanine/css/magnific-popup.css" %}">
<style>
.img-thumbnail {
cursor: zoom-in;
}
</style>
{% endblock %}

{% block richtext_content %}
{{ block.super }}

<h3>Available Themes</h3>

<div class="row">

{% for theme in theme_index.values|dictsort:"name" %}
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<strong>{{ theme.name }}</strong>
<span class="pull-right"><a href="{{ theme.colorscheme }}">Download</a></span>
</div>
<div class="panel-body gallery">
<a href="{{ theme.screenshot }}" title="{{ theme.name }} - {{ theme.description }}">
<img
src="data:image/png;base64,{{ theme.thumbnail }}"
class="img-responsive img-thumbnail center-block"
alt="Thumbnail of colorscheme {{ theme.name }}" />
</a>
<div class="text-center">{{ theme.description }}</div>
</div>
</div>
</div>

{% if forloop.counter|divisibleby:3 %}
</div>
<div class="row">
{% endif %}
{% endfor %}
</div>

{% endblock %}

{% block extra_js %}
{{ block.super }}
<script src="{% static "mezzanine/js/magnific-popup.js" %}"></script>
<script>
$(document).ready(function() {
$('.gallery').magnificPopup({
delegate: 'a',
type: 'image',
gallery: {
enabled: true,
}
});
});
</script>
{% endblock %}
4 changes: 3 additions & 1 deletion static_docs/urls.py
Expand Up @@ -14,10 +14,12 @@

from django.conf.urls import url

from static_docs.views import I18NStatisticsView, ReleaseNotesView, ToDoView
from static_docs.views import I18NStatisticsView, ReleaseNotesView, ThemesView, ToDoView


urlpatterns = ( # pylint: disable=invalid-name
url(r'^download/themes/$', ThemesView.as_view(), name='themes'),

url(r'^documentation/todo/$', ToDoView.as_view(), name='todo'),

url(r'^documentation/releasenotes/$', ReleaseNotesView.as_view(), name='releasenotes'),
Expand Down
64 changes: 62 additions & 2 deletions static_docs/views.py
Expand Up @@ -19,6 +19,7 @@
import re

from django.conf import settings
from django.core.cache import cache
from django.http import Http404
from django.views.generic.base import TemplateView
from mezzanine_pagedown.filters import plain as markdown_plain
Expand All @@ -30,6 +31,9 @@
RELEASE_REGEXP = re.compile(r'^Geany (?P<version>[0-9\.]+) \((?P<date>.*)\)$')
DATE_PATTERNS_TO_BE_IGNORED = ('TBD', 'TBA', 'unreleased')

CACHE_KEY_THEME_INDEX_MD5_HASH = 'THEME_INDEX_MD5_HASH'
CACHE_KEY_THEME_INDEX = 'THEME_INDEX'

logger = logging.getLogger(__name__) # pylint: disable=invalid-name


Expand All @@ -56,9 +60,9 @@ def __init__(self, *args, **kwargs):
self._file_contents = None

# ----------------------------------------------------------------------
def _fetch_file_via_github_api(self, filename):
def _fetch_file_via_github_api(self, filename, user=None, repository=None):
client = GitHubApiClient()
self._file_contents = client.get_file_contents(filename)
self._file_contents = client.get_file_contents(filename, user=user, repository=repository)


class ReleaseNotesView(StaticDocsView):
Expand Down Expand Up @@ -240,3 +244,59 @@ def _get_i18n_statistics(self):
settings.STATIC_DOCS_GEANY_I18N_STATISTICS_FILENAME)
with open(filename) as input_file:
return json.load(input_file)


class ThemesView(StaticDocsView):
"""
Fetch the Geany-Themes index from https://github.com/geany/geany-themes/tree/master/index
"""

template_name = "pages/download/themes.html"

# ----------------------------------------------------------------------
def get_context_data(self, **kwargs):
theme_index = self._get_theme_index()
context = super(ThemesView, self).get_context_data(**kwargs)
context['theme_index'] = theme_index
return context

# ----------------------------------------------------------------------
def _get_theme_index(self):
"""
Refresh the theme index by:
- querying the MD5 hash from Github
- compare the freshly retrieved MD5 hash against the cached one
- load the whole theme index if:
- the MD5 hashes differ
- the MD5 hash was not retrieved yet or has been expired from cache
- the theme index was not retrieved yet or has been expired from cache
- after loading the whole theme index cache it long (24 hours)
- store the freshly retrieved MD5 hash in the cache
"""
theme_index_md5_hash = self._query_theme_index_md5_hash()
cached_theme_index_md5_hash = cache.get(CACHE_KEY_THEME_INDEX_MD5_HASH)
theme_index = cache.get(CACHE_KEY_THEME_INDEX)

# theme index has been changed remotely?
if theme_index_md5_hash != cached_theme_index_md5_hash or theme_index is None:
logger.debug('Refresh theme index from Github (MD5: {})'.format(theme_index_md5_hash))
# query whole theme index
theme_index = self._query_parse_themes_index()
# cache it for later
cache.set(CACHE_KEY_THEME_INDEX, theme_index, CACHE_TIMEOUT_24HOURS)

# cache MD5 hash
cache.set(CACHE_KEY_THEME_INDEX_MD5_HASH, theme_index_md5_hash, CACHE_TIMEOUT_24HOURS)

return theme_index

# ----------------------------------------------------------------------
def _query_theme_index_md5_hash(self):
self._fetch_file_via_github_api('index/index.json.md5', repository='geany-themes')
return self._file_contents.strip()

# ----------------------------------------------------------------------
def _query_parse_themes_index(self):
self._fetch_file_via_github_api('index/index.json', repository='geany-themes')
theme_index = json.loads(self._file_contents)
return theme_index

0 comments on commit 6684928

Please sign in to comment.