Root/src/vido.cc

Source at commit 9387c0dd58913fda7211152214fc69e884f7da22 created 10 years 8 months ago.
By Mirko Lindner, add history and "go to top" functions
1/***************************************************************************
2 * Copyright (C) 2009 by Mirko Lindner,,, *
3 * vegyraupe@mira *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21
22#include <gtkmm.h>
23#include <zim/file.h>
24#include <zim/search.h>
25#include <iostream>
26#include <string>
27#include <vector>
28
29
30#include "config.h"
31#include "message_dialog.hh"
32#include "vido.hh"
33#include "main_window.hh"
34#include "search_dialog.hh"
35
36#include <cxxtools/loginit.h>
37
38log_define("vido.main")
39
40extern "C" {
41   #include "gtkhtml/gtkhtml.h"
42 }
43
44// std::string content;
45std::string fileName;
46
47main_window *window;
48Gtk::Widget *html;
49GtkWidget *html_wg;
50std::vector < std::pair< std::string, std::string > > history;
51
52
53// // // misc functions
54// get zimFile, if not already opened, open file
55const zim::File& get_file()
56{
57  static zim::File zimFile;
58  if (!zimFile.good())
59  {
60    log_debug("file not initialized:" << fileName);
61    zimFile = zim::File(fileName);
62    log_debug("number of articles: " << zimFile.getCountArticles());
63  }
64
65  log_debug("returning file.");
66  return zimFile;
67}
68
69// display message in gtk window
70void show_message(std::string title, std::string txt)
71{
72    message_dialog(window, title, txt);
73}
74
75// fill gtkhtml widget with new content
76//TODO prepend "top" anchor on html
77void fill_gtkhtml(std::string& html, std::string url, std::string title){
78    log_debug("fill gtkhtml called");
79    std::string ccontent;
80    ccontent = "<a name=\"top\"></a>" + html;
81    gtk_html_flush(GTK_HTML(html_wg));
82    gtk_html_load_from_string(GTK_HTML(html_wg), ccontent.c_str(), -1);
83    
84    if ((url != "") && title != ""){
85      log_debug("adding " << title << " to history");
86      history.push_back( std::make_pair( url, title ) );
87      if (history.size() == 11){
88        history.erase(history.begin());
89      }
90      
91    }
92    
93}
94
95void show_history()
96{
97  std::string res, url, title;
98  res += "<ul style=\"list-style-type:none;\">";
99
100  for(unsigned i=history.size(); i > 0; --i)
101  {
102    
103#if HAVE_ZIM_QUNICODE_H
104    res += "<li><a href=" + history[i-1].first + ">" + history[i-1].second + "</a></li>";
105#else
106    res += "<li><a href='" + history[i-1].first + "'>" + history[i-1].second + "</a></li>";
107#endif
108    
109  }
110  res += "</ul>";
111  url = "";
112  title = "";
113  
114  fill_gtkhtml(res, url, title);
115  
116}
117
118//UNUSED
119// // copy article html from while loop into global variable
120// void set_article(const std::string& txt)
121// {
122// content = txt;
123// }
124
125// // // externally called functions
126
127// // display random article
128void show_random()
129{
130
131    log_debug("random called.");
132    zim::File m = get_file();
133  
134    unsigned int seed = static_cast<unsigned int>(time(0));
135    zim::size_type idx = static_cast<zim::size_type>(static_cast<double>(m.getCountArticles()) * rand_r(&seed) / RAND_MAX);
136    zim::Article article;
137    
138    article = m.getArticle(idx);
139    
140    //loop in case article is redirect
141    do
142    {
143        article = article.getRedirectArticle();
144    }while(article.isRedirect());
145    
146    std::string res = article.getPage();
147
148    log_debug("article size=" << res.size());
149    log_debug("article title=" << article.getTitle());
150    log_debug("article namespace=" << article.getNamespace());
151    
152    fill_gtkhtml(res, article.getUrl(), article.getTitle());
153}
154
155// // display search dialog
156void search_window(main_window *window_x)
157{
158    search_dialog(window_x, " ");
159}
160
161// //
162void GoToTop()
163{
164    log_debug("go to top called");
165    std::string term = "top";
166    bool success = gtk_html_jump_to_anchor(GTK_HTML(html_wg), const_cast<char*>(term.c_str()));
167}
168
169// // // meta functions
170
171// // set displayed html to given url
172// // FIXME: returns several articles and displays on one page ... why?
173void getArticleFromUrl(const gchar *url)
174{
175    // TODO unescape url
176
177// // create ZIM file accessor
178    zim::File m = get_file();
179
180// // convert url to string
181    std::string term(url);
182    std::string content;
183// // replace '+' signs with spaces in url
184    std::replace(term.begin(), term.end(), '+', ' ');
185    
186// // find and declare namespace
187    size_t found;
188    size_t found2;
189    char ns;
190
191    found=term.find("/");
192    if (found != std::string::npos)
193    {
194        if (found)
195        {
196            ns = term[0];
197            term.erase(found + 1);
198        }
199        else
200        {
201            term.erase(1);
202            ns = term[0];
203            found2 = term.find("/");
204            term.erase(found2 + 1);
205        }
206    }
207    else
208    {
209        ns = 'A';
210    }
211
212// // try to retrieve article
213    try
214    {
215#if HAVE_ZIM_QUNICODE_H
216        zim::Article article = m.getArticle(ns, zim::QUnicodeString(term));
217#else
218        zim::Article article = m.getArticle(ns, term);
219#endif
220
221        if (article.good()) // check if article is really found
222        {
223            content = article.getPage();
224
225            fill_gtkhtml(content, article.getUrl(), article.getTitle());
226        }
227        else
228        {
229            std::cerr << "article \"" << url << "\" not found" << std::endl;
230            show_message("Error", "The article you requested (" + term + ") was not found.");
231        }
232    }
233    catch (const std::exception& e)
234    {
235        std::cerr << e.what() << std::endl;
236    }
237}
238
239
240// // test functions
241void getArticleFromTitle(const gchar *phrase)
242{
243    char ns;
244    ns = 'A';
245    zim::File z = get_file();
246    
247    zim::Search::Results result;
248    zim::Search search(z);
249    std::string term(phrase);
250    std::string res;
251    std::string url;
252    std::string title;
253    search.setSearchLimit(25);
254    search.find(result, ns, term);
255    if( result.size() == 0)
256    {
257        show_message("Error", "The article you requested (" + term + ") was not found.");
258    
259    }else{
260      
261      if (result.size() == 1){
262        log_debug("one article in result");
263        
264        zim::Article article = z.getArticle(result[0].getArticle().getIndex());
265        
266        //loop in case article is redirect
267        do
268        {
269            article = article.getRedirectArticle();
270        }while(article.isRedirect());
271        
272        res = article.getPage(false, 10);
273        url = article.getUrl();
274        title = article.getTitle();
275      }
276      else
277      {
278        log_debug("more than one article in result");
279        for (unsigned i = 0; i < result.size(); ++i)
280        {
281#if HAVE_ZIM_QUNICODE_H
282          res += "<li><a href=" + result[i].getArticle().getLongUrl().toXML() + ">" + result[i].getArticle().getLongUrl().toXML() + "</a></li>";
283#else
284          res += "<li><a href='" + result[i].getArticle().getUrl() + "'>" + result[i].getArticle().getUrl() + "</a></li>";
285#endif
286        }
287        url = "";
288        title = "";
289    
290      }
291      
292      fill_gtkhtml(res, url, title);
293    }
294}
295
296// // // window response functions
297
298// // open requested link
299// FIXME show error window when dead-link requested
300bool on_link_clicked(GtkHTML *html, const gchar *url)
301{
302    std::string term(url);
303    size_t found;
304    found=term.find("#");
305    if (found != std::string::npos){
306    
307      if (found == 0){
308        term.erase(0, 1);
309        bool success = gtk_html_jump_to_anchor(GTK_HTML(html_wg), const_cast<char*>(term.c_str()));
310        log_debug("jump to " << term << "worked: " << success);
311      }else{
312        term = term.substr(0, found);
313        //TODO make "set_html" func accept anchor name
314        getArticleFromUrl(const_cast<char*>(term.c_str()));
315      }
316      
317    }else{
318      getArticleFromUrl(url);
319    }
320    
321    return true;
322}
323
324bool scrolled(GtkHTML *cb_html, GtkOrientation orientation, GtkScrollType scroll_type, gfloat position)
325{
326  log_debug("scrolled");
327  // TODO on any scroll adjust cursor, maybe with:
328  //static void gtk_html_adjust_cursor_position (GtkHTML *html)
329}
330
331// // main function
332int main(int argc, char **argv)
333{
334  try
335  {
336    log_init();
337
338    if (argc == 2)
339    {
340      fileName = argv[1];
341
342      log_debug("vido is here file: " << fileName);
343      
344      Gtk::Main kit(argc, argv);
345
346      main_window window;
347      window.set_title("Vido");
348  // window.set_border_width(0);
349      window.set_default_size(220, 240);
350  // window.set_resizable(0);
351
352      html_wg = gtk_html_new();
353      
354      html = Glib::wrap(html_wg);
355      g_signal_connect( G_OBJECT( html_wg ), "link_clicked", G_CALLBACK( on_link_clicked ), NULL );
356      g_signal_connect( G_OBJECT( html_wg ), "scroll", G_CALLBACK( scrolled ), NULL );
357      gtk_html_set_caret_mode(GTK_HTML(html_wg),false);
358// gtk_html_adjust_cursor_position(GTK_HTML(html_wg));
359      static Gtk::ScrolledWindow scrolled_window;
360      scrolled_window.add(*html);
361      scrolled_window.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
362      
363      window.add(scrolled_window);
364      window.show_all();
365      
366      show_random();
367      gtk_html_edit_make_cursor_visible(GTK_HTML(html_wg));
368      Gtk::Main::run(window);
369    }
370    else
371    {
372      std::cout << "usage: " << argv[0] << " [PATH TO ZIM FILE]" << std::endl;
373    }
374
375  }
376  catch (const std::exception& e)
377  {
378    std::cerr << e.what() << std::endl;
379    return -1;
380  }
381
382}
383
384

Archive Download this file

Branches:
development
master



interactive