/*
 * This file is part of roccat-tools.
 *
 * roccat-tools 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.
 *
 * roccat-tools 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 roccat-tools. If not, see <http://www.gnu.org/licenses/>.
 */

#include <gaminggear/gaminggear_macro_dialog.h>
#include <gaminggear/key_translations.h>
#include <gaminggear/gdk_key_translations.h>
#include "tyon_key_combo_box.h"
#include "tyon_profile_buttons.h"
#include "roccat_talk_target_dialog.h"
#include "roccat_shortcut_dialog.h"
#include "roccat_timer_dialog.h"
#include "roccat_warning_dialog.h"
#include "roccat_helper.h"
#include "roccat_talk.h"
#include "gtk_roccat_helper.h"

#define TYON_KEY_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYON_KEY_COMBO_BOX_TYPE, TyonKeyComboBoxClass))
#define IS_TYON_KEY_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYON_KEY_COMBO_BOX_TYPE))
#define TYON_KEY_COMBO_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYON_KEY_COMBO_BOX_TYPE, TyonKeyComboBoxClass))
#define TYON_KEY_COMBO_BOX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TYON_KEY_COMBO_BOX_TYPE, TyonKeyComboBoxPrivate))

typedef struct _TyonKeyComboBoxClass TyonKeyComboBoxClass;
typedef struct _TyonKeyComboBoxPrivate TyonKeyComboBoxPrivate;

struct _TyonKeyComboBox {
	RoccatKeyComboBox parent;
	TyonKeyComboBoxPrivate *priv;
};

struct _TyonKeyComboBoxClass {
	RoccatKeyComboBoxClass parent_class;
	GtkTreeModel *model;
};

struct _TyonKeyComboBoxPrivate {
	TyonRmpMacroKeyInfo *key_info;
	gulong changed_handler_id;
};

G_DEFINE_TYPE(TyonKeyComboBox, tyon_key_combo_box, ROCCAT_KEY_COMBO_BOX_TYPE);

static gchar *shortcut_name(TyonRmpMacroKeyInfo const *macro_key_info) {
	return roccat_shortcut_dialog_create_name(roccat_get_bit(macro_key_info->keystrokes[0].action, TYON_BUTTON_MODIFIER_BIT_CTRL),
			roccat_get_bit(macro_key_info->keystrokes[0].action, TYON_BUTTON_MODIFIER_BIT_SHIFT),
			roccat_get_bit(macro_key_info->keystrokes[0].action, TYON_BUTTON_MODIFIER_BIT_ALT),
			roccat_get_bit(macro_key_info->keystrokes[0].action, TYON_BUTTON_MODIFIER_BIT_WIN),
			macro_key_info->keystrokes[0].key);
}

static void set_text(TyonKeyComboBox *key_combo_box) {
	TyonKeyComboBoxPrivate *priv = key_combo_box->priv;
	gchar *text;
	gchar *temp;

	switch (priv->key_info->type) {
	case TYON_BUTTON_TYPE_SHORTCUT:
		temp = shortcut_name(priv->key_info);
		text = g_strdup_printf("Shortcut: %s", temp);
		g_free(temp);
		break;
	case TYON_BUTTON_TYPE_MACRO:
		text = g_strdup_printf("Macro: %s/%s", (gchar const *)priv->key_info->macroset_name, (gchar const *)priv->key_info->macro_name);
		break;
	case TYON_BUTTON_TYPE_QUICKLAUNCH:
		temp = g_path_get_basename((gchar const *)priv->key_info->filename);
		text = g_strdup_printf("Quicklaunch: %s", temp);
		g_free(temp);
		break;
	case TYON_BUTTON_TYPE_TIMER:
		text = g_strdup_printf("Timer: %s", (gchar const *)priv->key_info->timer_name);
		break;
	case TYON_BUTTON_TYPE_EASYSHIFT_OTHER:
		text = g_strdup_printf("Easyshift: %s", roccat_talk_device_get_text_static(tyon_rmp_macro_key_info_get_talk_device(priv->key_info)));
		break;
	case TYON_BUTTON_TYPE_EASYSHIFT_LOCK_OTHER:
		text = g_strdup_printf("Easyshift Lock: %s", roccat_talk_device_get_text_static(tyon_rmp_macro_key_info_get_talk_device(priv->key_info)));
		break;
	default:
		text = roccat_key_combo_box_model_get_title_for_type(gtk_combo_box_get_model(GTK_COMBO_BOX(key_combo_box)), priv->key_info->type);
		break;
	}

	g_signal_handler_block(G_OBJECT(key_combo_box), priv->changed_handler_id);
	roccat_key_combo_box_set_text(ROCCAT_KEY_COMBO_BOX(key_combo_box), text);
	g_signal_handler_unblock(G_OBJECT(key_combo_box), priv->changed_handler_id);

	g_free(text);
}

static TyonRmpMacroKeyInfo *button_quicklaunch(GtkWindow *parent) {
	GtkWidget *dialog;
	gchar *filename;
	TyonRmpMacroKeyInfo *key_info = NULL;

	dialog = gtk_file_chooser_dialog_new("Select executable",
			parent,
			GTK_FILE_CHOOSER_ACTION_OPEN,
			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
			GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
			NULL
	);

	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
		key_info = tyon_rmp_macro_key_info_new_quicklaunch(filename);
		g_free(filename);
	}
	gtk_widget_destroy(dialog);
	return key_info;
}

static TyonRmpMacroKeyInfo *button_macro(GtkWindow *parent) {
	GaminggearMacro *gaminggear_macro;
	TyonRmpMacroKeyInfo *key_info = NULL;
	GError *local_error = NULL;

	gaminggear_macro = gaminggear_macro_dialog(parent);
	if (!gaminggear_macro)
		return NULL;

	key_info = gaminggear_macro_to_tyon_rmp_macro_key_info(gaminggear_macro, &local_error);
	gaminggear_macro_free(gaminggear_macro);
	if (!key_info)
		roccat_handle_error_dialog(parent, "Can't convert macro", &local_error);

	return key_info;
}

static TyonRmpMacroKeyInfo *button_shortcut(GtkWindow *parent) {
	RoccatShortcutDialog *dialog;
	TyonRmpMacroKeyInfo *key_info = NULL;

	dialog = ROCCAT_SHORTCUT_DIALOG(roccat_shortcut_dialog_new(parent));
	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
		key_info = tyon_rmp_macro_key_info_new_shortcut(
				gaminggear_xkeycode_to_hid(roccat_shortcut_dialog_get_xkeycode(dialog)),
				tyon_rmp_macro_key_info_build_shortcut_modifier(
						roccat_shortcut_dialog_get_ctrl(dialog),
						roccat_shortcut_dialog_get_shift(dialog),
						roccat_shortcut_dialog_get_alt(dialog),
						roccat_shortcut_dialog_get_win(dialog)));
	}
	gtk_widget_destroy(GTK_WIDGET(dialog));
	return key_info;
}

static TyonRmpMacroKeyInfo *button_timer(GtkWindow *parent) {
	TyonRmpMacroKeyInfo *key_info = NULL;
	RoccatTimer *timer;

	timer = roccat_timer_dialog(parent);

	if (timer) {
		key_info = tyon_rmp_macro_key_info_new_timer(timer->name, roccat_timer_get_seconds(timer));
		roccat_timer_free(timer);
	}

	return key_info;
}

static TyonRmpMacroKeyInfo *button_talk_other(TyonKeyComboBox *key_combo_box, gint key_type) {
	TyonKeyComboBoxPrivate *priv = key_combo_box->priv;
	RoccatTalkTargetDialog *talk_target_dialog;
	guint target;
	TyonRmpMacroKeyInfo *new_key_info = NULL;

	talk_target_dialog = ROCCAT_TALK_TARGET_DIALOG(roccat_talk_target_dialog_new(
			gtk_roccat_widget_get_gtk_window(GTK_WIDGET(key_combo_box)), ROCCAT_TALK_DEVICE_MOUSE));

	roccat_talk_target_dialog_set_value(talk_target_dialog, tyon_rmp_macro_key_info_get_talk_device(priv->key_info));

	if (gtk_dialog_run(GTK_DIALOG(talk_target_dialog)) == GTK_RESPONSE_ACCEPT) {
		target = roccat_talk_target_dialog_get_value(talk_target_dialog);
		new_key_info = tyon_rmp_macro_key_info_new_talk(key_type, target);
	}

	gtk_widget_destroy(GTK_WIDGET(talk_target_dialog));

	return new_key_info;
}

static TyonRmpMacroKeyInfo *get_macro_key_info(TyonKeyComboBox *key_combo_box, gint type) {
	GtkWindow *parent = gtk_roccat_widget_get_gtk_window(GTK_WIDGET(key_combo_box));
	TyonRmpMacroKeyInfo *key_info;

	switch (type) {
	case TYON_BUTTON_TYPE_MACRO:
		key_info = button_macro(parent);
		break;
	case TYON_BUTTON_TYPE_SHORTCUT:
		key_info = button_shortcut(parent);
		break;
	case TYON_BUTTON_TYPE_QUICKLAUNCH:
		key_info = button_quicklaunch(parent);
		break;
	case TYON_BUTTON_TYPE_TIMER:
		key_info = button_timer(parent);
		break;
	case TYON_BUTTON_TYPE_EASYSHIFT_OTHER:
	case TYON_BUTTON_TYPE_EASYSHIFT_LOCK_OTHER:
		key_info = button_talk_other(key_combo_box, type);
		break;
	case TYON_BUTTON_TYPE_EASYSHIFT_ALL:
		key_info = tyon_rmp_macro_key_info_new_talk(type, ROCCAT_TALK_DEVICE_ALL);
		break;
	default:
		key_info = tyon_rmp_macro_key_info_new_special(type);
	}

	return key_info;
}

static void button_changed_cb(GtkComboBox *combo, gpointer user_data) {
	TyonKeyComboBox *key_combo_box = TYON_KEY_COMBO_BOX(combo);
	TyonKeyComboBoxPrivate *priv = key_combo_box->priv;
	gint type_data;
	TyonRmpMacroKeyInfo *new_key_info;

	type_data = roccat_key_combo_box_get_active_type(ROCCAT_KEY_COMBO_BOX(combo));
	if (type_data == ROCCAT_KEY_COMBO_BOX_TYPE_NONE)
		return;

	new_key_info = get_macro_key_info(key_combo_box, type_data);
	if (new_key_info) {
		tyon_rmp_macro_key_info_free(priv->key_info);
		priv->key_info = new_key_info;
	}
	set_text(key_combo_box);
}

GtkWidget *tyon_key_combo_box_new(guint mask) {
	TyonKeyComboBox *key_combo_box;
	TyonKeyComboBoxClass *key_combo_box_class;
	TyonKeyComboBoxPrivate *priv;

	key_combo_box = TYON_KEY_COMBO_BOX(g_object_new(TYON_KEY_COMBO_BOX_TYPE,
			"exclude-mask", mask,
			NULL));

	priv = key_combo_box->priv;

	key_combo_box_class = TYON_KEY_COMBO_BOX_GET_CLASS(key_combo_box);
	roccat_key_combo_box_set_model(ROCCAT_KEY_COMBO_BOX(key_combo_box), key_combo_box_class->model);

	priv->changed_handler_id = g_signal_connect(G_OBJECT(key_combo_box), "changed", G_CALLBACK(button_changed_cb), NULL);

	return GTK_WIDGET(key_combo_box);
}

static void tyon_key_combo_box_init(TyonKeyComboBox *key_combo_box) {
	TyonKeyComboBoxPrivate *priv = TYON_KEY_COMBO_BOX_GET_PRIVATE(key_combo_box);
	key_combo_box->priv = priv;
}

static GtkTreeModel *button_info_model_new(void) {
	GtkTreeStore *store;
	GtkTreeIter toplevel, sublevel;

	store = roccat_key_combo_box_store_new();

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Buttons", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Button 1", TYON_BUTTON_TYPE_CLICK, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Button 2", TYON_BUTTON_TYPE_MENU, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Button 3", TYON_BUTTON_TYPE_UNIVERSAL_SCROLLING, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Button 6", TYON_BUTTON_TYPE_TILT_RIGHT, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Button 7", TYON_BUTTON_TYPE_TILT_LEFT, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Button 8", TYON_BUTTON_TYPE_IE_BACKWARD, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Button 9", TYON_BUTTON_TYPE_IE_FORWARD, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Double click", TYON_BUTTON_TYPE_DOUBLE_CLICK, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Scroll up", TYON_BUTTON_TYPE_SCROLL_UP, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Scroll down", TYON_BUTTON_TYPE_SCROLL_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "CPI", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, NULL, &toplevel, "CPI cycle", TYON_BUTTON_TYPE_CPI_CYCLE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "CPI up", TYON_BUTTON_TYPE_CPI_UP, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "CPI down", TYON_BUTTON_TYPE_CPI_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Multimedia", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Open player", TYON_BUTTON_TYPE_OPEN_PLAYER, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Previous track", TYON_BUTTON_TYPE_PREV_TRACK, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Next track", TYON_BUTTON_TYPE_NEXT_TRACK, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Play/Pause", TYON_BUTTON_TYPE_PLAY_PAUSE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Stop", TYON_BUTTON_TYPE_STOP, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Mute", TYON_BUTTON_TYPE_MUTE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Volume up", TYON_BUTTON_TYPE_VOLUME_UP, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Volume down", TYON_BUTTON_TYPE_VOLUME_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Profile", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Profile cycle", TYON_BUTTON_TYPE_PROFILE_CYCLE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Profile up", TYON_BUTTON_TYPE_PROFILE_UP, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Profile down", TYON_BUTTON_TYPE_PROFILE_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Sensitivity", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Sensitivity cycle", TYON_BUTTON_TYPE_SENSITIVITY_CYCLE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Sensitivity up", TYON_BUTTON_TYPE_SENSITIVITY_UP, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Sensitivity down", TYON_BUTTON_TYPE_SENSITIVITY_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Easywheel", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easywheel Sensitivity", TYON_BUTTON_TYPE_EASYWHEEL_SENSITIVITY, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easywheel Profile", TYON_BUTTON_TYPE_EASYWHEEL_PROFILE, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easywheel CPI", TYON_BUTTON_TYPE_EASYWHEEL_CPI, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easywheel Volume", TYON_BUTTON_TYPE_EASYWHEEL_VOLUME, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easywheel Alt Tab", TYON_BUTTON_TYPE_EASYWHEEL_ALT_TAB, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easywheel Aero Flip 3D", TYON_BUTTON_TYPE_EASYWHEEL_AERO_FLIP_3D, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Easyaim", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easyaim Setting 1", TYON_BUTTON_TYPE_EASYAIM_1, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easyaim Setting 2", TYON_BUTTON_TYPE_EASYAIM_2, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easyaim Setting 3", TYON_BUTTON_TYPE_EASYAIM_3, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easyaim Setting 4", TYON_BUTTON_TYPE_EASYAIM_4, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Easyaim Setting 5", TYON_BUTTON_TYPE_EASYAIM_5, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Easyshift", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, &sublevel, &toplevel, "Self", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &sublevel, "Self Easyshift", TYON_BUTTON_TYPE_EASYSHIFT_SELF, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, &sublevel, &toplevel, "Other", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &sublevel, "Other Easyshift", TYON_BUTTON_TYPE_EASYSHIFT_OTHER, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, NULL, &sublevel, "Other Easyshift lock", TYON_BUTTON_TYPE_EASYSHIFT_LOCK_OTHER, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);
	roccat_key_combo_box_store_append(store, &sublevel, &toplevel, "Both", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &sublevel, "Both Easyshift", TYON_BUTTON_TYPE_EASYSHIFT_ALL, ROCCAT_KEY_COMBO_BOX_GROUP_EASYSHIFT);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Timer", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Timer start", TYON_BUTTON_TYPE_TIMER, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Timer stop", TYON_BUTTON_TYPE_TIMER_STOP, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "XInput", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 1", TYON_BUTTON_TYPE_XINPUT_1, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 2", TYON_BUTTON_TYPE_XINPUT_2, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 3", TYON_BUTTON_TYPE_XINPUT_3, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 4", TYON_BUTTON_TYPE_XINPUT_4, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 5", TYON_BUTTON_TYPE_XINPUT_5, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 6", TYON_BUTTON_TYPE_XINPUT_6, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 7", TYON_BUTTON_TYPE_XINPUT_7, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 8", TYON_BUTTON_TYPE_XINPUT_8, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 9", TYON_BUTTON_TYPE_XINPUT_9, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput 10", TYON_BUTTON_TYPE_XINPUT_10, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Rx up", TYON_BUTTON_TYPE_XINPUT_RX_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Rx down", TYON_BUTTON_TYPE_XINPUT_RX_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Ry up", TYON_BUTTON_TYPE_XINPUT_RY_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Rx down", TYON_BUTTON_TYPE_XINPUT_RY_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput X up", TYON_BUTTON_TYPE_XINPUT_X_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput X down", TYON_BUTTON_TYPE_XINPUT_X_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Y up", TYON_BUTTON_TYPE_XINPUT_Y_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Y down", TYON_BUTTON_TYPE_XINPUT_Y_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Z up", TYON_BUTTON_TYPE_XINPUT_Z_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "XInput Z down", TYON_BUTTON_TYPE_XINPUT_Z_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "DInput", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 1", TYON_BUTTON_TYPE_DINPUT_1, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 2", TYON_BUTTON_TYPE_DINPUT_2, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 3", TYON_BUTTON_TYPE_DINPUT_3, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 4", TYON_BUTTON_TYPE_DINPUT_4, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 5", TYON_BUTTON_TYPE_DINPUT_5, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 6", TYON_BUTTON_TYPE_DINPUT_6, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 7", TYON_BUTTON_TYPE_DINPUT_7, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 8", TYON_BUTTON_TYPE_DINPUT_8, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 9", TYON_BUTTON_TYPE_DINPUT_9, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 10", TYON_BUTTON_TYPE_DINPUT_10, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 11", TYON_BUTTON_TYPE_DINPUT_11, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput 12", TYON_BUTTON_TYPE_DINPUT_12, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput X up", TYON_BUTTON_TYPE_DINPUT_X_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput X down", TYON_BUTTON_TYPE_DINPUT_X_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput Y up", TYON_BUTTON_TYPE_DINPUT_Y_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput Y down", TYON_BUTTON_TYPE_DINPUT_Y_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput Z up", TYON_BUTTON_TYPE_DINPUT_Z_UP, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "DInput Z down", TYON_BUTTON_TYPE_DINPUT_Z_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_ANALOG);

	roccat_key_combo_box_store_append(store, &toplevel, NULL, "Shortcuts", ROCCAT_KEY_COMBO_BOX_TYPE_NONE, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Shortcut", TYON_BUTTON_TYPE_SHORTCUT, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Windows key", TYON_BUTTON_TYPE_WINDOWS_KEY, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Home", TYON_BUTTON_TYPE_HOME, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "End", TYON_BUTTON_TYPE_END, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Page up", TYON_BUTTON_TYPE_PAGE_UP, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Page down", TYON_BUTTON_TYPE_PAGE_DOWN, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Left ctrl", TYON_BUTTON_TYPE_L_CTRL, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);
	roccat_key_combo_box_store_append(store, NULL, &toplevel, "Right ctrl", TYON_BUTTON_TYPE_R_CTRL, ROCCAT_KEY_COMBO_BOX_GROUP_SHORTCUT);

	roccat_key_combo_box_store_append(store, NULL, NULL, "Macro", TYON_BUTTON_TYPE_MACRO, ROCCAT_KEY_COMBO_BOX_GROUP_MACRO);
	roccat_key_combo_box_store_append(store, NULL, NULL, "Quicklaunch", TYON_BUTTON_TYPE_QUICKLAUNCH, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, NULL, "Open driver", TYON_BUTTON_TYPE_OPEN_DRIVER, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	roccat_key_combo_box_store_append(store, NULL, NULL, "Unused", TYON_BUTTON_TYPE_UNUSED, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);
	roccat_key_combo_box_store_append(store, NULL, NULL, "Disabled", TYON_BUTTON_TYPE_DISABLED, ROCCAT_KEY_COMBO_BOX_GROUP_NONE);

	return GTK_TREE_MODEL(store);
}

static void finalize(GObject *object) {
	TyonKeyComboBoxPrivate *priv = TYON_KEY_COMBO_BOX(object)->priv;
	G_OBJECT_CLASS(tyon_key_combo_box_parent_class)->finalize(object);
	g_free(priv->key_info);
}

static void tyon_key_combo_box_class_init(TyonKeyComboBoxClass *klass) {
	GObjectClass *gobject_class = (GObjectClass*)klass;

	gobject_class->finalize = finalize;
	g_type_class_add_private(klass, sizeof(TyonKeyComboBoxPrivate));
	klass->model = button_info_model_new();
}

void tyon_key_combo_box_set_value_blocked(TyonKeyComboBox *key_combo_box, TyonRmpMacroKeyInfo const *key_info) {
	TyonKeyComboBoxPrivate *priv = key_combo_box->priv;

	tyon_rmp_macro_key_info_free(priv->key_info);
	priv->key_info = tyon_rmp_macro_key_info_dup(key_info);

	set_text(key_combo_box);
}

TyonRmpMacroKeyInfo *tyon_key_combo_box_get_value(TyonKeyComboBox *key_combo_box) {
	return tyon_rmp_macro_key_info_dup(key_combo_box->priv->key_info);
}
