diff options
author | Rory MacQueen <rorymacqueen@gmail.com> | 2013-07-19 16:47:09 -0700 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2013-07-26 17:31:33 -0700 |
commit | 5852d75773d72d75995d07b3bc87f9e744b5f1b5 (patch) | |
tree | b773ffc22679a67756505b34c9d004b79fe3e2ec | |
parent | ae9928b88ac2bcc82921e04e8cf4df5e18be174d (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]
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 Binary files differnew file mode 100644 index 0000000..860ec32 --- /dev/null +++ b/wikipedia/data/category_images/cuisine.jpg diff --git a/wikipedia/data/category_images/history.jpg b/wikipedia/data/category_images/history.jpg Binary files differnew file mode 100644 index 0000000..57bab62 --- /dev/null +++ b/wikipedia/data/category_images/history.jpg 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; + }, +}); |