2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 2000 The LyX Team.
9 * ======================================================
17 #pragma implementation
23 #include "FormCitation.h"
27 #include "support/filetools.h"
28 #include "support/LRegex.h"
31 #include "diainsertcitation_interface.h"
35 #include <gtk--/scrolledwindow.h>
36 #include <gnome--/pixmap.h>
44 #ifdef SIGC_CXX_NAMESPACES
49 // gnome configuration file keys
50 #define LOCAL_CONFIGURE_PREFIX "FormCitation"
52 #define CONF_DIALOG_WIDTH "width"
53 #define CONF_DIALOG_WIDTH_DEFAULT "=550"
55 #define CONF_DIALOG_HEIGTH "heigth"
56 #define CONF_DIALOG_HEIGTH_DEFAULT "=550"
58 #define CONF_PANE_INFO "paneinfo"
59 #define CONF_PANE_INFO_DEFAULT "=300"
61 #define CONF_PANE_KEY "panekey"
62 #define CONF_PANE_KEY_DEFAULT "=225"
64 #define CONF_COLUMN "column"
65 #define CONF_COLUMN_DEFAULT "=50"
67 #define CONF_REGEXP "regexp"
68 #define CONF_REGEXP_DEFAULT "=0"
71 FormCitation::FormCitation(LyXView * lv, Dialogs * d)
72 : lv_(lv), d_(d), u_(0), h_(0), ih_(0), inset_(0), dialog_(NULL)
74 // let the dialog be shown
75 // These are permanent connections so we won't bother
76 // storing a copy because we won't be disconnecting.
77 d->showCitation.connect(slot(this, &FormCitation::showInset));
78 d->createCitation.connect(slot(this, &FormCitation::createInset));
82 FormCitation::~FormCitation()
87 void FormCitation::showInset( InsetCommand * const inset )
89 if( dialog_!=NULL || inset == 0 ) return;
92 ih_ = inset_->hide.connect(slot(this, &FormCitation::hide));
94 params = inset->params();
99 void FormCitation::createInset( string const & arg )
101 if( dialog_!=NULL ) return;
103 params.setFromString( arg );
108 void parseBibTeX(string data,
109 string const & findkey,
116 for (i=0; i<data.length(); ++i)
117 if (data[i]=='\n' || data[i]=='\t')
120 data = frontStrip(data);
123 && (data.find(' ')!=string::npos ||
124 data.find('=')!=string::npos) )
126 unsigned int keypos = min(data.find(' '), data.find('='));
127 string key = lowercase( data.substr(0, keypos) );
131 data = data.substr(keypos, data.length()-1);
132 data = frontStrip(strip(data));
133 if (data.length() > 1 && data[0]=='=')
135 data = frontStrip(data.substr(1, data.length()-1));
139 if (data[0]=='{') enclosing = '}';
140 else if (data[0]=='"') enclosing = '"';
141 else { keypos=0; enclosing=' '; }
144 data.find(enclosing)!=string::npos &&
147 tmp = data.substr(keypos, data.length()-1);
148 while (tmp.find('{')!=string::npos &&
149 tmp.find('}')!=string::npos &&
150 tmp.find('{') < tmp.find('}') &&
151 tmp.find('{') < tmp.find(enclosing))
153 keypos += tmp.find('{')+1;
154 tmp = data.substr(keypos, data.length()-1);
155 keypos += tmp.find('}')+1;
156 tmp = data.substr(keypos, data.length()-1);
159 if (tmp.find(enclosing)==string::npos) return;
162 keypos += tmp.find(enclosing);
163 tmp = data.substr(keypos, data.length()-1);
166 value = data.substr(1, keypos-1);
168 if (keypos+1<data.length()-1) data = frontStrip(data.substr(keypos+1, data.length()-1));
174 ) // numerical value ?
176 keypos = data.length()-1;
177 if (data.find(' ')!=string::npos) keypos = data.find(' ');
178 if (data.find(',')!=string::npos &&
179 keypos > data.find(','))
180 keypos = data.find(',');
182 value = data.substr(0, keypos);
184 if (keypos+1<data.length()-1) data = frontStrip(data.substr(keypos+1, data.length()-1));
189 if (findkey == key) { keyvalue = value; return; }
191 data = frontStrip(frontStrip(data,','));
198 void FormCitation::show()
202 GtkWidget * pd = create_DiaInsertCitation();
204 dialog_ = Gtk::wrap(pd);
205 clist_selected_ = Gtk::wrap( GTK_CLIST( lookup_widget(pd, "clist_selected") ) );
206 info_ = Gtk::wrap( GNOME_LESS( lookup_widget(pd, "info") ) );
207 text_after_ = Gtk::wrap( GNOME_ENTRY( lookup_widget(pd, "text_after") ) );
208 search_text_ = Gtk::wrap( GNOME_ENTRY( lookup_widget(pd, "search_text") ) );
210 button_select_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_select") ) );
211 button_unselect_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_unselect") ) );
212 button_up_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_up") ) );
213 button_down_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_down") ) );
214 button_search_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_search") ) );
216 button_regexp_ = Gtk::wrap( GTK_CHECK_BUTTON( lookup_widget(pd, "button_regexp") ) );
218 paned_info_ = Gtk::wrap( GTK_PANED( lookup_widget(pd, "vpaned_info") ) );
219 paned_key_ = Gtk::wrap( GTK_PANED( lookup_widget(pd, "hpaned_key") ) );
220 box_keys_ = Gtk::wrap( GTK_BOX( lookup_widget(pd, "vbox_keys") ) );
222 b_ok = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_ok") ) );
223 b_cancel = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_cancel") ) );
225 // constructing and packing CList
226 vector<string> colnames;
227 colnames.push_back("INVISIBLE");
228 colnames.push_back(N_("Key"));
229 colnames.push_back(N_("Author(s)"));
230 colnames.push_back(N_("Title"));
231 colnames.push_back(N_("Year"));
232 colnames.push_back(N_("Journal"));
233 clist_bib_ = manage( new Gtk::CList(colnames) );
234 clist_bib_->column(0).set_visiblity(false);
236 Gtk::ScrolledWindow * sw_ = Gtk::wrap( GTK_SCROLLED_WINDOW( lookup_widget(pd, "scrolledwindow_bib") ) );
237 sw_->add(*clist_bib_);
239 // populating buttons with icons
241 p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_BACK) ) );
242 button_select_->add(*p);
243 p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_TRASH) ) );
244 button_unselect_->add(*p);
245 p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_UP) ) );
247 p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_DOWN) ) );
248 button_down_->add(*p);
251 // connecting signals
252 clist_bib_->click_column.connect(slot(this, &FormCitation::sortBibList));
254 clist_selected_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
256 clist_bib_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
258 clist_selected_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
260 clist_bib_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
263 button_select_->clicked.connect(slot(this, &FormCitation::newCitation));
264 button_unselect_->clicked.connect(slot(this, &FormCitation::removeCitation));
265 button_up_->clicked.connect(slot(this, &FormCitation::moveCitationUp));
266 button_down_->clicked.connect(slot(this, &FormCitation::moveCitationDown));
268 search_text_->get_entry()->activate.connect(slot(this, &FormCitation::search));
269 button_search_->clicked.connect(slot(this, &FormCitation::search));
271 b_ok->clicked.connect(slot(this, &FormCitation::apply));
272 b_ok->clicked.connect(dialog_->destroy.slot());
273 b_cancel->clicked.connect(dialog_->destroy.slot());
274 dialog_->destroy.connect(slot(this, &FormCitation::free));
276 u_ = d_->updateBufferDependent.connect(slot(this, &FormCitation::update));
277 h_ = d_->hideBufferDependent.connect(slot(this, &FormCitation::hide));
279 // setting sizes of the widgets
282 path += PACKAGE "/" LOCAL_CONFIGURE_PREFIX;
283 w = path + "/" + CONF_DIALOG_WIDTH + CONF_DIALOG_WIDTH_DEFAULT;
284 h = path + "/" + CONF_DIALOG_HEIGTH + CONF_DIALOG_HEIGTH_DEFAULT;
285 dialog_->set_usize(gnome_config_get_int(w.c_str()),
286 gnome_config_get_int(h.c_str()));
288 w = path + "/" + CONF_PANE_INFO + CONF_PANE_INFO_DEFAULT;
289 paned_info_->set_position( gnome_config_get_int(w.c_str()) );
291 w = path + "/" + CONF_PANE_KEY + CONF_PANE_KEY_DEFAULT;
292 paned_key_->set_position( gnome_config_get_int(w.c_str()) );
295 for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
297 w = path + "/" + CONF_COLUMN + "_" + tostr(i) + CONF_COLUMN_DEFAULT;
298 clist_bib_->column(i).set_width( gnome_config_get_int(w.c_str()) );
301 // restoring regexp setting
302 w = path + "/" + CONF_REGEXP + CONF_REGEXP_DEFAULT;
303 button_regexp_->set_active( (gnome_config_get_int(w.c_str()) > 0) );
306 if (!dialog_->is_visible()) dialog_->show_all();
308 update(); // make sure its up-to-date
312 Gdk_Window dialog_win(dialog_->get_window());
317 void FormCitation::addItemToBibList(int i)
324 info = bibkeysInfo[i];
326 // don't change the order of these first two items:
327 // callback functions depend on the data stored in the first column (its hided)
328 // and in the second column (shown to user)
329 r.push_back( tostr(i) );
332 // this can be changed (configured by user?)
333 parseBibTeX( info, "author", val); r.push_back(val);
334 parseBibTeX( info, "title", val); r.push_back(val);
335 parseBibTeX( info, "year", val); r.push_back(val);
336 parseBibTeX( info, "journal", val); r.push_back(val);
338 clist_bib_->rows().push_back(r);
341 void FormCitation::update()
346 clist_selected_->rows().clear();
347 clist_bib_->rows().clear();
349 // populating clist_bib_
350 clist_bib_->freeze();
352 vector<pair<string,string> > blist =
353 lv_->buffer()->getBibkeyList();
356 for ( i = 0, sz = blist.size(); i < sz; ++i )
358 bibkeys.push_back(blist[i].first);
359 bibkeysInfo.push_back(blist[i].second);
364 for ( i = 0, sz = bibkeys.size(); i < sz; ++i )
371 // populating clist_selected_
373 string tmp, keys( params.getContents() );
374 keys = frontStrip( split(keys, tmp, ',') );
375 while( !tmp.empty() )
379 clist_selected_->rows().push_back(r);
381 keys = frontStrip( split(keys, tmp, ',') );
383 // clist_selected_: done
385 text_after_->get_entry()->set_text(params.getOptions());
390 void FormCitation::updateButtons()
394 sens = (clist_selected_->selection().size()>0);
395 button_unselect_->set_sensitive(sens);
396 button_up_->set_sensitive(sens &&
397 clist_selected_->selection().operator[](0).get_row_num()>0);
398 button_down_->set_sensitive(sens &&
399 clist_selected_->selection().operator[](0).get_row_num() <
400 clist_selected_->rows().size()-1);
402 sens = (clist_bib_->selection().size()>0);
403 button_select_->set_sensitive( (clist_bib_->selection().size()>0) );
406 void FormCitation::selection_toggled(gint row,
414 bool keyfound = false;
418 // lookup the record with the same key in bibkeys and show additional Info
420 int sz = bibkeys.size();
421 string key = clist_selected_->cell(row,0).get_text();
422 for (i=0; !keyfound && i<sz; ++i)
423 if (bibkeys[i] == key)
425 info = bibkeysInfo[i];
431 // the first column in clist_bib_ contains the index
433 info = bibkeysInfo[ strToInt(clist_bib_->cell(row,0).get_text()) ];
437 info_->show_string(info);
439 info_->show_string(N_("--- No such key in the database ---"));
443 info_->show_string("");
448 void FormCitation::removeCitation()
450 clist_selected_->rows().remove(clist_selected_->selection().operator[](0));
454 void FormCitation::moveCitationUp()
456 int i = clist_selected_->selection().operator[](0).get_row_num();
457 clist_selected_->swap_rows( i-1, i );
458 clist_selected_->row(i-1).select();
462 void FormCitation::moveCitationDown()
464 int i = clist_selected_->selection().operator[](0).get_row_num();
465 clist_selected_->swap_rows( i+1, i );
466 clist_selected_->row(i+1).select();
470 void FormCitation::newCitation()
472 // citation key is in the first column of clist_bib_ list
474 r.push_back( clist_bib_->selection().operator[](0).operator[](1).get_text() );
475 clist_selected_->rows().push_back(r);
476 clist_selected_->row( clist_selected_->rows().size()-1 ).select();
480 void FormCitation::hide()
482 if (dialog_!=NULL) dialog_->destroy();
485 void FormCitation::free()
489 // storing configuration
492 path = PACKAGE "/" LOCAL_CONFIGURE_PREFIX;
493 w = path + "/" + CONF_DIALOG_WIDTH;
494 h = path + "/" + CONF_DIALOG_HEIGTH;
496 gnome_config_set_int(w.c_str(), dialog_->width());
497 gnome_config_set_int(h.c_str(), dialog_->height());
499 w = path + "/" + CONF_PANE_INFO;
500 gnome_config_set_int(w.c_str(), paned_key_->height());
502 w = path + "/" + CONF_PANE_KEY;
503 gnome_config_set_int(w.c_str(), box_keys_->width());
506 for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
508 w = path + "/" + CONF_COLUMN + "_" + tostr(i);
509 gnome_config_set_int(w.c_str(), clist_bib_->get_column_width(i));
512 w = path + "/" + CONF_REGEXP;
513 gnome_config_set_int(w.c_str(), button_regexp_->get_active());
526 void FormCitation::apply()
528 if( lv_->buffer()->isReadonly() ) return;
531 for( unsigned int i = 0; i < clist_selected_->rows().size(); ++i )
533 if (i > 0) contents += ", ";
534 contents += clist_selected_->cell(i, 0).get_text();
537 params.setContents( contents );
538 params.setOptions( text_after_->get_entry()->get_text() );
542 // Only update if contents have changed
543 if( params != inset_->params() )
545 inset_->setParams( params );
546 lv_->view()->updateInset( inset_, true );
551 lv_->getLyXFunc()->Dispatch( LFUN_CITATION_INSERT,
552 params.getAsString().c_str() );
556 void FormCitation::sortBibList(gint col)
558 clist_bib_->set_sort_column(col);
562 void FormCitation::search()
564 if (button_regexp_->get_active()) searchReg();
568 // looking for entries which match regexp
569 void FormCitation::searchReg()
571 string tmp, rexptxt( search_text_->get_entry()->get_text() );
572 rexptxt = frontStrip( strip( rexptxt ) );
576 // populating clist_bib_
577 clist_bib_->rows().clear();
579 clist_bib_->freeze();
583 for ( i = 0, sz = bibkeys.size(); i < sz; ++i )
585 string data = bibkeys[i] + bibkeysInfo[i];
587 if (rexptxt.empty()) additem = true;
588 else additem = (reg.exec(data).size() > 0);
590 if ( additem ) addItemToBibList(i);
599 // looking for entries which contain all the words specified in search_text entry
600 void FormCitation::searchSimple()
602 vector<string> searchwords;
603 string tmp, stext( search_text_->get_entry()->get_text() );
604 stext = frontStrip( strip( stext ) );
605 stext = frontStrip( split(stext, tmp, ' ') );
606 while( !tmp.empty() )
608 searchwords.push_back(tmp);
609 stext = frontStrip( split(stext, tmp, ' ') );
612 // populating clist_bib_
613 clist_bib_->rows().clear();
615 clist_bib_->freeze();
619 for ( i = 0, sz = bibkeys.size(); i < sz; ++i )
621 string data = bibkeys[i] + bibkeysInfo[i];
626 for (j = 0, szs = searchwords.size();
627 additem && j < szs; ++j )
628 if ( data.find(searchwords[j]) == string::npos )
631 if ( additem ) addItemToBibList(i);