Commit b506439e authored by Maxime Doyen's avatar Maxime Doyen

5.1-rc

parent ef661aa5
......@@ -5,14 +5,16 @@
Made 5.1 rc release.
* change: xhb data file format (v1.2)
* change: win32: upgraded to gtk+ 3.20.x
* change: win32: upgraded to gtk+ 3.20.6
* change: internal storage of txn into accounts
* change: ??transaction dialog, changed the layout
* change: ??template/scheduled dialog, changed the layout
* change: register, refactored toolbar grouping single and multiple actions
* change: listview, removed deprecated rule hint (alternate row color)
* change: listview, added line grid (new GTK+ option)
* change: preferences, reworked layout
* change: preferences, reworked layout
* wish : #1610672 multiple edit should allow clearing fields
* wish : #1608025 revert prefill with shift/ctrl clicked txn when multiple edit
* wish : #1608025 revert prefill with shift/ctrl clicked txn when multiple edit
* wish : #1500235 automatic assignments based on regular expressions
* wish : #1500220 allow auto assignments to overwrite payee
......
......@@ -217,10 +217,16 @@ GList *selection, *list;
if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data->CM_info)) )
{
if(txn->info)
{
g_free(txn->info);
txn->info = NULL;
change = TRUE;
}
txt = gtk_entry_get_text(GTK_ENTRY(data->ST_info));
if (txt && *txt)
{
g_free(txn->info);
txn->info = g_strdup(txt);
change = TRUE;
}
......@@ -256,10 +262,16 @@ GList *selection, *list;
if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data->CM_memo)) )
{
if(txn->wording)
{
g_free(txn->wording);
txn->wording = NULL;
change = TRUE;
}
txt = gtk_entry_get_text(GTK_ENTRY(data->ST_memo));
if (txt && *txt)
{
g_free(txn->wording);
txn->wording = g_strdup(txt);
change = TRUE;
}
......
......@@ -451,7 +451,7 @@ gchar *version;
//gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(dialog), );
gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://homebank.free.fr");
//gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "Visit the HomeBank website");
gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "Visit the HomeBank website");
gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "homebank");
......@@ -895,7 +895,7 @@ GtkWidget *mainvbox, *widget, *label;
gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome1), dialog);
widget = gtk_button_new_with_mnemonic(_("Configure _Preferences"));
widget = gtk_button_new_with_mnemonic(_("Configure _preferences"));
gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome2), dialog);
......
......@@ -170,7 +170,7 @@ GtkWidget *scrollwin, *treeview;
//gtk_widget_set_double_buffered (GTK_WIDGET(widget), FALSE);
gtk_container_add( GTK_CONTAINER(scrollwin), chart->drawarea );
gtk_widget_set_size_request(chart->drawarea, 150, 150 );
gtk_widget_set_size_request(chart->drawarea, 100, 100 );
gtk_widget_set_has_tooltip(chart->drawarea, TRUE);
gtk_widget_show(chart->drawarea);
......@@ -1470,7 +1470,8 @@ cairo_t *cr;
#if CHART_PIE_DONUT == 1
a1 = 0;
a2 = 2 * M_PI;
radius = (gint)((chart->rayon/3) * (1 / PHI));
//radius = (gint)((chart->rayon/3) * (1 / PHI));
radius = (gint)((chart->rayon/2) * 2 / 3);
cairo_arc(cr, cx, cy, radius, a1, a2);
cairo_user_set_rgbcol(cr, &global_colors[THBASE]);
......
......@@ -242,21 +242,28 @@ da_cur_get(guint32 key)
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
/**
* da_cur_is_used:
* currency_is_used:
*
* controls if a currency is used [base or account]
*
* Return value: TRUE if used, FALSE, otherwise
*/
gboolean
da_cur_is_used(guint32 key)
currency_is_used(guint32 key)
{
GList *list;
gboolean retval;
if(GLOBALS->kcur == key)
return TRUE;
retval = FALSE;
list = g_hash_table_get_values(GLOBALS->h_acc);
while (list != NULL)
{
......@@ -264,18 +271,19 @@ GList *list;
if(item->kcur == key)
{
return TRUE;
retval = TRUE;
goto end;
}
list = g_list_next(list);
}
end:
g_list_free(list);
return FALSE;
return retval;
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
Currency4217 *iso4217format_get(gchar *code)
{
......
......@@ -85,9 +85,8 @@ guint32 da_cur_get_max_key(void);
Currency *da_cur_get_by_iso_code(gchar *iso_code);
Currency *da_cur_get(guint32 key);
gboolean da_cur_is_used(guint32 key);
gboolean currency_is_used(guint32 key);
Currency *currency_add_from_user(Currency4217 *curfmt);
gboolean currency_sync_online(GError **error);
......
......@@ -66,7 +66,7 @@ static GtkActionEntry entries[] = {
{ "Column" , ICONNAME_HB_VIEW_COLUMN , N_("Column") , NULL, N_("View results as column"), G_CALLBACK (ui_repdist_action_viewbar) },
{ "Donut" , ICONNAME_HB_VIEW_DONUT , N_("Donut") , NULL, N_("View results as donut"), G_CALLBACK (ui_repdist_action_viewpie) },
{ "Filter" , ICONNAME_HB_FILTER , N_("Filter") , NULL, N_("Edit the filter"), G_CALLBACK (ui_repdist_action_filter) },
{ "Filter" , ICONNAME_HB_FILTER , N_("Filter") , NULL, N_("Edit filter"), G_CALLBACK (ui_repdist_action_filter) },
{ "Refresh" , ICONNAME_REFRESH , N_("Refresh"), NULL, N_("Refresh results"), G_CALLBACK (ui_repdist_action_refresh) },
{ "Export" , ICONNAME_HB_FILE_EXPORT , N_("Export") , NULL, N_("Export as CSV"), G_CALLBACK (ui_repdist_action_export) },
......
......@@ -41,6 +41,7 @@
/* our global datas */
extern struct HomeBank *GLOBALS;
extern struct Preferences *PREFS;
gchar *CYA_ARCHIVE_TYPE[] = {
......@@ -142,12 +143,38 @@ Archive *arc = user_data;
*/
static gint ui_arc_listview_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
{
gint sortcol = GPOINTER_TO_INT(userdata);
Archive *entry1, *entry2;
gint retval = 0;
gtk_tree_model_get(model, a, LST_DEFARC_DATAS, &entry1, -1);
gtk_tree_model_get(model, b, LST_DEFARC_DATAS, &entry2, -1);
return hb_string_utf8_compare(entry1->wording, entry2->wording);
switch (sortcol)
{
case LST_DEFARC_SORT_MEMO:
retval = (entry1->flags & GF_INCOME) - (entry2->flags & GF_INCOME);
if(!retval)
{
retval = hb_string_utf8_compare(entry1->wording, entry2->wording);
}
break;
case LST_DEFARC_SORT_PAYEE:
{
Payee *p1, *p2;
p1 = da_pay_get(entry1->kpay);
p2 = da_pay_get(entry2->kpay);
if( p1 != NULL && p2 != NULL )
{
retval = hb_string_utf8_compare(p1->name, p2->name);
}
}
break;
default:
g_return_val_if_reached(0);
}
return retval;
}
......@@ -171,7 +198,7 @@ gchar *iconname = NULL;
/*
** draw some text from the stored data structure
*/
static void ui_arc_listview_text_cell_data_function (GtkTreeViewColumn *col,
static void ui_arc_listview_cell_data_function_memo (GtkTreeViewColumn *col,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
......@@ -189,6 +216,28 @@ gchar *name;
static void ui_arc_listview_cell_data_function_payee (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
{
Archive *arc;
Payee *pay;
gtk_tree_model_get(model, iter,
LST_DEFARC_DATAS, &arc,
-1);
if(arc)
{
pay = da_pay_get(arc->kpay);
if(pay != NULL)
g_object_set(renderer, "text", pay->name, NULL);
}
else
g_object_set(renderer, "text", NULL, NULL);
}
/*
**
*/
......@@ -207,15 +256,13 @@ GtkTreeViewColumn *column;
G_TYPE_BOOLEAN
);
//sortable
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_DATAS, ui_arc_listview_compare_func, GINT_TO_POINTER(LST_DEFARC_DATAS), NULL);
//treeview
view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
g_object_unref(store);
/* text column */
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
/* column: Memo */
renderer = gtk_cell_renderer_text_new ();
g_object_set(renderer,
"ellipsize", PANGO_ELLIPSIZE_END,
......@@ -225,13 +272,32 @@ GtkTreeViewColumn *column;
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Memo"));
gtk_tree_view_column_pack_start(column, renderer, TRUE);
gtk_tree_view_column_set_cell_data_func(column, renderer, ui_arc_listview_text_cell_data_function, GINT_TO_POINTER(1), NULL);
gtk_tree_view_column_set_cell_data_func(column, renderer, ui_arc_listview_cell_data_function_memo, GINT_TO_POINTER(LST_DEFARC_SORT_MEMO), NULL);
gtk_tree_view_column_set_sort_column_id (column, LST_DEFARC_SORT_MEMO);
gtk_tree_view_column_set_alignment (column, 0.5);
gtk_tree_view_column_set_min_width(column, HB_MINWIDTH_LIST);
gtk_tree_view_column_set_resizable(column, TRUE);
gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
/* icon column */
/* column: Payee */
renderer = gtk_cell_renderer_text_new ();
g_object_set(renderer,
"ellipsize", PANGO_ELLIPSIZE_END,
"ellipsize-set", TRUE,
NULL);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Payee"));
gtk_tree_view_column_pack_start(column, renderer, TRUE);
gtk_tree_view_column_set_cell_data_func(column, renderer, ui_arc_listview_cell_data_function_payee, GINT_TO_POINTER(LST_DEFARC_SORT_PAYEE), NULL);
gtk_tree_view_column_set_resizable(column, TRUE);
//gtk_tree_view_column_add_attribute(column, renderer, "text", 1);
gtk_tree_view_column_set_sort_column_id (column, LST_DEFARC_SORT_PAYEE);
gtk_tree_view_column_set_alignment (column, 0.5);
gtk_tree_view_column_set_min_width(column, HB_MINWIDTH_LIST);
gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
/* column: Scheduled icon */
column = gtk_tree_view_column_new();
renderer = gtk_cell_renderer_pixbuf_new ();
//gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
......@@ -239,7 +305,14 @@ GtkTreeViewColumn *column;
gtk_tree_view_column_set_cell_data_func(column, renderer, ui_arc_listview_auto_cell_data_function, NULL, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
//sortable
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_MEMO, ui_arc_listview_compare_func, GINT_TO_POINTER(LST_DEFARC_SORT_MEMO), NULL);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_PAYEE, ui_arc_listview_compare_func, GINT_TO_POINTER(LST_DEFARC_SORT_PAYEE), NULL);
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_MEMO, GTK_SORT_ASCENDING);
//gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
//gtk_tree_view_set_reorderable (GTK_TREE_VIEW(view), TRUE);
......@@ -762,7 +835,7 @@ Archive *arcitem;
data->lastarcitem = NULL;
}
gtk_widget_set_sensitive(data->LB_schedinsert, sensitive);
//gtk_widget_set_sensitive(data->LB_schedinsert, sensitive);
DB( g_print(" - call scheduled\n") );
......
......@@ -28,6 +28,8 @@ enum
ARC_TYPE_TEMPLATE
};
#define LST_DEFARC_SORT_MEMO 1
#define LST_DEFARC_SORT_PAYEE 2
enum {
HID_ARC_MEMO,
......
......@@ -32,6 +32,7 @@
/* our global datas */
extern struct HomeBank *GLOBALS;
extern struct Preferences *PREFS;
gchar *CYA_CAT_TYPE[] = {
......@@ -555,7 +556,6 @@ gint retval = 0;
gtk_tree_model_get(model, a, LST_DEFCAT_DATAS, &entry1, -1);
gtk_tree_model_get(model, b, LST_DEFCAT_DATAS, &entry2, -1);
switch (sortcol)
{
case LST_DEFCAT_SORT_NAME:
......@@ -1008,6 +1008,9 @@ GtkTreeViewColumn *column;
treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
g_object_unref(store);
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
// column 1: toggle
if( withtoggle == TRUE )
{
......
......@@ -336,16 +336,10 @@ gchar *name1, *name2;
gtk_tree_model_get(model, a, LST_DEFCUR_DATAS, &entry1, -1);
gtk_tree_model_get(model, b, LST_DEFCUR_DATAS, &entry2, -1);
name1 = entry1->name;
name2 = entry2->name;
if (name1 == NULL || name2 == NULL)
{
result = (name1 == NULL) ? -1 : 1;
}
else
{
result = g_utf8_collate(name1,name2);
}
name1 = (entry1->key == GLOBALS->kcur) ? NULL : entry1->iso_code;
name2 = (entry2->key == GLOBALS->kcur) ? NULL : entry2->iso_code;
result = hb_string_compare(name1,name2);
return result;
}
......@@ -367,14 +361,14 @@ gint weight;
#if MYDEBUG
if( entry->key == GLOBALS->kcur )
string = g_strdup_printf ("[%d] %s - %s<span size=\"x-small\">\n(%s)</span>", entry->key, entry->iso_code, entry->name, _("Base currency"));
string = g_strdup_printf ("[%d] %s - %s<span size=\"small\">\n(%s)</span>", entry->key, entry->iso_code, entry->name, _("Base currency"));
else
string = g_strdup_printf ("[%d] %s - %s", entry->key, entry->iso_code, entry->name);
g_object_set(renderer, "weight", weight, "markup", string, NULL);
g_free(string);
#else
if( entry->key == GLOBALS->kcur )
string = g_strdup_printf ("%s - %s<span size=\"x-small\">\n(%s)</span>", entry->iso_code, entry->name, _("Base currency"));
string = g_strdup_printf ("%s - %s<span size=\"small\">\n(%s)</span>", entry->iso_code, entry->name, _("Base currency"));
else
string = g_strdup_printf ("%s - %s", entry->iso_code, entry->name);
g_object_set(renderer, "weight", weight, "markup", string, NULL);
......@@ -493,7 +487,7 @@ GtkTreeIter iter;
gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
if( item!= NULL )
if( item != NULL )
return item->key;
}
return 0;
......@@ -611,6 +605,8 @@ GtkTreeViewColumn *column;
}
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
// column 1: name
renderer = gtk_cell_renderer_text_new ();
......@@ -624,7 +620,7 @@ GtkTreeViewColumn *column;
// column 2: code
renderer = gtk_cell_renderer_text_new ();
//g_object_set(renderer, "xalign", 1.0, NULL);
g_object_set(renderer, "xalign", 0.5, NULL);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Symbol"));
gtk_tree_view_column_set_alignment (column, 0.5);
......@@ -636,7 +632,7 @@ GtkTreeViewColumn *column;
// column 3: base rate
renderer = gtk_cell_renderer_text_new ();
//g_object_set (renderer, "editable", TRUE, NULL);
//g_object_set(renderer, "xalign", 1.0, NULL);
g_object_set(renderer, "xalign", 1.0, NULL);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Exchange rate"));
gtk_tree_view_column_set_alignment (column, 0.5);
......@@ -649,6 +645,7 @@ GtkTreeViewColumn *column;
// column 4: last modified
renderer = gtk_cell_renderer_text_new ();
g_object_set(renderer, "xalign", 0.5, NULL);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Last modfied"));
gtk_tree_view_column_set_alignment (column, 0.5);
......@@ -921,6 +918,14 @@ enum {
};
static void ui_cur_select_rowactivated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata)
{
struct ui_cur_select_dialog_data *data = userdata;
gtk_dialog_response(GTK_DIALOG(data->window), GTK_RESPONSE_ACCEPT);
}
static GtkTreeModel *ui_cur_select_model_create (void)
{
guint i = 0;
......@@ -1120,6 +1125,7 @@ Currency4217 *curfmt = NULL;
// signals
g_signal_connect (data.ST_search, "search-changed", G_CALLBACK (ui_cur_select_search_changed_cb), &data);
g_signal_connect (GTK_TREE_VIEW(data.LV_cur), "row-activated", G_CALLBACK (ui_cur_select_rowactivated), &data);
// wait for the user
......@@ -1224,6 +1230,8 @@ Currency4217 *curfmt;
{
item = currency_add_from_user(curfmt);
ui_cur_listview_add(GTK_TREE_VIEW(data->LV_cur), item);
gtk_tree_sortable_sort_column_changed(GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_cur))));
ui_cur_manage_dialog_update (widget, user_data);
GLOBALS->changes_count++;
}
......@@ -1287,7 +1295,7 @@ gboolean do_remove, result;
gchar *title;
gchar *secondtext;
if( da_cur_is_used(key) == TRUE )
if( currency_is_used(key) == TRUE )
{
do_remove = FALSE;
}
......@@ -1350,6 +1358,7 @@ gboolean do_change;
if(do_change == GTK_RESPONSE_YES)
{
hbfile_change_basecurrency(key);
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(data->LV_cur));
}
}
......@@ -1385,7 +1394,7 @@ gboolean sensitive;
gtk_widget_set_sensitive(data->BT_edit, TRUE);
sensitive = !(da_cur_is_used(item->key));
sensitive = !(currency_is_used(item->key));
//gtk_widget_set_sensitive(data->BT_mov, sensitive);
//gtk_widget_set_sensitive(data->BT_mod, sensitive);
gtk_widget_set_sensitive(data->BT_rem, sensitive);
......@@ -1468,8 +1477,8 @@ gint crow, row, w, h;
data.window = dialog;
data.change = 0;
//homebank_window_set_icon_from_file(GTK_WINDOW (dialog), "curee.svg");
//gtk_window_set_icon_name(GTK_WINDOW (dialog), HB_STOCK_CURRENCY);
//set the dialog icon
gtk_window_set_icon_name(GTK_WINDOW (dialog), ICONNAME_HB_CURRENCY);
//set a nice dialog size
gtk_window_get_size(GTK_WINDOW(GLOBALS->mainwindow), &w, &h);
......@@ -1515,6 +1524,7 @@ gint crow, row, w, h;
scrollwin = gtk_scrolled_window_new(NULL,NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scrollwin), HB_MINHEIGHT_LIST);
treeview = ui_cur_listview_new(FALSE);
data.LV_cur = treeview;
gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
......
......@@ -1262,7 +1262,7 @@ GtkWidget *parentwindow, *window, *content, *mainbox, *notebook, *label, *page;
parentwindow = gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW);
window = gtk_dialog_new_with_buttons (_("Edit Filter"),
window = gtk_dialog_new_with_buttons (_("Edit filter"),
GTK_WINDOW (parentwindow),
0,
_("_Reset"),
......
......@@ -33,6 +33,7 @@
/* our global datas */
extern struct HomeBank *GLOBALS;
extern struct Preferences *PREFS;
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
......@@ -647,6 +648,8 @@ GtkTreeViewColumn *column;
treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
g_object_unref(store);
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
// column: toggle
if( withtoggle == TRUE )
{
......
......@@ -865,9 +865,8 @@ GtkWidget *box, *widget, *scrollwin, *treeview;
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_SMALL);
widget = gtk_search_entry_new();
widget = make_search(NULL);
data->ST_search = widget;
gtk_entry_set_placeholder_text(GTK_ENTRY(widget), _("Search...") );
gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0);
......
......@@ -267,19 +267,15 @@ GtkWidget *entry;
GtkWidget *make_search(GtkWidget *label)
{
GtkWidget *entry;
entry = gtk_entry_new ();
gtk_entry_set_placeholder_text(GTK_ENTRY(entry), _("Search...") );
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, ICONNAME_FIND);
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, ICONNAME_CLEAR);
GtkWidget *search;
gtk_entry_set_icon_sensitive (GTK_ENTRY(entry), GTK_ENTRY_ICON_SECONDARY, FALSE);
search = gtk_search_entry_new();
gtk_entry_set_placeholder_text(GTK_ENTRY(search), _("Search...") );
if(label)
gtk_label_set_mnemonic_widget (GTK_LABEL(label), entry);
gtk_label_set_mnemonic_widget (GTK_LABEL(label), search);
return entry;
return search;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment