summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRory MacQueen <rorymacqueen@gmail.com>2013-07-19 16:47:09 -0700
committerPhilip Chimento <philip.chimento@gmail.com>2013-07-26 17:31:33 -0700
commit5852d75773d72d75995d07b3bc87f9e744b5f1b5 (patch)
treeb773ffc22679a67756505b34c9d004b79fe3e2ec
parentae9928b88ac2bcc82921e04e8cf4df5e18be174d (diff)
Moved wikipedia source files into sdk
Moved the wikipedia source files into the sdk repo since they will be eventually be shared by many apps [endlessm/eos-sdk#162]
-rw-r--r--wikipedia/Makefile.am52
-rw-r--r--wikipedia/README.md4
-rwxr-xr-xwikipedia/autogen.sh40
-rw-r--r--wikipedia/commit-msg16
-rw-r--r--wikipedia/configure.ac69
-rw-r--r--wikipedia/data/category_images/cuisine.jpgbin0 -> 83940 bytes
-rw-r--r--wikipedia/data/category_images/history.jpgbin0 -> 24291 bytes
-rw-r--r--wikipedia/data/css/endless_brazil.css28
-rw-r--r--wikipedia/data/endless_brazil.gresource.xml9
-rw-r--r--wikipedia/m4/as-linguas.m426
-rw-r--r--wikipedia/po/Makevars41
-rw-r--r--wikipedia/po/POTFILES.in1
-rw-r--r--wikipedia/po/eos-brazil.pot0
-rw-r--r--wikipedia/src/endless_brazil.js17
-rw-r--r--wikipedia/src/endless_wikipedia/ArticleList.js50
-rw-r--r--wikipedia/src/endless_wikipedia/BackButton.js18
-rw-r--r--wikipedia/src/endless_wikipedia/CategoryButton.js125
-rw-r--r--wikipedia/src/endless_wikipedia/CategorySelector.js39
-rw-r--r--wikipedia/src/endless_wikipedia/EndlessWikipedia.js31
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js87
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js85
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js67
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js127
-rw-r--r--wikipedia/src/endless_wikipedia/WikipediaApplication.js85
-rw-r--r--wikipedia/src/endless_wikipedia/models/WikipediaModel.js59
25 files changed, 1076 insertions, 0 deletions
diff --git a/wikipedia/Makefile.am b/wikipedia/Makefile.am
new file mode 100644
index 0000000..5cb2c94
--- /dev/null
+++ b/wikipedia/Makefile.am
@@ -0,0 +1,52 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright 2013 Endless Mobile, Inc.
+
+## -----------
+## Makefile.am
+## -----------
+## Please keep this file well-commented.
+
+# Subdirectories where we also want to run make
+SUBDIRS = po
+
+# Our Autoconf macros are kept in the m4/ directory
+ACLOCAL_AMFLAGS = -I m4
+
+# Generated files that 'make clean' should erase
+CLEANFILES =
+DISTCLEANFILES =
+EXTRA_DIST =
+
+# # # BUILD RULES # # #
+
+resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/data --generate-dependencies $(srcdir)/data/endless_brazil.gresource.xml)
+data/endless_brazil.gresource: data/endless_brazil.gresource.xml $(resource_files)
+ $(AM_V_GEN) $(MKDIR_P) $(builddir)/data && \
+ $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/data $<
+CLEANFILES += data/endless_brazil.gresource
+
+eos-brazil: Makefile
+ echo "gjs $(pkgdatadir)/src/endless_brazil.js" >$@
+CLEANFILES += eos-brazil
+
+# # # INSTALL RULES # # #
+
+js_sources = \
+ src/endless_brazil.js \
+ src/endless_wikipedia/EndlessWikipedia.js \
+ src/endless_wikipedia/PrebuiltWikipediaApplication.js \
+ $(NULL)
+nobase_pkgdata_DATA = \
+ data/endless_brazil.gresource \
+ $(js_sources) \
+ $(NULL)
+bin_SCRIPTS = eos-brazil
+
+EXTRA_DIST += \
+ $(js_sources) \
+ $(resource_files) \
+ data/endless_brazil.gresource.xml \
+ $(NULL)
+
+# # # TESTS # # #
diff --git a/wikipedia/README.md b/wikipedia/README.md
new file mode 100644
index 0000000..efcaa65
--- /dev/null
+++ b/wikipedia/README.md
@@ -0,0 +1,4 @@
+eos-wikipedia-brazil
+====================
+
+Brazil application based on the wikipedia database
diff --git a/wikipedia/autogen.sh b/wikipedia/autogen.sh
new file mode 100755
index 0000000..b8e046a
--- /dev/null
+++ b/wikipedia/autogen.sh
@@ -0,0 +1,40 @@
+# Bootstrap script for Endless Programming app
+# Run this script on a clean source checkout to get ready for building.
+
+FILE_MUST_EXIST=src/endless_brazil.js
+POT_FILE=po/eos-brazil.pot
+
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+olddir=`pwd`
+
+cd $srcdir
+test -f $FILE_MUST_EXIST || {
+ echo "You must run this script in the top-level checkout directory"
+ exit 1
+}
+
+# Install our commit message script if a git repo
+if [ -d .git ]; then
+ cp commit-msg .git/hooks/commit-msg
+ chmod +x .git/hooks/commit-msg
+fi
+
+# GNU gettext automake support doesn't get along with git
+# https://bugzilla.gnome.org/show_bug.cgi?id=661128
+touch -t 200001010000 $POT_FILE
+
+# NOCONFIGURE is used by gnome-common
+if test -z "$NOCONFIGURE"; then
+ echo "This script will run ./configure automatically. If you wish to pass "
+ echo "any arguments to it, please specify them on the $0 "
+ echo "command line. To disable this behavior, have NOCONFIGURE=1 in your "
+ echo "environment."
+fi
+
+# Run the actual tools to prepare the clean checkout
+autoreconf -fi || exit $?
+rm -f po/Makevars.template
+
+cd "$olddir"
+test -n "$NOCONFIGURE" || "./configure" "$@"
diff --git a/wikipedia/commit-msg b/wikipedia/commit-msg
new file mode 100644
index 0000000..7e5992f
--- /dev/null
+++ b/wikipedia/commit-msg
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# move this script to the .git/hooks directory for your repo.
+# make sure to chmod +x .git/hooks/commit-msg
+
+repo=$(basename `git rev-parse --show-toplevel`)
+branch=`git rev-parse --abbrev-ref HEAD`
+
+if [[ $branch == issues/* ]]; then
+ issue=$(echo "$branch" | awk -F/ '{ print $2 }')
+ link="[endlessm/$repo#$issue]"
+ echo "issue link: $link"
+ echo $link >> $1
+fi
+
+exit 0
diff --git a/wikipedia/configure.ac b/wikipedia/configure.ac
new file mode 100644
index 0000000..edb9dad
--- /dev/null
+++ b/wikipedia/configure.ac
@@ -0,0 +1,69 @@
+dnl Process this file with autoconf to produce configure
+
+# Copyright 2013 Endless Mobile, Inc.
+
+dnl ------------
+dnl configure.ac
+dnl ------------
+dnl Please keep this file well-commented. Autotools involve a lot of magical
+dnl incantations, and it is easy to mess things up if you don't know what you
+dnl are doing.
+
+# Initialization
+# --------------
+# Initialize Autoconf: package name, version, bug report address, tarball name,
+# website
+AC_INIT([Endless Brazil], [0],
+ [], [eos-brazil], [http://endlessm.com])
+# Initialize Automake: enable all warnings and do not insist on GNU standards
+# no-portability suppresses warnings about syntax specific to GNU make
+AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign 1.11])
+# Avoid spewing garbage over the terminal ('make V=1' to see the garbage)
+AM_SILENT_RULES([yes])
+# Keep Autotools macros local to this source tree
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_CACHE_SAVE
+
+# Required versions of libraries
+# Update these whenever you use a function that requires a certain API version
+EOS_SDK_REQUIREMENT="endless-0"
+
+# Gettext package name
+GETTEXT_PACKAGE=$PACKAGE
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, ["$GETTEXT_PACKAGE"],
+ [Package name for Gettext])
+# Detect which languages are available
+AS_ALL_LINGUAS
+
+# Required build tools
+# --------------------
+# Make sure we can create directory hierarchies
+AC_PROG_MKDIR_P
+# Library configuration tool
+PKG_PROG_PKG_CONFIG
+# Gettext
+AM_GNU_GETTEXT([external])
+AM_GNU_GETTEXT_VERSION([0.18.1])
+# Various tools
+GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0`
+AC_SUBST(GLIB_COMPILE_RESOURCES)
+
+AC_CACHE_SAVE
+
+# Required libraries
+# ------------------
+PKG_CHECK_MODULES([EOS_BRAZIL], [$EOS_SDK_REQUIREMENT])
+
+AC_CACHE_SAVE
+
+# Output
+# ------
+# List files here that the configure script should output
+AC_CONFIG_FILES([
+ Makefile
+ po/Makefile.in
+])
+# Do the output
+AC_OUTPUT
diff --git a/wikipedia/data/category_images/cuisine.jpg b/wikipedia/data/category_images/cuisine.jpg
new file mode 100644
index 0000000..860ec32
--- /dev/null
+++ b/wikipedia/data/category_images/cuisine.jpg
Binary files differ
diff --git a/wikipedia/data/category_images/history.jpg b/wikipedia/data/category_images/history.jpg
new file mode 100644
index 0000000..57bab62
--- /dev/null
+++ b/wikipedia/data/category_images/history.jpg
Binary files differ
diff --git a/wikipedia/data/css/endless_brazil.css b/wikipedia/data/css/endless_brazil.css
new file mode 100644
index 0000000..42d8382
--- /dev/null
+++ b/wikipedia/data/css/endless_brazil.css
@@ -0,0 +1,28 @@
+* {
+ font-family: "Benton Sans";
+}
+
+.title {
+ font-size: 48pt;
+}
+
+.title.category.front-page {
+ font-size: 36pt;
+ color: #a0a0a0;
+}
+
+Gjs_ArticleList .button {
+ border-top: 1px solid #555753;
+ padding: 10px;
+ background-color: #d3d7cf;
+ color: black;
+}
+
+Gjs_ArticleList .button:hover {
+ color: #555753;
+}
+
+.articles-page {
+ color: black;
+ background-color: #babdb6;
+} \ No newline at end of file
diff --git a/wikipedia/data/endless_brazil.gresource.xml b/wikipedia/data/endless_brazil.gresource.xml
new file mode 100644
index 0000000..7b9f502
--- /dev/null
+++ b/wikipedia/data/endless_brazil.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/com/endlessm/brazil">
+ <file compressed="true">brazil_categories.json</file>
+ <file compressed="true">css/endless_brazil.css</file>
+ <file>category_images/cuisine.jpg</file>
+ <file>category_images/history.jpg</file>
+ </gresource>
+</gresources>
diff --git a/wikipedia/m4/as-linguas.m4 b/wikipedia/m4/as-linguas.m4
new file mode 100644
index 0000000..8b4e07f
--- /dev/null
+++ b/wikipedia/m4/as-linguas.m4
@@ -0,0 +1,26 @@
+# Set ALL_LINGUAS based on the .po files present. Optional argument is the
+# name of the po directory. $podir/LINGUAS.ignore can be used to ignore a
+# subset of the po files.
+
+# Public domain, according to Emmanuele
+
+AC_DEFUN([AS_ALL_LINGUAS],
+[
+ AC_MSG_CHECKING([for linguas])
+ podir="m4_default([$1],[$srcdir/po])"
+ linguas=`cd $podir && ls *.po 2>/dev/null | awk 'BEGIN { FS="."; ORS=" " } { print $[]1 }'`
+ if test -f "$podir/LINGUAS.ignore"; then
+ ALL_LINGUAS="";
+ ignore_linguas=`sed -n -e 's/^\s\+\|\s\+$//g' -e '/^#/b' -e '/\S/!b' \
+ -e 's/\s\+/\n/g' -e p "$podir/LINGUAS.ignore"`;
+ for lang in $linguas; do
+ if ! echo "$ignore_linguas" | grep -q "^${lang}$"; then
+ ALL_LINGUAS="$ALL_LINGUAS $lang";
+ fi;
+ done;
+ else
+ ALL_LINGUAS="$linguas";
+ fi;
+ AC_SUBST([ALL_LINGUAS])
+ AC_MSG_RESULT($ALL_LINGUAS)
+])
diff --git a/wikipedia/po/Makevars b/wikipedia/po/Makevars
new file mode 100644
index 0000000..095c32a
--- /dev/null
+++ b/wikipedia/po/Makevars
@@ -0,0 +1,41 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
+# package. (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.) Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright. The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Endless Mobile, Inc.
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+# in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+# understood.
+# - Strings which make invalid assumptions about notation of date, time or
+# money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = philip@endlessm.com
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used. It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
diff --git a/wikipedia/po/POTFILES.in b/wikipedia/po/POTFILES.in
new file mode 100644
index 0000000..fc8cc34
--- /dev/null
+++ b/wikipedia/po/POTFILES.in
@@ -0,0 +1 @@
+src/endless_wikipedia/PrebuiltWikipediaApplication.js \ No newline at end of file
diff --git a/wikipedia/po/eos-brazil.pot b/wikipedia/po/eos-brazil.pot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wikipedia/po/eos-brazil.pot
diff --git a/wikipedia/src/endless_brazil.js b/wikipedia/src/endless_brazil.js
new file mode 100644
index 0000000..21726fd
--- /dev/null
+++ b/wikipedia/src/endless_brazil.js
@@ -0,0 +1,17 @@
+const Endless = imports.gi.Endless;
+const Gdk = imports.gi.Gdk;
+const Gio = imports.gi.Gio;
+const Gtk = imports.gi.Gtk;
+
+// Local imports
+imports.searchPath.unshift(Endless.getCurrentFileDir());
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+// Load GResource bundle
+let resource = Gio.Resource.load(Endless.getCurrentFileDir() + '/../data/endless_brazil.gresource');
+resource._register();
+
+let app = new EndlessWikipedia.PrebuiltWikipediaApplication({
+ categories_uri: 'resource:///com/endlessm/brazil/brazil_categories.json'
+});
+app.run(ARGV);
diff --git a/wikipedia/src/endless_wikipedia/ArticleList.js b/wikipedia/src/endless_wikipedia/ArticleList.js
new file mode 100644
index 0000000..b79e2e8
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/ArticleList.js
@@ -0,0 +1,50 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const ArticleList = new Lang.Class({
+ Name: 'ArticleList',
+ Extends: Gtk.ScrolledWindow,
+ Signals: {
+ 'article-chosen': {
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_STRING]
+ }
+ },
+
+ _init: function(props) {
+ props = props || {};
+ props.hscrollbar_policy = Gtk.PolicyType.NEVER;
+ props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC,
+ this.parent(props);
+
+ this._grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.VERTICAL,
+ vexpand: true
+ });
+ this.add(this._grid);
+ },
+
+ // Takes a list of dictionaries with keys 'title' and 'url'
+ setArticles: function(articles) {
+ // Remove all existing article links
+ this._grid.get_children().forEach(function(element, index, obj) {
+ this._grid.remove(element);
+ }, this);
+
+ // Create new ones
+ articles.forEach(function(element, index, obj) {
+ var button = Gtk.Button.new_with_label(element.title.toUpperCase());
+ button.image = Gtk.Image.new_from_icon_name('go-next-symbolic',
+ Gtk.IconSize.BUTTON);
+ button.always_show_image = true; // Don't do this, see BackButton.js
+ button.image_position = Gtk.PositionType.RIGHT;
+ button.xalign = 0;
+
+ button.connect('clicked', Lang.bind(this, function() {
+ this.emit('article-chosen', element.title, element.url);
+ }));
+ button.show();
+ this._grid.add(button);
+ }, this);
+ }
+});
diff --git a/wikipedia/src/endless_wikipedia/BackButton.js b/wikipedia/src/endless_wikipedia/BackButton.js
new file mode 100644
index 0000000..cfb3155
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/BackButton.js
@@ -0,0 +1,18 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const BackButton = new Lang.Class({
+ Name: 'BackButton',
+ Extends: Gtk.Button,
+
+ _init: function(props) {
+ props = props || {};
+ props.image = Gtk.Image.new_from_icon_name('go-previous-symbolic',
+ Gtk.IconSize.BUTTON);
+ props.always_show_image = true;
+ // Don't do that. What should actually happen is the system-wide setting
+ // that controls whether buttons show images should be changed.
+ this.parent(props);
+ }
+});
diff --git a/wikipedia/src/endless_wikipedia/CategoryButton.js b/wikipedia/src/endless_wikipedia/CategoryButton.js
new file mode 100644
index 0000000..e1b428e
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/CategoryButton.js
@@ -0,0 +1,125 @@
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+function _resourceUriToPath(uri) {
+ if(uri.startsWith('resource://'))
+ return uri.slice('resource://'.length);
+ throw new Error('Resource URI did not start with "resource://"');
+}
+
+const CategoryButton = new Lang.Class({
+ Name: 'CategoryButton',
+ Extends: Gtk.EventBox,
+ Properties: {
+ // resource URI for the category's accompanying image
+ 'image-uri': GObject.ParamSpec.string('image-uri',
+ 'Image URI',
+ 'Resource URI for the image file accompanying the category',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ ''),
+
+ // Title of the category to display
+ 'category-title': GObject.ParamSpec.string('category-title',
+ 'Category title',
+ 'Display name for the category',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+ Signals: {
+ 'clicked': {}
+ },
+
+ _init: function(props) {
+ // Get ready for property construction
+ this._image_uri = null;
+ this._category_title = null;
+
+ this._overlay = new Gtk.Overlay();
+ this._eventbox = new Gtk.EventBox({
+ vexpand: false,
+ valign: Gtk.Align.END,
+ halign: Gtk.Align.FILL
+ })
+ this._label = new Gtk.Label({
+ halign: Gtk.Align.START
+ });
+ let context = this._label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_FRONT_PAGE);
+ this._image = new Gtk.Image({
+ expand: true,
+ halign: Gtk.Align.FILL,
+ valign: Gtk.Align.FILL
+ });
+
+ // Parent constructor sets all properties
+ this.parent(props);
+
+ // Put widgets together
+ this.add(this._overlay);
+ this._overlay.add(this._image);
+ this._eventbox.add(this._label);
+ this._overlay.add_overlay(this._eventbox);
+ this.show_all();
+
+ // Connect signals
+ this.connect('button-press-event',
+ Lang.bind(this, this._onButtonPress));
+ },
+
+ get image_uri() {
+ return this._image_uri;
+ },
+
+ set image_uri(value) {
+ this._image_uri = value;
+ if(this._image) {
+ let res_path = _resourceUriToPath(value);
+ let allocation = this.get_allocation();
+ this._updateImage(res_path, allocation.width, allocation.height);
+ }
+ },
+
+ get category_title() {
+ return this._category_title;
+ },
+
+ set category_title(value) {
+ this._category_title = value;
+ if(this._label)
+ this._label.set_text(value.toUpperCase());
+ },
+
+ // OVERRIDES
+
+ vfunc_size_allocate: function(allocation) {
+ this.parent(allocation);
+ this._updateImage(_resourceUriToPath(this._image_uri),
+ allocation.width, allocation.height);
+ },
+
+ // HANDLERS
+
+ _onButtonPress: function(widget, event) {
+ this.emit('clicked')
+ },
+
+ // PRIVATE
+
+ _updateImage: function(res_path, width, height) {
+ let [source_width, source_height] = [width, height];
+ if(width > height)
+ source_height = -1;
+ else
+ source_width = -1;
+ let source_pixbuf = GdkPixbuf.Pixbuf.new_from_resource_at_scale(res_path,
+ source_width, source_height, true);
+ let cropped_pixbuf = source_pixbuf.new_subpixbuf(0, 0, width, height);
+ this._image.set_from_pixbuf(cropped_pixbuf);
+ }
+});
diff --git a/wikipedia/src/endless_wikipedia/CategorySelector.js b/wikipedia/src/endless_wikipedia/CategorySelector.js
new file mode 100644
index 0000000..f5b7b14
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/CategorySelector.js
@@ -0,0 +1,39 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const CategoryButton = imports.endless_wikipedia.CategoryButton;
+
+const CategorySelector = new Lang.Class({
+ Name: 'CategorySelector',
+ Extends: Gtk.Grid,
+ Signals: {
+ 'category-chosen': {
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
+ }
+ },
+
+ _init: function(props) {
+ props = props || {};
+ props.row_homogeneous = true;
+ props.column_homogeneous = true;
+ this.parent(props);
+ },
+
+ // Takes an array of dictionaries with keys 'title' and 'image_uri'
+ setCategories: function(categories) {
+ categories.forEach(function(category, index, obj) {
+ let button = new CategoryButton.CategoryButton({
+ category_title: category.title,
+ image_uri: category.image_uri
+ });
+ button.index = index;
+ button.connect('clicked', Lang.bind(this, this._onButtonClicked));
+ this.add(button);
+ }, this);
+ },
+
+ _onButtonClicked: function(button) {
+ this.emit('category-chosen', button.category_title, button.index);
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/src/endless_wikipedia/EndlessWikipedia.js b/wikipedia/src/endless_wikipedia/EndlessWikipedia.js
new file mode 100644
index 0000000..0f12986
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/EndlessWikipedia.js
@@ -0,0 +1,31 @@
+const _WikipediaApplication = imports.endless_wikipedia.WikipediaApplication;
+this.WikipediaApplication = _WikipediaApplication.WikipediaApplication;
+
+const _PrebuiltWikipediaApplication = imports.endless_wikipedia.PrebuiltWikipediaApplication;
+this.PrebuiltWikipediaApplication = _PrebuiltWikipediaApplication.PrebuiltWikipediaApplication;
+
+const _PrebuiltFrontPage = imports.endless_wikipedia.PrebuiltFrontPage;
+this.PrebuiltFrontPage = _PrebuiltFrontPage.PrebuiltFrontPage;
+
+const _PrebuiltCategoryPage = imports.endless_wikipedia.PrebuiltCategoryPage;
+this.PrebuiltCategoryPage = _PrebuiltCategoryPage.PrebuiltCategoryPage;
+
+const _PrebuiltArticlesPage = imports.endless_wikipedia.PrebuiltArticlesPage;
+this.PrebuiltArticlesPage = _PrebuiltArticlesPage.PrebuiltArticlesPage;
+
+const _CategorySelector = imports.endless_wikipedia.CategorySelector;
+this.CategorySelector = _CategorySelector.CategorySelector;
+
+const _ArticleList = imports.endless_wikipedia.ArticleList;
+this.ArticleList = _ArticleList.ArticleList;
+
+const _BackButton = imports.endless_wikipedia.BackButton;
+this.BackButton = _BackButton.BackButton;
+
+const STYLE_CLASS_TITLE = 'title';
+const STYLE_CLASS_PREBUILT = 'prebuilt';
+const STYLE_CLASS_CATEGORY = 'category';
+const STYLE_CLASS_ARTICLE = 'article';
+const STYLE_CLASS_FRONT_PAGE = 'front-page';
+const STYLE_CLASS_CATEGORY_PAGE = 'category-page';
+const STYLE_CLASS_ARTICLES_PAGE = 'articles-page';
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js b/wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js
new file mode 100644
index 0000000..12d9b45
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js
@@ -0,0 +1,87 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const PrebuiltArticlesPage = new Lang.Class({
+ Name: 'PrebuiltArticlesPage',
+ Extends: Gtk.Frame,
+ Properties: {
+ 'title': GObject.ParamSpec.string('title',
+ 'Article title',
+ 'Human-readable title for the article to be displayed',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ ''),
+ 'article-uri': GObject.ParamSpec.string('article-uri',
+ 'Article URI',
+ 'Last component of the Wikipedia URI for the article',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+
+ _init: function(props) {
+ this._title = null;
+ this._article_uri = null;
+
+ // Create widgets
+ this._grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.VERTICAL,
+ expand: true
+ });
+ this._title_label = new Gtk.Label({
+ vexpand: false,
+ halign: Gtk.Align.START
+ });
+ this._separator = new Gtk.Separator({
+ orientation: Gtk.Orientation.HORIZONTAL,
+ vexpand: false
+ });
+ this._wiki_view = new Gtk.Label({
+ vexpand: true
+ });
+
+ this.parent(props);
+
+ this._grid.add(this._title_label);
+ this._grid.add(this._separator);
+ this._grid.add(this._wiki_view);
+ this.add(this._grid);
+
+ // Add style contexts for CSS
+ let context = this._title_label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_PREBUILT);
+ let context = this._separator.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ let context = this._wiki_view.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ let context = this.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(value) {
+ this._title = value;
+ if(this._title_label)
+ this._title_label.label = value.toUpperCase();
+ },
+
+ get article_uri() {
+ return this._article_uri;
+ },
+
+ set article_uri(value) {
+ this._article_uri = value;
+ if(this._wiki_view)
+ this._wiki_view.label = 'This is a "webview" displaying the ' +
+ 'article http://en.wikipedia.org/wiki/%s'.format(value);
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js b/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js
new file mode 100644
index 0000000..3831c63
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js
@@ -0,0 +1,85 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const PrebuiltCategoryPage = new Lang.Class({
+ Name: 'PrebuiltCategoryPage',
+ Extends: Gtk.Frame,
+ Properties: {
+ 'title': GObject.ParamSpec.string('title',
+ 'Name of category',
+ 'Name of the category to be displayed at the top of the category page',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ ''),
+ 'description': GObject.ParamSpec.string('description',
+ 'Description',
+ 'Description of the category (excerpt from Wiki text)',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+
+ _init: function(props) {
+ this._title = null;
+ this._description = null;
+
+ this._grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.VERTICAL,
+ expand: true
+ });
+ this._title_label = new Gtk.Label({
+ vexpand: false,
+ halign: Gtk.Align.START
+ });
+ this._separator = new Gtk.Separator({
+ orientation: Gtk.Orientation.HORIZONTAL,
+ vexpand: false
+ });
+ this._description_label = new Gtk.Label({
+ valign: Gtk.Align.START,
+ halign: Gtk.Align.START
+ });
+
+ this.parent(props);
+
+ this._grid.add(this._title_label);
+ this._grid.add(this._separator);
+ this._grid.add(this._description_label);
+ this.add(this._grid);
+
+ let context = this._title_label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_PREBUILT);
+ let context = this._separator.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ let context = this._description_label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ let context = this.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(value) {
+ this._title = value;
+ if(this._title_label)
+ this._title_label.label = value.toUpperCase();
+ },
+
+ get description() {
+ return this._description;
+ },
+
+ set description(value) {
+ this._description = value;
+ if(this._description_label)
+ this._description_label.label = value;
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js b/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js
new file mode 100644
index 0000000..fed6a75
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js
@@ -0,0 +1,67 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const PrebuiltFrontPage = new Lang.Class({
+ Name: 'PrebuiltFrontPage',
+ Extends: Gtk.Grid,
+ Properties: {
+ 'title': GObject.ParamSpec.string('title',
+ 'Front page title',
+ 'Name of the Wikipedia-based application',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+ Signals: {
+ 'category-chosen': {
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
+ }
+ },
+
+ _init: function(props) {
+ this._title = null;
+
+ this._title_label = new Gtk.Label({
+ expand: true,
+ halign: Gtk.Align.START,
+ valign: Gtk.Align.END
+ });
+ let context = this._title_label.get_style_context()
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_PREBUILT);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_FRONT_PAGE);
+ this._category_selector = new EndlessWikipedia.CategorySelector();
+
+ props = props || {};
+ props.orientation = Gtk.Orientation.VERTICAL;
+ this.parent(props);
+
+ this.add(this._title_label);
+ this.add(this._category_selector);
+ this._category_selector.connect('category-chosen',
+ Lang.bind(this, this._onCategoryChosen));
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(value) {
+ this._title = value;
+ if(this._title_label)
+ this._title_label.label = value.toUpperCase();
+ },
+
+ setCategories: function(categories) {
+ this._category_selector.setCategories(categories);
+ },
+
+ // Proxy signal
+ _onCategoryChosen: function(widget, title, index) {
+ this.emit('category-chosen', title, index);
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js b/wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js
new file mode 100644
index 0000000..7b2ebbd
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js
@@ -0,0 +1,127 @@
+const Endless = imports.gi.Endless;
+const Format = imports.format;
+const Lang = imports.lang;
+const Gtk = imports.gi.Gtk;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+const _ = function(x) { return x; };
+
+String.prototype.format = Format.format;
+
+const PrebuiltWikipediaApplication = new Lang.Class({
+ Name: 'PrebuiltWikipediaApplication',
+ Extends: EndlessWikipedia.WikipediaApplication,
+
+ _init: function(props) {
+ this.parent(props);
+ },
+
+ vfunc_startup: function() {
+ this.parent();
+
+ // Front page
+ this._front_page = new EndlessWikipedia.PrebuiltFrontPage({
+ title: this.application_name
+ });
+ this._front_page.setCategories(this.getCategories());
+ this._front_page.connect('category-chosen',
+ Lang.bind(this, this._onCategoryClicked));
+
+ // Category page
+ this._category_page = new Gtk.Grid({
+ orientation: Gtk.Orientation.HORIZONTAL
+ });
+ this._category_view = new EndlessWikipedia.PrebuiltCategoryPage();
+ // _category_article_list is eventually going to be the same widget as
+ // _article_list, so that's why it's not built into the
+ // PrebuiltCategoryPage
+ this._category_article_list = new EndlessWikipedia.ArticleList({
+ halign: Gtk.Align.END,
+ hexpand: false
+ });
+ this._category_page.add(this._category_view);
+ this._category_page.add(this._category_article_list);
+
+ this._category_back_button = new EndlessWikipedia.BackButton({
+ label: _('START')
+ });
+ this._category_back_button.show();
+
+ this._category_article_list.connect('article-chosen',
+ Lang.bind(this, this._onArticleClicked));
+ this._category_back_button.connect('clicked',
+ Lang.bind(this, this._onCategoryBackClicked));
+
+ // Article page
+ this._article_page = new Gtk.Grid({
+ orientation: Gtk.Orientation.HORIZONTAL
+ });
+ this._article_view = new EndlessWikipedia.PrebuiltArticlesPage();
+ this._article_list = new EndlessWikipedia.ArticleList({
+ halign: Gtk.Align.START,
+ hexpand: false
+ });
+ this._article_page.add(this._article_list);
+ this._article_page.add(this._article_view);
+
+ this._article_back_button = new EndlessWikipedia.BackButton();
+ this._article_back_button.show();
+
+ this._article_list.connect('article-chosen',
+ Lang.bind(this, this._onArticleClicked));
+ this._article_back_button.connect('clicked',
+ Lang.bind(this, this._onArticleBackClicked));
+
+ // Build window
+ this._window = new Endless.Window({
+ title: this.application_name,
+ application: this
+ });
+ this._window.page_manager.transition_duration = 200; // ms
+ this._window.page_manager.add(this._front_page, {
+ name: 'front'
+ });
+ this._window.page_manager.add(this._category_page, {
+ name: 'category',
+ left_topbar_widget: this._category_back_button
+ });
+ this._window.page_manager.add(this._article_page, {
+ name: 'article',
+ left_topbar_widget: this._article_back_button
+ })
+ this._window.show_all();
+ },
+
+ _onCategoryClicked: function(page, title, index) {
+ let category = this.getCategories()[index];
+ let articles = this.getArticlesForCategoryIndex(index);
+
+ this._category_view.title = category.title;
+ this._category_view.description = category.content;
+ this._category_article_list.setArticles(articles);
+ this._article_list.setArticles(articles);
+ this._article_back_button.label = category.title.toUpperCase();
+
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_LEFT;
+ this._window.page_manager.visible_page_name = 'category';
+ },
+
+ _onArticleClicked: function(article_list, title, uri) {
+ this._article_view.title = title;
+ this._article_view.article_uri = uri;
+
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_LEFT;
+ this._window.page_manager.visible_page_name = 'article';
+ },
+
+ _onCategoryBackClicked: function(button) {
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_RIGHT;
+ this._window.page_manager.visible_page_name = 'front';
+ },
+
+ _onArticleBackClicked: function(button) {
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_RIGHT;
+ this._window.page_manager.visible_page_name = 'category';
+ }
+});
diff --git a/wikipedia/src/endless_wikipedia/WikipediaApplication.js b/wikipedia/src/endless_wikipedia/WikipediaApplication.js
new file mode 100644
index 0000000..b1cd6ff
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/WikipediaApplication.js
@@ -0,0 +1,85 @@
+const Lang = imports.lang;
+const GObject = imports.gi.GObject;
+const Gio = imports.gi.Gio;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const WikipediaApplication = new Lang.Class({
+ Name: 'WikipediaApplication',
+ Extends: Endless.Application,
+ Properties: {
+ // resource:// URI for the categories JSON file
+ 'categories-uri': GObject.ParamSpec.string('categories-uri',
+ 'Category file URI',
+ 'URI for the data file describing the categories and articles',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ ''),
+
+ // Name of the Wikipedia-based application, e.g. 'Brazil', 'Math'
+ 'application-name': GObject.ParamSpec.string('application-name',
+ 'Application name',
+ 'Name of the Wikipedia-based application',
+ GObject.ParamFlags.READABLE,
+ '')
+ },
+
+ _init: function(props) {
+ this._categories_uri = null;
+ this._categories = null;
+ this.parent(props);
+ },
+
+ // PROPERTIES
+
+ get categories_uri() {
+ return this._categories_uri;
+ },
+
+ set categories_uri(value) {
+ this._categories_uri = value;
+ },
+
+ get application_name() {
+ if(this._categories)
+ return this._categories.app_name;
+ return undefined;
+ },
+
+ // VIRTUAL FUNCTIONS
+
+ vfunc_startup: function() {
+ this.parent();
+
+ let category_file = Gio.File.new_for_uri(this.categories_uri);
+ let [success, category_json, etag] = category_file.load_contents(null);
+ this._categories = JSON.parse(category_json);
+
+ // Doesn't belong here
+ let provider = new Gtk.CssProvider();
+ let css_file = Gio.File.new_for_uri('resource:///com/endlessm/brazil/css/endless_brazil.css')
+ provider.load_from_file(css_file);
+ Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+ },
+
+ // PUBLIC API
+
+ getCategories: function() {
+ let category_list = this._categories.categories.map(function(element, index, obj) {
+ return {
+ title: element.category_name,
+ image_uri: element.image_uri,
+ content: element.content_text
+ };
+ })
+ return category_list;
+ },
+
+ getArticlesForCategory: function(category_title) {
+ //...
+ },
+
+ getArticlesForCategoryIndex: function(index) {
+ return this._categories.categories[index].articles;
+ }
+
+});
diff --git a/wikipedia/src/endless_wikipedia/models/WikipediaModel.js b/wikipedia/src/endless_wikipedia/models/WikipediaModel.js
new file mode 100644
index 0000000..d6660b8
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/models/WikipediaModel.js
@@ -0,0 +1,59 @@
+const Endless = imports.gi.Endless;
+const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
+const Json = imports.gi.Json;
+const Lang = imports.lang;
+
+// Local libraries
+//const CategoryModel = imports.models.category_model;
+const JsonUtils = imports.models.utils.json_utils;
+
+const CONTENT_DIRECTORY = Endless.getCurrentFileDir() + "/../../content/";
+const DEFAULT_METADATA_FILE = CONTENT_DIRECTORY + "metadata.json";
+
+const WikipediaModel = new Lang.Class({
+ Name: "WikipediaModel",
+ Extends: GObject.Object,
+
+ _init: function(f) {
+
+ let jsonFile;
+ jsonFile = f || DEFAULT_METADATA_FILE;
+
+ this._categories = new Array();
+
+ this.initFromJsonFile(jsonFile);
+ },
+
+ initFromJsonFile: function(theFile) {
+
+ let parser = new Json.Parser();
+
+ try {
+ parser.load_from_file(theFile);
+
+ let root = parser.get_root();
+ let reader = new Json.Reader();
+ reader.root = root;
+
+ reader.read_member("categories");
+ let categoryCount = reader.count_elements();
+ for(let i=0; i<categoryCount; i++) {
+ reader.read_element(i);
+ print("hello");
+ let vId = reader.get_string_value();
+ //let newCategory = new CategoryModel.CategoryModel({ id: vId });
+ //this._categories.push(newCategory);
+
+ reader.end_element();
+ }
+ reader.end_member();
+ } catch (e) {
+ throw e;
+ }
+ },
+
+ getCategories: function() {
+ return this._categories;
+ },
+});