/* * Tab page * * Copyright (C) 2017 Patrick McDermott * * This file is part of Marquee. * * Marquee 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 3 of the License, or * (at your option) any later version. * * Marquee 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 Marquee. If not, see . */ #include "tab-page.h" #include #include #include #include #include #include "application.h" #include "notebook.h" #include "tab-label.h" #include "toolbars/find-toolbar.h" #include "toolbars/navigation-toolbar.h" #include "web-view.h" #include "window.h" struct _MqTabPage { GtkBox parent_instance; MqWindow *window; gchar *uri; guint position; MqApplication *application; GtkWidget *container; GtkWidget *label; const gchar *title; WebKitWebView *web_view; }; enum { PROP_WINDOW = 1, PROP_URI, N_PROPERTIES }; static GParamSpec *obj_properties[N_PROPERTIES] = {NULL,}; struct _MqTabPageClass { GtkBoxClass parent_class; }; G_DEFINE_TYPE(MqTabPage, mq_tab_page, GTK_TYPE_BOX) static void title_cb(WebKitWebView *web_view, GParamSpec G_GNUC_UNUSED *param_spec, MqTabPage *tab_page) { tab_page->title = webkit_web_view_get_title(web_view); mq_notebook_update_tab_title( MQ_NOTEBOOK(gtk_widget_get_parent(GTK_WIDGET(tab_page))), tab_page, tab_page->title); } static void init_non_root(MqTabPage *tab_page) { GtkWidget *navigation_toolbar; GtkWidget *find_toolbar; tab_page->application = mq_window_get_application(tab_page->window); tab_page->web_view = WEBKIT_WEB_VIEW(mq_web_view_new(tab_page, tab_page->uri)); g_signal_connect(tab_page->web_view, "notify::title", G_CALLBACK(title_cb), tab_page); tab_page->label = mq_tab_label_new(tab_page, MQ_WEB_VIEW(tab_page->web_view)); find_toolbar = mq_find_toolbar_new(MQ_WEB_VIEW(tab_page->web_view)); navigation_toolbar = mq_navigation_toolbar_new( mq_application_get_config( mq_window_get_application(tab_page->window)), tab_page, MQ_FIND_TOOLBAR(find_toolbar), MQ_WEB_VIEW(tab_page->web_view), tab_page->uri); gtk_box_pack_start(GTK_BOX(tab_page), navigation_toolbar, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(tab_page), find_toolbar, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(tab_page), GTK_WIDGET(tab_page->web_view), TRUE, TRUE, 0); } static void constructed(GObject *object) { MqTabPage *tab_page; if (G_OBJECT_CLASS(mq_tab_page_parent_class)->constructed) { G_OBJECT_CLASS(mq_tab_page_parent_class)->constructed(object); } tab_page = MQ_TAB_PAGE(object); init_non_root(tab_page); } static void finalize(GObject *object) { MqTabPage *tab_page; tab_page = MQ_TAB_PAGE(object); g_free(tab_page->uri); G_OBJECT_CLASS(mq_tab_page_parent_class)->finalize(object); } static void get_property(GObject *object, guint property_id, GValue *value, GParamSpec *param_spec) { MqTabPage *tab_page; tab_page = MQ_TAB_PAGE(object); switch (property_id) { case PROP_WINDOW: g_value_set_object(value, tab_page->window); break; case PROP_URI: g_value_set_string(value, tab_page->uri); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, param_spec); break; } } static void set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *param_spec) { MqTabPage *tab_page; tab_page = MQ_TAB_PAGE(object); switch (property_id) { case PROP_WINDOW: tab_page->window = g_value_get_object(value); break; case PROP_URI: g_free(tab_page->uri); tab_page->uri = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, param_spec); break; } } static void mq_tab_page_class_init(MqTabPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->constructed = constructed; object_class->finalize = finalize; object_class->get_property = get_property; object_class->set_property = set_property; obj_properties[PROP_WINDOW] = g_param_spec_object( "window", "MqWindow", "The parent MqWindow instance", MQ_TYPE_WINDOW, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); obj_properties[PROP_URI] = g_param_spec_string( "uri", "URI", "The URI to load", "", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_properties(object_class, N_PROPERTIES, obj_properties); } static void mq_tab_page_init(MqTabPage *tab_page) { tab_page->title = "New tab"; } MqTabPage * mq_tab_page_new(MqWindow *window, const gchar *uri) { return g_object_new(MQ_TYPE_TAB_PAGE, "orientation", GTK_ORIENTATION_VERTICAL, "spacing", 0, "window", window, "uri", uri, NULL); } void mq_tab_page_close(MqTabPage *tab_page) { mq_notebook_remove_page( MQ_NOTEBOOK(gtk_widget_get_parent(GTK_WIDGET(tab_page))), tab_page); } void mq_tab_page_quit(MqTabPage *tab_page) { mq_window_quit(tab_page->window); } MqApplication * mq_tab_page_get_application(MqTabPage *tab_page) { return tab_page->application; } MqWindow * mq_tab_page_get_window(MqTabPage *tab_page) { return tab_page->window; } MqTabLabel * mq_tab_page_get_label(MqTabPage *tab_page) { return MQ_TAB_LABEL(tab_page->label); } guint mq_tab_page_get_position(MqTabPage *tab_page) { return tab_page->position; } void mq_tab_page_set_position(MqTabPage *tab_page, guint position) { tab_page->position = position; } const gchar * mq_tab_page_get_title(MqTabPage *tab_page) { return tab_page->title; } static void open_response_cb(GtkWidget *dialog, gint response_id, MqTabPage *tab_page) { gchar *filename; gchar *uri; if (response_id == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog)); uri = g_strconcat("file://", filename, NULL); g_free(filename); mq_web_view_load_uri(MQ_WEB_VIEW(tab_page->web_view), uri); g_free(uri); } gtk_widget_destroy(dialog); } void mq_tab_page_open(MqTabPage *tab_page) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(tab_page->window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", GTK_RESPONSE_CANCEL, "_Open", GTK_RESPONSE_ACCEPT, NULL); g_signal_connect(dialog, "response", G_CALLBACK(open_response_cb), tab_page); gtk_widget_show_all(dialog); } static void save_async_cb(WebKitWebView *web_view, GAsyncResult *result) { webkit_web_view_save_to_file_finish(web_view, result, NULL); } static void save_response_cb(GtkWidget *dialog, gint response_id, MqTabPage *tab_page) { gchar *filename; GFile *file; if (response_id == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog)); file = g_file_new_for_path(filename); g_free(filename); /* TODO: HTML-only file format? */ webkit_web_view_save_to_file(tab_page->web_view, file, WEBKIT_SAVE_MODE_MHTML, NULL, (GAsyncReadyCallback) save_async_cb, NULL); } gtk_widget_destroy(dialog); } void mq_tab_page_save(MqTabPage *tab_page) { GtkWidget *dialog; GtkFileChooser *chooser; gchar *filename; dialog = gtk_file_chooser_dialog_new("Save File", GTK_WINDOW(tab_page->window), GTK_FILE_CHOOSER_ACTION_SAVE, "_Cancel", GTK_RESPONSE_CANCEL, "_Save", GTK_RESPONSE_ACCEPT, NULL); chooser = GTK_FILE_CHOOSER(dialog); gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); /* TODO: gtk_file_chooser_set_current_folder() */ /* TODO: Clean up title for file name. */ filename = g_strconcat(tab_page->title, ".mhtml", NULL); gtk_file_chooser_set_current_name(chooser, filename); g_free(filename); g_signal_connect(dialog, "response", G_CALLBACK(save_response_cb), tab_page); gtk_widget_show_all(dialog); } void mq_tab_page_scroll_tab_labels(MqTabPage *node) { mq_tab_label_scroll(MQ_TAB_LABEL(node->label)); } void mq_tab_page_begin_scrolling_tab_labels(MqTabPage *node) { mq_tab_label_begin_scrolling(MQ_TAB_LABEL(node->label)); } void mq_tab_page_end_scrolling_tab_labels(MqTabPage *node) { mq_tab_label_end_scrolling(MQ_TAB_LABEL(node->label)); }