Na początek skopiuj do nowego katalogu kod przygotowany w rozdziale 4 ("Refaktoryzacja kodu"). Następnie zapisz w tym katalogu plik interfejsu (main_window.ui) stworzony w rozdziale poprzednim (6. Tworzenie przeglądarki internetowej). Teraz wyedytuj plik main.cpp i zastąp linijkę:
window = new MainWindow(gui->getWidget("wndHelloWorld"));
linijką:
window = new MainWindow(gui->getWidget("wndMainWindow"));
Zrobiliśmy to ponieważ nasze okno główne aplikacji nie nazywa się już wndHelloWorld lecz wndMainWindow. Na koniec wyedytuj plik Makefile i ustaw nazwę aplikacji na internet_viewer. W tym celu zastąp linijkę:
APP_NAME = hello_world
linijką:
APP_NAME = internet_viewer
Na koniec skompiluj program wydając polecenie make. Powstanie aplikacja internet_viewer. Po uruchomieniu program powinien prezentować się następująco:
Nieźle co? Zaledwie dwie drobne zmiany w kodzie i mamy zupełnie nowy program. Na razie jednak nie jest on kompletny. Przede wszystkim nie ma komponentu przeglądarki internetowej i brak obsługi zdarzeń dla przycisków. Zacznijmy więc uzupełniać nasz kod. Na początek zainstaluj komponent przeglądarki. W tym celu wykonaj polecenie:
sudo apt-get install libwebkitgtk-3.0
Po instalacji otwórz w geany pliki MainWindow.h i MainWindow.cpp. Do pliku MainWindow.h dodaj wytłuszczone na czarno zmiany:
#ifndef __MAIN_WINDOW_H__
#define __MAIN_WINDOW_H__
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include "Window.h"
class MainWindow : public Window {
public:
MainWindow(GtkWidget *wnd);
virtual ~MainWindow();
static void onDestroy(GtkWidget* widget, gpointer data);
static gboolean onDeleteEvent(GtkWidget* widget, GdkEvent* event, gpointer data);
static gboolean closeWebView(WebKitWebView* webView, GtkWidget* window);
protected:
WebKitWebView *webView;
};
#endif
Zainkludowaliśmy tu plik nagłówkowy biblioteki webkit, stworzyliśmy nagłówek funkcji statycznej closeWebView, która będzie odpowiadała za zamknięcie programu w momencie gdy nastąpiło żądanie zamknięcia okna przeglądarki (np. przez wywołanie w JavaScripcie komendy window.close) oraz zadeklarowaliśmy zmienną webView, która będzie przechowywała wskaźnik na okno przeglądarki.
Przejdźmy teraz do pliku MainWindow.cpp. Na jego końcu dodaj definicję metody closeWebView:
gboolean MainWindow::closeWebView(WebKitWebView* webView, GtkWidget* window) {
gtk_widget_destroy(window);
}
Jak widzimy - niszczy ona okno główne naszego programu przekazane w parametrze window. Teraz zastąp kod konstruktora następującym kodem:
MainWindow::MainWindow(GtkWidget *wnd)
: Window(wnd) {
g_signal_connect(G_OBJECT(this->wnd), "delete-event", G_CALLBACK(MainWindow::onDeleteEvent), NULL);
g_signal_connect(G_OBJECT(this->wnd), "destroy", G_CALLBACK(MainWindow::onDestroy), NULL);
this->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
GtkWidget* scrolledWindow = gui->getWidget("scrolledWindow");
gtk_container_add(GTK_CONTAINER(scrolledWindow), GTK_WIDGET(this->webView));
gtk_widget_show(GTK_WIDGET(this->webView));
g_signal_connect(this->webView, "close-web-view", G_CALLBACK(MainWindow::closeWebView), this->wnd);
webkit_web_view_load_uri(this->webView, "http://www.webkitgtk.org/");
gtk_widget_grab_focus(GTK_WIDGET(this->webView));
}
W dodanym wytłuszczonym kodzie wykonujemy co następuje:
Przed kompilacją wyedytuj jeszcze plik Makefile i dodaj bibliotekę webkitgtk-3.0 do opcji kompilatora:
CFLAGS = `pkg-config --cflags gtk+-3.0 webkitgtk-3.0` -Wno-format-security
LIBS = `pkg-config --libs gtk+-3.0 webkitgtk-3.0`
Skompiluj teraz program przy pomocy poleceń: make clean i make i uruchom go. Rezultat będzie wyglądał jak na rysunku poniżej:
Dodajmy teraz atrybuty edtUrl oraz homePage do klasy MainWindow. Pierwszy z nich będzie przechowywał wskaźnik na pole tekstowe adresu strony a drugi będzie zawierał adres strony głównej:
protected:
WebKitWebView *webView;
GtkWidget* edtUrl;
const gchar* homePage;
Natomiast do konstruktora klasy MainWindow dodaj kod inicjalizujący atrybut homePage, pobierający wskaźnik na pole tekstowe adresu strony oraz ustawiający zawartość pola tekstowego na aktualnie otwartą stronę główną:
gtk_widget_show(GTK_WIDGET(this->webView));
g_signal_connect(this->webView, "close-web-view", G_CALLBACK(MainWindow::closeWebView), this->wnd);
this->homePage = "http://www.webkitgtk.org/";
this->edtUrl = gui->getWidget("edtURL");
gtk_entry_set_text(GTK_ENTRY(this->edtUrl), this->homePage);
webkit_web_view_load_uri(this->webView, this->homePage);
gtk_widget_grab_focus(GTK_WIDGET(this->webView));
Teraz zróbmy, żeby pole tekstowe adresu strony przyjmowało poprawny adres aktualnie wyświetlany w komponencie webView. W tym celu podepnijmy funkcję obsługi zdarzenia notify::load-status pod tę kontrolkę. W pliku MainWindow.h dodaj nagłówek tej funkcji:
static gboolean closeWebView(WebKitWebView* webView, GtkWidget* window);
static void webViewLoadStatus(WebKitWebView *webView, GParamSpec *pspec, MainWindow* window);
protected:
Jako dodatkowy parametr przekazaliśmy wskaźnik na obiekt MainWindow, po to aby w funkcji statycznej mieć dostęp do kontrolki edtUrl. Następnie na samym końcu pliku MainWindow.cpp dodaj definicję tej funkcji:
void MainWindow::webViewLoadStatus(WebKitWebView *webView, GParamSpec *pspec, MainWindow* window) {
WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
GObject *object = G_OBJECT(webView);
g_object_freeze_notify(object);
switch (status) {
case WEBKIT_LOAD_COMMITTED:
gtk_entry_set_text(GTK_ENTRY(window->edtUrl), webkit_web_view_get_uri(webView));
break;
}
g_object_thaw_notify(object);
}
W funkcji tej pobieramy aktualny status kontrolki webView i na czas obsługi zdarzenia blokujemy przy pomocy funkcji g_object_freeze_notify emisję następnych sygnałów notify. Jeśli status jest równy WEBKIT_LOAD_COMMITTED, to do pola tekstowego edtUrl ładujemy aktualny adres przeglądarki. Komponent webView ma status WEBKIT_LOAD_COMMITTED wtedy gdy pobrał pierwsze bajty z nowego adresu. Na koniec przy pomocy funkcji g_object_thaw_notify odblokowujemy otrzymywanie sygnałów notify. Pozostało jeszcze podpiąć funkcję webViewLoadStatus pod sygnał notify::load-status:
g_signal_connect(this->webView, "close-web-view", G_CALLBACK(MainWindow::closeWebView), this->wnd);
g_signal_connect(this->webView, "notify::load-status", G_CALLBACK(MainWindow::webViewLoadStatus), this);
this->homePage = "http://www.webkitgtk.org/";
Na koniec rozdziału podepnijmy pod przycisk Przejdź funkcję ładującą podany w polu tekstowym adres strony. W tym celu stwórzmy funkcję obsługi zdarzenia click przycisku w pliku MainWindow.h:
static void webViewLoadStatus(WebKitWebView *webView, GParamSpec *pspec, MainWindow* window); static void btnGoClicked(GtkWidget* button, MainWindow* window); protected:
Następnie na końcu pliku MainWindow.cpp dodaj definicję tej funkcji:
void MainWindow::btnGoClicked(GtkWidget* button, MainWindow* window) {
const gchar* uri = gtk_entry_get_text(GTK_ENTRY(window->edtUrl));
webkit_web_view_load_uri(window->webView, uri);
gtk_widget_grab_focus(GTK_WIDGET(window->webView));
}
W funkcji tej najpierw pobieramy zawartość pola tekstowego (gtk_entry_get_text) a następnie ładujemy stronę o tym adresie w kontrolce webView. Aby operować na kontrolkach: polu tekstowym i przeglądarce, wykorzystujemy obiekt typu MainWindow przekazany w funkcji podpinającej tę funkcję pod sygnał clicked w konstruktorze obiektu:
this->edtUrl = gui->getWidget("edtURL");
gtk_entry_set_text(GTK_ENTRY(this->edtUrl), this->homePage);
GtkWidget* btnGo = gui->getWidget("btnGo");
g_signal_connect(btnGo, "clicked", G_CALLBACK(MainWindow::btnGoClicked), this);
webkit_web_view_load_uri(this->webView, this->homePage);
gtk_widget_grab_focus(GTK_WIDGET(this->webView));
I to narazie tyle. Obsługą zdarzeń dla przycisków toolbara oraz pozycji menu zajmiemy się w dalszych rozdziałach tego tutorialu.