AC_SUBST(GTK_CFLAGS)
AC_SUBST(GTK_LIBS)
+# Checks CURL
+PKG_CHECK_MODULES(CURL, libcurl )
+AC_SUBST(CURL_CFLAGS)
+AC_SUBST(CURL_LIBS)
+
# Check JSON
JSON_LIBS=
PKG_CHECK_MODULES(JSON, json)
AC_SUBST(JSON_CFLAGS)
AC_SUBST(JSON_LIBS)
+# Gsettings
+GLIB_GSETTINGS
+
+# Webkit
+PKG_CHECK_MODULES(WEBKIT, webkitgtk-3.0)
+AC_SUBST(WEBKIT_CFLAGS)
+AC_SUBST(WEBKIT_LIBS)
+
AC_CONFIG_FILES([
Makefile
po/Makefile.in
# -export-dynamic is need for defining handlers in the glade file.
AM_LDFLAGS = -Wl,--as-needed -export-dynamic
-AM_CPPFLAGS = -Wall -Werror $(GTK_CFLAGS) $(JSON_CFLAGS)
+AM_CPPFLAGS = -Wall -Werror $(CURL_CFLAGS) $(GTK_CFLAGS) $(JSON_CFLAGS) $(WEBKIT_CFLAGS)
DEFS = -DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" -DLOCALEDIR=\"$(localedir)\" @DEFS@
-LIBS = $(JSON_LIBS) $(GTK_LIBS)
+LIBS = $(CURL_LIBS) $(JSON_LIBS) $(GTK_LIBS) $(WEBKIT_LIBS)
bin_PROGRAMS = prss
-prss_SOURCES = main.c
+prss_SOURCES = main.c \
+ phttp.c \
+ phttp.h \
+ ttrss.c \
+ ttrss.h \
+ url.c \
+ url.h \
+ webbrowser.c \
+ webbrowser.h
+
+gsettings_SCHEMAS=prss.gschema.xml
+
+@GSETTINGS_RULES@
dist_man_MANS = prss.1
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="feed_store">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ <!-- column-name gpointer1 -->
+ <column type="gpointer"/>
+ </columns>
+ </object>
+ <object class="GtkListStore" id="headline_store">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ <!-- column-name gpointer1 -->
+ <column type="gpointer"/>
+ </columns>
+ </object>
<object class="GtkWindow" id="window">
<property name="can_focus">False</property>
+ <property name="title" translatable="yes">Pitchoune RSS</property>
+ <property name="default_width">800</property>
+ <property name="default_height">600</property>
<child>
- <placeholder/>
+ <object class="GtkPaned" id="paned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">200</property>
+ <property name="position_set">True</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="feed_tree">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">feed_store</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="fixed_height_mode">True</property>
+ <property name="enable_tree_lines">True</property>
+ <signal name="cursor-changed" handler="feed_cursor_changed_cbk" swapped="no"/>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <property name="resizable">True</property>
+ <property name="sizing">fixed</property>
+ <property name="fixed_width">100</property>
+ <property name="min_width">1</property>
+ <property name="title" translatable="yes">Feed</property>
+ <property name="expand">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext5"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkPaned" id="paned2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="orientation">vertical</property>
+ <property name="position">300</property>
+ <property name="position_set">True</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="headline_tree">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">headline_store</property>
+ <signal name="cursor-changed" handler="headline_cursor_changed_cbk" swapped="no"/>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <property name="spacing">3</property>
+ <property name="max_width">0</property>
+ <property name="title" translatable="yes">Headline</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="webkit_window">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
</child>
</object>
</interface>
#include <getopt.h>
#include <json/json.h>
-
+#include "ttrss.h"
+#include <webkit/webkit.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
+#include "phttp.h"
+#include "webbrowser.h"
+
static const char *program_name;
static struct option long_options[] = {
printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
}
+GtkTreeView *w_treeview;
+GtkTreeView *w_headlineview;
+
+void update()
+{
+ GSettings *settings;
+ struct feed **feeds;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ printf("update\n");
+ phttp_init();
+
+ settings = g_settings_new("prss");
+
+ ttrss_login(g_settings_get_string(settings, "url"),
+ g_settings_get_string(settings, "user"),
+ g_settings_get_string(settings, "password"));
+
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(w_treeview));
+ gtk_list_store_clear(GTK_LIST_STORE(model));
+
+ for (feeds = ttrss_get_feeds(); *feeds; feeds++) {
+ gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+
+ gtk_list_store_set(GTK_LIST_STORE(model),
+ &iter,
+ 0, (*feeds)->title,
+ 1, (*feeds),
+ -1);
+
+ printf("add\n");
+ }
+ printf("refresh done\n");
+}
+
+int feed_cursor_changed_cbk(GtkTreeView *treeview, gpointer data)
+{
+ printf("feed_cursor_changed_cbk\n");
+
+ GtkTreePath *path;
+ GtkTreeViewColumn *cols;
+ GtkTreeIter iter;
+ GtkTreeModel *model, *headline_model;
+ GtkListStore *headline_store;
+ struct feed *feed;
+ struct headline **headlines;
+
+ gtk_tree_view_get_cursor(treeview, &path, &cols);
+
+ if (path) {
+ model = gtk_tree_view_get_model(treeview);
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, 1, &feed, -1);
+
+ headline_model = gtk_tree_view_get_model(w_headlineview);
+ headline_store = GTK_LIST_STORE(headline_model);
+ gtk_list_store_clear(headline_store);
+ for (headlines = feed->headlines; *headlines; headlines++) {
+ gtk_list_store_append(headline_store, &iter);
+
+ gtk_list_store_set(headline_store,
+ &iter,
+ 0, (*headlines)->title,
+ 1, (*headlines),
+ -1);
+ }
+
+ gtk_tree_path_free(path);
+ }
+
+ return 1;
+}
+
+int headline_cursor_changed_cbk(GtkTreeView *treeview, gpointer data)
+{
+ printf("headline_cursor_changed_cbk\n");
+
+ GtkTreePath *path;
+ GtkTreeViewColumn *cols;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ struct headline *headline;
+
+ gtk_tree_view_get_cursor(treeview, &path, &cols);
+
+ if (path) {
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, 1, &headline, -1);
+
+ web_load(((struct headline *)headline)->content);
+
+
+
+
+ gtk_tree_path_free(path);
+ }
+
+ return 1;
+}
int main(int argc, char **argv)
{
- GtkWidget *window;
+ GtkWidget *window, *panh;
GtkBuilder *builder;
int optc, cmdok, opti;
PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "prss.glade",
NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+ w_treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder,
+ "feed_tree"));
+ w_headlineview = GTK_TREE_VIEW(gtk_builder_get_object(builder,
+ "headline_tree"));
+
+ gtk_builder_connect_signals(builder, NULL);
+
+ update();
+
+ panh = GTK_WIDGET(gtk_builder_get_object(builder, "webkit_window"));
+
+ gtk_container_add(GTK_CONTAINER(panh), web_get_widget());
gtk_builder_connect_signals(builder, NULL);
--- /dev/null
+/*
+ * Copyright (C) 2010-2013 jeanfi@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <locale.h>
+#include <libintl.h>
+#define _(str) gettext(str)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+#include <json/json.h>
+
+#include "url.h"
+
+struct ucontent {
+ char *data;
+ size_t len;
+};
+
+static CURL *curl;
+
+static size_t cbk_curl(void *buffer, size_t size, size_t nmemb, void *userp)
+{
+ size_t realsize;
+ struct ucontent *mem;
+
+ realsize = size * nmemb;
+ mem = (struct ucontent *)userp;
+
+ mem->data = realloc(mem->data, mem->len + realsize + 1);
+
+ memcpy(&(mem->data[mem->len]), buffer, realsize);
+ mem->len += realsize;
+ mem->data[mem->len] = 0;
+
+ return realsize;
+}
+
+void phttp_init()
+{
+ curl = curl_easy_init();
+}
+
+void phttp_cleanup()
+{
+ curl_easy_cleanup(curl);
+}
+
+json_object *get_json_object(const char *url)
+{
+ struct ucontent chunk;
+ json_object *obj;
+
+ obj = NULL;
+
+ if (!curl)
+ return NULL;
+
+ chunk.data = malloc(1);
+ chunk.len = 0;
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cbk_curl);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+
+ if (curl_easy_perform(curl) == CURLE_OK)
+ obj = json_tokener_parse(chunk.data);
+ else
+ fprintf(stderr, _("Fail to connect to: %s"), url);
+
+ free(chunk.data);
+
+ return obj;
+}
+
+static json_object *post(const char *url, const char *body)
+{
+ struct ucontent chunk;
+ json_object *obj;
+
+ obj = NULL;
+
+ chunk.data = malloc(1);
+ chunk.len = 0;
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(body));
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cbk_curl);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+
+ if (curl_easy_perform(curl) == CURLE_OK)
+ obj = json_tokener_parse(chunk.data);
+ else
+ fprintf(stderr, _("Fail to connect to: %s"), url);
+ free(chunk.data);
+
+ return obj;
+}
+
+json_object *post_json_object(const char *url, struct json_object *j)
+{
+ return post(url, json_object_to_json_string(j));
+}
--- /dev/null
+<schemalist>
+ <schema id="prss" path="/apps/prss/">
+ <key name="url" type="s">
+ <default>'http://localhost/tt-rss'</default>
+ </key>
+ <key name="user" type="s">
+ <default>'user'</default>
+ </key>
+ <key name="password" type="s">
+ <default>'password'</default>
+ </key>
+ </schema>
+</schemalist>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2010-2013 jeanfi@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+/*
+ * Part of the following code is based on:
+ * http://www.geekhideout.com/urlcode.shtml
+ */
+#include "url.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *url_normalize(const char *url)
+{
+ int n = strlen(url);
+ char *ret = strdup(url);
+
+ if (url[n - 1] == '/')
+ ret[n - 1] = '\0';
+
+ return ret;
+}
+
+static char to_hex(char code)
+{
+ static const char hex[] = "0123456789abcdef";
+ return hex[code & 0x0f];
+}
+
+/*
+ * Returns a url-encoded version of str.
+ */
+char *url_encode(const char *str)
+{
+ char *c, *buf, *pbuf;
+
+ buf = malloc(strlen(str) * 3 + 1);
+ pbuf = buf;
+
+ c = (char *)str;
+
+ while (*c) {
+
+ if (isalnum(*c) ||
+ *c == '.' || *c == '_' || *c == '-' || *c == '~')
+ *pbuf++ = *c;
+ else {
+ *pbuf++ = '%';
+ *pbuf++ = to_hex(*c >> 4);
+ *pbuf++ = to_hex(*c & 0x0f);
+ }
+ c++;
+ }
+ *pbuf = '\0';
+
+ return buf;
+}
--- /dev/null
+/*
+ * Copyright (C) 2010-2013 jeanfi@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#ifndef _PLIB_URL_H_
+#define _PLIB_URL_H_
+
+char *url_encode(const char *str);
+char *url_normalize(const char *url);
+
+#endif