Publi

Creando un navegador web basado en gtkwebkit y gtkmm [Actualizado: 15/11/2010]

webkitAhora, vamos a ir un poco más allá, aunque los ejemplos están hechos por mí, en parte me he basado un poco en la documentación de gtkmm (recomendable, llena de ejemplos e información interesante de cada widget), aunque ahora voy a utilizar algo de investigación propia.

El método a seguir será parecido a veces anteriores, un archivo principal, y una clase (con archivos cpp y h). Al compilar el proyecto, ha ocupado entre 45Kb y 60Kb, por lo que para ser un navegador no ocupa demasiado. Además, si leemos un poco la documentación de GtkWebkit veremos que podemos modificar el comportamiento del módulo para integrarlo en nuestras aplicaciones.

Para este pequeño proyecto he utilizado WebkitGtk+ >=1.1.7 y no Webkitmm porque este último no está muy avanzado en su desarrollo… y de paso quería practicar cómo podía comunicarme con widgets hechos en C en lugar de C++.

[ wk.cpp – Programa principal ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <gtkmm.h>
#include "wkmain.h"

WkWindow *wkwind;

int main(int argc, char *argv[])
{
  Main entorno (argc, argv);
  // Creamos la ventana
  WkWindow wkwind;

  // Ejecutamos
  entorno.run(wkwind);

  return 0;
}

[ wkmain.h ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef _WKMAIN_H
#define _WKMAIN_H

#include <gtkmm.h>
#include <webkit/webkit.h>

#define CLICK_CONNECT(widget, method) widget->signal_clicked().connect(sigc::bind<Widget*>(sigc::mem_fun(*this, &method),(Widget*)widget))

using namespace Gtk;

class WkWindow : public Window
{
 public:
  WkWindow();
  ~WkWindow();

// Click en el botón go
  void go_click(Widget *sender);

// Actualizamos la barra de progreso
  bool wkprogress();

// Cargamos una web
  void carga_web(Glib::ustring url);

  VBox vb;          // Divisiones en la vertical
  HBox cabecera; // Barra superior
  Label texto;      // Texto de dirección
  Entry direccion; // Editor de texto para la dirección
  Button *go;      // Botón para ver la web
  GtkWidget *web_view;  // Widget de webkit
  ScrolledWindow scroll;   // Ventana de scroll para páginas web grandes (más grandes que la ventana)
  Statusbar statusbar;     // Barra de estado
  ProgressBar progressbar; // Barra de progreso

 private:
  int timeout;    // Aquí almacenamos los eventos timeout
};

#endif

Bien, viendo esto, veremos que será un navegador sencillo (una entrada de texto para la dirección, un botón para ver la web, el motor webkit para ver la web, y una barra de estado con una barra de progreso).

Vemos el código wkmain.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "wkmain.h"

WkWindow::WkWindow() : texto("Dirección: ")
{
  // Configuro la ventana
  set_title("Navegador con Webkit");
  set_border_width(5);
  set_default_size(800, 600);

// Las barras de scroll salen automáticamente
  scroll.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC);

  // Configuro la cabecera
  go = new Button(Stock::GO_FORWARD);
  cabecera.pack_start(texto, PACK_SHRINK);
  cabecera.pack_start(direccion, PACK_EXPAND_WIDGET);
  cabecera.pack_start(*go, PACK_SHRINK);

  CLICK_CONNECT(go, WkWindow::go_click);

  vb.pack_start(cabecera, PACK_SHRINK);
  vb.set_spacing(3);        // Espacio de 3pixels entre elementos

// Configuramos el módulo webkit ! Atención es de Gtk, no Gtkmm
  web_view=webkit_web_view_new ();

// Llamamos al método de carga de web
  carga_web("https://poesiabinaria.net/");

// Seguimos añadiendo objetos al Vbox
  vb.pack_start(scroll, PACK_EXPAND_WIDGET);

// El moulo webkit no podemos añadirlo tan fácil, tenemos que añadir
// el webkit al scrollbox mediante funciones de gtk (gtk_container_add).
// Además, para sacar el objeto de Gtk del scrollbox (gtkmm) debemos llamar al método gobj()
  gtk_container_add(GTK_CONTAINER(scroll.gobj()), web_view);

  vb.pack_start(statusbar, PACK_SHRINK);
  statusbar.pack_start(progressbar, PACK_EXPAND_WIDGET);
  progressbar.set_fraction(0.0); // Progreso al 0%

  add(vb);

  show_all_children();
}

WkWindow::~WkWindow()
{

}

void WkWindow::carga_web(Glib::ustring url)
{
  progressbar.set_fraction(0.0); // Progreso al 0%
  webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url.data());

// Generamos un evento programado, cada 50ms se generará la señal
// y llamaremos al método wkprogress()
  timeout=Glib::signal_timeout().connect(sigc::mem_fun(*this, &WkWindow::wkprogress),50); // Actualizamos cada 50ms
}

void WkWindow::go_click(Widget *sender)
{
  carga_web(direccion.get_text());
}

bool WkWindow::wkprogress()
{
  // Calculamos el progreso
  double progreso=webkit_web_view_get_progress(WEBKIT_WEB_VIEW(web_view));

  // Pasamos el progreso a la progressbar (que está en la statusbar)
  progressbar.set_fraction(progreso);
  return (progreso!=0);     // Cuando progreso sea 0, devolveremos FALSE, y se desconectará el signal_timeout
}

Está todo más o menos explicado en los comentarios. Para compilar hacemos lo siguiente:

$ g++ -o webkitex wk.cpp wkmain.cpp `pkg-config –cflags gtkmm-2.4 webkit-1.0` `pkg-config –libs gtkmm-2.4 webkit-1.0`

(Haciendo coincidir las versiones de webkit y gtkmm

NOTA: Aunque en el blog parezca que pone `pkg-config -libs …` pone `pkg-config –libs` (dos signos menos).

ACTUALIZACIÓN 15/11/2010: Gracias a ChineseGeek por sus comentarios he añadido una versión compatible con versiones de webkit inferiores a 1.1.7. Podemos descargarlo desde aquí: (webkit_cpp.tar.bz2 2.5Kb).

También podría interesarte...

There are 9 comments left Ir a comentario

  1. Pingback: Bitacoras.com /

  2. Pingback: BlogESfera.com /

  3. ChineseGeek /
    Usando Google Chrome Google Chrome 9.0.575.0 en Ubuntu Linux Ubuntu Linux

    Hola, primero q todo felicitarte por el blog, muy bueno la verdad! Segundo, tengo algunas dudas al momento de compilar el browser, la primera es con respecto al comando; veo que incluyes un archivo wkmain.cpp al momento de compilar, el cual no lo tengo, de todas formas, si compilo con el comando que indicas alli me da este error:

    g++: wkmain.cpp: No existe el fichero ó directorio
    En el fichero incluído de wk.cpp:2:
    wkmain.h:1:1: error: #ifndef sin terminar

    Si intento compilar con el mismo comando pero cambiando wkmain.cpp por wkwin.cp (que es el otro archivo que realizaste en el post) me dan estos errores:

    En el fichero incluído de wk.cpp:2:
    wkmain.h:1:1: error: #ifndef sin terminar
    En el fichero incluído de wkwin.cp:1:
    wkmain.h:1:1: error: #ifndef sin terminar
    wkwin.cp: In constructor ‘WkWindow::WkWindow()’:
    wkwin.cp:18: error: ‘widget’ no se declaró en este ámbito
    wkwin.cp:18: error: ‘method’ no se declaró en este ámbito
    wkwin.cp:18: error: expected `;’ before ‘widget’
    wkwin.cp: At global scope:
    wkwin.cp:43: error: expected constructor, destructor, or type conversion before ‘::’ token
    wkwin.cp: In member function ‘void WkWindow::carga_web(Glib::ustring)’:
    wkwin.cp:49: error: ‘webkit_web_view_load_uri’ no se declaró en este ámbito
    wkwin.cp: In member function ‘bool WkWindow::wkprogress()’:
    wkwin.cp:61: error: ‘webkit_web_view_get_progress’ no se declaró en este ámbito

    Ojala puedas ayudarme, muchas gracias de antemano!

  4. admin / Post Author
    Usando Mozilla Firefox Mozilla Firefox 3.6 en Linux Linux

    @ChineseGeek
    ¡Gracias por tu apoyo!

    Perdóname, me equivoqué al nombrar uno de los archivos, anteriormente se llamaba wkwin.cp pero es wkmain.cpp; yo creo que todos los fallos vienen de ahí, prueba a ver y me comentas.

    Suerte!

  5. ChineseGeek /
    Usando Google Chrome Google Chrome 9.0.582.0 en Ubuntu Linux Ubuntu Linux

    @admin

    Compilando como me indicas me dan estos dos errores, por mas que googleo no veo como solventar estos inconvenientes:

    wkmain2.cpp: In member function ‘void WkWindow::carga_web(Glib::ustring)’:
    wkmain2.cpp:55: error: ‘webkit_web_view_load_uri’ no se declaró en este ámbito
    wkmain2.cpp: In member function ‘bool WkWindow::wkprogress()’:
    wkmain2.cpp:70: error: ‘webkit_web_view_get_progress’ no se declaró en este ámbito

  6. admin / Post Author
    Usando Mozilla Firefox Mozilla Firefox 3.6 en Linux Linux

    @ChineseGeek
    Pues el caso es que son errores de la versión, qué versión de gtkwebkit usas? Te lo digo, porque en la versión 1.1.1 surgieron las funciones webkit_web_view_load_uri() y webkit_web_view_get_progress().

    webkit_web_view_load_uri() es sustituto de webkit_web_view_open()

    y se usa igual, cambia
    webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url.data());
    por
    webkit_web_view_open(WEBKIT_WEB_VIEW(web_view), url.data());

    Para no usar webkit_web_view_get_progress() la he tenido que liar un montón, pero esepero poder publicar pronto resultados que compilen bien en esta página a lo largo del día.

  7. admin / Post Author
    Usando Mozilla Firefox Mozilla Firefox 3.6 en Linux Linux

    @ChineseGeek
    Ya lo tienes, descarga el archivo, a ver si te funciona bien. Pásate por aquí y me comentas qué tal; si tienes más errores, haremos lo posible por subsanarlos 🙂

  8. ChineseGeek /
    Usando Google Chrome Google Chrome 9.0.582.0 en Ubuntu Linux Ubuntu Linux

    @admin

    Ya sospechaba yo que era un problema con la version de webkit. Ahora ya funciona, gracias por la ayuda! Voy a ver si implemento los botones de atras y adelante, cuando lo tenga listo te aviso jajaja. Saludos!

  9. admin / Post Author
    Usando Mozilla Firefox Mozilla Firefox 3.6 en Linux Linux

    @ChineseGeek ,
    Espero tener noticias tuyas pronto!

Leave a Reply