📄 st-browser-tab.c
字号:
/* * Copyright (c) 2003, 2004 Jean-Yves Lefort * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include <string.h>#include <glib/gi18n.h>#include <gtk/gtk.h>#include "sgtk-util.h"#include "sg-util.h"#include "st-browser-tab.h"#include "st-browser-tab-label.h"#include "st-category-view.h"#include "st-dialog-api.h"#include "st-statusbar.h"#include "st-stream-view.h"#include "st-handler.h"#include "st-thread.h"#include "st-settings.h"#include "st-category-store.h"#include "st-stream-store.h"#include "st-util.h"#include "st-cache.h"#include "st-shell.h"#include "st-bookmarks.h"/*** type definitions ********************************************************/enum { STREAM_TASK_ADDED, STREAM_TASK_REMOVED, LAST_SIGNAL};enum { PROP_0, PROP_HANDLER, PROP_RUNNING}; typedef struct{ STBrowserTab *tab; STCategoryBag *category_bag; STThread *thread;} CategoryTask;struct _STBrowserTabPrivate{ GSList *running_categories; GSList *stream_tasks; GNode *pending_categories;};/*** variable declarations ***************************************************/static GObjectClass *parent_class = NULL;static unsigned int browser_tab_signals[LAST_SIGNAL] = { 0 };/*** function declarations ***************************************************/static void st_browser_tab_class_init (STBrowserTabClass *class);static void st_browser_tab_init (STBrowserTab *tab);static GObject *st_browser_tab_constructor (GType type, unsigned int n_construct_properties, GObjectConstructParam *construct_params);static void st_browser_tab_set_property (GObject *object, unsigned int prop_id, const GValue *value, GParamSpec *pspec);static void st_browser_tab_get_property (GObject *object, unsigned int prop_id, GValue *value, GParamSpec *pspec);static void st_browser_tab_update_counters (STBrowserTab *tab);static void st_browser_tab_reload_thread (gpointer data);static void st_browser_tab_run_category_task (STBrowserTab *tab, STCategoryBag *category_bag, STThreadCallback callback);static void st_browser_tab_category_task_print_cb (const char *str, gpointer data);static void st_browser_tab_category_task_set_progress_cb (double progress, gpointer data);static void st_browser_tab_category_task_cleanup_cb (gpointer data);static void st_browser_tab_category_task_data_destroy_cb (gpointer data);static void st_browser_tab_set_category_running (STBrowserTab *tab, STCategoryBag *bag, gboolean running);static void st_browser_tab_update_running (STBrowserTab *tab);static void st_browser_tab_category_selection_changed_h (STCategoryView *view, gpointer user_data);static void st_browser_tab_cache_load_streams_thread (gpointer data);static gboolean st_browser_tab_cache_load_streams_progress_cb (int n, int total, gpointer data);static void st_browser_tab_set_streams (STBrowserTab *tab, STCategoryBag *category_bag, STStreamStore *streams);static void st_browser_tab_paned_notify_position_h (GObject *object, GParamSpec *pspec, gpointer user_data);static void st_browser_tab_stream_task_thread (gpointer data);static void st_browser_tab_stream_task_add_bookmarks_thread (gpointer data);static void st_browser_tab_stream_task_cleanup_cb (gpointer data);static void st_browser_tab_stream_task_data_destroy_cb (gpointer data);/*** implementation **********************************************************/GTypest_browser_tab_get_type (void){ static GType browser_tab_type = 0; if (! browser_tab_type) { static const GTypeInfo browser_tab_info = { sizeof(STBrowserTabClass), NULL, NULL, (GClassInitFunc) st_browser_tab_class_init, NULL, NULL, sizeof(STBrowserTab), 0, (GInstanceInitFunc) st_browser_tab_init, }; browser_tab_type = g_type_register_static(GTK_TYPE_HPANED, "STBrowserTab", &browser_tab_info, 0); } return browser_tab_type;}static voidst_browser_tab_class_init (STBrowserTabClass *class){ GObjectClass *object_class = G_OBJECT_CLASS(class); parent_class = g_type_class_peek_parent(class); g_type_class_add_private(class, sizeof(STBrowserTabPrivate)); object_class->constructor = st_browser_tab_constructor; object_class->set_property = st_browser_tab_set_property; object_class->get_property = st_browser_tab_get_property; g_object_class_install_property(object_class, PROP_HANDLER, g_param_spec_pointer("handler", NULL, NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(object_class, PROP_RUNNING, g_param_spec_boolean("running", NULL, NULL, FALSE, G_PARAM_READABLE)); browser_tab_signals[STREAM_TASK_ADDED] = g_signal_new("stream-task-added", ST_TYPE_BROWSER_TAB, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(STBrowserTabClass, stream_task_added), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); browser_tab_signals[STREAM_TASK_REMOVED] = g_signal_new("stream-task-removed", ST_TYPE_BROWSER_TAB, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(STBrowserTabClass, stream_task_removed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);}static voidst_browser_tab_init (STBrowserTab *tab){ tab->priv = G_TYPE_INSTANCE_GET_PRIVATE(tab, ST_TYPE_BROWSER_TAB, STBrowserTabPrivate); tab->handler = NULL; tab->running = FALSE; tab->category_view = NULL; tab->stream_view = NULL;}static GObject *st_browser_tab_constructor (GType type, unsigned int n_construct_properties, GObjectConstructParam *construct_params){ GObject *object; STBrowserTab *tab; GtkWidget *scrolled; object = parent_class->constructor(type, n_construct_properties, construct_params); tab = ST_BROWSER_TAB(object); if (ST_HANDLER_HAS_CATEGORIES(tab->handler)) { STCategoryStore *categories; scrolled = gtk_scrolled_window_new(FALSE, FALSE); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); categories = st_handler_get_categories(tab->handler); tab->category_view = (STCategoryView *) st_category_view_new(categories); g_object_unref(categories); gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(tab->category_view)); gtk_paned_add1(GTK_PANED(tab), scrolled); gtk_widget_show_all(scrolled); g_signal_connect(tab->category_view, "selection-changed", G_CALLBACK(st_browser_tab_category_selection_changed_h), tab); } scrolled = gtk_scrolled_window_new(FALSE, FALSE); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); tab->stream_view = (STStreamView *) st_stream_view_new(tab->handler); gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(tab->stream_view)); gtk_paned_add2(GTK_PANED(tab), scrolled); gtk_widget_show_all(scrolled); tab->label = st_browser_tab_label_new(tab); gtk_widget_show(tab->label); gtk_paned_set_position(GTK_PANED(tab), st_handler_get_paned_position(tab->handler)); g_signal_connect(tab, "notify::position", G_CALLBACK(st_browser_tab_paned_notify_position_h), NULL); return object;}static voidst_browser_tab_set_property (GObject *object, unsigned int prop_id, const GValue *value, GParamSpec *pspec){ STBrowserTab *tab = ST_BROWSER_TAB(object); switch (prop_id) { case PROP_HANDLER: tab->handler = g_value_get_pointer(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; }}static voidst_browser_tab_get_property (GObject *object, unsigned int prop_id, GValue *value, GParamSpec *pspec){ STBrowserTab *tab = ST_BROWSER_TAB(object); switch (prop_id) { case PROP_RUNNING: g_value_set_boolean(value, tab->running); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; }}GtkWidget *st_browser_tab_new (STHandler *handler){ return g_object_new(ST_TYPE_BROWSER_TAB, "handler", handler, NULL);}voidst_browser_tab_update_sensitivity (STBrowserTab *tab){ g_return_if_fail(ST_IS_BROWSER_TAB(tab)); st_stream_view_update_sensitivity(tab->stream_view);}gbooleanst_browser_tab_can_reload (STBrowserTab *tab){ g_return_val_if_fail(ST_IS_BROWSER_TAB(tab), FALSE); return ST_HANDLER_EVENT_HAS_RELOAD(tab->handler);}voidst_browser_tab_reload (STBrowserTab *tab){ STCategoryBag *category_bag; STThread *task_thread; g_return_if_fail(ST_IS_BROWSER_TAB(tab)); category_bag = st_handler_get_selected_category(tab->handler); g_return_if_fail(category_bag != NULL); task_thread = st_category_bag_get_task_thread(category_bag); if (task_thread) st_thread_abort(task_thread); st_browser_tab_run_category_task(tab, category_bag, st_browser_tab_reload_thread); g_object_unref(category_bag);}static voidst_browser_tab_reload_thread (gpointer data){ CategoryTask *task = data; gboolean status; GNode *categories; STStreamStore *stream_store; GError *err = NULL; GDK_THREADS_ENTER(); st_thread_printf(task->thread, TRUE, _("Reloading...")); gdk_flush(); GDK_THREADS_LEAVE(); if (st_category_bag_apply_url_cb(task->category_bag)) { status = st_handler_reload(task->tab->handler, task->category_bag, &categories, &stream_store, &err); st_thread_validate_callback_return(task->thread, status, err); } else status = FALSE; /* aborted in url_cb */ GDK_THREADS_ENTER(); if (status) { /* defer setting categories */ if (task->tab->priv->pending_categories) sg_objects_free_node(task->tab->priv->pending_categories); task->tab->priv->pending_categories = categories; /* set streams */ st_browser_tab_set_streams(task->tab, task->category_bag, stream_store); if (stream_store) g_object_unref(stream_store); } st_thread_cleanup(task->thread); gdk_flush(); GDK_THREADS_LEAVE(); if (! status && err) { char *normalized; normalized = st_dialog_normalize(err->message); st_error_dialog(_("Unable to reload"), "%s", normalized); g_free(normalized); g_error_free(err); }}static voidst_browser_tab_run_category_task (STBrowserTab *tab, STCategoryBag *category_bag, STThreadCallback callback){ CategoryTask *task; g_return_if_fail(ST_IS_BROWSER_TAB(tab)); g_return_if_fail(ST_IS_CATEGORY_BAG(category_bag)); g_return_if_fail(callback != NULL); task = g_new(CategoryTask, 1); task->tab = g_object_ref(tab); task->category_bag = g_object_ref(category_bag); task->thread = st_thread_new(tab->handler); task->thread->thread = callback; task->thread->print = st_browser_tab_category_task_print_cb; task->thread->set_progress = st_browser_tab_category_task_set_progress_cb; task->thread->cleanup = st_browser_tab_category_task_cleanup_cb; task->thread->data = task; task->thread->data_destroy = st_browser_tab_category_task_data_destroy_cb; st_category_bag_set_task_thread(category_bag, task->thread); st_browser_tab_set_category_running(tab, category_bag, TRUE);}static voidst_browser_tab_category_task_print_cb (const char *str, gpointer data){ CategoryTask *task = data; st_statusbar_print(ST_STATUSBAR(task->category_bag->statusbar), task->category_bag->statusbar_context_task, str);}static voidst_browser_tab_category_task_set_progress_cb (double progress, gpointer data){ CategoryTask *task = data; if (progress < 0) /* -1 means "pulse" */ gtk_progress_bar_pulse(ST_STATUSBAR(task->category_bag->statusbar)->progress_bar); else gtk_progress_bar_set_fraction(ST_STATUSBAR(task->category_bag->statusbar)->progress_bar, progress);}static voidst_browser_tab_category_task_cleanup_cb (gpointer data){ CategoryTask *task = data; st_browser_tab_set_category_running(task->tab, task->category_bag, FALSE);}static voidst_browser_tab_category_task_data_destroy_cb (gpointer data){ CategoryTask *task = data; g_object_unref(task->tab); g_object_unref(task->category_bag); g_free(task);}static voidst_browser_tab_set_category_running (STBrowserTab *tab, STCategoryBag *bag, gboolean running){ g_return_if_fail(ST_IS_BROWSER_TAB(tab));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -