Skip to content

Commit

Permalink
Merge pull request #8 from geany/issue5_geany_themes_preview
Browse files Browse the repository at this point in the history
Add Geany-Themes page with theme preview
  • Loading branch information
eht16 committed Jun 30, 2019
2 parents a6909bc + 52941f9 commit 1ab6c22
Show file tree
Hide file tree
Showing 6 changed files with 153 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.


17 changes: 14 additions & 3 deletions static_docs/github_client.py
Expand Up @@ -30,15 +30,18 @@ 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
with requests.get(url, timeout=HTTP_REQUEST_TIMEOUT, stream=False) as response:
response_json = response.json()
self._log_rate_limit(response)
self._log_request(response)

# parse response
return self._parse_fetch_file_response(response_json)
Expand All @@ -49,6 +52,14 @@ def _log_rate_limit(self, response):
rate_limit = response.headers['X-RateLimit-Limit']
logger.info('Github rate limits: %s/%s', rate_limit_remaining, rate_limit)

# ----------------------------------------------------------------------
def _log_request(self, response):
logger.info(
'Requesting "{} {}" took {}s'.format(
response.request.method,
response.request.url,
response.elapsed.total_seconds()))

# ----------------------------------------------------------------------
def _parse_fetch_file_response(self, response_json):
content = response_json['content']
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 1ab6c22

Please sign in to comment.