Poesía Binaria

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

Ahora, 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....