* This file is part of StarDict.
*
* StarDict 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.
*
* StarDict 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 StarDict. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#ifdef _WIN32
#define VERSION "4.0.0"
# include <gdk/gdkwin32.h>
#endif
#include <list>
#include <algorithm>
#include "conf.h"
#include "desktop.h"
#include "stardict.h"
#include "lib/utils.h"
#include "lib/edit-distance.h"
#include "lib/stddict.h"
#include "lib/full_text_trans.h"
#include "mainwin.h"
TopWin::TopWin()
{
WordCombo = NULL;
BackList = NULL;
BackList_index = 0;
enable_change_cb = true;
MainMenu = NULL;
SearchMenu = NULL;
}
TopWin::~TopWin()
{
GList *list = BackList;
while (list) {
g_free(((BackListData *)(list->data))->word);
g_free(list->data);
list = list->next;
}
g_list_free(BackList);
}
static void unfocus_combo_arrow(GtkWidget *widget, gpointer data)
{
if (!GTK_IS_ENTRY(widget)) {
gtk_widget_set_can_focus(widget, FALSE);
}
}
void TopWin::Create(GtkWidget *vbox)
{
#if GTK_MAJOR_VERSION >= 3
GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
#else
GtkWidget *hbox = gtk_hbox_new(false,0);
#endif
gtk_widget_show(hbox);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(vbox),hbox,false,false,0);
#else
gtk_box_pack_start(GTK_BOX(vbox),hbox,false,false,3);
#endif
back_button = gtk_button_new();
gtk_container_add(GTK_CONTAINER(back_button),gtk_image_new_from_icon_name(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON));
gtk_widget_show_all(back_button);
gtk_button_set_relief (GTK_BUTTON (back_button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (back_button, FALSE);
gtk_widget_set_sensitive(back_button, FALSE);
g_signal_connect(G_OBJECT(back_button),"clicked", G_CALLBACK(BackCallback),this);
g_signal_connect(G_OBJECT(back_button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_start(GTK_BOX(hbox), back_button,false,false,0);
gtk_widget_set_tooltip_text(back_button,_("Go back (Alt+Left)"));
forward_button = gtk_button_new();
gtk_container_add(GTK_CONTAINER(forward_button),gtk_image_new_from_icon_name(GTK_STOCK_GO_FORWARD,GTK_ICON_SIZE_BUTTON));
gtk_widget_show_all(forward_button);
gtk_button_set_relief (GTK_BUTTON (forward_button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (forward_button, FALSE);
gtk_widget_set_sensitive(forward_button, FALSE);
g_signal_connect(G_OBJECT(forward_button),"clicked", G_CALLBACK(ForwardCallback),this);
g_signal_connect(G_OBJECT(forward_button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_start(GTK_BOX(hbox), forward_button,false,false,0);
gtk_widget_set_tooltip_text(forward_button,_("Go forward (Alt+Right)"));
GtkListStore* list_store = gtk_list_store_new(1, G_TYPE_STRING);
LoadHistory(list_store);
WordCombo = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(list_store));
gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(WordCombo), 0);
g_object_unref (G_OBJECT(list_store));
#if GTK_MAJOR_VERSION >= 3
gtk_widget_set_focus_on_click(GTK_WIDGET(WordCombo), FALSE);
#else
gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(WordCombo), FALSE);
#endif
gtk_container_forall(GTK_CONTAINER(WordCombo), unfocus_combo_arrow, this);
gtk_widget_set_size_request(WordCombo,60,-1);
gtk_widget_show(WordCombo);
GtkWidget *entry = gtk_bin_get_child(GTK_BIN(WordCombo));
gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_INDEX_KEY_SIZE-1);
gtk_entry_set_icon_from_icon_name (GTK_ENTRY(entry), GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
gtk_entry_set_icon_tooltip_text(GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, _("Clear the search box"));
g_signal_connect (G_OBJECT (entry), "icon-press", G_CALLBACK (on_entry_icon_press), this);
g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (on_entry_changed), this);
g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (on_entry_activate), this);
g_signal_connect (G_OBJECT (entry), "populate-popup", G_CALLBACK (on_entry_populate_popup), this);
gtk_box_pack_start(GTK_BOX(hbox),WordCombo,true,true,3);
#ifndef CONFIG_GPE
GtkWidget *button;
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_FIND,GTK_ICON_SIZE_BUTTON));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(GoCallback),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Fuzzy query"));
#endif
GtkWidget *label;
label = gtk_label_new("\t");
gtk_widget_show(label);
gtk_box_pack_start(GTK_BOX(hbox),label,false,false,0);
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_HOME,GTK_ICON_SIZE_BUTTON));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(MenuCallback),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Show the main menu (Alt+M)"));
}
void TopWin::Destroy(void)
{
InsertHisList(get_text());
SaveHistory();
if (MainMenu)
gtk_widget_destroy(MainMenu);
if (SearchMenu)
gtk_widget_destroy(SearchMenu);
}
void TopWin::on_entry_changed(GtkEntry *entry, TopWin *oTopWin)
{
if (!(oTopWin->enable_change_cb))
return;
const gchar *sWord = gtk_entry_get_text(entry);
if(sWord[0]!='\0') {
gpAppFrame->TopWinWordChange(sWord);
} else {
gpAppFrame->oMidWin.oTextWin.queryWord.clear();
gpAppFrame->oMidWin.oIndexWin.oResultWin.Clear();
gpAppFrame->oMidWin.oTextWin.ShowTips();
}
}
void TopWin::do_search_by_fuzzyquery (GtkWidget *item, TopWin *oTopWin)
{
const gchar *text = oTopWin->get_text();
if (text[0]=='\0')
return;
gpAppFrame->LookupWithFuzzyToMainWin(text);
bool enable_netdict = conf->get_bool_at("network/enable_netdict");
if (enable_netdict) {
std::string word;
word = "/";
word += text;
STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, word.c_str());
if (!gpAppFrame->oStarDictClient.try_cache(c)) {
gpAppFrame->waiting_mainwin_lookupcmd_seq = c->seq;
gpAppFrame->oStarDictClient.send_commands(1, c);
}
}
oTopWin->TextSelectAll();
oTopWin->grab_focus();
oTopWin->InsertHisList(text);
oTopWin->InsertBackList(text);
}
void TopWin::do_search_by_patternmatch (GtkWidget *item, TopWin *oTopWin)
{
const gchar *text = oTopWin->get_text();
if (text[0]=='\0')
return;
gpAppFrame->LookupWithRuleToMainWin(text);
bool enable_netdict = conf->get_bool_at("network/enable_netdict");
if (enable_netdict) {
STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, text);
if (!gpAppFrame->oStarDictClient.try_cache(c)) {
gpAppFrame->waiting_mainwin_lookupcmd_seq = c->seq;
gpAppFrame->oStarDictClient.send_commands(1, c);
}
}
oTopWin->TextSelectAll();
oTopWin->grab_focus();
oTopWin->InsertHisList(text);
oTopWin->InsertBackList(text);
}
void TopWin::do_search_by_regularmatch (GtkWidget *item, TopWin *oTopWin)
{
const gchar *text = oTopWin->get_text();
if (text[0]=='\0')
return;
gpAppFrame->LookupWithRegexToMainWin(text);
bool enable_netdict = conf->get_bool_at("network/enable_netdict");
if (enable_netdict) {
std::string word;
word = ":";
word += text;
STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, word.c_str());
if (!gpAppFrame->oStarDictClient.try_cache(c)) {
gpAppFrame->waiting_mainwin_lookupcmd_seq = c->seq;
gpAppFrame->oStarDictClient.send_commands(1, c);
}
}
oTopWin->TextSelectAll();
oTopWin->grab_focus();
oTopWin->InsertHisList(text);
oTopWin->InsertBackList(text);
}
void TopWin::do_search_by_fulltextsearch (GtkWidget *item, TopWin *oTopWin)
{
const gchar *text = oTopWin->get_text();
if (text[0]=='\0')
return;
gpAppFrame->LookupDataToMainWin(text);
oTopWin->TextSelectAll();
oTopWin->grab_focus();
oTopWin->InsertHisList(text);
oTopWin->InsertBackList(text);
}
void TopWin::on_entry_icon_press(GtkEntry *entry, gint position, GdkEventButton *event, TopWin *oTopWin)
{
if (position == GTK_ENTRY_ICON_PRIMARY) {
if (oTopWin->SearchMenu == NULL) {
oTopWin->SearchMenu = gtk_menu_new ();
GtkWidget *menuitem;
GtkWidget *image;
menuitem = gtk_menu_item_new_with_mnemonic (_("_Fuzzy query"));
image = gtk_image_new_from_icon_name (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect (menuitem, "activate", G_CALLBACK (do_search_by_fuzzyquery), oTopWin);
gtk_menu_shell_append (GTK_MENU_SHELL (oTopWin->SearchMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic (_("_Glob-style pattern matching"));
image = gtk_image_new_from_icon_name (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect (menuitem, "activate", G_CALLBACK (do_search_by_patternmatch), oTopWin);
gtk_menu_shell_append (GTK_MENU_SHELL (oTopWin->SearchMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic (_("_Regular expressions matching"));
image = gtk_image_new_from_icon_name (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect (menuitem, "activate", G_CALLBACK (do_search_by_regularmatch), oTopWin);
gtk_menu_shell_append (GTK_MENU_SHELL (oTopWin->SearchMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic (_("Full-_text search"));
image = gtk_image_new_from_icon_name (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect (menuitem, "activate", G_CALLBACK (do_search_by_fulltextsearch), oTopWin);
gtk_menu_shell_append (GTK_MENU_SHELL (oTopWin->SearchMenu), menuitem);
gtk_widget_show_all (oTopWin->SearchMenu);
}
#if ((GTK_MAJOR_VERSION == 3) && (GTK_MINOR_VERSION >= 22)) || (GTK_MAJOR_VERSION >= 4)
gtk_menu_popup_at_widget(GTK_MENU(oTopWin->SearchMenu), NULL, GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
#else
gtk_menu_popup(GTK_MENU(oTopWin->SearchMenu), NULL, NULL, NULL, NULL, 1, event->time);
#endif
} else {
play_sound_on_event("buttonactive");
oTopWin->clear_entry();
}
}
void TopWin::clear_entry()
{
if (get_text()[0]) {
InsertHisList(get_text());
InsertBackList();
SetText("");
}
grab_focus();
}
void TopWin::on_entry_activate(GtkEntry *entry, TopWin *oTopWin)
{
gpAppFrame->TopWinEnterWord();
}
void TopWin::on_clear_history_menu_item_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
GtkListStore* list_store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(oTopWin->WordCombo)));
gtk_list_store_clear(list_store);
}
void TopWin::on_entry_populate_popup(GtkEntry *entry, GtkMenu *menu, TopWin *oTopWin)
{
GtkWidget *menuitem;
menuitem = gtk_separator_menu_item_new();
gtk_widget_show(menuitem);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("Clear _history"));
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_clear_history_menu_item_activate), oTopWin);
GtkWidget *image = gtk_image_new_from_icon_name(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
gtk_widget_show(menuitem);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
}
#ifndef CONFIG_GPE
void TopWin::GoCallback(GtkWidget *widget, TopWin *oTopWin)
{
play_sound_on_event("buttonactive");
const gchar *text = oTopWin->get_text();
if (text[0]=='\0')
return;
std::string res;
query_t qt = analyse_query(text, res);
switch (qt) {
case qtFUZZY:
gpAppFrame->LookupWithFuzzyToMainWin(res.c_str());
break;
case qtPATTERN:
gpAppFrame->LookupWithRuleToMainWin(res.c_str());
break;
case qtREGEX:
gpAppFrame->LookupWithRegexToMainWin(res.c_str());
break;
case qtFULLTEXT:
gpAppFrame->LookupDataToMainWin(res.c_str());
break;
default:
gpAppFrame->LookupWithFuzzyToMainWin(res.c_str());
}
if (qt != qtFULLTEXT) {
bool enable_netdict = conf->get_bool_at("network/enable_netdict");
if (enable_netdict) {
std::string word;
if (qt == qtSIMPLE) {
word = "/";
word += res;
} else {
word = text;
}
STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, word.c_str());
if (!gpAppFrame->oStarDictClient.try_cache(c)) {
gpAppFrame->waiting_mainwin_lookupcmd_seq = c->seq;
gpAppFrame->oStarDictClient.send_commands(1, c);
}
}
}
oTopWin->TextSelectAll();
oTopWin->grab_focus();
oTopWin->InsertHisList(text);
oTopWin->InsertBackList(text);
}
#endif
void TopWin::do_back()
{
if (!BackList)
return;
GList *list = g_list_nth(BackList, BackList_index);
if (!list)
return;
list = g_list_next(list);
if (!list) {
gtk_widget_set_sensitive(back_button, FALSE);
return;
}
if (list->next == NULL)
gtk_widget_set_sensitive(back_button, FALSE);
BackList_index++;
gtk_widget_set_sensitive(forward_button, TRUE);
InsertHisList(get_text());
SetText(((BackListData *)(list->data))->word);
if (gtk_widget_has_focus(gtk_bin_get_child(GTK_BIN(WordCombo))))
gtk_editable_select_region(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(WordCombo))), 0, -1);
if (((BackListData *)(list->data))->adjustment_value != -1) {
ProcessGtkEvent();
gpAppFrame->oMidWin.oTextWin.view->scroll_to(((BackListData *)(list->data))->adjustment_value);
}
}
void TopWin::do_forward()
{
if (!BackList)
return;
GList *list = g_list_nth(BackList, BackList_index);
if (!list)
return;
list = g_list_previous(list);
if (!list) {
gtk_widget_set_sensitive(forward_button, FALSE);
return;
}
if (list->prev == NULL)
gtk_widget_set_sensitive(forward_button, FALSE);
BackList_index--;
gtk_widget_set_sensitive(back_button, TRUE);
InsertHisList(get_text());
SetText(((BackListData *)(list->data))->word);
if (gtk_widget_has_focus(GTK_WIDGET(gtk_bin_get_child(GTK_BIN(WordCombo)))))
gtk_editable_select_region(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(WordCombo))), 0, -1);
if (((BackListData *)(list->data))->adjustment_value != -1) {
ProcessGtkEvent();
gpAppFrame->oMidWin.oTextWin.view->scroll_to(((BackListData *)(list->data))->adjustment_value);
}
}
void TopWin::BackCallback(GtkWidget *widget, TopWin *oTopWin)
{
play_sound_on_event("buttonactive");
oTopWin->do_back();
}
void TopWin::ForwardCallback(GtkWidget *widget, TopWin *oTopWin)
{
play_sound_on_event("buttonactive");
oTopWin->do_forward();
}
void TopWin::do_prev()
{
MidWin &midwin = gpAppFrame->oMidWin;
if (midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_EMPTY)
return;
GtkTreeSelection *selection =
gtk_tree_view_get_selection(midwin.oIndexWin.oListWin.treeview_);
GtkTreeModel *model;
GtkTreeIter iter;
gboolean selected = gtk_tree_selection_get_selected(selection,&model,&iter);
if (midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_NORMAL_LIST) {
if (!selected) {
if (!gtk_tree_model_get_iter_first(model,&iter))
return;
}
GtkTreePath* path = gtk_tree_model_get_path(model,&iter);
if (gtk_tree_path_prev(path)) {
gtk_tree_model_get_iter(model,&iter,path);
gtk_tree_selection_select_iter(selection,&iter);
gtk_tree_view_scroll_to_cell(
midwin.oIndexWin.oListWin.treeview_,
path, NULL, FALSE, 0, 0);
} else {
gchar *word;
gtk_tree_model_get (model, &iter, 0, &word, -1);
gpAppFrame->ListPreWords(word);
if (conf->get_bool_at("network/enable_netdict")) {
STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_PREVIOUS, word);
if (!gpAppFrame->oStarDictClient.try_cache(c))
gpAppFrame->oStarDictClient.send_commands(1, c);
}
g_free(word);
}
gtk_tree_path_free(path);
} else if (midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_FUZZY_LIST ||
midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_PATTERN_LIST||
midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_DATA_LIST) {
if (!selected) {
if (!gtk_tree_model_get_iter_first(model,&iter))
return;
}
GtkTreePath* path = gtk_tree_model_get_path(model,&iter);
if (gtk_tree_path_prev(path)) {
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_selection_select_iter(selection, &iter);
gtk_tree_view_scroll_to_cell(
midwin.oIndexWin.oListWin.treeview_,
path, NULL, FALSE, 0, 0);
}
gtk_tree_path_free(path);
}
}
void TopWin::do_next()
{
MidWin &midwin = gpAppFrame->oMidWin;
if (midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_EMPTY)
return;
GtkTreeSelection *selection =
gtk_tree_view_get_selection(midwin.oIndexWin.oListWin.treeview_);
GtkTreeModel *model;
GtkTreeIter iter;
gboolean selected = gtk_tree_selection_get_selected(selection, &model, &iter);
if (midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_NORMAL_LIST) {
if (!selected) {
if (!gtk_tree_model_get_iter_first(model,&iter))
return;
}
GtkTreeIter new_iter = iter;
gchar *word;
if (gtk_tree_model_iter_next(model, &iter)) {
gtk_tree_selection_select_iter(selection, &iter);
GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
gtk_tree_view_scroll_to_cell(
midwin.oIndexWin.oListWin.treeview_,
path, NULL, FALSE, 0, 0);
gtk_tree_path_free(path);
} else {
gtk_tree_model_get(model, &new_iter, 0, &word, -1);
gpAppFrame->ListNextWords(word);
if (conf->get_bool_at("network/enable_netdict")) {
STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_NEXT, word);
if (!gpAppFrame->oStarDictClient.try_cache(c))
gpAppFrame->oStarDictClient.send_commands(1, c);
}
g_free(word);
}
} else if (midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_FUZZY_LIST ||
midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_PATTERN_LIST ||
midwin.oIndexWin.oListWin.list_word_type == LIST_WIN_DATA_LIST) {
if (!selected) {
if (!gtk_tree_model_get_iter_first(model,&iter))
return;
}
if (gtk_tree_model_iter_next(model,&iter)) {
gtk_tree_selection_select_iter(selection, &iter);
GtkTreePath* path = gtk_tree_model_get_path(model,&iter);
gtk_tree_view_scroll_to_cell(
midwin.oIndexWin.oListWin.treeview_,
path, NULL, FALSE, 0, 0);
gtk_tree_path_free(path);
}
}
}
void TopWin::on_main_menu_preferences_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
gpAppFrame->PopupPrefsDlg();
}
void TopWin::on_main_menu_dictmanage_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
gpAppFrame->PopupDictManageDlg();
}
void TopWin::on_main_menu_pluginmanage_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
gpAppFrame->PopupPluginManageDlg();
}
void TopWin::on_main_menu_keepabove_toggled(GtkCheckMenuItem *menuitem, TopWin *oTopWin)
{
bool keepabove = gtk_check_menu_item_get_active(menuitem);
conf->set_bool_at("main_window/keep_above", keepabove);
}
void TopWin::on_main_menu_downloaddict_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
show_url("http://download.huzheng.org");
}
void TopWin::on_main_menu_newversion_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
show_url("http://stardict-4.sourceforge.net");
}
void TopWin::on_main_menu_donate_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
show_url("http://www.huzheng.org/donate.php");
}
void TopWin::on_main_menu_help_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
show_help(NULL);
}
void TopWin::on_main_menu_about_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
const gchar *authors[] = {
"Hu Zheng <huzheng001@gmail.com>",
"Sergey <kubtek@gmail.com>",
"Wen Ji <wis2@hotmail.com>",
"DongXu <me@eipi.fun>",
"Evgeniy <dushistov@mail.ru>",
"atzlinux <atzlinux@sina.com>",
"Alex Murygin <murygin@aitoc.com>",
"Tao Wang <dancefire@gmail.com>",
"Opera Wang <wangvisual@sohu.com>",
"Ma Su'an <msa@wri.com.cn>",
NULL
};
const gchar *documenters[] = {
(gchar *)"Hu Zheng <huzheng001@gmail.com>",
(gchar *)"Will Robinson <wsr23@stanford.edu>",
(gchar *)"Anthony Fok <foka@debian.org>",
NULL
};
gchar *translator_credits = _("translator_credits");
gtk_show_about_dialog(GTK_WINDOW (gpAppFrame->window),
"name", _("StarDict"),
"version", VERSION,
"website", "http://stardict-4.sourceforge.net",
"comments", _("StarDict is an international dictionary for GNOME."),
"copyright", "Copyright \xc2\xa9 1999 by Ma Su'an\n" "Copyright \xc2\xa9 2002 by Opera Wang\n" "Copyright \xc2\xa9 2003-2004 by Hu Zheng\n" "Copyright \xc2\xa9 2005-2006 by Hu Zheng, Evgeniy\n" "Copyright \xc2\xa9 2007-2011 by Hu Zheng, Sergey\n" "Copyright \xc2\xa9 2012-2023 by Hu Zheng\n" "Copyright \xc2\xa9 2024 by Hu Zheng, Wen Ji, DongXu, atzlinux\n" "Copyright \xc2\xa9 2025 by Hu Zheng",
"authors", (const char **)authors,
"documenters", (const char **)documenters,
"translator-credits", strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL,
"logo", get_impl(gpAppFrame->oAppSkin.icon),
NULL);
}
void TopWin::on_main_menu_quit_activate(GtkMenuItem *menuitem, TopWin *oTopWin)
{
gpAppFrame->Quit();
}
void TopWin::ClipboardReceivedCallback(GtkClipboard *clipboard, const gchar *text, gpointer data)
{
if (text) {
std::string estr;
stardict_input_escape(text, estr);
gpAppFrame->Query(estr.c_str());
}
}
void TopWin::do_menu()
{
play_sound_on_event("menushow");
if (!MainMenu) {
MainMenu = gtk_menu_new();
GtkWidget *menuitem;
menuitem = gtk_menu_item_new_with_mnemonic(_("Pr_eferences"));
GtkWidget *image;
image = gtk_image_new_from_icon_name(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_preferences_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("Manage _dictionaries"));
image = gtk_image_new_from_icon_name(GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_dictmanage_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("Manage _plugins"));
image = gtk_image_new_from_icon_name(GTK_STOCK_DISCONNECT, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_pluginmanage_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_check_menu_item_new_with_mnemonic(_("_Keep window above"));
bool keepabove = conf->get_bool_at("main_window/keep_above");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), keepabove);
g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(on_main_menu_keepabove_toggled), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("Download dict_ionaries"));
image = gtk_image_new_from_icon_name(GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_downloaddict_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("_New version"));
image = gtk_image_new_from_icon_name(GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_newversion_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("D_onate"));
image = gtk_image_new_from_icon_name(GTK_STOCK_CDROM, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_donate_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("_Help"));
image = gtk_image_new_from_icon_name(GTK_STOCK_HELP, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_help_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("_About"));
image = gtk_image_new_from_icon_name (GTK_STOCK_ABOUT, GTK_ICON_SIZE_BUTTON);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_about_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("_Quit"));
image = gtk_image_new_from_icon_name(GTK_STOCK_QUIT, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_main_menu_quit_activate), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(MainMenu), menuitem);
gtk_widget_show_all(MainMenu);
}
#if ((GTK_MAJOR_VERSION == 3) && (GTK_MINOR_VERSION >= 22)) || (GTK_MAJOR_VERSION >= 4)
gtk_menu_popup_at_widget(GTK_MENU(MainMenu), NULL, GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
#else
gtk_menu_popup(GTK_MENU(MainMenu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time());
#endif
}
void TopWin::MenuCallback(GtkWidget *widget, TopWin *oTopWin)
{
oTopWin->do_menu();
}
void TopWin::SetText(const gchar *word, bool notify)
{
if (strcmp(word, get_text()) == 0)
return;
enable_change_cb = false;
gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(WordCombo))), word);
enable_change_cb = true;
if (!notify)
return;
if(word[0]!='\0') {
gpAppFrame->TopWinWordChange(word);
} else {
gpAppFrame->oMidWin.oTextWin.queryWord.clear();
gpAppFrame->oMidWin.oIndexWin.oResultWin.Clear();
gpAppFrame->oMidWin.oTextWin.ShowTips();
}
}
{
enable_change_cb = false;
gtk_entry_set_text(GTK_ENTRY(GTK_BIN(WordCombo)->child),word);
enable_change_cb = true;
}*/
void TopWin::TextSelectAll()
{
gtk_editable_select_region(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(WordCombo))),0,-1);
}
gboolean TopWin::TextSelected()
{
return (gtk_editable_get_selection_bounds(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(WordCombo))),NULL,NULL));
}
gint TopWin::BackListDataCompareFunc(gconstpointer a,gconstpointer b)
{
return strcmp(((const BackListData *)a)->word, ((const BackListData *)b)->word);
}
*/
void TopWin::InsertHisList(const gchar *word)
{
if (!word || word[0]=='\0')
return;
GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(WordCombo));
GtkTreeIter iter;
gboolean have_item = gtk_tree_model_get_iter_first(model, &iter);
gchar *str;
size_t count = 0;
GtkTreeIter iter_last;
while (have_item) {
count++;
iter_last = iter;
gtk_tree_model_get(model, &iter, 0, &str, -1);
if (strcmp(str, word)==0) {
gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, NULL);
g_free(str);
return;
}
g_free(str);
have_item = gtk_tree_model_iter_next(model, &iter);
}
if (count >= MAX_HISTORY_WORD_ITEM_NUM) {
gtk_list_store_remove(GTK_LIST_STORE(model), &iter_last);
}
gtk_list_store_prepend(GTK_LIST_STORE(model), &iter);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, word, -1);
}
void TopWin::SaveHistory()
{
const std::string& filePath = conf->get_string_at("dictionary/history");
#ifdef _WIN32
FILE *f=g_fopen(abs_path_to_data_dir(filePath).c_str(), "w");
#else
FILE *f=g_fopen(filePath.c_str(), "w");
#endif
if (!f)
return;
GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(WordCombo));
GtkTreeIter iter;
gboolean have_item = gtk_tree_model_get_iter_first(model, &iter);
gchar *word;
while (have_item) {
gtk_tree_model_get(model, &iter, 0, &word, -1);
#ifdef _MSC_VER
fprintf_s(f, "%s\n", word);
#else
fprintf(f, "%s\n", word);
#endif
g_free(word);
have_item = gtk_tree_model_iter_next(model, &iter);
}
fclose(f);
}
void TopWin::LoadHistory(GtkListStore* list_store)
{
const std::string& filePath = conf->get_string_at("dictionary/history");
gchar *buffer;
#ifdef _WIN32
if(!g_file_get_contents(abs_path_to_data_dir(filePath).c_str(), &buffer, NULL, NULL))
#else
if(!g_file_get_contents(filePath.c_str(), &buffer, NULL, NULL))
#endif
return;
gchar *p,*p1;
p=buffer;
GtkTreeIter iter;
while (*p) {
p1=strchr(p, '\n');
if (p1) {
*p1='\0';
gtk_list_store_append(list_store, &iter);
gtk_list_store_set(list_store, &iter, 0, p, -1);
p = p1+1;
} else {
break;
}
}
g_free(buffer);
}
void TopWin::InsertBackList(const gchar *word)
{
BackListData *backlistdata;
if (word) {
if (word[0] == '\0')
return;
if (BackList && (strcmp(((BackListData *)(BackList->data))->word, word) == 0))
return;
backlistdata = (BackListData *)g_malloc(sizeof(BackListData));
backlistdata->word = g_strdup(word);
backlistdata->adjustment_value = -1;
} else {
word = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(WordCombo))));
if (word[0] == '\0')
return;
if (BackList && (strcmp(((BackListData *)(BackList->data))->word, word) == 0))
return;
backlistdata = (BackListData *)g_malloc(sizeof(BackListData));
backlistdata->word = g_strdup(word);
backlistdata->adjustment_value = gpAppFrame->oMidWin.oTextWin.view->scroll_pos();
}
for (guint i=0; i< BackList_index; i++) {
g_free(((BackListData *)((BackList)->data))->word);
g_free(BackList->data);
BackList = g_list_delete_link(BackList, BackList);
}
if (BackList != NULL)
gtk_widget_set_sensitive(back_button, TRUE);
gtk_widget_set_sensitive(forward_button, FALSE);
BackList = g_list_prepend(BackList, backlistdata);
BackList_index = 0;
if (g_list_length(BackList)> MAX_BACK_WORD_ITEM_NUM) {
GList *list = g_list_last(BackList);
g_free(((BackListData *)(list->data))->word);
g_free(list->data);
BackList = g_list_delete_link(BackList,list);
}
}
void ListWin::Create(GtkWidget *notebook)
{
list_word_type = LIST_WIN_EMPTY;
list_model = gtk_list_store_new (1,G_TYPE_STRING);
tree_model = gtk_tree_store_new (1,G_TYPE_STRING);
treeview_ = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_model)));
nowIsList = true;
gtk_widget_show(GTK_WIDGET(treeview_));
#if GTK_MAJOR_VERSION >= 3
#else
gtk_tree_view_set_rules_hint(treeview_, TRUE);
#endif
gtk_tree_view_set_headers_visible(treeview_, FALSE);
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ("word", renderer,
"text", 0, NULL);
gtk_tree_view_append_column(treeview_, column);
GtkTreeSelection *selection =
gtk_tree_view_get_selection(treeview_);
g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (on_selection_changed), this);
g_signal_connect(G_OBJECT(treeview_), "button_press_event",
G_CALLBACK(on_button_press), this);
GtkWidget *scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show(scrolledwindow);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(scrolledwindow), GTK_WIDGET(treeview_));
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolledwindow, NULL);
}
void ListWin::SetModel(bool isListModel)
{
if (isListModel) {
if (!nowIsList) {
gtk_tree_view_set_model(treeview_, GTK_TREE_MODEL(list_model));
nowIsList = true;
}
} else {
if (nowIsList) {
gtk_tree_view_set_model(treeview_, GTK_TREE_MODEL(tree_model));
nowIsList = false;
}
}
}
void ListWin::Destroy()
{
g_object_unref (list_model);
g_object_unref (tree_model);
}
void ListWin::Clear()
{
gtk_list_store_clear(list_model);
gtk_tree_store_clear(tree_model);
}
void ListWin::RemoveLast()
{
//note,this function is not to remove the list row,but the LIST_WIN_ROW_NUM row.
gchar lastrow[5];
sprintf(lastrow,"%d", LIST_WIN_ROW_NUM); // not LIST_WIN_ROW_NUM -1,as Prepend is done first.
GtkTreePath *path = gtk_tree_path_new_from_string (lastrow);
GtkTreeIter iter;
if (gtk_tree_model_get_iter (GTK_TREE_MODEL(list_model), &iter, path)) {
gtk_list_store_remove(list_model, &iter);
}
gtk_tree_path_free(path);
}
void ListWin::UnSelectAll()
{
gtk_tree_selection_unselect_all(gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)));
}
*/
void ListWin::Prepend(const gchar *word)
{
GtkTreeIter iter;
gtk_list_store_prepend (list_model, &iter);
gtk_list_store_set (list_model, &iter, 0, word, -1);
}
void ListWin::ReScroll()
{
GtkTreePath *path = gtk_tree_path_new_from_string ("0");
gtk_tree_view_scroll_to_cell(treeview_, path, NULL, FALSE, 0, 0);
gtk_tree_path_free(path);
gtk_tree_view_scroll_to_point(GTK_TREE_VIEW(treeview),0,0);*/
}
void ListWin::InsertLast(const gchar *word)
{
GtkTreeIter iter;
gtk_list_store_append (list_model, &iter);
gtk_list_store_set (list_model, &iter, 0, word, -1);
}
void ListWin::SetTreeModel(std::vector<gchar *> *reslist, std::vector<InstantDictIndex> &dictmask)
{
GtkTreeIter parent;
GtkTreeIter iter;
const char *bookname = "";
for (size_t i=0; i<dictmask.size(); i++) {
if (!reslist[i].empty()) {
gtk_tree_store_append(tree_model, &parent, NULL);
if (dictmask[i].type == InstantDictType_LOCAL)
bookname = gpAppFrame->oLibs.dict_name(dictmask[i].index).c_str();
else if (dictmask[i].type == InstantDictType_VIRTUAL)
bookname = gpAppFrame->oStarDictPlugins->VirtualDictPlugins.dict_name(dictmask[i].index);
else if (dictmask[i].type == InstantDictType_NET)
bookname = gpAppFrame->oStarDictPlugins->NetDictPlugins.dict_name(dictmask[i].index);
gtk_tree_store_set(tree_model, &parent, 0, bookname, -1);
for (std::vector<gchar *>::iterator p=reslist[i].begin();
p != reslist[i].end(); ++p) {
gtk_tree_store_append(tree_model, &iter, &parent);
gtk_tree_store_set (tree_model, &iter, 0, *p, -1);
g_free(*p);
}
}
}
gtk_tree_view_expand_all(treeview_);
}
void ListWin::SetTreeModel(std::list<STARDICT::LookupResponse::WordTreeElement *> *wordtree)
{
GtkTreeIter parent;
GtkTreeIter iter;
for (std::list<STARDICT::LookupResponse::WordTreeElement *>::iterator i = wordtree->begin(); i != wordtree->end(); ++i) {
gtk_tree_store_append(tree_model, &parent, NULL);
gtk_tree_store_set(tree_model, &parent, 0, (*i)->bookname, -1);
for (std::list<char *>::iterator j = (*i)->wordlist.begin(); j != (*i)->wordlist.end(); ++j) {
gtk_tree_store_append(tree_model, &iter, &parent);
gtk_tree_store_set (tree_model, &iter, 0, *j, -1);
}
}
gtk_tree_view_expand_all(treeview_);
}
static inline bool less_for_word_compare(const char *lh, const char *rh) {
return stardict_server_collate(lh, rh, gpAppFrame->oLibs.get_CollationLevel(), gpAppFrame->oLibs.get_CollateFunction(), 0)<0;
}
void ListWin::MergeWordList(std::list<char *> *wordlist)
{
std::list<char *> current_list;
gboolean have_iter;
GtkTreeIter iter;
gchar *word;
GtkTreeModel *model = GTK_TREE_MODEL(list_model);
have_iter = gtk_tree_model_get_iter_first(model, &iter);
while (have_iter) {
gtk_tree_model_get (model, &iter, 0, &word, -1);
current_list.push_back(word);
have_iter = gtk_tree_model_iter_next(model, &iter);
}
std::vector<char *> merge_list;
for (std::list<char *>::iterator i = current_list.begin(); i != current_list.end(); ++i) {
merge_list.push_back(*i);
}
bool duplicated;
for (std::list<char *>::iterator i = wordlist->begin(); i != wordlist->end(); ++i) {
duplicated = false;
for (std::list<char *>::iterator j = current_list.begin(); j != current_list.end(); ++j) {
if (strcmp(*i, *j)==0) {
duplicated = true;
break;
}
}
if (duplicated)
continue;
merge_list.push_back(*i);
}
std::sort(merge_list.begin(), merge_list.end(), less_for_word_compare);
gtk_list_store_clear(list_model);
for (std::vector<char *>::iterator i = merge_list.begin(); i != merge_list.end(); ++i) {
gtk_list_store_append (list_model, &iter);
gtk_list_store_set (list_model, &iter, 0, *i, -1);
}
for (std::list<char *>::iterator i = current_list.begin(); i != current_list.end(); ++i) {
g_free(*i);
}
}
struct FuzzyWordstruct {
char * pMatchWord;
int iMatchWordDistance;
};
static inline bool less_for_fuzzy_compare(const FuzzyWordstruct & lh, const FuzzyWordstruct & rh) {
if (lh.iMatchWordDistance!=rh.iMatchWordDistance)
return lh.iMatchWordDistance<rh.iMatchWordDistance;
return stardict_server_collate(lh.pMatchWord, rh.pMatchWord, gpAppFrame->oLibs.get_CollationLevel(), gpAppFrame->oLibs.get_CollateFunction(), 0)<0;
}
static inline void unicode_strdown(gunichar *str) {
while (*str) {
*str=g_unichar_tolower(*str);
++str;
}
}
void ListWin::MergeFuzzyList(std::list<char *> *wordlist)
{
std::list<char *> current_list;
gboolean have_iter;
GtkTreeIter iter;
gchar *word;
GtkTreeModel *model = GTK_TREE_MODEL(list_model);
have_iter = gtk_tree_model_get_iter_first(model, &iter);
while (have_iter) {
gtk_tree_model_get (model, &iter, 0, &word, -1);
current_list.push_back(word);
have_iter = gtk_tree_model_iter_next(model, &iter);
}
std::vector<FuzzyWordstruct> merge_list;
FuzzyWordstruct fuzzyitem;
EditDistance oEditDistance;
gunichar *ucs4_str1, *ucs4_str2;
glong ucs4_str1_len, ucs4_str2_len;
ucs4_str2 = g_utf8_to_ucs4_fast(fuzzyWord.c_str(), -1, &ucs4_str2_len);
unicode_strdown(ucs4_str2);
for (std::list<char *>::iterator i = current_list.begin(); i != current_list.end(); ++i) {
fuzzyitem.pMatchWord = *i;
ucs4_str1 = g_utf8_to_ucs4_fast(*i, -1, &ucs4_str1_len);
if (ucs4_str1_len > ucs4_str2_len)
ucs4_str1[ucs4_str2_len]=0;
unicode_strdown(ucs4_str1);
fuzzyitem.iMatchWordDistance = oEditDistance.CalEditDistance(ucs4_str1, ucs4_str2, MAX_FUZZY_DISTANCE);
g_free(ucs4_str1);
merge_list.push_back(fuzzyitem);
}
bool duplicated;
for (std::list<char *>::iterator i = wordlist->begin(); i != wordlist->end(); ++i) {
duplicated = false;
for (std::list<char *>::iterator j = current_list.begin(); j != current_list.end(); ++j) {
if (strcmp(*i, *j)==0) {
duplicated = true;
break;
}
}
if (duplicated)
continue;
fuzzyitem.pMatchWord = *i;
ucs4_str1 = g_utf8_to_ucs4_fast(*i, -1, &ucs4_str1_len);
if (ucs4_str1_len > ucs4_str2_len)
ucs4_str1[ucs4_str2_len]=0;
unicode_strdown(ucs4_str1);
fuzzyitem.iMatchWordDistance = oEditDistance.CalEditDistance(ucs4_str1, ucs4_str2, MAX_FUZZY_DISTANCE);
g_free(ucs4_str1);
merge_list.push_back(fuzzyitem);
}
g_free(ucs4_str2);
std::sort(merge_list.begin(), merge_list.end(), less_for_fuzzy_compare);
gtk_list_store_clear(list_model);
for (std::vector<FuzzyWordstruct>::iterator i = merge_list.begin(); i != merge_list.end(); ++i) {
gtk_list_store_append (list_model, &iter);
gtk_list_store_set (list_model, &iter, 0, i->pMatchWord, -1);
}
for (std::list<char *>::iterator i = current_list.begin(); i != current_list.end(); ++i) {
g_free(*i);
}
}
gboolean ListWin::on_button_press(GtkWidget * widget, GdkEventButton * event, ListWin *oListWin)
{
if (event->type==GDK_2BUTTON_PRESS) {
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection *selection =
gtk_tree_view_get_selection(oListWin->treeview_);
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
if (!oListWin->nowIsList) {
if (gtk_tree_model_iter_has_child(model, &iter)) {
GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
if (gtk_tree_view_row_expanded(
oListWin->treeview_, path))
gtk_tree_view_collapse_row(
oListWin->treeview_, path);
else
gtk_tree_view_expand_row(
oListWin->treeview_, path, FALSE);
gtk_tree_path_free(path);
return TRUE;
}
}
gchar *word;
gtk_tree_model_get(model, &iter, 0, &word, -1);
gpAppFrame->ListClick(word);
g_free(word);
}
return TRUE;
} else
return FALSE;
}
void ListWin::on_selection_changed(GtkTreeSelection *selection, ListWin *oListWin)
{
GtkTreeModel *model;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
if (!oListWin->nowIsList) {
gchar *path_str = gtk_tree_model_get_string_from_iter(model,&iter);
if (!strchr(path_str, ':')) {
g_free(path_str);
return;
}
g_free(path_str);
}
gchar *word;
gtk_tree_model_get (model, &iter, 0, &word, -1);
gpAppFrame->SimpleLookupToTextWin(word, NULL);
bool enable_netdict = conf->get_bool_at("network/enable_netdict");
if (enable_netdict) {
STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_DEFINE, word);
if (!gpAppFrame->oStarDictClient.try_cache(c)) {
gpAppFrame->waiting_mainwin_lookupcmd_seq = c->seq;
gpAppFrame->oStarDictClient.send_commands(1, c);
}
}
gpAppFrame->LookupNetDict(word, true);
g_free(word);
}
}
bool TreeWin::Create(GtkWidget *notebook)
{
const std::list<std::string>& treedict_order_list
= conf->get_strlist("/apps/stardict/manage_dictionaries/treedict_order_list");
const std::list<std::string>& treedict_disable_list
= conf->get_strlist("/apps/stardict/manage_dictionaries/treedict_disable_list");
const std::list<std::string>& treedict_dirs_list
= conf->get_strlist("/apps/stardict/manage_dictionaries/treedict_dirs_list");
#ifdef _WIN32
std::list<std::string> treedict_order_list_abs;
std::list<std::string> treedict_disable_list_abs;
std::list<std::string> treedict_dirs_list_abs;
abs_path_to_data_dir(treedict_order_list, treedict_order_list_abs);
abs_path_to_data_dir(treedict_disable_list, treedict_disable_list_abs);
abs_path_to_data_dir(treedict_dirs_list, treedict_dirs_list_abs);
GtkTreeStore *model =
gpAppFrame->oTreeDicts.Load(treedict_dirs_list_abs,
treedict_order_list_abs,
treedict_disable_list_abs);
#else
GtkTreeStore *model =
gpAppFrame->oTreeDicts.Load(treedict_dirs_list,
treedict_order_list,
treedict_disable_list);
#endif
if (!model)
return false;
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(model));
gtk_widget_show(treeview);
g_object_unref (model);
#if GTK_MAJOR_VERSION >= 3
#else
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
#endif
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ("word", renderer,
"text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (on_selection_changed), this);
g_signal_connect (G_OBJECT (treeview), "button_press_event", G_CALLBACK (on_button_press), this);
GtkWidget *scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show(scrolledwindow);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(scrolledwindow),treeview);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolledwindow, NULL);
return true;
}
gboolean TreeWin::on_button_press(GtkWidget * widget, GdkEventButton * event, TreeWin *oTreeWin)
{
if (event->type==GDK_2BUTTON_PRESS)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (oTreeWin->treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
if (gtk_tree_model_iter_has_child(model, &iter)) {
GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
if (gtk_tree_view_row_expanded(GTK_TREE_VIEW (oTreeWin->treeview), path))
gtk_tree_view_collapse_row(GTK_TREE_VIEW (oTreeWin->treeview), path);
else
gtk_tree_view_expand_row(GTK_TREE_VIEW (oTreeWin->treeview), path, false);
gtk_tree_path_free(path);
}
else {
guint32 offset, size;
gtk_tree_model_get (model, &iter, 1, &offset, 2, &size, -1);
if (size != 0) {
gchar *path_str = gtk_tree_model_get_string_from_iter(model,&iter);
gint iTreeDict;
gchar *p = strchr(path_str, ':');
if (p)
*p = '\0';
iTreeDict = atoi(path_str);
gpAppFrame->ShowTreeDictDataToTextWin(offset, size, iTreeDict);
g_free(path_str);
}
}
}
return true;
}
else
{
return false;
}
}
void TreeWin::on_selection_changed(GtkTreeSelection *selection, TreeWin *oTreeWin)
{
GtkTreeModel *model;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
guint32 offset, size;
gtk_tree_model_get (model, &iter, 1, &offset, 2, &size, -1);
if (size != 0) {
gchar *path_str = gtk_tree_model_get_string_from_iter(model,&iter);
gint iTreeDict;
gchar *p = strchr(path_str, ':');
if (p)
*p = '\0';
iTreeDict = atoi(path_str);
gpAppFrame->ShowTreeDictDataToTextWin(offset, size, iTreeDict);
g_free(path_str);
}
}
}
void ResultWin::Create(GtkWidget *notebook)
{
GtkListStore *model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(model));
gtk_widget_show(treeview);
g_object_unref (model);
#if GTK_MAJOR_VERSION >= 3
#else
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
#endif
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ("word", renderer,
"text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (on_selection_changed), this);
GtkWidget *scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show(scrolledwindow);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(scrolledwindow),treeview);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolledwindow, NULL);
}
void ResultWin::InsertLast(const gchar *word, const gchar *mark)
{
GtkListStore *model = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)));
GtkTreeIter iter;
gtk_list_store_append (model, &iter);
gtk_list_store_set (model, &iter, 0, word, 1, mark, -1);
}
void ResultWin::Clear()
{
GtkListStore *model = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)));
gtk_list_store_clear(model);
}
void ResultWin::on_selection_changed(GtkTreeSelection *selection, ResultWin *oResultWin)
{
GtkTreeModel *model;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
gchar *markstr;
gtk_tree_model_get(model, &iter, 1, &markstr, -1);
GtkTextView *textview = GTK_TEXT_VIEW(gpAppFrame->oMidWin.oTextWin.view->widget());
GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
GtkTextMark *mark = gtk_text_buffer_get_mark(buffer, markstr);
g_free(markstr);
if (mark) {
gtk_text_view_scroll_to_mark(textview, mark, 0.0, TRUE, 0.0, 0.0);
}
}
}
void HistoryWin::Create(GtkWidget *notebook)
{
GtkListStore *model = gpAppFrame->oTopWin.get_wordcombo_model();
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(model));
gtk_widget_show(treeview);
g_object_unref (model);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
"word", renderer, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
g_signal_connect (G_OBJECT (treeview), "key_press_event",
G_CALLBACK (on_key_pressed), this);
GtkTreeSelection *selection = gtk_tree_view_get_selection (
GTK_TREE_VIEW (treeview));
g_signal_connect (G_OBJECT (selection), "changed",
G_CALLBACK (on_selection_changed), this);
GtkWidget *scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show(scrolledwindow);
gtk_scrolled_window_set_shadow_type (
GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(scrolledwindow),treeview);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolledwindow, NULL);
}
gboolean HistoryWin::on_key_pressed(GtkWidget *widget, GdkEventKey *event,
HistoryWin *oHistoryWin)
{
if (event->type==GDK_KEY_PRESS &&
(event->keyval==GDK_KEY_Delete || event->keyval==GDK_KEY_KP_Delete)) {
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection *selection = gtk_tree_view_get_selection (
GTK_TREE_VIEW (oHistoryWin->treeview));
if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
gtk_tree_selection_select_iter(selection, &iter);
if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
gint total = gtk_tree_model_iter_n_children(model, NULL);
gtk_tree_model_iter_nth_child (model, &iter, NULL, total-1);
gtk_tree_selection_select_iter(selection, &iter);
}
return TRUE;
}
}
return FALSE;
}
void HistoryWin::on_selection_changed(GtkTreeSelection *selection, HistoryWin *oHistoryWin)
{
GtkTreeModel *model;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
gchar *word;
gtk_tree_model_get (model, &iter, 0, &word, -1);
gpAppFrame->SimpleLookupToTextWin(word, NULL);
bool enable_netdict = conf->get_bool_at(
"network/enable_netdict");
if (enable_netdict) {
STARDICT::Cmd *c = new STARDICT::Cmd(
STARDICT::CMD_DEFINE, word);
if (!gpAppFrame->oStarDictClient.try_cache(c)) {
gpAppFrame->waiting_mainwin_lookupcmd_seq = c->seq;
gpAppFrame->oStarDictClient.send_commands(1, c);
}
}
gpAppFrame->LookupNetDict(word, true);
g_free(word);
}
}
LeftWin::LeftWin()
{
choosegroup_menu = NULL;
}
LeftWin::~LeftWin()
{
if (choosegroup_menu)
gtk_widget_destroy(choosegroup_menu);
}
void LeftWin::Create(GtkWidget *hbox, bool has_treedict)
{
#if GTK_MAJOR_VERSION >= 3
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
#else
vbox = gtk_vbox_new(FALSE, 3);
#endif
if (!conf->get_bool_at("main_window/hide_list"))
gtk_widget_show(vbox);
gtk_box_pack_start(GTK_BOX(hbox),vbox, false, false, 0);
GtkWidget *wazard_button = gtk_radio_button_new(NULL);
gtk_widget_set_can_focus (wazard_button, FALSE);
gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(wazard_button), false);
gtk_box_pack_start(GTK_BOX(vbox),wazard_button, false, false, 0);
GtkWidget *image = gtk_image_new_from_pixbuf(get_impl(gpAppFrame->oAppSkin.index_wazard));
gtk_container_add (GTK_CONTAINER (wazard_button), image);
gtk_widget_show_all(wazard_button);
gtk_widget_set_tooltip_text(wazard_button,_("List"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wazard_button), true);
g_signal_connect(G_OBJECT(wazard_button),"toggled", G_CALLBACK(on_wazard_button_toggled), this);
GtkWidget *result_button = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(wazard_button));
gtk_widget_set_can_focus (result_button, FALSE);
gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(result_button), false);
gtk_box_pack_start(GTK_BOX(vbox),result_button, false, false, 0);
image = gtk_image_new_from_pixbuf(get_impl(gpAppFrame->oAppSkin.index_dictlist));
gtk_container_add (GTK_CONTAINER (result_button), image);
gtk_widget_show_all(result_button);
gtk_widget_set_tooltip_text(result_button,_("Result"));
g_signal_connect(G_OBJECT(result_button),"toggled", G_CALLBACK(on_result_button_toggled), this);
GtkWidget *translate_button = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(result_button));
gtk_widget_set_can_focus (translate_button, FALSE);
gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(translate_button), false);
gtk_box_pack_start(GTK_BOX(vbox),translate_button, false, false, 0);
image = gtk_image_new_from_pixbuf(get_impl(gpAppFrame->oAppSkin.index_translate));
gtk_container_add (GTK_CONTAINER (translate_button), image);
gtk_widget_show_all(translate_button);
gtk_widget_set_tooltip_text(translate_button,_("Full-Text Translation"));
g_signal_connect(G_OBJECT(translate_button),"toggled", G_CALLBACK(on_translate_button_toggled), this);
GtkWidget *history_button = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(wazard_button));
gtk_widget_set_can_focus (history_button, FALSE);
gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(history_button), false);
gtk_box_pack_start(GTK_BOX(vbox),history_button, false, false, 0);
image = gtk_image_new_from_pixbuf(get_impl(gpAppFrame->oAppSkin.index_history));
gtk_container_add (GTK_CONTAINER (history_button), image);
gtk_widget_show_all(history_button);
gtk_widget_set_tooltip_text(history_button,_("History"));
g_signal_connect(G_OBJECT(history_button),"toggled", G_CALLBACK(on_history_button_toggled), this);
if (has_treedict) {
GtkWidget *appendix_button = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(translate_button));
gtk_widget_set_can_focus (appendix_button, FALSE);
gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(appendix_button), false);
gtk_box_pack_start(GTK_BOX(vbox),appendix_button, false, false, 0);
image = gtk_image_new_from_pixbuf(get_impl(gpAppFrame->oAppSkin.index_appendix));
gtk_container_add (GTK_CONTAINER (appendix_button), image);
gtk_widget_show_all(appendix_button);
gtk_widget_set_tooltip_text(appendix_button,_("Tree"));
g_signal_connect(G_OBJECT(appendix_button),"toggled", G_CALLBACK(on_appendix_button_toggled), this);
}
GtkWidget *choosegroup_button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(choosegroup_button),gtk_image_new_from_icon_name(GTK_STOCK_CONVERT,GTK_ICON_SIZE_BUTTON));
gtk_widget_show_all(choosegroup_button);
gtk_button_set_relief (GTK_BUTTON (choosegroup_button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (choosegroup_button, FALSE);
g_signal_connect(G_OBJECT(choosegroup_button),"clicked", G_CALLBACK(on_choose_group_button_clicked),this);
gtk_box_pack_start(GTK_BOX(vbox),choosegroup_button,false,false,0);
gtk_widget_set_tooltip_text(choosegroup_button, _("Choose dict group"));
GtkWidget *button;
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_GO_DOWN,GTK_ICON_SIZE_BUTTON));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(NextCallback),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_end(GTK_BOX(vbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Next word (Alt+Down)"));
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_GO_UP,GTK_ICON_SIZE_BUTTON));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(PreviousCallback),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_end(GTK_BOX(vbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Previous word (Alt+Up)"));
}
void LeftWin::on_wazard_button_toggled(GtkToggleButton *button, LeftWin *oLeftWin)
{
if (gtk_toggle_button_get_active(button)) {
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.notebook), 0);
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.oIndexWin.notebook), 0);
}
}
void LeftWin::on_result_button_toggled(GtkToggleButton *button, LeftWin *oLeftWin)
{
if (gtk_toggle_button_get_active(button)) {
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.notebook), 0);
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.oIndexWin.notebook), 1);
}
}
void LeftWin::on_history_button_toggled(GtkToggleButton *button, LeftWin *oLeftWin)
{
if (gtk_toggle_button_get_active(button)) {
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.notebook), 0);
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.oIndexWin.notebook), 2);
}
}
void LeftWin::on_translate_button_toggled(GtkToggleButton *button, LeftWin *oLeftWin)
{
if (gtk_toggle_button_get_active(button))
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.notebook), 1);
}
void LeftWin::on_appendix_button_toggled(GtkToggleButton *button, LeftWin *oLeftWin)
{
if (gtk_toggle_button_get_active(button)) {
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.notebook), 0);
gtk_notebook_set_current_page(GTK_NOTEBOOK(gpAppFrame->oMidWin.oIndexWin.notebook), 2);
}
}
void LeftWin::PreviousCallback(GtkWidget *widget, LeftWin *oLeftWin)
{
play_sound_on_event("buttonactive");
gpAppFrame->oTopWin.do_prev();
}
void LeftWin::NextCallback(GtkWidget *widget, LeftWin *oLeftWin)
{
play_sound_on_event("buttonactive");
gpAppFrame->oTopWin.do_next();
}
void LeftWin::UpdateChooseGroup()
{
if (choosegroup_menu)
gtk_widget_destroy(choosegroup_menu);
choosegroup_menu = gtk_menu_new();
GtkWidget *menuitem;
menuitem = gtk_check_menu_item_new_with_label(_("Enable Net Dict"));
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), conf->get_bool_at("network/enable_netdict"));
g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(on_enable_netdict_menuitem_toggled), this);
gtk_menu_shell_append(GTK_MENU_SHELL(choosegroup_menu), menuitem);
menuitem = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(choosegroup_menu), menuitem);
std::list<std::string> group_list;
for (std::list<DictManageGroup>::iterator i = gpAppFrame->dictinfo.groups.begin(); i != gpAppFrame->dictinfo.groups.end(); ++i) {
group_list.push_back(i->name);
}
GSList *group = NULL;
for (std::list<std::string>::iterator i = group_list.begin(); i != group_list.end(); ++i) {
menuitem = gtk_radio_menu_item_new_with_label(group, i->c_str());
g_object_set_data_full(G_OBJECT(menuitem), "stardict_dict_group", g_strdup(i->c_str()), g_free);
g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(on_choose_group_menuitem_toggled), this);
gtk_menu_shell_append(GTK_MENU_SHELL(choosegroup_menu), menuitem);
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
if (*i == gpAppFrame->dictinfo.active_group) {
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
}
}
gtk_widget_show_all(choosegroup_menu);
}
void LeftWin::on_enable_netdict_menuitem_toggled(GtkCheckMenuItem *menuitem, LeftWin *oLeftWin)
{
bool enable_netdict = static_cast<bool>(gtk_check_menu_item_get_active(menuitem));
if(enable_netdict) {
if(!confirm_enable_network_dicts())
enable_netdict = false;
}
conf->set_bool_at("network/enable_netdict", enable_netdict);
}
void LeftWin::on_choose_group_menuitem_toggled(GtkCheckMenuItem *menuitem, LeftWin *oLeftWin)
{
if (gtk_check_menu_item_get_active(menuitem)) {
const char *group = (const char *)g_object_get_data(G_OBJECT(menuitem), "stardict_dict_group");
gpAppFrame->dictinfo.active_group = group;
UpdateDictMask();
const gchar *sWord = gpAppFrame->oTopWin.get_text();
if (sWord && sWord[0])
gpAppFrame->TopWinWordChange(sWord);
}
}
void LeftWin::on_choose_group_button_clicked(GtkWidget *widget, LeftWin *oLeftWin)
{
oLeftWin->UpdateChooseGroup();
if (oLeftWin->choosegroup_menu) {
play_sound_on_event("menushow");
#if ((GTK_MAJOR_VERSION == 3) && (GTK_MINOR_VERSION >= 22)) || (GTK_MAJOR_VERSION >= 4)
gtk_menu_popup_at_widget(GTK_MENU(oLeftWin->choosegroup_menu), NULL, GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
#else
gtk_menu_popup(GTK_MENU(oLeftWin->choosegroup_menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time());
#endif
}
}
IndexWin::IndexWin()
{
}
bool IndexWin::Create(GtkWidget *hpaned)
{
notebook = gtk_notebook_new();
if (!conf->get_bool_at("main_window/hide_list"))
gtk_widget_show(notebook);
gtk_paned_pack1(GTK_PANED(hpaned),notebook,true,false);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook),FALSE);
oListWin.Create(notebook);
oResultWin.Create(notebook);
oHistoryWin.Create(notebook);
return oTreeWin.Create(notebook);
}
ToolWin::ToolWin()
{
}
ToolWin::~ToolWin()
{
}
void ToolWin::on_pronounce_menu_item_activate(GtkMenuItem *menuitem, int engine_index)
{
gpAppFrame->oReadWord.ReadByEngine(gpAppFrame->oMidWin.oTextWin.pronounceWord.c_str(), engine_index);
}
void ToolWin::UpdatePronounceMenu()
{
GtkWidget *PronounceWordMenu;
std::list<std::pair<std::string, int> > engine_list = gpAppFrame->oReadWord.GetEngineList();
if (engine_list.empty()) {
PronounceWordMenu = NULL;
} else {
PronounceWordMenu = gtk_menu_new();
GtkWidget *menuitem;
for (std::list<std::pair<std::string, int> >::iterator i = engine_list.begin(); i != engine_list.end(); ++i) {
menuitem = gtk_menu_item_new_with_label(i->first.c_str());
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_pronounce_menu_item_activate), GINT_TO_POINTER(i->second));
gtk_menu_shell_append(GTK_MENU_SHELL(PronounceWordMenu), menuitem);
}
gtk_widget_show_all(PronounceWordMenu);
}
gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(PronounceWordMenuButton), PronounceWordMenu);
}
static void unfocus_menu_button(GtkWidget *widget, gpointer data)
{
gtk_widget_set_can_focus(widget, FALSE);
if (GTK_IS_CONTAINER(widget))
gtk_container_forall(GTK_CONTAINER(widget), unfocus_menu_button, data);
}
void ToolWin::Create(GtkWidget *vbox)
{
GtkWidget *hbox;
#if GTK_MAJOR_VERSION >= 3
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
#else
hbox = gtk_hbox_new(false,0);
#endif
gtk_widget_show(hbox);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(vbox),hbox,false,false,0);
#else
gtk_box_pack_start(GTK_BOX(vbox),hbox,false,false,3);
#endif
GtkWidget *image;
ShowListButton=gtk_button_new();
image = gtk_image_new_from_icon_name(GTK_STOCK_GOTO_LAST,GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_widget_show(image);
gtk_container_add(GTK_CONTAINER(ShowListButton),image);
gtk_button_set_relief (GTK_BUTTON (ShowListButton), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (ShowListButton, FALSE);
g_signal_connect(G_OBJECT(ShowListButton),"clicked", G_CALLBACK(ShowListCallback),NULL);
g_signal_connect(G_OBJECT(ShowListButton),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(hbox),ShowListButton,false,false,0);
#else
gtk_box_pack_start(GTK_BOX(hbox),ShowListButton,false,false,5);
#endif
gtk_widget_set_tooltip_text(ShowListButton,_("Show the word list"));
HideListButton=gtk_button_new();
image = gtk_image_new_from_icon_name(GTK_STOCK_GOTO_FIRST,GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_widget_show(image);
gtk_container_add(GTK_CONTAINER(HideListButton),image);
gtk_button_set_relief (GTK_BUTTON (HideListButton), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (HideListButton, FALSE);
g_signal_connect(G_OBJECT(HideListButton),"clicked", G_CALLBACK(HideListCallback),NULL);
g_signal_connect(G_OBJECT(HideListButton),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(hbox),HideListButton,false,false,0);
#else
gtk_box_pack_start(GTK_BOX(hbox),HideListButton,false,false,5);
#endif
gtk_widget_set_tooltip_text(HideListButton,_("Hide the word list"));
if (conf->get_bool_at("main_window/hide_list"))
gtk_widget_show(ShowListButton);
else
gtk_widget_show(HideListButton);
GtkWidget *button;
#ifndef CONFIG_GPE
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_COPY,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(CopyCallback),this);
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,5);
gtk_widget_set_tooltip_text(button,_("Copy"));
#endif
PronounceWordMenuButton = gtk_menu_tool_button_new_from_stock(GTK_STOCK_EXECUTE);
UpdatePronounceMenu();
gtk_widget_show(GTK_WIDGET(PronounceWordMenuButton));
gtk_widget_set_can_focus (GTK_WIDGET(PronounceWordMenuButton), FALSE);
gtk_container_forall(GTK_CONTAINER(PronounceWordMenuButton), unfocus_menu_button, this);
g_signal_connect(G_OBJECT(PronounceWordMenuButton),"clicked", G_CALLBACK(PlayCallback),this);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(PronounceWordMenuButton),false,false,0);
#else
gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(PronounceWordMenuButton),false,false,5);
#endif
gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(PronounceWordMenuButton), _("Pronounce the word (Enter)"));
gtk_widget_set_sensitive(GTK_WIDGET(PronounceWordMenuButton), false);
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_SAVE,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(SaveCallback),this);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,0);
#else
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,5);
#endif
gtk_widget_set_tooltip_text(button,_("Save to file (Alt+E)"));
#if 0
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_PRINT,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(PrintCallback),this);
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,5);
gtk_widget_set_tooltip_text(button,_("Print"));
gtk_widget_set_sensitive(button, false);
#endif
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_FIND,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(SearchCallback),this);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,0);
#else
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,5);
#endif
gtk_widget_set_tooltip_text(button,_("Search in the definition text (Ctrl+F)"));
}
void ToolWin::ShowListCallback(GtkWidget *widget, gpointer data)
{
conf->set_bool_at("main_window/hide_list", false);
}
void ToolWin::HideListCallback(GtkWidget *widget, gpointer data)
{
conf->set_bool_at("main_window/hide_list", true);
}
#ifndef CONFIG_GPE
void ToolWin::CopyCallback(GtkWidget *widget, ToolWin *oToolWin)
{
std::string text = gpAppFrame->oMidWin.oTextWin.view->get_text();
GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_text(clipboard, text.c_str(), -1);
}
#endif
void ToolWin::PlayCallback(GtkWidget *widget, ToolWin *oToolWin)
{
gpAppFrame->oTopWin.InsertHisList(gpAppFrame->oTopWin.get_text());
gpAppFrame->oTopWin.InsertBackList();
gpAppFrame->oReadWord.read(gpAppFrame->oMidWin.oTextWin.pronounceWord.c_str(), gpAppFrame->oMidWin.oTextWin.readwordtype);
}
void ToolWin::do_save()
{
TextWin &oTextWin=gpAppFrame->oMidWin.oTextWin;
if (conf->get_bool_at("dictionary/only_export_word")) {
if (!oTextWin.queryWord.empty()) {
const std::string& filePath = conf->get_string_at("dictionary/export_file");
#ifdef _WIN32
FILE *fp = fopen(abs_path_to_data_dir(filePath).c_str(), "a+");
#else
FILE *fp = fopen(filePath.c_str(), "a+");
#endif
if(fp) {
fputs(oTextWin.queryWord.c_str(),fp);
fputs("\n",fp);
fclose(fp);
}
}
} else {
GtkTextIter start, end;
gchar *str = NULL;
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTextWin.view->widget()));
if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end))
str = gtk_text_buffer_get_text(buffer, &start, &end, false);
const std::string& filePath = conf->get_string_at("dictionary/export_file");
#ifdef _WIN32
FILE *fp = fopen(abs_path_to_data_dir(filePath).c_str(), "a+");
#else
FILE *fp = fopen(filePath.c_str(), "a+");
#endif
if(fp) {
if(str) {
fputs(oTextWin.queryWord.c_str(),fp);
fputs("\n",fp);
fputs(str,fp);
fputs("\n",fp);
} else {
fputs(oTextWin.view->get_text().c_str(),fp);
}
fputs("\n",fp);
fclose(fp);
}
if (str)
g_free(str);
}
play_sound_on_event("buttonactive");
}
void ToolWin::SaveCallback(GtkWidget *widget, ToolWin *oToolWin)
{
oToolWin->do_save();
}
void ToolWin::do_search()
{
TextWin &oTextWin=gpAppFrame->oMidWin.oTextWin;
oTextWin.ShowSearchPanel();
oTextWin.search_from_beginning = TRUE;
GtkTextIter start,end;
GtkTextBuffer *buffer =
gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTextWin.view->widget()));
if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) {
if (gtk_text_iter_get_offset(&end) - gtk_text_iter_get_offset(&start) < 80) {
gchar *str = gtk_text_buffer_get_text(buffer, &start, &end, false);
oTextWin.find_text = str;
g_free(str);
}
}
if (!oTextWin.find_text.empty())
gtk_entry_set_text(oTextWin.eSearch, oTextWin.find_text.c_str());
}
void ToolWin::SearchCallback(GtkWidget *widget, ToolWin *oToolWin)
{
oToolWin->do_search();
}
void TextWin::OnCloseSearchPanel(GtkWidget *widget, TextWin *oTextWin)
{
oTextWin->HideSearchPanel();
}
gboolean TextWin::OnSearchKeyPress(GtkWidget *widget, GdkEventKey *event,
TextWin *oTextWin)
{
if (event->type==GDK_KEY_PRESS && event->keyval==GDK_KEY_Return)
gtk_button_clicked(oTextWin->btFind);
return FALSE;
}
void TextWin::OnFindSearchPanel(GtkWidget *widget, TextWin *oTextWin)
{
const gchar *text=gtk_entry_get_text(oTextWin->eSearch);
if (text && *text) {
if (oTextWin->Find(text, oTextWin->search_from_beginning)) {
oTextWin->search_from_beginning = FALSE;
oTextWin->find_text = text;
} else {
oTextWin->search_from_beginning = TRUE;
}
}
}
void TextWin::ShowSearchPanel()
{
gtk_widget_show(hbSearchPanel);
gtk_widget_grab_focus(GTK_WIDGET(eSearch));
}
void TextWin::HideSearchPanel()
{
gtk_widget_hide(hbSearchPanel);
}
void TextWin::set_bookname_style(BookNameStyle style)
{
if (view.get()) {
view->set_bookname_style(style);
}
}
void TextWin::set_font_name(const gchar *fontname)
{
if (view.get()) {
view->set_font_name(fontname);
}
}
void TextWin::Create(GtkWidget *vbox)
{
view.reset(new ArticleView(GTK_BOX(vbox), (BookNameStyle)conf->get_int_at("dictionary/bookname_style")));
if (conf->get_bool_at("dictionary/use_textview_font")) {
const std::string &textview_font(conf->get_string_at("main_window/textview_font"));
if (!textview_font.empty()) {
view->set_font_name(textview_font.c_str());
}
}
view->connect_on_link(sigc::mem_fun(gpAppFrame, &AppCore::on_link_click));
g_signal_connect(G_OBJECT(view->widget()), "button_press_event",
G_CALLBACK(on_button_press), this);
g_signal_connect(G_OBJECT(view->widget()), "selection_received",
G_CALLBACK(SelectionCallback), this);
g_signal_connect(G_OBJECT(view->widget()), "populate-popup",
G_CALLBACK(on_populate_popup), this);
#if GTK_MAJOR_VERSION >= 3
hbSearchPanel = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
#else
hbSearchPanel = gtk_hbox_new(FALSE, 0);
#endif
btClose = GTK_BUTTON(gtk_button_new());
gtk_widget_show(GTK_WIDGET(btClose));
GtkWidget *image =
gtk_image_new_from_icon_name(GTK_STOCK_CANCEL,
GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_widget_show(image);
gtk_container_add(GTK_CONTAINER(btClose), image);
gtk_button_set_relief(btClose, GTK_RELIEF_NONE);
gtk_widget_set_can_focus(GTK_WIDGET(btClose), FALSE);
gtk_widget_set_tooltip_text(GTK_WIDGET(btClose), _("Close"));
g_signal_connect(G_OBJECT(btClose), "clicked",
G_CALLBACK(OnCloseSearchPanel), this);
gtk_box_pack_start(GTK_BOX(hbSearchPanel), GTK_WIDGET(btClose), FALSE, FALSE, 3);
eSearch = GTK_ENTRY(gtk_entry_new());
gtk_widget_show(GTK_WIDGET(eSearch));
gtk_widget_set_size_request(GTK_WIDGET(eSearch), 20, -1);
g_signal_connect(G_OBJECT(eSearch), "key_press_event",
G_CALLBACK(OnSearchKeyPress), this);
gtk_box_pack_start(GTK_BOX(hbSearchPanel), GTK_WIDGET(eSearch), TRUE, TRUE, 0);
btFind = GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_FIND));
gtk_widget_show(GTK_WIDGET(btFind));
gtk_button_set_relief(btFind, GTK_RELIEF_NONE);
gtk_widget_set_can_focus(GTK_WIDGET(btFind), FALSE);
gtk_widget_set_tooltip_text(GTK_WIDGET(btFind), _("Find"));
g_signal_connect(G_OBJECT(btFind), "clicked",
G_CALLBACK(OnFindSearchPanel), this);
gtk_box_pack_start(GTK_BOX(hbSearchPanel), GTK_WIDGET(btFind), FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(vbox), hbSearchPanel, FALSE, FALSE, 0);
}
void TextWin::ShowInitFailed()
{
char *fmt = _("Warning! No dictionary is loaded.\n"
"Please go to StarDict's website, download some dictionaries:\n"
"%s%s%s and put them in %s.");
const char *link_pos = strstr(fmt, "%s%s%s");
LinksPosList links;
links.push_back(LinkDesc(g_utf8_strlen(fmt, link_pos - fmt),
sizeof("http://stardict-4.sourceforge.net") - 1, "http://stardict-4.sourceforge.net"));
glib::CharStr esc_fmt(g_markup_escape_text(fmt, -1));
std::string dirs_str;
#ifdef _WIN32
std::list<std::string> dirs;
{
const std::list<std::string>& dirs_rel = conf->get_strlist("/apps/stardict/manage_dictionaries/dict_dirs_list");
abs_path_to_data_dir(dirs_rel, dirs);
}
#else
const std::list<std::string>& dirs = conf->get_strlist("/apps/stardict/manage_dictionaries/dict_dirs_list");
#endif
for(std::list<std::string>::const_iterator it = dirs.begin(); it != dirs.end(); ++it) {
if(!dirs_str.empty())
dirs_str += ", ";
dirs_str += *it;
}
glib::CharStr mes(
g_strdup_printf(get_impl(esc_fmt),
"<span foreground=\"blue\" underline=\"single\">",
"http://stardict-4.sourceforge.net",
"</span>",
dirs_str.c_str()));
view->clear();
view->append_pango_text_with_links(get_impl(mes), links);
view->scroll_to(0);
}
void TextWin::ShowTips()
{
query_result = TEXT_WIN_TIPS;
view->set_text(
_(" Welcome to StarDict!\n\n"
" Press Ctrl+Q to quit. Press Alt+Z to iconify (minimize) the window or Alt+X to minimize to tray.\n"
" Press Alt+C or ESC to clear the input entry's text.\n"
" Press Space key to move focus to the input entry.\n"
" If the query word was not found, you can press Tab key to select the first word in the word list.\n"
" After selected some text, clicking the middle mouse button on the main window's Definition area or on the notification area icon will look up that word.\n"
" StarDict can match strings against patterns containing '*' (wildcard) and '?' (joker).\n"
" Input a word beginning with \'/\' to do a Fuzzy query.\n"
" When the floating window reports that a word was not found, double clicking will perform a fuzzy query.\n")
);
view->scroll_to(0);
}
void TextWin::ShowInfo()
{
query_result = TEXT_WIN_INFO;
view->set_text(
_(" Welcome to StarDict\n"
"StarDict is a Cross-Platform and international dictionary written in Gtk. "
"It has powerful features, such as \"Glob-style pattern matching,\" \"Scan selected word,\" \"Fuzzy query\" and \"Full-text search\".\n\n"
" Here is an introduction to using StarDict:\n\n"
" 1. Glob-style pattern matching\n"
" You can input strings containing \'*\' (wildcard) and \'?\' (joker) as the pattern. "
"\'*\' matches an arbitrary, possibly empty, string, and \'?\' matches an arbitrary character. "
"After pressing Enter, the words that match this pattern will be shown in the list.\n"
" 2. Regular expressions matching\n"
" You can input strings as Perl-compatible regular expressions with a beginning \":\" character as the identifier. "
"After pressing Enter, the words that match this regex will be shown in the list.\n"
" 3. Fuzzy query\n"
" When you can't remember how to spell a word exactly, you can try StarDict's Fuzzy query. "
"It uses \"Levenshtein Edit Distance\" to compute the similarity between two words, and gives the match results which are most "
"similar to the word that you input. "
"To create a fuzzy query, just input the word with a beginning \"/\", and then press Enter.\n"
" 4. Full-text search\n"
" Full-text search searches for a word in the data. To create a Full-text search, just input the word with a beginning \"|\", and then press Enter. For example, \"|ab cd\" searches data which contain both \"ab\" and \"cd\". If the words contain Space character, you can use \"\\ \", such as \"|apple\\ pie\", other escaping characters are \"\\\\\" for \'\\\', \"\\t\" for Tab and \"\\n\" for new line.\n"
" 5. Special character search\n"
" If your words contain special characters, you can use \'\\\' to escape it, for example, \"a\\*b\\?\" searches \"a*b?\", \"\\/abc\" searches \"/abc\".\n"
" 6. Scan the selected word\n"
" Turn on the check button at the bottom-left corner of the StarDict window to activate this feature. "
"When this feature is on, StarDict will automatically look up words, phrases, and Chinese characters in other applications. "
"Just highlight a word or phrase with your mouse, and a floating window will pop up showing the definition of the "
"selected word.\n"
" 7. Dictionary management\n"
" Click the \"Manage dictionaries\" button at the bottom-right corner of the window to access the dictionary management "
"dialog. From here, you can disable some dictionaries that you don't need, and set the dictionaries\' querying order.\n"
"\n\n"
" Statement: This program is distributed in the hope that it will be useful, "
"but WITHOUT ANY WARRANTY; without the warranty "
"that the word spelling, definition, and phonetic information are correct.\n"
)
);
view->scroll_to(0);
}
void TextWin::Show(const gchar *str)
{
view->set_text(str);
view->scroll_to(0);
}
void TextWin::Show(const gchar *orig_word, gchar ***Word, gchar ****WordData)
{
view->begin_update();
view->clear();
view->goto_begin();
int j,k;
for (size_t i=0; i<gpAppFrame->query_dictmask.size(); i++) {
if (Word[i]) {
view->SetDictIndex(gpAppFrame->query_dictmask[i]);
if (gpAppFrame->query_dictmask[i].type == InstantDictType_LOCAL) {
const std::string &dicttype = gpAppFrame->oLibs.dict_type(gpAppFrame->query_dictmask[i].index);
if (!dicttype.empty()) {
size_t nPlugins = gpAppFrame->oStarDictPlugins->SpecialDictPlugins.nplugins();
GtkWidget *widget = NULL;
for (size_t iPlugin = 0; iPlugin < nPlugins; iPlugin++) {
if (dicttype == gpAppFrame->oStarDictPlugins->SpecialDictPlugins.dict_type(iPlugin)) {
gpAppFrame->oStarDictPlugins->SpecialDictPlugins.render_widget(iPlugin, true, gpAppFrame->query_dictmask[i].index, orig_word, Word[i], WordData[i], &widget);
break;
}
}
if (widget) {
view->AppendHeaderMark();
view->append_widget(widget);
view->AppendNewline();
continue;
}
}
view->AppendHeader(gpAppFrame->oLibs.dict_name(gpAppFrame->query_dictmask[i].index).c_str());
} else if (gpAppFrame->query_dictmask[i].type == InstantDictType_VIRTUAL) {
view->AppendHeader(gpAppFrame->oStarDictPlugins->VirtualDictPlugins.dict_name(gpAppFrame->query_dictmask[i].index));
} else if (gpAppFrame->query_dictmask[i].type == InstantDictType_NET) {
view->AppendHeader(gpAppFrame->oStarDictPlugins->NetDictPlugins.dict_name(gpAppFrame->query_dictmask[i].index), gpAppFrame->oStarDictPlugins->NetDictPlugins.dict_link(gpAppFrame->query_dictmask[i].index));
}
j=0;
do {
view->AppendWord(Word[i][j]);
view->AppendData(WordData[i][j][0], Word[i][j],
orig_word);
view->AppendNewline();
k=1;
while (WordData[i][j][k]) {
view->AppendDataSeparate();
view->AppendData(WordData[i][j][k],
Word[i][j], orig_word);
view->AppendNewline();
k++;
}
j++;
} while (Word[i][j]);
}
}
view->end_update();
}
void TextWin::Show(NetDictResponse *resp)
{
view->begin_update();
bool do_append;
if (query_result == TEXT_WIN_FOUND || query_result == TEXT_WIN_SHOW_FIRST || query_result == TEXT_WIN_NET_FOUND || query_result == TEXT_WIN_NET_SHOW_FIRST) {
do_append = true;
view->goto_end();
} else {
do_append = false;
view->clear();
view->goto_begin();
}
if (resp->data) {
query_result = TEXT_WIN_NET_FOUND;
InstantDictIndex dict_index;
dict_index.type = InstantDictType_UNKNOWN;
view->SetDictIndex(dict_index);
gchar *mark = g_strdup_printf("%d", view->get_bookindex());
gpAppFrame->oMidWin.oIndexWin.oResultWin.InsertLast(resp->bookname, mark);
g_free(mark);
view->AppendHeader(resp->bookname, resp->booklink);
view->AppendWord(resp->word);
view->AppendData(resp->data, resp->word, resp->word);
view->AppendNewline();
} else {
if (!do_append) {
query_result = TEXT_WIN_NET_NOT_FOUND;
Show(_("<Not Found!>"));
}
}
view->end_update();
}
void TextWin::Show(const struct STARDICT::LookupResponse::DictResponse *dict_response, STARDICT::LookupResponse::ListType list_type)
{
view->begin_update();
bool do_append;
if (query_result == TEXT_WIN_FOUND || query_result == TEXT_WIN_SHOW_FIRST || query_result == TEXT_WIN_NET_FOUND || query_result == TEXT_WIN_NET_SHOW_FIRST) {
do_append = true;
view->goto_end();
} else {
do_append = false;
view->clear();
view->goto_begin();
}
if (dict_response->dict_result_list.empty()) {
if (!do_append) {
query_result = TEXT_WIN_NET_NOT_FOUND;
if (list_type == STARDICT::LookupResponse::ListType_Rule_List) {
Show(_("Found no words matching this pattern!"));
} else if (list_type == STARDICT::LookupResponse::ListType_Regex_List) {
Show(_("Found no words matching this regular expression!"));
} else if (list_type == STARDICT::LookupResponse::ListType_Fuzzy_List) {
Show(_("There are too many spelling errors :-("));
} else if (list_type == STARDICT::LookupResponse::ListType_Tree) {
Show(_("There are no dictionary articles containing this word. :-("));
} else {
Show(_("<Not Found!>"));
}
}
} else {
if (dict_response->oword == queryWord) {
query_result = TEXT_WIN_NET_FOUND;
} else {
if (query_result == TEXT_WIN_FOUND)
query_result = TEXT_WIN_NET_FOUND;
else if (query_result == TEXT_WIN_SHOW_FIRST)
query_result = TEXT_WIN_NET_SHOW_FIRST;
}
InstantDictIndex dict_index;
dict_index.type = InstantDictType_UNKNOWN;
view->SetDictIndex(dict_index);
for (std::list<struct STARDICT::LookupResponse::DictResponse::DictResult *>::const_iterator i = dict_response->dict_result_list.begin(); i != dict_response->dict_result_list.end(); ++i) {
gchar *mark = g_strdup_printf("%d", view->get_bookindex());
gpAppFrame->oMidWin.oIndexWin.oResultWin.InsertLast((*i)->bookname, mark);
g_free(mark);
view->AppendHeader((*i)->bookname);
for (std::list<struct STARDICT::LookupResponse::DictResponse::DictResult::WordResult *>::iterator j = (*i)->word_result_list.begin(); j != (*i)->word_result_list.end(); ++j) {
view->AppendWord((*j)->word);
std::list<char *>::iterator k = (*j)->datalist.begin();
view->AppendData(*k, (*j)->word, dict_response->oword);
view->AppendNewline();
for (++k; k != (*j)->datalist.end(); ++k) {
view->AppendDataSeparate();
view->AppendData(*k, (*j)->word, dict_response->oword);
view->AppendNewline();
}
}
}
}
view->end_update();
}
void TextWin::ShowTreeDictData(gchar *data)
{
view->begin_update();
view->clear();
view->goto_begin();
if (data) {
view->AppendData(data, "", NULL);
view->AppendNewline();
}
view->end_update();
}
gboolean TextWin::Find (const gchar *text, gboolean start)
{
GtkTextBuffer *buffer =
gtk_text_view_get_buffer(GTK_TEXT_VIEW(view->widget()));
GtkTextIter iter;
if (start)
gtk_text_buffer_get_start_iter(buffer, &iter);
else {
GtkTextMark *mark = gtk_text_buffer_get_mark(buffer, "last_search");
if (mark)
gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
else
gtk_text_buffer_get_start_iter(buffer, &iter);
}
GtkTextIter match_start, match_end;
if (gtk_text_iter_forward_search(&iter, text,
(GtkTextSearchFlags) (GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY),
&match_start, &match_end,
NULL)) {
gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(view->widget()), &match_start,
0.0, TRUE, 0.5, 0.5);
gtk_text_buffer_place_cursor(buffer, &match_end);
gtk_text_buffer_move_mark(buffer,
gtk_text_buffer_get_mark(buffer, "selection_bound"),
&match_start);
gtk_text_buffer_create_mark(buffer, "last_search", &match_end, FALSE);
return TRUE;
} else {
GtkWidget *message_dlg =
gtk_message_dialog_new(
GTK_WINDOW(gpAppFrame->window),
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
_("The text \"%s\" was not found."), text);
gtk_dialog_set_default_response (GTK_DIALOG (message_dlg), GTK_RESPONSE_OK);
gtk_window_set_resizable (GTK_WINDOW (message_dlg), FALSE);
if (gtk_dialog_run(GTK_DIALOG(message_dlg))!=GTK_RESPONSE_NONE)
gtk_widget_destroy(message_dlg);
return FALSE;
}
}
gboolean TextWin::on_button_press(GtkWidget * widget, GdkEventButton * event, TextWin *oTextWin)
{
if (event->button == 2) {
#ifdef _WIN32
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTextWin->view->widget()));
if (gtk_text_buffer_get_selection_bounds(buffer, NULL, NULL)) {
gtk_selection_convert(widget, GDK_SELECTION_PRIMARY,
gpAppFrame->oSelection.UTF8_STRING_Atom,
GDK_CURRENT_TIME);
} else {
gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
gpAppFrame->oTopWin.ClipboardReceivedCallback, &(gpAppFrame->oTopWin));
}
#else
gtk_selection_convert(widget, GDK_SELECTION_PRIMARY,
gpAppFrame->oSelection.UTF8_STRING_Atom,
GDK_CURRENT_TIME);
#endif
return TRUE;
}
return FALSE;
}
void TextWin::on_pronounce_menu_item_activate(GtkMenuItem *menuitem, TextWin *oTextWin)
{
GtkTextIter start, end;
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTextWin->view->widget()));
if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) {
gchar *str = gtk_text_buffer_get_text(buffer, &start, &end, false);
gpAppFrame->oReadWord.read(str, oTextWin->selection_readwordtype);
g_free(str);
}
}
void TextWin::on_query_menu_item_activate(GtkMenuItem *menuitem, TextWin *oTextWin)
{
GtkTextIter start, end;
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTextWin->view->widget()));
if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) {
gchar *str = gtk_text_buffer_get_text(buffer, &start, &end, false);
std::string estr;
stardict_input_escape(str, estr);
g_free(str);
gpAppFrame->Query(estr.c_str());
}
}
void TextWin::on_populate_popup(GtkTextView *textview, GtkMenu *menu, TextWin *oTextWin)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
GtkTextIter start, end;
if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) {
GtkWidget *menuitem;
menuitem = gtk_separator_menu_item_new();
gtk_widget_show(menuitem);
gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
gchar *str = gtk_text_buffer_get_text(buffer, &start, &end, false);
oTextWin->selection_readwordtype = gpAppFrame->oReadWord.canRead(str);
if (oTextWin->selection_readwordtype != READWORD_CANNOT) {
menuitem = gtk_menu_item_new_with_mnemonic(_("_Pronounce"));
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_pronounce_menu_item_activate), oTextWin);
GtkWidget *image = gtk_image_new_from_icon_name(GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
gtk_widget_show(menuitem);
gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
}
g_free(str);
menuitem = gtk_menu_item_new_with_mnemonic(_("_Query"));
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_query_menu_item_activate), oTextWin);
GtkWidget *image = gtk_image_new_from_icon_name(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
gtk_widget_show(menuitem);
gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
}
}
void TextWin::SelectionCallback(GtkWidget* widget,GtkSelectionData *selection_data, guint time, TextWin *oTextWin)
{
gchar *result;
result = (gchar *)gtk_selection_data_get_text (selection_data);
if (!result) {
* if we asked for compound_text and didn't get it, try string;
* If we asked for anything else and didn't get it, give up.
*/
if (gtk_selection_data_get_target(selection_data) == gpAppFrame->oSelection.UTF8_STRING_Atom) {
gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, gpAppFrame->oSelection.COMPOUND_TEXT_Atom, GDK_CURRENT_TIME);
}
else if (gtk_selection_data_get_target(selection_data) == gpAppFrame->oSelection.COMPOUND_TEXT_Atom)
{
gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, GDK_TARGET_STRING, GDK_CURRENT_TIME);
}
return;
}
std::string estr;
stardict_input_escape(result, estr);
g_free(result);
gpAppFrame->Query(estr.c_str());
}
TransWin::TransWin()
{
}
void TransWin::SetEngine(gint index)
{
if(index < 0 || index >= TranslateEngine_Size)
index = 0;
gtk_combo_box_set_active(GTK_COMBO_BOX(engine_combobox), index);
}
void TransWin::SetFromLang(bool load, gint index)
{
if(load) {
const gint engine_index = gtk_combo_box_get_active(GTK_COMBO_BOX(engine_combobox));
const TransEngine& engine = gpAppFrame->oFullTextTrans.get_engine(engine_index);
const size_t fromlangcnt = engine.get_source_lang_cnt();
GtkListStore* list_store = gtk_list_store_new(1, G_TYPE_STRING);
GtkTreeIter iter;
for(size_t i = 0; i<fromlangcnt; ++i) {
gtk_list_store_append(list_store, &iter);
gtk_list_store_set(list_store, &iter,
0, engine.get_source_lang(i).c_str(),
-1);
}
gtk_combo_box_set_model(GTK_COMBO_BOX(fromlang_combobox), GTK_TREE_MODEL(list_store));
g_object_unref (G_OBJECT(list_store));
}
if(index < 0)
index = 0;
gtk_combo_box_set_active(GTK_COMBO_BOX(fromlang_combobox), index);
}
void TransWin::SetToLang(bool load, gint index)
{
if(load) {
const gint engine_index = gtk_combo_box_get_active(GTK_COMBO_BOX(engine_combobox));
const TransEngine& engine = gpAppFrame->oFullTextTrans.get_engine(engine_index);
const gint fromlang_index = gtk_combo_box_get_active(GTK_COMBO_BOX(fromlang_combobox));
const size_t tolangcnt = engine.get_target_lang_cnt(fromlang_index);
GtkListStore* list_store = gtk_list_store_new(1, G_TYPE_STRING);
GtkTreeIter iter;
for(size_t i = 0; i<tolangcnt; ++i) {
gtk_list_store_append(list_store, &iter);
gtk_list_store_set(list_store, &iter,
0, engine.get_target_lang(fromlang_index, i).c_str(),
-1
);
}
gtk_combo_box_set_model(GTK_COMBO_BOX(tolang_combobox), GTK_TREE_MODEL(list_store));
g_object_unref (G_OBJECT(list_store));
}
if(index < 0)
index = 0;
gtk_combo_box_set_active(GTK_COMBO_BOX(tolang_combobox), index);
}
void TransWin::on_pronounce_menu_item_activate(GtkMenuItem *menuitem, TransWin *oTransWin)
{
gpAppFrame->oReadWord.read(oTransWin->pronounceWord.c_str(), oTransWin->selection_readwordtype);
}
void TransWin::on_populate_popup(GtkTextView *textview, GtkMenu *menu, TransWin *oTransWin)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
GtkTextIter start, end;
if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) {
gchar *str = gtk_text_buffer_get_text(buffer, &start, &end, false);
oTransWin->selection_readwordtype = gpAppFrame->oReadWord.canRead(str);
if (oTransWin->selection_readwordtype != READWORD_CANNOT) {
oTransWin->pronounceWord = str;
GtkWidget *menuitem;
menuitem = gtk_separator_menu_item_new();
gtk_widget_show(menuitem);
gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
menuitem = gtk_menu_item_new_with_mnemonic(_("_Pronounce"));
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_pronounce_menu_item_activate), oTransWin);
GtkWidget *image = gtk_image_new_from_icon_name(GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
gtk_widget_show(menuitem);
gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
}
g_free(str);
}
}
void TransWin::Create(GtkWidget *notebook)
{
GtkWidget *frame;
frame = gtk_frame_new(NULL);
GtkWidget *vbox;
#if GTK_MAJOR_VERSION >= 3
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
#else
vbox = gtk_vbox_new(false, 3);
#endif
gtk_container_set_border_width(GTK_CONTAINER(vbox),8);
gtk_container_add(GTK_CONTAINER(frame), vbox);
GtkWidget *label = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(label), _("<b>Full-Text Translation</b>"));
gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
gtk_box_pack_start(GTK_BOX(vbox), label, false, false, 0);
GtkWidget *hbox;
#if GTK_MAJOR_VERSION >= 3
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
#else
hbox = gtk_hbox_new(false, 5);
#endif
gtk_box_pack_start(GTK_BOX(vbox), hbox, false, false, 0);
GtkListStore* list_store = gtk_list_store_new(1, G_TYPE_STRING);
GtkTreeIter iter;
for (size_t i = 0; i<TranslateEngine_Size; i++) {
gtk_list_store_append(list_store, &iter);
gtk_list_store_set(list_store, &iter,
0, gpAppFrame->oFullTextTrans.get_engine(i).get_name().c_str(),
-1
);
}
engine_combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(list_store));
g_object_unref (G_OBJECT(list_store));
GtkCellRenderer *renderer;
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (engine_combobox), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (engine_combobox), renderer, "text", 0, NULL);
#if GTK_MAJOR_VERSION >= 3
gtk_widget_set_focus_on_click(GTK_WIDGET(engine_combobox), FALSE);
#else
gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(WordCombo), FALSE);
#endif
gtk_box_pack_start(GTK_BOX(hbox), engine_combobox, false, false, 0);
label = gtk_label_new(":");
gtk_box_pack_start(GTK_BOX(hbox), label, false, false, 0);
fromlang_combobox = gtk_combo_box_new();
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (fromlang_combobox), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (fromlang_combobox), renderer, "text", 0, NULL);
#if GTK_MAJOR_VERSION >= 3
gtk_widget_set_focus_on_click(GTK_WIDGET(fromlang_combobox), FALSE);
#else
gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(WordCombo), FALSE);
#endif
gtk_box_pack_start(GTK_BOX(hbox), fromlang_combobox, false, false, 0);
label = gtk_label_new(_("To"));
gtk_box_pack_start(GTK_BOX(hbox), label, false, false, 0);
tolang_combobox = gtk_combo_box_new();
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (tolang_combobox), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (tolang_combobox), renderer, "text", 0, NULL);
#if GTK_MAJOR_VERSION >= 3
gtk_widget_set_focus_on_click(GTK_WIDGET(tolang_combobox), FALSE);
#else
gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(WordCombo), FALSE);
#endif
gtk_box_pack_start(GTK_BOX(hbox), tolang_combobox, false, false, 0);
SetEngine(conf->get_int_at("translate/engine"));
SetFromLang(true, conf->get_int_at("translate/fromlang"));
SetToLang(true, conf->get_int_at("translate/tolang"));
g_signal_connect(G_OBJECT(engine_combobox),"changed", G_CALLBACK(on_engine_combobox_changed), this);
g_signal_connect(G_OBJECT(fromlang_combobox),"changed", G_CALLBACK(on_fromlang_combobox_changed), this);
g_signal_connect(G_OBJECT(tolang_combobox),"changed", G_CALLBACK(on_tolang_combobox_changed), this);
input_textview = gtk_text_view_new();
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(input_textview), GTK_WRAP_WORD_CHAR);
gtk_text_view_set_left_margin(GTK_TEXT_VIEW(input_textview), 5);
gtk_text_view_set_right_margin(GTK_TEXT_VIEW(input_textview), 5);
g_signal_connect(G_OBJECT(input_textview), "populate-popup", G_CALLBACK(on_populate_popup), this);
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(scrolled_window), input_textview);
gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, true, true, 0);
#if GTK_MAJOR_VERSION >= 3
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
#else
hbox = gtk_hbox_new(false, 5);
#endif
gtk_box_pack_start(GTK_BOX(vbox), hbox, false, false, 0);
trans_button = gtk_button_new();
#if GTK_MAJOR_VERSION >= 3
GtkWidget *hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
#else
GtkWidget *hbox1 = gtk_hbox_new(false, 2);
#endif
gtk_container_add (GTK_CONTAINER (trans_button), hbox1);
GtkWidget *image = gtk_image_new_from_pixbuf(get_impl(gpAppFrame->oAppSkin.index_translate));
gtk_box_pack_start (GTK_BOX (hbox1), image, FALSE, FALSE, 0);
label = gtk_label_new_with_mnemonic(_("_Translate"));
gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0);
gtk_label_set_mnemonic_widget(GTK_LABEL(label), trans_button);
g_signal_connect(G_OBJECT(trans_button),"clicked", G_CALLBACK(on_translate_button_clicked), this);
gtk_box_pack_start(GTK_BOX(hbox), trans_button, false, false, 0);
GtkWidget *clear_button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
g_signal_connect(G_OBJECT(clear_button),"clicked", G_CALLBACK(on_clear_button_clicked), this);
gtk_box_pack_start(GTK_BOX(hbox), clear_button, false, false, 5);
result_textview = gtk_text_view_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(result_textview), FALSE);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(result_textview), GTK_WRAP_WORD_CHAR);
gtk_text_view_set_left_margin(GTK_TEXT_VIEW(result_textview), 3);
gtk_text_view_set_right_margin(GTK_TEXT_VIEW(result_textview), 3);
g_signal_connect(G_OBJECT(result_textview), "populate-popup", G_CALLBACK(on_populate_popup), this);
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(scrolled_window), result_textview);
gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, true, true, 0);
#if GTK_MAJOR_VERSION >= 3
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
#else
hbox = gtk_hbox_new(false, 8);
#endif
gtk_box_pack_start(GTK_BOX(vbox), hbox, false, false, 0);
label = gtk_label_new(NULL);
gtk_box_pack_start(GTK_BOX(hbox), label, true, true, 0);
label = gtk_label_new(_("Powered by -"));
gtk_box_pack_start(GTK_BOX(hbox), label, false, false, 0);
link_label = gtk_label_new(NULL);
GtkWidget *link_eventbox = gtk_event_box_new();
g_signal_connect(G_OBJECT(link_eventbox),"button-release-event", G_CALLBACK(on_link_eventbox_clicked), this);
gtk_container_add(GTK_CONTAINER(link_eventbox), link_label);
gtk_box_pack_start (GTK_BOX (hbox), link_eventbox, FALSE, FALSE, 0);
label = gtk_label_new(NULL);
gtk_box_pack_end(GTK_BOX(hbox), label, true, true, 0);
const gint engine_index = gtk_combo_box_get_active(GTK_COMBO_BOX(engine_combobox));
SetLink(engine_index);
g_signal_connect(G_OBJECT(frame), "destroy", G_CALLBACK(on_destroy), this);
gtk_widget_show_all(frame);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, NULL);
gtk_widget_realize(link_eventbox);
#if GTK_MAJOR_VERSION >= 3
GdkCursor* cursor = gdk_cursor_new_for_display(gdk_display_get_default(), GDK_HAND2);
#else
GdkCursor* cursor = gdk_cursor_new(GDK_HAND2);
#endif
gdk_window_set_cursor(gtk_widget_get_window(link_eventbox), cursor);
#if GTK_MAJOR_VERSION >= 3
g_object_unref(cursor);
#else
gdk_cursor_unref(cursor);
#endif
gpAppFrame->oFullTextTrans.on_error_.connect(sigc::mem_fun(this, &TransWin::on_translate_error));
gpAppFrame->oFullTextTrans.on_response_.connect(sigc::mem_fun(this, &TransWin::on_translate_response));
}
void TransWin::SetLink(gint engine_index)
{
SetLink(gpAppFrame->oFullTextTrans.get_engine(engine_index).get_website_url().c_str());
}
void TransWin::SetLink(const char *linkname)
{
gchar *markup = g_markup_printf_escaped("<span foreground=\"blue\" underline=\"single\">%s</span>", linkname);
gtk_label_set_markup(GTK_LABEL(link_label), markup);
g_free(markup);
}
void TransWin::on_link_eventbox_clicked(GtkWidget *widget, GdkEventButton *event, TransWin *oTransWin)
{
gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->engine_combobox));
show_url(gpAppFrame->oFullTextTrans.get_engine(index).get_website_name().c_str());
}
void TransWin::on_engine_combobox_changed(GtkWidget *widget, TransWin *oTransWin)
{
const gint engine_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
oTransWin->SetLink(engine_index);
oTransWin->SetFromLang(true, -1);
oTransWin->SetToLang(true, -1);
}
void TransWin::on_fromlang_combobox_changed(GtkWidget *widget, TransWin *oTransWin)
{
const gint engine_index = gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->engine_combobox));
if(!gpAppFrame->oFullTextTrans.get_engine(engine_index).independent_target_lang())
oTransWin->SetToLang(true, -1);
}
void TransWin::on_tolang_combobox_changed(GtkWidget *widget, TransWin *oTransWin)
{
}
void TransWin::on_translate_button_clicked(GtkWidget *widget, TransWin *oTransWin)
{
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTransWin->input_textview));
GtkTextIter start, end;
gtk_text_buffer_get_bounds(buffer, &start, &end);
gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, false);
if (text[0] == '\0') {
g_free(text);
GtkWidget *message_dlg =
gtk_message_dialog_new(
GTK_WINDOW(gpAppFrame->window),
(GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
_("Please input some words to translate."));
gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
g_signal_connect_swapped (message_dlg, "response", G_CALLBACK (gtk_widget_destroy), message_dlg);
gtk_widget_show(message_dlg);
return;
}
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTransWin->result_textview));
gtk_text_buffer_set_text(buffer, _("Connecting..."), -1);
gpAppFrame->oFullTextTrans.Translate(
gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->engine_combobox)),
gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->fromlang_combobox)),
gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->tolang_combobox)),
text
);
g_free(text);
}
void TransWin::on_clear_button_clicked(GtkWidget *widget, TransWin *oTransWin)
{
GtkTextBuffer* buffer;
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTransWin->input_textview));
gtk_text_buffer_set_text(buffer, "", -1);
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(oTransWin->result_textview));
gtk_text_buffer_set_text(buffer, "", -1);
gtk_widget_grab_focus(oTransWin->input_textview);
}
void TransWin::on_destroy(GtkWidget *object, TransWin* oTransWin)
{
const gint engine_index = gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->engine_combobox));
const gint fromlang_index = gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->fromlang_combobox));
const gint tolang_index = gtk_combo_box_get_active(GTK_COMBO_BOX(oTransWin->tolang_combobox));
conf->set_int_at("translate/engine", engine_index);
conf->set_int_at("translate/fromlang", fromlang_index);
conf->set_int_at("translate/tolang", tolang_index);
}
void TransWin::on_translate_error(const char * error_msg)
{
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(result_textview));
gtk_text_buffer_set_text(buffer, "", -1);
GtkWindow *parent = GTK_WINDOW(gpAppFrame->window);
GtkWidget *message_dlg =
gtk_message_dialog_new(
parent,
(GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"%s", error_msg);
gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
g_signal_connect_swapped (message_dlg, "response", G_CALLBACK (gtk_widget_destroy), message_dlg);
gtk_widget_show(message_dlg);
}
void TransWin::on_translate_response(const char * text)
{
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(result_textview));
gtk_text_buffer_set_text(buffer, text, -1);
}
void MidWin::Create(GtkWidget *vbox)
{
#if GTK_MAJOR_VERSION >= 3
GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
#else
GtkWidget *hbox = gtk_hbox_new(FALSE, 2);
#endif
gtk_widget_show(hbox);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
notebook = gtk_notebook_new();
gtk_widget_show(notebook);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook),FALSE);
#if GTK_MAJOR_VERSION >= 3
hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
#else
hpaned = gtk_hpaned_new();
#endif
gtk_widget_show(hpaned);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hpaned, NULL);
bool has_treedict = oIndexWin.Create(hpaned);
oLeftWin.Create(hbox, has_treedict);
gtk_box_pack_start(GTK_BOX(hbox),notebook, true, true, 0);
#if GTK_MAJOR_VERSION >= 3
GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
#else
GtkWidget *vbox1 = gtk_vbox_new(FALSE, 0);
#endif
gtk_widget_show(vbox1);
oToolWin.Create(vbox1);
oTextWin.Create(vbox1);
gtk_paned_pack2(GTK_PANED(hpaned), vbox1, TRUE, FALSE);
oTransWin.Create(notebook);
}
BottomWin::BottomWin()
{
SearchWebsiteMenu = NULL;
news_timeout_id = 0;
link_timeout_id = 0;
need_resume_news = false;
}
void BottomWin::Destroy()
{
if (news_timeout_id != 0) {
g_source_remove(news_timeout_id);
news_timeout_id = 0;
}
if (link_timeout_id != 0) {
g_source_remove(link_timeout_id);
link_timeout_id = 0;
}
if (SearchWebsiteMenu)
gtk_widget_destroy(SearchWebsiteMenu);
}
void BottomWin::Create(GtkWidget *vbox)
{
#if GTK_MAJOR_VERSION >= 3
GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
#else
GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
#endif
gtk_widget_show(hbox);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
#else
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
#endif
ScanSelectionCheckButton = gtk_check_button_new_with_mnemonic(_("_Scan"));
gtk_widget_show(ScanSelectionCheckButton);
gtk_widget_set_can_focus (ScanSelectionCheckButton, FALSE);
bool scan=conf->get_bool_at("dictionary/scan_selection");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ScanSelectionCheckButton), scan);
g_signal_connect(G_OBJECT(ScanSelectionCheckButton), "toggled",
G_CALLBACK(ScanCallback), NULL);
gtk_box_pack_start(GTK_BOX(hbox),ScanSelectionCheckButton,false,false,0);
gtk_widget_set_tooltip_text(ScanSelectionCheckButton,_("Scan the selection"));
GtkWidget *button = gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_DIALOG_INFO,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(AboutCallback), NULL);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
#ifdef CONFIG_GPE
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,2);
#else
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,8);
#endif
gtk_widget_set_tooltip_text(button,_("Show info"));
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_QUIT,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(QuitCallback), NULL);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_start(GTK_BOX(hbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Quit"));
movenews_event_box = gtk_event_box_new();
g_signal_connect (G_OBJECT (movenews_event_box), "enter_notify_event", G_CALLBACK (vEnterNotifyCallback), this);
g_signal_connect (G_OBJECT (movenews_event_box), "leave_notify_event", G_CALLBACK (vLeaveNotifyCallback), this);
gtk_widget_show(movenews_event_box);
gtk_box_pack_start(GTK_BOX(hbox),movenews_event_box,false,false,0);
news_label = gtk_label_new(NULL);
gtk_container_add(GTK_CONTAINER(movenews_event_box), news_label);
gtk_misc_set_alignment (GTK_MISC (news_label), 0.0, 0.5);
gtk_widget_show(news_label);
#if GTK_MAJOR_VERSION >= 3
link_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
#else
link_hbox = gtk_hbox_new(false, 0);
#endif
gtk_box_pack_start(GTK_BOX(hbox),link_hbox,true,true,0);
GtkWidget *label = gtk_label_new(NULL);
gtk_widget_show(label);
gtk_box_pack_start(GTK_BOX(link_hbox), label, true, true, 0);
GtkWidget *event_box = gtk_event_box_new();
gtk_box_pack_start(GTK_BOX(link_hbox),event_box,false,false,0);
g_signal_connect (G_OBJECT (event_box), "button-release-event", G_CALLBACK(on_link_eventbox_clicked), this);
gtk_widget_show(event_box);
gtk_widget_realize(event_box);
#if GTK_MAJOR_VERSION >= 3
GdkCursor* cursor = gdk_cursor_new_for_display(gdk_display_get_default(), GDK_HAND2);
#else
GdkCursor* cursor = gdk_cursor_new(GDK_HAND2);
#endif
gdk_window_set_cursor(gtk_widget_get_window(event_box), cursor);
#if GTK_MAJOR_VERSION >= 3
g_object_unref(cursor);
#else
gdk_cursor_unref(cursor);
#endif
link_label = gtk_label_new(NULL);
gtk_container_add(GTK_CONTAINER(event_box), link_label);
gtk_widget_show(link_label);
label = gtk_label_new(NULL);
gtk_widget_show(label);
gtk_box_pack_end(GTK_BOX(link_hbox), label, true, true, 0);
#ifndef CONFIG_GPE
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(PreferenceCallback),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_end(GTK_BOX(hbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Preferences"));
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_PROPERTIES,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(DictManageCallback),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_end(GTK_BOX(hbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Manage dictionaries"));
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_INDEX,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(NewVersionCallback),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_end(GTK_BOX(hbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Go to the StarDict website"));
#endif
button=gtk_button_new();
gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_icon_name(GTK_STOCK_JUMP_TO,GTK_ICON_SIZE_SMALL_TOOLBAR));
gtk_widget_show_all(button);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(InternetSearchCallback),this);
g_signal_connect(G_OBJECT(button),"button_press_event", G_CALLBACK(on_internetsearch_button_press),this);
g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
gtk_box_pack_end(GTK_BOX(hbox),button,false,false,0);
gtk_widget_set_tooltip_text(button,_("Search an Internet dictionary - Right button: website list"));
}
void BottomWin::on_link_eventbox_clicked(GtkWidget *widget, GdkEventButton *event, BottomWin *oBottomWin)
{
gpAppFrame->on_link_click(oBottomWin->linklist[oBottomWin->link_index].second);
}
gboolean BottomWin::vEnterNotifyCallback (GtkWidget *widget, GdkEventCrossing *event, BottomWin *oBottomWin)
{
if (oBottomWin->news_timeout_id != 0) {
g_source_remove(oBottomWin->news_timeout_id);
oBottomWin->news_timeout_id = 0;
oBottomWin->need_resume_news = true;
}
return TRUE;
}
gboolean BottomWin::vLeaveNotifyCallback (GtkWidget *widget, GdkEventCrossing *event, BottomWin *oBottomWin)
{
if (oBottomWin->need_resume_news) {
oBottomWin->news_timeout_id = g_timeout_add(300, move_news, oBottomWin);
oBottomWin->need_resume_news = false;
}
return TRUE;
}
gboolean BottomWin::change_link(gpointer data)
{
BottomWin *oBottomWin = static_cast<BottomWin *>(data);
oBottomWin->link_index++;
if (oBottomWin->link_index == oBottomWin->linklist.size()) {
oBottomWin->news_timeout_id = g_timeout_add(300, move_news, data);
gtk_widget_hide(oBottomWin->link_hbox);
gtk_widget_show(oBottomWin->movenews_event_box);
oBottomWin->link_timeout_id = 0;
return FALSE;
} else {
char *markup = g_markup_printf_escaped ("<span foreground=\"blue\" underline=\"single\">%s</span>", oBottomWin->linklist[oBottomWin->link_index].first.c_str());
gtk_label_set_markup(GTK_LABEL(oBottomWin->link_label), markup);
g_free(markup);
return TRUE;
}
}
gboolean BottomWin::move_news(gpointer data)
{
BottomWin *oBottomWin = static_cast<BottomWin *>(data);
const char *p = oBottomWin->news_text.c_str();
size_t i;
for (i = 0; i < oBottomWin->news_move_index; i++) {
if (*p) {
p = g_utf8_next_char(p);
} else {
break;
}
}
if (*p) {
oBottomWin->news_move_index++;
} else {
oBottomWin->news_move_index = 0;
if (oBottomWin->linklist.empty()) {
p = oBottomWin->news_text.c_str();
} else {
oBottomWin->link_index = 0;
gtk_label_set_text(GTK_LABEL(oBottomWin->news_label), "");
gtk_widget_hide(oBottomWin->movenews_event_box);
char *markup = g_markup_printf_escaped ("<span foreground=\"blue\" underline=\"single\">%s</span>", oBottomWin->linklist[0].first.c_str());
gtk_label_set_markup(GTK_LABEL(oBottomWin->link_label), markup);
g_free(markup);
gtk_widget_show(oBottomWin->link_hbox);
oBottomWin->link_timeout_id = g_timeout_add(4000, change_link, data);
oBottomWin->news_timeout_id = 0;
return FALSE;
}
}
const char *p1 = p;
for (i=0; i < oBottomWin->news_move_len; i++) {
if (*p1) {
p1 = g_utf8_next_char(p1);
} else {
break;
}
}
std::string text;
text = "\t";
text.append(p, p1-p);
gtk_label_set_text(GTK_LABEL(oBottomWin->news_label), text.c_str());
return TRUE;
}
void BottomWin::set_news(const char *news, const char *links)
{
if (news) {
news_text = news;
if (IsASCII(news)) {
news_move_len = 30;
} else {
news_move_len = 20;
}
news_move_index = 0;
if (news_timeout_id == 0) {
news_timeout_id = g_timeout_add(300, move_news, this);
}
} else {
news_text.clear();
news_move_index = 0;
if (news_timeout_id != 0) {
g_source_remove(news_timeout_id);
news_timeout_id = 0;
}
gtk_label_set_text(GTK_LABEL(news_label), "");
}
if (links) {
linklist.clear();
std::list<std::string> lines;
const char *p, *p1;
p = links;
do {
p1 = strchr(p, '\n');
if (p1) {
lines.push_back(std::string(p, p1-p));
p = p1 + 1;
}
} while (p1);
lines.push_back(p);
for (std::list<std::string>::iterator i = lines.begin(); i != lines.end(); ++i) {
p = i->c_str();
p1 = strchr(p, '\t');
if (p1) {
linklist.push_back(std::pair<std::string, std::string>(std::string(p, p1-p), std::string(p1+1)));
}
}
} else {
linklist.clear();
}
}
void BottomWin::ScanCallback(GtkToggleButton *button, gpointer data)
{
bool scan_selection=gtk_toggle_button_get_active(button);
conf->set_bool_at("dictionary/scan_selection", scan_selection);
}
void BottomWin::AboutCallback(GtkButton *button, gpointer data)
{
play_sound_on_event("buttonactive");
gpAppFrame->oMidWin.oTextWin.ShowInfo();
}
void BottomWin::QuitCallback(GtkButton *button, gpointer data)
{
play_sound_on_event("buttonactive");
gpAppFrame->Quit();
}
gboolean BottomWin::on_internetsearch_button_press(GtkWidget * widget, GdkEventButton * event , BottomWin *oBottomWin)
{
if (event->button == 3) {
const std::list<std::string> &list=
conf->get_strlist_at("main_window/search_website_list");
if (list.empty())
return true;
if (oBottomWin->SearchWebsiteMenu)
gtk_widget_destroy(oBottomWin->SearchWebsiteMenu);
oBottomWin->SearchWebsiteMenu = gtk_menu_new();
GtkWidget *menuitem;
for (std::list<std::string>::const_iterator ci=list.begin(); ci!=list.end(); ++ci) {
std::vector<std::string> web_list = split(*ci, '\t');
if (web_list.size()==3 && web_list[2].find("%s")!=std::string::npos) {
menuitem = gtk_menu_item_new_with_label(web_list[0].c_str());
g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_internetsearch_menu_item_activate), const_cast<char *>(ci->c_str()));
gtk_menu_shell_append(GTK_MENU_SHELL(oBottomWin->SearchWebsiteMenu), menuitem);
}
}
gtk_widget_show_all(oBottomWin->SearchWebsiteMenu);
#if ((GTK_MAJOR_VERSION == 3) && (GTK_MINOR_VERSION >= 22)) || (GTK_MAJOR_VERSION >= 4)
gtk_menu_popup_at_widget(GTK_MENU(oBottomWin->SearchWebsiteMenu), NULL, GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
#else
gtk_menu_popup(GTK_MENU(oBottomWin->SearchWebsiteMenu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time());
#endif
return true;
}
return false;
}
void BottomWin::on_internetsearch_menu_item_activate(GtkMenuItem *menuitem, const gchar *website)
{
InternetSearch(website);
}
void BottomWin::InternetSearchCallback(GtkButton *button, BottomWin *oBottomWin)
{
const std::list<std::string> &search_website_list=
conf->get_strlist_at("main_window/search_website_list");
if (search_website_list.empty())
return;
InternetSearch(search_website_list.front());
}
#ifndef CONFIG_GPE
void BottomWin::NewVersionCallback(GtkButton *button, BottomWin *oBottomWin)
{
show_url("http://stardict-4.sourceforge.net");
}
void BottomWin::DictManageCallback(GtkButton *button, BottomWin *oBottomWin)
{
gpAppFrame->PopupDictManageDlg();
}
void BottomWin::PreferenceCallback(GtkButton *button, BottomWin *oBottomWin)
{
gpAppFrame->PopupPrefsDlg();
}
#endif
void BottomWin::InternetSearch(const std::string& website)
{
std::vector<std::string> weblist = split(website.c_str(), '\t');
if (weblist.size()!=3)
return;
const gchar *text = gpAppFrame->oTopWin.get_text();
if (text[0]) {
const gchar *str, *p;
str = weblist[2].c_str();
p = strstr(str, "%s");
if (p) {
const gchar *p1;
p1 = p +2;
p = strchr(p1, '%');
if (p) {
g_print(_("Wrong InternetSearch URL! More than 1 \'%%\' in the string!\n"));
return;
}
} else {
g_print(_("Wrong InternetSearch URL! No \'%%s\' in the string!\n"));
return;
}
glib::CharStr esc_text(g_uri_escape_string(text, NULL, FALSE));
glib::CharStr url(g_strdup_printf(str, get_impl(esc_text)));
show_url(get_impl(url));
} else {
show_url(weblist[1].c_str());
}
}