/*
 * transmission-remote-gtk - A GTK RPC client to Transmission
 * Copyright (C) 2011-2013  Alan Fitton

 * This program 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 2 of the License, or
 * (at your option) any later version.

 * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "config.h"

#include <gdk/gdkkeysyms-compat.h>
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>

#include "trg-main-window.h"
#include "trg-menu-bar.h"
#include "trg-prefs.h"
#include "trg-torrent-tree-view.h"
#include "trg-tree-view.h"

enum {
    PROP_0,
    PROP_CONNECT_BUTTON,
    PROP_DISCONNECT_BUTTON,
    PROP_ADD_BUTTON,
    PROP_ADD_URL_BUTTON,
    PROP_REMOVE_BUTTON,
    PROP_DELETE_BUTTON,
    PROP_RESUME_BUTTON,
    PROP_RESUME_ALL_BUTTON,
    PROP_PAUSE_BUTTON,
    PROP_PAUSE_ALL_BUTTON,
    PROP_VERIFY_BUTTON,
    PROP_REANNOUNCE_BUTTON,
    PROP_PROPS_BUTTON,
    PROP_COPYMAGNET_BUTTON,
    PROP_MOVE_BUTTON,
    PROP_REMOTE_PREFS_BUTTON,
    PROP_LOCAL_PREFS_BUTTON,
    PROP_ABOUT_BUTTON,
    PROP_VIEW_STATS_BUTTON,
    PROP_VIEW_STATES_BUTTON,
    PROP_VIEW_NOTEBOOK_BUTTON,
    PROP_QUIT,
    PROP_PREFS,
    PROP_MAIN_WINDOW,
    PROP_TORRENT_TREE_VIEW,
    PROP_ACCEL_GROUP,
    PROP_DIR_FILTERS,
    PROP_TRACKER_FILTERS,
    PROP_DIRECTORIES_FIRST,
    PROP_MOVE_DOWN_QUEUE,
    PROP_MOVE_UP_QUEUE,
    PROP_MOVE_BOTTOM_QUEUE,
    PROP_MOVE_TOP_QUEUE,
    PROP_START_NOW
};

#define G_DATAKEY_CONF_KEY   "conf-key"
#define G_DATAKEY_PREF_VALUE "pref-index"

struct _TrgMenuBar {
    GtkMenuBar parent;

    GtkWidget *mb_connect;
    GtkWidget *mb_disconnect;
    GtkWidget *mb_add;
    GtkWidget *mb_add_url;
    GtkWidget *mb_move;
    GtkWidget *mb_remove;
    GtkWidget *mb_delete;
    GtkWidget *mb_resume;
    GtkWidget *mb_pause;
    GtkWidget *mb_resume_all;
    GtkWidget *mb_pause_all;
    GtkWidget *mb_verify;
    GtkWidget *mb_reannounce;
    GtkWidget *mb_props;
    GtkWidget *mb_copy_magnetlink;
    GtkWidget *mb_local_prefs;
    GtkWidget *mb_remote_prefs;
    GtkWidget *mb_view_states;
    GtkWidget *mb_view_notebook;
    GtkWidget *mb_view_stats;
    GtkWidget *mb_about;
    GtkWidget *mb_quit;
    GtkWidget *mb_directory_filters;
    GtkWidget *mb_tracker_filters;
    GtkWidget *mb_directory_first;
    GtkWidget *mb_down_queue;
    GtkWidget *mb_up_queue;
    GtkWidget *mb_bottom_queue;
    GtkWidget *mb_top_queue;
    GtkWidget *mb_start_now;
    GtkWidget *mb_queues_seperator;
    GtkWidget *mb_view_classic;
    GtkWidget *mb_view_transmission;
    GtkWidget *mb_view_transmission_compact;
    GtkAccelGroup *accel_group;
    TrgPrefs *prefs;
    TrgMainWindow *main_window;
    TrgTorrentTreeView *torrent_tree_view;
};

G_DEFINE_TYPE(TrgMenuBar, trg_menu_bar, GTK_TYPE_MENU_BAR)

void trg_menu_bar_set_supports_queues(TrgMenuBar *mb, gboolean supportsQueues)
{
    gtk_widget_set_visible(mb->mb_down_queue, supportsQueues);
    gtk_widget_set_visible(mb->mb_up_queue, supportsQueues);
    gtk_widget_set_visible(mb->mb_top_queue, supportsQueues);
    gtk_widget_set_visible(mb->mb_bottom_queue, supportsQueues);
    gtk_widget_set_visible(mb->mb_queues_seperator, supportsQueues);
    gtk_widget_set_visible(mb->mb_start_now, supportsQueues);
}

void trg_menu_bar_connected_change(TrgMenuBar *mb, gboolean connected)
{
    gtk_widget_set_sensitive(mb->mb_add, connected);
    gtk_widget_set_sensitive(mb->mb_add_url, connected);
    gtk_widget_set_sensitive(mb->mb_disconnect, connected);
    gtk_widget_set_sensitive(mb->mb_remote_prefs, connected);
    gtk_widget_set_sensitive(mb->mb_view_stats, connected);
    gtk_widget_set_sensitive(mb->mb_resume_all, connected);
    gtk_widget_set_sensitive(mb->mb_pause_all, connected);
}

void trg_menu_bar_torrent_actions_sensitive(TrgMenuBar *mb, gboolean sensitive)
{
    gtk_widget_set_sensitive(mb->mb_props, sensitive);
    gtk_widget_set_sensitive(mb->mb_copy_magnetlink, sensitive);
    gtk_widget_set_sensitive(mb->mb_remove, sensitive);
    gtk_widget_set_sensitive(mb->mb_delete, sensitive);
    gtk_widget_set_sensitive(mb->mb_resume, sensitive);
    gtk_widget_set_sensitive(mb->mb_pause, sensitive);
    gtk_widget_set_sensitive(mb->mb_verify, sensitive);
    gtk_widget_set_sensitive(mb->mb_reannounce, sensitive);
    gtk_widget_set_sensitive(mb->mb_move, sensitive);
    gtk_widget_set_sensitive(mb->mb_start_now, sensitive);
    gtk_widget_set_sensitive(mb->mb_up_queue, sensitive);
    gtk_widget_set_sensitive(mb->mb_down_queue, sensitive);
    gtk_widget_set_sensitive(mb->mb_top_queue, sensitive);
    gtk_widget_set_sensitive(mb->mb_bottom_queue, sensitive);
}

static void trg_menu_bar_set_property(GObject *object, guint prop_id, const GValue *value,
                                      GParamSpec *pspec G_GNUC_UNUSED)
{
    TrgMenuBar *self = TRG_MENU_BAR(object);
    switch (prop_id) {
    case PROP_ACCEL_GROUP:
        self->accel_group = g_value_get_object(value);
        break;
    case PROP_PREFS:
        self->prefs = g_value_get_object(value);
        break;
    case PROP_MAIN_WINDOW:
        self->main_window = g_value_get_object(value);
        break;
    case PROP_TORRENT_TREE_VIEW:
        self->torrent_tree_view = g_value_get_object(value);
        break;
    }
}

static void trg_menu_bar_get_property(GObject *object, guint property_id, GValue *value,
                                      GParamSpec *pspec)
{
    TrgMenuBar *self = TRG_MENU_BAR(object);
    switch (property_id) {
    case PROP_CONNECT_BUTTON:
        g_value_set_object(value, self->mb_connect);
        break;
    case PROP_DISCONNECT_BUTTON:
        g_value_set_object(value, self->mb_disconnect);
        break;
    case PROP_ADD_BUTTON:
        g_value_set_object(value, self->mb_add);
        break;
    case PROP_ADD_URL_BUTTON:
        g_value_set_object(value, self->mb_add_url);
        break;
    case PROP_REMOVE_BUTTON:
        g_value_set_object(value, self->mb_remove);
        break;
    case PROP_DELETE_BUTTON:
        g_value_set_object(value, self->mb_delete);
        break;
    case PROP_MOVE_UP_QUEUE:
        g_value_set_object(value, self->mb_up_queue);
        break;
    case PROP_MOVE_DOWN_QUEUE:
        g_value_set_object(value, self->mb_down_queue);
        break;
    case PROP_MOVE_TOP_QUEUE:
        g_value_set_object(value, self->mb_top_queue);
        break;
    case PROP_MOVE_BOTTOM_QUEUE:
        g_value_set_object(value, self->mb_bottom_queue);
        break;
    case PROP_START_NOW:
        g_value_set_object(value, self->mb_start_now);
        break;
    case PROP_MOVE_BUTTON:
        g_value_set_object(value, self->mb_move);
        break;
    case PROP_RESUME_BUTTON:
        g_value_set_object(value, self->mb_resume);
        break;
    case PROP_RESUME_ALL_BUTTON:
        g_value_set_object(value, self->mb_resume_all);
        break;
    case PROP_PAUSE_BUTTON:
        g_value_set_object(value, self->mb_pause);
        break;
    case PROP_PAUSE_ALL_BUTTON:
        g_value_set_object(value, self->mb_pause_all);
        break;
    case PROP_VERIFY_BUTTON:
        g_value_set_object(value, self->mb_verify);
        break;
    case PROP_REANNOUNCE_BUTTON:
        g_value_set_object(value, self->mb_reannounce);
        break;
    case PROP_PROPS_BUTTON:
        g_value_set_object(value, self->mb_props);
        break;
    case PROP_COPYMAGNET_BUTTON:
        g_value_set_object(value, self->mb_copy_magnetlink);
        break;
    case PROP_REMOTE_PREFS_BUTTON:
        g_value_set_object(value, self->mb_remote_prefs);
        break;
    case PROP_LOCAL_PREFS_BUTTON:
        g_value_set_object(value, self->mb_local_prefs);
        break;
    case PROP_ABOUT_BUTTON:
        g_value_set_object(value, self->mb_about);
        break;
    case PROP_VIEW_STATES_BUTTON:
        g_value_set_object(value, self->mb_view_states);
        break;
    case PROP_VIEW_NOTEBOOK_BUTTON:
        g_value_set_object(value, self->mb_view_notebook);
        break;
    case PROP_VIEW_STATS_BUTTON:
        g_value_set_object(value, self->mb_view_stats);
        break;
    case PROP_QUIT:
        g_value_set_object(value, self->mb_quit);
        break;
    case PROP_DIR_FILTERS:
        g_value_set_object(value, self->mb_directory_filters);
        break;
    case PROP_TRACKER_FILTERS:
        g_value_set_object(value, self->mb_tracker_filters);
        break;
    case PROP_DIRECTORIES_FIRST:
        g_value_set_object(value, self->mb_directory_first);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
        break;
    }
}

static void trg_menu_bar_install_widget_prop(GObjectClass *class, guint propId, const gchar *name,
                                             const gchar *nick)
{
    g_object_class_install_property(class, propId,
                                    g_param_spec_object(name, nick, nick, GTK_TYPE_WIDGET,
                                                        G_PARAM_READABLE | G_PARAM_STATIC_NAME
                                                            | G_PARAM_STATIC_NICK
                                                            | G_PARAM_STATIC_BLURB));
}

GtkWidget *trg_menu_bar_item_new(GtkMenuShell *shell, const gchar *text, gboolean sensitive)
{
    GtkWidget *item = gtk_menu_item_new_with_label(text);
    gtk_menu_item_set_use_underline(GTK_MENU_ITEM(item), TRUE);
    gtk_widget_set_sensitive(item, sensitive);
    gtk_menu_shell_append(shell, item);

    return item;
}

static void trg_menu_bar_accel_add(TrgMenuBar *menu, GtkWidget *item, guint key,
                                   GdkModifierType mods)
{
    gtk_widget_add_accelerator(item, "activate", menu->accel_group, key, mods, GTK_ACCEL_VISIBLE);
}

static void view_menu_radio_item_toggled_cb(GtkCheckMenuItem *w, gpointer data)
{
    TrgPrefs *p = TRG_PREFS(data);
    const gchar *key = (gchar *)g_object_get_data(G_OBJECT(w), G_DATAKEY_CONF_KEY);

    if (gtk_check_menu_item_get_active(w)) {
        gint index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), G_DATAKEY_PREF_VALUE));
        trg_prefs_set_int(p, key, index, TRG_PREFS_GLOBAL);
    }
}

static void view_menu_item_toggled_cb(GtkCheckMenuItem *w, gpointer data)
{
    TrgPrefs *p = TRG_PREFS(data);
    const gchar *key = (gchar *)g_object_get_data(G_OBJECT(w), G_DATAKEY_CONF_KEY);
    trg_prefs_set_bool(p, key, gtk_check_menu_item_get_active(w), TRG_PREFS_GLOBAL);
}

static void view_menu_bar_toggled_dependency_cb(GtkCheckMenuItem *w, gpointer data)
{
    gtk_widget_set_sensitive(GTK_WIDGET(data),
                             gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
}

static void trg_menu_bar_view_item_update(TrgPrefs *p, const gchar *updatedKey, gpointer data)
{
    const gchar *key = (gchar *)g_object_get_data(G_OBJECT(data), G_DATAKEY_CONF_KEY);
    if (!g_strcmp0(updatedKey, key))
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(data),
                                       trg_prefs_get_bool(p, key, TRG_PREFS_GLOBAL));
}

static void trg_menu_bar_view_radio_item_update(TrgPrefs *p, const gchar *updatedKey, gpointer data)
{
    const gchar *key = (gchar *)g_object_get_data(G_OBJECT(data), G_DATAKEY_CONF_KEY);
    gint myIndex = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), G_DATAKEY_PREF_VALUE));

    if (!g_strcmp0(updatedKey, key)) {
        gboolean shouldBeActive = trg_prefs_get_int(p, key, TRG_PREFS_GLOBAL) == myIndex;
        if (shouldBeActive != gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(data)))
            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(data), shouldBeActive);
    }
}

static GtkWidget *trg_menu_bar_view_radio_item_new(TrgPrefs *prefs, GSList *group, const gchar *key,
                                                   gint index, const gchar *label)
{
    GtkWidget *w = gtk_radio_menu_item_new_with_label(group, label);
    g_object_set_data_full(G_OBJECT(w), G_DATAKEY_CONF_KEY, g_strdup(key), g_free);
    g_object_set_data(G_OBJECT(w), G_DATAKEY_PREF_VALUE, GINT_TO_POINTER(index));

    gtk_check_menu_item_set_active(
        GTK_CHECK_MENU_ITEM(w), trg_prefs_get_int(prefs, key, TRG_PREFS_GLOBAL) == (gint64)index);

    g_signal_connect(w, "toggled", G_CALLBACK(view_menu_radio_item_toggled_cb), prefs);
    g_signal_connect(prefs, "pref-changed", G_CALLBACK(trg_menu_bar_view_radio_item_update), w);

    return w;
}

static GtkWidget *trg_menu_bar_view_item_new(TrgPrefs *prefs, const gchar *key, const gchar *label,
                                             GtkWidget *dependency)
{
    GtkWidget *w = gtk_check_menu_item_new_with_label(label);
    g_object_set_data_full(G_OBJECT(w), G_DATAKEY_CONF_KEY, g_strdup(key), g_free);

    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
                                   trg_prefs_get_bool(prefs, key, TRG_PREFS_GLOBAL));

    if (dependency) {
        gtk_widget_set_sensitive(w,
                                 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(dependency)));
        g_signal_connect(dependency, "toggled", G_CALLBACK(view_menu_bar_toggled_dependency_cb), w);
    }

    g_signal_connect(w, "toggled", G_CALLBACK(view_menu_item_toggled_cb), prefs);
    g_signal_connect(prefs, "pref-changed", G_CALLBACK(trg_menu_bar_view_item_update), w);

    return w;
}

static GtkWidget *trg_menu_bar_view_menu_new(TrgMenuBar *mb)
{
    GtkWidget *view = gtk_menu_item_new_with_mnemonic(_("_View"));
    GtkWidget *viewMenu = gtk_menu_new();
    GSList *group;

    gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), viewMenu);

    mb->mb_view_transmission = trg_menu_bar_view_radio_item_new(
        mb->prefs, NULL, TRG_PREFS_KEY_STYLE, TRG_STYLE_TR, _("Transmission Style"));
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_view_transmission);
    group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mb->mb_view_transmission));
    mb->mb_view_transmission_compact
        = trg_menu_bar_view_radio_item_new(mb->prefs, group, TRG_PREFS_KEY_STYLE,
                                           TRG_STYLE_TR_COMPACT, _("Transmission Compact Style"));
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_view_transmission_compact);
    group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mb->mb_view_transmission_compact));
    mb->mb_view_classic = trg_menu_bar_view_radio_item_new(mb->prefs, group, TRG_PREFS_KEY_STYLE,
                                                           TRG_STYLE_CLASSIC, _("Classic Style"));
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_view_classic);

    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu),
                          trg_tree_view_sort_menu(TRG_TREE_VIEW(mb->torrent_tree_view), _("Sort")));

    mb->mb_view_states = trg_menu_bar_view_item_new(mb->prefs, TRG_PREFS_KEY_SHOW_STATE_SELECTOR,
                                                    _("State selector"), NULL);
    trg_menu_bar_accel_add(mb, mb->mb_view_states, GDK_F2, 0);
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_view_states);

    mb->mb_directory_filters = trg_menu_bar_view_item_new(
        mb->prefs, TRG_PREFS_KEY_FILTER_DIRS, _("Directory filters"), mb->mb_view_states);
    trg_menu_bar_accel_add(mb, mb->mb_directory_filters, GDK_F3, 0);
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_directory_filters);

    mb->mb_tracker_filters = trg_menu_bar_view_item_new(mb->prefs, TRG_PREFS_KEY_FILTER_TRACKERS,
                                                        _("Tracker filters"), mb->mb_view_states);
    trg_menu_bar_accel_add(mb, mb->mb_tracker_filters, GDK_F4, 0);
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_tracker_filters);

    mb->mb_directory_first = trg_menu_bar_view_item_new(mb->prefs, TRG_PREFS_KEY_DIRECTORIES_FIRST,
                                                        _("Directories first"), mb->mb_view_states);
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_directory_first);

    mb->mb_view_notebook = trg_menu_bar_view_item_new(mb->prefs, TRG_PREFS_KEY_SHOW_NOTEBOOK,
                                                      _("Torrent Details"), NULL);
    trg_menu_bar_accel_add(mb, mb->mb_view_notebook, GDK_F5, 0);
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_view_notebook);

    mb->mb_view_stats = gtk_menu_item_new_with_mnemonic(_("_Statistics"));
    trg_menu_bar_accel_add(mb, mb->mb_view_stats, GDK_F7, 0);
    gtk_widget_set_sensitive(mb->mb_view_stats, FALSE);
    gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), mb->mb_view_stats);

    return view;
}

static GtkWidget *trg_menu_bar_options_menu_new(TrgMenuBar *mb)
{
    GtkWidget *opts = gtk_menu_item_new_with_mnemonic(_("_Options"));
    GtkWidget *optsMenu = gtk_menu_new();
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(opts), optsMenu);

    mb->mb_local_prefs
        = trg_menu_bar_item_new(GTK_MENU_SHELL(optsMenu), _("_Local Preferences"), TRUE);
    trg_menu_bar_accel_add(mb, mb->mb_local_prefs, GDK_s, GDK_CONTROL_MASK);

    mb->mb_remote_prefs
        = trg_menu_bar_item_new(GTK_MENU_SHELL(optsMenu), _("_Remote Preferences"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_remote_prefs, GDK_s, GDK_MOD1_MASK);

    return opts;
}

static void trg_menu_bar_file_connect_item_new(TrgMainWindow *win, GtkMenuShell *shell,
                                               const gchar *text, gboolean checked,
                                               JsonObject *profile)
{
    GtkWidget *item = gtk_check_menu_item_new_with_label(text);

    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), checked);
    g_object_set_data(G_OBJECT(item), "profile", profile);
    gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(item), TRUE);

    g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(connect_cb), win);

    gtk_menu_shell_append(shell, item);
}

GtkWidget *trg_menu_bar_file_connect_menu_new(TrgMainWindow *win, TrgPrefs *p)
{
    GtkWidget *menu = gtk_menu_new();
    GList *profiles = json_array_get_elements(trg_prefs_get_profiles(p));
    JsonObject *currentProfile = trg_prefs_get_profile(p);
    GList *li;

    for (li = profiles; li; li = g_list_next(li)) {
        JsonObject *profile = json_node_get_object((JsonNode *)li->data);
        const gchar *name_value;

        if (json_object_has_member(profile, TRG_PREFS_KEY_PROFILE_NAME)) {
            name_value = json_object_get_string_member(profile, TRG_PREFS_KEY_PROFILE_NAME);
        } else {
            name_value = _(TRG_PROFILE_NAME_DEFAULT);
        }

        trg_menu_bar_file_connect_item_new(win, GTK_MENU_SHELL(menu), name_value,
                                           profile == currentProfile, profile);
    }

    g_list_free(profiles);

    return menu;
}

static GtkWidget *trg_menu_bar_file_file_menu_new(TrgMenuBar *mb)
{
    GtkWidget *file = gtk_menu_item_new_with_mnemonic(_("_File"));
    GtkWidget *fileMenu = gtk_menu_new();

    GtkWidget *connectMenu = trg_menu_bar_file_connect_menu_new(mb->main_window, mb->prefs);

    mb->mb_connect = trg_menu_bar_item_new(GTK_MENU_SHELL(fileMenu), _("Connect"), TRUE);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(mb->mb_connect), connectMenu);

    mb->mb_disconnect = trg_menu_bar_item_new(GTK_MENU_SHELL(fileMenu), _("_Disconnect"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_disconnect, GDK_d, GDK_CONTROL_MASK);

    mb->mb_add = trg_menu_bar_item_new(GTK_MENU_SHELL(fileMenu), _("_Add"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_add, GDK_o, GDK_CONTROL_MASK);

    mb->mb_add_url = trg_menu_bar_item_new(GTK_MENU_SHELL(fileMenu), _("Add from _URL"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_add_url, GDK_u, GDK_CONTROL_MASK);

    mb->mb_quit = trg_menu_bar_item_new(GTK_MENU_SHELL(fileMenu), _("_Quit"), TRUE);
    trg_menu_bar_accel_add(mb, mb->mb_quit, GDK_q, GDK_CONTROL_MASK);

    gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), fileMenu);

    return file;
}

static GtkWidget *trg_menu_bar_torrent_menu_new(TrgMenuBar *mb)
{
    GtkWidget *torrent = gtk_menu_item_new_with_mnemonic(_("_Torrent"));
    GtkWidget *torrentMenu = gtk_menu_new();

    gtk_menu_item_set_submenu(GTK_MENU_ITEM(torrent), torrentMenu);

    mb->mb_props = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Properties"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_props, GDK_i, GDK_CONTROL_MASK);

    mb->mb_copy_magnetlink
        = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("_Copy Magnet Link"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_copy_magnetlink, GDK_c, GDK_CONTROL_MASK);

    mb->mb_resume = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("_Resume"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_resume, GDK_r, GDK_CONTROL_MASK);

    mb->mb_pause = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("_Pause"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_pause, GDK_p, GDK_CONTROL_MASK);

    mb->mb_verify = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("_Verify"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_verify, GDK_h, GDK_CONTROL_MASK);

    mb->mb_reannounce
        = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Re-_announce"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_reannounce, GDK_q, GDK_CONTROL_MASK);

    mb->mb_move = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("_Move"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_move, GDK_m, GDK_CONTROL_MASK);

    mb->mb_remove = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Remove"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_remove, GDK_Delete, 0);

    mb->mb_delete
        = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Remove and delete data"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_delete, GDK_Delete, GDK_SHIFT_MASK);

    mb->mb_queues_seperator = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(torrentMenu), mb->mb_queues_seperator);

    mb->mb_start_now = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Start Now"), FALSE);

    mb->mb_up_queue = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Move Up Queue"), FALSE);

    mb->mb_down_queue
        = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Move Down Queue"), FALSE);

    mb->mb_bottom_queue
        = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Bottom Of Queue"), FALSE);

    mb->mb_top_queue = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("Top Of Queue"), FALSE);

    gtk_menu_shell_append(GTK_MENU_SHELL(torrentMenu), gtk_separator_menu_item_new());

    mb->mb_resume_all = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("_Resume All"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_resume_all, GDK_r, GDK_SHIFT_MASK | GDK_CONTROL_MASK);

    mb->mb_pause_all = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), _("_Pause All"), FALSE);
    trg_menu_bar_accel_add(mb, mb->mb_pause_all, GDK_p, GDK_SHIFT_MASK | GDK_CONTROL_MASK);

    return torrent;
}

static GtkWidget *trg_menu_bar_help_menu_new(TrgMenuBar *menuBar)
{
    GtkWidget *help = gtk_menu_item_new_with_mnemonic(_("_Help"));
    GtkWidget *helpMenu = gtk_menu_new();
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(help), helpMenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), help);

    menuBar->mb_about = trg_menu_bar_item_new(GTK_MENU_SHELL(helpMenu), _("_About"), TRUE);

    return helpMenu;
}

static void menu_bar_refresh_menu(GtkWidget *w, gpointer data)
{
    TrgMenuBar *mb = TRG_MENU_BAR(data);
    GtkWidget *old = gtk_menu_item_get_submenu(GTK_MENU_ITEM(mb->mb_connect));
    GtkWidget *new = trg_menu_bar_file_connect_menu_new(mb->main_window, mb->prefs);

    gtk_widget_destroy(old);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(mb->mb_connect), new);
    gtk_widget_show_all(new);
}

static GObject *trg_menu_bar_constructor(GType type, guint n_construct_properties,
                                         GObjectConstructParam *construct_params)
{
    GObject *object;
    TrgMenuBar *menu;

    object = G_OBJECT_CLASS(trg_menu_bar_parent_class)
                 ->constructor(type, n_construct_properties, construct_params);
    menu = TRG_MENU_BAR(object);

    gtk_menu_shell_append(GTK_MENU_SHELL(object), trg_menu_bar_file_file_menu_new(menu));
    gtk_menu_shell_append(GTK_MENU_SHELL(object), trg_menu_bar_torrent_menu_new(menu));
    gtk_menu_shell_append(GTK_MENU_SHELL(object), trg_menu_bar_options_menu_new(menu));
    gtk_menu_shell_append(GTK_MENU_SHELL(object), trg_menu_bar_view_menu_new(menu));
    trg_menu_bar_help_menu_new(TRG_MENU_BAR(object));

    g_signal_connect(G_OBJECT(menu->prefs), "pref-profile-changed",
                     G_CALLBACK(menu_bar_refresh_menu), object);

    return object;
}

static void trg_menu_bar_class_init(TrgMenuBarClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS(klass);
    object_class->get_property = trg_menu_bar_get_property;
    object_class->set_property = trg_menu_bar_set_property;
    object_class->constructor = trg_menu_bar_constructor;

    trg_menu_bar_install_widget_prop(object_class, PROP_CONNECT_BUTTON, "connect-button",
                                     "Connect Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_DISCONNECT_BUTTON, "disconnect-button",
                                     "Disconnect Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_ADD_BUTTON, "add-button", "Add Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_ADD_URL_BUTTON, "add-url-button",
                                     "Add URL Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_REMOVE_BUTTON, "remove-button",
                                     "Remove Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_MOVE_BUTTON, "move-button", "Move Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_DELETE_BUTTON, "delete-button",
                                     "Delete Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_RESUME_BUTTON, "resume-button",
                                     "Resume Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_RESUME_ALL_BUTTON, "resume-all-button",
                                     "Resume All Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_VERIFY_BUTTON, "verify-button",
                                     "Verify Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_REANNOUNCE_BUTTON, "reannounce-button",
                                     "Re-announce Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_PAUSE_ALL_BUTTON, "pause-all-button",
                                     "Pause All Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_PAUSE_BUTTON, "pause-button",
                                     "Pause Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_PROPS_BUTTON, "props-button",
                                     "Props Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_COPYMAGNET_BUTTON, "copymagnet-button",
                                     "Copy-magnet Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_ABOUT_BUTTON, "about-button",
                                     "About Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_VIEW_STATS_BUTTON, "view-stats-button",
                                     "View stats button");
    trg_menu_bar_install_widget_prop(object_class, PROP_VIEW_STATES_BUTTON, "view-states-button",
                                     "View states Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_VIEW_NOTEBOOK_BUTTON,
                                     "view-notebook-button", "View notebook Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_REMOTE_PREFS_BUTTON, "remote-prefs-button",
                                     "Remote Prefs Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_LOCAL_PREFS_BUTTON, "local-prefs-button",
                                     "Local Prefs Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_QUIT, "quit-button", "Quit Button");
    trg_menu_bar_install_widget_prop(object_class, PROP_DIR_FILTERS, "dir-filters", "Dir Filters");
    trg_menu_bar_install_widget_prop(object_class, PROP_TRACKER_FILTERS, "tracker-filters",
                                     "Tracker Filters");
    trg_menu_bar_install_widget_prop(object_class, PROP_DIRECTORIES_FIRST,
                                     TRG_PREFS_KEY_DIRECTORIES_FIRST, "Directories first");
    trg_menu_bar_install_widget_prop(object_class, PROP_MOVE_DOWN_QUEUE, "down-queue",
                                     "Down Queue");
    trg_menu_bar_install_widget_prop(object_class, PROP_MOVE_UP_QUEUE, "up-queue", "Up Queue");
    trg_menu_bar_install_widget_prop(object_class, PROP_MOVE_BOTTOM_QUEUE, "bottom-queue",
                                     "Bottom Queue");
    trg_menu_bar_install_widget_prop(object_class, PROP_MOVE_TOP_QUEUE, "top-queue", "Top Queue");
    trg_menu_bar_install_widget_prop(object_class, PROP_START_NOW, "start-now", "Start Now");

    g_object_class_install_property(
        object_class, PROP_PREFS,
        g_param_spec_object("prefs", "prefs", "Prefs", TRG_TYPE_PREFS,
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME
                                | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_ACCEL_GROUP,
        g_param_spec_object("accel-group", "accel-group", "accel-group", GTK_TYPE_ACCEL_GROUP,
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME
                                | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_MAIN_WINDOW,
        g_param_spec_object("mainwin", "mainwin", "mainwin", TRG_TYPE_MAIN_WINDOW,
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME
                                | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_TORRENT_TREE_VIEW,
        g_param_spec_object("torrent-tree-view", "torrent-tree-view", "torrent-tree-view",
                            TRG_TYPE_TORRENT_TREE_VIEW,
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME
                                | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
}

static void trg_menu_bar_init(TrgMenuBar *self)
{
}

TrgMenuBar *trg_menu_bar_new(TrgMainWindow *win, TrgPrefs *prefs, TrgTorrentTreeView *ttv,
                             GtkAccelGroup *accel_group)
{
    return g_object_new(TRG_TYPE_MENU_BAR, "torrent-tree-view", ttv, "prefs", prefs, "mainwin", win,
                        "accel-group", accel_group, NULL);
}
