summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am92
-rw-r--r--src/Makefile.in1710
-rw-r--r--src/comment.cpp93
-rw-r--r--src/comment.h49
-rw-r--r--src/commentwidget.cpp98
-rw-r--r--src/commentwidget.h55
-rw-r--r--src/documentlistview.cpp768
-rw-r--r--src/documentlistview.h127
-rw-r--r--src/documentlistviewitem.cpp151
-rw-r--r--src/documentlistviewitem.h55
-rw-r--r--src/documentsourceview.cpp380
-rw-r--r--src/documentsourceview.h96
-rw-r--r--src/documentwidget.cpp1740
-rw-r--r--src/documentwidget.h174
-rw-r--r--src/element.cpp50
-rw-r--r--src/element.h49
-rw-r--r--src/encoder.cpp25
-rw-r--r--src/encoder.h54
-rw-r--r--src/encoderlatex.cpp876
-rw-r--r--src/encoderlatex.h78
-rw-r--r--src/encoderxml.cpp127
-rw-r--r--src/encoderxml.h64
-rw-r--r--src/entry.cpp714
-rw-r--r--src/entry.h92
-rw-r--r--src/entryfield.cpp227
-rw-r--r--src/entryfield.h57
-rw-r--r--src/entrywidget.cpp677
-rw-r--r--src/entrywidget.h158
-rw-r--r--src/entrywidgetauthor.cpp114
-rw-r--r--src/entrywidgetauthor.h60
-rw-r--r--src/entrywidgetexternal.cpp297
-rw-r--r--src/entrywidgetexternal.h76
-rw-r--r--src/entrywidgetkeyword.cpp283
-rw-r--r--src/entrywidgetkeyword.h93
-rw-r--r--src/entrywidgetmisc.cpp172
-rw-r--r--src/entrywidgetmisc.h57
-rw-r--r--src/entrywidgetother.cpp319
-rw-r--r--src/entrywidgetother.h96
-rw-r--r--src/entrywidgetpublication.cpp563
-rw-r--r--src/entrywidgetpublication.h80
-rw-r--r--src/entrywidgetsource.cpp161
-rw-r--r--src/entrywidgetsource.h61
-rw-r--r--src/entrywidgettab.cpp91
-rw-r--r--src/entrywidgettab.h62
-rw-r--r--src/entrywidgettitle.cpp136
-rw-r--r--src/entrywidgettitle.h55
-rw-r--r--src/entrywidgetuserdefined.cpp144
-rw-r--r--src/entrywidgetuserdefined.h54
-rw-r--r--src/entrywidgetwarningsitem.cpp62
-rw-r--r--src/entrywidgetwarningsitem.h46
-rw-r--r--src/fieldlineedit.cpp369
-rw-r--r--src/fieldlineedit.h106
-rw-r--r--src/fieldlistview.cpp455
-rw-r--r--src/fieldlistview.h101
-rw-r--r--src/file.cpp402
-rw-r--r--src/file.h108
-rw-r--r--src/fileexporter.cpp36
-rw-r--r--src/fileexporter.h63
-rw-r--r--src/fileexporterbibtex.cpp491
-rw-r--r--src/fileexporterbibtex.h88
-rw-r--r--src/fileexporterbibutils.cpp259
-rw-r--r--src/fileexporterbibutils.h70
-rw-r--r--src/fileexporterdocbook5.cpp96
-rw-r--r--src/fileexporterdocbook5.h54
-rw-r--r--src/fileexporterexternal.cpp179
-rw-r--r--src/fileexporterexternal.h66
-rw-r--r--src/fileexporterpdf.cpp197
-rw-r--r--src/fileexporterpdf.h62
-rw-r--r--src/fileexporterps.cpp135
-rw-r--r--src/fileexporterps.h58
-rw-r--r--src/fileexporterris.cpp200
-rw-r--r--src/fileexporterris.h50
-rw-r--r--src/fileexporterrtf.cpp134
-rw-r--r--src/fileexporterrtf.h56
-rw-r--r--src/fileexportertoolchain.cpp232
-rw-r--r--src/fileexportertoolchain.h70
-rw-r--r--src/fileexporterxml.cpp228
-rw-r--r--src/fileexporterxml.h61
-rw-r--r--src/fileexporterxslt.cpp95
-rw-r--r--src/fileexporterxslt.h50
-rw-r--r--src/fileimporter.cpp57
-rw-r--r--src/fileimporter.h66
-rw-r--r--src/fileimporterbibtex.cpp658
-rw-r--r--src/fileimporterbibtex.h96
-rw-r--r--src/fileimporterbibutils.cpp296
-rw-r--r--src/fileimporterbibutils.h72
-rw-r--r--src/fileimporterexternal.cpp150
-rw-r--r--src/fileimporterexternal.h72
-rw-r--r--src/fileimporterris.cpp517
-rw-r--r--src/fileimporterris.h64
-rw-r--r--src/findduplicates.cpp444
-rw-r--r--src/findduplicates.h85
-rw-r--r--src/hi128-app-kbibtex.pngbin0 -> 21254 bytes
-rw-r--r--src/hi16-app-kbibtex.pngbin0 -> 836 bytes
-rw-r--r--src/hi22-app-kbibtex.pngbin0 -> 1363 bytes
-rw-r--r--src/hi32-app-kbibtex.pngbin0 -> 2468 bytes
-rw-r--r--src/hi48-app-kbibtex.pngbin0 -> 4715 bytes
-rw-r--r--src/hi64-app-kbibtex.pngbin0 -> 7301 bytes
-rw-r--r--src/idsuggestions.cpp363
-rw-r--r--src/idsuggestions.h75
-rw-r--r--src/idsuggestionswidget.cpp567
-rw-r--r--src/idsuggestionswidget.h163
-rw-r--r--src/iso5426converter.cpp892
-rw-r--r--src/iso5426converter.h52
-rw-r--r--src/iso6937converter.cpp606
-rw-r--r--src/iso6937converter.h50
-rw-r--r--src/kbibtex.desktop12
-rw-r--r--src/kbibtex.lsm15
-rw-r--r--src/kbibtex_part.cpp758
-rw-r--r--src/kbibtex_part.desktop15
-rw-r--r--src/kbibtex_part.h169
-rw-r--r--src/kbibtex_part.rc158
-rw-r--r--src/kbibtex_shell.rc31
-rw-r--r--src/kbibtexshell.cpp387
-rw-r--r--src/kbibtexshell.h100
-rw-r--r--src/latin1literal.h99
-rw-r--r--src/macro.cpp115
-rw-r--r--src/macro.h57
-rw-r--r--src/macrowidget.cpp99
-rw-r--r--src/macrowidget.h56
-rw-r--r--src/main.cpp128
-rw-r--r--src/mergeelements.cpp864
-rw-r--r--src/mergeelements.h179
-rw-r--r--src/messagehandler.cpp44
-rw-r--r--src/messagehandler.h56
-rw-r--r--src/preamble.cpp107
-rw-r--r--src/preamble.h54
-rw-r--r--src/preamblewidget.cpp84
-rw-r--r--src/preamblewidget.h59
-rw-r--r--src/searchbar.cpp192
-rw-r--r--src/searchbar.h78
-rw-r--r--src/settings.cpp966
-rw-r--r--src/settings.h205
-rw-r--r--src/settingsdlg.cpp137
-rw-r--r--src/settingsdlg.h70
-rw-r--r--src/settingsediting.cpp331
-rw-r--r--src/settingsediting.h100
-rw-r--r--src/settingsfileio.cpp341
-rw-r--r--src/settingsfileio.h73
-rw-r--r--src/settingsidsuggestions.cpp400
-rw-r--r--src/settingsidsuggestions.h108
-rw-r--r--src/settingskeyword.cpp194
-rw-r--r--src/settingskeyword.h69
-rw-r--r--src/settingssearchurl.cpp221
-rw-r--r--src/settingssearchurl.h68
-rw-r--r--src/settingsuserdefinedinput.cpp264
-rw-r--r--src/settingsuserdefinedinput.h74
-rw-r--r--src/settingsz3950.cpp364
-rw-r--r--src/settingsz3950.h128
-rw-r--r--src/sidebar.cpp255
-rw-r--r--src/sidebar.h89
-rw-r--r--src/value.cpp465
-rw-r--r--src/value.h162
-rw-r--r--src/valuewidget.cpp254
-rw-r--r--src/valuewidget.h77
-rw-r--r--src/webquery.cpp637
-rw-r--r--src/webquery.h179
-rw-r--r--src/webqueryamatex.cpp123
-rw-r--r--src/webqueryamatex.h64
-rw-r--r--src/webqueryarxiv.cpp568
-rw-r--r--src/webqueryarxiv.h87
-rw-r--r--src/webquerybibsonomy.cpp127
-rw-r--r--src/webquerybibsonomy.h64
-rw-r--r--src/webquerycitebase.cpp129
-rw-r--r--src/webquerycitebase.h64
-rw-r--r--src/webqueryciteseerx.cpp318
-rw-r--r--src/webqueryciteseerx.h141
-rw-r--r--src/webquerycsb.cpp289
-rw-r--r--src/webquerycsb.h89
-rw-r--r--src/webquerydblp.cpp213
-rw-r--r--src/webquerydblp.h70
-rw-r--r--src/webquerygooglescholar.cpp469
-rw-r--r--src/webquerygooglescholar.h111
-rw-r--r--src/webqueryieeexplore.cpp267
-rw-r--r--src/webqueryieeexplore.h83
-rw-r--r--src/webquerymathscinet.cpp188
-rw-r--r--src/webquerymathscinet.h67
-rw-r--r--src/webquerypubmed.cpp535
-rw-r--r--src/webquerypubmed.h106
-rw-r--r--src/webquerysciencedirect.cpp425
-rw-r--r--src/webquerysciencedirect.h90
-rw-r--r--src/webqueryspireshep.cpp248
-rw-r--r--src/webqueryspireshep.h76
-rw-r--r--src/webqueryz3950.cpp397
-rw-r--r--src/webqueryz3950.h122
-rw-r--r--src/webqueryzmath.cpp124
-rw-r--r--src/webqueryzmath.h64
-rw-r--r--src/xsltransform.cpp81
-rw-r--r--src/xsltransform.h46
-rw-r--r--src/z3950-servers.cfg263
-rw-r--r--src/z3950connection.cpp589
-rw-r--r--src/z3950connection.h131
192 files changed, 38809 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..68488d0
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,92 @@
+# set the include path for X, qt and KDE
+INCLUDES = $(all_includes) $(LIBXSLT_CFLAGS) $(LIBXML_CFLAGS) $(LIBYAZ_CFLAGS) $(LIBBIBUTILS_CFLAGS)
+
+# these are the headers for your project
+noinst_HEADERS = documentlistviewitem.h fileexportertoolchain.h \
+ comment.h commentwidget.h documentlistview.h documentlistviewitem.h \
+ documentsourceview.h documentwidget.h element.h encoder.h encoderlatex.h encoderxml.h \
+ entry.h entryfield.h entrywidget.h entrywidgetauthor.h entrywidgetexternal.h \
+ entrywidgetkeyword.h entrywidgetmisc.h entrywidgetother.h entrywidgetpublication.h \
+ entrywidgetsource.h entrywidgettab.h entrywidgettitle.h entrywidgetuserdefined.h \
+ entrywidgetwarningsitem.h fieldlineedit.h fieldlistview.h file.h fileexporter.h \
+ fileexporterbibtex.h fileexporterbibutils.h fileexporterdocbook5.h fileexporterexternal.h \
+ fileexporterpdf.h fileexporterps.h fileexporterris.h fileimporterbibtex.h \
+ fileexporterrtf.h fileexporterxml.h fileexporterxslt.h fileimporter.h \
+ fileimporterbibutils.h fileimporterexternal.h fileimporterris.h findduplicates.h \
+ idsuggestions.h idsuggestionswidget.h iso5426converter.h iso6937converter.h \
+ kbibtex_part.h kbibtexshell.h latin1literal.h macro.h macrowidget.h mergeelements.h \
+ messagehandler.h preamble.h preamblewidget.h searchbar.h settings.h settingsdlg.h \
+ settingsediting.h settingsfileio.h settingsidsuggestions.h settingskeyword.h \
+ settingssearchurl.h settingsuserdefinedinput.h settingsz3950.h sidebar.h value.h \
+ valuewidget.h webquery.h webqueryamatex.h webqueryarxiv.h webquerybibsonomy.h \
+ webquerycitebase.h webqueryciteseerx.h webquerycsb.h webquerydblp.h \
+ webquerygooglescholar.h webqueryieeexplore.h webquerymathscinet.h webquerypubmed.h \
+ webquerysciencedirect.h webqueryspireshep.h webqueryz3950.h webqueryzmath.h xsltransform.h \
+ z3950connection.h
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc >>rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kbibtex.pot
+
+KDE_ICON = AUTO
+
+# this Makefile creates both a KPart application and a KPart
+#########################################################################
+# APPLICATION SECTION
+#########################################################################
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+bin_PROGRAMS = kbibtex
+
+# the application source, library search path, and link libraries
+kbibtex_SOURCES = kbibtexshell.cpp main.cpp
+kbibtex_LDFLAGS = $(all_libraries)
+kbibtex_LDADD = $(LIB_KPARTS)
+
+# this is where the desktop file will go
+shelldesktopdir = $(xdg_appsdir)
+shelldesktop_DATA = kbibtex.desktop
+
+#########################################################################
+# KPART SECTION
+#########################################################################
+kde_module_LTLIBRARIES = libkbibtexpart.la
+
+# the Part's source, library search path, and link libraries
+libkbibtexpart_la_SOURCES = comment.cpp fileexporterdocbook5.cpp commentwidget.cpp documentlistview.cpp \
+ documentlistviewitem.cpp documentsourceview.cpp documentwidget.cpp element.cpp encoder.cpp \
+ encoderlatex.cpp encoderxml.cpp entry.cpp entryfield.cpp entrywidget.cpp \
+ entrywidgetauthor.cpp entrywidgetexternal.cpp entrywidgetkeyword.cpp entrywidgetmisc.cpp \
+ entrywidgetother.cpp entrywidgetpublication.cpp entrywidgetsource.cpp entrywidgettab.cpp \
+ entrywidgettitle.cpp entrywidgetuserdefined.cpp entrywidgetwarningsitem.cpp \
+ z3950connection.cpp fieldlineedit.cpp fieldlistview.cpp file.cpp fileexporter.cpp \
+ fileexporterbibtex.cpp fileexporterris.cpp fileexporterbibutils.cpp fileexporterexternal.cpp fileexporterpdf.cpp \
+ fileexporterps.cpp fileexporterrtf.cpp fileexportertoolchain.cpp fileexporterxml.cpp \
+ fileexporterxslt.cpp fileimporter.cpp fileimporterbibtex.cpp fileimporterbibutils.cpp \
+ fileimporterexternal.cpp fileimporterris.cpp idsuggestions.cpp idsuggestionswidget.cpp \
+ kbibtex_part.cpp macro.cpp macrowidget.cpp mergeelements.cpp preamble.cpp webqueryieeexplore.cpp \
+ preamblewidget.cpp searchbar.cpp settings.cpp settingsdlg.cpp settingsediting.cpp \
+ settingsfileio.cpp settingsidsuggestions.cpp settingskeyword.cpp settingssearchurl.cpp \
+ settingsuserdefinedinput.cpp sidebar.cpp value.cpp valuewidget.cpp webquery.cpp webqueryamatex.cpp \
+ webqueryarxiv.cpp webqueryciteseerx.cpp webquerybibsonomy.cpp webquerycsb.cpp webquerycitebase.cpp webquerydblp.cpp webqueryz3950.cpp \
+ webquerygooglescholar.cpp webquerypubmed.cpp webqueryspireshep.cpp webqueryzmath.cpp \
+ xsltransform.cpp webquerysciencedirect.cpp findduplicates.cpp settingsz3950.cpp \
+ messagehandler.cpp iso6937converter.cpp iso5426converter.cpp webquerymathscinet.cpp
+libkbibtexpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+libkbibtexpart_la_LIBADD = $(LIB_KPARTS) $(LIB_KFILE) $(LIB_KUTILS) $(LIBXSLT_LIBS) $(LIBXML_LIBS) $(LIBYAZ_LIBS) $(LIBBIBUTILS_LIBS) -lkatepartinterfaces
+
+# this is where the desktop file will go
+partdesktopdir = $(kde_servicesdir)
+partdesktop_DATA = kbibtex_part.desktop
+
+# this is where the XML-GUI resource fileis go
+partrcdir = ${kde_datadir}/kbibtexpart
+partrc_DATA = kbibtex_part.rc
+shellrcdir = ${kde_datadir}/kbibtex
+shellrc_DATA = kbibtex_shell.rc
+
+appdir = $(kde_datadir)/kbibtex
+app_DATA = z3950-servers.cfg
+
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..d858e05
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,1710 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# KDE tags expanded automatically by am_edit - $Revision: 483858 $
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = kbibtex$(EXEEXT)
+subdir = src
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/admin/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(kde_moduledir)" "$(DESTDIR)$(bindir)" \
+ "$(DESTDIR)$(appdir)" "$(DESTDIR)$(partdesktopdir)" \
+ "$(DESTDIR)$(partrcdir)" "$(DESTDIR)$(shelldesktopdir)" \
+ "$(DESTDIR)$(shellrcdir)"
+kde_moduleLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(kde_module_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libkbibtexpart_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libkbibtexpart_la_OBJECTS = comment.lo fileexporterdocbook5.lo \
+ commentwidget.lo documentlistview.lo documentlistviewitem.lo \
+ documentsourceview.lo documentwidget.lo element.lo encoder.lo \
+ encoderlatex.lo encoderxml.lo entry.lo entryfield.lo \
+ entrywidget.lo entrywidgetauthor.lo entrywidgetexternal.lo \
+ entrywidgetkeyword.lo entrywidgetmisc.lo entrywidgetother.lo \
+ entrywidgetpublication.lo entrywidgetsource.lo \
+ entrywidgettab.lo entrywidgettitle.lo \
+ entrywidgetuserdefined.lo entrywidgetwarningsitem.lo \
+ z3950connection.lo fieldlineedit.lo fieldlistview.lo file.lo \
+ fileexporter.lo fileexporterbibtex.lo fileexporterris.lo \
+ fileexporterbibutils.lo fileexporterexternal.lo \
+ fileexporterpdf.lo fileexporterps.lo fileexporterrtf.lo \
+ fileexportertoolchain.lo fileexporterxml.lo \
+ fileexporterxslt.lo fileimporter.lo fileimporterbibtex.lo \
+ fileimporterbibutils.lo fileimporterexternal.lo \
+ fileimporterris.lo idsuggestions.lo idsuggestionswidget.lo \
+ kbibtex_part.lo macro.lo macrowidget.lo mergeelements.lo \
+ preamble.lo webqueryieeexplore.lo preamblewidget.lo \
+ searchbar.lo settings.lo settingsdlg.lo settingsediting.lo \
+ settingsfileio.lo settingsidsuggestions.lo settingskeyword.lo \
+ settingssearchurl.lo settingsuserdefinedinput.lo sidebar.lo \
+ value.lo valuewidget.lo webquery.lo webqueryamatex.lo \
+ webqueryarxiv.lo webqueryciteseerx.lo webquerybibsonomy.lo \
+ webquerycsb.lo webquerycitebase.lo webquerydblp.lo \
+ webqueryz3950.lo webquerygooglescholar.lo webquerypubmed.lo \
+ webqueryspireshep.lo webqueryzmath.lo xsltransform.lo \
+ webquerysciencedirect.lo findduplicates.lo settingsz3950.lo \
+ messagehandler.lo iso6937converter.lo iso5426converter.lo \
+ webquerymathscinet.lo
+#>- libkbibtexpart_la_OBJECTS = $(am_libkbibtexpart_la_OBJECTS)
+#>+ 33
+libkbibtexpart_la_final_OBJECTS = libkbibtexpart_la.all_cpp.lo
+libkbibtexpart_la_nofinal_OBJECTS = comment.lo fileexporterdocbook5.lo \
+ commentwidget.lo documentlistview.lo documentlistviewitem.lo \
+ documentsourceview.lo documentwidget.lo element.lo encoder.lo \
+ encoderlatex.lo encoderxml.lo entry.lo entryfield.lo \
+ entrywidget.lo entrywidgetauthor.lo entrywidgetexternal.lo \
+ entrywidgetkeyword.lo entrywidgetmisc.lo entrywidgetother.lo \
+ entrywidgetpublication.lo entrywidgetsource.lo \
+ entrywidgettab.lo entrywidgettitle.lo \
+ entrywidgetuserdefined.lo entrywidgetwarningsitem.lo \
+ z3950connection.lo fieldlineedit.lo fieldlistview.lo file.lo \
+ fileexporter.lo fileexporterbibtex.lo fileexporterris.lo \
+ fileexporterbibutils.lo fileexporterexternal.lo \
+ fileexporterpdf.lo fileexporterps.lo fileexporterrtf.lo \
+ fileexportertoolchain.lo fileexporterxml.lo \
+ fileexporterxslt.lo fileimporter.lo fileimporterbibtex.lo \
+ fileimporterbibutils.lo fileimporterexternal.lo \
+ fileimporterris.lo idsuggestions.lo idsuggestionswidget.lo \
+ kbibtex_part.lo macro.lo macrowidget.lo mergeelements.lo \
+ preamble.lo webqueryieeexplore.lo preamblewidget.lo \
+ searchbar.lo settings.lo settingsdlg.lo settingsediting.lo \
+ settingsfileio.lo settingsidsuggestions.lo settingskeyword.lo \
+ settingssearchurl.lo settingsuserdefinedinput.lo sidebar.lo \
+ value.lo valuewidget.lo webquery.lo webqueryamatex.lo \
+ webqueryarxiv.lo webqueryciteseerx.lo webquerybibsonomy.lo \
+ webquerycsb.lo webquerycitebase.lo webquerydblp.lo \
+ webqueryz3950.lo webquerygooglescholar.lo webquerypubmed.lo \
+ webqueryspireshep.lo webqueryzmath.lo xsltransform.lo \
+ webquerysciencedirect.lo findduplicates.lo settingsz3950.lo \
+ messagehandler.lo iso6937converter.lo iso5426converter.lo \
+ webquerymathscinet.lo
+@KDE_USE_FINAL_FALSE@libkbibtexpart_la_OBJECTS = $(libkbibtexpart_la_nofinal_OBJECTS)
+@KDE_USE_FINAL_TRUE@libkbibtexpart_la_OBJECTS = $(libkbibtexpart_la_final_OBJECTS)
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_kbibtex_OBJECTS = kbibtexshell.$(OBJEXT) main.$(OBJEXT)
+#>- kbibtex_OBJECTS = $(am_kbibtex_OBJECTS)
+#>+ 4
+kbibtex_final_OBJECTS = kbibtex.all_cpp.o
+kbibtex_nofinal_OBJECTS = kbibtexshell.$(OBJEXT) main.$(OBJEXT)
+@KDE_USE_FINAL_FALSE@kbibtex_OBJECTS = $(kbibtex_nofinal_OBJECTS)
+@KDE_USE_FINAL_TRUE@kbibtex_OBJECTS = $(kbibtex_final_OBJECTS)
+kbibtex_DEPENDENCIES = $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/admin/depcomp
+am__depfiles_maybe = depfiles
+#>- CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+#>- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+#>+ 2
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS)
+#>- LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+#>- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+#>- $(AM_CXXFLAGS) $(CXXFLAGS)
+#>+ 3
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS)
+CXXLD = $(CXX)
+#>- CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+#>- $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+#>+ 2
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(KDE_CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libkbibtexpart_la_SOURCES) $(kbibtex_SOURCES)
+DIST_SOURCES = $(libkbibtexpart_la_SOURCES) $(kbibtex_SOURCES)
+appDATA_INSTALL = $(INSTALL_DATA)
+partdesktopDATA_INSTALL = $(INSTALL_DATA)
+partrcDATA_INSTALL = $(INSTALL_DATA)
+shelldesktopDATA_INSTALL = $(INSTALL_DATA)
+shellrcDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(app_DATA) $(partdesktop_DATA) $(partrc_DATA) \
+ $(shelldesktop_DATA) $(shellrc_DATA)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+#>- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+#>+ 1
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+ARTSCCONFIG = @ARTSCCONFIG@
+AUTOCONF = @AUTOCONF@
+AUTODIRS = @AUTODIRS@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONF_FILES = @CONF_FILES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DCOPIDL = @DCOPIDL@
+DCOPIDL2CPP = @DCOPIDL2CPP@
+DCOPIDLNG = @DCOPIDLNG@
+DCOP_DEPENDENCIES = @DCOP_DEPENDENCIES@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_PERMISSIVE_FLAG = @ENABLE_PERMISSIVE_FLAG@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FRAMEWORK_COREAUDIO = @FRAMEWORK_COREAUDIO@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+HAVE_GCC_VISIBILITY = @HAVE_GCC_VISIBILITY@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KCFG_DEPENDENCIES = @KCFG_DEPENDENCIES@
+KCONFIG_COMPILER = @KCONFIG_COMPILER@
+KDECONFIG = @KDECONFIG@
+KDE_CHECK_PLUGIN = @KDE_CHECK_PLUGIN@
+KDE_EXTRA_RPATH = @KDE_EXTRA_RPATH@
+KDE_INCLUDES = @KDE_INCLUDES@
+KDE_LDFLAGS = @KDE_LDFLAGS@
+KDE_MT_LDFLAGS = @KDE_MT_LDFLAGS@
+KDE_MT_LIBS = @KDE_MT_LIBS@
+KDE_NO_UNDEFINED = @KDE_NO_UNDEFINED@
+KDE_PLUGIN = @KDE_PLUGIN@
+KDE_RPATH = @KDE_RPATH@
+KDE_USE_CLOSURE_FALSE = @KDE_USE_CLOSURE_FALSE@
+KDE_USE_CLOSURE_TRUE = @KDE_USE_CLOSURE_TRUE@
+KDE_USE_FINAL_FALSE = @KDE_USE_FINAL_FALSE@
+KDE_USE_FINAL_TRUE = @KDE_USE_FINAL_TRUE@
+KDE_USE_FPIE = @KDE_USE_FPIE@
+KDE_USE_NMCHECK_FALSE = @KDE_USE_NMCHECK_FALSE@
+KDE_USE_NMCHECK_TRUE = @KDE_USE_NMCHECK_TRUE@
+KDE_USE_PIE = @KDE_USE_PIE@
+KDE_XSL_STYLESHEET = @KDE_XSL_STYLESHEET@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_AS_NEEDED = @LDFLAGS_AS_NEEDED@
+LDFLAGS_NEW_DTAGS = @LDFLAGS_NEW_DTAGS@
+LIBCOMPAT = @LIBCOMPAT@
+LIBCRYPT = @LIBCRYPT@
+LIBDL = @LIBDL@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPTHREAD = @LIBPTHREAD@
+LIBRESOLV = @LIBRESOLV@
+LIBS = @LIBS@
+LIBSM = @LIBSM@
+LIBSOCKET = @LIBSOCKET@
+LIBTOOL = @LIBTOOL@
+LIBUCB = @LIBUCB@
+LIBUTIL = @LIBUTIL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBYAZ_CFLAGS = @LIBYAZ_CFLAGS@
+LIBYAZ_LIBS = @LIBYAZ_LIBS@
+LIBYAZ_RPATH = @LIBYAZ_RPATH@
+LIBZ = @LIBZ@
+LIB_KAB = @LIB_KAB@
+LIB_KABC = @LIB_KABC@
+LIB_KDECORE = @LIB_KDECORE@
+LIB_KDED = @LIB_KDED@
+LIB_KDEPIM = @LIB_KDEPIM@
+LIB_KDEPRINT = @LIB_KDEPRINT@
+LIB_KDEUI = @LIB_KDEUI@
+LIB_KDNSSD = @LIB_KDNSSD@
+LIB_KFILE = @LIB_KFILE@
+LIB_KFM = @LIB_KFM@
+LIB_KHTML = @LIB_KHTML@
+LIB_KIMPROXY = @LIB_KIMPROXY@
+LIB_KIO = @LIB_KIO@
+LIB_KJS = @LIB_KJS@
+LIB_KNEWSTUFF = @LIB_KNEWSTUFF@
+LIB_KPARTS = @LIB_KPARTS@
+LIB_KSPELL = @LIB_KSPELL@
+LIB_KSYCOCA = @LIB_KSYCOCA@
+LIB_KUNITTEST = @LIB_KUNITTEST@
+LIB_KUTILS = @LIB_KUTILS@
+LIB_POLL = @LIB_POLL@
+LIB_QPE = @LIB_QPE@
+LIB_QT = @LIB_QT@
+LIB_SMB = @LIB_SMB@
+LIB_X11 = @LIB_X11@
+LIB_XEXT = @LIB_XEXT@
+LIB_XRENDER = @LIB_XRENDER@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKEKDEWIDGETS = @MAKEKDEWIDGETS@
+MCOPIDL = @MCOPIDL@
+MEINPROC = @MEINPROC@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+NOOPT_CFLAGS = @NOOPT_CFLAGS@
+NOOPT_CXXFLAGS = @NOOPT_CXXFLAGS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+QTE_NORTTI = @QTE_NORTTI@
+QT_INCLUDES = @QT_INCLUDES@
+QT_LDFLAGS = @QT_LDFLAGS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPSUBDIRS = @TOPSUBDIRS@
+UIC = @UIC@
+UIC_TR = @UIC_TR@
+USER_INCLUDES = @USER_INCLUDES@
+USER_LDFLAGS = @USER_LDFLAGS@
+USE_EXCEPTIONS = @USE_EXCEPTIONS@
+USE_RTTI = @USE_RTTI@
+USE_THREADS = @USE_THREADS@
+VERSION = @VERSION@
+WOVERLOADED_VIRTUAL = @WOVERLOADED_VIRTUAL@
+XGETTEXT = @XGETTEXT@
+XMKMF = @XMKMF@
+XMLLINT = @XMLLINT@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_INCLUDES = @X_INCLUDES@
+X_LDFLAGS = @X_LDFLAGS@
+X_PRE_LIBS = @X_PRE_LIBS@
+X_RPATH = @X_RPATH@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+include_ARTS_FALSE = @include_ARTS_FALSE@
+include_ARTS_TRUE = @include_ARTS_TRUE@
+include_x11_FALSE = @include_x11_FALSE@
+include_x11_TRUE = @include_x11_TRUE@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+kde_appsdir = @kde_appsdir@
+kde_bindir = @kde_bindir@
+kde_confdir = @kde_confdir@
+kde_datadir = @kde_datadir@
+kde_htmldir = @kde_htmldir@
+kde_icondir = @kde_icondir@
+kde_includes = @kde_includes@
+kde_kcfgdir = @kde_kcfgdir@
+kde_libraries = @kde_libraries@
+kde_libs_htmldir = @kde_libs_htmldir@
+kde_libs_prefix = @kde_libs_prefix@
+kde_locale = @kde_locale@
+kde_mimedir = @kde_mimedir@
+kde_moduledir = @kde_moduledir@
+kde_qtver = @kde_qtver@
+kde_servicesdir = @kde_servicesdir@
+kde_servicetypesdir = @kde_servicetypesdir@
+kde_sounddir = @kde_sounddir@
+kde_styledir = @kde_styledir@
+kde_templatesdir = @kde_templatesdir@
+kde_wallpaperdir = @kde_wallpaperdir@
+kde_widgetdir = @kde_widgetdir@
+kdeinitdir = @kdeinitdir@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+qt_includes = @qt_includes@
+qt_libraries = @qt_libraries@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+unsermake_enable_pch_FALSE = @unsermake_enable_pch_FALSE@
+unsermake_enable_pch_TRUE = @unsermake_enable_pch_TRUE@
+x_includes = @x_includes@
+x_libraries = @x_libraries@
+xdg_appsdir = @xdg_appsdir@
+xdg_directorydir = @xdg_directorydir@
+xdg_menudir = @xdg_menudir@
+
+# set the include path for X, qt and KDE
+INCLUDES = $(all_includes) $(LIBXSLT_CFLAGS) $(LIBXML_CFLAGS) $(LIBYAZ_CFLAGS) $(LIBBIBUTILS_CFLAGS)
+
+# these are the headers for your project
+noinst_HEADERS = documentlistviewitem.h fileexportertoolchain.h \
+ comment.h commentwidget.h documentlistview.h documentlistviewitem.h \
+ documentsourceview.h documentwidget.h element.h encoder.h encoderlatex.h encoderxml.h \
+ entry.h entryfield.h entrywidget.h entrywidgetauthor.h entrywidgetexternal.h \
+ entrywidgetkeyword.h entrywidgetmisc.h entrywidgetother.h entrywidgetpublication.h \
+ entrywidgetsource.h entrywidgettab.h entrywidgettitle.h entrywidgetuserdefined.h \
+ entrywidgetwarningsitem.h fieldlineedit.h fieldlistview.h file.h fileexporter.h \
+ fileexporterbibtex.h fileexporterbibutils.h fileexporterdocbook5.h fileexporterexternal.h \
+ fileexporterpdf.h fileexporterps.h fileexporterris.h fileimporterbibtex.h \
+ fileexporterrtf.h fileexporterxml.h fileexporterxslt.h fileimporter.h \
+ fileimporterbibutils.h fileimporterexternal.h fileimporterris.h findduplicates.h \
+ idsuggestions.h idsuggestionswidget.h iso5426converter.h iso6937converter.h \
+ kbibtex_part.h kbibtexshell.h latin1literal.h macro.h macrowidget.h mergeelements.h \
+ messagehandler.h preamble.h preamblewidget.h searchbar.h settings.h settingsdlg.h \
+ settingsediting.h settingsfileio.h settingsidsuggestions.h settingskeyword.h \
+ settingssearchurl.h settingsuserdefinedinput.h settingsz3950.h sidebar.h value.h \
+ valuewidget.h webquery.h webqueryamatex.h webqueryarxiv.h webquerybibsonomy.h \
+ webquerycitebase.h webqueryciteseerx.h webquerycsb.h webquerydblp.h \
+ webquerygooglescholar.h webqueryieeexplore.h webquerymathscinet.h webquerypubmed.h \
+ webquerysciencedirect.h webqueryspireshep.h webqueryz3950.h webqueryzmath.h xsltransform.h \
+ z3950connection.h
+
+# let automoc handle all of the meta source files (moc)
+#>- METASOURCES = AUTO
+KDE_ICON = AUTO
+
+# the application source, library search path, and link libraries
+kbibtex_SOURCES = kbibtexshell.cpp main.cpp
+kbibtex_LDFLAGS = $(all_libraries)
+kbibtex_LDADD = $(LIB_KPARTS)
+
+# this is where the desktop file will go
+shelldesktopdir = $(xdg_appsdir)
+shelldesktop_DATA = kbibtex.desktop
+
+#########################################################################
+# KPART SECTION
+#########################################################################
+kde_module_LTLIBRARIES = libkbibtexpart.la
+
+# the Part's source, library search path, and link libraries
+libkbibtexpart_la_SOURCES = comment.cpp fileexporterdocbook5.cpp commentwidget.cpp documentlistview.cpp \
+ documentlistviewitem.cpp documentsourceview.cpp documentwidget.cpp element.cpp encoder.cpp \
+ encoderlatex.cpp encoderxml.cpp entry.cpp entryfield.cpp entrywidget.cpp \
+ entrywidgetauthor.cpp entrywidgetexternal.cpp entrywidgetkeyword.cpp entrywidgetmisc.cpp \
+ entrywidgetother.cpp entrywidgetpublication.cpp entrywidgetsource.cpp entrywidgettab.cpp \
+ entrywidgettitle.cpp entrywidgetuserdefined.cpp entrywidgetwarningsitem.cpp \
+ z3950connection.cpp fieldlineedit.cpp fieldlistview.cpp file.cpp fileexporter.cpp \
+ fileexporterbibtex.cpp fileexporterris.cpp fileexporterbibutils.cpp fileexporterexternal.cpp fileexporterpdf.cpp \
+ fileexporterps.cpp fileexporterrtf.cpp fileexportertoolchain.cpp fileexporterxml.cpp \
+ fileexporterxslt.cpp fileimporter.cpp fileimporterbibtex.cpp fileimporterbibutils.cpp \
+ fileimporterexternal.cpp fileimporterris.cpp idsuggestions.cpp idsuggestionswidget.cpp \
+ kbibtex_part.cpp macro.cpp macrowidget.cpp mergeelements.cpp preamble.cpp webqueryieeexplore.cpp \
+ preamblewidget.cpp searchbar.cpp settings.cpp settingsdlg.cpp settingsediting.cpp \
+ settingsfileio.cpp settingsidsuggestions.cpp settingskeyword.cpp settingssearchurl.cpp \
+ settingsuserdefinedinput.cpp sidebar.cpp value.cpp valuewidget.cpp webquery.cpp webqueryamatex.cpp \
+ webqueryarxiv.cpp webqueryciteseerx.cpp webquerybibsonomy.cpp webquerycsb.cpp webquerycitebase.cpp webquerydblp.cpp webqueryz3950.cpp \
+ webquerygooglescholar.cpp webquerypubmed.cpp webqueryspireshep.cpp webqueryzmath.cpp \
+ xsltransform.cpp webquerysciencedirect.cpp findduplicates.cpp settingsz3950.cpp \
+ messagehandler.cpp iso6937converter.cpp iso5426converter.cpp webquerymathscinet.cpp
+
+libkbibtexpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+libkbibtexpart_la_LIBADD = $(LIB_KPARTS) $(LIB_KFILE) $(LIB_KUTILS) $(LIBXSLT_LIBS) $(LIBXML_LIBS) $(LIBYAZ_LIBS) $(LIBBIBUTILS_LIBS) -lkatepartinterfaces
+
+# this is where the desktop file will go
+partdesktopdir = $(kde_servicesdir)
+partdesktop_DATA = kbibtex_part.desktop
+
+# this is where the XML-GUI resource fileis go
+partrcdir = ${kde_datadir}/kbibtexpart
+partrc_DATA = kbibtex_part.rc
+shellrcdir = ${kde_datadir}/kbibtex
+shellrc_DATA = kbibtex_shell.rc
+appdir = $(kde_datadir)/kbibtex
+app_DATA = z3950-servers.cfg
+#>- all: all-am
+#>+ 1
+all: docs-am all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+#>- @for dep in $?; do \
+#>- case '$(am__configure_deps)' in \
+#>- *$$dep*) \
+#>- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+#>- && exit 0; \
+#>- exit 1;; \
+#>- esac; \
+#>- done; \
+#>- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+#>- cd $(top_srcdir) && \
+#>- $(AUTOMAKE) --gnu src/Makefile
+#>+ 12
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+ cd $(top_srcdir) && perl admin/am_edit src/Makefile.in
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-kde_moduleLTLIBRARIES: $(kde_module_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(kde_moduledir)" || $(mkdir_p) "$(DESTDIR)$(kde_moduledir)"
+ @list='$(kde_module_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(kde_moduleLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(kde_moduledir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(kde_moduleLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(kde_moduledir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-kde_moduleLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(kde_module_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(kde_moduledir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(kde_moduledir)/$$p"; \
+ done
+
+clean-kde_moduleLTLIBRARIES:
+ -test -z "$(kde_module_LTLIBRARIES)" || rm -f $(kde_module_LTLIBRARIES)
+ @list='$(kde_module_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+#>- libkbibtexpart.la: $(libkbibtexpart_la_OBJECTS) $(libkbibtexpart_la_DEPENDENCIES)
+#>+ 2
+@[email protected]: libkbibtexpart.la.closure $(libkbibtexpart_la_OBJECTS) $(libkbibtexpart_la_DEPENDENCIES)
+@[email protected]: $(libkbibtexpart_la_OBJECTS) $(libkbibtexpart_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(kde_moduledir) $(libkbibtexpart_la_LDFLAGS) $(libkbibtexpart_la_OBJECTS) $(libkbibtexpart_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+kbibtex$(EXEEXT): $(kbibtex_OBJECTS) $(kbibtex_DEPENDENCIES)
+ @rm -f kbibtex$(EXEEXT)
+ $(CXXLINK) $(kbibtex_LDFLAGS) $(kbibtex_OBJECTS) $(kbibtex_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comment.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commentwidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/documentlistview.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/documentlistviewitem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/documentsourceview.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/documentwidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/element.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoderlatex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoderxml.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entryfield.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetauthor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetexternal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetkeyword.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetmisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetother.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetpublication.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetsource.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgettab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgettitle.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetuserdefined.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entrywidgetwarningsitem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fieldlineedit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fieldlistview.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterbibtex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterbibutils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterdocbook5.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterexternal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterpdf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterps.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterris.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterrtf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexportertoolchain.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterxml.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileexporterxslt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileimporter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileimporterbibtex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileimporterbibutils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileimporterexternal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileimporterris.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findduplicates.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idsuggestions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idsuggestionswidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso5426converter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso6937converter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbibtex_part.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kbibtexshell.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macro.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macrowidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mergeelements.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messagehandler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preamble.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preamblewidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/searchbar.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingsdlg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingsediting.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingsfileio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingsidsuggestions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingskeyword.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingssearchurl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingsuserdefinedinput.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingsz3950.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sidebar.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/value.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/valuewidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquery.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webqueryamatex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webqueryarxiv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerybibsonomy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerycitebase.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webqueryciteseerx.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerycsb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerydblp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerygooglescholar.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webqueryieeexplore.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerymathscinet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerypubmed.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webquerysciencedirect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webqueryspireshep.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webqueryz3950.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webqueryzmath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsltransform.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/z3950connection.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-appDATA: $(app_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(appdir)" || $(mkdir_p) "$(DESTDIR)$(appdir)"
+ @list='$(app_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(appDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(appdir)/$$f'"; \
+ $(appDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(appdir)/$$f"; \
+ done
+
+uninstall-appDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(app_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(appdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(appdir)/$$f"; \
+ done
+install-partdesktopDATA: $(partdesktop_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(partdesktopdir)" || $(mkdir_p) "$(DESTDIR)$(partdesktopdir)"
+ @list='$(partdesktop_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(partdesktopDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(partdesktopdir)/$$f'"; \
+ $(partdesktopDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(partdesktopdir)/$$f"; \
+ done
+
+uninstall-partdesktopDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(partdesktop_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(partdesktopdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(partdesktopdir)/$$f"; \
+ done
+install-partrcDATA: $(partrc_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(partrcdir)" || $(mkdir_p) "$(DESTDIR)$(partrcdir)"
+ @list='$(partrc_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(partrcDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(partrcdir)/$$f'"; \
+ $(partrcDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(partrcdir)/$$f"; \
+ done
+
+uninstall-partrcDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(partrc_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(partrcdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(partrcdir)/$$f"; \
+ done
+install-shelldesktopDATA: $(shelldesktop_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(shelldesktopdir)" || $(mkdir_p) "$(DESTDIR)$(shelldesktopdir)"
+ @list='$(shelldesktop_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(shelldesktopDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(shelldesktopdir)/$$f'"; \
+ $(shelldesktopDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(shelldesktopdir)/$$f"; \
+ done
+
+uninstall-shelldesktopDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(shelldesktop_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(shelldesktopdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(shelldesktopdir)/$$f"; \
+ done
+install-shellrcDATA: $(shellrc_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(shellrcdir)" || $(mkdir_p) "$(DESTDIR)$(shellrcdir)"
+ @list='$(shellrc_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(shellrcDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(shellrcdir)/$$f'"; \
+ $(shellrcDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(shellrcdir)/$$f"; \
+ done
+
+uninstall-shellrcDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(shellrc_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(shellrcdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(shellrcdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(kde_moduledir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(appdir)" "$(DESTDIR)$(partdesktopdir)" "$(DESTDIR)$(partrcdir)" "$(DESTDIR)$(shelldesktopdir)" "$(DESTDIR)$(shellrcdir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+#>- clean: clean-am
+#>+ 1
+clean: kde-rpo-clean clean-am
+
+#>- clean-am: clean-binPROGRAMS clean-generic clean-kde_moduleLTLIBRARIES \
+#>- clean-libtool mostlyclean-am
+#>+ 2
+clean-am: clean-metasources clean-closures clean-bcheck clean-final clean-binPROGRAMS clean-generic clean-kde_moduleLTLIBRARIES \
+ clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+#>- install-data-am: install-appDATA install-kde_moduleLTLIBRARIES \
+#>- install-partdesktopDATA install-partrcDATA \
+#>- install-shelldesktopDATA install-shellrcDATA
+#>+ 3
+install-data-am: install-kde-icons install-appDATA \
+ install-partdesktopDATA install-partrcDATA \
+ install-shelldesktopDATA install-shellrcDATA
+
+#>- install-exec-am: install-binPROGRAMS
+#>+ 1
+install-exec-am: install-binPROGRAMS install-kde_moduleLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+#>- uninstall-am: uninstall-appDATA uninstall-binPROGRAMS \
+#>- uninstall-info-am uninstall-kde_moduleLTLIBRARIES \
+#>- uninstall-partdesktopDATA uninstall-partrcDATA \
+#>- uninstall-shelldesktopDATA uninstall-shellrcDATA
+#>+ 4
+uninstall-am: uninstall-kde-icons uninstall-appDATA uninstall-binPROGRAMS \
+ uninstall-info-am uninstall-kde_moduleLTLIBRARIES \
+ uninstall-partdesktopDATA uninstall-partrcDATA \
+ uninstall-shelldesktopDATA uninstall-shellrcDATA
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-kde_moduleLTLIBRARIES clean-libtool ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-appDATA \
+ install-binPROGRAMS install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am \
+ install-kde_moduleLTLIBRARIES install-man \
+ install-partdesktopDATA install-partrcDATA \
+ install-shelldesktopDATA install-shellrcDATA install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-appDATA \
+ uninstall-binPROGRAMS uninstall-info-am \
+ uninstall-kde_moduleLTLIBRARIES uninstall-partdesktopDATA \
+ uninstall-partrcDATA uninstall-shelldesktopDATA \
+ uninstall-shellrcDATA
+
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc >>rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kbibtex.pot
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+#>+ 8
+libkbibtexpart.la.closure: $(libkbibtexpart_la_OBJECTS) $(libkbibtexpart_la_DEPENDENCIES)
+ @echo "int main() {return 0;}" > libkbibtexpart_la_closure.cpp
+ @$(LTCXXCOMPILE) -c libkbibtexpart_la_closure.cpp
+ $(CXXLINK) libkbibtexpart_la_closure.lo $(libkbibtexpart_la_LDFLAGS) $(libkbibtexpart_la_OBJECTS) $(libkbibtexpart_la_LIBADD) $(LIBS)
+ @rm -f libkbibtexpart_la_closure.* libkbibtexpart.la.closure
+ @echo "timestamp" > libkbibtexpart.la.closure
+
+
+#>+ 3
+entrywidgetuserdefined.moc: $(srcdir)/entrywidgetuserdefined.h
+ $(MOC) $(srcdir)/entrywidgetuserdefined.h -o entrywidgetuserdefined.moc
+
+#>+ 2
+mocs: entrywidgetuserdefined.moc
+
+#>+ 3
+documentlistview.moc: $(srcdir)/documentlistview.h
+ $(MOC) $(srcdir)/documentlistview.h -o documentlistview.moc
+
+#>+ 2
+mocs: documentlistview.moc
+
+#>+ 3
+file.moc: $(srcdir)/file.h
+ $(MOC) $(srcdir)/file.h -o file.moc
+
+#>+ 2
+mocs: file.moc
+
+#>+ 3
+documentsourceview.moc: $(srcdir)/documentsourceview.h
+ $(MOC) $(srcdir)/documentsourceview.h -o documentsourceview.moc
+
+#>+ 2
+mocs: documentsourceview.moc
+
+#>+ 3
+webqueryamatex.moc: $(srcdir)/webqueryamatex.h
+ $(MOC) $(srcdir)/webqueryamatex.h -o webqueryamatex.moc
+
+#>+ 2
+mocs: webqueryamatex.moc
+
+#>+ 3
+fileimporterbibutils.moc: $(srcdir)/fileimporterbibutils.h
+ $(MOC) $(srcdir)/fileimporterbibutils.h -o fileimporterbibutils.moc
+
+#>+ 2
+mocs: fileimporterbibutils.moc
+
+#>+ 3
+fieldlineedit.moc: $(srcdir)/fieldlineedit.h
+ $(MOC) $(srcdir)/fieldlineedit.h -o fieldlineedit.moc
+
+#>+ 2
+mocs: fieldlineedit.moc
+
+#>+ 3
+webquerymathscinet.moc: $(srcdir)/webquerymathscinet.h
+ $(MOC) $(srcdir)/webquerymathscinet.h -o webquerymathscinet.moc
+
+#>+ 2
+mocs: webquerymathscinet.moc
+
+#>+ 3
+webqueryciteseerx.moc: $(srcdir)/webqueryciteseerx.h
+ $(MOC) $(srcdir)/webqueryciteseerx.h -o webqueryciteseerx.moc
+
+#>+ 2
+mocs: webqueryciteseerx.moc
+
+#>+ 3
+webquerygooglescholar.moc: $(srcdir)/webquerygooglescholar.h
+ $(MOC) $(srcdir)/webquerygooglescholar.h -o webquerygooglescholar.moc
+
+#>+ 2
+mocs: webquerygooglescholar.moc
+
+#>+ 3
+entrywidget.moc: $(srcdir)/entrywidget.h
+ $(MOC) $(srcdir)/entrywidget.h -o entrywidget.moc
+
+#>+ 2
+mocs: entrywidget.moc
+
+#>+ 3
+webquerypubmed.moc: $(srcdir)/webquerypubmed.h
+ $(MOC) $(srcdir)/webquerypubmed.h -o webquerypubmed.moc
+
+#>+ 2
+mocs: webquerypubmed.moc
+
+#>+ 3
+webqueryz3950.moc: $(srcdir)/webqueryz3950.h
+ $(MOC) $(srcdir)/webqueryz3950.h -o webqueryz3950.moc
+
+#>+ 2
+mocs: webqueryz3950.moc
+
+#>+ 3
+fileexporterbibutils.moc: $(srcdir)/fileexporterbibutils.h
+ $(MOC) $(srcdir)/fileexporterbibutils.h -o fileexporterbibutils.moc
+
+#>+ 2
+mocs: fileexporterbibutils.moc
+
+#>+ 3
+entrywidgetmisc.moc: $(srcdir)/entrywidgetmisc.h
+ $(MOC) $(srcdir)/entrywidgetmisc.h -o entrywidgetmisc.moc
+
+#>+ 2
+mocs: entrywidgetmisc.moc
+
+#>+ 3
+entrywidgetexternal.moc: $(srcdir)/entrywidgetexternal.h
+ $(MOC) $(srcdir)/entrywidgetexternal.h -o entrywidgetexternal.moc
+
+#>+ 2
+mocs: entrywidgetexternal.moc
+
+#>+ 3
+kbibtex_part.moc: $(srcdir)/kbibtex_part.h
+ $(MOC) $(srcdir)/kbibtex_part.h -o kbibtex_part.moc
+
+#>+ 2
+mocs: kbibtex_part.moc
+
+#>+ 3
+webqueryzmath.moc: $(srcdir)/webqueryzmath.h
+ $(MOC) $(srcdir)/webqueryzmath.h -o webqueryzmath.moc
+
+#>+ 2
+mocs: webqueryzmath.moc
+
+#>+ 3
+webqueryspireshep.moc: $(srcdir)/webqueryspireshep.h
+ $(MOC) $(srcdir)/webqueryspireshep.h -o webqueryspireshep.moc
+
+#>+ 2
+mocs: webqueryspireshep.moc
+
+#>+ 3
+entrywidgetother.moc: $(srcdir)/entrywidgetother.h
+ $(MOC) $(srcdir)/entrywidgetother.h -o entrywidgetother.moc
+
+#>+ 2
+mocs: entrywidgetother.moc
+
+#>+ 3
+settingsediting.moc: $(srcdir)/settingsediting.h
+ $(MOC) $(srcdir)/settingsediting.h -o settingsediting.moc
+
+#>+ 2
+mocs: settingsediting.moc
+
+#>+ 3
+webqueryieeexplore.moc: $(srcdir)/webqueryieeexplore.h
+ $(MOC) $(srcdir)/webqueryieeexplore.h -o webqueryieeexplore.moc
+
+#>+ 2
+mocs: webqueryieeexplore.moc
+
+#>+ 3
+settingssearchurl.moc: $(srcdir)/settingssearchurl.h
+ $(MOC) $(srcdir)/settingssearchurl.h -o settingssearchurl.moc
+
+#>+ 2
+mocs: settingssearchurl.moc
+
+#>+ 3
+webquerycitebase.moc: $(srcdir)/webquerycitebase.h
+ $(MOC) $(srcdir)/webquerycitebase.h -o webquerycitebase.moc
+
+#>+ 2
+mocs: webquerycitebase.moc
+
+#>+ 3
+webquerydblp.moc: $(srcdir)/webquerydblp.h
+ $(MOC) $(srcdir)/webquerydblp.h -o webquerydblp.moc
+
+#>+ 2
+mocs: webquerydblp.moc
+
+#>+ 3
+preamblewidget.moc: $(srcdir)/preamblewidget.h
+ $(MOC) $(srcdir)/preamblewidget.h -o preamblewidget.moc
+
+#>+ 2
+mocs: preamblewidget.moc
+
+#>+ 3
+commentwidget.moc: $(srcdir)/commentwidget.h
+ $(MOC) $(srcdir)/commentwidget.h -o commentwidget.moc
+
+#>+ 2
+mocs: commentwidget.moc
+
+#>+ 3
+mergeelements.moc: $(srcdir)/mergeelements.h
+ $(MOC) $(srcdir)/mergeelements.h -o mergeelements.moc
+
+#>+ 2
+mocs: mergeelements.moc
+
+#>+ 3
+fileimporterexternal.moc: $(srcdir)/fileimporterexternal.h
+ $(MOC) $(srcdir)/fileimporterexternal.h -o fileimporterexternal.moc
+
+#>+ 2
+mocs: fileimporterexternal.moc
+
+#>+ 3
+settingskeyword.moc: $(srcdir)/settingskeyword.h
+ $(MOC) $(srcdir)/settingskeyword.h -o settingskeyword.moc
+
+#>+ 2
+mocs: settingskeyword.moc
+
+#>+ 3
+webquerybibsonomy.moc: $(srcdir)/webquerybibsonomy.h
+ $(MOC) $(srcdir)/webquerybibsonomy.h -o webquerybibsonomy.moc
+
+#>+ 2
+mocs: webquerybibsonomy.moc
+
+#>+ 3
+findduplicates.moc: $(srcdir)/findduplicates.h
+ $(MOC) $(srcdir)/findduplicates.h -o findduplicates.moc
+
+#>+ 2
+mocs: findduplicates.moc
+
+#>+ 3
+entrywidgettitle.moc: $(srcdir)/entrywidgettitle.h
+ $(MOC) $(srcdir)/entrywidgettitle.h -o entrywidgettitle.moc
+
+#>+ 2
+mocs: entrywidgettitle.moc
+
+#>+ 3
+entrywidgetkeyword.moc: $(srcdir)/entrywidgetkeyword.h
+ $(MOC) $(srcdir)/entrywidgetkeyword.h -o entrywidgetkeyword.moc
+
+#>+ 2
+mocs: entrywidgetkeyword.moc
+
+#>+ 3
+entrywidgetsource.moc: $(srcdir)/entrywidgetsource.h
+ $(MOC) $(srcdir)/entrywidgetsource.h -o entrywidgetsource.moc
+
+#>+ 2
+mocs: entrywidgetsource.moc
+
+#>+ 3
+fileexporter.moc: $(srcdir)/fileexporter.h
+ $(MOC) $(srcdir)/fileexporter.h -o fileexporter.moc
+
+#>+ 2
+mocs: fileexporter.moc
+
+#>+ 3
+fileimporter.moc: $(srcdir)/fileimporter.h
+ $(MOC) $(srcdir)/fileimporter.h -o fileimporter.moc
+
+#>+ 2
+mocs: fileimporter.moc
+
+#>+ 3
+searchbar.moc: $(srcdir)/searchbar.h
+ $(MOC) $(srcdir)/searchbar.h -o searchbar.moc
+
+#>+ 2
+mocs: searchbar.moc
+
+#>+ 3
+settingsz3950.moc: $(srcdir)/settingsz3950.h
+ $(MOC) $(srcdir)/settingsz3950.h -o settingsz3950.moc
+
+#>+ 2
+mocs: settingsz3950.moc
+
+#>+ 3
+idsuggestionswidget.moc: $(srcdir)/idsuggestionswidget.h
+ $(MOC) $(srcdir)/idsuggestionswidget.h -o idsuggestionswidget.moc
+
+#>+ 2
+mocs: idsuggestionswidget.moc
+
+#>+ 3
+entrywidgettab.moc: $(srcdir)/entrywidgettab.h
+ $(MOC) $(srcdir)/entrywidgettab.h -o entrywidgettab.moc
+
+#>+ 2
+mocs: entrywidgettab.moc
+
+#>+ 3
+entrywidgetpublication.moc: $(srcdir)/entrywidgetpublication.h
+ $(MOC) $(srcdir)/entrywidgetpublication.h -o entrywidgetpublication.moc
+
+#>+ 2
+mocs: entrywidgetpublication.moc
+
+#>+ 3
+kbibtexshell.moc: $(srcdir)/kbibtexshell.h
+ $(MOC) $(srcdir)/kbibtexshell.h -o kbibtexshell.moc
+
+#>+ 2
+mocs: kbibtexshell.moc
+
+#>+ 3
+fileexportertoolchain.moc: $(srcdir)/fileexportertoolchain.h
+ $(MOC) $(srcdir)/fileexportertoolchain.h -o fileexportertoolchain.moc
+
+#>+ 2
+mocs: fileexportertoolchain.moc
+
+#>+ 3
+settingsidsuggestions.moc: $(srcdir)/settingsidsuggestions.h
+ $(MOC) $(srcdir)/settingsidsuggestions.h -o settingsidsuggestions.moc
+
+#>+ 2
+mocs: settingsidsuggestions.moc
+
+#>+ 3
+webquerysciencedirect.moc: $(srcdir)/webquerysciencedirect.h
+ $(MOC) $(srcdir)/webquerysciencedirect.h -o webquerysciencedirect.moc
+
+#>+ 2
+mocs: webquerysciencedirect.moc
+
+#>+ 3
+settingsfileio.moc: $(srcdir)/settingsfileio.h
+ $(MOC) $(srcdir)/settingsfileio.h -o settingsfileio.moc
+
+#>+ 2
+mocs: settingsfileio.moc
+
+#>+ 3
+entrywidgetauthor.moc: $(srcdir)/entrywidgetauthor.h
+ $(MOC) $(srcdir)/entrywidgetauthor.h -o entrywidgetauthor.moc
+
+#>+ 2
+mocs: entrywidgetauthor.moc
+
+#>+ 3
+settingsuserdefinedinput.moc: $(srcdir)/settingsuserdefinedinput.h
+ $(MOC) $(srcdir)/settingsuserdefinedinput.h -o settingsuserdefinedinput.moc
+
+#>+ 2
+mocs: settingsuserdefinedinput.moc
+
+#>+ 3
+settingsdlg.moc: $(srcdir)/settingsdlg.h
+ $(MOC) $(srcdir)/settingsdlg.h -o settingsdlg.moc
+
+#>+ 2
+mocs: settingsdlg.moc
+
+#>+ 3
+sidebar.moc: $(srcdir)/sidebar.h
+ $(MOC) $(srcdir)/sidebar.h -o sidebar.moc
+
+#>+ 2
+mocs: sidebar.moc
+
+#>+ 3
+webqueryarxiv.moc: $(srcdir)/webqueryarxiv.h
+ $(MOC) $(srcdir)/webqueryarxiv.h -o webqueryarxiv.moc
+
+#>+ 2
+mocs: webqueryarxiv.moc
+
+#>+ 3
+webquery.moc: $(srcdir)/webquery.h
+ $(MOC) $(srcdir)/webquery.h -o webquery.moc
+
+#>+ 2
+mocs: webquery.moc
+
+#>+ 3
+fileexporterexternal.moc: $(srcdir)/fileexporterexternal.h
+ $(MOC) $(srcdir)/fileexporterexternal.h -o fileexporterexternal.moc
+
+#>+ 2
+mocs: fileexporterexternal.moc
+
+#>+ 3
+valuewidget.moc: $(srcdir)/valuewidget.h
+ $(MOC) $(srcdir)/valuewidget.h -o valuewidget.moc
+
+#>+ 2
+mocs: valuewidget.moc
+
+#>+ 3
+fieldlistview.moc: $(srcdir)/fieldlistview.h
+ $(MOC) $(srcdir)/fieldlistview.h -o fieldlistview.moc
+
+#>+ 2
+mocs: fieldlistview.moc
+
+#>+ 3
+macrowidget.moc: $(srcdir)/macrowidget.h
+ $(MOC) $(srcdir)/macrowidget.h -o macrowidget.moc
+
+#>+ 2
+mocs: macrowidget.moc
+
+#>+ 3
+webquerycsb.moc: $(srcdir)/webquerycsb.h
+ $(MOC) $(srcdir)/webquerycsb.h -o webquerycsb.moc
+
+#>+ 2
+mocs: webquerycsb.moc
+
+#>+ 3
+documentwidget.moc: $(srcdir)/documentwidget.h
+ $(MOC) $(srcdir)/documentwidget.h -o documentwidget.moc
+
+#>+ 2
+mocs: documentwidget.moc
+
+#>+ 3
+clean-metasources:
+ -rm -f entrywidgetuserdefined.moc documentlistview.moc file.moc documentsourceview.moc webqueryamatex.moc fileimporterbibutils.moc fieldlineedit.moc webquerymathscinet.moc webqueryciteseerx.moc webquerygooglescholar.moc entrywidget.moc webquerypubmed.moc webqueryz3950.moc fileexporterbibutils.moc entrywidgetmisc.moc entrywidgetexternal.moc kbibtex_part.moc webqueryzmath.moc webqueryspireshep.moc entrywidgetother.moc settingsediting.moc webqueryieeexplore.moc settingssearchurl.moc webquerycitebase.moc webquerydblp.moc preamblewidget.moc commentwidget.moc mergeelements.moc fileimporterexternal.moc settingskeyword.moc webquerybibsonomy.moc findduplicates.moc entrywidgettitle.moc entrywidgetkeyword.moc entrywidgetsource.moc fileexporter.moc fileimporter.moc searchbar.moc settingsz3950.moc idsuggestionswidget.moc entrywidgettab.moc entrywidgetpublication.moc kbibtexshell.moc fileexportertoolchain.moc settingsidsuggestions.moc webquerysciencedirect.moc settingsfileio.moc entrywidgetauthor.moc settingsuserdefinedinput.moc settingsdlg.moc sidebar.moc webqueryarxiv.moc webquery.moc fileexporterexternal.moc valuewidget.moc fieldlistview.moc macrowidget.moc webquerycsb.moc documentwidget.moc
+
+#>+ 2
+KDE_DIST=hi64-app-kbibtex.png Makefile.in z3950-servers.cfg kbibtex_shell.rc hi48-app-kbibtex.png kbibtex_part.rc hi128-app-kbibtex.png kbibtex.desktop hi16-app-kbibtex.png hi22-app-kbibtex.png hi32-app-kbibtex.png kbibtex.lsm Makefile.am kbibtex_part.desktop
+
+#>+ 3
+clean-closures:
+ -rm -f libkbibtexpart.la.closure
+
+#>+ 2
+docs-am:
+
+#>+ 22
+install-kde-icons:
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/22x22/apps
+ $(INSTALL_DATA) $(srcdir)/hi22-app-kbibtex.png $(DESTDIR)$(kde_icondir)/hicolor/22x22/apps/kbibtex.png
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/128x128/apps
+ $(INSTALL_DATA) $(srcdir)/hi128-app-kbibtex.png $(DESTDIR)$(kde_icondir)/hicolor/128x128/apps/kbibtex.png
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/64x64/apps
+ $(INSTALL_DATA) $(srcdir)/hi64-app-kbibtex.png $(DESTDIR)$(kde_icondir)/hicolor/64x64/apps/kbibtex.png
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/16x16/apps
+ $(INSTALL_DATA) $(srcdir)/hi16-app-kbibtex.png $(DESTDIR)$(kde_icondir)/hicolor/16x16/apps/kbibtex.png
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/48x48/apps
+ $(INSTALL_DATA) $(srcdir)/hi48-app-kbibtex.png $(DESTDIR)$(kde_icondir)/hicolor/48x48/apps/kbibtex.png
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/32x32/apps
+ $(INSTALL_DATA) $(srcdir)/hi32-app-kbibtex.png $(DESTDIR)$(kde_icondir)/hicolor/32x32/apps/kbibtex.png
+
+uninstall-kde-icons:
+ -rm -f $(DESTDIR)$(kde_icondir)/hicolor/22x22/apps/kbibtex.png
+ -rm -f $(DESTDIR)$(kde_icondir)/hicolor/128x128/apps/kbibtex.png
+ -rm -f $(DESTDIR)$(kde_icondir)/hicolor/64x64/apps/kbibtex.png
+ -rm -f $(DESTDIR)$(kde_icondir)/hicolor/16x16/apps/kbibtex.png
+ -rm -f $(DESTDIR)$(kde_icondir)/hicolor/48x48/apps/kbibtex.png
+ -rm -f $(DESTDIR)$(kde_icondir)/hicolor/32x32/apps/kbibtex.png
+
+#>+ 15
+force-reedit:
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+ cd $(top_srcdir) && perl admin/am_edit src/Makefile.in
+
+
+#>+ 21
+clean-bcheck:
+ rm -f *.bchecktest.cc *.bchecktest.cc.class a.out
+
+bcheck: bcheck-am
+
+bcheck-am:
+ @for i in ; do \
+ if test $(srcdir)/$$i -nt $$i.bchecktest.cc; then \
+ echo "int main() {return 0;}" > $$i.bchecktest.cc ; \
+ echo "#include \"$$i\"" >> $$i.bchecktest.cc ; \
+ echo "$$i"; \
+ if ! $(CXXCOMPILE) --dump-class-hierarchy -c $$i.bchecktest.cc; then \
+ rm -f $$i.bchecktest.cc; exit 1; \
+ fi ; \
+ echo "" >> $$i.bchecktest.cc.class; \
+ perl $(top_srcdir)/admin/bcheck.pl $$i.bchecktest.cc.class || { rm -f $$i.bchecktest.cc; exit 1; }; \
+ rm -f a.out; \
+ fi ; \
+ done
+
+
+#>+ 11
+libkbibtexpart_la.all_cpp.cpp: $(srcdir)/Makefile.in $(srcdir)/comment.cpp $(srcdir)/fileexporterdocbook5.cpp $(srcdir)/commentwidget.cpp $(srcdir)/documentlistview.cpp $(srcdir)/documentlistviewitem.cpp $(srcdir)/documentsourceview.cpp $(srcdir)/documentwidget.cpp $(srcdir)/element.cpp $(srcdir)/encoder.cpp $(srcdir)/encoderlatex.cpp $(srcdir)/encoderxml.cpp $(srcdir)/entry.cpp $(srcdir)/entryfield.cpp $(srcdir)/entrywidget.cpp $(srcdir)/entrywidgetauthor.cpp $(srcdir)/entrywidgetexternal.cpp $(srcdir)/entrywidgetkeyword.cpp $(srcdir)/entrywidgetmisc.cpp $(srcdir)/entrywidgetother.cpp $(srcdir)/entrywidgetpublication.cpp $(srcdir)/entrywidgetsource.cpp $(srcdir)/entrywidgettab.cpp $(srcdir)/entrywidgettitle.cpp $(srcdir)/entrywidgetuserdefined.cpp $(srcdir)/entrywidgetwarningsitem.cpp $(srcdir)/z3950connection.cpp $(srcdir)/fieldlineedit.cpp $(srcdir)/fieldlistview.cpp $(srcdir)/file.cpp $(srcdir)/fileexporter.cpp $(srcdir)/fileexporterbibtex.cpp $(srcdir)/fileexporterris.cpp $(srcdir)/fileexporterbibutils.cpp $(srcdir)/fileexporterexternal.cpp $(srcdir)/fileexporterpdf.cpp $(srcdir)/fileexporterps.cpp $(srcdir)/fileexporterrtf.cpp $(srcdir)/fileexportertoolchain.cpp $(srcdir)/fileexporterxml.cpp $(srcdir)/fileexporterxslt.cpp $(srcdir)/fileimporter.cpp $(srcdir)/fileimporterbibtex.cpp $(srcdir)/fileimporterbibutils.cpp $(srcdir)/fileimporterexternal.cpp $(srcdir)/fileimporterris.cpp $(srcdir)/idsuggestions.cpp $(srcdir)/idsuggestionswidget.cpp $(srcdir)/kbibtex_part.cpp $(srcdir)/macro.cpp $(srcdir)/macrowidget.cpp $(srcdir)/mergeelements.cpp $(srcdir)/preamble.cpp $(srcdir)/webqueryieeexplore.cpp $(srcdir)/preamblewidget.cpp $(srcdir)/searchbar.cpp $(srcdir)/settings.cpp $(srcdir)/settingsdlg.cpp $(srcdir)/settingsediting.cpp $(srcdir)/settingsfileio.cpp $(srcdir)/settingsidsuggestions.cpp $(srcdir)/settingskeyword.cpp $(srcdir)/settingssearchurl.cpp $(srcdir)/settingsuserdefinedinput.cpp $(srcdir)/sidebar.cpp $(srcdir)/value.cpp $(srcdir)/valuewidget.cpp $(srcdir)/webquery.cpp $(srcdir)/webqueryamatex.cpp $(srcdir)/webqueryarxiv.cpp $(srcdir)/webqueryciteseerx.cpp $(srcdir)/webquerybibsonomy.cpp $(srcdir)/webquerycsb.cpp $(srcdir)/webquerycitebase.cpp $(srcdir)/webquerydblp.cpp $(srcdir)/webqueryz3950.cpp $(srcdir)/webquerygooglescholar.cpp $(srcdir)/webquerypubmed.cpp $(srcdir)/webqueryspireshep.cpp $(srcdir)/webqueryzmath.cpp $(srcdir)/xsltransform.cpp $(srcdir)/webquerysciencedirect.cpp $(srcdir)/findduplicates.cpp $(srcdir)/settingsz3950.cpp $(srcdir)/messagehandler.cpp $(srcdir)/iso6937converter.cpp $(srcdir)/iso5426converter.cpp $(srcdir)/webquerymathscinet.cpp documentsourceview.moc file.moc documentlistview.moc entrywidgetuserdefined.moc webqueryamatex.moc fileimporterbibutils.moc webquerymathscinet.moc fieldlineedit.moc webqueryciteseerx.moc webquerygooglescholar.moc webquerypubmed.moc entrywidget.moc webqueryz3950.moc fileexporterbibutils.moc entrywidgetmisc.moc entrywidgetexternal.moc kbibtex_part.moc webqueryspireshep.moc webqueryzmath.moc settingsediting.moc entrywidgetother.moc settingssearchurl.moc webqueryieeexplore.moc webquerycitebase.moc webquerydblp.moc preamblewidget.moc commentwidget.moc mergeelements.moc fileimporterexternal.moc settingskeyword.moc webquerybibsonomy.moc findduplicates.moc entrywidgetkeyword.moc entrywidgettitle.moc fileexporter.moc entrywidgetsource.moc fileimporter.moc searchbar.moc idsuggestionswidget.moc settingsz3950.moc entrywidgettab.moc entrywidgetpublication.moc fileexportertoolchain.moc settingsidsuggestions.moc settingsuserdefinedinput.moc entrywidgetauthor.moc settingsfileio.moc webquerysciencedirect.moc settingsdlg.moc webqueryarxiv.moc sidebar.moc fileexporterexternal.moc webquery.moc valuewidget.moc fieldlistview.moc documentwidget.moc webquerycsb.moc macrowidget.moc
+ @echo 'creating libkbibtexpart_la.all_cpp.cpp ...'; \
+ rm -f libkbibtexpart_la.all_cpp.files libkbibtexpart_la.all_cpp.final; \
+ echo "#define KDE_USE_FINAL 1" >> libkbibtexpart_la.all_cpp.final; \
+ for file in comment.cpp fileexporterdocbook5.cpp commentwidget.cpp documentlistview.cpp documentlistviewitem.cpp documentsourceview.cpp documentwidget.cpp element.cpp encoder.cpp encoderlatex.cpp encoderxml.cpp entry.cpp entryfield.cpp entrywidget.cpp entrywidgetauthor.cpp entrywidgetexternal.cpp entrywidgetkeyword.cpp entrywidgetmisc.cpp entrywidgetother.cpp entrywidgetpublication.cpp entrywidgetsource.cpp entrywidgettab.cpp entrywidgettitle.cpp entrywidgetuserdefined.cpp entrywidgetwarningsitem.cpp z3950connection.cpp fieldlineedit.cpp fieldlistview.cpp file.cpp fileexporter.cpp fileexporterbibtex.cpp fileexporterris.cpp fileexporterbibutils.cpp fileexporterexternal.cpp fileexporterpdf.cpp fileexporterps.cpp fileexporterrtf.cpp fileexportertoolchain.cpp fileexporterxml.cpp fileexporterxslt.cpp fileimporter.cpp fileimporterbibtex.cpp fileimporterbibutils.cpp fileimporterexternal.cpp fileimporterris.cpp idsuggestions.cpp idsuggestionswidget.cpp kbibtex_part.cpp macro.cpp macrowidget.cpp mergeelements.cpp preamble.cpp webqueryieeexplore.cpp preamblewidget.cpp searchbar.cpp settings.cpp settingsdlg.cpp settingsediting.cpp settingsfileio.cpp settingsidsuggestions.cpp settingskeyword.cpp settingssearchurl.cpp settingsuserdefinedinput.cpp sidebar.cpp value.cpp valuewidget.cpp webquery.cpp webqueryamatex.cpp webqueryarxiv.cpp webqueryciteseerx.cpp webquerybibsonomy.cpp webquerycsb.cpp webquerycitebase.cpp webquerydblp.cpp webqueryz3950.cpp webquerygooglescholar.cpp webquerypubmed.cpp webqueryspireshep.cpp webqueryzmath.cpp xsltransform.cpp webquerysciencedirect.cpp findduplicates.cpp settingsz3950.cpp messagehandler.cpp iso6937converter.cpp iso5426converter.cpp webquerymathscinet.cpp ; do \
+ echo "#include \"$$file\"" >> libkbibtexpart_la.all_cpp.files; \
+ test ! -f $(srcdir)/$$file || egrep '^#pragma +implementation' $(srcdir)/$$file >> libkbibtexpart_la.all_cpp.final; \
+ done; \
+ cat libkbibtexpart_la.all_cpp.final libkbibtexpart_la.all_cpp.files > libkbibtexpart_la.all_cpp.cpp; \
+ rm -f libkbibtexpart_la.all_cpp.final libkbibtexpart_la.all_cpp.files
+
+#>+ 11
+kbibtex.all_cpp.cpp: $(srcdir)/Makefile.in $(srcdir)/kbibtexshell.cpp $(srcdir)/main.cpp kbibtexshell.moc
+ @echo 'creating kbibtex.all_cpp.cpp ...'; \
+ rm -f kbibtex.all_cpp.files kbibtex.all_cpp.final; \
+ echo "#define KDE_USE_FINAL 1" >> kbibtex.all_cpp.final; \
+ for file in kbibtexshell.cpp main.cpp ; do \
+ echo "#include \"$$file\"" >> kbibtex.all_cpp.files; \
+ test ! -f $(srcdir)/$$file || egrep '^#pragma +implementation' $(srcdir)/$$file >> kbibtex.all_cpp.final; \
+ done; \
+ cat kbibtex.all_cpp.final kbibtex.all_cpp.files > kbibtex.all_cpp.cpp; \
+ rm -f kbibtex.all_cpp.final kbibtex.all_cpp.files
+
+#>+ 3
+clean-final:
+ -rm -f libkbibtexpart_la.all_cpp.cpp kbibtex.all_cpp.cpp
+
+#>+ 3
+final:
+ $(MAKE) libkbibtexpart_la_OBJECTS="$(libkbibtexpart_la_final_OBJECTS)" kbibtex_OBJECTS="$(kbibtex_final_OBJECTS)" all-am
+
+#>+ 3
+final-install:
+ $(MAKE) libkbibtexpart_la_OBJECTS="$(libkbibtexpart_la_final_OBJECTS)" kbibtex_OBJECTS="$(kbibtex_final_OBJECTS)" install-am
+
+#>+ 3
+no-final:
+ $(MAKE) libkbibtexpart_la_OBJECTS="$(libkbibtexpart_la_nofinal_OBJECTS)" kbibtex_OBJECTS="$(kbibtex_nofinal_OBJECTS)" all-am
+
+#>+ 3
+no-final-install:
+ $(MAKE) libkbibtexpart_la_OBJECTS="$(libkbibtexpart_la_nofinal_OBJECTS)" kbibtex_OBJECTS="$(kbibtex_nofinal_OBJECTS)" install-am
+
+#>+ 3
+kde-rpo-clean:
+ -rm -f *.rpo
+
+#>+ 121
+idsuggestionswidget.lo: idsuggestionswidget.moc
+idsuggestionswidget.o: idsuggestionswidget.moc
+settingskeyword.lo: settingskeyword.moc
+sidebar.o: sidebar.moc
+kbibtex_part.lo: kbibtex_part.moc
+settingssearchurl.lo: settingssearchurl.moc
+sidebar.lo: sidebar.moc
+settingsidsuggestions.lo: settingsidsuggestions.moc
+fieldlistview.o: fieldlistview.moc
+webqueryz3950.o: webqueryz3950.moc
+webquerybibsonomy.lo: webquerybibsonomy.moc
+kbibtex_part.o: kbibtex_part.moc
+webquerydblp.lo: webquerydblp.moc
+entrywidgetpublication.lo: entrywidgetpublication.moc
+settingsuserdefinedinput.o: settingsuserdefinedinput.moc
+kbibtexshell.lo: kbibtexshell.moc
+documentwidget.o: documentwidget.moc
+findduplicates.o: findduplicates.moc
+nmcheck-am: nmcheck
+entrywidgetother.o: entrywidgetother.moc
+webquerypubmed.lo: webquerypubmed.moc
+fileexportertoolchain.lo: fileexportertoolchain.moc
+entrywidgetother.lo: entrywidgetother.moc
+fileexportertoolchain.o: fileexportertoolchain.moc
+settingsz3950.lo: settingsz3950.moc
+mergeelements.lo: mergeelements.moc
+webqueryzmath.lo: webqueryzmath.moc
+fieldlineedit.lo: fieldlineedit.moc
+file.o: file.moc
+entrywidgetexternal.o: entrywidgetexternal.moc
+valuewidget.lo: valuewidget.moc
+commentwidget.o: commentwidget.moc
+entrywidgetsource.lo: entrywidgetsource.moc
+entrywidgetpublication.o: entrywidgetpublication.moc
+entrywidgetmisc.o: entrywidgetmisc.moc
+settingsfileio.lo: settingsfileio.moc
+entrywidget.o: entrywidget.moc
+webqueryieeexplore.o: webqueryieeexplore.moc
+webqueryciteseerx.o: webqueryciteseerx.moc
+documentsourceview.lo: documentsourceview.moc
+settingssearchurl.o: settingssearchurl.moc
+fieldlistview.lo: fieldlistview.moc
+webqueryamatex.o: webqueryamatex.moc
+webqueryz3950.lo: webqueryz3950.moc
+fileexporter.lo: fileexporter.moc
+entrywidgetuserdefined.o: entrywidgetuserdefined.moc
+entrywidget.lo: entrywidget.moc
+webquerymathscinet.lo: webquerymathscinet.moc
+fileimporterbibutils.lo: fileimporterbibutils.moc
+searchbar.lo: searchbar.moc
+kbibtexshell.o: kbibtexshell.moc
+fileexporterbibutils.o: fileexporterbibutils.moc
+entrywidgetkeyword.lo: entrywidgetkeyword.moc
+fieldlineedit.o: fieldlineedit.moc
+mergeelements.o: mergeelements.moc
+webqueryieeexplore.lo: webqueryieeexplore.moc
+webquerycsb.lo: webquerycsb.moc
+webquerysciencedirect.o: webquerysciencedirect.moc
+macrowidget.o: macrowidget.moc
+webqueryspireshep.o: webqueryspireshep.moc
+webquerycitebase.o: webquerycitebase.moc
+webqueryspireshep.lo: webqueryspireshep.moc
+webquerydblp.o: webquerydblp.moc
+entrywidgettitle.o: entrywidgettitle.moc
+webqueryciteseerx.lo: webqueryciteseerx.moc
+webquerysciencedirect.lo: webquerysciencedirect.moc
+entrywidgetmisc.lo: entrywidgetmisc.moc
+webquerycsb.o: webquerycsb.moc
+webquerygooglescholar.o: webquerygooglescholar.moc
+fileexporter.o: fileexporter.moc
+preamblewidget.lo: preamblewidget.moc
+fileimporterexternal.o: fileimporterexternal.moc
+settingsdlg.o: settingsdlg.moc
+documentsourceview.o: documentsourceview.moc
+documentlistview.o: documentlistview.moc
+findduplicates.lo: findduplicates.moc
+fileimporter.lo: fileimporter.moc
+settingsediting.lo: settingsediting.moc
+settingsuserdefinedinput.lo: settingsuserdefinedinput.moc
+settingsidsuggestions.o: settingsidsuggestions.moc
+entrywidgetkeyword.o: entrywidgetkeyword.moc
+preamblewidget.o: preamblewidget.moc
+settingsediting.o: settingsediting.moc
+fileimporterexternal.lo: fileimporterexternal.moc
+entrywidgetauthor.lo: entrywidgetauthor.moc
+entrywidgetsource.o: entrywidgetsource.moc
+documentwidget.lo: documentwidget.moc
+macrowidget.lo: macrowidget.moc
+webquerypubmed.o: webquerypubmed.moc
+webqueryamatex.lo: webqueryamatex.moc
+entrywidgetuserdefined.lo: entrywidgetuserdefined.moc
+webquery.lo: webquery.moc
+fileimporter.o: fileimporter.moc
+webquery.o: webquery.moc
+settingsz3950.o: settingsz3950.moc
+webquerymathscinet.o: webquerymathscinet.moc
+documentlistview.lo: documentlistview.moc
+settingsfileio.o: settingsfileio.moc
+fileexporterexternal.lo: fileexporterexternal.moc
+entrywidgettitle.lo: entrywidgettitle.moc
+file.lo: file.moc
+webquerygooglescholar.lo: webquerygooglescholar.moc
+webquerybibsonomy.o: webquerybibsonomy.moc
+nmcheck:
+entrywidgetauthor.o: entrywidgetauthor.moc
+fileimporterbibutils.o: fileimporterbibutils.moc
+fileexporterexternal.o: fileexporterexternal.moc
+settingsdlg.lo: settingsdlg.moc
+entrywidgettab.o: entrywidgettab.moc
+entrywidgettab.lo: entrywidgettab.moc
+settingskeyword.o: settingskeyword.moc
+webqueryarxiv.lo: webqueryarxiv.moc
+fileexporterbibutils.lo: fileexporterbibutils.moc
+searchbar.o: searchbar.moc
+entrywidgetexternal.lo: entrywidgetexternal.moc
+valuewidget.o: valuewidget.moc
+webquerycitebase.lo: webquerycitebase.moc
+webqueryarxiv.o: webqueryarxiv.moc
+webqueryzmath.o: webqueryzmath.moc
+commentwidget.lo: commentwidget.moc
diff --git a/src/comment.cpp b/src/comment.cpp
new file mode 100644
index 0000000..dcf0a58
--- /dev/null
+++ b/src/comment.cpp
@@ -0,0 +1,93 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include <comment.h>
+#include <xsltransform.h>
+
+namespace BibTeX
+{
+
+ Comment::Comment( const QString& text, bool useCommand ) : Element(), m_text( text ), m_useCommand( useCommand )
+ {
+ // nothing
+ }
+
+ Comment::Comment( Comment *other )
+ {
+ m_text = other->m_text;
+ m_useCommand = other->m_useCommand;
+ }
+
+ Comment::~Comment()
+ {
+ // nothing
+ }
+
+ QString Comment::text() const
+ {
+ return m_text;
+ }
+
+ void Comment::setText( const QString &text )
+ {
+ m_text = text;
+ }
+
+ bool Comment::useCommand() const
+ {
+ return m_useCommand;
+ }
+
+ void Comment::setUseCommand( bool useCommand )
+ {
+ m_useCommand = useCommand;
+ }
+
+ bool Comment::containsPattern( const QString& pattern, EntryField::FieldType fieldType, FilterType filterType, bool caseSensitive ) const
+ {
+ if ( filterType == ftExact )
+ {
+ /** check for exact match */
+ return fieldType == EntryField::ftUnknown && m_text.contains( pattern, caseSensitive );
+ }
+ else
+ {
+ /** for each word in the search pattern ... */
+ QStringList words = QStringList::split( QRegExp( "\\s+" ), pattern );
+ unsigned int hits = 0;
+ for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it )
+ {
+ /** check if word is contained in text */
+ if ( fieldType == EntryField::ftUnknown && m_text.contains( *it, caseSensitive ) )
+ ++hits;
+ }
+
+ /** return success depending on filter type and number of hits */
+ return ( ( filterType == ftAnyWord && hits > 0 ) || ( filterType == ftEveryWord && hits == words.count() ) );
+ }
+ }
+
+ Element* Comment::clone()
+ {
+ return new Comment( this );
+ }
+}
diff --git a/src/comment.h b/src/comment.h
new file mode 100644
index 0000000..f259daf
--- /dev/null
+++ b/src/comment.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXCOMMENT_H
+#define BIBTEXCOMMENT_H
+
+#include <element.h>
+
+namespace BibTeX
+{
+
+ class Comment : public Element
+ {
+ public:
+ Comment( const QString &text, bool useCommand = false );
+ Comment( Comment *other );
+ virtual ~Comment();
+
+ QString text() const;
+ void setText( const QString &text );
+ bool useCommand() const;
+ void setUseCommand( bool useCommand );
+
+ bool containsPattern( const QString& pattern, EntryField::FieldType fieldType = EntryField::ftUnknown, FilterType filterType = BibTeX::Element::ftExact, bool caseSensitive = FALSE ) const;
+ Element* clone();
+
+ private:
+ QString m_text;
+ bool m_useCommand;
+ };
+
+}
+#endif
diff --git a/src/commentwidget.cpp b/src/commentwidget.cpp
new file mode 100644
index 0000000..09d371f
--- /dev/null
+++ b/src/commentwidget.cpp
@@ -0,0 +1,98 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlabel.h>
+#include <qmultilineedit.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <kdialogbase.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <comment.h>
+#include <element.h>
+
+#include "commentwidget.h"
+
+namespace KBibTeX
+{
+ CommentWidget::CommentWidget( BibTeX::Comment *comment, bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_comment( comment ), m_isReadOnly( isReadOnly )
+ {
+ setupGUI();
+ getCommentData();
+ m_multiLineEdit->setReadOnly( isReadOnly );
+ }
+
+
+ CommentWidget::~CommentWidget()
+ {
+ // nothing
+ }
+
+ void CommentWidget::setupGUI()
+ {
+ setMinimumWidth( 384 );
+ QVBoxLayout * layout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "Co&mment:" ), this );
+ layout->addWidget( label );
+
+ m_multiLineEdit = new QMultiLineEdit( this );
+ m_multiLineEdit->setFont( KGlobalSettings::fixedFont() );
+ layout->addWidget( m_multiLineEdit );
+ label->setBuddy( m_multiLineEdit );
+ m_multiLineEdit->setReadOnly( m_isReadOnly );
+
+ m_checkboxUseCommand = new QCheckBox( i18n( "&Use @Comment for comment instead of plain text" ), this );
+ layout->addWidget( m_checkboxUseCommand );
+ }
+
+ void CommentWidget::getCommentData()
+ {
+ m_multiLineEdit->setText( m_comment->text() );
+ m_checkboxUseCommand->setChecked( m_comment->useCommand() );
+ }
+
+ void CommentWidget::setCommentData()
+ {
+ m_comment->setText( m_multiLineEdit->text() );
+ m_comment->setUseCommand( m_checkboxUseCommand->isChecked() );
+ }
+
+ QDialog::DialogCode CommentWidget::execute( BibTeX::Comment *comment, bool isReadOnly, QWidget *parent, const char *name )
+ {
+ KDialogBase * dlg = new KDialogBase( parent, name, true, i18n( "Edit BibTeX Comment" ), KDialogBase::Ok | KDialogBase::Cancel );
+ CommentWidget* ui = new CommentWidget( comment, isReadOnly, dlg, "kbibtex::commentwidget" );
+ dlg->setMainWidget( ui );
+
+ QDialog::DialogCode result = ( QDialog::DialogCode ) dlg->exec();
+ if ( !isReadOnly && result == QDialog::Accepted )
+ ui->setCommentData();
+
+ delete( ui );
+ delete( dlg );
+
+ return result;
+ }
+}
+
+#include "commentwidget.moc"
+
diff --git a/src/commentwidget.h b/src/commentwidget.h
new file mode 100644
index 0000000..16ac051
--- /dev/null
+++ b/src/commentwidget.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef COMMENTWIDGET_H
+#define COMMENTWIDGET_H
+
+#include <qwidget.h>
+#include <qdialog.h>
+
+#include <comment.h>
+
+class QMultiLineEdit;
+class QCheckBox;
+
+namespace KBibTeX
+{
+ class CommentWidget : public QWidget
+ {
+ Q_OBJECT
+ public:
+ CommentWidget( BibTeX::Comment *comment, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~CommentWidget();
+
+ static QDialog::DialogCode execute( BibTeX::Comment *comment, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+
+ private:
+ BibTeX::Comment* m_comment;
+ QCheckBox *m_checkboxUseCommand;
+ QMultiLineEdit *m_multiLineEdit;
+ bool m_isReadOnly;
+
+ void setupGUI();
+ void setCommentData();
+ void getCommentData();
+ };
+
+}
+
+#endif
diff --git a/src/documentlistview.cpp b/src/documentlistview.cpp
new file mode 100644
index 0000000..61ff980
--- /dev/null
+++ b/src/documentlistview.cpp
@@ -0,0 +1,768 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qfile.h>
+#include <qvaluelist.h>
+#include <qcursor.h>
+#include <qbuffer.h>
+#include <qlistview.h>
+#include <qclipboard.h>
+#include <qheader.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kio/netaccess.h>
+#include <ktempfile.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kurldrag.h>
+#include <kactionclasses.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kmessagebox.h>
+#include <kprogress.h>
+#include <kiconloader.h>
+
+#include <kbibtex_part.h>
+#include <documentlistviewitem.h>
+#include <file.h>
+#include <fileimporterbibutils.h>
+#include <fileimporterris.h>
+#include <fileimporterbibtex.h>
+#include <fileexporterbibtex.h>
+#include <element.h>
+#include <entry.h>
+#include <macro.h>
+#include <comment.h>
+#include <preamblewidget.h>
+#include <preamble.h>
+#include <entrywidget.h>
+#include <commentwidget.h>
+#include <macrowidget.h>
+#include <settings.h>
+#include <encoderlatex.h>
+
+#include "documentlistview.h"
+
+namespace KBibTeX
+{
+ DocumentListView::DocumentListView( KBibTeX::DocumentWidget *docWidget, bool isReadOnly, QWidget *parent, const char *name )
+ : KListView( parent, name ), m_docWidget( docWidget ), m_bibtexFile( NULL ), m_contextMenu( NULL ), m_headerMenu( NULL ), m_isReadOnly( isReadOnly ), m_newElementCounter( 1 )
+ {
+ setAllColumnsShowFocus( true );
+ setShowSortIndicator( true );
+ setSelectionMode( QListView::Extended );
+ header() ->setClickEnabled( TRUE );
+ header() ->setMovingEnabled( TRUE );
+ buildColumns();
+
+ setDragEnabled( true );
+ // setDragAutoScroll( true );
+ setAcceptDrops( TRUE );
+ setDropVisualizer( TRUE );
+
+ connect( header(), SIGNAL( clicked( int ) ), this, SLOT( setSortingColumn( int ) ) );
+ connect( this, SIGNAL( contextMenu( KListView *, QListViewItem *, const QPoint & ) ), this, SLOT( showBibtexListContextMenu( KListView *, QListViewItem *, const QPoint & ) ) );
+ connect( this, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ), this, SLOT( slotDoubleClick( QListViewItem* ) ) );
+ connect( this, SIGNAL( dropped( QDropEvent*, QListViewItem* ) ), this, SLOT( slotDropped( QDropEvent*, QListViewItem* ) ) );
+ }
+
+ DocumentListView::~DocumentListView()
+ {
+ // nothing
+ }
+
+ void DocumentListView::setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client )
+ {
+ m_contextMenu = static_cast<KPopupMenu*>( factory -> container( "popup_bibtexlist", client ) );
+ }
+
+ bool DocumentListView::setBibTeXFile( BibTeX::File *bibtexFile )
+ {
+ m_bibtexFile = bibtexFile;
+ setItems();
+
+ return TRUE;
+ }
+
+ BibTeX::File* DocumentListView::getBibTeXFile( )
+ {
+ return m_bibtexFile;
+ }
+
+ void DocumentListView::setItems()
+ {
+ QApplication::setOverrideCursor( Qt::waitCursor );
+
+ KProgressDialog *prgDlg = new KProgressDialog( this, "prgDlg", i18n( "List View" ), i18n( "Updating main view ..." ), TRUE );
+ prgDlg->show();
+ KProgress *progress = prgDlg->progressBar();
+ progress->setTotalSteps( m_bibtexFile->count() );
+
+ bool update = viewport()->isUpdatesEnabled();
+ viewport()->setUpdatesEnabled( FALSE );
+ int sortCol = sortColumn();
+ setSortColumn( -1 );
+
+ clear();
+ for ( unsigned int i = 0; i < m_bibtexFile->count(); i++ )
+ {
+ BibTeX::Element *element = m_bibtexFile->at( i );
+ new DocumentListViewItem( m_bibtexFile, element, this );
+ progress->setProgress( i );
+
+ if ( i % 43 == 23 )
+ kapp->processEvents();
+ }
+
+ viewport()->setUpdatesEnabled( update );
+ setSortColumn( sortCol );
+ triggerUpdate();
+ delete prgDlg;
+
+ updateVisiblity();
+
+ QApplication::restoreOverrideCursor();
+ }
+
+ void DocumentListView::insertItems( BibTeX::File *items, KBibTeX::DocumentListViewItem *after )
+ {
+ for ( BibTeX::File::ElementList::iterator it = items->begin(); it != items->end(); it++ )
+ after = insertItem( *it, after );
+ }
+
+ KBibTeX::DocumentListViewItem * DocumentListView::insertItem( BibTeX::Element *item, KBibTeX::DocumentListViewItem *after )
+ {
+ if ( m_bibtexFile == NULL )
+ m_bibtexFile = new BibTeX::File();
+
+ BibTeX::Element *element = NULL;
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry *>( item );
+ if ( entry != NULL )
+ {
+ BibTeX::Entry *newEntry = new BibTeX::Entry( entry );
+ if ( m_bibtexFile->containsKey( newEntry->id() ) )
+ {
+ int counter = 0;
+ QString newId = QString( newEntry->id() ).append( '_' ).append( QString::number( ++counter ) );
+ while ( m_bibtexFile->containsKey( newId ) )
+ newId = QString( newEntry->id() ).append( '_' ).append( QString::number( ++counter ) );
+ newEntry->setId( newId );
+ }
+ element = newEntry;
+ }
+ else
+ element = item->clone();
+
+
+ m_bibtexFile->appendElement( element, after == NULL ? NULL : after->element() );
+ after = new DocumentListViewItem( m_bibtexFile, element, this, after );
+ after->setUnreadStatus( TRUE );
+ updateVisiblity( after );
+ m_unreadItems.append( after );
+
+ emit modified();
+ QTimer::singleShot( 3500, this, SLOT( makeNewItemsUnread() ) );
+
+ return after;
+ }
+
+ void DocumentListView::insertItem( BibTeX::Element *item )
+ {
+ insertItem( item, NULL );
+ }
+
+ void DocumentListView::updateVisiblity()
+ {
+ QListViewItemIterator it( this );
+ while ( it.current() )
+ {
+ DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ updateVisiblity( kblvi );
+ it++;
+ }
+ }
+
+ void DocumentListView::updateVisiblity( KBibTeX::DocumentListViewItem *item )
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ BibTeX::Element *element = item->element();
+ bool notFiltered = m_filter.isEmpty() || element ->containsPattern( m_filter, m_filterFieldType, m_filterType );
+
+ BibTeX::Macro *macro = dynamic_cast<BibTeX::Macro*>( element );
+ if ( macro != NULL )
+ item->setVisible( notFiltered && settings->editing_ShowMacros );
+ else
+ {
+ BibTeX::Comment *comment = dynamic_cast<BibTeX::Comment*>( element );
+ if ( comment != NULL )
+ item->setVisible( notFiltered && settings->editing_ShowComments );
+ else
+ item->setVisible( notFiltered );
+ }
+ }
+
+ void DocumentListView::deferredInitialization()
+ {
+ connect( header(), SIGNAL( sizeChange( int, int, int ) ), this, SLOT( saveColumnWidths() ) );
+ connect( header(), SIGNAL( indexChange( int, int, int ) ), this, SLOT( saveColumnIndex() ) );
+ }
+
+ void DocumentListView::restoreState()
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ if ( settings->editing_UseSpecialFont )
+ setFont( settings->editing_SpecialFont );
+ else
+ setFont( KGlobalSettings::generalFont() );
+ header() ->setFont( KGlobalSettings::generalFont() );
+
+ restoreColumnIndex();
+ restoreColumnWidths();
+ restoreSortingColumn();
+ }
+
+ void DocumentListView::setViewShowColumnsMenu( KActionMenu *actionMenu )
+ {
+ if ( m_headerMenu == NULL )
+ {
+ m_headerMenu = actionMenu->popupMenu();
+ m_headerMenu->insertTitle( i18n( "Show Columns" ) );
+ m_headerMenu->setCheckable( TRUE );
+ connect( m_headerMenu, SIGNAL( activated( int ) ), this, SLOT( activateShowColumnMenu( int ) ) );
+
+ Settings * settings = Settings::self( m_bibtexFile );
+
+ int item = m_headerMenu->insertItem( i18n( "Element Type" ), 0 );
+ m_headerMenu->setItemChecked( item, settings->editing_MainListColumnsWidth[ 0 ] > 0 );
+ m_headerMenu->insertSeparator();
+
+ for ( int i = 0; i <= ( int ) BibTeX::EntryField::ftYear - ( int ) BibTeX::EntryField::ftAbstract; i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType )( i + ( int ) BibTeX::EntryField::ftAbstract );
+ QString label = Settings::fieldTypeToI18NString( fieldType );
+ item = m_headerMenu->insertItem( label, ( int ) fieldType + 2 );
+ m_headerMenu->setItemChecked( item, settings->editing_MainListColumnsWidth[ i + 2 ] > 0 );
+ }
+ }
+ }
+
+ void DocumentListView::deleteSelected()
+ {
+ QListViewItemIterator it( this, QListViewItemIterator::Selected | QListViewItemIterator::Visible );
+ if ( it.current() == NULL ) return;
+
+ QListViewItem *above = it.current() ->itemAbove();
+ QValueList<DocumentListViewItem*> toBeDeleted;
+ while ( it.current() )
+ {
+ DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ toBeDeleted.append( kblvi );
+ it++;
+ }
+
+ for ( QValueList<DocumentListViewItem*>::Iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it )
+ {
+ m_bibtexFile->deleteElement(( *it )->element() );
+ takeItem( *it );
+ delete( *it );
+ }
+
+ if ( above )
+ ensureItemVisible( above );
+
+ emit modified();
+ }
+
+ const QValueList<BibTeX::Element*> DocumentListView::selectedItems()
+ {
+ QValueList<BibTeX::Element*> result;
+
+ QListViewItemIterator it( this, QListViewItemIterator::Selected );
+ while ( it.current() )
+ {
+ DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ if ( kblvi->isVisible() )
+ result.append( kblvi->element() );
+ it++;
+ }
+
+ return result;
+ }
+
+ QString DocumentListView::selectedToBibTeXText()
+ {
+ BibTeX::FileExporterBibTeX *exporter = new BibTeX::FileExporterBibTeX();
+ exporter->setEncoding( "latex" );
+
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ QValueList<BibTeX::Element*> selectedElements = selectedItems();
+ for ( QValueList<BibTeX::Element*>::iterator it = selectedElements.begin(); it != selectedElements.end(); ++it )
+ exporter->save( &buffer, *it );
+ buffer.close();
+ delete exporter;
+
+ buffer.open( IO_ReadOnly );
+ QTextStream in( &buffer );
+ in.setEncoding( QTextStream::UnicodeUTF8 );
+ QString result = in.read();
+ buffer.close();
+
+ return result;
+ }
+
+ QString DocumentListView::selectedToBibTeXRefs()
+ {
+ QString refs;
+ QValueList<BibTeX::Element*> selectedElements = selectedItems();
+ for ( QValueList<BibTeX::Element*>::iterator it = selectedElements.begin(); it != selectedElements.end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry == NULL ) continue;
+
+ if ( !refs.isEmpty() )
+ refs.append( "," );
+ refs.append( entry->id() );
+ }
+ return QString( "\\cite{%1}" ).arg( refs );
+ }
+
+ void DocumentListView::copy()
+ {
+ kapp->clipboard() ->setText( selectedToBibTeXText() );
+ }
+
+ void DocumentListView::copyReferences()
+ {
+ kapp->clipboard() ->setText( selectedToBibTeXRefs() );
+ }
+
+ void DocumentListView::cut()
+ {
+ copy();
+ deleteSelected();
+ }
+
+ bool DocumentListView::paste()
+ {
+ DocumentListViewItem * dlvi = dynamic_cast<KBibTeX::DocumentListViewItem *>( selectedItem() );
+ if ( dlvi == NULL )
+ dlvi = dynamic_cast<KBibTeX::DocumentListViewItem *>( currentItem() );
+
+ QString clipboardText = kapp->clipboard() ->text();
+ return paste( clipboardText, dlvi );
+ }
+
+ bool DocumentListView::paste( const QString& text, DocumentListViewItem *at )
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+
+ /** check if clipboard contains BibTeX content */
+ if ( BibTeX::FileImporterBibTeX::guessCanDecode( text ) )
+ {
+ BibTeX::FileImporter *importer = new BibTeX::FileImporterBibTeX( settings->editing_FirstNameFirst );
+ BibTeX::File *clipboardData = importer->load( text );
+ delete importer;
+
+ if ( clipboardData != NULL )
+ {
+ insertItems( clipboardData, at );
+ delete clipboardData;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && BibTeX::FileImporterBibUtils::guessCanDecode( text ) )
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ BibTeX::File::FileFormat inputFormat = BibTeX::FileImporterBibUtils::guessInputFormat( text );
+ BibTeX::FileImporter *importer = NULL;
+ if ( inputFormat == BibTeX::File::formatRIS && !settings->fileIO_useBibUtils )
+ importer = new BibTeX::FileImporterRIS();
+ else
+ importer = new BibTeX::FileImporterBibUtils( inputFormat );
+ BibTeX::File *clipboardData = importer->load( text );
+ delete importer;
+
+ if ( clipboardData != NULL )
+ {
+ insertItems( clipboardData, at );
+ delete clipboardData;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else if ( BibTeX::FileImporterRIS::guessCanDecode( text ) )
+ {
+ BibTeX::FileImporter *importer = new BibTeX::FileImporterRIS( );
+ BibTeX::File *clipboardData = importer->load( text );
+ delete importer;
+
+ if ( clipboardData != NULL )
+ {
+ insertItems( clipboardData, at );
+ delete clipboardData;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else
+ {
+ /** Decoding the paste text as bibtex failed. Maybe the user wants
+ to paste the text as link address, abstract, etc... */
+ if ( !at ) // no list view item selected to add data to
+ return FALSE;
+
+ // fetch BibTeX element from current list view item
+ BibTeX::Entry * element = dynamic_cast<BibTeX::Entry*>( at->element() );
+ if ( ! element )
+ return FALSE;
+
+ // build popup menu
+ KPopupMenu * popup = new KPopupMenu( this, "pastePopup" );
+ popup->insertTitle( i18n( "Paste text as..." ) );
+ for ( int i = ( int ) BibTeX::EntryField::ftAuthor; i <= ( int ) BibTeX::EntryField::ftYear; i++ )
+ {
+ BibTeX::EntryField::FieldType ft = ( BibTeX::EntryField::FieldType ) i;
+ popup->insertItem( Settings::fieldTypeToI18NString( ft ), i );
+ }
+ popup->insertSeparator();
+ QIconSet cancelPixmap = KGlobal::iconLoader() ->loadIconSet( "cancel", KIcon::Small );
+ int cancelId = popup->insertItem( cancelPixmap, i18n( "Cancel" ) );
+
+ // show popup menu
+ int selectedId = popup->exec( QCursor::pos() );
+ if ( selectedId == cancelId || selectedId == -1 )
+ return FALSE; // cancel menu
+
+ // determine field to add clipboard value to
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType ) selectedId;
+ BibTeX::EntryField * field = element->getField( fieldType );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( fieldType );
+ element->addField( field );
+ }
+ else if ( field->value() != NULL )
+ delete field->value();
+
+ QString encodedText = BibTeX::EncoderLaTeX::currentEncoderLaTeX() ->encode( text );
+
+ // create new value from clipboard's content
+ BibTeX::Value * value = new BibTeX::Value();
+ if ( fieldType == BibTeX::EntryField::ftAuthor || fieldType == BibTeX::EntryField::ftEditor )
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ value->items.append( new BibTeX::PersonContainer( encodedText, settings->editing_FirstNameFirst ) );
+ }
+ else if ( fieldType == BibTeX::EntryField::ftKeywords )
+ value->items.append( new BibTeX::KeywordContainer( encodedText ) );
+ else
+ value->items.append( new BibTeX::PlainText( encodedText ) );
+
+ field->setValue( value );
+
+ return TRUE;
+ }
+ }
+
+ void DocumentListView::selectAll()
+ {
+ QListView::selectAll( true );
+ }
+
+ /* void DocumentListView::sendSelectedToLyx()
+ {
+ QStringList refsToSend;
+ QListViewItemIterator it( this, QListViewItemIterator::Selected );
+ while ( it.current() )
+ {
+ DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( kblvi->element() );
+ if ( entry != NULL && kblvi->isVisible() )
+ refsToSend.append( entry->id() );
+ it++;
+ }
+
+ Settings * settings = Settings::self( m_bibtexFile );
+ QString lyxPipeFilename = settings->detectLyXInPipe();
+ kdDebug() << "sendSelectedToLyx: lyxPipeFilename= " << lyxPipeFilename << endl;
+ QFile pipe( lyxPipeFilename );
+ if ( pipe.exists() && pipe.open( IO_WriteOnly ) )
+ {
+ QTextStream * writer = new QTextStream( &pipe );
+ QString msg = "LYXCMD:kbibtex:citation-insert:" + refsToSend.join( "," );
+ *writer << msg << endl;
+ delete writer;
+ pipe.close();
+ }
+ else
+ KMessageBox::error( this, ( lyxPipeFilename.isEmpty() ? i18n( "Cannot establish a link to LyX" ) : QString( i18n( "Cannot establish a link to LyX using the pipe \"%1\"" ) ).arg( lyxPipeFilename ) ) + i18n( "\nMaybe LyX is not running?" ), i18n( "Error communicating with LyX" ) );
+ }*/
+
+ void DocumentListView::slotDoubleClick( QListViewItem *item )
+ {
+ DocumentListViewItem *dlvi = dynamic_cast<DocumentListViewItem*>( item );
+ if ( dlvi != NULL ) emit executed( dlvi );
+ }
+
+ void DocumentListView::filter( const QString & text, BibTeX::Element::FilterType filterType, BibTeX::EntryField::FieldType fieldType )
+ {
+ m_filter = text;
+ m_filterType = filterType;
+ m_filterFieldType = fieldType;
+ updateVisiblity();
+ }
+
+ void DocumentListView::setReadOnly( bool isReadOnly )
+ {
+ m_isReadOnly = isReadOnly;
+ }
+
+ void DocumentListView::activateShowColumnMenu( int id )
+ {
+ if ( id >= 0 )
+ {
+ if ( columnWidth( id ) > 0 )
+ {
+ hideColumn( id );
+ m_headerMenu->setItemChecked( id, FALSE );
+ }
+ else
+ {
+ showColumn( id );
+ m_headerMenu->setItemChecked( id, TRUE );
+ }
+ }
+ }
+
+ void DocumentListView::showBibtexListContextMenu( KListView *, QListViewItem *, const QPoint & p )
+ {
+ if ( m_contextMenu != NULL )
+ {
+ emit selectionChanged();
+ m_contextMenu->popup( p );
+ }
+ }
+
+ void DocumentListView::setSortingColumn( int column )
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ settings->editing_MainListSortingColumn = column;
+ settings->editing_MainListSortingOrder = ( sortOrder() == Qt::Ascending ) ? 1 : -1;
+ }
+
+ bool DocumentListView::acceptDrag( QDropEvent * event ) const
+ {
+ if ( event->source() == this ) return false;
+ return QTextDrag::canDecode( event ) || QUriDrag::canDecode( event );
+ }
+
+ void DocumentListView::startDrag()
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ QDragObject *d = new QTextDrag( settings->editing_DragAction == Settings::COPYREFERENCE ? selectedToBibTeXRefs() : selectedToBibTeXText(), this );
+ d->dragCopy();
+ }
+ void DocumentListView::saveColumnIndex()
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ QHeader *hdr = header();
+
+ for ( int i = 0; i < columns(); i++ )
+ settings->editing_MainListColumnsIndex[ i ] = hdr->mapToIndex( i );
+ }
+
+ void DocumentListView::restoreColumnIndex()
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ QHeader *hdr = header();
+
+ for ( int i = 0; i < columns(); i++ )
+ hdr->moveSection( i, settings->editing_MainListColumnsIndex[ i ] );
+ }
+
+ void DocumentListView::saveColumnWidths( int col )
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+
+ int from = col == -1 ? 0 : col, to = col == -1 ? columns() : ( col + 1 );
+
+ for ( int i = from; i < to; i++ )
+ {
+ if ( columnWidthMode( i ) == QListView::Manual )
+ settings->editing_MainListColumnsWidth[ i ] = columnWidth( i );
+ else
+ settings->editing_MainListColumnsWidth[ i ] = 0xffff;
+ }
+ }
+
+ void DocumentListView::restoreColumnWidths()
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+
+ for ( int col = 0; col < columns(); col++ )
+ {
+ int colWidth = settings->editing_MainListColumnsWidth[ col ];
+ showColumn( col, colWidth );
+ }
+ }
+
+ void DocumentListView::restoreSortingColumn()
+ {
+ Settings * settings = Settings::self( m_bibtexFile );
+ setSortColumn( settings->editing_MainListSortingColumn );
+ setSortOrder( settings->editing_MainListSortingOrder > 0 ? Qt::Ascending : Qt::Descending );
+ }
+
+ void DocumentListView::makeNewItemsUnread()
+ {
+ for ( QValueList<DocumentListViewItem*>::ConstIterator it = m_unreadItems.begin() ; it != m_unreadItems.end(); ++it )
+ {
+ ( *it ) ->setUnreadStatus( FALSE );
+ ( *it ) ->repaint();
+ }
+
+ m_unreadItems.clear();
+ }
+
+ void DocumentListView::slotDropped( QDropEvent * event, QListViewItem * item )
+ {
+ QString text;
+ QStrList urlList;
+
+ if ( QTextDrag::decode( event, text ) && KURL( text ).isValid() )
+ urlList.append( text );
+
+ if ( !urlList.isEmpty() || QUriDrag::decode( event, urlList ) )
+ {
+ QString url = urlList.at( 0 );
+ QString tmpFile;
+ if ( ! KIO::NetAccess::download( url, tmpFile, 0 ) )
+ {
+ KMessageBox::error( this, KIO::NetAccess::lastErrorString() );
+ return ;
+ }
+ QFile f( tmpFile );
+ if ( ! f.open( IO_ReadOnly ) )
+ {
+ KMessageBox::error( this, f.errorString() );
+ KIO::NetAccess::removeTempFile( tmpFile );
+ return ;
+ }
+ QByteArray ba = f.readAll();
+ text = QString( ba );
+ f.close();
+ KIO::NetAccess::removeTempFile( tmpFile );
+ }
+ else if ( !QTextDrag::decode( event, text ) )
+ return;
+
+ event->accept( TRUE );
+ DocumentListViewItem * dlvi = dynamic_cast<KBibTeX::DocumentListViewItem *>( item );
+
+ paste( text, dlvi );
+ }
+
+ bool DocumentListView::eventFilter( QObject * watched, QEvent * e )
+ {
+ if ( watched == header() )
+ {
+ switch ( e->type() )
+ {
+ case QEvent::MouseButtonPress:
+ {
+ if ( static_cast<QMouseEvent *>( e ) ->button() == RightButton && m_headerMenu != NULL )
+ m_headerMenu->popup( QCursor::pos() );
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ return KListView::eventFilter( watched, e );
+ }
+
+ void DocumentListView::keyPressEvent( QKeyEvent *e )
+ {
+ if ( e->key() == QKeyEvent::Key_Enter || e->key() == QKeyEvent::Key_Return )
+ {
+ DocumentListViewItem *item = dynamic_cast<DocumentListViewItem*>( selectedItem() );
+ if ( item == NULL )
+ item = dynamic_cast<DocumentListViewItem*>( currentItem() );
+ if ( item != NULL )
+ emit executed( item );
+ }
+ else
+ KListView::keyPressEvent( e );
+ }
+
+ void DocumentListView::showColumn( int col, int colWidth )
+ {
+ if ( colWidth == 0xffff )
+ {
+ adjustColumn( col );
+ if ( columnWidth( col ) > width() / 3 )
+ colWidth = width() / 4;
+ if ( columnWidth( col ) < width() / 12 )
+ colWidth = width() / 8;
+ }
+
+ if ( colWidth < 0xffff )
+ setColumnWidth( col, colWidth );
+
+ header() ->setResizeEnabled( colWidth > 0, col );
+ setColumnWidthMode( col, colWidth < 0xffff ? QListView::Manual : QListView::Maximum );
+ saveColumnWidths( col );
+ }
+
+ void DocumentListView::hideColumn( int col )
+ {
+ showColumn( col, 0 );
+ }
+
+ void DocumentListView::buildColumns()
+ {
+ addColumn( i18n( "Element Type" ) );
+ addColumn( i18n( "Entry Id" ) );
+
+ for ( int i = 0; i <= ( int ) BibTeX::EntryField::ftYear - ( int ) BibTeX::EntryField::ftAbstract; i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType )( i + ( int ) BibTeX::EntryField::ftAbstract );
+ QString label = Settings::fieldTypeToI18NString( fieldType );
+ addColumn( label );
+ }
+ }
+}
+
+#include "documentlistview.moc"
diff --git a/src/documentlistview.h b/src/documentlistview.h
new file mode 100644
index 0000000..da2c6c5
--- /dev/null
+++ b/src/documentlistview.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXDOCUMENTLISTVIEW_H
+#define KBIBTEXDOCUMENTLISTVIEW_H
+
+#include <klistview.h>
+#include <kxmlguifactory.h>
+
+#include <fileimporter.h>
+#include <settings.h>
+#include <file.h>
+
+class QString;
+class KURL;
+class KActionMenu;
+class KPopupMenu;
+
+namespace KBibTeX
+{
+ class DocumentWidget;
+ class DocumentListViewItem;
+
+ class DocumentListView : public KListView
+ {
+ Q_OBJECT
+ public:
+ DocumentListView( KBibTeX::DocumentWidget *docWidget, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~DocumentListView();
+
+ void setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client );
+ void setViewShowColumnsMenu( KActionMenu *actionMenu );
+
+ bool setBibTeXFile( BibTeX::File *bibtexFile );
+ BibTeX::File* getBibTeXFile( );
+ KBibTeX::DocumentListViewItem *insertItem( BibTeX::Element *item, KBibTeX::DocumentListViewItem *after );
+
+ void deleteSelected();
+ const QValueList<BibTeX::Element*> selectedItems();
+// void sendSelectedToLyx();
+
+ void updateVisiblity();
+ void updateVisiblity( KBibTeX::DocumentListViewItem *item );
+
+ void deferredInitialization();
+ void restoreState();
+
+ signals:
+ void modified();
+ void executed( DocumentListViewItem* );
+
+ public slots:
+ void copy();
+ void copyReferences();
+ void cut();
+ bool paste();
+ bool paste( const QString& text, DocumentListViewItem *at );
+ void selectAll();
+ void filter( const QString& text, BibTeX::Element::FilterType filterType, BibTeX::EntryField::FieldType fieldType );
+ void setReadOnly( bool isReadOnly );
+ void activateShowColumnMenu( int id );
+
+ void insertItems( BibTeX::File *items, KBibTeX::DocumentListViewItem *after = NULL );
+ void insertItem( BibTeX::Element *item );
+
+ private slots:
+ void slotDoubleClick( QListViewItem * item = NULL );
+ void setSortingColumn( int column );
+ void showBibtexListContextMenu( KListView *, QListViewItem *, const QPoint &p );
+ void slotDropped( QDropEvent* event, QListViewItem* item );
+ void saveColumnIndex();
+ void restoreColumnIndex();
+ void saveColumnWidths( int col = -1 );
+ void restoreColumnWidths();
+ void restoreSortingColumn();
+ void makeNewItemsUnread();
+
+ protected:
+ bool acceptDrag( QDropEvent* e ) const;
+ void startDrag();
+
+ virtual bool eventFilter( QObject *watched, QEvent *e );
+
+ virtual void keyPressEvent( QKeyEvent *e );
+
+ private:
+ static const int maxColumns = 256;
+ KBibTeX::DocumentWidget *m_docWidget;
+ BibTeX::File *m_bibtexFile;
+ KPopupMenu *m_contextMenu;
+ KPopupMenu *m_headerMenu;
+ KActionMenu *m_columnVisibleAction;
+ bool m_isReadOnly;
+ QValueList<DocumentListViewItem*> m_unreadItems;
+
+ QString m_filter;
+ BibTeX::Element::FilterType m_filterType;
+ BibTeX::EntryField::FieldType m_filterFieldType;
+ int m_newElementCounter;
+
+ void setItems();
+ QString selectedToBibTeXText();
+ QString selectedToBibTeXRefs();
+
+ void showColumn( int col, int colWidth = 0xffff );
+ void hideColumn( int col );
+ void buildColumns();
+ };
+}
+
+#endif
diff --git a/src/documentlistviewitem.cpp b/src/documentlistviewitem.cpp
new file mode 100644
index 0000000..7a71873
--- /dev/null
+++ b/src/documentlistviewitem.cpp
@@ -0,0 +1,151 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlistview.h>
+#include <qpainter.h>
+#include <qpen.h>
+
+#include <klocale.h>
+
+#include "documentlistviewitem.h"
+#include "entry.h"
+#include "comment.h"
+#include <preamble.h>
+#include "macro.h"
+
+namespace KBibTeX
+{
+ DocumentListViewItem::DocumentListViewItem( BibTeX::File *file, BibTeX::Element *element, DocumentListView *parent ) : KListViewItem( parent, parent->lastItem() ), m_element( element ), m_bibtexFile( file ), m_parent( parent ), m_unreadStatus( FALSE )
+ {
+ setTexts();
+ }
+
+ DocumentListViewItem::DocumentListViewItem( BibTeX::File *file, BibTeX::Element *element, DocumentListView *parent, QListViewItem *after ) : KListViewItem( parent, after ), m_element( element ), m_bibtexFile( file ), m_parent( parent )
+ {
+ setTexts();
+ }
+
+ DocumentListViewItem::~DocumentListViewItem()
+ {
+ // nothing
+ }
+
+ BibTeX::Element* DocumentListViewItem::element()
+ {
+ return m_element;
+ }
+
+ void DocumentListViewItem::updateItem()
+ {
+ setTexts();
+ }
+
+ void DocumentListViewItem::setUnreadStatus( bool unread )
+ {
+ m_unreadStatus = unread;
+ }
+
+ void DocumentListViewItem::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align )
+ {
+ if ( !p )
+ return ;
+
+ // make unread items bold
+ if ( m_unreadStatus )
+ {
+ QFont f = p->font();
+ f.setBold( TRUE );
+ p->setFont( f );
+ }
+
+ KListViewItem::paintCell( p, cg, column, width, align );
+ }
+
+
+ void DocumentListViewItem::setTexts()
+ {
+ BibTeX::Entry * entry = dynamic_cast<BibTeX::Entry*>( m_element );
+
+ if ( entry )
+ {
+ entry = new BibTeX::Entry( entry );
+ m_bibtexFile->completeReferencedFields( entry );
+
+ if ( entry->entryType() != BibTeX::Entry::etUnknown )
+ setText( 0, BibTeX::Entry::entryTypeToString( entry->entryType() ) );
+ else
+ setText( 0, entry->entryTypeString() );
+ setText( 1, entry->id() );
+
+ for ( int i = 2; i < m_parent->columns(); i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType )( i - 2 + ( int ) BibTeX::EntryField::ftAbstract );
+ BibTeX::EntryField *field = entry->getField( fieldType );
+ BibTeX::Value *value = NULL;
+ if ( field != NULL && (( value = field->value() ) != NULL ) )
+ setText( i, value->text().replace( '{', "" ).replace( '}', "" ).replace( '~', "" ) );
+ else
+ setText( i, "" );
+ }
+
+ delete entry;
+ }
+ else
+ {
+ BibTeX::Comment *comment = dynamic_cast<BibTeX::Comment*>( m_element );
+ if ( comment )
+ {
+ setText( 0, i18n( "Comment" ) );
+ QString text = comment->text();
+ text.replace( '\n', ' ' );
+ setText(( int ) BibTeX::EntryField::ftTitle - ( int ) BibTeX::EntryField::ftAbstract + 2, text );
+ }
+ else
+ {
+ BibTeX::Macro * macro = dynamic_cast<BibTeX::Macro*>( m_element );
+ if ( macro )
+ {
+ setText( 0, i18n( "Macro" ) );
+ setText( 1, macro->key() );
+ BibTeX::Value *value = macro->value();
+ int i = ( int ) BibTeX::EntryField::ftTitle - ( int ) BibTeX::EntryField::ftAbstract + 2;
+ if ( value )
+ setText( i, macro->value() ->text() );
+ else
+ setText( i, "" );
+ }
+ else
+ {
+ BibTeX::Preamble *preamble = dynamic_cast<BibTeX::Preamble*>( m_element );
+ if ( preamble )
+ {
+ setText( 0, i18n( "Preamble" ) );
+ BibTeX::Value *value = preamble->value();
+ int i = ( int ) BibTeX::EntryField::ftTitle - ( int ) BibTeX::EntryField::ftAbstract + 2;
+ if ( value )
+ setText( i, preamble->value() ->text() );
+ else
+ setText( i, "" );
+ }
+
+ }
+ }
+ }
+ }
+}
diff --git a/src/documentlistviewitem.h b/src/documentlistviewitem.h
new file mode 100644
index 0000000..3462fd6
--- /dev/null
+++ b/src/documentlistviewitem.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef DOCUMENTLISTVIEWITEM_H
+#define DOCUMENTLISTVIEWITEM_H
+
+#include <klistview.h>
+
+#include <element.h>
+#include "documentlistview.h"
+
+namespace KBibTeX
+{
+ class DocumentListViewItem : public KListViewItem
+ {
+ public:
+ DocumentListViewItem( BibTeX::File *file, BibTeX::Element *element, DocumentListView *parent );
+ DocumentListViewItem( BibTeX::File *file, BibTeX::Element *element, DocumentListView *parent, QListViewItem *after );
+
+ ~DocumentListViewItem();
+
+ BibTeX::Element* element();
+ void updateItem();
+ void setUnreadStatus( bool unread );
+
+ protected:
+ void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align );
+
+ private:
+ BibTeX::Element *m_element;
+ BibTeX::File *m_bibtexFile;
+ DocumentListView *m_parent;
+ bool m_unreadStatus;
+
+ void setTexts();
+ };
+}
+
+#endif // DOCUMENTLISTVIEWITEM_H
diff --git a/src/documentsourceview.cpp b/src/documentsourceview.cpp
new file mode 100644
index 0000000..0edce91
--- /dev/null
+++ b/src/documentsourceview.cpp
@@ -0,0 +1,380 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qbuffer.h>
+#include <qlayout.h>
+#include <qfile.h>
+
+#include <klibloader.h>
+#include <kxmlguifactory.h>
+#include <kapplication.h>
+#include <klibloader.h>
+#include <kfinddialog.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktrader.h>
+#include <kmimetype.h>
+#include <kservice.h>
+#include <kprogress.h>
+#include <kparts/componentfactory.h>
+#include <ktexteditor/configinterface.h>
+#include <ktexteditor/editorchooser.h>
+#include <ktexteditor/undointerface.h>
+
+#include <fileexporterbibtex.h>
+#include <fileimporterbibtex.h>
+#include <settings.h>
+#include "documentsourceview.h"
+
+namespace KBibTeX
+{
+
+ DocumentSourceView::DocumentSourceView( KBibTeX::DocumentWidget *docWidget, bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_isReadOnly( isReadOnly ), m_docWidget( docWidget ), m_bibtexFile( NULL ), m_document( NULL ), m_view( NULL ), m_progDlg( NULL )
+ {
+ setupGUI();
+
+ readConfig();
+ }
+
+ DocumentSourceView::~DocumentSourceView()
+ {
+ kapp->config() ->sync();
+ }
+
+ /**
+ * Copy the selected text to the clipboard
+ */
+ void DocumentSourceView::copy()
+ {
+ KTextEditor::ClipboardInterface * clip = dynamic_cast<KTextEditor::ClipboardInterface*>( m_view );
+ if ( clip )
+ clip->copy();
+ }
+
+ /**
+ * Cut the selected text to the clipboard
+ */
+ void DocumentSourceView::cut()
+ {
+ KTextEditor::ClipboardInterface * clip = dynamic_cast<KTextEditor::ClipboardInterface*>( m_view );
+ if ( clip )
+ clip->cut();
+ }
+
+ /**
+ * Paste the clipboard's content into the document
+ */
+ bool DocumentSourceView::paste()
+ {
+ KTextEditor::ClipboardInterface * clip = dynamic_cast<KTextEditor::ClipboardInterface*>( m_view );
+ if ( clip )
+ {
+ clip->paste();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ /**
+ * Paste a line of text into the document at the designated position
+ */
+ void DocumentSourceView::insertLines( const QString& text, int line )
+ {
+ m_editInterface->insertLine( line < 0 ? m_editInterface->numLines() : ( uint ) line, text );
+
+ KTextEditor::ViewCursorInterface * cursorIf = dynamic_cast<KTextEditor::ViewCursorInterface*>( m_view );
+ if ( cursorIf )
+ cursorIf->setCursorPosition( line < 0 ? m_editInterface->numLines() - 1 : ( uint ) line, 0 );
+ }
+
+ void DocumentSourceView::selectAll()
+ {
+ KTextEditor::SelectionInterface * selI = dynamic_cast<KTextEditor::SelectionInterface*>( m_view );
+ if ( selI )
+ selI->selectAll();
+ }
+
+ void DocumentSourceView::setReadOnly( bool isReadOnly )
+ {
+ m_isReadOnly = isReadOnly;
+ m_document->setReadWrite( !m_isReadOnly );
+ }
+
+ void DocumentSourceView::setFactory( KXMLGUIFactory *factory, KXMLGUIClient * client )
+ {
+ KTextEditor::PopupMenuInterface * popupInterface = dynamic_cast<KTextEditor::PopupMenuInterface*>( m_view );
+ popupInterface->installPopup(( QPopupMenu* )( factory ->container( "ktexteditor_popup", client ) ) );
+ }
+
+ void DocumentSourceView::configureEditor()
+ {
+ KTextEditor::ConfigInterface * conf = KTextEditor::configInterface( m_document );
+ if ( !conf )
+ {
+ kdDebug() << "*** No KTextEditor::ConfigInterface for part!" << endl;
+ return ;
+ }
+
+ // show the modal config dialog for this part if it has a ConfigInterface
+ conf->configDialog();
+ conf->writeConfig();
+ }
+
+ void DocumentSourceView::undo()
+ {
+ KTextEditor::UndoInterface * undoIf = dynamic_cast<KTextEditor::UndoInterface*>( m_document );
+ if ( undoIf != NULL )
+ undoIf->undo();
+ else
+ kdDebug() << "Cannot determine undo interface" << endl;
+ }
+
+ void DocumentSourceView::find()
+ {
+ KFindDialog dlg( TRUE, this );
+ dlg.setFindHistory( m_findHistory );
+ dlg.setHasSelection( FALSE );
+#if KDE_IS_VERSION(3,4,0)
+ dlg.setSupportsWholeWordsFind( FALSE );
+ dlg.setSupportsBackwardsFind( FALSE );
+ dlg.setSupportsCaseSensitiveFind( FALSE );
+ dlg.setSupportsRegularExpressionFind( FALSE );
+#endif
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ m_lastSearchTerm = dlg.pattern();
+ m_findHistory = dlg.findHistory();
+
+
+
+ KTextEditor::ViewCursorInterface * cursorIf = dynamic_cast<KTextEditor::ViewCursorInterface*>( m_view );
+
+ if ( cursorIf )
+ {
+ unsigned int fromLine = 0;
+ unsigned int fromCol = 0;
+ if ( dlg.options() && KFindDialog::FromCursor )
+ {
+ cursorIf->cursorPosition( &fromLine, &fromCol );
+ fromCol++;
+ }
+
+ search( fromLine, fromCol );
+ }
+ else
+ kdDebug() << "Failed to instantiate ViewCursorInterface, SearchInterface, or SelectionInterface" << endl;
+ }
+ }
+
+ void DocumentSourceView::findNext()
+ {
+ if ( m_lastSearchTerm.isEmpty() )
+ find();
+ else
+ {
+ KTextEditor::ViewCursorInterface * cursorIf = dynamic_cast<KTextEditor::ViewCursorInterface*>( m_view );
+
+ if ( cursorIf )
+ {
+ unsigned int fromLine = 0;
+ unsigned int fromCol = 0;
+ cursorIf->cursorPosition( &fromLine, &fromCol );
+
+ search( fromLine, fromCol );
+ }
+ else
+ kdDebug() << "Failed to instantiate ViewCursorInterface, SearchInterface, or SelectionInterface" << endl;
+ }
+ }
+
+ bool DocumentSourceView::setBibTeXFile( BibTeX::File *bibtexFile )
+ {
+ Settings * settings = Settings::self();
+
+ bool result = FALSE;
+ m_progDlg = new KProgressDialog( this, NULL, i18n( "Source View" ), i18n( "Converting BibTeX document to plain text ..." ), true );
+ m_progDlg->setAllowCancel( false );
+ kapp->processEvents();
+
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ BibTeX::FileExporterBibTeX * exporter = new BibTeX::FileExporterBibTeX();
+ connect( exporter, SIGNAL( progress( int, int ) ), this, SLOT( updateProgress( int, int ) ) );
+ exporter->setStringDelimiter( settings->fileIO_BibtexStringOpenDelimiter, settings->fileIO_BibtexStringCloseDelimiter );
+ exporter->setKeywordCasing( settings->fileIO_KeywordCasing );
+ exporter->setEncoding( "latex" );
+ exporter->setEnclosingCurlyBrackets( settings->fileIO_EnclosingCurlyBrackets );
+ result = exporter->save( &buffer, bibtexFile );
+ delete exporter;
+ buffer.close();
+
+ if ( result )
+ {
+ kapp->processEvents();
+ buffer.open( IO_ReadOnly );
+ QTextStream in( &buffer );
+ in.setEncoding( QTextStream::UnicodeUTF8 );
+ QString text = in.read();
+ buffer.close();
+
+ if ( m_editInterface )
+ {
+ kapp->processEvents();
+ // very strange: to set the text, you have to set
+ // readwrite to TRUE...
+ m_document->setReadWrite( TRUE );
+ m_editInterface->setText( text );
+ m_document->setReadWrite( !m_isReadOnly );
+ }
+
+ m_bibtexFile = bibtexFile;
+ }
+
+ kapp->processEvents();
+ delete m_progDlg;
+
+ return result;
+ }
+
+ BibTeX::File* DocumentSourceView::getBibTeXFile()
+ {
+ if ( m_editInterface )
+ {
+ QBuffer buffer;
+
+ buffer.open( IO_WriteOnly );
+ QTextStream stream( &buffer );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ stream << m_editInterface->text();
+ buffer.close();
+
+ Settings * settings = Settings::self( m_bibtexFile );
+
+ buffer.open( IO_ReadOnly );
+ BibTeX::FileImporter *importer = new BibTeX::FileImporterBibTeX( settings->editing_FirstNameFirst );
+ BibTeX::File *result = importer->load( &buffer );
+ delete importer;
+ buffer.close();
+
+ return result;
+ }
+
+ return NULL;
+ }
+
+ void DocumentSourceView::focusInEvent( QFocusEvent* /*event*/ )
+ {
+ if ( m_view != NULL )
+ m_view->setFocus();
+ }
+
+ void DocumentSourceView::setupGUI()
+ {
+ // create the Kate::Document
+ m_document = Kate::createDocument( this, "Kate::Document" );
+
+ m_view = ( Kate::View * ) m_document->createView( this, 0L );
+ m_editInterface = editInterface( m_document );
+ m_document->setReadWrite( !m_isReadOnly );
+ if ( !m_isReadOnly )
+ connect( m_document, SIGNAL( textChanged() ), this, SIGNAL( modified() ) );
+ QBoxLayout * layout = new QVBoxLayout( this );
+ layout->addWidget( static_cast<QWidget*>( m_view ) );
+
+ int c = m_document->hlModeCount() ;
+ int hlIdx = -1;
+ for ( int i = 0; i < c; i++ )
+ if ( m_document->hlModeName( i ) .compare( "BibTeX" ) == 0 )
+ {
+ hlIdx = i;
+ break;
+ }
+ if ( hlIdx > -1 )
+ m_document-> setHlMode( hlIdx );
+ }
+
+ void DocumentSourceView::readConfig()
+ {
+ KConfig * config = kapp->config();
+ readConfig( config );
+ }
+
+ void DocumentSourceView::writeConfig()
+ {
+ KConfig * config = kapp->config();
+ writeConfig( config );
+ }
+
+ void DocumentSourceView::readConfig( KConfig *config )
+ {
+ if ( m_view )
+ {
+ KTextEditor::ConfigInterface * conf = KTextEditor::configInterface( m_document );
+ if ( conf )
+ conf->readConfig( config );
+ }
+ }
+
+ void DocumentSourceView::writeConfig( KConfig *config )
+ {
+ if ( m_view )
+ {
+ KTextEditor::ConfigInterface * conf = KTextEditor::configInterface( m_document );
+ if ( conf )
+ conf->writeConfig( config );
+ }
+ config->sync();
+ }
+
+ void DocumentSourceView::search( int fromLine, int fromCol )
+ {
+ unsigned int foundAtLine, foundAtCol, matchLen;
+
+ KTextEditor::SearchInterface * searchIf = KTextEditor::searchInterface( m_document );
+ KTextEditor::SelectionInterface *selectionIf = KTextEditor::selectionInterface( m_document );
+ KTextEditor::ViewCursorInterface * cursorIf = dynamic_cast<KTextEditor::ViewCursorInterface*>( m_view );
+
+ do
+ {
+ bool result = searchIf->searchText( fromLine, fromCol, m_lastSearchTerm, &foundAtLine, &foundAtCol, &matchLen, FALSE );
+ if ( result )
+ {
+ selectionIf->setSelection( foundAtLine, foundAtCol, foundAtLine, foundAtCol + matchLen );
+ cursorIf->setCursorPositionReal( foundAtLine, foundAtCol + matchLen );
+ break;
+ }
+
+ fromLine = 0;
+ fromCol = 0;
+ }
+ while ( KMessageBox::questionYesNo( this, QString( i18n( "Could not find text '%1' in the document.\nStart from the beginning?" ) ).arg( m_lastSearchTerm ), i18n( "Find text in source view" ), KGuiItem( i18n( "Restart search" ) ) ) == KMessageBox::Yes );
+ }
+
+ void DocumentSourceView::updateProgress( int current, int total )
+ {
+ m_progDlg->progressBar()->setTotalSteps( total );
+ m_progDlg->progressBar()->setValue( current );
+ kapp->processEvents();
+ }
+
+}
+#include "documentsourceview.moc"
diff --git a/src/documentsourceview.h b/src/documentsourceview.h
new file mode 100644
index 0000000..8edb23a
--- /dev/null
+++ b/src/documentsourceview.h
@@ -0,0 +1,96 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXDOCUMENTSOURCEVIEW_H
+#define KBIBTEXDOCUMENTSOURCEVIEW_H
+
+#include <qwidget.h>
+
+#include <file.h>
+
+#include <ktexteditor/editinterface.h>
+#include <kate/view.h>
+#include <kate/document.h>
+
+class KProgressDialog;
+
+namespace KBibTeX
+{
+ class DocumentWidget;
+
+ /**
+ * @author Thomas Fischer <[email protected]>
+ */
+ class DocumentSourceView : public QWidget
+ {
+ Q_OBJECT
+ public:
+ DocumentSourceView( KBibTeX::DocumentWidget *docWidget, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~DocumentSourceView();
+
+ bool setBibTeXFile( BibTeX::File *bibtexFile );
+ BibTeX::File* getBibTeXFile( );
+
+ void copy();
+ void cut();
+ bool paste();
+ void insertLines( const QString& text, int line = -1 );
+ void selectAll();
+
+ void setReadOnly( bool isReadOnly );
+ void setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client );
+
+ public slots:
+ void configureEditor();
+ void undo();
+ void find();
+ void findNext();
+
+ signals:
+ void modified();
+
+ protected:
+ virtual void focusInEvent( QFocusEvent* event );
+
+ private:
+ bool m_isReadOnly;
+ KBibTeX::DocumentWidget *m_docWidget;
+ BibTeX::File *m_bibtexFile;
+ Kate::Document* m_document;
+ Kate::View* m_view;
+ KTextEditor::EditInterface* m_editInterface;
+ QString m_lastSearchTerm;
+ QStringList m_findHistory;
+ KProgressDialog *m_progDlg;
+
+ void setupGUI();
+ void readConfig();
+ void writeConfig();
+ void readConfig( KConfig *config );
+ void writeConfig( KConfig *config );
+
+ void search( int fromLine, int fromCol );
+
+ private slots:
+ void updateProgress(int current, int total);
+ };
+
+}
+
+#endif
diff --git a/src/documentwidget.cpp b/src/documentwidget.cpp
new file mode 100644
index 0000000..1a59434
--- /dev/null
+++ b/src/documentwidget.cpp
@@ -0,0 +1,1740 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <cmath>
+
+#include <qlayout.h>
+#include <qfile.h>
+#include <qdragobject.h>
+#include <qregexp.h>
+#include <qsplitter.h>
+#include <qurl.h>
+#include <qtextedit.h>
+#include <qprogressdialog.h>
+#include <qbuffer.h>
+#include <qtooltip.h>
+#include <qapplication.h>
+#include <qpushbutton.h>
+#include <qfileinfo.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <kglobalsettings.h>
+#include <kurl.h>
+#include <kinputdialog.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <klineedit.h>
+#include <kdebug.h>
+#include <ktextedit.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <searchbar.h>
+#include <sidebar.h>
+#include <documentlistview.h>
+#include <documentlistviewitem.h>
+#include <documentsourceview.h>
+#include <macrowidget.h>
+#include <preamblewidget.h>
+#include <commentwidget.h>
+#include <entrywidget.h>
+#include <fileimporterbibtex.h>
+#include <fileimporterbibutils.h>
+#include <fileimporterris.h>
+#include <fileexporterbibtex.h>
+#include <fileexporterbibutils.h>
+#include <fileexporterris.h>
+#include <fileexporterxml.h>
+#include <fileexporterrtf.h>
+#include <fileexporterdocbook5.h>
+#include <fileexporterpdf.h>
+#include <fileexporterps.h>
+#include <fileexporterxslt.h>
+#include <fileimporterexternal.h>
+#include <fileexporterexternal.h>
+#include <xsltransform.h>
+#include <entry.h>
+#include <entryfield.h>
+#include <comment.h>
+#include <macro.h>
+#include <preamble.h>
+#include <settings.h>
+#include <webquery.h>
+#include <mergeelements.h>
+#include <idsuggestions.h>
+
+#include "documentwidget.h"
+
+namespace KBibTeX
+{
+
+ DocumentWidget::DocumentWidget( bool isReadOnly, QWidget *parent, const char *name )
+ : QTabWidget( parent, name ), m_lineEditNewKeyword( NULL ), m_isReadOnly( isReadOnly ), m_filename( QString::null ), m_progressDialog( NULL ), m_newElementCounter( 1 ), m_editMode( emList ), m_viewDocumentActionMenu( NULL ), m_assignKeywordsActionMenu( NULL ), m_searchWebsitesActionMenu( NULL ), m_actionEditCut( NULL ), m_actionEditCopy( NULL ), m_actionEditCopyRef( NULL ), m_actionEditPaste( NULL ), m_actionEditSelectAll( NULL ), m_actionEditFind( NULL ), m_actionEditFindNext( NULL ), m_dirWatch( this )
+ {
+ m_bibtexfile = new BibTeX::File();
+
+ setupGUI();
+
+ m_listViewElements->setBibTeXFile( m_bibtexfile );
+ m_sourceView->setBibTeXFile( m_bibtexfile );
+ }
+
+ DocumentWidget::~DocumentWidget()
+ {
+ delete m_bibtexfile;
+ }
+
+ void DocumentWidget::setupGUI()
+ {
+ setAcceptDrops( TRUE );
+ setFocusPolicy( QWidget::ClickFocus );
+
+ // List view tab widget ===============================
+
+ m_container = new QWidget( this );
+ QVBoxLayout *layout = new QVBoxLayout( m_container, 0, 0 );
+ addTab( m_container, i18n( "L&ist view" ) );
+
+ m_searchBar = new SearchBar( m_container );
+ layout->addWidget( m_searchBar );
+
+ m_horSplitter = new QSplitter( Qt::Horizontal, m_container );
+ layout->addWidget( m_horSplitter );
+ m_horSplitter->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+
+ m_sideBar = new SideBar( m_isReadOnly, m_horSplitter );
+ m_vertSplitter = new QSplitter( Qt::Vertical, m_horSplitter );
+ m_vertSplitter->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+
+ m_listViewElements = new DocumentListView( this, m_isReadOnly, m_vertSplitter );
+
+ m_preview = new KTextEdit( m_vertSplitter );
+ m_preview->setReadOnly( TRUE );
+ m_preview->setAlignment( Qt::AlignTop && Qt::AlignLeft );
+
+ // Source view tab widget =============================
+
+ m_sourceView = new DocumentSourceView( this, m_isReadOnly, this , "source_view" );
+ addTab( m_sourceView, i18n( "So&urce view" ) );
+ m_sourceView->setFont( KGlobalSettings::fixedFont() );
+
+ // Setup actions
+ connect( m_searchBar, SIGNAL( onlineSearch() ), this, SLOT( onlineSearch() ) );
+ connect( m_searchBar, SIGNAL( doSearch( const QString&, BibTeX::Element::FilterType, BibTeX::EntryField::FieldType ) ), m_listViewElements, SLOT( filter( const QString&, BibTeX::Element::FilterType, BibTeX::EntryField::FieldType ) ) );
+ connect( m_listViewElements, SIGNAL( executed( DocumentListViewItem* ) ), this, SLOT( executeElement( DocumentListViewItem* ) ) );
+ connect( m_listViewElements, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) );
+ connect( m_listViewElements, SIGNAL( currentChanged( QListViewItem* ) ), this, SLOT( slotPreviewElement( QListViewItem* ) ) );
+ connect( m_listViewElements, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( slotPreviewElement( QListViewItem* ) ) );
+ connect( this, SIGNAL( currentChanged( QWidget * ) ), this, SLOT( slotTabChanged( QWidget* ) ) );
+ connect( m_sourceView, SIGNAL( modified() ), this, SLOT( slotModified() ) );
+ connect( m_listViewElements, SIGNAL( modified() ), this, SLOT( slotModified() ) );
+ connect( m_sideBar, SIGNAL( valueRenamed() ), this, SLOT( slotModified() ) );
+ connect( m_sideBar, SIGNAL( valueRenamed() ), this, SLOT( refreshBibTeXFile() ) );
+ connect( m_sideBar, SIGNAL( selected( const QString&, BibTeX::Element::FilterType, BibTeX::EntryField::FieldType ) ), m_searchBar, SLOT( setSearch( const QString&, BibTeX::Element::FilterType, BibTeX::EntryField::FieldType ) ) );
+ connect( &m_dirWatch, SIGNAL( dirty( const QString& ) ), this, SLOT( slotFileGotDirty( const QString & ) ) );
+ }
+
+
+ bool DocumentWidget::open( const QString &fileName, bool mergeOnly )
+ {
+ bool result = FALSE;
+ if ( !mergeOnly )
+ m_dirWatch.removeFile( m_filename );
+
+ BibTeX::FileImporter *importer = fileImporterFactory( fileName );
+ if ( importer != NULL )
+ {
+ QFile file( fileName );
+ if ( file.open( IO_ReadOnly ) )
+ {
+ result = open( &file, mergeOnly, QString( i18n( "<qt>Loading file <b>%1</b></qt>" ) ).arg( fileName ), importer );
+ if ( result )
+ {
+ m_bibtexfile->fileName = fileName;
+ m_filename = fileName;
+ }
+ file.close();
+ }
+ else
+ kdDebug() << "Cannot open file " << fileName << endl;
+
+ delete importer;
+ }
+
+
+ if ( !mergeOnly )
+ m_dirWatch.addFile( m_filename );
+
+ return result;
+ }
+
+ bool DocumentWidget::open( QIODevice *iodevice, bool mergeOnly, const QString &label, BibTeX::FileImporter *importer )
+ {
+ bool result = FALSE;
+ setEnabled( FALSE );
+
+ bool usingDefaultImporter = importer == NULL;
+ if ( usingDefaultImporter )
+ {
+ Settings * settings = Settings::self( NULL );
+ importer = new BibTeX::FileImporterBibTeX( settings->editing_FirstNameFirst, settings->fileIO_Encoding );
+ }
+
+ startProgress( label, importer );
+ BibTeX::File *newFile = importer->load( iodevice );
+ endProgress( importer );
+
+ if ( usingDefaultImporter )
+ delete importer;
+
+ if ( newFile != NULL )
+ {
+ if ( mergeOnly )
+ {
+ for ( QValueList<BibTeX::Element*>::ConstIterator eit = newFile->constBegin(); eit != newFile->constEnd(); ++eit )
+ m_bibtexfile->appendElement(( *eit )->clone() );
+
+ if ( KMessageBox::questionYesNo( this, i18n( "Do you want to search for duplicates in the merged document?" ), i18n( "Find duplicates?" ), KGuiItem( i18n( "Find Duplicates" ) ) ) == KMessageBox::Yes )
+ {
+ MergeElements *me = new MergeElements( this );
+ me->mergeDuplicates( m_bibtexfile );
+ delete me;
+ }
+ delete newFile;
+ }
+ else
+ {
+ delete m_bibtexfile;
+ m_bibtexfile = newFile;
+ }
+
+ if ( currentPage() == m_sourceView )
+ m_sourceView->setBibTeXFile( m_bibtexfile );
+ else if ( currentPage() == m_container )
+ m_listViewElements->setBibTeXFile( m_bibtexfile );
+
+ Settings * settings = Settings::self( m_bibtexfile );
+ settings->addToCompletion( m_bibtexfile );
+ m_sideBar->refreshLists( m_bibtexfile );
+
+ result = TRUE;
+ }
+ else
+ {
+ kdDebug() << "Could not load bibliography file from io device" << endl;
+ result = FALSE;
+ }
+
+ setEnabled( TRUE );
+ return result;
+ }
+
+ bool DocumentWidget::save( const QString &fileName, QStringList *errorLog )
+ {
+ bool result = FALSE;
+ m_dirWatch.removeFile( m_filename );
+ Settings * settings = Settings::self( NULL );
+
+ BibTeX::File::FileFormat format = BibTeX::File::formatUndefined;
+ if ( fileName.endsWith( ".rtf", FALSE ) )
+ format = BibTeX::File::formatRTF;
+ else if ( fileName.endsWith( ".pdf", FALSE ) )
+ format = BibTeX::File::formatPDF;
+ else if ( fileName.endsWith( ".bib", FALSE ) )
+ format = BibTeX::File::formatBibTeX;
+ else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && ( fileName.endsWith( ".ref", FALSE ) || fileName.endsWith( ".refer", FALSE ) || fileName.endsWith( ".txt", FALSE ) || fileName.endsWith( ".rfr", FALSE ) ) )
+ format = BibTeX::File::formatEndNote;
+ else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && ( fileName.endsWith( ".isi", FALSE ) || fileName.endsWith( ".cgi", FALSE ) ) )
+ format = BibTeX::File::formatISI;
+ else if ( fileName.endsWith( ".ris", FALSE ) )
+ format = BibTeX::File::formatRIS;
+ else if ( fileName.endsWith( ".ps", FALSE ) )
+ format = BibTeX::File::formatPS;
+ else if ( fileName.endsWith( ".xml", FALSE ) )
+ {
+ QStringList options = QStringList::split( '|', ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable ? "DocBook5|MODS|internal XML" : "DocBook5|internal XML" ) );
+ bool ok = false;
+ QString answer = KInputDialog::getItem( i18n( "Choose file format" ), QString( i18n( "Choose file format of file '%1':" ) ).arg( fileName ), options, 0, false, &ok, this );
+ if ( ok && !answer.isNull() && answer == "DocBook5" )
+ format = BibTeX::File::formatDocBook5;
+ else if ( ok && !answer.isNull() && answer == "MODS" )
+ format = BibTeX::File::formatMODS;
+ else if ( ok && !answer.isNull() && answer == "internal XML" )
+ format = BibTeX::File::formatXML;
+ }
+ else if ( fileName.endsWith( ".html", FALSE ) || fileName.endsWith( ".xhtml", FALSE ) || fileName.endsWith( ".htm", FALSE ) )
+ format = BibTeX::File::formatHTML;
+
+ if ( format != BibTeX::File::formatUndefined )
+ {
+ QString usedFileName = fileName;
+ QFileInfo fi( fileName );
+ if ( !fi.readLink().isNull() && KMessageBox::questionYesNo( this, QString( i18n( "The selected filename \"%1\" is a symbolic link pointing to \"%2\".\nReplace the link with a new file or overwrite the existing file the link points to?" ) ).arg( usedFileName ).arg( Settings::resolveLink( fileName, fi.readLink() ) ), i18n( "Symbolic Link" ), KGuiItem( i18n( "Replace link" ) ), KGuiItem( i18n( "Overwrite file the link points to" ) ) ) == KMessageBox::No )
+ usedFileName = Settings::resolveLink( fileName, fi.readLink() );
+ QFile file( usedFileName );
+ if ( file.open( IO_WriteOnly ) )
+ {
+ result = save( &file, format, QString( i18n( "<qt>Writing file <b>%1</b></qt>" ) ).arg( fileName ), errorLog );
+ if ( result )
+ {
+ m_bibtexfile->fileName = fileName;
+ m_filename = fileName;
+ }
+ file.close();
+ }
+ else
+ kdDebug() << "Cannot write to file " << fileName << endl;
+ }
+ else
+ kdDebug() << "Unknown file format to save to (filename is " << fileName << ")" << endl;
+
+ m_dirWatch.addFile( m_filename );
+ return result;
+ }
+
+ bool DocumentWidget::save( QIODevice *iodevice, BibTeX::File::FileFormat format, const QString &label, QStringList *errorLog )
+ {
+ Settings * settings = Settings::self( m_bibtexfile );
+
+ bool result = FALSE;
+ setEnabled( FALSE );
+
+ updateFromGUI();
+
+ BibTeX::XSLTransform *transform = NULL;
+
+ BibTeX::FileExporter * exporter = NULL;
+ switch ( format )
+ {
+ case BibTeX::File::formatBibTeX:
+ {
+ BibTeX::FileExporterBibTeX * bibtexExporter = new BibTeX::FileExporterBibTeX();
+ bibtexExporter->setStringDelimiter( settings->fileIO_BibtexStringOpenDelimiter, settings->fileIO_BibtexStringCloseDelimiter );
+ bibtexExporter->setKeywordCasing( settings->fileIO_KeywordCasing );
+ bibtexExporter->setEncoding( settings->fileIO_Encoding );
+ bibtexExporter->setEnclosingCurlyBrackets( settings->fileIO_EnclosingCurlyBrackets );
+ exporter = bibtexExporter;
+ }
+ break;
+ case BibTeX::File::formatRIS:
+ if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && settings->fileIO_useBibUtils )
+ exporter = new BibTeX::FileExporterBibUtils( BibTeX::File::formatRIS );
+ else
+ exporter = new BibTeX::FileExporterRIS( );
+ break;
+ case BibTeX::File::formatEndNote:
+ case BibTeX::File::formatEndNoteXML:
+ case BibTeX::File::formatMODS:
+ case BibTeX::File::formatISI:
+ if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable )
+ exporter = new BibTeX::FileExporterBibUtils( format );
+ break;
+ case BibTeX::File::formatXML:
+ exporter = new BibTeX::FileExporterXML();
+ break;
+ case BibTeX::File::formatHTML:
+ switch ( settings->fileIO_ExporterHTML )
+ {
+ case BibTeX::FileExporterExternal::exporterNone:
+ case BibTeX::FileExporterExternal::exporterXSLT:
+ {
+ KStandardDirs * kstd = KGlobal::dirs();
+ QString resPath = kstd->findResource( "data", "kbibtexpart/xslt/html.xsl" );
+ if ( resPath != NULL )
+ transform = new BibTeX::XSLTransform( resPath );
+
+ if ( transform != NULL )
+ exporter = new BibTeX::FileExporterXSLT( transform );
+ else
+ {
+ kdDebug() << "XSLT for HTML export is not available" << endl;
+ }
+ }
+ break;
+ default:
+ {
+ exporter = new BibTeX::FileExporterExternal( settings->fileIO_ExporterHTML, BibTeX::File::formatHTML );
+ }
+ }
+ break;
+ case BibTeX::File::formatRTF:
+ {
+ if ( !settings->external_latex2rtfAvailable )
+ {
+ QString msg = i18n( "To export a BibTeX document to the Rich Text Format (RTF) KBibTeX requires the program 'latex2rtf'." ) ;
+ KMessageBox::information( this, msg );
+ errorLog->append( msg );
+ }
+ else
+ {
+ BibTeX::FileExporterRTF *rtfExporter = new BibTeX::FileExporterRTF();
+ rtfExporter->setLaTeXLanguage( settings->fileIO_ExportLanguage );
+ rtfExporter->setLaTeXBibliographyStyle( settings->fileIO_ExportBibliographyStyle );
+ exporter = rtfExporter;
+ }
+ }
+ break;
+ case BibTeX::File::formatDocBook5:
+ {
+ if ( settings->fileIO_bib2db5ClassPath == QString::null )
+ {
+ QString msg = i18n( "To export a BibTeX document to the DocBook5 format KBibTeX requires the program 'bib2db5'." ) ;
+ KMessageBox::information( this, msg );
+ errorLog->append( msg );
+ }
+ else
+ {
+ BibTeX::FileExporterDocBook5 *db5Exporter = new BibTeX::FileExporterDocBook5( settings->fileIO_bib2db5ClassPath );
+ exporter = db5Exporter;
+ }
+ }
+ break;
+ case BibTeX::File::formatPDF:
+ {
+ if ( settings->fileIO_EmbedFiles && !Settings::kpsewhich( "embedfile.sty" ) )
+ {
+ KMessageBox::sorry( this, i18n( "Embedding files into the PDF file is enabled, but the required file 'embedfile.sty' was not found. Embedding files will be disabled." ), i18n( "Embedding files disabled" ) );
+ settings->fileIO_EmbedFiles = FALSE;
+ }
+
+ BibTeX::FileExporterPDF *pdfExporter = new BibTeX::FileExporterPDF( settings->fileIO_EmbedFiles );
+ pdfExporter->setLaTeXLanguage( settings->fileIO_ExportLanguage );
+ pdfExporter->setLaTeXBibliographyStyle( settings->fileIO_ExportBibliographyStyle );
+ QStringList searchPaths;
+ for ( QStringList::Iterator it = settings->editing_DocumentSearchPaths.begin(); it != settings->editing_DocumentSearchPaths.end(); ++it )
+ searchPaths.append( *it );
+ if ( m_bibtexfile->fileName != QString::null )
+ searchPaths.append( KURL( m_bibtexfile->fileName ).directory( FALSE, FALSE ) );
+ pdfExporter->setDocumentSearchPaths( searchPaths );
+ exporter = pdfExporter;
+ }
+ break;
+ case BibTeX::File::formatPS:
+ {
+ BibTeX::FileExporterPS *psExporter = new BibTeX::FileExporterPS();
+ psExporter->setLaTeXLanguage( settings->fileIO_ExportLanguage );
+ psExporter->setLaTeXBibliographyStyle( settings->fileIO_ExportBibliographyStyle );
+ exporter = psExporter;
+ }
+ break;
+ default:
+ kdDebug() << "Unsupported export format selected" << endl;
+ }
+
+ if ( exporter != NULL )
+ {
+ startProgress( label, exporter );
+ result = exporter->save( iodevice, m_bibtexfile, errorLog );
+ endProgress( exporter );
+
+ if ( transform != NULL )
+ delete transform;
+ delete exporter;
+ }
+
+ setEnabled( TRUE );
+ return result;
+ }
+
+ bool DocumentWidget::newElement( const QString& elementType )
+ {
+ Settings * settings = Settings::self( m_bibtexfile );
+
+ if ( m_editMode == emList )
+ {
+ if ( elementType.lower() == "macro" )
+ {
+ QString name = QString( i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewMacro%1" ) ).arg( m_newElementCounter++ );
+ BibTeX::Macro *macro = new BibTeX::Macro( name );
+ if ( MacroWidget::execute( macro, m_isReadOnly ) == QDialog::Accepted )
+ {
+ new DocumentListViewItem( m_bibtexfile, macro, m_listViewElements );
+ m_bibtexfile->appendElement( macro );
+ settings->addToCompletion( macro );
+ m_sideBar->refreshLists( m_bibtexfile );
+ return TRUE;
+ }
+ else
+ {
+ delete macro;
+ return FALSE;
+ }
+ }
+ else if ( elementType.lower() == "comment" )
+ {
+ BibTeX::Comment * comment = new BibTeX::Comment( i18n( "Put your comment here..." ) );
+ if ( CommentWidget::execute( comment, m_isReadOnly ) == QDialog::Accepted )
+ {
+ new DocumentListViewItem( m_bibtexfile, comment, m_listViewElements );
+ m_bibtexfile->appendElement( comment );
+ return TRUE;
+ }
+ else
+ {
+ delete comment;
+ return FALSE;
+ }
+ }
+ else if ( elementType.lower() == "preamble" )
+ {
+ BibTeX::Preamble * preamble = new BibTeX::Preamble( );
+ if ( PreambleWidget::execute( preamble, m_isReadOnly ) == QDialog::Accepted )
+ {
+ new DocumentListViewItem( m_bibtexfile, preamble, m_listViewElements );
+ m_bibtexfile->appendElement( preamble );
+ return TRUE;
+ }
+ else
+ {
+ delete preamble;
+ return FALSE;
+ }
+ }
+ else
+ {
+ QString name = nextNewEntry();
+ BibTeX::Entry *entry = new BibTeX::Entry( elementType, name );
+ m_dirWatch.stopScan();
+ if ( EntryWidget::execute( entry, m_bibtexfile, m_isReadOnly, TRUE ) == QDialog::Accepted )
+ {
+ new DocumentListViewItem( m_bibtexfile, entry, m_listViewElements );
+ m_bibtexfile->appendElement( entry );
+ settings->addToCompletion( entry );
+ m_sideBar->refreshLists( m_bibtexfile );
+ m_dirWatch.startScan();
+ return TRUE;
+ }
+ else
+ {
+ delete entry;
+ m_dirWatch.startScan();
+ return FALSE;
+ }
+ }
+ }
+ else if ( m_editMode == emSource )
+ {
+ if ( elementType.lower() == "macro" )
+ {
+ QString name = QString( i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewString%1" ) ).arg( m_newElementCounter++ );
+ m_sourceView->insertLines( QString( "@string{ %1 = \"%2\" }" ).arg( name ).arg( i18n( "No text yet" ) ) );
+ }
+ else if ( elementType.lower() == "comment" )
+ {
+ m_sourceView->insertLines( i18n( "@comment{ Put your comment here... }" ) );
+ }
+ else if ( elementType.lower() == "preamble" )
+ {
+ m_sourceView->insertLines( i18n( "@preamble{\"Put your preamble here using double quotes...\"}" ), 0 );
+ }
+ else
+ {
+ QString name = nextNewEntry();
+ BibTeX::Entry *entry = new BibTeX::Entry( elementType, name );
+
+ for ( int t = 0; t < 2; t++ )
+ for ( int i = ( int ) BibTeX::EntryField::ftAbstract; i <= ( int ) BibTeX::EntryField::ftYear; i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType ) i;
+ BibTeX::Entry::FieldRequireStatus fieldRequireStatus = BibTeX::Entry::getRequireStatus( entry->entryType(), fieldType );
+
+ if (( t == 0 && fieldRequireStatus == BibTeX::Entry::frsRequired ) || ( t == 1 && fieldRequireStatus == BibTeX::Entry::frsOptional ) )
+ {
+ BibTeX::Value * value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText( fieldRequireStatus == BibTeX::Entry::frsRequired ? i18n( "REQUIRED" ) : i18n( "optional" ) ) );
+ BibTeX::EntryField *field = new BibTeX::EntryField( fieldType );
+ field->setValue( value );
+ entry->addField( field );
+ }
+ }
+
+ BibTeX::FileExporter * exporter = new BibTeX::FileExporterBibTeX( );
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ bool result = exporter->save( &buffer, entry );
+ buffer.close();
+
+ if ( result )
+ {
+ buffer.open( IO_ReadOnly );
+ QTextStream textStream( &buffer );
+ textStream.setEncoding( QTextStream::UnicodeUTF8 );
+ QString text = textStream.read();
+ buffer.close();
+ QStringList lines = QStringList::split( '\n', text );
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
+ m_sourceView->insertLines( *it );
+ }
+
+ delete exporter;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ void DocumentWidget::updateViews()
+ {
+ m_listViewElements->updateVisiblity();
+ }
+
+ void DocumentWidget::showStatistics()
+ {
+ int n = m_bibtexfile->count();
+ KMessageBox::information( this, i18n( "This BibTeX file contains 1 element.", "This BibTeX file contains %n elements.", n ), i18n( "File Statistics" ) );
+ }
+
+ void DocumentWidget::refreshBibTeXFile()
+ {
+ if ( currentPage() == m_sourceView )
+ m_sourceView->setBibTeXFile( m_bibtexfile );
+ else if ( currentPage() == m_container )
+ m_listViewElements->setBibTeXFile( m_bibtexfile );
+ }
+
+ void DocumentWidget::setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client )
+ {
+ m_searchBar->setFactory( factory, client );
+ m_listViewElements->setFactory( factory, client );
+ m_sourceView->setFactory( factory, client );
+
+ m_viewDocumentActionMenu = dynamic_cast<KActionMenu*>( client->action( "view_document" ) );
+ if ( m_viewDocumentActionMenu != NULL )
+ connect( m_viewDocumentActionMenu->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotViewDocument( int ) ) );
+ m_assignKeywordsActionMenu = dynamic_cast<KActionMenu*>( client->action( "assign_keywords" ) );
+ if ( m_assignKeywordsActionMenu != NULL )
+ connect( m_assignKeywordsActionMenu->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotAssignKeywords( int ) ) );
+
+ m_actionEditCut = client->action( "edit_cut" );
+ m_actionEditCopy = client->action( "edit_copy" );
+ m_actionEditCopyRef = client->action( "edit_copyref" );
+ m_actionEditPaste = client->action( "edit_paste" );
+ m_actionEditSelectAll = client->action( "edit_select_all" );
+ m_actionEditFind = client->action( "edit_find" );
+ m_actionEditFindNext = client->action( "edit_find_next" );
+ m_listViewElements->setViewShowColumnsMenu( dynamic_cast<KActionMenu*>( client->action( "view_showcolumns" ) ) );
+ m_searchWebsitesActionMenu = dynamic_cast<KActionMenu*>( client->action( "search_document_online" ) );
+ }
+
+ void DocumentWidget::updateViewDocumentMenu( )
+ {
+ if ( m_viewDocumentActionMenu == NULL )
+ {
+ kdDebug() << "FIXME: m_viewDocumentActionMenu is not set" << endl;
+ return;
+ }
+
+ KPopupMenu * popup = m_viewDocumentActionMenu->popupMenu();
+ popup->clear();
+ m_viewDocumentActionMenuURLs.clear();
+
+ BibTeX::Element * currentElement = NULL;
+
+ QListViewItem * item = m_listViewElements->selectedItem();
+ if ( item == NULL )
+ item = m_listViewElements->currentItem();
+ DocumentListViewItem * dlvi = dynamic_cast<DocumentListViewItem*>( item );
+ if ( dlvi )
+ currentElement = dlvi->element();
+
+ BibTeX::Entry *entry = NULL;
+ if ( currentElement != NULL )
+ entry = dynamic_cast<BibTeX::Entry*>( currentElement );
+
+ m_viewDocumentActionMenu->setEnabled( FALSE );
+ if ( entry != NULL )
+ {
+ KURL::List documentURLs = getEntryURLs( entry );
+ if ( !documentURLs.isEmpty() )
+ {
+ for ( KURL::List::Iterator i = documentURLs.begin(); i != documentURLs.end(); ++i )
+ {
+ QString prettyURL = ( *i ).prettyURL();
+ if ( prettyURL.endsWith( ".pdf", FALSE ) || prettyURL.find( "/pdf/" ) > 0 )
+ popup->insertItem( SmallIcon( "pdf" ), prettyURL );
+ else if ( prettyURL.endsWith( ".ps", FALSE ) )
+ popup->insertItem( SmallIcon( "postscript" ), prettyURL );
+ else if ( prettyURL.endsWith( ".html", FALSE ) || prettyURL.startsWith( "http://", FALSE ) )
+ popup->insertItem( SmallIcon( "html" ), prettyURL );
+ else
+ popup->insertItem( prettyURL );
+ m_viewDocumentActionMenuURLs.append( prettyURL );
+ }
+ m_viewDocumentActionMenu->setEnabled( TRUE );
+ }
+ }
+ }
+
+ void DocumentWidget::updateAssignKeywords()
+ {
+ if ( m_assignKeywordsActionMenu == NULL )
+ {
+ kdDebug() << "FIXME: m_assignKeywordsActionMenu is not set" << endl;
+ return;
+ }
+
+ KPopupMenu * popup = m_assignKeywordsActionMenu->popupMenu();
+ popup->clear();
+ m_assignKeywordsActionMenuURLs.clear();
+ QStringList entryKeywords;
+ QStringList fileKeywords;
+
+ /**
+ * Fetch keywords from selected entries into entryKeywords list
+ */
+ QValueList<BibTeX::Entry*> entryList;
+ for ( QListViewItemIterator it( m_listViewElements, QListViewItemIterator::Selected ); it.current(); ++it )
+ {
+ BibTeX::Element * currentElement = NULL;
+ DocumentListViewItem * dlvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ if ( dlvi && (( currentElement = dlvi->element() ) != NULL ) )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( currentElement );
+ if ( entry != NULL )
+ entryList << entry;
+ }
+ }
+
+ for ( QValueList<BibTeX::Entry*>::Iterator it = entryList.begin(); it != entryList.end(); ++it )
+ {
+ BibTeX::Entry *entry = *it;
+ BibTeX::EntryField *field = NULL;
+ BibTeX::Value *valueKeywords = NULL;
+ if (( field = entry->getField( BibTeX::EntryField::ftKeywords ) ) != NULL && ( valueKeywords = field->value() ) != NULL )
+ for ( QValueList<BibTeX::ValueItem*>::ConstIterator it = valueKeywords->items.begin();it != valueKeywords->items.end();++it )
+ {
+ BibTeX::KeywordContainer *container = dynamic_cast<BibTeX::KeywordContainer*>( *it );
+ if ( container != NULL )
+ for ( QValueList<BibTeX::Keyword*>::ConstIterator kit = container->keywords.begin();kit != container->keywords.end();++kit )
+ entryKeywords.append(( *kit )->text() );
+ }
+ }
+
+ /**
+ * Fetch all keywords from current file into fileKeywords
+ */
+ for ( QValueList<BibTeX::Element*>::ConstIterator eit = m_bibtexfile->constBegin(); eit != m_bibtexfile->constEnd(); ++eit )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *eit );
+ BibTeX::EntryField *field = NULL;
+ BibTeX::Value *value = NULL;
+ if ( entry != NULL && (( field = entry->getField( BibTeX::EntryField::ftKeywords ) ) != NULL ) && (( value = field->value() ) != NULL ) )
+ {
+ for ( QValueList<BibTeX::ValueItem*>::ConstIterator vit = value->items.constBegin(); vit != value->items.constEnd();++vit )
+ {
+ BibTeX::KeywordContainer *container = dynamic_cast<BibTeX::KeywordContainer *>( *vit );
+ for ( QValueList<BibTeX::Keyword*>::ConstIterator kit = container->keywords.constBegin(); kit != container->keywords.constEnd();++kit )
+ {
+ QString text = ( *kit )->text();
+ if ( !fileKeywords.contains( text ) )
+ fileKeywords.append( text );
+ }
+ }
+ }
+ }
+
+ /**
+ * Merge keyword lists
+ */
+ Settings * settings = Settings::self( m_bibtexfile );
+ QStringList allKeywords = QStringList( fileKeywords );
+ for ( QStringList::Iterator it = settings->keyword_GlobalList.begin(); it != settings->keyword_GlobalList.end(); ++it )
+ if ( !allKeywords.contains( *it ) )
+ allKeywords.append( *it );
+ allKeywords.sort();
+
+ /**
+ * Build menu
+ */
+ bool popupEmpty = FALSE;
+ if ( allKeywords.isEmpty() )
+ popupEmpty = TRUE;
+ else if ( allKeywords.count() < 24 )
+ {
+ for ( QStringList::Iterator it = allKeywords.begin(); it != allKeywords.end(); ++it )
+ {
+ int i = popup->insertItem( *it );
+ popup->setItemChecked( i, entryKeywords.contains( *it ) );
+ m_assignKeywordsActionMenuURLs[i] = *it;
+ }
+ }
+ else
+ {
+ int maxCountPerSubMenu = ( int )sqrt( allKeywords.count() ) + 1;
+ int countPerSubMenu = 0;
+ KPopupMenu *subMenu = new KPopupMenu( popup );
+ connect( subMenu, SIGNAL( activated( int ) ), this, SLOT( slotAssignKeywords( int ) ) );
+ QString startWord, endWord;
+ for ( QStringList::Iterator it = allKeywords.begin(); it != allKeywords.end(); ++it )
+ {
+ if ( countPerSubMenu == 0 )
+ startWord = *it;
+ endWord = *it;
+ int i = subMenu->insertItem( *it );
+ subMenu->setItemChecked( i, entryKeywords.contains( *it ) );
+ m_assignKeywordsActionMenuURLs[i] = *it;
+
+ ++countPerSubMenu;
+ if ( countPerSubMenu >= maxCountPerSubMenu )
+ {
+ popup->insertItem( QString( i18n( "%1 ... %2" ) ).arg( startWord ).arg( endWord ), subMenu );
+ subMenu = new KPopupMenu( popup );
+ connect( subMenu, SIGNAL( activated( int ) ), this, SLOT( slotAssignKeywords( int ) ) );
+ countPerSubMenu = 0;
+ }
+ }
+
+ if ( countPerSubMenu > 0 )
+ {
+ popup->insertItem( QString( i18n( "%1 ... %2" ) ).arg( startWord ).arg( endWord ), subMenu );
+ }
+ else
+ delete subMenu;
+ }
+
+ if ( !popupEmpty )
+ popup->insertSeparator();
+
+ QWidget *container = new QWidget( popup );
+ container->setBackgroundColor( KGlobalSettings::baseColor() );
+ QHBoxLayout *layout = new QHBoxLayout( container, 1, 1 );
+ QLabel *label = new QLabel( i18n( "New keyword:" ), container );
+ label->setBackgroundColor( KGlobalSettings::baseColor() );
+ layout->addWidget( label );
+ m_lineEditNewKeyword = new KLineEdit( container );
+ layout->addWidget( m_lineEditNewKeyword );
+ container->setFocusProxy( m_lineEditNewKeyword );
+ container->setFocusPolicy( QWidget::ClickFocus );
+ popup->insertItem( container );
+
+ connect( m_lineEditNewKeyword, SIGNAL( returnPressed() ), this, SLOT( slotAddKeyword() ) );
+ }
+
+ void DocumentWidget::deferredInitialization()
+ {
+ restoreState();
+ m_listViewElements->deferredInitialization();
+ }
+
+ void DocumentWidget::saveState()
+ {
+ Settings * settings = Settings::self( m_bibtexfile );
+ settings->editing_HorSplitterSizes = m_horSplitter->sizes();
+ settings->editing_VertSplitterSizes = m_vertSplitter->sizes();
+ }
+
+ void DocumentWidget::restoreState()
+ {
+ m_listViewElements->restoreState();
+ m_searchBar->restoreState();
+ m_sideBar->restoreState();
+
+ Settings * settings = Settings::self( m_bibtexfile );
+ m_horSplitter->setSizes( settings->editing_HorSplitterSizes );
+ m_vertSplitter->setSizes( settings->editing_VertSplitterSizes );
+
+ if ( m_searchWebsitesActionMenu != NULL )
+ {
+ KPopupMenu * popup = m_searchWebsitesActionMenu->popupMenu();
+ popup->clear();
+ int i = 0;
+ for ( QValueList<Settings::SearchURL*>::ConstIterator it = settings->searchURLs.begin(); it != settings->searchURLs.end(); ++it )
+ popup->insertItem(( *it ) ->description, ++i );
+ }
+
+ if ( settings->editing_UseSpecialFont )
+ m_preview->setFont( settings->editing_SpecialFont );
+ else
+ m_preview->setFont( KGlobalSettings::generalFont() );
+
+ }
+
+ void DocumentWidget::executeElement( DocumentListViewItem* item )
+ {
+ Settings * settings = Settings::self( m_bibtexfile );
+ bool openingDocumentOK = FALSE;
+
+ if ( settings->editing_MainListDoubleClickAction == 1 )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( item->element() );
+ if ( entry != NULL )
+ {
+ /** prefer local urls over remote urls, so first check for file:// and use other protocols only if no file:// was found */
+ QString protocol = "file";
+ KURL::List urls = getEntryURLs( entry );
+ KURL selected = KURL();
+ while ( !selected.isValid() && protocol != QString::null )
+ {
+ for ( KURL::List::Iterator it = urls.begin(); !selected.isValid() && it != urls.end(); ++it )
+ {
+ KURL url = *it;
+ if ( url.isValid() && ( !url.isLocalFile() || QFile::exists( url.path() ) ) && url.protocol().startsWith( protocol ) )
+ selected = url;
+ }
+ /** little trick setting protocol prefix in the first round to "file://", then to "", and setting to null to quit the loop */
+ if ( !protocol.isEmpty() ) protocol = "";
+ else protocol = QString::null;
+ }
+
+ if ( selected.isValid() )
+ openingDocumentOK = Settings::openUrl( selected, this );
+ }
+ }
+
+ if ( !openingDocumentOK )
+ editElement( item );
+ }
+
+ bool DocumentWidget::editElement()
+ {
+ bool result = false;
+ QListViewItem * item = m_listViewElements->selectedItem();
+ if ( item == NULL )
+ item = m_listViewElements->currentItem();
+ DocumentListViewItem * dlvi = dynamic_cast<DocumentListViewItem*>( item );
+ if ( dlvi )
+ result = editElement( dlvi );
+ return result;
+ }
+
+ bool DocumentWidget::editElement( DocumentListViewItem*item )
+ {
+ BibTeX::Element * element = item->element();
+ bool result = editElement( element );
+ if ( result )
+ {
+ item->updateItem();
+ slotPreviewElement( item );
+ }
+ return result;
+ }
+
+ bool DocumentWidget::editElement( BibTeX::Element*element )
+ {
+ m_dirWatch.stopScan();
+ bool result = editElementDialog( element );
+ m_dirWatch.startScan( );
+
+ Settings * settings = Settings::self( m_bibtexfile );
+ settings->addToCompletion( element );
+ m_sideBar->refreshLists( m_bibtexfile );
+
+ return result;
+ }
+
+ bool DocumentWidget::editElementDialog( BibTeX::Element *element )
+ {
+ QDialog::DialogCode dialogResult = QDialog::Rejected;
+ BibTeX::Entry * entry = dynamic_cast<BibTeX::Entry*>( element );
+ if ( entry )
+ dialogResult = KBibTeX::EntryWidget::execute( entry, m_bibtexfile, m_isReadOnly, FALSE );
+ else
+ {
+ BibTeX::Comment * comment = dynamic_cast<BibTeX::Comment*>( element );
+ if ( comment )
+ dialogResult = KBibTeX::CommentWidget::execute( comment, m_isReadOnly );
+ else
+ {
+ BibTeX::Macro* macro = dynamic_cast<BibTeX::Macro*>( element );
+ if ( macro )
+ dialogResult = KBibTeX::MacroWidget::execute( macro, m_isReadOnly );
+ else
+ {
+ BibTeX::Preamble* preamble = dynamic_cast<BibTeX::Preamble*>( element );
+ if ( preamble )
+ dialogResult = KBibTeX::PreambleWidget::execute( preamble, m_isReadOnly );
+ }
+ }
+ }
+
+ if ( dialogResult == QDialog::Accepted )
+ slotModified();
+
+ return dialogResult == QDialog::Accepted;
+ }
+
+ void DocumentWidget::deleteElements()
+ {
+ if ( !m_isReadOnly )
+ {
+ if ( m_editMode == emList )
+ {
+ m_listViewElements->deleteSelected();
+ slotModified();
+ }
+ }
+ }
+
+ void DocumentWidget::sendSelectedToLyx()
+ {
+ if ( m_editMode == emList )
+ {
+ QValueList<BibTeX::Element*> elements = m_listViewElements->selectedItems();
+ QString genericMsg = i18n( "\n\nEither LyX is not running or has not been correctly configured to send references to." );
+ QString title = i18n( "Error communicating with LyX" );
+
+ Settings * settings = Settings::self( m_bibtexfile );
+ QString lyxPipeFilename = settings->detectLyXInPipe();
+ kdDebug() << "sendSelectedToLyx: lyxPipeFilename= " << lyxPipeFilename << endl;
+
+ if ( lyxPipeFilename.isNull() )
+ KMessageBox::error( this, i18n( "Cannot determine how to send references to LyX." ).append( genericMsg ), title );
+ else
+ {
+ QFile pipe( lyxPipeFilename );
+ if ( !pipe.exists() )
+ KMessageBox::error( this, i18n( "The inpipe as configured in LyX does not exist." ).append( genericMsg ), title );
+ else
+ {
+ if ( !pipe.open( IO_WriteOnly ) )
+ KMessageBox::error( this, i18n( "Cannot open the inpipe as configured in LyX." ).append( genericMsg ), title );
+ else
+ {
+ QStringList refsToSend;
+ for ( QValueList<BibTeX::Element*>::Iterator it = elements.begin(); it != elements.end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL ) refsToSend.append( entry->id() );
+ }
+
+ QTextStream * writer = new QTextStream( &pipe );
+ QString msg = "LYXCMD:kbibtex:citation-insert:" + refsToSend.join( "," );
+ *writer << msg << endl;
+ delete writer;
+ pipe.close();
+ }
+ }
+ }
+ }
+ }
+
+ void DocumentWidget::cutElements()
+ {
+ if ( !m_isReadOnly )
+ {
+ if ( m_editMode == emList )
+ {
+ m_listViewElements->cut();
+ }
+ else if ( m_editMode == emSource )
+ {
+ m_sourceView->cut();
+ }
+ slotModified();
+ }
+ }
+
+ void DocumentWidget::copyElements()
+ {
+ if ( m_editMode == emList )
+ {
+ m_listViewElements->copy();
+ }
+ else if ( m_editMode == emSource )
+ {
+ m_sourceView->copy();
+ }
+ }
+
+ void DocumentWidget::copyRefElements()
+ {
+ if ( m_editMode == emList )
+ {
+ m_listViewElements->copyReferences();
+ }
+ else if ( m_editMode == emSource )
+ {
+// TODO: Get selected text, parse text into BibTeX::File and join list of entries' ids
+ }
+ }
+
+ void DocumentWidget::pasteElements()
+ {
+ if ( !m_isReadOnly )
+ {
+ if ( m_editMode == emList )
+ {
+ if ( m_listViewElements->paste() )
+ slotModified();
+ }
+ else if ( m_editMode == emSource )
+ {
+ if ( m_sourceView->paste() )
+ slotModified();
+ }
+ }
+ }
+
+ void DocumentWidget::selectAll()
+ {
+ if ( m_editMode == emList )
+ m_listViewElements->selectAll();
+ else if ( m_editMode == emSource )
+ m_sourceView->selectAll();
+ }
+
+ void DocumentWidget::setReadOnly( bool isReadOnly )
+ {
+ m_isReadOnly = isReadOnly;
+ m_listViewElements->setReadOnly( m_isReadOnly );
+ m_sourceView->setReadOnly( m_isReadOnly );
+ m_sideBar->setReadOnly( m_isReadOnly );
+ }
+
+ void DocumentWidget::configureEditor()
+ {
+ m_sourceView->configureEditor();
+ }
+
+ void DocumentWidget::undoEditor()
+ {
+ m_sourceView->undo();
+ }
+
+ void DocumentWidget::find()
+ {
+ if ( m_editMode == emSource )
+ m_sourceView->find();
+ }
+ void DocumentWidget::findNext()
+ {
+ if ( m_editMode == emSource )
+ m_sourceView->findNext();
+ }
+
+ void DocumentWidget::slotShowProgress( int current, int total )
+ {
+ if ( m_progressDialog != NULL )
+ {
+ m_progressDialog->setProgress( current, total );
+ qApp->processEvents();
+ }
+ }
+
+ void DocumentWidget::startProgress( const QString & label, QObject * progressFrom )
+ {
+ m_progressDialog = new QProgressDialog( this );
+ m_progressDialog->setLabelText( label );
+ connect( progressFrom, SIGNAL( progress( int, int ) ), this, SLOT( slotShowProgress( int, int ) ) );
+ connect( m_progressDialog, SIGNAL( canceled() ), progressFrom, SLOT( cancel( ) ) );
+ QApplication::setOverrideCursor( Qt::waitCursor );
+ }
+
+ void DocumentWidget::endProgress( QObject * progressFrom )
+ {
+ disconnect( progressFrom, SIGNAL( progress( int, int ) ), this, SLOT( slotShowProgress( int, int ) ) );
+ disconnect( m_progressDialog, SIGNAL( canceled() ), progressFrom, SLOT( cancel( ) ) );
+ delete m_progressDialog;
+ m_progressDialog = NULL;
+ QApplication::restoreOverrideCursor();
+ }
+
+ void DocumentWidget::searchWebsites( const QString& searchURL, bool includeAuthor )
+ {
+ DocumentListViewItem * item = dynamic_cast<DocumentListViewItem*>( m_listViewElements->selectedItem() );
+ if ( item == NULL )
+ item = dynamic_cast<DocumentListViewItem*>( m_listViewElements->currentItem() );
+
+ if ( item != NULL )
+ searchWebsites( item->element(), searchURL, includeAuthor );
+ }
+
+ void DocumentWidget::searchWebsites( BibTeX::Element * element, const QString& searchURL, bool includeAuthor )
+ {
+ QString queryString = QString::null;
+
+ BibTeX::Entry* entry = dynamic_cast<BibTeX::Entry*>( element );
+ if ( entry != NULL )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftTitle );
+ if ( field && field->value() )
+ queryString = field->value() ->text();
+ if ( includeAuthor )
+ {
+ field = entry->getField( BibTeX::EntryField::ftAuthor );
+ if ( field && field->value() )
+ {
+ BibTeX::PersonContainer *personContainer = dynamic_cast<BibTeX::PersonContainer*>( field->value()->items.first() );
+ if ( personContainer != NULL )
+ {
+ QValueList<BibTeX::Person*> list = personContainer->persons;
+ for ( QValueList<BibTeX::Person*>::ConstIterator it = list.begin(); it != list.end(); ++it )
+ queryString = queryString.append( " " ).append(( *it )->lastName() );
+
+ }
+ }
+ }
+ }
+ else
+ {
+ BibTeX::Comment * comment = dynamic_cast<BibTeX::Comment*>( element );
+ if ( comment != NULL )
+ queryString = comment->text();
+ else
+ {
+ BibTeX::Macro * macro = dynamic_cast<BibTeX::Macro*>( element );
+ if ( macro != NULL && macro->value() )
+ queryString = macro->value() ->text();
+ else
+ kdDebug() << "Not yet supported" << endl;
+ }
+ }
+
+ if ( queryString != QString::null )
+ {
+ queryString = queryString.stripWhiteSpace().replace( '$', "" ).replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ).replace( '{', "" ).replace( '}', "" );
+ KURL url( QString( searchURL ).arg( queryString ) );
+ Settings::openUrl( url, this );
+ }
+ }
+
+ void DocumentWidget::onlineSearch()
+ {
+ if ( !m_isReadOnly )
+ {
+ BibTeX::FileExporter * exporter = new BibTeX::FileExporterBibTeX( );
+ QValueList<BibTeX::Entry*> list;
+ if ( WebQueryWizard::execute( this, list ) == QDialog::Accepted )
+ {
+ Settings * settings = Settings::self( m_bibtexfile );
+ for ( QValueList<BibTeX::Entry*>::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ ( *it )->setId( IdSuggestions::resolveConflict( m_bibtexfile, ( *it )->id() ) );
+ if ( m_editMode == emList )
+ m_listViewElements->insertItem( new BibTeX::Entry( *it ) );
+ else
+ {
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ bool result = exporter->save( &buffer, *it );
+ buffer.close();
+ if ( result )
+ {
+ buffer.open( IO_ReadOnly );
+ QTextStream textStream( &buffer );
+ textStream.setEncoding( QTextStream::UnicodeUTF8 );
+ QString text = textStream.read();
+ buffer.close();
+ QStringList lines = QStringList::split( '\n', text );
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
+ m_sourceView->insertLines( *it );
+ m_sourceView->insertLines( "" );
+ }
+
+ }
+ settings->addToCompletion( *it );
+ }
+
+ slotModified();
+ }
+ delete exporter;
+ }
+ }
+
+ void DocumentWidget::findDuplicates()
+ {
+ MergeElements *me = new MergeElements( this );
+ if ( me->mergeDuplicates( m_bibtexfile ) == QDialog::Accepted )
+ {
+ refreshBibTeXFile();
+ slotModified();
+ }
+ delete me;
+ }
+
+ void DocumentWidget::updateFromGUI()
+ {
+ BibTeX::File * file = NULL;
+ if ( currentPage() == m_sourceView )
+ file = m_sourceView->getBibTeXFile();
+ else if ( currentPage() == m_container )
+ file = m_listViewElements->getBibTeXFile();
+
+ if ( file != NULL && file != m_bibtexfile )
+ {
+ delete m_bibtexfile;
+ m_bibtexfile = file;
+ }
+ }
+
+ QString DocumentWidget::nextNewEntry()
+ {
+ QString name = QString( i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewEntry%1" ) ).arg( m_newElementCounter++ );
+
+ while ( m_bibtexfile->containsKey( name ) != NULL )
+ {
+ ++m_newElementCounter;
+ name = QString( i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewEntry%1" ) ).arg( m_newElementCounter++ );
+ }
+
+ return name;
+ }
+
+ KURL::List DocumentWidget::getEntryURLs( BibTeX::Entry *entry )
+ {
+ QStringList urls = entry->urls();
+ KURL::List result;
+
+ for ( QStringList::Iterator it = urls.begin(); it != urls.end(); ++it )
+ {
+ KURL url = Settings::locateFile( *it, m_bibtexfile->fileName, this );
+ if ( url.isValid() )
+ result.append( url );
+ }
+
+ return result;
+ }
+
+ void DocumentWidget::slotSelectionChanged()
+ {
+ int numSelected = 0;
+ QListViewItemIterator it( m_listViewElements, QListViewItemIterator::Selected );
+ while ( it.current() && numSelected < 3 )
+ {
+ numSelected++;
+ it++;
+ }
+
+ emit listViewSelectionChanged( numSelected );
+ }
+
+ BibTeX::FileImporter *DocumentWidget::fileImporterFactory( const QString &fileName )
+ {
+ Settings * settings = Settings::self( NULL );
+ BibTeX::FileImporter * importer = NULL;
+ BibTeX::File::FileFormat format = BibTeX::File::formatUndefined;
+
+ if ( fileName.endsWith( ".bib", FALSE ) )
+ format = BibTeX::File::formatBibTeX;
+ else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && ( fileName.endsWith( ".ref", FALSE ) || fileName.endsWith( ".refer", FALSE ) || fileName.endsWith( ".txt", FALSE ) || fileName.endsWith( ".rfr", FALSE ) ) )
+ format = BibTeX::File::formatEndNote;
+ else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && ( fileName.endsWith( ".isi", FALSE ) || fileName.endsWith( ".cgi", FALSE ) ) )
+ format = BibTeX::File::formatISI;
+ else if ( fileName.endsWith( ".ris", FALSE ) )
+ format = BibTeX::File::formatRIS;
+ else if ( fileName.endsWith( ".xml", FALSE ) )
+ {
+ QStringList options = QStringList::split( '|', ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable ? "MODS|EndNote XML|internal XML" : "internal XML" ) );
+ bool ok = false;
+ QString answer = KInputDialog::getItem( i18n( "Choose file format" ), QString( i18n( "Choose file format of file '%1':" ) ).arg( fileName ), options, 0, false, &ok, this );
+ if ( ok && !answer.isNull() && answer == "DocBook5" )
+ format = BibTeX::File::formatDocBook5;
+ else if ( ok && !answer.isNull() && answer == "MODS" )
+ format = BibTeX::File::formatMODS;
+ else if ( ok && !answer.isNull() && answer == "EndNote XML" )
+ format = BibTeX::File::formatEndNoteXML;
+ else if ( ok && !answer.isNull() && answer == "internal XML" )
+ format = BibTeX::File::formatXML;
+ }
+ else
+ {
+ QStringList options = QStringList::split( '|', ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable ? "BibTeX|EndNote|ISI|RIS" : "BibTeX|RIS" ) );
+ bool ok = false;
+ QString answer = KInputDialog::getItem( i18n( "Choose file format" ), QString( i18n( "Choose file format of file '%1':" ) ).arg( fileName ), options, 0, false, &ok, this );
+ if ( ok && !answer.isNull() && answer == "BibTeX" )
+ format = BibTeX::File::formatBibTeX;
+ else if ( ok && !answer.isNull() && answer == "EndNote" )
+ format = BibTeX::File::formatEndNote;
+ else if ( ok && !answer.isNull() && answer == "ISI" )
+ format = BibTeX::File::formatISI;
+ else if ( ok && !answer.isNull() && answer == "RIS" )
+ format = BibTeX::File::formatRIS;
+ }
+
+ if ( format != BibTeX::File::formatUndefined )
+ {
+ Settings * settings = Settings::self( NULL );
+ switch ( format )
+ {
+ case BibTeX::File::formatBibTeX:
+ {
+ Settings * settings = Settings::self( NULL );
+ importer = new BibTeX::FileImporterBibTeX( settings->editing_FirstNameFirst, settings->fileIO_Encoding );
+ }
+ break;
+ case BibTeX::File::formatRIS:
+ {
+ if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && settings->fileIO_useBibUtils )
+ importer = new BibTeX::FileImporterBibUtils( BibTeX::File::formatRIS );
+ else
+ importer = new BibTeX::FileImporterRIS( );
+ break;
+ }
+ case BibTeX::File::formatEndNote:
+ case BibTeX::File::formatEndNoteXML:
+ case BibTeX::File::formatISI:
+ case BibTeX::File::formatMODS:
+ if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable )
+ importer = new BibTeX::FileImporterBibUtils( format );
+ break;
+ default:
+ {
+ KMessageBox::sorry( this, QString( i18n( "The file '%1' does not contain a known type of bibliography." ) ).arg( fileName ), i18n( "Unknown file format" ) );
+ }
+ }
+ }
+
+ return importer;
+ }
+
+ void DocumentWidget::slotPreviewElement( QListViewItem * item )
+ {
+ if ( item == NULL )
+ item = m_listViewElements->selectedItem();
+ if ( item == NULL )
+ item = m_listViewElements->currentItem();
+ if ( item != NULL )
+ {
+ DocumentListViewItem * dlvi = dynamic_cast<DocumentListViewItem*>( item );
+ if ( dlvi != NULL && m_listViewElements->isEnabled() )
+ {
+ BibTeX::Element *currentElement = dlvi->element()->clone();
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( currentElement );
+ if ( entry != NULL )
+ m_bibtexfile->completeReferencedFields( entry );
+
+ KStandardDirs * kstd = KGlobal::dirs();
+
+ BibTeX::XSLTransform *transform = new BibTeX::XSLTransform( kstd->findResource( "data", "kbibtexpart/xslt/html.xsl" ) );
+ if ( transform != NULL )
+ {
+ BibTeX::FileExporterXSLT * exporter = new BibTeX::FileExporterXSLT( transform );
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ bool result = exporter->save( &buffer, currentElement );
+ buffer.close();
+
+ if ( result )
+ {
+ buffer.open( IO_ReadOnly );
+ QTextStream htmlTS( &buffer );
+ htmlTS.setEncoding( QTextStream::UnicodeUTF8 );
+ QString htmlText = htmlTS.read();
+ buffer.close();
+ QString text = htmlText.remove( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ).append( "</qt>" ).prepend( "<qt>" ).replace( QRegExp( "\\\\emph\\{([^}]+)\\}" ), "<em>\\1</em>" ).replace( QRegExp( "\\\\[A-Za-z0-9]+" ), "" ).replace( '{', "" ).replace( '}', "" );
+ m_preview->setText( text );
+ }
+ else
+ {
+ int i = ( int ) BibTeX::EntryField::ftTitle - ( int ) BibTeX::EntryField::ftAbstract + 2;
+ m_preview->setText( m_listViewElements->currentItem()->text( i ) );
+ }
+
+ delete exporter;
+ delete transform;
+ }
+ else
+ m_preview->setText( i18n( "No preview available" ) );
+
+ delete currentElement;
+ }
+ }
+ }
+
+ void DocumentWidget::slotTabChanged( QWidget *tab )
+ {
+ setEnabled( FALSE );
+ QApplication::setOverrideCursor( Qt::waitCursor );
+
+ BibTeX::File *bibTeXFile = NULL;
+ if ( m_editMode == emSource )
+ bibTeXFile = m_sourceView->getBibTeXFile();
+ else if ( m_editMode == emList )
+ bibTeXFile = m_listViewElements->getBibTeXFile();
+
+ if ( tab == m_sourceView && m_editMode != emSource )
+ {
+ // switching from list view to source view
+ if ( bibTeXFile != NULL )
+ {
+ // check whether the selected widget has changed the bibtex file
+ if ( bibTeXFile != m_bibtexfile )
+ {
+ delete m_bibtexfile;
+ m_bibtexfile = bibTeXFile;
+ }
+ m_sourceView->setBibTeXFile( m_bibtexfile );
+ }
+ m_editMode = emSource;
+
+ if ( m_actionEditCut && m_actionEditCopy && m_actionEditPaste )
+ {
+ m_actionEditCut->setEnabled( TRUE );
+ m_actionEditCopy->setEnabled( TRUE );
+ m_actionEditPaste->setEnabled( TRUE );
+ }
+ }
+ else if ( tab == m_container && m_editMode != emList )
+ {
+ // switching from source view to list view
+ if ( bibTeXFile != NULL )
+ {
+ // check whether the selected widget has changed the bibtex file
+ if ( bibTeXFile != m_bibtexfile )
+ {
+ delete m_bibtexfile;
+ m_bibtexfile = bibTeXFile;
+
+ Settings * settings = Settings::self( m_bibtexfile );
+ settings->addToCompletion( m_bibtexfile );
+ m_sideBar->refreshLists( m_bibtexfile );
+ }
+ m_listViewElements->setBibTeXFile( m_bibtexfile );
+ emit listViewSelectionChanged( 0 );
+ }
+ m_editMode = emList;
+ }
+
+ setEnabled( TRUE );
+
+ if ( tab == m_sourceView )
+ m_sourceView->setFocus();
+ else if ( tab == m_container )
+ m_listViewElements->setFocus();
+
+ if ( m_actionEditFind && m_actionEditFindNext )
+ {
+ m_actionEditFind->setEnabled( m_editMode == emSource );
+ m_actionEditFindNext->setEnabled( m_editMode == emSource );
+ }
+ if ( m_actionEditCopyRef )
+ m_actionEditCopyRef->setEnabled( m_editMode == emList );
+
+ QApplication::restoreOverrideCursor();
+
+ emit undoChanged( m_editMode == emSource );
+ }
+
+ void DocumentWidget::slotModified()
+ {
+ if ( isEnabled() )
+ {
+ m_sideBar->refreshLists( m_bibtexfile );
+ emit modified( );
+ }
+ }
+
+ void DocumentWidget::slotFileGotDirty( const QString& path )
+ {
+ if ( path == m_filename )
+ {
+ m_dirWatch.removeFile( m_filename );
+ QTimer::singleShot( 100, this, SLOT( slotRefreshDirtyFile( ) ) );
+ }
+ }
+
+ void DocumentWidget::slotRefreshDirtyFile()
+ {
+ if ( KMessageBox::questionYesNo( this, QString( i18n( "File '%1' has been modified. Reload file to import changes or ignore changes?" ) ).arg( m_filename ), i18n( "Reload file?" ), KGuiItem( i18n( "Reload" ), "reload" ), KGuiItem( i18n( "Ignore" ), "ignore" ) ) == KMessageBox::Yes )
+ open( m_filename, FALSE );
+ else
+ m_dirWatch.addFile( m_filename );
+ }
+
+ void DocumentWidget::slotViewDocument( int id )
+ {
+ Settings::openUrl( m_viewDocumentActionMenuURLs[ m_viewDocumentActionMenu->popupMenu() ->indexOf( id )], this );
+ }
+
+ void DocumentWidget::slotViewFirstDocument()
+ {
+ for ( QStringList::Iterator it = m_viewDocumentActionMenuURLs.begin(); it != m_viewDocumentActionMenuURLs.end(); ++it )
+ if (( *it ).endsWith( ".pdf" ) || ( *it ).endsWith( ".ps" ) || ( *it ).endsWith( ".djv" ) )
+ {
+ Settings::openUrl( *it, this );
+ break;
+ }
+ }
+
+ void DocumentWidget::slotViewFirstDocumentsOnlineRef()
+ {
+ for ( QStringList::Iterator it = m_viewDocumentActionMenuURLs.begin(); it != m_viewDocumentActionMenuURLs.end(); ++it )
+ if (( *it ).contains( "dx.doi.org" ) )
+ {
+ Settings::openUrl( *it, this );
+ break;
+ }
+ }
+
+ void DocumentWidget::slotAssignKeywords( int id )
+ {
+ QValueList<BibTeX::Entry*> entryList;
+
+ QListViewItem * item = m_listViewElements->selectedItem();
+ if ( item == NULL )
+ item = m_listViewElements->currentItem();
+ for ( QListViewItemIterator it( m_listViewElements, QListViewItemIterator::Selected ); it.current(); ++it )
+ {
+ BibTeX::Element * currentElement = NULL;
+ DocumentListViewItem * dlvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ if ( dlvi && (( currentElement = dlvi->element() ) != NULL ) )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( currentElement );
+ if ( entry != NULL )
+ entryList << entry;
+ }
+ }
+
+ for ( QValueList<BibTeX::Entry*>::Iterator it = entryList.begin(); it != entryList.end(); ++it )
+ {
+ BibTeX::Entry *entry = *it;
+ BibTeX::EntryField *field = NULL;
+ BibTeX::KeywordContainer *keywordContainer = NULL;
+ if (( field = entry->getField( BibTeX::EntryField::ftKeywords ) ) == NULL )
+ {
+ entry->addField( field = new BibTeX::EntryField( BibTeX::EntryField::ftKeywords ) );
+ }
+
+ BibTeX::Value *value = field->value();
+
+ if ( !value->items.isEmpty() )
+ keywordContainer = dynamic_cast<BibTeX::KeywordContainer*>( value->items.first() );
+
+ if ( keywordContainer == NULL )
+ value->items.append( keywordContainer = new BibTeX::KeywordContainer() );
+
+ if ( m_assignKeywordsActionMenu->popupMenu() ->isItemChecked( id ) )
+ keywordContainer->remove( m_assignKeywordsActionMenuURLs[ id ] );
+ else
+ keywordContainer->append( m_assignKeywordsActionMenuURLs[ id ] );
+
+ slotModified();
+ }
+ }
+
+ void DocumentWidget::slotAddKeyword()
+ {
+ QString newKeyword = m_lineEditNewKeyword->text();
+
+ QValueList<BibTeX::Entry*> entryList;
+ for ( QListViewItemIterator it( m_listViewElements, QListViewItemIterator::Selected ); it.current(); ++it )
+ {
+ BibTeX::Element * currentElement = NULL;
+ DocumentListViewItem * dlvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ if ( dlvi && (( currentElement = dlvi->element() ) != NULL ) )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( currentElement );
+ if ( entry != NULL )
+ entryList << entry;
+ }
+ }
+
+ for ( QValueList<BibTeX::Entry*>::Iterator it = entryList.begin(); it != entryList.end(); ++it )
+ {
+ BibTeX::Entry *entry = *it;
+ BibTeX::EntryField *field = entry->getField( BibTeX::EntryField::ftKeywords );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftKeywords );
+ entry->addField( field );
+ }
+
+ BibTeX::Value *value = field->value();
+ BibTeX::KeywordContainer *keywordContainer = NULL;
+
+ if ( !value->items.isEmpty() )
+ keywordContainer = dynamic_cast<BibTeX::KeywordContainer*>( value->items.first() );
+
+ if ( keywordContainer == NULL )
+ value->items.append( keywordContainer = new BibTeX::KeywordContainer() );
+
+ keywordContainer->append( newKeyword );
+ }
+
+ if ( !entryList.isEmpty() )
+ {
+ if ( m_lineEditNewKeyword->isVisible() &&
+ m_lineEditNewKeyword->parentWidget() &&
+ m_lineEditNewKeyword->parentWidget()->parentWidget() &&
+ m_lineEditNewKeyword->parentWidget()->parentWidget()->inherits( "QPopupMenu" ) )
+ m_lineEditNewKeyword->parentWidget()->parentWidget()->close();
+
+ slotModified();
+ }
+ }
+
+ void DocumentWidget::slotNormalizeIds()
+ {
+ Settings * settings = Settings::self();
+ QMap<BibTeX::Entry*, QString> entryToNewId;
+ QMap<BibTeX::Entry*, DocumentListViewItem*> entryToItem;
+ QStringList msgList;
+
+ if ( settings->idSuggestions_default < 0 )
+ {
+ KMessageBox::sorry( this, i18n( "You must set a default id suggestion in the settings dialog." ) );
+ return;
+ }
+
+ for ( QListViewItemIterator it( m_listViewElements, QListViewItemIterator::Selected ); it.current(); ++it )
+ {
+ BibTeX::Element * currentElement = NULL;
+ DocumentListViewItem * dlvi = dynamic_cast<DocumentListViewItem*>( it.current() );
+ if ( dlvi && (( currentElement = dlvi->element() ) != NULL ) )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( currentElement );
+ if ( entry != NULL )
+ {
+ QString newEntryId = IdSuggestions::createDefaultSuggestion( m_bibtexfile, entry );
+ entryToNewId[entry] = newEntryId;
+ entryToItem[entry] = dlvi;
+ msgList << "Replacing id of entry \"" + entry->id() + "\" with new id \"" + newEntryId + "\"";
+ }
+ }
+ }
+
+ if ( entryToNewId.isEmpty() )
+ KMessageBox::information( this, i18n( "No entries were selected." ) );
+ else if ( KMessageBox::questionYesNoList( this, i18n( "The following changes will be applied to the currently selected elements.\nConflicts with duplicate entry ids will be resolved when applying the new ids." ), msgList, i18n( "Normalize Entry Ids" ), KGuiItem( i18n( "Replace Entry Ids" ), "run" ), KGuiItem( i18n( "Cancel" ), "cancel" ) ) == KMessageBox::Yes )
+ {
+ QApplication::setOverrideCursor( Qt::waitCursor );
+ QMap<BibTeX::Entry*, DocumentListViewItem*>::Iterator itItem = entryToItem.begin();
+ for ( QMap<BibTeX::Entry*, QString>::Iterator it = entryToNewId.begin(); it != entryToNewId.end(); ++it, ++itItem )
+ {
+ BibTeX::Entry *entry = it.key();
+ QString newEntryId = it.data();
+ newEntryId = IdSuggestions::resolveConflict( m_bibtexfile, newEntryId, entry );
+ qDebug( "Replacing id of entry \"%s\" with new id \"%s\"", entry->id().latin1(), newEntryId.latin1() );
+ entry->setId( newEntryId );
+ itItem.data()->updateItem();
+ }
+ slotModified();
+ m_sideBar->refreshLists( m_bibtexfile );
+ QApplication::restoreOverrideCursor();
+ }
+ }
+
+ KDirWatch &DocumentWidget::dirWatch()
+ {
+ return m_dirWatch;
+ }
+
+}
+
+#include "documentwidget.moc"
diff --git a/src/documentwidget.h b/src/documentwidget.h
new file mode 100644
index 0000000..cc6e344
--- /dev/null
+++ b/src/documentwidget.h
@@ -0,0 +1,174 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXDOCUMENTWIDGET_H
+#define KBIBTEXDOCUMENTWIDGET_H
+
+#include <qtabwidget.h>
+
+#include <kdirwatch.h>
+
+#include <fileimporter.h>
+#include <file.h>
+#include <settings.h>
+
+class QIODevice;
+class QProgressDialog;
+class QListViewItem;
+class QWidget;
+class QSplitter;
+
+class KPopupMenu;
+class KActionMenu;
+class KURL;
+class KTextEdit;
+class KLineEdit;
+
+namespace KBibTeX
+{
+ class DocumentListView;
+ class DocumentListViewItem;
+ class DocumentSourceView;
+ class SearchBar;
+ class SideBar;
+ class WebQuery;
+
+ class DocumentWidget : public QTabWidget
+ {
+ Q_OBJECT
+ public:
+ DocumentWidget( bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~DocumentWidget();
+
+ bool open( const QString &fileName, bool mergeOnly = FALSE );
+ bool open( QIODevice *iodevice, bool mergeOnly = FALSE, const QString &label = QString::null, BibTeX::FileImporter *importer = NULL );
+ bool save( const QString &fileName, QStringList *errorLog = NULL );
+ bool save( QIODevice *iodevice, BibTeX::File::FileFormat format = BibTeX::File::formatBibTeX, const QString &label = QString::null, QStringList *errorLog = NULL );
+
+ bool newElement( const QString& elementType );
+ void searchWebsites( const QString& searchURL, bool includeAuthor );
+ void updateViews();
+ void showStatistics();
+
+ void setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client );
+ void updateViewDocumentMenu( );
+ void updateAssignKeywords( );
+
+ void deferredInitialization();
+ void saveState();
+ void restoreState();
+
+ KDirWatch &dirWatch();
+
+ signals:
+ void modified();
+ void listViewSelectionChanged( int numSelected );
+ void undoChanged( bool undoAvailable );
+
+ public slots:
+ void executeElement( DocumentListViewItem* );
+ bool editElement();
+ bool editElement( DocumentListViewItem* );
+ bool editElement( BibTeX::Element* );
+ void deleteElements();
+ void sendSelectedToLyx();
+ void cutElements();
+ void copyElements();
+ void copyRefElements();
+ void pasteElements();
+ void selectAll();
+ void setReadOnly( bool isReadOnly );
+ void configureEditor();
+ void undoEditor();
+ void find();
+ void findNext();
+ void refreshBibTeXFile();
+ void onlineSearch();
+ void findDuplicates();
+ void slotViewFirstDocument();
+ void slotViewFirstDocumentsOnlineRef();
+ void slotNormalizeIds();
+
+ private:
+ enum EditMode
+ {
+ emList, emSource
+ };
+
+ KLineEdit *m_lineEditNewKeyword;
+ bool m_isReadOnly;
+ QSplitter *m_horSplitter;
+ QSplitter *m_vertSplitter;
+ QWidget *m_container;
+ SearchBar *m_searchBar;
+ DocumentListView *m_listViewElements;
+ KTextEdit * m_preview;
+ DocumentSourceView *m_sourceView;
+ SideBar* m_sideBar;
+ BibTeX::File *m_bibtexfile;
+ QString m_filename;
+ QProgressDialog *m_progressDialog;
+ int m_newElementCounter;
+ EditMode m_editMode;
+ KActionMenu *m_viewDocumentActionMenu;
+ KActionMenu *m_assignKeywordsActionMenu;
+ QStringList m_viewDocumentActionMenuURLs;
+ QMap<int, QString> m_assignKeywordsActionMenuURLs;
+ KActionMenu *m_searchWebsitesActionMenu;
+ KAction *m_actionEditCut;
+ KAction *m_actionEditCopy;
+ KAction *m_actionEditCopyRef;
+ KAction *m_actionEditPaste;
+ KAction *m_actionEditSelectAll;
+ KAction *m_actionEditFind;
+ KAction *m_actionEditFindNext;
+ KAction *m_actionNormalizeIds;
+ KDirWatch m_dirWatch;
+
+ void setupGUI();
+
+ void startProgress( const QString &label, QObject *progressFrom );
+ void endProgress( QObject *progressFrom );
+
+ void searchWebsites( BibTeX::Element *element, const QString& searchURL, bool includeAuthor );
+
+ bool editElementDialog( BibTeX::Element *element );
+ void updateFromGUI();
+ QString nextNewEntry();
+
+ KURL::List getEntryURLs( BibTeX::Entry *entry );
+
+ BibTeX::FileImporter *fileImporterFactory( const QString &fileName );
+
+ private slots:
+ void slotShowProgress( int current, int total );
+ void slotSelectionChanged();
+ void slotPreviewElement( QListViewItem * item = NULL );
+ void slotTabChanged( QWidget *tab );
+ void slotModified();
+ void slotFileGotDirty( const QString& path );
+ void slotRefreshDirtyFile();
+ void slotViewDocument( int id );
+ void slotAssignKeywords( int id );
+ void slotAddKeyword();
+ };
+
+}
+
+#endif
diff --git a/src/element.cpp b/src/element.cpp
new file mode 100644
index 0000000..73b3178
--- /dev/null
+++ b/src/element.cpp
@@ -0,0 +1,50 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qstring.h>
+
+#include <xsltransform.h>
+#include "element.h"
+
+namespace BibTeX
+{
+
+
+ Element::Element( )
+ {
+ // nothing
+ }
+
+ Element::~Element()
+ {
+ // nothing
+ }
+
+ bool Element::isSimpleString( const QString &text )
+ {
+ bool result = TRUE;
+ const QString goodChars = "abcdefghijklmnopqrstuvwxyz0123456789-_";
+
+ for ( unsigned int i = 0; result && i < text.length(); i++ )
+ result &= goodChars.contains( text.at( i ), FALSE );
+
+ return result;
+ }
+
+}
diff --git a/src/element.h b/src/element.h
new file mode 100644
index 0000000..1955383
--- /dev/null
+++ b/src/element.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXELEMENT_H
+#define BIBTEXELEMENT_H
+
+#include <file.h>
+#include <entryfield.h>
+
+class QString;
+
+namespace BibTeX
+{
+
+ class Element
+ {
+ public:
+ enum FilterType {ftExact, ftEveryWord, ftAnyWord};
+
+ Element();
+ virtual ~Element();
+
+ virtual bool containsPattern( const QString& /* pattern */, BibTeX::EntryField::FieldType /* fieldType */, FilterType /* filterType */ = BibTeX::Element::ftExact, bool /* caseSensitive */ = false ) const = 0;
+ virtual Element* clone() = 0;
+ virtual QString text() const = 0;
+
+ static bool isSimpleString( const QString &text );
+
+ };
+
+}
+
+#endif
diff --git a/src/encoder.cpp b/src/encoder.cpp
new file mode 100644
index 0000000..394e7d0
--- /dev/null
+++ b/src/encoder.cpp
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "encoder.h"
+
+namespace BibTeX
+{
+// nothing
+}
diff --git a/src/encoder.h b/src/encoder.h
new file mode 100644
index 0000000..7997b8e
--- /dev/null
+++ b/src/encoder.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXENCODER_H
+#define BIBTEXENCODER_H
+
+#include <entryfield.h>
+
+class QString;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class Encoder
+ {
+ public:
+ virtual ~Encoder() { /* nothing */};
+
+ virtual QString decode( const QString & /*text*/ )
+ {
+ return QString::null;
+ };
+ virtual QString encode( const QString & /*text*/ )
+ {
+ return QString::null;
+ };
+ virtual QString encodeSpecialized( const QString & /*text*/, const EntryField::FieldType /*fieldType*/ = EntryField::ftUnknown )
+ {
+ return QString::null;
+ };
+ };
+
+}
+
+#endif
diff --git a/src/encoderlatex.cpp b/src/encoderlatex.cpp
new file mode 100644
index 0000000..f111848
--- /dev/null
+++ b/src/encoderlatex.cpp
@@ -0,0 +1,876 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qstring.h>
+#include <qapplication.h>
+#include <qregexp.h>
+
+#include "encoderlatex.h"
+
+namespace BibTeX
+{
+ EncoderLaTeX *EncoderLaTeX::encoderLaTeX = NULL;
+
+ static struct Decomposition
+ {
+ const char *latexCommand;
+ unsigned int unicode;
+ }
+ decompositions[] =
+ {
+ {"`", 0x0300},
+ {"'", 0x0301},
+ {"^", 0x0302},
+ {"~", 0x0303},
+ {"=", 0x0304},
+ /*{"x", 0x0305}, OVERLINE */
+ {"u", 0x0306},
+ {".", 0x0307},
+ /*{"x", 0x0309}, HOOK ABOVE */
+ {"r", 0x030a},
+ {"H", 0x030b},
+ {"v", 0x030c},
+ /*{"x", 0x030d}, VERTICAL LINE ABOVE */
+ /*{"x", 0x030e}, DOUBLE VERTICAL LINE ABOVE */
+ /*{"x", 0x030f}, DOUBLE GRAVE ACCENT */
+ /*{"x", 0x0310}, CANDRABINDU */
+ /*{"x", 0x0311}, INVERTED BREVE */
+ /*{"x", 0x0312}, TURNED COMMA ABOVE */
+ /*{"x", 0x0313}, COMMA ABOVE */
+ /*{"x", 0x0314}, REVERSED COMMA ABOVE */
+ /*{"x", 0x0315}, */
+ /*{"x", 0x0316}, */
+ /*{"x", 0x0317}, */
+ /*{"x", 0x0318}, */
+ /*{"x", 0x0319}, */
+ /*{"x", 0x031a}, */
+ /*{"x", 0x031b}, */
+ /*{"x", 0x031c}, */
+ /*{"x", 0x031d}, */
+ /*{"x", 0x031e}, */
+ /*{"x", 0x031f}, */
+ /*{"x", 0x0320}, */
+ /*{"x", 0x0321}, */
+ /*{"x", 0x0322}, */
+ {"d", 0x0323},
+ /*{"x", 0x0324}, */
+ /*{"x", 0x0325}, */
+ /*{"x", 0x0326}, */
+ {"d", 0x0327},
+ {"k", 0x0328},
+ /*{"x", 0x0329}, */
+ /*{"x", 0x032a}, */
+ /*{"x", 0x032b}, */
+ /*{"x", 0x032c}, */
+ /*{"x", 0x032d}, */
+ /*{"x", 0x032e}, */
+ /*{"x", 0x032f}, */
+ {"b", 0x0331},
+ {"t", 0x0361}
+ };
+
+ static const int decompositionscount = sizeof( decompositions ) / sizeof( decompositions[ 0 ] ) ;
+
+ static const struct EncoderLaTeXCommandMapping
+ {
+ const char *letters;
+ unsigned int unicode;
+ }
+ commandmappingdatalatex[] =
+ {
+ {"AA", 0x00C5},
+ {"AE", 0x00C6},
+ {"ss", 0x00DF},
+ {"aa", 0x00E5},
+ {"ae", 0x00E6},
+ {"OE", 0x0152},
+ {"oe", 0x0153},
+ {"ldots", 0x2026},
+ {"L", 0x0141},
+ {"l", 0x0142},
+ {"grqq", 0x201C},
+ {"glqq", 0x201E},
+ {"frqq", 0x00BB},
+ {"flqq", 0x00AB},
+
+// awk -F '[{}\\\\]+' '/DeclareUnicodeCharacter/ { print "{\""$4"\", 0x"$3"},"}' /usr/share/texmf-dist/tex/latex/base/t2aenc.dfu | grep '0x04' | sort -r -f
+ {"cyrzhdsc", 0x0497},
+ {"CYRZHDSC", 0x0496},
+ {"cyrzh", 0x0436},
+ {"CYRZH", 0x0416},
+ {"cyrzdsc", 0x0499},
+ {"CYRZDSC", 0x0498},
+ {"cyrz", 0x0437},
+ {"CYRZ", 0x0417},
+ {"cyryu", 0x044E},
+ {"CYRYU", 0x042E},
+ {"cyryo", 0x0451},
+ {"CYRYO", 0x0401},
+ {"cyryi", 0x0457},
+ {"CYRYI", 0x0407},
+ {"cyryhcrs", 0x04B1},
+ {"CYRYHCRS", 0x04B0},
+ {"cyrya", 0x044F},
+ {"CYRYA", 0x042F},
+ {"cyry", 0x04AF},
+ {"CYRY", 0x04AE},
+ {"cyrv", 0x0432},
+ {"CYRV", 0x0412},
+ {"cyrushrt", 0x045E},
+ {"CYRUSHRT", 0x040E},
+ {"cyru", 0x0443},
+ {"CYRU", 0x0423},
+ {"cyrtshe", 0x045B},
+ {"CYRTSHE", 0x040B},
+ {"cyrtdsc", 0x04AD},
+ {"CYRTDSC", 0x04AC},
+ {"cyrt", 0x0442},
+ {"CYRT", 0x0422},
+ {"cyrshha", 0x04BB},
+ {"CYRSHHA", 0x04BA},
+ {"cyrshch", 0x0449},
+ {"CYRSHCH", 0x0429},
+ {"cyrsh", 0x0448},
+ {"CYRSH", 0x0428},
+ {"cyrsftsn", 0x044C},
+ {"CYRSFTSN", 0x042C},
+ {"cyrsdsc", 0x04AB},
+ {"CYRSDSC", 0x04AA},
+ {"cyrschwa", 0x04D9},
+ {"CYRSCHWA", 0x04D8},
+ {"cyrs", 0x0441},
+ {"CYRS", 0x0421},
+ {"cyrr", 0x0440},
+ {"CYRR", 0x0420},
+ {"CYRpalochka", 0x04C0},
+ {"cyrp", 0x043F},
+ {"CYRP", 0x041F},
+ {"cyrotld", 0x04E9},
+ {"CYROTLD", 0x04E8},
+ {"cyro", 0x043E},
+ {"CYRO", 0x041E},
+ {"cyrnje", 0x045A},
+ {"CYRNJE", 0x040A},
+ {"cyrng", 0x04A5},
+ {"CYRNG", 0x04A4},
+ {"cyrndsc", 0x04A3},
+ {"CYRNDSC", 0x04A2},
+ {"cyrn", 0x043D},
+ {"CYRN", 0x041D},
+ {"cyrm", 0x043C},
+ {"CYRM", 0x041C},
+ {"cyrlje", 0x0459},
+ {"CYRLJE", 0x0409},
+ {"cyrl", 0x043B},
+ {"CYRL", 0x041B},
+ {"cyrkvcrs", 0x049D},
+ {"CYRKVCRS", 0x049C},
+ {"cyrkdsc", 0x049B},
+ {"CYRKDSC", 0x049A},
+ {"cyrk", 0x043A},
+ {"CYRK", 0x041A},
+ {"cyrje", 0x0458},
+ {"CYRJE", 0x0408},
+ {"cyrishrt", 0x0439},
+ {"CYRISHRT", 0x0419},
+ {"cyrii", 0x0456},
+ {"CYRII", 0x0406},
+ {"cyrie", 0x0454},
+ {"CYRIE", 0x0404},
+ {"cyri", 0x0438},
+ {"CYRI", 0x0418},
+ {"cyrhrdsn", 0x044A},
+ {"CYRHRDSN", 0x042A},
+ {"cyrhdsc", 0x04B3},
+ {"CYRHDSC", 0x04B2},
+ {"cyrh", 0x0445},
+ {"CYRH", 0x0425},
+ {"cyrgup", 0x0491},
+ {"CYRGUP", 0x0490},
+ {"cyrghcrs", 0x0493},
+ {"CYRGHCRS", 0x0492},
+ {"cyrg", 0x0433},
+ {"CYRG", 0x0413},
+ {"cyrf", 0x0444},
+ {"CYRF", 0x0424},
+ {"cyrery", 0x044B},
+ {"CYRERY", 0x042B},
+ {"cyrerev", 0x044D},
+ {"CYREREV", 0x042D},
+ {"cyre", 0x0435},
+ {"CYRE", 0x0415},
+ {"cyrdzhe", 0x045F},
+ {"CYRDZHE", 0x040F},
+ {"cyrdze", 0x0455},
+ {"CYRDZE", 0x0405},
+ {"cyrdje", 0x0452},
+ {"CYRDJE", 0x0402},
+ {"cyrd", 0x0434},
+ {"CYRD", 0x0414},
+ {"cyrchvcrs", 0x04B9},
+ {"CYRCHVCRS", 0x04B8},
+ {"cyrchrdsc", 0x04B7},
+ {"CYRCHRDSC", 0x04B6},
+ {"cyrch", 0x0447},
+ {"CYRCH", 0x0427},
+ {"cyrc", 0x0446},
+ {"CYRC", 0x0426},
+ {"cyrb", 0x0431},
+ {"CYRB", 0x0411},
+ {"cyrae", 0x04D5},
+ {"CYRAE", 0x04D4},
+ {"cyra", 0x0430},
+ {"CYRA", 0x0410}
+ };
+
+ static const int commandmappingdatalatexcount = sizeof( commandmappingdatalatex ) / sizeof( commandmappingdatalatex[ 0 ] ) ;
+
+ /** Command can be either
+ (1) {embraced}
+ (2) delimited by {},
+ (3) <space>, line end,
+ (4) \following_command (including \<space>, which must be maintained!),
+ (5) } (end of entry or group)
+ **/
+ const char *expansionsCmd[] = {"\\{\\\\%1\\}", "\\\\%1\\{\\}", "\\\\%1(\\n|\\r|\\\\|\\})", "\\\\%1\\s"};
+ static const int expansionscmdcount = sizeof( expansionsCmd ) / sizeof( expansionsCmd[0] );
+
+ static const struct EncoderLaTeXModCharMapping
+ {
+ const char *modifier;
+ const char *letter;
+ unsigned int unicode;
+ }
+ modcharmappingdatalatex[] =
+ {
+ {"\\\\`", "A", 0x00C0},
+ {"\\\\'", "A", 0x00C1},
+ {"\\\\\\^", "A", 0x00C2},
+ {"\\\\~", "A", 0x00C3},
+ {"\\\\\"", "A", 0x00C4},
+ {"\\\\r", "A", 0x00C5},
+ /** 0x00C6 */
+ {"\\\\c", "C", 0x00C7},
+ {"\\\\`", "E", 0x00C8},
+ {"\\\\'", "E", 0x00C9},
+ {"\\\\\\^", "E", 0x00CA},
+ {"\\\\\"", "E", 0x00CB},
+ {"\\\\`", "I", 0x00CC},
+ {"\\\\'", "I", 0x00CD},
+ {"\\\\\\^", "I", 0x00CE},
+ {"\\\\\"", "I", 0x00CF},
+ /** 0x00D0 */
+ {"\\\\~", "N", 0x00D1},
+ {"\\\\`", "O", 0x00D2},
+ {"\\\\'", "O", 0x00D3},
+ {"\\\\\\^", "O", 0x00D4},
+ /** 0x00D5 */
+ {"\\\\\"", "O", 0x00D6},
+ /** 0x00D7 */
+ {"\\\\", "O", 0x00D8},
+ {"\\\\`", "U", 0x00D9},
+ {"\\\\'", "U", 0x00DA},
+ {"\\\\\\^", "U", 0x00DB},
+ {"\\\\\"", "U", 0x00DC},
+ {"\\\\'", "Y", 0x00DD},
+ /** 0x00DE */
+ {"\\\\\"", "s", 0x00DF},
+ {"\\\\`", "a", 0x00E0},
+ {"\\\\'", "a", 0x00E1},
+ {"\\\\\\^", "a", 0x00E2},
+ {"\\\\~", "a", 0x00E3},
+ {"\\\\\"", "a", 0x00E4},
+ {"\\\\r", "a", 0x00E5},
+ /** 0x00E6 */
+ {"\\\\c", "c", 0x00E7},
+ {"\\\\`", "e", 0x00E8},
+ {"\\\\'", "e", 0x00E9},
+ {"\\\\\\^", "e", 0x00EA},
+ {"\\\\\"", "e", 0x00EB},
+ {"\\\\`", "i", 0x00EC},
+ {"\\\\'", "i", 0x00ED},
+ {"\\\\'", "\\\\i", 0x00ED},
+ {"\\\\\\^", "i", 0x00EE},
+ /** 0x00EF */
+ /** 0x00F0 */
+ {"\\\\~", "n", 0x00F1},
+ {"\\\\`", "o", 0x00F2},
+ {"\\\\'", "o", 0x00F3},
+ {"\\\\\\^", "o", 0x00F4},
+ /** 0x00F5 */
+ {"\\\\\"", "o", 0x00F6},
+ /** 0x00F7 */
+ {"\\\\", "o", 0x00F8},
+ {"\\\\`", "u", 0x00F9},
+ {"\\\\'", "u", 0x00FA},
+ {"\\\\\\^", "u", 0x00FB},
+ {"\\\\\"", "u", 0x00FC},
+ {"\\\\'", "y", 0x00FD},
+ /** 0x00FE */
+ /** 0x00FF */
+ /** 0x0100 */
+ /** 0x0101 */
+ {"\\\\u", "A", 0x0102},
+ {"\\\\u", "a", 0x0103},
+ /** 0x0104 */
+ /** 0x0105 */
+ {"\\\\'", "C", 0x0106},
+ {"\\\\'", "c", 0x0107},
+ /** 0x0108 */
+ /** 0x0109 */
+ /** 0x010A */
+ /** 0x010B */
+ {"\\\\v", "C", 0x010C},
+ {"\\\\v", "c", 0x010D},
+ {"\\\\v", "D", 0x010E},
+ /** 0x010F */
+ /** 0x0110 */
+ /** 0x0111 */
+ /** 0x0112 */
+ /** 0x0113 */
+ /** 0x0114 */
+ /** 0x0115 */
+ /** 0x0116 */
+ /** 0x0117 */
+ {"\\\\c", "E", 0x0118},
+ {"\\\\c", "e", 0x0119},
+ {"\\\\v", "E", 0x011A},
+ {"\\\\v", "e", 0x011B},
+ /** 0x011C */
+ /** 0x011D */
+ {"\\\\u", "G", 0x011E},
+ {"\\\\u", "g", 0x011F},
+ /** 0x0120 */
+ /** 0x0121 */
+ /** 0x0122 */
+ /** 0x0123 */
+ /** 0x0124 */
+ /** 0x0125 */
+ /** 0x0126 */
+ /** 0x0127 */
+ /** 0x0128 */
+ /** 0x0129 */
+ /** 0x012A */
+ /** 0x012B */
+ {"\\\\u", "I", 0x012C},
+ {"\\\\u", "i", 0x012D},
+ /** 0x012E */
+ /** 0x012F */
+ /** 0x0130 */
+ /** 0x0131 */
+ /** 0x0132 */
+ /** 0x0133 */
+ /** 0x0134 */
+ /** 0x0135 */
+ /** 0x0136 */
+ /** 0x0137 */
+ /** 0x0138 */
+ {"\\\\'", "L", 0x0139},
+ {"\\\\'", "l", 0x013A},
+ /** 0x013B */
+ /** 0x013C */
+ /** 0x013D */
+ /** 0x013E */
+ /** 0x013F */
+ /** 0x0140 */
+ /** 0x0141 */
+ /** 0x0142 */
+ {"\\\\'", "N", 0x0143},
+ {"\\\\'", "n", 0x0144},
+ /** 0x0145 */
+ /** 0x0146 */
+ {"\\\\v", "N", 0x0147},
+ {"\\\\v", "n", 0x0148},
+ /** 0x0149 */
+ /** 0x014A */
+ /** 0x014B */
+ /** 0x014C */
+ /** 0x014D */
+ {"\\\\u", "O", 0x014E},
+ {"\\\\u", "o", 0x014F},
+ {"\\\\H", "O", 0x0150},
+ {"\\\\H", "o", 0x0151},
+ /** 0x0152 */
+ /** 0x0153 */
+ {"\\\\'", "R", 0x0154},
+ {"\\\\'", "r", 0x0155},
+ /** 0x0156 */
+ /** 0x0157 */
+ {"\\\\v", "R", 0x0158},
+ {"\\\\v", "r", 0x0159},
+ {"\\\\'", "S", 0x015A},
+ {"\\\\'", "s", 0x015B},
+ /** 0x015C */
+ /** 0x015D */
+ {"\\\\c", "S", 0x015E},
+ {"\\\\c", "s", 0x015F},
+ {"\\\\v", "S", 0x0160},
+ {"\\\\v", "s", 0x0161},
+ /** 0x0162 */
+ /** 0x0163 */
+ {"\\\\v", "T", 0x0164},
+ /** 0x0165 */
+ /** 0x0166 */
+ /** 0x0167 */
+ /** 0x0168 */
+ /** 0x0169 */
+ /** 0x016A */
+ /** 0x016B */
+ {"\\\\u", "U", 0x016C},
+ {"\\\\u", "u", 0x016D},
+ {"\\\\r", "U", 0x016E},
+ {"\\\\r", "u", 0x016F},
+ /** 0x0170 */
+ /** 0x0171 */
+ /** 0x0172 */
+ /** 0x0173 */
+ /** 0x0174 */
+ /** 0x0175 */
+ /** 0x0176 */
+ /** 0x0177 */
+ {"\\\\\"", "Y", 0x0178},
+ {"\\\\'", "Z", 0x0179},
+ {"\\\\'", "z", 0x017A},
+ /** 0x017B */
+ /** 0x017C */
+ {"\\\\v", "Z", 0x017D},
+ {"\\\\v", "z", 0x017E},
+ /** 0x017F */
+ /** 0x0180 */
+ {"\\\\v", "A", 0x01CD},
+ {"\\\\v", "a", 0x01CE},
+ {"\\\\v", "G", 0x01E6},
+ {"\\\\v", "g", 0x01E7}
+ };
+
+ const char *expansionsMod1[] = {"\\{%1\\{%2\\}\\}", "\\{%1 %2\\}", "%1\\{%2\\}"};
+ static const int expansionsmod1count = sizeof( expansionsMod1 ) / sizeof( expansionsMod1[0] );
+ const char *expansionsMod2[] = {"\\{%1%2\\}", "%1%2\\{\\}", "%1%2"};
+ static const int expansionsmod2count = sizeof( expansionsMod2 ) / sizeof( expansionsMod2[0] );
+
+ static const int modcharmappingdatalatexcount = sizeof( modcharmappingdatalatex ) / sizeof( modcharmappingdatalatex[ 0 ] ) ;
+
+ static const struct EncoderLaTeXCharMapping
+ {
+ const char *regexp;
+ unsigned int unicode;
+ const char *latex;
+ }
+ charmappingdatalatex[] =
+ {
+ {"\\\\#", 0x0023, "\\#"},
+ {"\\\\&", 0x0026, "\\&"},
+ {"\\\\_", 0x005F, "\\_"},
+ {"!`", 0x00A1, "!`"},
+ {"\"<", 0x00AB, "\"<"},
+ {"\">", 0x00BB, "\">"},
+ {"[?]`", 0x00BF, "?`"},
+ {"--", 0x2013, "--"}
+ };
+
+ static const int charmappingdatalatexcount = sizeof( charmappingdatalatex ) / sizeof( charmappingdatalatex[ 0 ] ) ;
+
+ EncoderLaTeX::EncoderLaTeX()
+ {
+ buildCharMapping();
+ buildCombinedMapping();
+ }
+
+ EncoderLaTeX::~EncoderLaTeX()
+ {
+ // nothing
+ }
+
+ QString EncoderLaTeX::decode( const QString & text )
+ {
+ const QString splitMarker = "|KBIBTEX|";
+
+ /** start-stop marker ensures that each text starts and stops
+ * with plain text and not with an inline math environment.
+ * This invariant is exploited implicitly in the code below. */
+ const QString startStopMarker="|STARTSTOP|";
+ QString result = startStopMarker + text + startStopMarker;
+
+ /** Collect (all?) urls from the BibTeX file and store them in urls */
+ /** Problem is that the replace function below will replace
+ * character sequences in the URL rendering the URL invalid.
+ * Later, all URLs will be replaced back to their original
+ * in the hope nothing breaks ... */
+ QStringList urls;
+ QRegExp httpRegExp( "(ht|f)tp://[^\"} ]+" );
+ httpRegExp.setMinimal( false );
+ int pos = 0;
+ while ( pos >= 0 )
+ {
+ pos = httpRegExp.search( result, pos );
+ if ( pos >= 0 )
+ {
+ ++pos;
+ QString url = httpRegExp.cap( 0 );
+ urls << url;
+ }
+ }
+
+ decomposedUTF8toLaTeX( result );
+
+ /** split text into math and non-math regions */
+ QStringList intermediate = QStringList::split( '$', result, true );
+ QStringList::Iterator it = intermediate.begin();
+ while ( it != intermediate.end() )
+ {
+ /**
+ * Sometimes we split strings like "\$", which is not intended.
+ * So, we have to manually fix things by checking for strings
+ * ending with "\" and append both the removed dollar sign and
+ * the following string (which was never supposed to be an
+ * independent string). Finally, we remove the unnecessary
+ * string and continue.
+ */
+ if (( *it ).endsWith( "\\" ) )
+ {
+ QStringList::Iterator cur = it;
+ ++it;
+ ( *cur ).append( '$' ).append( *it );
+ intermediate.remove( it );
+ it = cur;
+ }
+ else
+ ++it;
+ }
+
+ qApp->processEvents();
+
+ result = "";
+ for ( QStringList::Iterator it = intermediate.begin(); it != intermediate.end(); ++it )
+ {
+ if ( !result.isEmpty() ) result.append( splitMarker );
+ result.append( *it );
+
+ ++it;
+ if ( it == intermediate.end() )
+ break;
+
+ if (( *it ).length() > 256 )
+ qDebug( "Very long math equation using $ found, maybe due to broken inline math: %s", ( *it ).left( 48 ).latin1() );
+ }
+
+ qApp->processEvents();
+
+ for ( QValueList<CharMappingItem>::ConstIterator cmit = m_charMapping.begin(); cmit != m_charMapping.end(); ++cmit )
+ result.replace(( *cmit ).regExp, ( *cmit ).unicode );
+
+ qApp->processEvents();
+
+ QStringList transformed = QStringList::split( splitMarker, result, true );
+
+ qApp->processEvents();
+
+ result = "";
+ for ( QStringList::Iterator itt = transformed.begin(), iti = intermediate.begin(); itt != transformed.end() && iti != intermediate.end(); ++itt, ++iti )
+ {
+ result.append( *itt );
+
+ ++iti;
+ if ( iti == intermediate.end() )
+ break;
+
+ result.append( "$" ).append( *iti ).append( "$" );
+ }
+
+ qApp->processEvents();
+
+ /** Reinserting original URLs as explained above */
+ pos = 0;
+ int idx = 0;
+ while ( pos >= 0 )
+ {
+ pos = httpRegExp.search( result, pos );
+ if ( pos >= 0 )
+ {
+ ++pos;
+ int len = httpRegExp.cap( 0 ).length();
+ result = result.left( pos - 1 ).append( urls[idx++] ).append( result.mid( pos + len - 1 ) );
+ }
+ }
+
+ return result.replace( startStopMarker,"" );
+ }
+
+ QString EncoderLaTeX::encode( const QString & text )
+ {
+ const QString splitMarker = "|KBIBTEX|";
+
+ /** start-stop marker ensures that each text starts and stops
+ * with plain text and not with an inline math environment.
+ * This invariant is exploited implicitly in the code below. */
+ const QString startStopMarker="|STARTSTOP|";
+ QString result = startStopMarker + text + startStopMarker;
+
+ /** Collect (all?) urls from the BibTeX file and store them in urls */
+ /** Problem is that the replace function below will replace
+ * character sequences in the URL rendering the URL invalid.
+ * Later, all URLs will be replaced back to their original
+ * in the hope nothing breaks ... */
+ QStringList urls;
+ QRegExp httpRegExp( "(ht|f)tp://[^\"} ]+" );
+ httpRegExp.setMinimal( false );
+ int pos = 0;
+ while ( pos >= 0 )
+ {
+ pos = httpRegExp.search( result, pos );
+ if ( pos >= 0 )
+ {
+ ++pos;
+ QString url = httpRegExp.cap( 0 );
+ urls << url;
+ }
+ }
+
+ /** split text into math and non-math regions */
+ QStringList intermediate = QStringList::split( '$', result, true );
+ QStringList::Iterator it = intermediate.begin();
+ while ( it != intermediate.end() )
+ {
+ /**
+ * Sometimes we split strings like "\$", which is not intended.
+ * So, we have to manually fix things by checking for strings
+ * ending with "\" and append both the removed dollar sign and
+ * the following string (which was never supposed to be an
+ * independent string). Finally, we remove the unnecessary
+ * string and continue.
+ */
+ if (( *it ).endsWith( "\\" ) )
+ {
+ QStringList::Iterator cur = it;
+ ++it;
+ ( *cur ).append( '$' ).append( *it );
+ intermediate.remove( it );
+ it = cur;
+ }
+ else
+ ++it;
+ }
+
+ qApp->processEvents();
+
+ result = "";
+ for ( QStringList::Iterator it = intermediate.begin(); it != intermediate.end(); ++it )
+ {
+ if ( !result.isEmpty() ) result.append( splitMarker );
+ result.append( *it );
+
+ ++it;
+ if ( it == intermediate.end() )
+ break;
+
+ if (( *it ).length() > 256 )
+ qDebug( "Very long math equation using $ found, maybe due to broken inline math: %s", ( *it ).left( 48 ).latin1() );
+ }
+
+ qApp->processEvents();
+
+ for ( QValueList<CharMappingItem>::ConstIterator cmit = m_charMapping.begin(); cmit != m_charMapping.end(); ++cmit )
+ result.replace(( *cmit ).unicode, ( *cmit ).latex );
+
+ qApp->processEvents();
+
+ QStringList transformed = QStringList::split( splitMarker, result, true );
+
+ qApp->processEvents();
+
+ result = "";
+ for ( QStringList::Iterator itt = transformed.begin(), iti = intermediate.begin(); itt != transformed.end() && iti != intermediate.end(); ++itt, ++iti )
+ {
+ result.append( *itt );
+
+ ++iti;
+ if ( iti == intermediate.end() )
+ break;
+
+ result.append( "$" ).append( *iti ).append( "$" );
+ }
+
+ qApp->processEvents();
+
+ /** \url accepts unquotet & and _
+ May introduce new problem tough */
+ if ( result.contains( "\\url{" ) )
+ result.replace( "\\&", "&" ).replace( "\\_", "_" ).replace( QChar( 0x2013 ), "--" ).replace( "\\#", "#" );
+
+ decomposedUTF8toLaTeX( result );
+
+ /** Reinserting original URLs as explained above */
+ pos = 0;
+ int idx = 0;
+ while ( pos >= 0 )
+ {
+ pos = httpRegExp.search( result, pos );
+ if ( pos >= 0 )
+ {
+ ++pos;
+ int len = httpRegExp.cap( 0 ).length();
+ result = result.left( pos - 1 ).append( urls[idx++] ).append( result.mid( pos + len - 1 ) );
+ }
+ }
+
+ return result.replace( startStopMarker,"" );
+ }
+
+ QString EncoderLaTeX::encode( const QString &text, const QChar &replace )
+ {
+ QString result = text;
+ for ( QValueList<CharMappingItem>::ConstIterator it = m_charMapping.begin(); it != m_charMapping.end(); ++it )
+ if (( *it ).unicode == replace )
+ result.replace(( *it ).unicode, ( *it ).latex );
+ return result;
+ }
+
+ QString EncoderLaTeX::encodeSpecialized( const QString & text, const EntryField::FieldType fieldType )
+ {
+ QString result = encode( text );
+
+ switch ( fieldType )
+ {
+ case EntryField::ftPages:
+ result.replace( QChar( 0x2013 ), "--" );
+ break;
+
+ case EntryField::ftURL:
+ result.replace( "\\&", "&" ).replace( "\\_", "_" ).replace( QChar( 0x2013 ), "--" ).replace( "\\#", "#" );
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+ }
+
+ QString& EncoderLaTeX::decomposedUTF8toLaTeX( QString &text )
+ {
+ for ( QValueList<CombinedMappingItem>::Iterator it = m_combinedMapping.begin(); it != m_combinedMapping.end(); ++it )
+ {
+ int i = ( *it ).regExp.search( text );
+ while ( i >= 0 )
+ {
+ QString a = ( *it ).regExp.cap( 1 );
+ text = text.left( i ) + "\\" + ( *it ).latex + "{" + a + "}" + text.mid( i + 2 );
+ i = ( *it ).regExp.search( text, i + 1 );
+ }
+ }
+
+ return text;
+ }
+
+ void EncoderLaTeX::buildCombinedMapping()
+ {
+ for ( int i = 0; i < decompositionscount; i++ )
+ {
+ CombinedMappingItem item;
+ item.regExp = QRegExp( "(.)" + QString( QChar( decompositions[i].unicode ) ) );
+ item.latex = decompositions[i].latexCommand;
+ m_combinedMapping.append( item );
+ }
+ }
+
+ void EncoderLaTeX::buildCharMapping()
+ {
+ /** encoding and decoding for digraphs such as -- or ?` */
+ for ( int i = 0; i < charmappingdatalatexcount; i++ )
+ {
+ CharMappingItem charMappingItem;
+ charMappingItem.regExp = QRegExp( charmappingdatalatex[ i ].regexp );
+ charMappingItem.unicode = QChar( charmappingdatalatex[ i ].unicode );
+ charMappingItem.latex = QString( charmappingdatalatex[ i ].latex );
+ m_charMapping.append( charMappingItem );
+ }
+
+ /** encoding and decoding for commands such as \AA or \ss */
+ for ( int i = 0; i < commandmappingdatalatexcount; ++i )
+ {
+ /** different types of writing such as {\AA} or \AA{} possible */
+ for ( int j = 0; j < expansionscmdcount; ++j )
+ {
+ CharMappingItem charMappingItem;
+ charMappingItem.regExp = QRegExp( QString( expansionsCmd[j] ).arg( commandmappingdatalatex[i].letters ) );
+ charMappingItem.unicode = QChar( commandmappingdatalatex[i].unicode );
+ if ( charMappingItem.regExp.numCaptures() > 0 )
+ charMappingItem.unicode += QString( "\\1" );
+ charMappingItem.latex = QString( "{\\%1}" ).arg( commandmappingdatalatex[i].letters );
+ m_charMapping.append( charMappingItem );
+ }
+ }
+
+ /** encoding and decoding for letters such as \"a */
+ for ( int i = 0; i < modcharmappingdatalatexcount; ++i )
+ {
+ QString modifierRegExp = QString( modcharmappingdatalatex[i].modifier );
+ QString modifier = modifierRegExp;
+ modifier.replace( "\\^", "^" ).replace( "\\\\", "\\" );
+
+ /** first batch of replacement rules, where no separator is required between modifier and character (e.g. \"a) */
+ if ( !modifierRegExp.at( modifierRegExp.length() - 1 ).isLetter() )
+ for ( int j = 0; j < expansionsmod2count; ++j )
+ {
+ CharMappingItem charMappingItem;
+ charMappingItem.regExp = QRegExp( QString( expansionsMod2[j] ).arg( modifierRegExp ).arg( modcharmappingdatalatex[i].letter ) );
+ charMappingItem.unicode = QChar( modcharmappingdatalatex[i].unicode );
+ charMappingItem.latex = QString( "{%1%2}" ).arg( modifier ).arg( modcharmappingdatalatex[i].letter );
+ m_charMapping.append( charMappingItem );
+ }
+
+ /** second batch of replacement rules, where a separator is required between modifier and character (e.g. \v{g}) */
+ for ( int j = 0; j < expansionsmod1count; ++j )
+ {
+ CharMappingItem charMappingItem;
+ charMappingItem.regExp = QRegExp( QString( expansionsMod1[j] ).arg( modifierRegExp ).arg( modcharmappingdatalatex[i].letter ) );
+ charMappingItem.unicode = QChar( modcharmappingdatalatex[i].unicode );
+ charMappingItem.latex = QString( "%1{%2}" ).arg( modifier ).arg( modcharmappingdatalatex[i].letter );
+ m_charMapping.append( charMappingItem );
+ }
+ }
+ }
+
+ EncoderLaTeX* EncoderLaTeX::currentEncoderLaTeX()
+ {
+ if ( encoderLaTeX == NULL )
+ encoderLaTeX = new EncoderLaTeX();
+
+ return encoderLaTeX;
+ }
+
+ void EncoderLaTeX::deleteCurrentEncoderLaTeX()
+ {
+ if ( encoderLaTeX != NULL )
+ {
+ delete encoderLaTeX;
+ encoderLaTeX = NULL;
+ }
+ }
+
+ char EncoderLaTeX::unicodeToASCII( unsigned int unicode )
+ {
+ if ( unicode < 128 ) return ( char )unicode;
+ for ( int i = 0; i < modcharmappingdatalatexcount; ++i )
+ if ( modcharmappingdatalatex[i].unicode == unicode )
+ return *modcharmappingdatalatex[i].letter;
+ return '?';
+ }
+
+}
diff --git a/src/encoderlatex.h b/src/encoderlatex.h
new file mode 100644
index 0000000..d301652
--- /dev/null
+++ b/src/encoderlatex.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef ENCODERLATEX_H
+#define ENCODERLATEX_H
+
+#include <qvaluelist.h>
+#include <qregexp.h>
+
+#include <encoder.h>
+#include <entry.h>
+
+class QString;
+
+namespace BibTeX
+{
+
+ class EncoderLaTeX: public Encoder
+ {
+ public:
+ EncoderLaTeX();
+ ~EncoderLaTeX();
+
+ QString decode( const QString &text );
+ QString encode( const QString &text );
+ QString encode( const QString &text, const QChar &replace );
+ QString encodeSpecialized( const QString &text, const EntryField::FieldType fieldType = EntryField::ftUnknown );
+ QString& decomposedUTF8toLaTeX( QString &text );
+
+ static EncoderLaTeX *currentEncoderLaTeX();
+ static void deleteCurrentEncoderLaTeX();
+
+ static char unicodeToASCII( unsigned int unicode );
+
+ private:
+ static EncoderLaTeX *encoderLaTeX;
+
+ struct CombinedMappingItem
+ {
+ QRegExp regExp;
+ QString latex;
+ };
+
+ QValueList<CombinedMappingItem> m_combinedMapping;
+
+ void buildCombinedMapping();
+
+ struct CharMappingItem
+ {
+ QRegExp regExp;
+ QString unicode;
+ QString latex;
+ };
+
+ QValueList<CharMappingItem> m_charMapping;
+
+ void buildCharMapping();
+ };
+
+}
+
+#endif // ENCODERLATEX_H
diff --git a/src/encoderxml.cpp b/src/encoderxml.cpp
new file mode 100644
index 0000000..bbb76dd
--- /dev/null
+++ b/src/encoderxml.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qregexp.h>
+
+#include "encoderxml.h"
+
+namespace BibTeX
+{
+ EncoderXML *encoderXML = NULL;
+
+ static const struct EncoderXMLCharMapping
+ {
+ const char *regexp;
+ unsigned int unicode;
+ const char *latex;
+ }
+ charmappingdataxml[] =
+ {
+ {"&amp;", 0x0026, "&amp;"},
+ {"&lt;", 0x003C, "&lt;"},
+ {"&gt;", 0x003E, "&gt;"}
+ };
+ static const int charmappingdataxmlcount = sizeof( charmappingdataxml ) / sizeof( charmappingdataxml[ 0 ] ) ;
+
+ EncoderXML::EncoderXML()
+ : Encoder()
+ {
+ buildCharMapping();
+ }
+
+
+ EncoderXML::~EncoderXML()
+ {
+ // nothing
+ }
+
+ QString EncoderXML::decode( const QString &text )
+ {
+ QString result = text;
+
+ for ( QValueList<CharMappingItem>::ConstIterator it = m_charMapping.begin(); it != m_charMapping.end(); ++it )
+ result.replace(( *it ).regExp, ( *it ).unicode );
+
+ /**
+ * Find and replace all characters written as hexadecimal number
+ */
+ int p = -1;
+ while (( p = result.find( "&#x", p + 1 ) ) >= 0 )
+ {
+ int p2 = result.find( ";", p + 1 );
+ if ( p2 < 0 ) break;
+ bool ok = FALSE;
+ int hex = result.mid( p + 3, p2 - p - 3 ).toInt( &ok, 16 );
+ if ( ok && hex > 0 )
+ result.replace( result.mid( p, p2 - p + 1 ), QChar( hex ) );
+ }
+
+ /**
+ * Find and replace all characters written as decimal number
+ */
+ p = -1;
+ while (( p = result.find( "&#", p + 1 ) ) >= 0 )
+ {
+ int p2 = result.find( ";", p + 1 );
+ if ( p2 < 0 ) break;
+ bool ok = FALSE;
+ int dec = result.mid( p + 2, p2 - p - 2 ).toInt( &ok, 10 );
+ if ( ok && dec > 0 )
+ result.replace( result.mid( p, p2 - p + 1 ), QChar( dec ) );
+ }
+
+ return result;
+ }
+
+ QString EncoderXML::encode( const QString &text )
+ {
+ QString result = text;
+
+ for ( QValueList<CharMappingItem>::ConstIterator it = m_charMapping.begin(); it != m_charMapping.end(); ++it )
+ result.replace(( *it ).unicode, ( *it ).latex );
+
+ return result;
+ }
+
+ QString EncoderXML::encodeSpecialized( const QString &text, const EntryField::FieldType /* fieldType */ )
+ {
+ return encode( text );
+ }
+
+ void EncoderXML::buildCharMapping()
+ {
+ for ( int i = 0; i < charmappingdataxmlcount; i++ )
+ {
+ CharMappingItem charMappingItem;
+ charMappingItem.regExp = QRegExp( charmappingdataxml[ i ].regexp );
+ charMappingItem.unicode = QChar( charmappingdataxml[ i ].unicode );
+ charMappingItem.latex = QString( charmappingdataxml[ i ].latex );
+ m_charMapping.append( charMappingItem );
+ }
+ }
+
+ EncoderXML *EncoderXML::currentEncoderXML()
+ {
+ if ( encoderXML == NULL )
+ encoderXML = new EncoderXML();
+
+ return encoderXML;
+ }
+
+}
diff --git a/src/encoderxml.h b/src/encoderxml.h
new file mode 100644
index 0000000..89e1be1
--- /dev/null
+++ b/src/encoderxml.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXENCODERXML_H
+#define BIBTEXENCODERXML_H
+
+#include <qptrlist.h>
+#include <qregexp.h>
+
+#include <encoder.h>
+
+class QString;
+class QRegExp;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class EncoderXML : public Encoder
+ {
+ public:
+ EncoderXML();
+ ~EncoderXML();
+
+ QString decode( const QString &text );
+ QString encode( const QString &text );
+ QString encodeSpecialized( const QString &text, const EntryField::FieldType fieldType = EntryField::ftUnknown );
+
+ static EncoderXML *currentEncoderXML();
+
+ private:
+ struct CharMappingItem
+ {
+ QRegExp regExp;
+ QChar unicode;
+ QString latex;
+ };
+
+ QValueList<CharMappingItem> m_charMapping;
+
+ void buildCharMapping();
+ };
+
+}
+
+#endif
diff --git a/src/entry.cpp b/src/entry.cpp
new file mode 100644
index 0000000..fcd81fd
--- /dev/null
+++ b/src/entry.cpp
@@ -0,0 +1,714 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+
+#include <entry.h>
+#include <file.h>
+#include <xsltransform.h>
+#include <entryfield.h>
+
+#define max(a,b) ((a)>(b)?(a):(b))
+
+namespace BibTeX
+{
+
+ Entry::Entry( )
+ : Element(), m_entryType( etUnknown ), m_entryTypeString( QString::null ), m_id( QString::null )
+ {
+ // nothing
+ }
+
+ Entry::Entry( const EntryType entryType, const QString &id )
+ : Element( ), m_entryType( entryType ), m_id( id )
+ {
+ m_entryTypeString = entryTypeToString( entryType );
+ }
+
+ Entry::Entry( const QString& entryTypeString, const QString& id ) : Element( ), m_entryTypeString( entryTypeString ), m_id( id )
+ {
+ m_entryType = entryTypeFromString( entryTypeString );
+ if ( m_entryType != etUnknown )
+ m_entryTypeString = entryTypeToString( m_entryType );
+ }
+
+ Entry::Entry( const Entry *other )
+ {
+ copyFrom( other );
+ }
+
+ Entry::~Entry()
+ {
+ for ( EntryFields::iterator it = m_fields.begin(); it != m_fields.end(); it++ )
+ {
+ delete( *it );
+ }
+ }
+
+ Element* Entry::clone()
+ {
+ return new Entry( this );
+ }
+
+ bool Entry::equals( const Entry &other )
+ {
+ if ( other.id().compare( id() ) != 0 )
+ return false;
+
+ for ( EntryFields::iterator it = m_fields.begin(); it != m_fields.end(); it++ )
+ {
+ EntryField *field1 = *it;
+ EntryField *field2 = other.getField( field1->fieldTypeName() );
+
+ if ( field2 == NULL || field1->value() == NULL || field2->value() == NULL || field1->value()->text().compare( field2->value()->text() ) != 0 )
+ return false;
+ }
+
+ return true;
+ }
+
+ QString Entry::text() const
+ {
+ QString result = "Id: ";
+ result.append( m_id ).append( " (" ).append( entryTypeString() ).append( ")\n" );
+
+ for ( EntryFields::ConstIterator it = m_fields.begin(); it != m_fields.end(); it++ )
+ {
+ result.append(( *it )->fieldTypeName() ).append( ": " );
+ result.append(( *it )->value()->text() ).append( "\n" );
+ }
+
+ return result;
+ }
+
+ void Entry::setEntryType( const EntryType entryType )
+ {
+ m_entryType = entryType;
+ m_entryTypeString = entryTypeToString( entryType );
+ }
+
+ void Entry::setEntryTypeString( const QString& entryTypeString )
+ {
+ m_entryTypeString = entryTypeString;
+ m_entryType = entryTypeFromString( entryTypeString );
+ }
+
+ Entry::EntryType Entry::entryType() const
+ {
+ return m_entryType;
+ }
+
+ QString Entry::entryTypeString() const
+ {
+ return m_entryTypeString;
+ }
+
+ void Entry::setId( const QString& id )
+ {
+ m_id = id;
+ }
+
+ QString Entry::id() const
+ {
+ return m_id;
+ }
+
+ bool Entry::containsPattern( const QString & pattern, EntryField::FieldType fieldType, BibTeX::Element::FilterType filterType, bool caseSensitive ) const
+ {
+ if ( filterType == ftExact )
+ {
+ /** check for exact match */
+ bool result = fieldType == EntryField::ftUnknown && m_id.contains( pattern, caseSensitive );
+
+ for ( EntryFields::ConstIterator it = m_fields.begin(); !result && it != m_fields.end(); it++ )
+ if ( fieldType == EntryField::ftUnknown || ( *it ) ->fieldType() == fieldType )
+ result |= ( *it ) ->value() ->containsPattern( pattern, caseSensitive );
+
+ return result;
+ }
+ else
+ {
+ /** for each word in the search pattern ... */
+ QStringList words = QStringList::split( QRegExp( "\\s+" ), pattern );
+ bool *hits = new bool[words.count()];
+ int i = 0;
+ for ( QStringList::Iterator wit = words.begin(); wit != words.end(); ++wit, ++i )
+ {
+ hits[i] = fieldType == EntryField::ftUnknown && m_id.contains( *wit, caseSensitive );
+
+ /** check if word is contained in any field */
+ for ( EntryFields::ConstIterator fit = m_fields.begin(); fit != m_fields.end(); ++fit )
+ if ( fieldType == EntryField::ftUnknown || ( *fit ) ->fieldType() == fieldType )
+ hits[i] |= ( *fit ) ->value() ->containsPattern( *wit, caseSensitive );
+ }
+
+ unsigned int hitCount = 0;
+ for ( i = words.count() - 1; i >= 0; --i )
+ if ( hits[i] ) ++hitCount;
+ delete[] hits;
+
+ /** return success depending on filter type and number of hits */
+ return (( filterType == ftAnyWord && hitCount > 0 ) || ( filterType == ftEveryWord && hitCount == words.count() ) );
+ }
+ }
+
+ QStringList Entry::urls() const
+ {
+ QStringList result;
+ const QString fieldNames[] = {"localfile", "pdf", "ps", "postscript", "doi", "url", "howpublished", "ee", "biburl", "note"};
+ const int fieldNamesCount = sizeof( fieldNames ) / sizeof( fieldNames[0] );
+
+ for ( int j = 1; j < 5 ; ++j ) /** there may be variants such as url3 or doi2 */
+ for ( int i = 0; i < fieldNamesCount; i++ )
+ {
+ QString fieldName = fieldNames[i];
+ /** field names should be like url, url2, url3, ... */
+ if ( j > 1 ) fieldName.append( QString::number( j ) );
+
+ EntryField * field = getField( fieldName );
+ if (( field && !field->value()->items.isEmpty() ) )
+ {
+ PlainText *plainText = dynamic_cast<PlainText*>( field->value()->items.first() );
+ if ( plainText != NULL )
+ {
+ QString plain = plainText->text();
+ int urlPos = plain.find( "\\url{", 0, FALSE );
+ if ( urlPos > -1 )
+ {
+ plain = plain.mid( urlPos + 5 );
+ urlPos = plain.find( "}", 0, FALSE );
+ if ( urlPos > 0 )
+ plain = plain.left( urlPos - 1 );
+ }
+
+ if ( fieldNames[ i ] == "doi" && !plain.startsWith( "http", FALSE ) )
+ plain.prepend( "http://dx.doi.org/" );
+
+ result.append( plain );
+ }
+ }
+ }
+
+ return result;
+ }
+
+ bool Entry::addField( EntryField * field )
+ {
+ m_fields.append( field );
+ return TRUE;
+ }
+
+ EntryField* Entry::getField( const EntryField::FieldType fieldType ) const
+ {
+ EntryField * result = NULL;
+
+ for ( EntryFields::ConstIterator it = m_fields.begin(); ( it != m_fields.end() ) && ( result == NULL ); it++ )
+ if (( *it ) ->fieldType() == fieldType ) result = *it;
+
+ return result;
+ }
+
+ EntryField* Entry::getField( const QString & fieldName ) const
+ {
+ EntryField * result = NULL;
+
+ for ( EntryFields::ConstIterator it = m_fields.begin(); ( it != m_fields.end() ) && ( result == NULL ); it++ )
+ if (( *it ) ->fieldTypeName().lower() == fieldName.lower() )
+ result = *it;
+
+ return result;
+ }
+
+ bool Entry::deleteField( const QString & fieldName )
+ {
+ for ( EntryFields::ConstIterator it = m_fields.begin(); it != m_fields.end(); it++ )
+ if (( *it ) ->fieldTypeName().lower() == fieldName.lower() )
+ {
+ delete( *it );
+ m_fields.remove( *it );
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ bool Entry::deleteField( const EntryField::FieldType fieldType )
+ {
+ for ( EntryFields::iterator it = m_fields.begin(); it != m_fields.end(); it++ )
+ if (( *it ) ->fieldType() == fieldType )
+ {
+ delete( *it );
+ m_fields.remove( it );
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ Entry::EntryFields::ConstIterator Entry::begin() const
+ {
+ return m_fields.constBegin();
+ }
+
+ Entry::EntryFields::ConstIterator Entry::end() const
+ {
+ return m_fields.constEnd();
+ }
+
+ int Entry::getFieldCount() const
+ {
+ return m_fields.count();
+ }
+
+ void Entry::clearFields()
+ {
+ for ( EntryFields::iterator it = m_fields.begin(); it != m_fields.end(); it++ )
+ delete( *it );
+ m_fields.clear();
+ }
+
+ void Entry::copyFrom( const Entry *other )
+ {
+ if ( other == NULL ) return;
+
+ m_entryType = other->m_entryType;
+ m_entryTypeString = other->m_entryTypeString;
+ m_id = other->m_id;
+ clearFields();
+ for ( EntryFields::ConstIterator it = other->m_fields.begin(); it != other->m_fields.end(); it++ )
+ m_fields.append( new EntryField( *it ) );
+ }
+
+ void Entry::merge( BibTeX::Entry *other, MergeSemantics mergeSemantics )
+ {
+ for ( EntryFields::iterator it = other->m_fields.begin(); it != other->m_fields.end(); it++ )
+ {
+ EntryField *otherField = new EntryField( *it );
+ EntryField::FieldType otherFieldType = otherField->fieldType();
+ QString otherFieldTypeName = otherField->fieldTypeName();
+ EntryField *thisField = otherFieldType != EntryField::ftUnknown ? getField( otherFieldType ) : getField( otherFieldTypeName );
+
+ if ( thisField == NULL )
+ {
+ m_fields.append( otherField );
+ }
+ else if ( otherField->value()->text() == thisField->value()->text() && mergeSemantics == msForceAdding )
+ {
+ otherFieldTypeName.prepend( "OPT" );
+ otherField->setFieldType( EntryField::ftUnknown, otherFieldTypeName );
+ m_fields.append( otherField );
+ }
+ }
+ }
+
+ QString Entry::entryTypeToString( const EntryType entryType )
+ {
+ switch ( entryType )
+ {
+ case etArticle:
+ return QString( "Article" );
+ case etBook:
+ return QString( "Book" );
+ case etBooklet:
+ return QString( "Booklet" );
+ case etCollection:
+ return QString( "Collection" );
+ case etElectronic:
+ return QString( "Electronic" );
+ case etInBook:
+ return QString( "InBook" );
+ case etInCollection:
+ return QString( "InCollection" );
+ case etInProceedings:
+ return QString( "InProceedings" );
+ case etManual:
+ return QString( "Manual" );
+ case etMastersThesis:
+ return QString( "MastersThesis" );
+ case etMisc:
+ return QString( "Misc" );
+ case etPhDThesis:
+ return QString( "PhDThesis" );
+ case etProceedings:
+ return QString( "Proceedings" );
+ case etTechReport:
+ return QString( "TechReport" );
+ case etUnpublished:
+ return QString( "Unpublished" );
+ default:
+ return QString( "Unknown" );
+ }
+ }
+
+ Entry::EntryType Entry::entryTypeFromString( const QString & entryTypeString )
+ {
+ QString entryTypeStringLower = entryTypeString.lower();
+ if ( entryTypeStringLower == "article" )
+ return etArticle;
+ else if ( entryTypeStringLower == "book" )
+ return etBook;
+ else if ( entryTypeStringLower == "booklet" )
+ return etBooklet;
+ else if ( entryTypeStringLower == "collection" )
+ return etCollection;
+ else if (( entryTypeStringLower == "electronic" ) || ( entryTypeStringLower == "online" ) || ( entryTypeStringLower == "internet" ) || ( entryTypeStringLower == "webpage" ) )
+ return etElectronic;
+ else if ( entryTypeStringLower == "inbook" )
+ return etInBook;
+ else if ( entryTypeStringLower == "incollection" )
+ return etInCollection;
+ else if (( entryTypeStringLower == "inproceedings" ) || ( entryTypeStringLower == "conference" ) )
+ return etInProceedings;
+ else if ( entryTypeStringLower == "manual" )
+ return etManual;
+ else if ( entryTypeStringLower == "mastersthesis" )
+ return etMastersThesis;
+ else if ( entryTypeStringLower == "misc" )
+ return etMisc;
+ else if ( entryTypeStringLower == "phdthesis" )
+ return etPhDThesis;
+ else if ( entryTypeStringLower == "proceedings" )
+ return etProceedings;
+ else if ( entryTypeStringLower == "techreport" )
+ return etTechReport;
+ else if ( entryTypeStringLower == "unpublished" )
+ return etUnpublished;
+ else
+ return etUnknown;
+ }
+
+ Entry::FieldRequireStatus Entry::getRequireStatus( Entry::EntryType entryType, EntryField::FieldType fieldType )
+ {
+ switch ( entryType )
+ {
+ case etArticle:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftJournal:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftVolume:
+ case EntryField::ftMonth:
+ case EntryField::ftDoi:
+ case EntryField::ftNumber:
+ case EntryField::ftPages:
+ case EntryField::ftNote:
+ case EntryField::ftKey:
+ case EntryField::ftISSN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etBook:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftEditor:
+ case EntryField::ftTitle:
+ case EntryField::ftPublisher:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftVolume:
+ case EntryField::ftNumber:
+ case EntryField::ftSeries:
+ case EntryField::ftAddress:
+ case EntryField::ftDoi:
+ case EntryField::ftEdition:
+ case EntryField::ftMonth:
+ case EntryField::ftNote:
+ case EntryField::ftKey:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etBooklet:
+ switch ( fieldType )
+ {
+ case EntryField::ftTitle:
+ return Entry::frsRequired;
+ case EntryField::ftAuthor:
+ case EntryField::ftHowPublished:
+ case EntryField::ftAddress:
+ case EntryField::ftDoi:
+ case EntryField::ftMonth:
+ case EntryField::ftYear:
+ case EntryField::ftNote:
+ case EntryField::ftKey:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etElectronic:
+ switch ( fieldType )
+ {
+ case EntryField::ftTitle:
+ case EntryField::ftURL:
+ return Entry::frsRequired;
+ case EntryField::ftAuthor:
+ case EntryField::ftHowPublished:
+ case EntryField::ftDoi:
+ case EntryField::ftMonth:
+ case EntryField::ftYear:
+ case EntryField::ftKey:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etInBook:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftEditor:
+ case EntryField::ftTitle:
+ case EntryField::ftPages:
+ case EntryField::ftChapter:
+ case EntryField::ftPublisher:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftVolume:
+ case EntryField::ftSeries:
+ case EntryField::ftAddress:
+ case EntryField::ftDoi:
+ case EntryField::ftEdition:
+ case EntryField::ftMonth:
+ case EntryField::ftNote:
+ case EntryField::ftCrossRef:
+ case EntryField::ftKey:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etInCollection:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftBookTitle:
+ case EntryField::ftPublisher:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftEditor:
+ case EntryField::ftPages:
+ case EntryField::ftOrganization:
+ case EntryField::ftAddress:
+ case EntryField::ftMonth:
+ case EntryField::ftLocation:
+ case EntryField::ftNote:
+ case EntryField::ftCrossRef:
+ case EntryField::ftDoi:
+ case EntryField::ftKey:
+ case EntryField::ftType:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etInProceedings:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftYear:
+ case EntryField::ftBookTitle:
+ return Entry::frsRequired;
+ case EntryField::ftPages:
+ case EntryField::ftEditor:
+ case EntryField::ftVolume:
+ case EntryField::ftNumber:
+ case EntryField::ftSeries:
+ case EntryField::ftType:
+ case EntryField::ftChapter:
+ case EntryField::ftAddress:
+ case EntryField::ftDoi:
+ case EntryField::ftEdition:
+ case EntryField::ftLocation:
+ case EntryField::ftMonth:
+ case EntryField::ftNote:
+ case EntryField::ftCrossRef:
+ case EntryField::ftPublisher:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etManual:
+ switch ( fieldType )
+ {
+ case EntryField::ftTitle:
+ return Entry::frsRequired;
+ case EntryField::ftAuthor:
+ case EntryField::ftOrganization:
+ case EntryField::ftAddress:
+ case EntryField::ftDoi:
+ case EntryField::ftEdition:
+ case EntryField::ftMonth:
+ case EntryField::ftYear:
+ case EntryField::ftNote:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etMastersThesis:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftSchool:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftAddress:
+ case EntryField::ftMonth:
+ case EntryField::ftDoi:
+ case EntryField::ftNote:
+ case EntryField::ftKey:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etMisc:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftHowPublished:
+ case EntryField::ftMonth:
+ case EntryField::ftYear:
+ case EntryField::ftDoi:
+ case EntryField::ftNote:
+ case EntryField::ftKey:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etPhDThesis:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftSchool:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftAddress:
+ case EntryField::ftMonth:
+ case EntryField::ftNote:
+ case EntryField::ftDoi:
+ case EntryField::ftKey:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etCollection:
+ case etProceedings:
+ switch ( fieldType )
+ {
+ case EntryField::ftTitle:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftEditor:
+ case EntryField::ftPublisher:
+ case EntryField::ftOrganization:
+ case EntryField::ftAddress:
+ case EntryField::ftMonth:
+ case EntryField::ftLocation:
+ case EntryField::ftNote:
+ case EntryField::ftDoi:
+ case EntryField::ftKey:
+ case EntryField::ftSeries:
+ case EntryField::ftBookTitle:
+ case EntryField::ftISBN:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etTechReport:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftInstitution:
+ case EntryField::ftYear:
+ return Entry::frsRequired;
+ case EntryField::ftType:
+ case EntryField::ftDoi:
+ case EntryField::ftNumber:
+ case EntryField::ftAddress:
+ case EntryField::ftMonth:
+ case EntryField::ftNote:
+ case EntryField::ftKey:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ case EntryField::ftISSN:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ case etUnpublished:
+ switch ( fieldType )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftTitle:
+ case EntryField::ftNote:
+ return Entry::frsRequired;
+ case EntryField::ftMonth:
+ case EntryField::ftYear:
+ case EntryField::ftDoi:
+ case EntryField::ftKey:
+ case EntryField::ftURL:
+ case EntryField::ftLocalFile:
+ return Entry::frsOptional;
+ default:
+ return Entry::frsIgnored;
+ }
+ default:
+ return Entry::frsOptional;
+ }
+ }
+}
diff --git a/src/entry.h b/src/entry.h
new file mode 100644
index 0000000..6a8633c
--- /dev/null
+++ b/src/entry.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXBIBTEXENTRY_H
+#define BIBTEXBIBTEXENTRY_H
+
+#include <qvaluelist.h>
+#include <qstringlist.h>
+
+#include <element.h>
+#include <entryfield.h>
+
+class QString;
+class QStringList;
+
+namespace BibTeX
+{
+
+ class Entry : public Element
+ {
+ public:
+ typedef QValueList<BibTeX::EntryField*> EntryFields;
+
+ enum EntryType {etArticle, etBook, etBooklet, etCollection, etElectronic, etInBook, etInCollection, etInProceedings, etManual, etMastersThesis, etMisc, etPhDThesis, etProceedings, etTechReport, etUnpublished, etUnknown};
+
+ enum FieldRequireStatus {frsRequired, frsOptional, frsIgnored};
+
+ enum MergeSemantics {msAddNew, msForceAdding};
+
+ Entry( );
+ Entry( const EntryType entryType, const QString &id );
+ Entry( const QString& entryTypeString, const QString& id );
+ Entry( const Entry *other );
+ virtual ~Entry();
+ Element* clone();
+ bool equals( const Entry &other );
+ QString text() const;
+
+ void setEntryType( const EntryType elementType );
+ void setEntryTypeString( const QString& elementTypeString );
+ EntryType entryType() const;
+ QString entryTypeString() const;
+ void setId( const QString& id );
+ QString id() const;
+
+ bool containsPattern( const QString& pattern, EntryField::FieldType fieldType = EntryField::ftUnknown, BibTeX::Element::FilterType filterType = BibTeX::Element::ftExact, bool caseSensitive = FALSE ) const;
+ QStringList urls() const;
+
+ bool addField( EntryField *field );
+ BibTeX::EntryField* getField( const EntryField::FieldType fieldType ) const;
+ BibTeX::EntryField* getField( const QString& fieldName ) const;
+ bool deleteField( const BibTeX::EntryField::FieldType fieldType );
+ bool deleteField( const QString &fieldName );
+
+ EntryFields::const_iterator begin() const;
+ EntryFields::const_iterator end() const;
+ int getFieldCount() const;
+ void clearFields();
+
+ void copyFrom( const BibTeX::Entry *other );
+ void merge( BibTeX::Entry *other, MergeSemantics mergeSemantics );
+
+ static QString entryTypeToString( const EntryType entryType );
+ static EntryType entryTypeFromString( const QString &entryTypeString );
+ static Entry::FieldRequireStatus getRequireStatus( Entry::EntryType entryType, EntryField::FieldType fieldType );
+
+ private:
+ EntryType m_entryType;
+ QString m_entryTypeString;
+ QString m_id;
+ EntryFields m_fields;
+ };
+
+}
+
+#endif
diff --git a/src/entryfield.cpp b/src/entryfield.cpp
new file mode 100644
index 0000000..bb7cb9d
--- /dev/null
+++ b/src/entryfield.cpp
@@ -0,0 +1,227 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include "entryfield.h"
+
+namespace BibTeX
+{
+
+ EntryField::EntryField( FieldType fieldType ) : m_fieldType( fieldType )
+ {
+ m_fieldTypeName = fieldTypeToString( m_fieldType );
+ m_value = new Value();
+ }
+
+ EntryField::EntryField( const QString &fieldTypeName ) : m_fieldTypeName( fieldTypeName )
+ {
+ m_fieldType = fieldTypeFromString( m_fieldTypeName );
+ m_value = new Value();
+ }
+
+ EntryField::EntryField( BibTeX::EntryField *other ) : m_fieldType( other->m_fieldType ), m_fieldTypeName( other->m_fieldTypeName ), m_value( NULL )
+ {
+ setValue( other->m_value );
+ }
+
+ EntryField::~EntryField()
+ {
+ delete m_value;
+ }
+
+ QString EntryField::fieldTypeName() const
+ {
+ return m_fieldTypeName;
+ }
+
+ void EntryField::setFieldType( FieldType fieldType, const QString& fieldTypeName )
+ {
+ m_fieldType = fieldType;
+ m_fieldTypeName = fieldTypeName;
+ }
+
+ EntryField::FieldType EntryField::fieldType() const
+ {
+ return m_fieldType;
+ }
+
+ QString EntryField::fieldTypeToString( const FieldType fieldType )
+ {
+ switch ( fieldType )
+ {
+ case ftAbstract:
+ return QString( "abstract" );
+ case ftAddress:
+ return QString( "address" );
+ case ftAnnote:
+ return QString( "annote" );
+ case ftAuthor:
+ return QString( "author" );
+ case ftBookTitle:
+ return QString( "booktitle" );
+ case ftChapter:
+ return QString( "chapter" );
+ case ftCrossRef:
+ return QString( "crossref" );
+ case ftDoi:
+ return QString( "doi" );
+ case ftEdition:
+ return QString( "edition" );
+ case ftEditor:
+ return QString( "editor" );
+ case ftHowPublished:
+ return QString( "howpublished" );
+ case ftInstitution:
+ return QString( "institution" );
+ case ftISBN:
+ return QString( "isbn" );
+ case ftISSN:
+ return QString( "issn" );
+ case ftJournal:
+ return QString( "journal" );
+ case ftKey:
+ return QString( "key" );
+ case ftKeywords:
+ return QString( "keywords" );
+ case ftLocalFile:
+ return QString( "localfile" );
+ case ftLocation:
+ return QString( "location" );
+ case ftMonth:
+ return QString( "month" );
+ case ftNote:
+ return QString( "note" );
+ case ftNumber:
+ return QString( "number" );
+ case ftOrganization:
+ return QString( "organization" );
+ case ftPages:
+ return QString( "pages" );
+ case ftPublisher:
+ return QString( "publisher" );
+ case ftSeries:
+ return QString( "series" );
+ case ftSchool:
+ return QString( "school" );
+ case ftTitle:
+ return QString( "title" );
+ case ftType:
+ return QString( "type" );
+ case ftURL:
+ return QString( "url" );
+ case ftVolume:
+ return QString( "volume" );
+ case ftYear:
+ return QString( "year" );
+ default:
+ return QString( "unknown" );
+ }
+ }
+
+ EntryField::FieldType EntryField::fieldTypeFromString( const QString & fieldTypeString )
+ {
+ QString fieldTypeStringLower = fieldTypeString.lower();
+
+ if ( fieldTypeStringLower == "abstract" )
+ return ftAbstract;
+ else if ( fieldTypeStringLower == "address" )
+ return ftAddress;
+ else if ( fieldTypeStringLower == "annote" )
+ return ftAnnote;
+ else if ( fieldTypeStringLower == "author" )
+ return ftAuthor;
+ else if ( fieldTypeStringLower == "booktitle" )
+ return ftBookTitle;
+ else if ( fieldTypeStringLower == "chapter" )
+ return ftChapter;
+ else if ( fieldTypeStringLower == "crossref" )
+ return ftCrossRef;
+ else if ( fieldTypeStringLower == "doi" )
+ return ftDoi;
+ else if ( fieldTypeStringLower == "edition" )
+ return ftEdition;
+ else if ( fieldTypeStringLower == "editor" )
+ return ftEditor;
+ else if ( fieldTypeStringLower == "howpublished" )
+ return ftHowPublished;
+ else if ( fieldTypeStringLower == "institution" )
+ return ftInstitution;
+ else if ( fieldTypeStringLower == "isbn" )
+ return ftISBN;
+ else if ( fieldTypeStringLower == "issn" )
+ return ftISSN;
+ else if ( fieldTypeStringLower == "journal" )
+ return ftJournal;
+ else if ( fieldTypeStringLower == "key" )
+ return ftKey;
+ else if ( fieldTypeStringLower == "keywords" )
+ return ftKeywords;
+ else if ( fieldTypeStringLower == "localfile" )
+ return ftLocalFile;
+ else if ( fieldTypeStringLower == "location" )
+ return ftLocation;
+ else if ( fieldTypeStringLower == "month" )
+ return ftMonth;
+ else if ( fieldTypeStringLower == "note" )
+ return ftNote;
+ else if ( fieldTypeStringLower == "number" )
+ return ftNumber;
+ else if ( fieldTypeStringLower == "organization" )
+ return ftOrganization;
+ else if ( fieldTypeStringLower == "pages" )
+ return ftPages;
+ else if ( fieldTypeStringLower == "publisher" )
+ return ftPublisher;
+ else if ( fieldTypeStringLower == "series" )
+ return ftSeries;
+ else if ( fieldTypeStringLower == "school" )
+ return ftSchool;
+ else if ( fieldTypeStringLower == "title" )
+ return ftTitle;
+ else if ( fieldTypeStringLower == "type" )
+ return ftType;
+ else if ( fieldTypeStringLower == "url" )
+ return ftURL;
+ else if ( fieldTypeStringLower == "volume" )
+ return ftVolume;
+ else if ( fieldTypeStringLower == "year" )
+ return ftYear;
+ else
+ return ftUnknown;
+ }
+
+ Value *EntryField::value()
+ {
+ return m_value;
+ }
+
+ void EntryField::setValue( const Value *value )
+ {
+ if ( value != m_value )
+ {
+ delete m_value;
+
+ if ( value != NULL )
+ {
+ m_value = new Value( value );
+ }
+ else
+ m_value = new Value();
+ }
+ }
+}
diff --git a/src/entryfield.h b/src/entryfield.h
new file mode 100644
index 0000000..6b3af30
--- /dev/null
+++ b/src/entryfield.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXBIBTEXENTRYFIELD_H
+#define BIBTEXBIBTEXENTRYFIELD_H
+
+#include <qstring.h>
+
+#include <value.h>
+
+namespace BibTeX
+{
+ class EntryField
+ {
+ public:
+ enum FieldType {ftAbstract, ftAddress, ftAnnote, ftAuthor, ftBookTitle, ftChapter, ftCrossRef, ftDoi, ftEdition, ftEditor, ftHowPublished, ftInstitution, ftISBN, ftISSN, ftJournal, ftKey, ftKeywords, ftLocalFile, ftLocation, ftMonth, ftNote, ftNumber, ftOrganization, ftPages, ftPublisher, ftSchool, ftSeries, ftTitle, ftType, ftURL, ftVolume, ftYear, ftUnknown = -1};
+
+ EntryField( FieldType fieldType );
+ EntryField( const QString &fieldTypeName );
+ EntryField( BibTeX::EntryField *other );
+ ~EntryField();
+
+ QString fieldTypeName() const;
+ FieldType fieldType() const;
+ void setFieldType( FieldType fieldType, const QString& fieldTypeName );
+
+ static QString fieldTypeToString( const FieldType fieldType );
+ static FieldType fieldTypeFromString( const QString &fieldTypeString );
+
+ BibTeX::Value *value();
+ void setValue( const BibTeX::Value *value );
+
+ private:
+ FieldType m_fieldType;
+ QString m_fieldTypeName;
+ Value *m_value;
+ };
+
+}
+
+#endif
diff --git a/src/entrywidget.cpp b/src/entrywidget.cpp
new file mode 100644
index 0000000..cb4c7ff
--- /dev/null
+++ b/src/entrywidget.cpp
@@ -0,0 +1,677 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qlistview.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <qpushbutton.h>
+#include <qpopupmenu.h>
+#include <qtabwidget.h>
+#include <qcombobox.h>
+#include <qtimer.h>
+#include <qlineedit.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kwin.h>
+
+#include <entry.h>
+#include <entryfield.h>
+#include <file.h>
+#include <settings.h>
+#include <entrywidgettab.h>
+#include <entrywidgettitle.h>
+#include <entrywidgetauthor.h>
+#include <entrywidgetkeyword.h>
+#include <entrywidgetpublication.h>
+#include <entrywidgetmisc.h>
+#include <entrywidgetexternal.h>
+#include <entrywidgetuserdefined.h>
+#include <entrywidgetother.h>
+#include <entrywidgetwarningsitem.h>
+#include <fieldlistview.h>
+#include <idsuggestions.h>
+#include <webqueryarxiv.h>
+#include "entrywidget.h"
+
+namespace KBibTeX
+{
+ QDialog::DialogCode EntryWidget::execute( BibTeX::Entry *entry, BibTeX::File *bibtexfile, bool isReadOnly, bool isNew, QWidget *parent, const char *name )
+ {
+ EntryWidgetDialog *dlg = new EntryWidgetDialog( parent, name, TRUE, i18n( "Edit BibTeX Entry" ), KDialogBase::Ok | KDialogBase::Cancel );
+ EntryWidget *entryWidget = new EntryWidget( entry, bibtexfile, isReadOnly, isNew, dlg, "entryWidget" );
+ dlg->setMainWidget( entryWidget );
+
+ QDialog::DialogCode result = ( QDialog::DialogCode ) dlg->exec();
+
+ delete entryWidget;
+ delete dlg;
+
+ return result;
+ }
+
+ EntryWidget::EntryWidget( BibTeX::File *bibtexfile, bool isReadOnly, bool isNew, QDialog *parent, const char *name )
+ : QWidget( parent, name ), m_originalEntry( NULL ), m_bibtexfile( bibtexfile ), m_isReadOnly( isReadOnly ), m_isNew( isNew ), m_lastPage( NULL ), m_dlgParent( parent ), m_wqa( new WebQueryArXiv( NULL ) )
+ {
+ setupGUI( parent, FALSE );
+
+ Settings * settings = Settings::self();
+ m_checkBoxEnableAll->setChecked( settings->editing_EnableAllFields );
+ m_defaultIdSuggestionAvailable = settings->idSuggestions_default >= 0;
+ m_pushButtonForceDefaultIdSuggestion->setEnabled( !m_isReadOnly && m_defaultIdSuggestionAvailable );
+ m_pushButtonIdSuggestions->setEnabled( !m_isReadOnly );
+
+ connect( m_wqa, SIGNAL( foundEntry( BibTeX::Entry*, bool ) ), this, SLOT( useExternalEntry( BibTeX::Entry*, bool ) ) );
+ connect( m_wqa, SIGNAL( endSearch( WebQuery::Status ) ), this, SLOT( endExternalSearch( WebQuery::Status ) ) );
+ }
+
+ EntryWidget::EntryWidget( BibTeX::Entry *entry, BibTeX::File *bibtexfile, bool isReadOnly, bool isNew, QDialog *parent, const char *name )
+ : QWidget( parent, name ), m_originalEntry( entry ), m_bibtexfile( bibtexfile ), m_isReadOnly( isReadOnly ), m_isNew( isNew ), m_lastPage( NULL ), m_dlgParent( parent ), m_wqa( new WebQueryArXiv( NULL ) )
+ {
+ setupGUI( parent );
+
+ Settings * settings = Settings::self();
+ m_checkBoxEnableAll->setChecked( settings->editing_EnableAllFields );
+ m_defaultIdSuggestionAvailable = settings->idSuggestions_default >= 0;
+ m_pushButtonForceDefaultIdSuggestion->setEnabled( !m_isReadOnly && m_defaultIdSuggestionAvailable );
+ m_pushButtonIdSuggestions->setEnabled( !m_isReadOnly );
+
+ reset();
+
+ connect( m_wqa, SIGNAL( foundEntry( BibTeX::Entry*, bool ) ), this, SLOT( useExternalEntry( BibTeX::Entry*, bool ) ) );
+ connect( m_wqa, SIGNAL( endSearch( WebQuery::Status ) ), this, SLOT( endExternalSearch( WebQuery::Status ) ) );
+ }
+
+ EntryWidget::~EntryWidget()
+ {
+ m_updateWarningsTimer->stop();
+ delete m_updateWarningsTimer;
+
+ delete m_wqa;
+
+ KConfig * config = kapp->config();
+ config->setGroup( "EntryWidget" );
+ saveWindowSize( config );
+ }
+
+ void EntryWidget::showEvent( QShowEvent *showev )
+ {
+ QWidget::showEvent( showev );
+ EntryWidgetTitle *ewt = dynamic_cast<EntryWidgetTitle*>( m_tabWidget->page( 0 ) );
+ if ( ewt != NULL )
+ ewt->m_fieldLineEditTitle->setFocus();
+
+ KConfig * config = kapp->config();
+ config->setGroup( "EntryWidget" );
+ restoreWindowSize( config );
+ }
+
+ bool EntryWidget::queryClose()
+ {
+ bool isModified = m_lineEditID->isModified();
+
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); !isModified && it != m_internalEntryWidgets.end(); ++it )
+ isModified = ( *it ) ->isModified();
+ isModified |= m_sourcePage->isModified();
+
+ KGuiItem discardBtn = KGuiItem( i18n( "Discard" ), "editshred" );
+ return !isModified || KMessageBox::warningContinueCancel( this, i18n( "The current entry has been modified. Do you want do discard your changes?" ), i18n( "Discard changes" ), discardBtn ) == KMessageBox::Continue;
+ }
+
+ void EntryWidget::apply()
+ {
+ if ( !m_isReadOnly )
+ {
+ apply( m_originalEntry );
+ m_originalEntry->setId( IdSuggestions::resolveConflict( m_bibtexfile, m_originalEntry->id(), m_originalEntry ) );
+
+ Settings * settings = Settings::self();
+ settings->addToCompletion( m_originalEntry );
+ }
+ }
+
+ void EntryWidget::apply( BibTeX::Entry *entry )
+ {
+ internalApply( entry );
+ if ( m_tabWidget->currentPage() == m_sourcePage )
+ m_sourcePage->apply( entry );
+ else
+ {
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); it != m_internalEntryWidgets.end(); ++it )
+ ( *it ) ->apply( entry );
+ }
+ }
+
+ void EntryWidget::internalApply( BibTeX::Entry *entry )
+ {
+ BibTeX::Entry::EntryType entryType = BibTeX::Entry::entryTypeFromString( m_comboBoxEntryType->currentText() );
+ if ( entryType == BibTeX::Entry::etUnknown )
+ entry->setEntryTypeString( m_comboBoxEntryType->currentText() );
+ else
+ entry->setEntryType( entryType );
+
+ entry->setId( m_lineEditID->text() );
+ }
+
+ void EntryWidget::reset()
+ {
+ reset( m_originalEntry );
+ }
+
+ void EntryWidget::reset( BibTeX::Entry *entry )
+ {
+ internalReset( entry );
+ m_sourcePage->reset( entry );
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); it != m_internalEntryWidgets.end(); ++it )
+ ( *it ) ->reset( entry );
+
+ updateGUI();
+ }
+
+ void EntryWidget::internalReset( BibTeX::Entry *entry )
+ {
+ m_lineEditID->setText( entry->id() );
+ Settings * settings = Settings::self();
+ m_pushButtonForceDefaultIdSuggestion->setOn( m_defaultIdSuggestionAvailable && settings->idSuggestions_forceDefault && m_isNew );
+ m_pushButtonForceDefaultIdSuggestion->setEnabled( !m_isReadOnly && m_defaultIdSuggestionAvailable );
+
+ bool foundEntryType = FALSE;
+ for ( int i = 0; !foundEntryType && i < m_comboBoxEntryType->count(); i++ )
+ if (( BibTeX::Entry::EntryType ) i + BibTeX::Entry::etArticle == entry->entryType() )
+ {
+ m_comboBoxEntryType->setCurrentItem( i );
+ foundEntryType = TRUE;
+ }
+ if ( !foundEntryType )
+ m_comboBoxEntryType->setCurrentText( entry->entryTypeString() );
+ }
+
+ void EntryWidget::slotEnableAllFields( )
+ {
+ updateGUI();
+ }
+
+ void EntryWidget::slotForceDefaultIdSuggestion()
+ {
+ m_isNew = FALSE;
+ m_lineEditID->setEnabled( !m_pushButtonForceDefaultIdSuggestion->isOn() );
+ m_pushButtonIdSuggestions->setEnabled( !m_pushButtonForceDefaultIdSuggestion->isOn() && !m_isReadOnly );
+ updateWarnings();
+ }
+
+ void EntryWidget::slotEntryTypeChanged( )
+ {
+ updateGUI();
+ }
+
+ void EntryWidget::slotCurrentPageChanged( QWidget* newPage )
+ {
+ BibTeX::Entry temporaryEntry;
+
+ if ( newPage == m_sourcePage )
+ {
+ // switching to source tab
+ m_updateWarningsTimer->stop();
+ internalApply( &temporaryEntry );
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); it != m_internalEntryWidgets.end(); ++it )
+ ( *it ) ->apply( &temporaryEntry );
+ m_sourcePage->reset( &temporaryEntry );
+
+ m_comboBoxEntryType->setEnabled( FALSE );
+ m_lineEditID->setEnabled( FALSE );
+ m_pushButtonIdSuggestions->setEnabled( FALSE );
+ m_pushButtonForceDefaultIdSuggestion->setEnabled( FALSE );
+ }
+ else if ( m_lastPage == m_sourcePage )
+ {
+ // switching from source tab away
+ bool doApply = true;
+ bool doChange = true;
+ if ( !m_sourcePage->containsValidText() )
+ {
+ if ( KMessageBox::warningYesNo( this, i18n( "The source code does not contain valid BibTeX code.\n\nRestore previous version or continue editing?" ), i18n( "Invalid BibTeX code" ), KGuiItem( i18n( "Restore" ) ), KGuiItem( i18n( "Edit" ) ) ) == KMessageBox::No )
+ {
+ QString text = m_sourcePage->text();
+ m_tabWidget->showPage( m_sourcePage );
+ m_sourcePage->setText( text );
+ doChange = false;
+ newPage = m_sourcePage;
+ }
+ else
+ doApply = false;
+ }
+
+ if ( doChange )
+ {
+ if ( doApply )
+ {
+ m_sourcePage->apply( &temporaryEntry );
+ internalReset( &temporaryEntry );
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); it != m_internalEntryWidgets.end(); ++it )
+ ( *it ) ->reset( &temporaryEntry );
+ updateWarnings();
+ }
+
+ m_comboBoxEntryType->setEnabled( TRUE );
+ m_lineEditID->setEnabled( !m_defaultIdSuggestionAvailable || !m_pushButtonForceDefaultIdSuggestion->isOn() );
+ m_pushButtonIdSuggestions->setEnabled(( !m_defaultIdSuggestionAvailable || !m_pushButtonForceDefaultIdSuggestion->isOn() ) && !m_isReadOnly );
+ m_pushButtonForceDefaultIdSuggestion->setEnabled( !m_isReadOnly && m_defaultIdSuggestionAvailable );
+ if ( !m_isReadOnly )
+ m_updateWarningsTimer->start( 500 );
+ }
+ }
+
+ m_lastPage = newPage;
+ }
+
+ void EntryWidget::warningsExecute( QListViewItem* item )
+ {
+ EntryWidgetWarningsItem * ewwi = dynamic_cast<KBibTeX::EntryWidgetWarningsItem*>( item );
+ if ( ewwi != NULL && ewwi->widget() != NULL )
+ {
+ ewwi->widget() ->setFocus();
+ // find and activate corresponding tab page
+ QObject *parent = ewwi->widget();
+ KBibTeX::EntryWidgetTab *ewt = dynamic_cast<KBibTeX::EntryWidgetTab*>( parent );
+ while ( ewt == NULL && parent != NULL )
+ {
+ parent = parent->parent();
+ ewt = dynamic_cast<KBibTeX::EntryWidgetTab*>( parent );
+ }
+ m_tabWidget->setCurrentPage( m_tabWidget-> indexOf( ewt ) );
+ }
+ }
+
+ void EntryWidget::setupGUI( QWidget *parent, bool showWarnings )
+ {
+ QGridLayout * layout = new QGridLayout( this, 4, 6, 0, KDialog::spacingHint() );
+
+ // in the top row on the left, put an entry type label and combobox
+ QLabel *label = new QLabel( i18n( "E&ntry Type:" ), this );
+ layout->addWidget( label, 0, 0 );
+ m_comboBoxEntryType = new QComboBox( TRUE, this, "m_comboBoxEntryType" );
+ label->setBuddy( m_comboBoxEntryType );
+ m_comboBoxEntryType->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
+ m_comboBoxEntryType->setEnabled( !m_isReadOnly );
+ layout->addWidget( m_comboBoxEntryType, 0, 1 );
+ setupEntryTypes();
+
+ // in the top row on the left, put an identifier label and combobox
+ label = new QLabel( i18n( "&Identifier" ), this );
+ layout->addWidget( label, 0, 2 );
+ m_lineEditID = new QLineEdit( this, "m_lineEditID" );
+ label->setBuddy( m_lineEditID );
+ m_lineEditID->setReadOnly( m_isReadOnly );
+ m_lineEditID->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
+ layout->addWidget( m_lineEditID, 0, 3 );
+
+ m_pushButtonIdSuggestions = new QPushButton( QIconSet( BarIcon( "wizard" ) ), "", this, "m_pushButtonIdSuggestions" );
+ m_menuIdSuggestions = new QPopupMenu( m_pushButtonIdSuggestions );
+ connect( m_menuIdSuggestions, SIGNAL( activated( int ) ), this, SLOT( insertIdSuggestion( int ) ) );
+ m_pushButtonIdSuggestions->setPopup( m_menuIdSuggestions );
+ layout->addWidget( m_pushButtonIdSuggestions, 0, 4 );
+
+ m_pushButtonForceDefaultIdSuggestion = new QPushButton( QIconSet( BarIcon( "favorites" ) ), "", this, "m_pushButtonForceDefaultIdSuggestion" );
+ m_pushButtonForceDefaultIdSuggestion->setToggleButton( TRUE );
+ layout->addWidget( m_pushButtonForceDefaultIdSuggestion, 0, 5 );
+ QToolTip::add( m_pushButtonForceDefaultIdSuggestion, i18n( "Use the default id suggestion to set the entry id" ) );
+ QWhatsThis::add( m_pushButtonForceDefaultIdSuggestion, i18n( "Use the default id suggestion to set the entry id.\nYou can edit and select the default id suggestion in the configuration dialog." ) );
+
+ // central tab widget for all the tabs
+ m_tabWidget = new QTabWidget( this );
+ layout->addMultiCellWidget( m_tabWidget, 1, 1, 0, 5 );
+ addTabWidgets();
+
+ // a check box if the user want to edit all fields
+ m_checkBoxEnableAll = new QCheckBox( i18n( "Enable all &fields for editing" ), this );
+ layout->addMultiCellWidget( m_checkBoxEnableAll, 2, 2, 0, 4 );
+
+ m_pushButtonRefetch = new QPushButton( KGlobal::iconLoader() ->loadIconSet( "reload", KIcon::Small ), i18n( "Refetch" ), this );
+ layout->addWidget( m_pushButtonRefetch, 2, 5 );
+ connect( m_pushButtonRefetch, SIGNAL( clicked() ), this, SLOT( refreshFromURL() ) );
+
+ if ( showWarnings )
+ {
+ // list view for warnings, errors and suggestions
+ m_listViewWarnings = new QListView( this );
+ m_listViewWarnings->addColumn( i18n( "Message" ) );
+ m_listViewWarnings->setAllColumnsShowFocus( true );
+ layout->addMultiCellWidget( m_listViewWarnings, 3, 3, 0, 5 );
+ connect( m_listViewWarnings, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ), this, SLOT( warningsExecute( QListViewItem* ) ) );
+ }
+ else
+ m_listViewWarnings = NULL;
+
+ connect( m_checkBoxEnableAll, SIGNAL( toggled( bool ) ), this, SLOT( slotEnableAllFields( ) ) );
+ connect( m_comboBoxEntryType, SIGNAL( activated( int ) ), this, SLOT( slotEntryTypeChanged( ) ) );
+ connect( m_pushButtonForceDefaultIdSuggestion, SIGNAL( toggled( bool ) ), this, SLOT( slotForceDefaultIdSuggestion() ) );
+ connect( m_comboBoxEntryType, SIGNAL( textChanged( const QString & ) ), this, SLOT( slotEntryTypeChanged() ) );
+ connect( m_tabWidget, SIGNAL( currentChanged( QWidget* ) ), this, SLOT( slotCurrentPageChanged( QWidget* ) ) );
+ connect( parent, SIGNAL( okClicked() ), this, SLOT( apply() ) );
+ connect( m_menuIdSuggestions, SIGNAL( aboutToShow() ), this, SLOT( updateIdSuggestionsMenu() ) );
+
+ m_updateWarningsTimer = new QTimer( this );
+ connect( m_updateWarningsTimer, SIGNAL( timeout() ), this, SLOT( updateWarnings() ) );
+ if ( !m_isReadOnly )
+ m_updateWarningsTimer->start( 500 );
+ }
+
+ void EntryWidget::addTabWidgets()
+ {
+ addTabWidget( new KBibTeX::EntryWidgetTitle( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetTitle" ), i18n( "Title" ) );
+ addTabWidget( new KBibTeX::EntryWidgetAuthor( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetAuthor" ), i18n( "Author/Editor" ) );
+ addTabWidget( new KBibTeX::EntryWidgetPublication( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetPublication" ), i18n( "Publication" ) );
+ addTabWidget( new KBibTeX::EntryWidgetMisc( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetMisc" ), i18n( "Misc" ) );
+ addTabWidget( new KBibTeX::EntryWidgetKeyword( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetKeyword" ), i18n( "Keywords" ) );
+ addTabWidget( new KBibTeX::EntryWidgetExternal( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetExternal" ), i18n( "External" ) );
+ addTabWidget( new KBibTeX::EntryWidgetUserDefined( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetUserDefined" ), i18n( "User Defined" ) );
+ addTabWidget( new KBibTeX::EntryWidgetOther( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetOther" ), i18n( "Other Fields" ) );
+
+ m_sourcePage = new KBibTeX::EntryWidgetSource( m_bibtexfile, m_isReadOnly, m_tabWidget, "EntryWidgetSource" );
+ m_tabWidget->insertTab( m_sourcePage, i18n( "Source" ) );
+ }
+
+ void EntryWidget::addTabWidget( EntryWidgetTab *widget, const QString& title )
+ {
+ m_tabWidget->insertTab( widget, title );
+ m_internalEntryWidgets.append( widget );
+ }
+
+ void EntryWidget::setupEntryTypes()
+ {
+ int i = ( int ) BibTeX::Entry::etArticle;
+ BibTeX::Entry::EntryType entryType = ( BibTeX::Entry::EntryType ) i;
+ while ( entryType != BibTeX::Entry::etUnknown )
+ {
+ QString currentString = BibTeX::Entry::entryTypeToString( entryType );
+ m_comboBoxEntryType->insertItem( currentString );
+ entryType = ( BibTeX::Entry::EntryType ) ++i;
+ }
+ }
+
+ void EntryWidget::updateGUI()
+ {
+ BibTeX::Entry::EntryType entryType = BibTeX::Entry::entryTypeFromString( m_comboBoxEntryType->currentText() );
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); it != m_internalEntryWidgets.end(); ++it )
+ ( *it ) ->updateGUI( entryType, m_checkBoxEnableAll->isChecked() );
+ updateWarnings( );
+ }
+
+ void EntryWidget::updateWarnings()
+ {
+ if ( m_listViewWarnings == NULL )
+ return;
+
+ m_listViewWarnings->clear();
+
+ int p = 0;
+ if ( m_defaultIdSuggestionAvailable && m_pushButtonForceDefaultIdSuggestion->isOn() )
+ {
+ BibTeX::Entry temporaryEntry;
+ apply( &temporaryEntry );
+ QString id = IdSuggestions::createDefaultSuggestion( m_bibtexfile, &temporaryEntry );
+ if ( id.isNull() || id.isEmpty() )
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlWarning, i18n( "Please supply more fields to use the default id" ), m_pushButtonForceDefaultIdSuggestion, m_listViewWarnings );
+ else
+ {
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlInformation, QString( i18n( "Using '%1' as entry id" ) ).arg( id ), m_pushButtonForceDefaultIdSuggestion, m_listViewWarnings );
+ m_lineEditID->setText( id );
+ }
+ }
+ else if ( m_lineEditID->text().isEmpty() )
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlError, i18n( "An entry has to have an identifier" ), m_lineEditID, m_listViewWarnings );
+ else if (( p = m_lineEditID->text().find( Settings::noIdChars ) ) > 0 )
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlError, QString( i18n( "The identifier contains invalid characters at position %1" ) ).arg( p + 1 ), m_lineEditID, m_listViewWarnings );
+
+ BibTeX::Entry::EntryType entryType = BibTeX::Entry::entryTypeFromString( m_comboBoxEntryType->currentText() );
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); it != m_internalEntryWidgets.end(); ++it )
+ ( *it ) ->updateWarnings( entryType, m_listViewWarnings );
+
+ QString text = m_lineEditID->text();
+ for ( unsigned int i = 0; i < text.length(); i++ )
+ if ( text.at( i ).unicode() > 127 )
+ {
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlWarning, QString( i18n( "The identifier contains non-ascii characters, first one is '%1'" ) ).arg( text.at( i ) ), m_lineEditID, m_listViewWarnings );
+ break;
+ }
+
+ BibTeX::Entry temporaryEntry;
+ /** fetch data from GUI elements */
+ for ( QValueList<KBibTeX::EntryWidgetTab*>::iterator it( m_internalEntryWidgets.begin() ); it != m_internalEntryWidgets.end(); ++it )
+ ( *it ) ->apply( &temporaryEntry );
+ internalApply( &temporaryEntry );
+
+ /** check if entry with same id already exists */
+ QString id = temporaryEntry.id();
+ if ( m_bibtexfile != NULL && !id.isEmpty() )
+ {
+ BibTeX::Entry *nameMatched = dynamic_cast<BibTeX::Entry*>( m_bibtexfile->containsKey( id ) );
+ if ( nameMatched != NULL && nameMatched != m_originalEntry )
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlError, QString( i18n( "This BibTeX file already contains an entry with id '%1'." ) ).arg( id ), m_lineEditID, m_listViewWarnings );
+ }
+
+ BibTeX::Entry *crossRefEntry = NULL;
+ QString crossRefText = "";
+ BibTeX::EntryField *crossRef = temporaryEntry.getField( BibTeX::EntryField::ftCrossRef );
+ if ( crossRef != NULL && m_bibtexfile != NULL )
+ {
+ crossRefText = crossRef->value()->text();
+ crossRefEntry = dynamic_cast<BibTeX::Entry*>( m_bibtexfile->containsKey( crossRefText ) );
+ }
+
+ switch ( temporaryEntry.entryType() )
+ {
+ case BibTeX::Entry::etProceedings:
+ if ( temporaryEntry.getField( BibTeX::EntryField::ftEditor ) == NULL && temporaryEntry.getField( BibTeX::EntryField::ftOrganization ) == NULL && temporaryEntry.getField( BibTeX::EntryField::ftKey ) == NULL )
+ {
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlWarning, i18n( "Require either 'Editor', 'Organization', or 'Key'" ), NULL, m_listViewWarnings );
+ }
+ break;
+ case BibTeX::Entry::etInProceedings:
+ {
+ if ( crossRefEntry != NULL )
+ {
+ if ( crossRefEntry->getField( BibTeX::EntryField::ftEditor ) == NULL && crossRefEntry->getField( BibTeX::EntryField::ftKey ) == NULL && crossRefEntry->getField( BibTeX::EntryField::ftBookTitle ) == NULL )
+ {
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlWarning, QString( i18n( "Cross referenced entry '%1' must contain either 'Editor', 'Key', or 'Book Title'" ) ).arg( crossRefText ), NULL, m_listViewWarnings );
+ }
+ }
+ }
+ break;
+ case BibTeX::Entry::etInBook:
+ {
+ if ( crossRefEntry != NULL )
+ {
+ if ( crossRefEntry->getField( BibTeX::EntryField::ftVolume ) == NULL )
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlWarning, QString( i18n( "Cross referenced entry '%1' must contain 'Volume'" ) ).arg( crossRefText ), NULL, m_listViewWarnings );
+ if ( crossRefEntry->getField( BibTeX::EntryField::ftEditor ) == NULL && crossRefEntry->getField( BibTeX::EntryField::ftKey ) == NULL && crossRefEntry->getField( BibTeX::EntryField::ftSeries ) == NULL )
+ {
+ new KBibTeX::EntryWidgetWarningsItem( KBibTeX::EntryWidgetWarningsItem::wlWarning, QString( i18n( "Cross referenced entry '%1' must contain either 'Editor', 'Key', or 'Series'" ) ).arg( crossRefText ), NULL, m_listViewWarnings );
+ }
+ }
+ }
+ break;
+ default:
+ {
+// nothing
+ }
+ }
+ }
+
+ void EntryWidget::updateIdSuggestionsMenu()
+ {
+ BibTeX::Entry temporaryEntry;
+ m_menuIdSuggestions->clear();
+ m_idToSuggestion.clear();
+
+ apply( &temporaryEntry );
+ QStringList suggestions = IdSuggestions::createSuggestions( m_bibtexfile, &temporaryEntry );
+ for ( QStringList::ConstIterator it = suggestions.begin(); it != suggestions.end(); ++it )
+ m_idToSuggestion.insert( m_menuIdSuggestions->insertItem( *it ), *it );
+
+ if ( m_idToSuggestion.count() == 0 )
+ m_menuIdSuggestions->setItemEnabled( m_menuIdSuggestions->insertItem( i18n( "No suggestions available" ) ), FALSE );
+ }
+
+ void EntryWidget::insertIdSuggestion( int id )
+ {
+ m_lineEditID->setText( m_idToSuggestion[id] );
+ }
+
+ /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
+ void EntryWidget::saveWindowSize( KConfig *config ) const
+ {
+ int scnum = QApplication::desktop()->screenNumber( parentWidget() );
+ QRect desk = QApplication::desktop()->screenGeometry( scnum );
+ int w, h;
+#if defined Q_WS_X11
+ // save maximalization as desktop size + 1 in that direction
+ KWin::WindowInfo info = KWin::windowInfo( m_dlgParent->winId(), NET::WMState );
+ w = info.state() & NET::MaxHoriz ? desk.width() + 1 : m_dlgParent->width();
+ h = info.state() & NET::MaxVert ? desk.height() + 1 : m_dlgParent->height();
+#else
+ if ( isMaximized() )
+ {
+ w = desk.width() + 1;
+ h = desk.height() + 1;
+ }
+ //TODO: add "Maximized" property instead "+1" hack
+#endif
+ QRect size( desk.width(), w, desk.height(), h );
+ bool defaultSize = false;//( size == d->defaultWindowSize );
+ QString widthString = QString::fromLatin1( "Width %1" ).arg( desk.width() );
+ QString heightString = QString::fromLatin1( "Height %1" ).arg( desk.height() );
+ if ( !config->hasDefault( widthString ) && defaultSize )
+ config->revertToDefault( widthString );
+ else
+ config->writeEntry( widthString, w );
+
+ if ( !config->hasDefault( heightString ) && defaultSize )
+ config->revertToDefault( heightString );
+ else
+ config->writeEntry( heightString, h );
+ }
+
+ /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
+ void EntryWidget::restoreWindowSize( KConfig *config )
+ {
+ // restore the size
+ int scnum = QApplication::desktop()->screenNumber( parentWidget() );
+ QRect desk = QApplication::desktop()->screenGeometry( scnum );
+// if ( d->defaultWindowSize.isNull() ) // only once
+// d->defaultWindowSize = QRect( desk.width(), width(), desk.height(), height() ); // store default values
+ QSize size( config->readNumEntry( QString::fromLatin1( "Width %1" ).arg( desk.width() ), 0 ),
+ config->readNumEntry( QString::fromLatin1( "Height %1" ).arg( desk.height() ), 0 ) );
+ if ( size.isEmpty() )
+ {
+ // try the KDE 2.0 way
+ size = QSize( config->readNumEntry( QString::fromLatin1( "Width" ), 0 ),
+ config->readNumEntry( QString::fromLatin1( "Height" ), 0 ) );
+ if ( !size.isEmpty() )
+ {
+ // make sure the other resolutions don't get old settings
+ config->writeEntry( QString::fromLatin1( "Width" ), 0 );
+ config->writeEntry( QString::fromLatin1( "Height" ), 0 );
+ }
+ }
+ if ( !size.isEmpty() )
+ {
+#ifdef Q_WS_X11
+ int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
+ | ( size.height() > desk.height() ? NET::MaxVert : 0 );
+ if (( state & NET::Max ) == NET::Max )
+ ; // no resize
+ else if (( state & NET::MaxHoriz ) == NET::MaxHoriz )
+ m_dlgParent->resize( width(), size.height() );
+ else if (( state & NET::MaxVert ) == NET::MaxVert )
+ m_dlgParent->resize( size.width(), height() );
+ else
+ m_dlgParent->resize( size );
+ // QWidget::showMaximized() is both insufficient and broken
+ KWin::setState( m_dlgParent->winId(), state );
+#else
+ if ( size.width() > desk.width() || size.height() > desk.height() )
+ m_dlgParent->setWindowState( WindowMaximized );
+ else
+ m_dlgParent->resize( size );
+#endif
+ }
+ }
+
+ void EntryWidget::refreshFromURL()
+ {
+ BibTeX::Entry *entry = new BibTeX::Entry();
+ apply( entry );
+ m_oldId = entry->id();
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftURL );
+ KURL url = field != NULL ? KURL( field->value()->text().lower() ) : KURL();
+
+ if ( url.isValid() && url.prettyURL().contains( "arxiv.org/abs/" ) )
+ {
+ m_pushButtonRefetch->setEnabled( false );
+ qDebug( "Refetching from url %s", url.prettyURL().latin1() );
+ m_wqa->fetchFromAbstract( url );
+ }
+ else
+ {
+ KMessageBox::information( this, i18n( "Currently only refetching from ArXiv sources is supported.\n\nThis requires that the URL field points to an \"abstract\" page (i.e. the URL contains \"arxiv.org/abs/\")." ), i18n( "Refetching entry" ) );
+ m_pushButtonRefetch->setEnabled( true );
+ }
+ }
+
+ void EntryWidget::useExternalEntry( BibTeX::Entry* entry, bool )
+ {
+ if ( entry != NULL )
+ {
+ BibTeX::Entry *oldEntry = new BibTeX::Entry();
+ apply( oldEntry );
+
+ entry->setId( m_oldId );
+ for ( BibTeX::Entry::EntryFields::ConstIterator it = oldEntry->begin(); it != oldEntry->end(); ++it )
+ {
+ BibTeX::EntryField *oldField = *it;
+ BibTeX::EntryField *field = entry->getField( oldField->fieldTypeName() );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( oldField->fieldTypeName() );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( oldField->value() ) );
+ }
+ }
+ reset( entry );
+ }
+ else
+ KMessageBox::error( this, i18n( "Fetching updated bibliographic data failed." ), i18n( "Refetching entry" ) );
+ }
+
+ void EntryWidget::endExternalSearch( WebQuery::Status )
+ {
+ m_pushButtonRefetch->setEnabled( true );
+ }
+
+}
+#include "entrywidget.moc"
diff --git a/src/entrywidget.h b/src/entrywidget.h
new file mode 100644
index 0000000..10dfd13
--- /dev/null
+++ b/src/entrywidget.h
@@ -0,0 +1,158 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGET_H
+#define KBIBTEXENTRYWIDGET_H
+
+#include <qwidget.h>
+#include <qdialog.h>
+#include <qvaluelist.h>
+#include <qmap.h>
+
+#include <kdialogbase.h>
+
+#include <entry.h>
+#include <entrywidgetsource.h>
+#include <webquery.h>
+
+class QComboBox;
+class QLineEdit;
+class QCheckBox;
+class QTabWidget;
+class QString;
+class QTimer;
+class QListView;
+
+class KConfig;
+
+namespace KBibTeX
+{
+ class EntryWidgetTab;
+ class WebQueryArXiv;
+
+ class EntryWidget : public QWidget
+ {
+ Q_OBJECT
+
+ friend class EntryWidgetDialog;
+
+ public:
+ ~EntryWidget();
+
+ static QDialog::DialogCode execute( BibTeX::Entry *entry, BibTeX::File *bibtexfile, bool isReadOnly, bool isNew, QWidget *parent = 0, const char *name = 0 );
+
+ protected:
+ EntryWidget( BibTeX::File *bibtexfile, bool isReadOnly, bool isNew, QDialog *parent, const char *name = 0 );
+ void showEvent( QShowEvent * );
+ bool queryClose();
+
+ private slots:
+ void apply();
+ void reset();
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void slotEnableAllFields();
+ void slotForceDefaultIdSuggestion();
+ void slotEntryTypeChanged();
+ void slotCurrentPageChanged( QWidget* newPage );
+ void warningsExecute( QListViewItem* item );
+ void updateWarnings();
+ void insertIdSuggestion( int id );
+ void updateIdSuggestionsMenu();
+ void refreshFromURL();
+ void useExternalEntry( BibTeX::Entry*, bool );
+ void endExternalSearch( WebQuery::Status );
+
+ signals:
+ void updateTabs( BibTeX::Entry::EntryType entryType, bool enableAll, bool isReadOnly );
+
+ private:
+ EntryWidget( BibTeX::Entry *entry, BibTeX::File *bibtexfile, bool isReadOnly, bool isNew, QDialog *parent, const char *name = 0 );
+ BibTeX::Entry *m_originalEntry;
+ BibTeX::File *m_bibtexfile;
+ bool m_isReadOnly;
+ bool m_isNew;
+ bool m_defaultIdSuggestionAvailable;
+
+ QComboBox *m_comboBoxEntryType;
+ QLineEdit *m_lineEditID;
+ QPushButton *m_pushButtonForceDefaultIdSuggestion;
+ QPushButton *m_pushButtonIdSuggestions;
+ QPopupMenu *m_menuIdSuggestions;
+ QMap<int, QString> m_idToSuggestion;
+ QCheckBox *m_checkBoxEnableAll;
+ QPushButton *m_pushButtonRefetch;
+ QListView *m_listViewWarnings;
+ QTabWidget *m_tabWidget;
+ KBibTeX::EntryWidgetSource *m_sourcePage;
+ QValueList<KBibTeX::EntryWidgetTab*> m_internalEntryWidgets;
+ QWidget *m_lastPage;
+ QTimer *m_updateWarningsTimer;
+ QDialog *m_dlgParent;
+ WebQueryArXiv *m_wqa;
+ QString m_oldId;
+
+ void setupGUI( QWidget *parent, bool showWarnings = TRUE );
+ void addTabWidgets();
+ void addTabWidget( EntryWidgetTab *widget, const QString& title );
+ void setupEntryTypes();
+ void updateGUI();
+ void internalApply( BibTeX::Entry *entry );
+ void internalReset( BibTeX::Entry *entry );
+ void restoreWindowSize( KConfig *config );
+ void saveWindowSize( KConfig *config ) const;
+ };
+
+ class EntryWidgetDialog: public KDialogBase
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetDialog( QWidget *parent = 0, const char *name = 0, bool modal = true, const QString &caption = QString::null, int buttonMask = Ok | Apply | Cancel ) : KDialogBase( parent, name, modal, caption, buttonMask ) {/* nothing */};
+ ~EntryWidgetDialog() {/* nothing */};
+ void setMainWidget( EntryWidget *widget )
+ {
+ KDialogBase::setMainWidget( widget );
+ m_widget = widget;
+ };
+
+ protected:
+ void closeEvent( QCloseEvent * e )
+ {
+ if ( m_widget->queryClose() ) e->accept();
+ else e->ignore();
+ }
+
+ protected slots:
+ void slotCancel()
+ {
+ if ( m_widget->queryClose() ) QDialog::done( Cancel );
+ }
+
+ void slotClose()
+ {
+ if ( m_widget->queryClose() ) QDialog::done( Cancel );
+ }
+
+ private:
+ EntryWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetauthor.cpp b/src/entrywidgetauthor.cpp
new file mode 100644
index 0000000..32e2e18
--- /dev/null
+++ b/src/entrywidgetauthor.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+
+#include <fieldlistview.h>
+#include <entrywidgetwarningsitem.h>
+#include "entrywidgetauthor.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetAuthor::EntryWidgetAuthor( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : EntryWidgetTab( bibtexfile, isReadOnly, parent, name )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetAuthor::~EntryWidgetAuthor()
+ {
+ // nothing
+ }
+
+ bool EntryWidgetAuthor::isModified()
+ {
+ return m_fieldListViewAuthor->isModified() || m_fieldListViewEditor->isModified();
+ }
+
+ void EntryWidgetAuthor::updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll )
+ {
+ bool enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftAuthor ) != BibTeX::Entry::frsIgnored;
+ m_fieldListViewAuthor->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftEditor ) != BibTeX::Entry::frsIgnored;
+ m_fieldListViewEditor->setEnabled( enableWidget );
+ }
+
+ void EntryWidgetAuthor::apply( BibTeX::Entry *entry )
+ {
+ BibTeX::Value * value = m_fieldListViewAuthor->value();
+ setValue( entry, BibTeX::EntryField::ftAuthor, value );
+ if ( value != NULL ) delete value;
+
+ value = m_fieldListViewEditor->value();
+ setValue( entry, BibTeX::EntryField::ftEditor, value );
+ if ( value != NULL ) delete value;
+ }
+
+ void EntryWidgetAuthor::reset( BibTeX::Entry *entry )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftAuthor );
+ m_fieldListViewAuthor->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftEditor );
+ m_fieldListViewEditor->setValue( field != NULL ? field->value() : NULL );
+ }
+
+ void EntryWidgetAuthor::updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings )
+ {
+ if ( entryType == BibTeX::Entry::etBook || entryType == BibTeX::Entry::etInBook )
+ {
+ if ( m_fieldListViewAuthor->isEmpty() && m_fieldListViewEditor->isEmpty() )
+ new EntryWidgetWarningsItem( EntryWidgetWarningsItem::wlWarning, i18n( "The fields 'Author' or 'Editor' are required, but both are missing" ), m_fieldListViewAuthor, listViewWarnings, "warning" );
+ }
+ else
+ {
+ addMissingWarning( entryType, BibTeX::EntryField::ftAuthor, m_fieldListViewAuthor->caption(), !m_fieldListViewAuthor->isEmpty(), m_fieldListViewAuthor, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftEditor, m_fieldListViewEditor->caption(), !m_fieldListViewEditor->isEmpty(), m_fieldListViewEditor, listViewWarnings );
+ }
+ }
+
+ void EntryWidgetAuthor::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 2, 3, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setColSpacing( 1, KDialog::spacingHint() * 4 );
+
+ QLabel *label = new QLabel( QString( "%1:" ).arg( i18n( "Author" ) ), this );
+ gridLayout->addWidget( label, 0, 0 );
+ m_fieldListViewAuthor = new KBibTeX::FieldListView( i18n( "Author" ), i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewAuthor" ), m_isReadOnly, this );
+ m_fieldListViewAuthor->setFieldType( BibTeX::EntryField::ftAuthor );
+ gridLayout->addWidget( m_fieldListViewAuthor, 1, 0 );
+ label->setBuddy( m_fieldListViewAuthor );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Editor" ) ), this );
+ gridLayout->addWidget( label, 0, 2 );
+ m_fieldListViewEditor = new KBibTeX::FieldListView( i18n( "Editor" ), i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewEditor" ), m_isReadOnly, this );
+ m_fieldListViewEditor->setFieldType( BibTeX::EntryField::ftEditor );
+ gridLayout->addWidget( m_fieldListViewEditor, 1, 2 );
+ label->setBuddy( m_fieldListViewEditor );
+ }
+
+}
+#include "entrywidgetauthor.moc"
diff --git a/src/entrywidgetauthor.h b/src/entrywidgetauthor.h
new file mode 100644
index 0000000..1986614
--- /dev/null
+++ b/src/entrywidgetauthor.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETAUTHOR_H
+#define KBIBTEXENTRYWIDGETAUTHOR_H
+
+#include <entrywidgettab.h>
+
+class QWidget;
+class QScrollView;
+
+namespace KBibTeX
+{
+ class FieldListView;
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class EntryWidgetAuthor : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetAuthor( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetAuthor();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private:
+ FieldListView *m_fieldListViewAuthor;
+ FieldListView *m_fieldListViewEditor;
+
+ void setupGUI();
+
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetexternal.cpp b/src/entrywidgetexternal.cpp
new file mode 100644
index 0000000..a672e25
--- /dev/null
+++ b/src/entrywidgetexternal.cpp
@@ -0,0 +1,297 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+
+#include <kpushbutton.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kurl.h>
+#include <kurllabel.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+#include <fieldlineedit.h>
+#include <settings.h>
+#include "entrywidgetexternal.h"
+
+namespace KBibTeX
+{
+
+ const int EntryWidgetExternal::m_menuIdCurrentDirectory = 8192;
+ const int EntryWidgetExternal::m_menuIdPreviousDirectory = 8191;
+ QString EntryWidgetExternal::m_previousDirectory = QString::null;
+
+ EntryWidgetExternal::EntryWidgetExternal( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : EntryWidgetTab( bibtexfile, isReadOnly, parent, name )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetExternal::~EntryWidgetExternal()
+ {
+ // nothing
+ }
+
+ bool EntryWidgetExternal::isModified()
+ {
+ return m_fieldLineEditURL->isModified() || m_fieldLineEditDoi->isModified() || m_fieldLineEditLocalFile->isModified();
+ }
+
+ void EntryWidgetExternal::updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll )
+ {
+ bool enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftURL ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditURL->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftDoi ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditDoi->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftLocalFile ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditLocalFile->setEnabled( enableWidget );
+ m_pushButtonBrowseLocalFile->setEnabled( !m_isReadOnly && enableWidget );
+
+ updateGUI();
+ }
+
+ void EntryWidgetExternal::apply( BibTeX::Entry *entry )
+ {
+ BibTeX::Value * value = m_fieldLineEditURL->value();
+ setValue( entry, BibTeX::EntryField::ftURL, value );
+ delete value;
+
+ value = m_fieldLineEditDoi->value();
+ setValue( entry, BibTeX::EntryField::ftDoi, value );
+ delete value;
+
+ value = m_fieldLineEditLocalFile->value();
+ setValue( entry, BibTeX::EntryField::ftLocalFile, value );
+ delete value;
+ }
+
+ void EntryWidgetExternal::reset( BibTeX::Entry *entry )
+ {
+ disconnect( m_fieldLineEditURL, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+ disconnect( m_fieldLineEditDoi, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+ disconnect( m_fieldLineEditLocalFile, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+
+
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftURL );
+ m_fieldLineEditURL->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftDoi );
+ m_fieldLineEditDoi->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftLocalFile );
+ m_fieldLineEditLocalFile->setValue( field != NULL ? field->value() : NULL );
+
+ updateGUI();
+
+ connect( m_fieldLineEditURL, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_fieldLineEditDoi, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_fieldLineEditLocalFile, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+ }
+
+ void EntryWidgetExternal::updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings )
+ {
+ addMissingWarning( entryType, BibTeX::EntryField::ftURL, m_fieldLineEditURL->caption(), !m_fieldLineEditURL->isEmpty(), m_fieldLineEditURL, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftDoi, m_fieldLineEditDoi->caption(), !m_fieldLineEditDoi->isEmpty(), m_fieldLineEditDoi, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftLocalFile, m_fieldLineEditDoi->caption(), !m_fieldLineEditDoi->isEmpty(), m_fieldLineEditLocalFile, listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditURL, m_fieldLineEditURL->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditDoi, m_fieldLineEditDoi->caption(), listViewWarnings );
+
+ updateGUI();
+ }
+
+ void EntryWidgetExternal::openURL()
+ {
+ BibTeX::Value * value = m_fieldLineEditURL->value();
+ KURL url = Settings::locateFile( value->text(), m_bibtexfile->fileName, this );
+ if ( url.isValid() )
+ Settings::openUrl( url, this );
+ else
+ m_pushButtonOpenURL->setEnabled( FALSE );
+ }
+
+ void EntryWidgetExternal::openURL( const QString &url )
+ {
+ Settings::openUrl( KURL( url ), this );
+ }
+
+ void EntryWidgetExternal::openDoi()
+ {
+ BibTeX::Value * value = m_fieldLineEditDoi->value();
+ KURL url = Settings::doiURL( value->text() );
+ if ( url.isValid() )
+ Settings::openUrl( url, this );
+ else
+ m_pushButtonOpenDoi->setEnabled( FALSE );
+ }
+
+ void EntryWidgetExternal::openLocalFile()
+ {
+ BibTeX::Value * value = m_fieldLineEditLocalFile->value();
+ KURL url = Settings::locateFile( value->text(), m_bibtexfile->fileName, this );
+ if ( url.isValid() )
+ Settings::openUrl( url, this );
+ else
+ m_pushButtonOpenLocalFile->setEnabled( FALSE );
+ }
+
+ void EntryWidgetExternal::browseLocalFile( int id )
+ {
+ Settings * settings = Settings::self();
+ QString startDir = QString::null;
+ if ( id == m_menuIdPreviousDirectory && m_previousDirectory != QString::null )
+ startDir = m_previousDirectory;
+ else if ( settings->editing_DocumentSearchPaths.size() > ( unsigned int )id )
+ startDir = *settings->editing_DocumentSearchPaths.at( id );
+ else
+ startDir = QDir::currentDirPath();
+ QString filename = KFileDialog::getOpenFileName( startDir );
+
+ if ( !filename.isEmpty() )
+ {
+ /** if the user started browsing for files from a search path,
+ * remove this search path prefix from the absolute path returned
+ * by the file open dialog. */
+ if ( id >= 0 && filename.startsWith( startDir ) )
+ {
+ int len = startDir.length();
+ if ( startDir == "/" )
+ len = 0;
+ else if ( !startDir.endsWith( "/" ) )
+ ++len;
+ filename = filename.mid( len );
+ }
+
+ BibTeX::Value * value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText( filename ) );
+ m_fieldLineEditLocalFile->setValue( value );
+
+ if ( m_previousDirectory == QString::null )
+ {
+ QPopupMenu *menu = m_pushButtonBrowseLocalFile->popup();
+ menu->insertItem( QIconSet( SmallIcon( "favorite" ) ), i18n( "Previously used directory" ), m_menuIdPreviousDirectory, 2 );
+ }
+ QFileInfo fileInfo( filename );
+ m_previousDirectory = fileInfo.dirPath( true );
+ }
+ }
+
+ void EntryWidgetExternal::updateGUI()
+ {
+ BibTeX::Value * value = m_fieldLineEditURL->value();
+ m_pushButtonOpenURL->setEnabled( value != NULL && Settings::locateFile( value->text(), m_bibtexfile->fileName, this ).isValid() );
+
+ value = m_fieldLineEditLocalFile->value();
+ m_pushButtonOpenLocalFile->setEnabled( value != NULL && Settings::locateFile( value->text(), m_bibtexfile->fileName, this ).isValid() );
+
+ value = m_fieldLineEditDoi->value();
+ m_pushButtonOpenDoi->setEnabled( value != NULL && Settings::doiURL( value->text() ).isValid() );
+ }
+
+ void EntryWidgetExternal::setupGUI()
+ {
+ Settings * settings = Settings::self();
+
+ QGridLayout * gridLayout = new QGridLayout( this, 5, 3, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( 4, 10 );
+
+ QLabel *label = new QLabel( QString( "%1:" ).arg( i18n( "URL" ) ), this );
+ gridLayout->addWidget( label, 0, 0 );
+ m_fieldLineEditURL = new KBibTeX::FieldLineEdit( i18n( "URL" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditURL" );
+ m_fieldLineEditURL->setFieldType( BibTeX::EntryField::ftURL );
+ gridLayout->addWidget( m_fieldLineEditURL, 0, 1 );
+ label->setBuddy( m_fieldLineEditURL );
+ connect( m_fieldLineEditURL, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+
+ m_pushButtonOpenURL = new KPushButton( this );
+ gridLayout->addWidget( m_pushButtonOpenURL, 0, 2 );
+ m_pushButtonOpenURL->setIconSet( QIconSet( SmallIcon( "fileopen" ) ) );
+ m_pushButtonOpenURL->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QToolTip::add( m_pushButtonOpenURL, QString( i18n( "Open %1" ) ).arg( i18n( "URL" ) ) );
+ connect( m_pushButtonOpenURL, SIGNAL( clicked() ), this, SLOT( openURL() ) );
+
+ KURLLabel *urllabel = new KURLLabel( "http://www.doi.org/", QString( "%1:" ).arg( i18n( "DOI" ) ), this );
+ QToolTip::add( urllabel, i18n( "Digital Object Identifier" ) );
+ urllabel->setFocusPolicy( QWidget::NoFocus );
+ gridLayout->addWidget( urllabel, 1, 0 );
+ m_fieldLineEditDoi = new KBibTeX::FieldLineEdit( i18n( "DOI" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditDoi" );
+ m_fieldLineEditDoi->setFieldType( BibTeX::EntryField::ftDoi );
+ gridLayout->addWidget( m_fieldLineEditDoi, 1, 1 );
+ urllabel->setBuddy( m_fieldLineEditDoi );
+ connect( m_fieldLineEditDoi, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+ connect( urllabel, SIGNAL( leftClickedURL( const QString& ) ), this, SLOT( openURL( const QString& ) ) );
+
+ m_pushButtonOpenDoi = new KPushButton( this );
+ gridLayout->addWidget( m_pushButtonOpenDoi, 1, 2 );
+ m_pushButtonOpenDoi->setIconSet( QIconSet( SmallIcon( "fileopen" ) ) );
+ m_pushButtonOpenDoi->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QToolTip::add( m_pushButtonOpenDoi, i18n( "Open DOI" ) );
+ connect( m_pushButtonOpenDoi, SIGNAL( clicked() ), this, SLOT( openDoi() ) );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Local File" ) ), this );
+ gridLayout->addWidget( label, 2, 0 );
+ m_fieldLineEditLocalFile = new KBibTeX::FieldLineEdit( i18n( "Local File" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditLocalFile" );
+ m_fieldLineEditLocalFile->setFieldType( BibTeX::EntryField::ftLocalFile );
+ gridLayout->addWidget( m_fieldLineEditLocalFile, 2, 1 );
+ label->setBuddy( m_fieldLineEditLocalFile );
+ connect( m_fieldLineEditLocalFile, SIGNAL( textChanged() ), this, SLOT( updateGUI() ) );
+
+ m_pushButtonOpenLocalFile = new KPushButton( this );
+ gridLayout->addWidget( m_pushButtonOpenLocalFile, 2, 2 );
+ m_pushButtonOpenLocalFile->setIconSet( QIconSet( SmallIcon( "fileopen" ) ) );
+ m_pushButtonOpenLocalFile->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QToolTip::add( m_pushButtonOpenLocalFile, QString( i18n( "Open %1" ) ).arg( i18n( "Local File" ) ) );
+ connect( m_pushButtonOpenLocalFile, SIGNAL( clicked() ), this, SLOT( openLocalFile() ) );
+
+ QWidget *container = new QWidget( this );
+ QHBoxLayout *containerLayout = new QHBoxLayout( container );
+ gridLayout->addWidget( container, 3, 1 );
+ m_pushButtonBrowseLocalFile = new KPushButton( i18n( "&Browse..." ), container );
+ QToolTip::add( m_pushButtonBrowseLocalFile, i18n( "Browse for a local file" ) );
+ m_pushButtonBrowseLocalFile->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ containerLayout->addWidget( m_pushButtonBrowseLocalFile );
+ containerLayout->addStretch( 10 );
+ m_pushButtonBrowseLocalFile->setIconSet( QIconSet( SmallIcon( "fileopen" ) ) );
+
+ KPopupMenu *menu = new KPopupMenu( m_pushButtonBrowseLocalFile );
+ menu->insertTitle( i18n( "Select base directory" ) );
+ menu->insertItem( QIconSet( SmallIcon( "favorite" ) ), i18n( "Current directory" ), m_menuIdCurrentDirectory );
+ if ( m_previousDirectory != QString::null )
+ menu->insertItem( QIconSet( SmallIcon( "favorite" ) ), i18n( "Previously used directory" ), m_menuIdPreviousDirectory );
+ if ( !settings->editing_DocumentSearchPaths.isEmpty() )
+ {
+ menu->insertSeparator();
+ int i = 0;
+ for ( QStringList::Iterator it = settings->editing_DocumentSearchPaths.begin(); it != settings->editing_DocumentSearchPaths.end(); ++it, ++i )
+ menu->insertItem( QIconSet( SmallIcon( "folder" ) ), *it, i );
+ }
+ m_pushButtonBrowseLocalFile->setPopup( menu );
+ connect( menu, SIGNAL( activated( int ) ), this, SLOT( browseLocalFile( int ) ) );
+ }
+}
+#include "entrywidgetexternal.moc"
diff --git a/src/entrywidgetexternal.h b/src/entrywidgetexternal.h
new file mode 100644
index 0000000..16cb608
--- /dev/null
+++ b/src/entrywidgetexternal.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETEXTERNAL_H
+#define KBIBTEXENTRYWIDGETEXTERNAL_H
+
+#include <entrywidgettab.h>
+
+class KPushButton;
+class KURL;
+
+namespace KBibTeX
+{
+
+ class FieldLineEdit;
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class EntryWidgetExternal : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetExternal( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetExternal();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private slots:
+ void openURL();
+ void openURL( const QString & );
+ void openDoi();
+ void openLocalFile();
+ void browseLocalFile( int id );
+ void updateGUI();
+
+ private:
+ FieldLineEdit *m_fieldLineEditURL;
+ KPushButton *m_pushButtonOpenURL;
+ FieldLineEdit *m_fieldLineEditDoi;
+ KPushButton *m_pushButtonOpenDoi;
+ FieldLineEdit *m_fieldLineEditLocalFile;
+ KPushButton *m_pushButtonOpenLocalFile;
+ KPushButton *m_pushButtonBrowseLocalFile;
+
+ static QString m_previousDirectory;
+ static const int m_menuIdCurrentDirectory, m_menuIdPreviousDirectory;
+
+ void setupGUI();
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetkeyword.cpp b/src/entrywidgetkeyword.cpp
new file mode 100644
index 0000000..b61acc0
--- /dev/null
+++ b/src/entrywidgetkeyword.cpp
@@ -0,0 +1,283 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qregexp.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <qtimer.h>
+#include <qlabel.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdialogbase.h>
+#include <kmessagebox.h>
+#include <klistview.h>
+#include <kguiitem.h>
+#include <kdebug.h>
+
+#include <settings.h>
+#include "entrywidgetkeyword.h"
+
+namespace KBibTeX
+{
+ KeywordListViewItem::KeywordListViewItem( KListView * parent, const QString & text, bool global ) : QCheckListItem( parent, text, QCheckListItem::CheckBox )
+ {
+ setGlobal( global );
+ }
+
+ KeywordListViewItem::~KeywordListViewItem()
+ {
+// nothing
+ }
+
+ void KeywordListViewItem::setGlobal( bool global )
+ {
+ m_isGlobal = global;
+ if ( m_isGlobal )
+ {
+ setText( 1, i18n( "Global" ) );
+ setPixmap( 1, SmallIcon( "package" ) );
+ }
+ else
+ {
+ setText( 1, i18n( "In this file only" ) );
+ setPixmap( 1, SmallIcon( "editcopy" ) );
+ }
+ }
+
+ EntryWidgetKeyword::EntryWidgetKeyword( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name ) : EntryWidgetTab( bibtexfile, isReadOnly, parent, name ), m_bibtexfile( bibtexfile ), m_isModified( FALSE ), m_numKeywords( 0 )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetKeyword::~EntryWidgetKeyword()
+ {
+ // nothing
+ }
+
+ bool EntryWidgetKeyword::isModified()
+ {
+ return m_isModified;
+ }
+
+ void EntryWidgetKeyword::updateGUI( BibTeX::Entry::EntryType /*entryType*/, bool /*enableAll*/ )
+ {
+ // nothing
+ }
+
+ void EntryWidgetKeyword::apply( BibTeX::Entry *entry )
+ {
+ readListView();
+
+ /**
+ * Update entry
+ */
+ if ( m_usedKeywords.empty() )
+ entry->deleteField( BibTeX::EntryField::ftKeywords );
+ else
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftKeywords );
+ BibTeX::Value *value = NULL;
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftKeywords );
+ entry->addField( field );
+ }
+ value = field->value();
+ value->items.clear();
+ BibTeX::KeywordContainer *keywordContainer = new BibTeX::KeywordContainer( m_usedKeywords );
+ value->items.append( keywordContainer );
+ }
+
+ /**
+ * Update global keyword list
+ */
+ KBibTeX::Settings * settings = KBibTeX::Settings::self();
+ settings->keyword_GlobalList = m_globalKeywords;
+ }
+
+ void EntryWidgetKeyword::reset( BibTeX::Entry *entry )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftKeywords );
+ BibTeX::KeywordContainer *keywordContainer = NULL;
+ if ( field != NULL && ( keywordContainer = dynamic_cast<BibTeX::KeywordContainer*>( field->value()->items.first() ) ) != NULL )
+ for ( QValueList<BibTeX::Keyword*>::Iterator it = keywordContainer->keywords.begin(); it != keywordContainer->keywords.end(); ++it )
+ m_usedKeywords.append(( *it )->text() );
+
+ if ( m_bibtexfile != NULL )
+ m_fileKeywords = m_bibtexfile->getAllValuesAsStringList( BibTeX::EntryField::ftKeywords );
+
+ KBibTeX::Settings * settings = KBibTeX::Settings::self();
+ m_globalKeywords = settings->keyword_GlobalList;
+
+ m_availableKeywords = QStringList( m_globalKeywords );
+ for ( QStringList::Iterator it = m_fileKeywords.begin(); it != m_fileKeywords.end(); ++it )
+ if ( !m_availableKeywords.contains( *it ) )
+ m_availableKeywords.append( *it );
+ for ( QStringList::Iterator it = m_usedKeywords.begin(); it != m_usedKeywords.end(); ++it )
+ if ( !m_availableKeywords.contains( *it ) )
+ m_availableKeywords.append( *it );
+
+ setListView();
+ }
+
+ void EntryWidgetKeyword::updateWarnings( BibTeX::Entry::EntryType /*entryType*/, QListView */*listViewWarnings*/ )
+ {
+ // nothing
+ }
+
+ void EntryWidgetKeyword::slotSelectionChanged()
+ {
+ bool hasCurrent = m_listviewKeywords->selectedItem() != NULL;
+
+ m_buttonEdit->setEnabled( hasCurrent );
+ m_buttonToggleGlobal->setEnabled( hasCurrent );
+ }
+
+ void EntryWidgetKeyword::slotKeywordRenamed( QListViewItem * item, const QString & text, int /*col*/ )
+ {
+ KeywordListViewItem *kwlvi = dynamic_cast<KeywordListViewItem*>( item );
+ if ( text.isEmpty() )
+ {
+ item->setText( 0, m_beforeRenaming );
+ kwlvi->setOn( FALSE );
+ }
+ else if ( text != m_beforeRenaming )
+ {
+ if ( m_availableKeywords.contains( text ) )
+ {
+ item->setText( 0, m_beforeRenaming );
+ KMessageBox::error( this, QString( i18n( "The keyword '%1' does already exist in the list of keywords.\nThe old name has been restored." ) ).arg( text ), i18n( "Renaming keyword failed" ) );
+ }
+ else
+ {
+ m_availableKeywords.remove( m_beforeRenaming );
+ m_availableKeywords.append( text );
+ if ( kwlvi->isGlobal() )
+ {
+ m_globalKeywords.remove( m_beforeRenaming );
+ m_globalKeywords.append( text );
+ }
+ else
+ {
+ m_fileKeywords.remove( m_beforeRenaming );
+ m_fileKeywords.append( text );
+ }
+ QCheckListItem *checkedItem = dynamic_cast<QCheckListItem*>( item );
+ if ( checkedItem != NULL )
+ checkedItem->setOn( TRUE );
+ }
+ }
+ }
+
+ void EntryWidgetKeyword::slotNewKeyword()
+ {
+ KeywordListViewItem * item = new KeywordListViewItem( m_listviewKeywords, QString( i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewKeyword%1" ) ).arg( ++m_numKeywords ), FALSE );
+ m_listviewKeywords->setSelected( item, TRUE );
+ QTimer::singleShot( 100, this, SLOT( slotEditKeyword() ) );
+ }
+
+ void EntryWidgetKeyword::slotEditKeyword()
+ {
+ QListViewItem * item = m_listviewKeywords->selectedItem();
+ if ( item != NULL )
+ {
+ m_beforeRenaming = item->text( 0 );
+ m_listviewKeywords->rename( item, 0 );
+ }
+ }
+
+ void EntryWidgetKeyword::slotToggleGlobal()
+ {
+ KeywordListViewItem *item = dynamic_cast<KeywordListViewItem*>( m_listviewKeywords->selectedItem() );
+ if ( item != NULL )
+ {
+ bool isGlobal = item->isGlobal();
+ if ( isGlobal )
+ m_globalKeywords.remove( item->text( 0 ) );
+ else
+ m_globalKeywords.append( item->text( 0 ) );
+
+ item->setGlobal( !isGlobal );
+ }
+ }
+
+ void EntryWidgetKeyword::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 6, 2, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( 4, 1 );
+
+ m_listviewKeywords = new KListView( this );
+ m_listviewKeywords->setEnabled( !m_isReadOnly );
+ m_listviewKeywords->addColumn( i18n( "Keyword" ) );
+ m_listviewKeywords->addColumn( i18n( "Origin" ) );
+ gridLayout->addMultiCellWidget( m_listviewKeywords, 0, 4, 0, 0 );
+ m_listviewKeywords->setAllColumnsShowFocus( TRUE );
+ connect( m_listviewKeywords, SIGNAL( currentChanged( QListViewItem* ) ), this, SLOT( slotSelectionChanged() ) );
+ connect( m_listviewKeywords, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( slotSelectionChanged() ) );
+ connect( m_listviewKeywords, SIGNAL( itemRenamed( QListViewItem*, const QString&, int ) ), this, SLOT( slotKeywordRenamed( QListViewItem*, const QString&, int ) ) );
+
+ m_buttonNew = new QPushButton( i18n( "keyword", "New" ), this );
+ m_buttonNew->setEnabled( !m_isReadOnly );
+ m_buttonNew->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ QToolTip::add( m_buttonNew, i18n( "Add a new keyword to the list" ) );
+ gridLayout->addWidget( m_buttonNew, 0, 1 );
+ connect( m_buttonNew, SIGNAL( clicked() ), this, SLOT( slotNewKeyword() ) );
+
+ m_buttonEdit = new QPushButton( i18n( "keyword", "Edit" ), this );
+ m_buttonEdit->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ QToolTip::add( m_buttonEdit, i18n( "Edit the selected keyword" ) );
+ gridLayout->addWidget( m_buttonEdit, 1, 1 );
+ m_buttonEdit->setEnabled( FALSE );
+ connect( m_buttonEdit, SIGNAL( clicked() ), this, SLOT( slotEditKeyword() ) );
+
+ m_buttonToggleGlobal = new QPushButton( i18n( "keyword", "Toggle &global" ), this );
+ m_buttonToggleGlobal->setIconSet( QIconSet( SmallIcon( "package" ) ) );
+ QToolTip::add( m_buttonToggleGlobal, i18n( "Add or remove the selected keyword to or from the global list" ) );
+ gridLayout->addWidget( m_buttonToggleGlobal, 2, 1 );
+ m_buttonToggleGlobal->setEnabled( FALSE );
+ connect( m_buttonToggleGlobal, SIGNAL( clicked() ), this, SLOT( slotToggleGlobal() ) );
+
+ QLabel *label = new QLabel( i18n( "There is no need to delete keywords. Simply uncheck unwanted keywords and make them non-global.\nGlobal keywords can also be edited in the settings dialog." ), this );
+ label->setAlignment( QLabel::WordBreak | QLabel::AlignTop );
+ gridLayout->addMultiCellWidget( label, 5, 5, 0, 1 );
+ }
+
+ void EntryWidgetKeyword::setListView()
+ {
+ m_availableKeywords.sort();
+ m_listviewKeywords->clear();
+ for ( QStringList::Iterator it = m_availableKeywords.begin(); it != m_availableKeywords.end(); ++it )
+ {
+ KeywordListViewItem *item = new KeywordListViewItem( m_listviewKeywords, *it, m_globalKeywords.contains( *it ) );
+ if ( m_usedKeywords.contains( *it ) )
+ item->setOn( TRUE );
+ }
+ }
+
+ void EntryWidgetKeyword::readListView()
+ {
+ m_usedKeywords.clear();
+ for ( QListViewItemIterator it = QListViewItemIterator( m_listviewKeywords, QListViewItemIterator::Checked ); it.current() != NULL; ++it )
+ m_usedKeywords.append(( *it ) ->text( 0 ) );
+ }
+}
+#include "entrywidgetkeyword.moc"
diff --git a/src/entrywidgetkeyword.h b/src/entrywidgetkeyword.h
new file mode 100644
index 0000000..88eae61
--- /dev/null
+++ b/src/entrywidgetkeyword.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETKEYWORD_H
+#define KBIBTEXENTRYWIDGETKEYWORD_H
+
+#include <entrywidgettab.h>
+
+class QPushButton;
+class KListView;
+
+namespace KBibTeX
+{
+ class KeywordListViewItem: public QCheckListItem
+ {
+ public:
+ KeywordListViewItem( KListView * parent, const QString & text, bool isGlobal );
+ ~KeywordListViewItem();
+
+ bool isGlobal()
+ {
+ return m_isGlobal;
+ };
+ void setGlobal( bool global );
+
+ protected:
+ bool m_isGlobal;
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class EntryWidgetKeyword : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetKeyword( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetKeyword();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private slots:
+ void slotSelectionChanged();
+ void slotKeywordRenamed( QListViewItem * item, const QString & text, int col );
+ void slotNewKeyword();
+ void slotEditKeyword();
+ void slotToggleGlobal();
+
+ private:
+ BibTeX::File *m_bibtexfile;
+ QStringList m_availableKeywords;
+ QStringList m_globalKeywords;
+ QStringList m_fileKeywords;
+ QStringList m_usedKeywords;
+ bool m_isModified;
+ KListView *m_listviewKeywords;
+ QPushButton *m_buttonNew;
+ QPushButton *m_buttonEdit;
+ QPushButton *m_buttonToggleGlobal;
+ int m_numKeywords;
+ QString m_beforeRenaming;
+
+ void setupGUI();
+ void setListView();
+ void readListView();
+ bool editKeywords( QStringList *keywords );
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetmisc.cpp b/src/entrywidgetmisc.cpp
new file mode 100644
index 0000000..f2e4f5e
--- /dev/null
+++ b/src/entrywidgetmisc.cpp
@@ -0,0 +1,172 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+
+#include <fieldlineedit.h>
+#include <value.h>
+#include <entryfield.h>
+#include "entrywidgetmisc.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetMisc::EntryWidgetMisc( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : EntryWidgetTab( bibtexfile, isReadOnly, parent, name )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetMisc::~EntryWidgetMisc()
+ {
+ // nothing
+ }
+
+ bool EntryWidgetMisc::isModified()
+ {
+ return m_fieldLineEditType->isModified() || m_fieldLineEditKey->isModified() || m_fieldLineEditNote->isModified() || m_fieldLineEditAnnote->isModified() || m_fieldLineEditAbstract->isModified();
+ }
+
+ void EntryWidgetMisc::updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll )
+ {
+ bool enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftType ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditType->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftKey ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditKey->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftNote ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditNote->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftAnnote ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditAnnote->setEnabled( enableWidget );
+ }
+
+ void EntryWidgetMisc::apply( BibTeX::Entry *entry )
+ {
+ BibTeX::Value * value = m_fieldLineEditType->value();
+ setValue( entry, BibTeX::EntryField::ftType, value );
+ delete value;
+
+ value = m_fieldLineEditKey-> value();
+ setValue( entry, BibTeX::EntryField::ftKey, value );
+ delete value;
+
+ value = m_fieldLineEditNote-> value();
+ setValue( entry, BibTeX::EntryField::ftNote, value );
+ delete value;
+
+ value = m_fieldLineEditAnnote-> value();
+ setValue( entry, BibTeX::EntryField::ftAnnote, value );
+ delete value;
+
+ value = m_fieldLineEditAbstract-> value();
+ setValue( entry, BibTeX::EntryField::ftAbstract, value );
+ delete value;
+ }
+
+ void EntryWidgetMisc::reset( BibTeX::Entry *entry )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftType );
+ m_fieldLineEditType->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftKey );
+ m_fieldLineEditKey->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftNote );
+ m_fieldLineEditNote->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftAnnote );
+ m_fieldLineEditAnnote->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftAbstract );
+ m_fieldLineEditAbstract->setValue( field != NULL ? field->value() : NULL );
+ }
+
+ void EntryWidgetMisc::updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings )
+ {
+ addMissingWarning( entryType, BibTeX::EntryField::ftType, m_fieldLineEditType->caption(), !m_fieldLineEditType->isEmpty(), m_fieldLineEditType, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftKey, m_fieldLineEditKey->caption(), !m_fieldLineEditKey->isEmpty(), m_fieldLineEditKey, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftNote, m_fieldLineEditNote->caption(), !m_fieldLineEditNote->isEmpty(), m_fieldLineEditNote, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftAnnote, m_fieldLineEditAnnote->caption(), !m_fieldLineEditAnnote->isEmpty(), m_fieldLineEditAnnote, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftAbstract, m_fieldLineEditAbstract->caption(), !m_fieldLineEditAbstract->isEmpty(), m_fieldLineEditAbstract, listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditType, m_fieldLineEditType->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditKey, m_fieldLineEditKey->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditNote, m_fieldLineEditNote->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditAnnote, m_fieldLineEditAnnote->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditAbstract, m_fieldLineEditAbstract->caption(), listViewWarnings );
+ }
+
+ void EntryWidgetMisc::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 5, 5, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setColSpacing( 2, KDialog::spacingHint() * 4 );
+ gridLayout->setRowStretch( 4, 1 );
+
+ QLabel *label = new QLabel( QString( "%1:" ).arg( i18n( "Type" ) ), this );
+ gridLayout->addWidget( label, 0, 0 );
+ m_fieldLineEditType = new KBibTeX::FieldLineEdit( i18n( "Type" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditType" );
+ m_fieldLineEditType->setFieldType( BibTeX::EntryField::ftType );
+ label->setBuddy( m_fieldLineEditType );
+ gridLayout->addWidget( m_fieldLineEditType, 0, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Key" ) ), this );
+ gridLayout->addWidget( label, 0, 3 );
+ m_fieldLineEditKey = new KBibTeX::FieldLineEdit( i18n( "Key" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditKey" );
+ m_fieldLineEditKey->setFieldType( BibTeX::EntryField::ftKey );
+ label->setBuddy( m_fieldLineEditKey );
+ gridLayout->addWidget( m_fieldLineEditKey, 0, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Note" ) ), this );
+ gridLayout->addWidget( label, 1, 0 );
+ m_fieldLineEditNote = new KBibTeX::FieldLineEdit( i18n( "Note" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditNote" );
+ m_fieldLineEditNote->setFieldType( BibTeX::EntryField::ftNote );
+ label->setBuddy( m_fieldLineEditNote );
+ gridLayout->addMultiCellWidget( m_fieldLineEditNote, 1, 1, 1, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Annote" ) ), this );
+ gridLayout->addWidget( label, 2, 0 );
+ m_fieldLineEditAnnote = new KBibTeX::FieldLineEdit( i18n( "Annote" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditAnnote" );
+ m_fieldLineEditAnnote->setFieldType( BibTeX::EntryField::ftAnnote );
+ label->setBuddy( m_fieldLineEditAnnote );
+ gridLayout->addMultiCellWidget( m_fieldLineEditAnnote, 2, 2, 1, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Abstract" ) ), this );
+ gridLayout->addWidget( label, 3, 0 );
+ m_fieldLineEditAbstract = new KBibTeX::FieldLineEdit( i18n( "Abstract" ), KBibTeX::FieldLineEdit::itMultiLine, m_isReadOnly, this, "m_fieldLineEditAbstract" );
+ m_fieldLineEditAbstract->setFieldType( BibTeX::EntryField::ftAbstract );
+ label->setBuddy( m_fieldLineEditAbstract );
+ gridLayout->addMultiCellWidget( m_fieldLineEditAbstract, 3, 4, 1, 4 );
+ }
+
+}
+#include "entrywidgetmisc.moc"
diff --git a/src/entrywidgetmisc.h b/src/entrywidgetmisc.h
new file mode 100644
index 0000000..5cb99b2
--- /dev/null
+++ b/src/entrywidgetmisc.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETMISC_H
+#define KBIBTEXENTRYWIDGETMISC_H
+
+#include <entrywidgettab.h>
+
+namespace KBibTeX
+{
+ class FieldLineEdit;
+
+ class EntryWidgetMisc : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetMisc( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetMisc();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private:
+ FieldLineEdit *m_fieldLineEditType;
+ FieldLineEdit *m_fieldLineEditKey;
+ FieldLineEdit *m_fieldLineEditNote;
+ FieldLineEdit *m_fieldLineEditAnnote;
+ FieldLineEdit *m_fieldLineEditAbstract;
+
+ void setupGUI();
+
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetother.cpp b/src/entrywidgetother.cpp
new file mode 100644
index 0000000..1c5d13b
--- /dev/null
+++ b/src/entrywidgetother.cpp
@@ -0,0 +1,319 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qstringlist.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+
+#include <kdialog.h>
+#include <kapplication.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <kpushbutton.h>
+#include <klineedit.h>
+
+#include <fieldlineedit.h>
+#include <settings.h>
+#include "entrywidgetother.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetOther::EntryWidgetOther( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : EntryWidgetTab( bibtexfile, isReadOnly, parent, name ), m_isModified( FALSE )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetOther::~EntryWidgetOther()
+ {
+ m_listViewFields->clear();
+ }
+
+ bool EntryWidgetOther::isModified()
+ {
+ return m_isModified;
+ }
+
+ void EntryWidgetOther::updateGUI( BibTeX::Entry::EntryType /*entryType*/, bool /*enableAll*/ )
+ {
+ // nothing
+ }
+
+ void EntryWidgetOther::apply( BibTeX::Entry *entry )
+ {
+ Settings * settings = Settings::self();
+ QStringList toBeDeleted;
+ for ( QValueList<BibTeX::EntryField*>::ConstIterator it = entry->begin(); it != entry->end(); it++ )
+ {
+ BibTeX::EntryField *field = *it;
+ bool doDel = field->fieldType() == BibTeX::EntryField::ftUnknown;
+ if ( !doDel ) continue;
+
+ QString ftn = field->fieldTypeName().lower();
+ for ( unsigned int i = 0; doDel && i < settings->userDefinedInputFields.count(); ++i )
+ doDel &= settings->userDefinedInputFields[i]->name.lower() != ftn;
+
+ if ( doDel )
+ toBeDeleted.append( ftn );
+ }
+ for ( QStringList::ConstIterator it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it )
+ entry->deleteField( *it );
+
+ for ( QListViewItemIterator it( m_listViewFields ); it.current(); it++ )
+ {
+ ValueListViewItem *vlvi = dynamic_cast<KBibTeX::ValueListViewItem*>( it.current() );
+ if ( vlvi != NULL )
+ {
+ BibTeX::EntryField * field = new BibTeX::EntryField( vlvi->title() );
+ field->setValue( vlvi->value() );
+ entry->addField( field );
+ }
+ }
+
+ m_isModified = FALSE;
+ }
+
+ void EntryWidgetOther::reset( BibTeX::Entry *entry )
+ {
+ m_listViewFields->clear();
+
+ Settings * settings = Settings::self();
+ for ( QValueList<BibTeX::EntryField*>::ConstIterator it = entry->begin(); it != entry->end(); it++ )
+ {
+ BibTeX::EntryField *field = *it;
+ bool doAdd = field->fieldType() == BibTeX::EntryField::ftUnknown;
+ if ( !doAdd ) continue;
+
+ QString ftn = field->fieldTypeName().lower();
+ for ( unsigned int i = 0; doAdd && i < settings->userDefinedInputFields.count(); ++i )
+ doAdd &= settings->userDefinedInputFields[i]->name.lower() != ftn;
+
+ if ( doAdd )
+ new ValueListViewItem( field->fieldTypeName(), field->value(), m_listViewFields );
+ }
+
+ m_isModified = FALSE;
+ }
+
+ void EntryWidgetOther::updateWarnings( BibTeX::Entry::EntryType /*entryType*/, QListView * /*listViewWarnings*/ )
+ {
+ // no warnings neccessary for user fields
+ }
+
+ void EntryWidgetOther::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 5, 3, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+
+ m_lineEditKey = new KLineEdit( this, "m_lineEditKey" );
+ m_lineEditKey->setReadOnly( m_isReadOnly );
+ gridLayout->addWidget( m_lineEditKey, 0, 1 );
+ QToolTip::add( m_lineEditKey, i18n( "Name of the user-defined field" ) );
+ QWhatsThis::add( m_lineEditKey, i18n( "The name of the user-defined field. Should only contain letters and numbers." ) );
+ QLabel *label = new QLabel( i18n( "&Name:" ), this );
+ label->setBuddy( m_lineEditKey );
+ gridLayout->addWidget( label, 0, 0 );
+
+ m_pushButtonAdd = new KPushButton( i18n( "&Add" ), this, "m_pushButtonAdd" );
+ gridLayout->addWidget( m_pushButtonAdd, 0, 2 );
+ m_pushButtonAdd->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+
+ m_fieldLineEditValue = new KBibTeX::FieldLineEdit( i18n( "Value" ), KBibTeX::FieldLineEdit::itMultiLine, m_isReadOnly, this, "m_fieldLineEditValue" );
+ gridLayout->addMultiCellWidget( m_fieldLineEditValue, 1, 2, 1, 2 );
+ QToolTip::add( m_fieldLineEditValue, i18n( "Content of the user-defined field" ) );
+ QWhatsThis::add( m_fieldLineEditValue, i18n( "The content of the user-defined field. May contain any text." ) );
+ label = new QLabel( i18n( "&Content:" ), this );
+ label->setBuddy( m_fieldLineEditValue );
+ gridLayout->addWidget( label, 1, 0 );
+
+ QSpacerItem* spacer = new QSpacerItem( 20, 110, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ gridLayout->addItem( spacer, 2, 0 );
+
+ m_listViewFields = new KListView( this, "m_listViewFields" );
+ m_listViewFields->addColumn( i18n( "Key" ) );
+ m_listViewFields->addColumn( i18n( "Value" ) );
+ m_listViewFields->setAllColumnsShowFocus( true );
+ m_listViewFields->setFullWidth( TRUE );
+ gridLayout->addMultiCellWidget( m_listViewFields, 3, 5, 1, 1 );
+
+ label = new QLabel( i18n( "&List:" ), this );
+ label->setBuddy( m_listViewFields );
+ label->setAlignment( Qt::AlignTop );
+ gridLayout->addWidget( label, 3, 0 );
+
+ m_pushButtonDelete = new KPushButton( i18n( "&Delete" ), this, "m_pushButtonDelete" );
+ gridLayout->addWidget( m_pushButtonDelete, 3, 2 );
+ m_pushButtonDelete->setIconSet( QIconSet( SmallIcon( "delete" ) ) );
+
+ m_pushButtonOpen = new KPushButton( i18n( "Op&en" ), this, "m_pushButtonOpen" );
+ gridLayout->addWidget( m_pushButtonOpen, 4, 2 );
+ m_pushButtonOpen->setIconSet( QIconSet( SmallIcon( "fileopen" ) ) );
+
+ spacer = new QSpacerItem( 20, 110, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ gridLayout->addItem( spacer, 5, 2 );
+
+ m_pushButtonOpen->setEnabled( FALSE );
+ m_pushButtonAdd->setEnabled( FALSE );
+ m_pushButtonDelete->setEnabled( FALSE );
+
+ connect( m_listViewFields, SIGNAL( clicked( QListViewItem*, const QPoint&, int ) ), this, SLOT( fieldExecute( QListViewItem* ) ) );
+ connect( m_lineEditKey, SIGNAL( textChanged( const QString& ) ), this, SLOT( updateGUI() ) );
+ connect( m_fieldLineEditValue, SIGNAL( textChanged( ) ), this, SLOT( updateGUI() ) );
+ connect( m_pushButtonAdd, SIGNAL( clicked( ) ), this, SLOT( addClicked( ) ) );
+ connect( m_pushButtonDelete, SIGNAL( clicked( ) ), this, SLOT( deleteClicked( ) ) );
+ connect( m_pushButtonOpen, SIGNAL( clicked() ), this, SLOT( openClicked() ) );
+ }
+
+ void EntryWidgetOther::updateGUI()
+ {
+ QString text = m_lineEditKey->text();
+ QListViewItem * item = m_listViewFields->findItem( text, 0 ) ;
+ bool contains = item != NULL;
+ bool isUnknown = BibTeX::EntryField::fieldTypeFromString( text ) == BibTeX::EntryField::ftUnknown;
+
+ if ( contains )
+ m_listViewFields->setSelected( item, TRUE );
+ else
+ m_listViewFields->clearSelection();
+
+ m_pushButtonDelete->setEnabled( !m_isReadOnly && contains );
+ m_pushButtonAdd->setEnabled( !m_isReadOnly && !text.isEmpty() && !m_fieldLineEditValue->isEmpty() && isUnknown );
+ m_pushButtonAdd->setText( contains ? i18n( "&Apply" ) : i18n( "&Add" ) );
+ m_pushButtonAdd->setIconSet( QIconSet( SmallIcon( contains ? "apply" : "fileopen" ) ) );
+
+ bool validURL = FALSE;
+ if ( contains )
+ {
+ KURL url = Settings::locateFile( item->text( 1 ), m_bibtexfile->fileName, this );
+ validURL = url.isValid();
+ m_internalURL = url;
+ }
+ m_pushButtonOpen->setEnabled( validURL );
+ }
+
+ void EntryWidgetOther::fieldExecute( QListViewItem * item )
+ {
+ ValueListViewItem * vlvi = dynamic_cast<KBibTeX::ValueListViewItem*>( item );
+ if ( vlvi != NULL )
+ {
+ m_lineEditKey->setText( vlvi->title() );
+ m_fieldLineEditValue->setValue( vlvi->value() );
+ }
+ }
+
+ void EntryWidgetOther::addClicked()
+ {
+ QString key = m_lineEditKey->text();
+ QListViewItem * item = m_listViewFields->findItem( key, 0 ) ;
+ ValueListViewItem * vlvi = item != NULL ? dynamic_cast<KBibTeX::ValueListViewItem*>( item ) : NULL;
+
+ if ( vlvi != NULL )
+ vlvi->setValue( m_fieldLineEditValue->value() );
+ else
+ new ValueListViewItem( key, m_fieldLineEditValue->value(), m_listViewFields );
+
+ updateGUI();
+
+ m_isModified = TRUE;
+ }
+
+ void EntryWidgetOther::deleteClicked()
+ {
+ QListViewItem * item = m_listViewFields->findItem( m_lineEditKey->text(), 0 );
+
+ if ( item != NULL )
+ {
+ delete item;
+ m_lineEditKey->setText( "" );
+ m_fieldLineEditValue->setValue( new BibTeX::Value() );
+ updateGUI();
+ }
+
+ m_isModified = TRUE;
+ }
+
+ void EntryWidgetOther::openClicked()
+ {
+ if ( m_internalURL.isValid() )
+ {
+ BibTeX::Value * value = m_fieldLineEditValue->value();
+ Settings::openUrl( m_internalURL, this );
+ delete value;
+ }
+ else
+ m_fieldLineEditValue->setEnabled( FALSE );
+ }
+
+ ValueListViewItem::ValueListViewItem( const QString& title, BibTeX::Value *value, QListView *parent )
+ : QListViewItem( parent ), m_title( title )
+ {
+ m_value = new BibTeX::Value( value );
+ setTexts( m_title );
+ }
+
+ ValueListViewItem::~ValueListViewItem()
+ {
+ delete m_value;
+ }
+
+ const BibTeX::Value *ValueListViewItem::value()
+ {
+ return m_value;
+ }
+
+ QString ValueListViewItem::title()
+ {
+ return m_title;
+ }
+
+ void ValueListViewItem::setValue( BibTeX::Value *value )
+ {
+ if ( value != m_value )
+ {
+ if ( m_value != NULL )
+ delete m_value;
+
+ if ( value != NULL )
+ m_value = new BibTeX::Value( value );
+ else
+ m_value = new BibTeX::Value();
+
+ }
+ setTexts( m_title );
+ }
+
+ void ValueListViewItem::setTitle( const QString &title )
+ {
+ m_title = title;
+ setTexts( title );
+ }
+
+ void ValueListViewItem::setTexts( const QString& title )
+ {
+ setText( 0, title );
+ if ( m_value != NULL )
+ setText( 1, m_value->text() );
+ }
+
+}
+#include "entrywidgetother.moc"
diff --git a/src/entrywidgetother.h b/src/entrywidgetother.h
new file mode 100644
index 0000000..1119214
--- /dev/null
+++ b/src/entrywidgetother.h
@@ -0,0 +1,96 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETOTHER_H
+#define KBIBTEXENTRYWIDGETOTHER_H
+
+#include <kurl.h>
+
+#include <entrywidgettab.h>
+
+class QPushButton;
+class KListView;
+class QLineEdit;
+
+namespace KBibTeX
+{
+
+ class ValueListViewItem;
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class EntryWidgetOther : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetOther( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetOther();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType /*entryType*/, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView * /*listViewWarnings*/ );
+
+ private:
+ bool m_isModified;
+
+ QPushButton *m_pushButtonAdd;
+ QPushButton *m_pushButtonDelete;
+ QPushButton *m_pushButtonOpen;
+ QLineEdit *m_lineEditKey;
+ FieldLineEdit *m_fieldLineEditValue;
+ KListView *m_listViewFields;
+ KURL m_internalURL;
+
+ void setupGUI();
+
+ private slots:
+ void updateGUI();
+ void fieldExecute( QListViewItem * item );
+ void addClicked();
+ void deleteClicked();
+ void openClicked();
+
+ };
+
+ class ValueListViewItem : public QListViewItem
+ {
+ public:
+ ValueListViewItem( const QString& title, BibTeX::Value *value, QListView *parent );
+ ~ValueListViewItem();
+
+ const BibTeX::Value *value();
+ QString title();
+ void setValue( BibTeX::Value *value );
+ void setTitle( const QString &title );
+
+ private:
+ QString m_title;
+ BibTeX::Value *m_value;
+
+ void setTexts( const QString& title );
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetpublication.cpp b/src/entrywidgetpublication.cpp
new file mode 100644
index 0000000..d1dfd14
--- /dev/null
+++ b/src/entrywidgetpublication.cpp
@@ -0,0 +1,563 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <qpushbutton.h>
+#include <qpopupmenu.h>
+#include <qtooltip.h>
+
+#include <kurl.h>
+#include <kiconloader.h>
+#include <kdialog.h>
+#include <klocale.h>
+
+#include <settings.h>
+#include <fieldlineedit.h>
+#include <entrywidgetwarningsitem.h>
+#include "entrywidgetpublication.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetPublication::EntryWidgetPublication( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : EntryWidgetTab( bibtexfile, isReadOnly, parent, name )
+ {
+ setupGUI();
+ }
+
+
+ EntryWidgetPublication::~EntryWidgetPublication()
+ {
+ // nothing
+ }
+
+ bool EntryWidgetPublication::isModified()
+ {
+ return m_fieldLineEditOrganization->isModified() || m_fieldLineEditPublisher->isModified() || m_fieldLineEditSchool->isModified() || m_fieldLineEditInstitution->isModified() || m_fieldLineEditLocation->isModified() || m_fieldLineEditAddress->isModified() || m_fieldLineEditJournal->isModified() || m_fieldLineEditPages->isModified() || m_fieldLineEditEdition->isModified() || m_fieldLineEditChapter->isModified() || m_fieldLineEditVolume->isModified() || m_fieldLineEditNumber->isModified() || m_fieldLineEditMonth->isModified() || m_fieldLineEditYear->isModified() || m_fieldLineEditISBN->isModified() || m_fieldLineEditISSN->isModified() || m_fieldLineEditCrossRef->isModified() || m_fieldLineEditHowPublished->isModified();
+ }
+
+ void EntryWidgetPublication::updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll )
+ {
+ bool enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftOrganization ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditOrganization->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftPublisher ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditPublisher->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftSchool ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditSchool->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftInstitution ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditInstitution->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftLocation ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditLocation->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftAddress ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditAddress->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftJournal ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditJournal->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftEdition ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditEdition->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftVolume ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditVolume->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftNumber ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditNumber->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftMonth ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditMonth->setEnabled( enableWidget );
+ m_pushButtonMonths->setEnabled( enableWidget && !m_isReadOnly );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftYear ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditYear->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftISBN ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditISBN->setEnabled( enableWidget );
+ int len = isbn().length();
+ m_pushButtonISBN->setEnabled( len == 10 || len == 13 );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftISSN ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditISSN->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftCrossRef ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditCrossRef->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftHowPublished ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditHowPublished->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftChapter ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditChapter->setEnabled( enableWidget );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftPages ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditPages->setEnabled( enableWidget );
+ }
+
+ void EntryWidgetPublication::apply( BibTeX::Entry *entry )
+ {
+ BibTeX::Value * value = m_fieldLineEditHowPublished->value();
+ setValue( entry, BibTeX::EntryField::ftHowPublished, value );
+ delete value;
+
+ value = m_fieldLineEditPublisher->value();
+ setValue( entry, BibTeX::EntryField::ftPublisher, value );
+ delete value;
+
+ value = m_fieldLineEditOrganization->value();
+ setValue( entry, BibTeX::EntryField::ftOrganization, value );
+ delete value;
+
+ value = m_fieldLineEditInstitution->value();
+ setValue( entry, BibTeX::EntryField::ftInstitution, value );
+ delete value;
+
+ value = m_fieldLineEditSchool->value();
+ setValue( entry, BibTeX::EntryField::ftSchool, value );
+ delete value;
+
+ value = m_fieldLineEditLocation->value();
+ setValue( entry, BibTeX::EntryField::ftLocation, value );
+ delete value;
+
+ value = m_fieldLineEditAddress->value();
+ setValue( entry, BibTeX::EntryField::ftAddress, value );
+ delete value;
+
+ value = m_fieldLineEditJournal->value();
+ setValue( entry, BibTeX::EntryField::ftJournal, value );
+ delete value;
+
+ value = m_fieldLineEditPages->value();
+ if ( value != NULL && value->items.first() != NULL )
+ {
+ BibTeX::PlainText *plainText = dynamic_cast<BibTeX::PlainText*>( value->items.first() );
+ if ( plainText != NULL )
+ plainText->setText( plainText->text().replace( QRegExp( "\\s*--?\\s*" ), QChar( 0x2013 ) ) );
+ }
+ setValue( entry, BibTeX::EntryField::ftPages, value );
+ delete value;
+
+ value = m_fieldLineEditEdition->value();
+ setValue( entry, BibTeX::EntryField::ftEdition, value );
+ delete value;
+
+ value = m_fieldLineEditChapter->value();
+ setValue( entry, BibTeX::EntryField::ftChapter, value );
+ delete value;
+
+ value = m_fieldLineEditVolume->value();
+ setValue( entry, BibTeX::EntryField::ftVolume, value );
+ delete value;
+
+ value = m_fieldLineEditNumber->value();
+ setValue( entry, BibTeX::EntryField::ftNumber, value );
+ delete value;
+
+ value = m_fieldLineEditMonth->value();
+ setValue( entry, BibTeX::EntryField::ftMonth, value );
+ delete value;
+
+ value = m_fieldLineEditYear->value();
+ setValue( entry, BibTeX::EntryField::ftYear, value );
+ delete value;
+
+ value = m_fieldLineEditISBN->value();
+ setValue( entry, BibTeX::EntryField::ftISBN, value );
+ delete value;
+
+ value = m_fieldLineEditISSN->value();
+ setValue( entry, BibTeX::EntryField::ftISSN, value );
+ delete value;
+
+ value = m_fieldLineEditCrossRef->value();
+ setValue( entry, BibTeX::EntryField::ftCrossRef, value );
+ delete value;
+ }
+
+ void EntryWidgetPublication::reset( BibTeX::Entry *entry )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftHowPublished );
+ m_fieldLineEditHowPublished->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftPublisher );
+ m_fieldLineEditPublisher->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftOrganization );
+ m_fieldLineEditOrganization->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftInstitution );
+ m_fieldLineEditInstitution->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftSchool );
+ m_fieldLineEditSchool->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftLocation );
+ m_fieldLineEditLocation->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftAddress );
+ m_fieldLineEditAddress->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftJournal );
+ m_fieldLineEditJournal->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftPages );
+ m_fieldLineEditPages->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftEdition );
+ m_fieldLineEditEdition->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftChapter );
+ m_fieldLineEditChapter->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftVolume );
+ m_fieldLineEditVolume->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftNumber );
+ m_fieldLineEditNumber->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftMonth );
+ m_fieldLineEditMonth->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftYear );
+ m_fieldLineEditYear->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftISBN );
+ m_fieldLineEditISBN->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftISSN );
+ m_fieldLineEditISSN->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftCrossRef );
+ m_fieldLineEditCrossRef->setValue( field != NULL ? field->value() : NULL );
+ slotSetCrossRefEntry();
+ }
+
+ void EntryWidgetPublication::updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings )
+ {
+ bool crossRefValid = FALSE;
+ BibTeX::Value *value = NULL;
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftHowPublished, m_fieldLineEditHowPublished->caption(), !m_fieldLineEditHowPublished->isEmpty(), m_fieldLineEditHowPublished, listViewWarnings );
+
+ crossRefValid = m_crossRefEntry != NULL && m_crossRefEntry->getField( BibTeX::EntryField::ftPublisher ) != NULL;
+ addMissingWarning( entryType, BibTeX::EntryField::ftPublisher, m_fieldLineEditPublisher->caption(), !m_fieldLineEditPublisher->isEmpty() || crossRefValid, m_fieldLineEditPublisher, listViewWarnings );
+ if ( crossRefValid && m_fieldLineEditPublisher->isEmpty() )
+ addCrossRefInfo( m_fieldLineEditPublisher->caption(), m_fieldLineEditPublisher, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftOrganization, m_fieldLineEditOrganization->caption(), !m_fieldLineEditOrganization->isEmpty(), m_fieldLineEditOrganization, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftInstitution, m_fieldLineEditInstitution->caption(), !m_fieldLineEditInstitution->isEmpty(), m_fieldLineEditInstitution, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftSchool, m_fieldLineEditSchool->caption(), !m_fieldLineEditSchool->isEmpty(), m_fieldLineEditSchool, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftLocation, m_fieldLineEditLocation->caption(), !m_fieldLineEditLocation->isEmpty(), m_fieldLineEditLocation, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftAddress, m_fieldLineEditAddress->caption(), !m_fieldLineEditAddress->isEmpty(), m_fieldLineEditAddress, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftJournal, m_fieldLineEditJournal->caption(), !m_fieldLineEditJournal->isEmpty(), m_fieldLineEditJournal, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftEdition, m_fieldLineEditEdition->caption(), !m_fieldLineEditEdition->isEmpty(), m_fieldLineEditEdition, listViewWarnings );
+
+ crossRefValid = m_crossRefEntry != NULL && m_crossRefEntry->getField( BibTeX::EntryField::ftVolume ) != NULL;
+ addMissingWarning( entryType, BibTeX::EntryField::ftVolume, m_fieldLineEditVolume->caption(), !m_fieldLineEditVolume->isEmpty() || crossRefValid, m_fieldLineEditVolume, listViewWarnings );
+ if ( crossRefValid && m_fieldLineEditVolume->isEmpty() )
+ addCrossRefInfo( m_fieldLineEditVolume->caption(), m_fieldLineEditVolume, listViewWarnings );
+
+ crossRefValid = m_crossRefEntry != NULL && m_crossRefEntry->getField( BibTeX::EntryField::ftNumber ) != NULL;
+ addMissingWarning( entryType, BibTeX::EntryField::ftNumber, m_fieldLineEditNumber->caption(), !m_fieldLineEditNumber->isEmpty() || crossRefValid, m_fieldLineEditNumber, listViewWarnings );
+ if ( crossRefValid && m_fieldLineEditNumber->isEmpty() )
+ addCrossRefInfo( m_fieldLineEditNumber->caption(), m_fieldLineEditNumber, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftMonth, m_fieldLineEditMonth->caption(), !m_fieldLineEditMonth->isEmpty(), m_fieldLineEditMonth, listViewWarnings );
+
+ crossRefValid = m_crossRefEntry != NULL && m_crossRefEntry->getField( BibTeX::EntryField::ftYear ) != NULL;
+ addMissingWarning( entryType, BibTeX::EntryField::ftYear, m_fieldLineEditYear->caption(), !m_fieldLineEditYear->isEmpty() || crossRefValid, m_fieldLineEditYear, listViewWarnings );
+ if ( crossRefValid && m_fieldLineEditYear->isEmpty() )
+ addCrossRefInfo( m_fieldLineEditYear->caption(), m_fieldLineEditYear, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftISBN, m_fieldLineEditISBN->caption(), !m_fieldLineEditISBN->isEmpty(), m_fieldLineEditISBN, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftISSN, m_fieldLineEditISSN->caption(), !m_fieldLineEditISSN->isEmpty(), m_fieldLineEditISSN, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftCrossRef, m_fieldLineEditCrossRef->caption(), !m_fieldLineEditCrossRef->isEmpty(), m_fieldLineEditCrossRef, listViewWarnings );
+
+ if ( entryType == BibTeX::Entry::etInBook )
+ {
+ if ( m_fieldLineEditChapter->isEmpty() && m_fieldLineEditPages->isEmpty() )
+ new EntryWidgetWarningsItem( EntryWidgetWarningsItem::wlWarning, i18n( "The fields 'Chapter' or 'Pages' are required, but both are missing" ), m_fieldLineEditPages, listViewWarnings, "warning" );
+ }
+ else
+ {
+ addMissingWarning( entryType, BibTeX::EntryField::ftPages, m_fieldLineEditPages->caption(), !m_fieldLineEditPages->isEmpty(), m_fieldLineEditPages, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftChapter, m_fieldLineEditChapter->caption(), !m_fieldLineEditChapter->isEmpty(), m_fieldLineEditChapter, listViewWarnings );
+ }
+
+ value = m_fieldLineEditJournal->value();
+ if ( value != NULL && !value->items.isEmpty() )
+ {
+ BibTeX::MacroKey *key = dynamic_cast<BibTeX::MacroKey*>( value->items[0] );
+ if ( key != NULL )
+ {
+ QString jourText = key->text();
+ if ( !jourText.isEmpty() && !m_bibtexfile->containsKey( jourText ) )
+ new EntryWidgetWarningsItem( EntryWidgetWarningsItem::wlWarning, i18n( "The field 'Journal' refers to a not existing entry" ), m_fieldLineEditJournal, listViewWarnings, "warning" );
+ }
+ }
+
+ addFieldLineEditWarning( m_fieldLineEditHowPublished, m_fieldLineEditHowPublished->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditPublisher, m_fieldLineEditPublisher->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditOrganization, m_fieldLineEditOrganization->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditInstitution, m_fieldLineEditInstitution->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditSchool, m_fieldLineEditSchool->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditLocation, m_fieldLineEditLocation->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditAddress, m_fieldLineEditAddress->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditJournal, m_fieldLineEditJournal->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditPages, m_fieldLineEditPages->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditEdition, m_fieldLineEditEdition->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditChapter, m_fieldLineEditChapter->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditVolume, m_fieldLineEditVolume->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditNumber, m_fieldLineEditNumber->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditMonth, m_fieldLineEditMonth->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditYear, m_fieldLineEditYear->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditISBN, m_fieldLineEditISBN->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditISSN, m_fieldLineEditISSN->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditCrossRef, m_fieldLineEditCrossRef->caption(), listViewWarnings );
+
+ /** misusing this function to enable/disable ISBN button */
+ int len = isbn().length();
+ m_pushButtonISBN->setEnabled( len == 10 || len == 13 );
+ }
+
+ void EntryWidgetPublication::slotSetMonth( int month )
+ {
+ BibTeX::MacroKey *item = new BibTeX::MacroKey( BibTeX::MonthsTriple[ month ] );
+ BibTeX::Value * value = new BibTeX::Value();
+ value->items.append( item );
+ m_fieldLineEditMonth->setValue( value );
+ delete value;
+ }
+
+ void EntryWidgetPublication::slotSetCrossRefEntry()
+ {
+ m_crossRefEntry = NULL;
+ if ( m_fieldLineEditCrossRef->value() != NULL && m_bibtexfile != NULL )
+ {
+ QString crossRefText = m_fieldLineEditCrossRef->value() ->text();
+ if ( !crossRefText.isEmpty() )
+ m_crossRefEntry = dynamic_cast<BibTeX::Entry*>( m_bibtexfile->containsKey( crossRefText ) );
+ }
+ }
+
+ void EntryWidgetPublication::slotOpenISBN()
+ {
+ KURL url = KURL( QString( i18n( "http://en.wikipedia.org/w/index.php?title=Special:Booksources&isbn=%1" ) ).arg( isbn() ) );
+ Settings::openUrl( url, this );
+ }
+
+ /**
+ *
+ */
+ void EntryWidgetPublication::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 10, 5, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setColSpacing( 2, KDialog::spacingHint() * 4 );
+ gridLayout->setRowStretch( 9, 1 );
+
+ QLabel *label = new QLabel( QString( "%1:" ).arg( i18n( "Journal" ) ), this );
+ gridLayout->addWidget( label, 0, 0 );
+ m_fieldLineEditJournal = new KBibTeX::FieldLineEdit( i18n( "Journal" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditJournal" );
+ m_fieldLineEditJournal ->setFieldType( BibTeX::EntryField::ftJournal );
+ label->setBuddy( m_fieldLineEditJournal );
+ gridLayout->addWidget( m_fieldLineEditJournal, 0, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Volume" ) ), this );
+ gridLayout->addWidget( label, 1, 0 );
+ m_fieldLineEditVolume = new KBibTeX::FieldLineEdit( i18n( "Volume" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditVolume" );
+ m_fieldLineEditVolume->setFieldType( BibTeX::EntryField::ftVolume );
+ label->setBuddy( m_fieldLineEditVolume );
+ gridLayout->addWidget( m_fieldLineEditVolume, 1, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Number" ) ), this );
+ gridLayout->addWidget( label, 2, 0 );
+ m_fieldLineEditNumber = new KBibTeX::FieldLineEdit( i18n( "Number" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditNumber" );
+ m_fieldLineEditNumber ->setFieldType( BibTeX::EntryField::ftNumber );
+ label->setBuddy( m_fieldLineEditNumber );
+ gridLayout->addWidget( m_fieldLineEditNumber, 2, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Month" ) ), this );
+ gridLayout->addWidget( label, 3, 0 );
+ QHBoxLayout *innerLayout = new QHBoxLayout();
+ gridLayout->addLayout( innerLayout, 3, 1 );
+ m_pushButtonMonths = new QPushButton( this, "m_pushButtonMonths" );
+ m_pushButtonMonths->setIconSet( QIconSet( SmallIcon( "vcalendar" ) ) );
+ m_pushButtonMonths->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum );
+ m_pushButtonMonths->setEnabled( !m_isReadOnly );
+ innerLayout->addWidget( m_pushButtonMonths );
+ m_fieldLineEditMonth = new KBibTeX::FieldLineEdit( i18n( "Month" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditMonth" );
+ m_fieldLineEditMonth->setFieldType( BibTeX::EntryField::ftMonth );
+ label->setBuddy( m_fieldLineEditMonth );
+ innerLayout->addWidget( m_fieldLineEditMonth );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Year" ) ), this );
+ gridLayout->addWidget( label, 4, 0 );
+ m_fieldLineEditYear = new KBibTeX::FieldLineEdit( i18n( "Year" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditYear" );
+ m_fieldLineEditYear->setFieldType( BibTeX::EntryField::ftYear );
+ label->setBuddy( m_fieldLineEditYear );
+ gridLayout->addWidget( m_fieldLineEditYear, 4, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Pages" ) ), this );
+ gridLayout->addWidget( label, 5, 0 );
+ m_fieldLineEditPages = new KBibTeX::FieldLineEdit( i18n( "Pages" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditPages" );
+ m_fieldLineEditPages->setFieldType( BibTeX::EntryField::ftPages );
+ label->setBuddy( m_fieldLineEditPages );
+ gridLayout->addWidget( m_fieldLineEditPages, 5, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Edition" ) ), this );
+ gridLayout->addWidget( label, 6, 0 );
+ m_fieldLineEditEdition = new KBibTeX::FieldLineEdit( i18n( "Edition" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditEdition" );
+ m_fieldLineEditEdition->setFieldType( BibTeX::EntryField::ftEdition );
+ label->setBuddy( m_fieldLineEditEdition );
+ gridLayout->addWidget( m_fieldLineEditEdition, 6, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Chapter" ) ), this );
+ gridLayout->addWidget( label, 7, 0 );
+ m_fieldLineEditChapter = new KBibTeX::FieldLineEdit( i18n( "Chapter" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditChapter" );
+ m_fieldLineEditChapter ->setFieldType( BibTeX::EntryField::ftChapter );
+ label->setBuddy( m_fieldLineEditChapter );
+ gridLayout->addWidget( m_fieldLineEditChapter, 7, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Cross Reference" ) ), this );
+ gridLayout->addWidget( label, 8, 0 );
+ m_fieldLineEditCrossRef = new KBibTeX::FieldLineEdit( i18n( "Cross Reference" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditCrossRef" );
+ m_fieldLineEditCrossRef->setFieldType( BibTeX::EntryField::ftCrossRef );
+ label->setBuddy( m_fieldLineEditCrossRef );
+ gridLayout->addWidget( m_fieldLineEditCrossRef, 8, 1 );
+ connect( m_fieldLineEditCrossRef, SIGNAL( textChanged() ), this, SLOT( slotSetCrossRefEntry() ) );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Organization" ) ), this );
+ gridLayout->addWidget( label, 0, 3 );
+ m_fieldLineEditOrganization = new KBibTeX::FieldLineEdit( i18n( "Organization" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditOrganization" );
+ m_fieldLineEditOrganization->setFieldType( BibTeX::EntryField::ftOrganization );
+ label->setBuddy( m_fieldLineEditOrganization );
+ gridLayout->addWidget( m_fieldLineEditOrganization, 0, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Publisher" ) ), this );
+ gridLayout->addWidget( label, 1, 3 );
+ m_fieldLineEditPublisher = new KBibTeX::FieldLineEdit( i18n( "Publisher" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditPublisher" );
+ m_fieldLineEditPublisher->setFieldType( BibTeX::EntryField::ftPublisher );
+ label->setBuddy( m_fieldLineEditPublisher );
+ gridLayout->addWidget( m_fieldLineEditPublisher, 1, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "School" ) ), this );
+ gridLayout->addWidget( label, 2, 3 );
+ m_fieldLineEditSchool = new KBibTeX::FieldLineEdit( i18n( "School" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditSchool" );
+ m_fieldLineEditSchool->setFieldType( BibTeX::EntryField::ftSchool );
+ label->setBuddy( m_fieldLineEditSchool );
+ gridLayout->addWidget( m_fieldLineEditSchool, 2, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Institution" ) ), this );
+ gridLayout->addWidget( label, 3, 3 );
+ m_fieldLineEditInstitution = new KBibTeX::FieldLineEdit( i18n( "Institution" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditInstitution" );
+ m_fieldLineEditInstitution->setFieldType( BibTeX::EntryField::ftInstitution );
+ label->setBuddy( m_fieldLineEditInstitution );
+ gridLayout->addWidget( m_fieldLineEditInstitution, 3, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Location" ) ), this );
+ gridLayout->addWidget( label, 4, 3 );
+ m_fieldLineEditLocation = new KBibTeX::FieldLineEdit( i18n( "Location" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditLocation" );
+ m_fieldLineEditLocation->setFieldType( BibTeX::EntryField::ftLocation );
+ label->setBuddy( m_fieldLineEditLocation );
+ gridLayout->addWidget( m_fieldLineEditLocation, 4, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Address" ) ), this );
+ gridLayout->addWidget( label, 5, 3 );
+ m_fieldLineEditAddress = new KBibTeX::FieldLineEdit( i18n( "Address" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditAddress" );
+ m_fieldLineEditAddress->setFieldType( BibTeX::EntryField::ftAddress );
+ label->setBuddy( m_fieldLineEditAddress );
+ gridLayout->addWidget( m_fieldLineEditAddress, 5, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "ISBN" ) ), this );
+ gridLayout->addWidget( label, 6, 3 );
+ innerLayout = new QHBoxLayout();
+ gridLayout->addLayout( innerLayout, 6, 4 );
+ m_pushButtonISBN = new QPushButton( this, "m_pushButtonMonths" );
+ m_pushButtonISBN->setIconSet( QIconSet( SmallIcon( "find" ) ) );
+ m_pushButtonISBN->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum );
+ QToolTip::add( m_pushButtonISBN, i18n( "Lookup ISBN number in Wikipedia" ) );
+ innerLayout->addWidget( m_pushButtonISBN );
+ m_fieldLineEditISBN = new KBibTeX::FieldLineEdit( i18n( "ISBN" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditISBN" );
+ m_fieldLineEditISBN ->setFieldType( BibTeX::EntryField::ftISBN );
+ label->setBuddy( m_fieldLineEditISBN );
+ innerLayout->addWidget( m_fieldLineEditISBN );
+ connect( m_pushButtonISBN, SIGNAL( clicked() ), this, SLOT( slotOpenISBN() ) );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "ISSN" ) ), this );
+ gridLayout->addWidget( label, 7, 3 );
+ m_fieldLineEditISSN = new KBibTeX::FieldLineEdit( i18n( "ISSN" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditISSN" );
+ m_fieldLineEditISSN->setFieldType( BibTeX::EntryField::ftISSN );
+ label->setBuddy( m_fieldLineEditISSN );
+ gridLayout->addWidget( m_fieldLineEditISSN, 7, 4 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "How Published" ) ), this );
+ gridLayout->addWidget( label, 8, 3 );
+ m_fieldLineEditHowPublished = new KBibTeX::FieldLineEdit( i18n( "How Published" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditHowPublished" );
+ m_fieldLineEditHowPublished->setFieldType( BibTeX::EntryField::ftHowPublished );
+ label->setBuddy( m_fieldLineEditHowPublished );
+ gridLayout->addWidget( m_fieldLineEditHowPublished, 8, 4 );
+
+ QPopupMenu *menuMonths = new QPopupMenu( this, "menuMonths" );
+ for ( int i = 0; i < 12; i++ )
+ menuMonths->insertItem( BibTeX::Months[ i ], i );
+ m_pushButtonMonths->setPopup( menuMonths );
+ connect( menuMonths, SIGNAL( activated( int ) ), this, SLOT( slotSetMonth( int ) ) );
+ }
+
+ QString EntryWidgetPublication::isbn() const
+ {
+ BibTeX::Value *value = m_fieldLineEditISBN->value();
+ if ( value == NULL )
+ return "";
+
+ return value->text().replace( QRegExp( "[^0-9X]" ), "" );
+ }
+}
+#include "entrywidgetpublication.moc"
diff --git a/src/entrywidgetpublication.h b/src/entrywidgetpublication.h
new file mode 100644
index 0000000..e0e21ca
--- /dev/null
+++ b/src/entrywidgetpublication.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETPUBLICATION_H
+#define KBIBTEXENTRYWIDGETPUBLICATION_H
+
+#include <entrywidgettab.h>
+
+class QPushButton;
+
+namespace KBibTeX
+{
+ class FieldLineEdit;
+
+ class EntryWidgetPublication : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetPublication( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetPublication();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private slots:
+ void slotSetMonth( int month );
+ void slotSetCrossRefEntry();
+ void slotOpenISBN();
+
+ private:
+ KBibTeX::FieldLineEdit *m_fieldLineEditOrganization;
+ KBibTeX::FieldLineEdit *m_fieldLineEditPublisher;
+ KBibTeX::FieldLineEdit *m_fieldLineEditSchool;
+ KBibTeX::FieldLineEdit *m_fieldLineEditInstitution;
+ KBibTeX::FieldLineEdit *m_fieldLineEditLocation;
+ KBibTeX::FieldLineEdit *m_fieldLineEditAddress;
+ KBibTeX::FieldLineEdit *m_fieldLineEditJournal;
+ KBibTeX::FieldLineEdit *m_fieldLineEditPages;
+ KBibTeX::FieldLineEdit *m_fieldLineEditEdition;
+ KBibTeX::FieldLineEdit *m_fieldLineEditChapter;
+ KBibTeX::FieldLineEdit *m_fieldLineEditVolume;
+ KBibTeX::FieldLineEdit *m_fieldLineEditNumber;
+ KBibTeX::FieldLineEdit *m_fieldLineEditMonth;
+ QPushButton *m_pushButtonMonths;
+ KBibTeX::FieldLineEdit *m_fieldLineEditYear;
+ KBibTeX::FieldLineEdit *m_fieldLineEditISBN;
+ QPushButton *m_pushButtonISBN;
+ KBibTeX::FieldLineEdit *m_fieldLineEditISSN;
+ KBibTeX::FieldLineEdit *m_fieldLineEditCrossRef;
+ KBibTeX::FieldLineEdit *m_fieldLineEditHowPublished;
+
+ void setupGUI();
+ QString isbn() const;
+
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetsource.cpp b/src/entrywidgetsource.cpp
new file mode 100644
index 0000000..27d95a6
--- /dev/null
+++ b/src/entrywidgetsource.cpp
@@ -0,0 +1,161 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qtextedit.h>
+#include <qbuffer.h>
+
+#include <kdialog.h>
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+
+#include <fileexporterbibtex.h>
+#include <fileimporterbibtex.h>
+#include <entry.h>
+#include <settings.h>
+#include "entrywidgetsource.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetSource::EntryWidgetSource( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : EntryWidgetTab( bibtexfile, isReadOnly, parent, name ), m_entry( NULL )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetSource::~EntryWidgetSource()
+ {
+ if ( m_entry != NULL ) delete m_entry;
+ }
+
+ bool EntryWidgetSource::isModified()
+ {
+ return m_textEditSource->isModified();
+ }
+
+ bool EntryWidgetSource::containsValidText()
+ {
+ BibTeX::Entry dummy( BibTeX::Entry::etArticle, "iaKWjDMVuB2vQDuYRK49Y85tyxa9" );
+ apply( &dummy );
+ return dummy.id().compare( "iaKWjDMVuB2vQDuYRK49Y85tyxa9" ) != 0;
+ }
+
+ QString EntryWidgetSource::text()
+ {
+ return m_textEditSource->text();
+ }
+
+ void EntryWidgetSource::setText( const QString& text )
+ {
+ m_textEditSource->setText( text );
+ }
+
+ void EntryWidgetSource::updateGUI( BibTeX::Entry::EntryType /*entryType*/, bool /*enableAll*/ )
+ {
+ // nothing
+ }
+
+ void EntryWidgetSource::apply( BibTeX::Entry *entry )
+ {
+ Settings * settings = Settings::self();
+ QBuffer buffer;
+ BibTeX::FileImporterBibTeX importer( settings->editing_FirstNameFirst );
+
+ buffer.open( IO_WriteOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << m_textEditSource->text() << endl;
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ BibTeX::File *bibtexFile = importer.load( &buffer );
+ buffer.close();
+
+ if ( bibtexFile != NULL )
+ {
+ if ( bibtexFile->count() == 1 )
+ {
+ BibTeX::Entry * parsedEntry = dynamic_cast<BibTeX::Entry*>( bibtexFile->at( 0 ) );
+ if ( parsedEntry != NULL )
+ {
+ entry->copyFrom( parsedEntry );
+ settings->addToCompletion( parsedEntry );
+ }
+ }
+ delete bibtexFile;
+ }
+ }
+
+ void EntryWidgetSource::reset( BibTeX::Entry *entry )
+ {
+ if ( m_entry != entry )
+ {
+ if ( m_entry != NULL ) m_entry->copyFrom( entry ); else m_entry = new BibTeX::Entry( entry );
+ }
+
+ Settings * settings = Settings::self();
+
+ QBuffer buffer;
+ BibTeX::FileExporterBibTeX exporter;
+ exporter.setEncoding( "latex" );
+ exporter.setStringDelimiter( settings->fileIO_BibtexStringOpenDelimiter, settings->fileIO_BibtexStringCloseDelimiter );
+ exporter.setKeywordCasing( settings->fileIO_KeywordCasing );
+ exporter.setEnclosingCurlyBrackets( settings->fileIO_EnclosingCurlyBrackets );
+
+ buffer.open( IO_WriteOnly );
+ exporter.save( &buffer, entry );
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ m_textEditSource->setText( ts.read() );
+ buffer.close();
+ }
+
+ void EntryWidgetSource::restore()
+ {
+ reset( m_entry );
+ }
+
+ void EntryWidgetSource::updateWarnings( BibTeX::Entry::EntryType /*entryType*/, QListView * /*listViewWarnings*/ )
+ {
+ // nothing
+ }
+
+ void EntryWidgetSource::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 2, 2, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( 0, 5 );
+ gridLayout->setColStretch( 0, 5 );
+
+ m_textEditSource = new QTextEdit( this );
+ gridLayout->addMultiCellWidget( m_textEditSource, 0, 0, 0, 1 );
+ m_textEditSource->setFont( KGlobalSettings::fixedFont() );
+ m_textEditSource->setReadOnly( m_isReadOnly );
+
+ KPushButton *btnReset = new KPushButton( i18n( "Restore" ), this );
+ gridLayout->addWidget( btnReset, 1, 1 );
+ connect( btnReset, SIGNAL( clicked() ), this, SLOT( restore() ) );
+ }
+
+}
+#include "entrywidgetsource.moc"
diff --git a/src/entrywidgetsource.h b/src/entrywidgetsource.h
new file mode 100644
index 0000000..77b98e2
--- /dev/null
+++ b/src/entrywidgetsource.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETSOURCE_H
+#define KBIBTEXENTRYWIDGETSOURCE_H
+
+#include <entrywidgettab.h>
+
+class QTextEdit;
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class EntryWidgetSource : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetSource( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetSource();
+
+ bool isModified();
+ bool containsValidText();
+ QString text();
+ void setText( const QString& text );
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void restore();
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private:
+ QTextEdit *m_textEditSource;
+ BibTeX::Entry *m_entry;
+
+ void setupGUI();
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgettab.cpp b/src/entrywidgettab.cpp
new file mode 100644
index 0000000..c4efc51
--- /dev/null
+++ b/src/entrywidgettab.cpp
@@ -0,0 +1,91 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <klocale.h>
+
+#include <entry.h>
+#include <entrywidgetwarningsitem.h>
+#include <fieldlineedit.h>
+#include "entrywidgettab.h"
+
+namespace KBibTeX
+{
+ BibTeX::Entry *EntryWidgetTab::m_crossRefEntry = NULL;
+
+ EntryWidgetTab::EntryWidgetTab(BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_isReadOnly( isReadOnly ), m_bibtexfile( bibtexfile )
+ {
+ // nothing
+ }
+
+ EntryWidgetTab::~EntryWidgetTab()
+ {
+ // nothing
+ }
+
+ void EntryWidgetTab::setValue( BibTeX::Entry *entry, const BibTeX::EntryField::FieldType fieldType, BibTeX::Value *value )
+ {
+ BibTeX::EntryField * field = entry->getField( fieldType );
+
+ if ( value != NULL )
+ {
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( fieldType );
+ entry->addField( field );
+ }
+ field->setValue( value );
+ }
+ else
+ {
+ if ( field != NULL )
+ entry->deleteField( fieldType );
+ }
+ }
+
+ void EntryWidgetTab::addMissingWarning( BibTeX::Entry::EntryType entryType, BibTeX::EntryField::FieldType fieldType, const QString& label, bool valid, QWidget *widget, QListView *listView )
+ {
+ if ( BibTeX::Entry::getRequireStatus( entryType, fieldType ) == BibTeX::Entry::frsRequired && !valid )
+ new EntryWidgetWarningsItem( EntryWidgetWarningsItem::wlWarning, QString( i18n( "The field '%1' is required, but missing" ) ).arg( label ), widget, listView, "warning" );
+ }
+
+ void EntryWidgetTab::addCrossRefInfo( const QString& label, QWidget *widget, QListView *listView )
+ {
+ QString crossRefId = m_crossRefEntry != NULL ? m_crossRefEntry->id() : "???";
+ new EntryWidgetWarningsItem( EntryWidgetWarningsItem::wlInformation, QString( i18n( "Using cross referenced entry '%1' for field '%2'" ) ).arg( crossRefId ).arg( label ), widget, listView, "information" );
+ }
+
+ void EntryWidgetTab::addFieldLineEditWarning( FieldLineEdit *fieldLineEdit, const QString& label, QListView *listView )
+ {
+ switch ( fieldLineEdit->error() )
+ {
+ case FieldLineEdit::etInvalidStringKey:
+ new EntryWidgetWarningsItem( EntryWidgetWarningsItem::wlError, QString( i18n( "The field '%1' contains string keys with invalid characters" ) ).arg( label ), fieldLineEdit, listView, "error" );
+ break;
+ case FieldLineEdit::etNoError:
+ {
+ // nothing
+ }
+ break;
+ default:
+ new EntryWidgetWarningsItem( EntryWidgetWarningsItem::wlError, QString( i18n( "The field '%1' contains some unknown error" ) ).arg( label ), fieldLineEdit, listView, "error" );
+ }
+ }
+}
+#include "entrywidgettab.moc"
diff --git a/src/entrywidgettab.h b/src/entrywidgettab.h
new file mode 100644
index 0000000..8e63252
--- /dev/null
+++ b/src/entrywidgettab.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETTAB_H
+#define KBIBTEXENTRYWIDGETTAB_H
+
+#include <qwidget.h>
+
+#include <entry.h>
+#include <file.h>
+
+class QListView;
+
+namespace KBibTeX
+{
+ class FieldLineEdit;
+
+ class EntryWidgetTab : public QWidget
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetTab( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetTab();
+
+ virtual bool isModified() = 0;
+
+ public slots:
+ virtual void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll ) = 0;
+ virtual void apply( BibTeX::Entry *entry ) = 0;
+ virtual void reset( BibTeX::Entry *entry ) = 0;
+ virtual void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings ) = 0;
+
+ protected:
+ void setValue( BibTeX::Entry *entry, const BibTeX::EntryField::FieldType fieldType, BibTeX::Value *value );
+ void addMissingWarning( BibTeX::Entry::EntryType entryType, BibTeX::EntryField::FieldType fieldType, const QString& label, bool valid, QWidget *widget, QListView *listView );
+ void addCrossRefInfo( const QString& label, QWidget *widget, QListView *listView );
+ void addFieldLineEditWarning( FieldLineEdit *fieldLineEdit, const QString& label, QListView *listView );
+
+ bool m_isReadOnly;
+ static BibTeX::Entry *m_crossRefEntry;
+ BibTeX::File *m_bibtexfile;
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgettitle.cpp b/src/entrywidgettitle.cpp
new file mode 100644
index 0000000..f72bb71
--- /dev/null
+++ b/src/entrywidgettitle.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+#include <kdialog.h>
+#include <klocale.h>
+
+#include <fieldlineedit.h>
+#include <value.h>
+#include <entryfield.h>
+#include "entrywidgettitle.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetTitle::EntryWidgetTitle( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name )
+ : EntryWidgetTab( bibtexfile, isReadOnly, parent, name )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetTitle::~EntryWidgetTitle()
+ {
+ // nothing
+ }
+
+ bool EntryWidgetTitle::isModified()
+ {
+ return m_fieldLineEditTitle->isModified() || m_fieldLineEditBookTitle->isModified() || m_fieldLineEditSeries->isModified();
+ }
+
+ void EntryWidgetTitle::updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll )
+ {
+ bool enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftTitle ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditTitle->setEnabled( enableWidget );
+ m_fieldLineEditTitle->setFieldType( BibTeX::EntryField::ftTitle );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftBookTitle ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditBookTitle->setEnabled( enableWidget );
+ m_fieldLineEditBookTitle->setFieldType( BibTeX::EntryField::ftBookTitle );
+
+ enableWidget = enableAll || BibTeX::Entry::getRequireStatus( entryType, BibTeX::EntryField::ftSeries ) != BibTeX::Entry::frsIgnored;
+ m_fieldLineEditSeries->setEnabled( enableWidget );
+ m_fieldLineEditSeries->setFieldType( BibTeX::EntryField::ftSeries );
+ }
+
+ void EntryWidgetTitle::apply(BibTeX::Entry *entry )
+ {
+ BibTeX::Value * value = m_fieldLineEditTitle->value();
+ setValue( entry, BibTeX::EntryField::ftTitle, value );
+ delete value;
+
+ value = m_fieldLineEditBookTitle->value();
+ setValue( entry, BibTeX::EntryField::ftBookTitle, value );
+ delete value;
+
+ value = m_fieldLineEditSeries->value();
+ setValue( entry, BibTeX::EntryField::ftSeries, value );
+ delete value;
+ }
+
+ void EntryWidgetTitle::reset(BibTeX::Entry *entry )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftTitle );
+ m_fieldLineEditTitle->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftBookTitle );
+ m_fieldLineEditBookTitle->setValue( field != NULL ? field->value() : NULL );
+
+ field = entry->getField( BibTeX::EntryField::ftSeries );
+ m_fieldLineEditSeries->setValue( field != NULL ? field->value() : NULL );
+ }
+
+ void EntryWidgetTitle::updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings )
+ {
+ bool crossRefValid = FALSE;
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftTitle, m_fieldLineEditTitle->caption(), !m_fieldLineEditTitle->isEmpty(), m_fieldLineEditTitle, listViewWarnings );
+
+ crossRefValid = m_crossRefEntry != NULL && m_crossRefEntry->getField( BibTeX::EntryField::ftTitle ) != NULL;
+ addMissingWarning( entryType, BibTeX::EntryField::ftBookTitle, m_fieldLineEditBookTitle->caption(), !m_fieldLineEditBookTitle->isEmpty() || crossRefValid, m_fieldLineEditBookTitle, listViewWarnings );
+ if ( crossRefValid && m_fieldLineEditBookTitle->isEmpty() )
+ addCrossRefInfo( m_fieldLineEditBookTitle->caption(), m_fieldLineEditBookTitle, listViewWarnings );
+
+ addMissingWarning( entryType, BibTeX::EntryField::ftSeries, m_fieldLineEditSeries->caption(), !m_fieldLineEditSeries->isEmpty(), m_fieldLineEditSeries, listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditTitle, m_fieldLineEditTitle->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditBookTitle, m_fieldLineEditBookTitle->caption(), listViewWarnings );
+
+ addFieldLineEditWarning( m_fieldLineEditSeries, m_fieldLineEditSeries->caption(), listViewWarnings );
+ }
+
+ void EntryWidgetTitle::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 4, 2, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( 3, 1 );
+
+ QLabel *label = new QLabel( QString( "%1:" ).arg( i18n( "Title" ) ), this );
+ gridLayout->addWidget( label, 0, 0 );
+ m_fieldLineEditTitle = new KBibTeX::FieldLineEdit( i18n( "Title" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditTitle" );
+ label->setBuddy( m_fieldLineEditTitle );
+ gridLayout->addWidget( m_fieldLineEditTitle, 0, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Book Title" ) ), this );
+ gridLayout->addWidget( label, 1, 0 );
+ m_fieldLineEditBookTitle = new KBibTeX::FieldLineEdit( i18n( "Book Title" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditBookTitle" );
+ label->setBuddy( m_fieldLineEditBookTitle );
+ gridLayout->addWidget( m_fieldLineEditBookTitle, 1, 1 );
+
+ label = new QLabel( QString( "%1:" ).arg( i18n( "Series" ) ), this );
+ gridLayout->addWidget( label, 2, 0 );
+ m_fieldLineEditSeries = new KBibTeX::FieldLineEdit( i18n( "Series" ), KBibTeX::FieldLineEdit::itSingleLine, m_isReadOnly, this, "m_fieldLineEditSeries" );
+ label->setBuddy( m_fieldLineEditSeries );
+ gridLayout->addWidget( m_fieldLineEditSeries, 2, 1 );
+ }
+
+}
+#include "entrywidgettitle.moc"
diff --git a/src/entrywidgettitle.h b/src/entrywidgettitle.h
new file mode 100644
index 0000000..c43bb57
--- /dev/null
+++ b/src/entrywidgettitle.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETTITLE_H
+#define KBIBTEXENTRYWIDGETTITLE_H
+
+#include <entrywidgettab.h>
+
+namespace KBibTeX
+{
+ class FieldLineEdit;
+
+ class EntryWidgetTitle : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetTitle( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetTitle();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply( BibTeX::Entry *entry );
+ void reset( BibTeX::Entry *entry );
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private:
+ friend class EntryWidget;
+ KBibTeX::FieldLineEdit *m_fieldLineEditTitle;
+ KBibTeX::FieldLineEdit *m_fieldLineEditBookTitle;
+ KBibTeX::FieldLineEdit *m_fieldLineEditSeries;
+
+ void setupGUI();
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetuserdefined.cpp b/src/entrywidgetuserdefined.cpp
new file mode 100644
index 0000000..6479f73
--- /dev/null
+++ b/src/entrywidgetuserdefined.cpp
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <kdebug.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include <settings.h>
+#include "entrywidgetuserdefined.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetUserDefined::EntryWidgetUserDefined( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent, const char *name ) : EntryWidgetTab( bibtexfile, isReadOnly, parent, name )
+ {
+ setupGUI();
+ }
+
+ EntryWidgetUserDefined::~EntryWidgetUserDefined()
+ {
+ // nothing
+ }
+
+ bool EntryWidgetUserDefined::isModified()
+ {
+ bool result = FALSE;
+ for ( QValueList<FieldLineEdit*>::iterator it = m_widgets.begin(); !FALSE && it != m_widgets.end(); ++it )
+ result |= ( *it )->isModified();
+ return result;
+ }
+
+ void EntryWidgetUserDefined::updateGUI( BibTeX::Entry::EntryType /*entryType*/, bool /*enableAll*/ )
+ {
+// nothing
+ }
+
+ void EntryWidgetUserDefined::apply( BibTeX::Entry *entry )
+ {
+ Settings * settings = Settings::self();
+ for ( unsigned int i = 0; i < settings->userDefinedInputFields.count(); ++i )
+ {
+ FieldLineEdit *widget = m_widgets[i];
+ Settings::UserDefinedInputFields *udif = settings->userDefinedInputFields[i];
+
+ BibTeX::Value * value = widget->value();
+ if ( value == NULL )
+ entry->deleteField( udif->name );
+ else
+ {
+ if ( value->text().isEmpty() )
+ entry->deleteField( udif->name );
+ else
+ {
+ BibTeX::EntryField * field = entry->getField( udif->name );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( udif->name );
+ entry->addField( field );
+ }
+ field->setValue( value );
+ }
+ delete value;
+ }
+ }
+ }
+
+ void EntryWidgetUserDefined::reset( BibTeX::Entry *entry )
+ {
+ Settings * settings = Settings::self();
+ for ( unsigned int i = 0; i < settings->userDefinedInputFields.count(); ++i )
+ {
+ FieldLineEdit *widget = m_widgets[i];
+ Settings::UserDefinedInputFields *udif = settings->userDefinedInputFields[i];
+
+ BibTeX::EntryField * field = entry->getField( udif->name );
+ widget->setValue( field != NULL ? field->value() : NULL );
+ }
+ }
+
+ void EntryWidgetUserDefined::updateWarnings( BibTeX::Entry::EntryType /*entryType*/, QListView */*listViewWarnings*/ )
+ {
+// nothing
+ }
+
+ void EntryWidgetUserDefined::setupGUI()
+ {
+ Settings * settings = Settings::self();
+ int rows = settings->userDefinedInputFields.count() + 1;
+ if ( rows < 2 ) rows = 2;
+ QGridLayout *gridLayout = new QGridLayout( this, rows, 2, KDialog::marginHint(), KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( rows - 1, 1 );
+
+ if ( settings->userDefinedInputFields.count() > 0 )
+ for ( unsigned int i = 0; i < settings->userDefinedInputFields.count(); ++i )
+ {
+ QLabel *label = new QLabel( settings->userDefinedInputFields[i]->label, this );
+ gridLayout->addWidget( label, i, 0 );
+ if ( settings->userDefinedInputFields[i]->inputType == FieldLineEdit::itMultiLine )
+ label->setAlignment( Qt::AlignTop );
+
+ FieldLineEdit *widget = new FieldLineEdit( settings->userDefinedInputFields[i]->label, settings->userDefinedInputFields[i]->inputType, m_isReadOnly, this );
+ gridLayout->addWidget( widget, i, 1 );
+
+ label->setBuddy( widget );
+ m_widgets << widget;
+ }
+ else
+ {
+ gridLayout->setColStretch( 0, 0 );
+ gridLayout->setColStretch( 1, 1 );
+
+ QLabel *label = new QLabel( this );
+ gridLayout->addWidget( label, 0, 0 );
+ label->setPixmap( BarIcon( "messagebox_info" ) );
+ label->setAlignment( Qt::AlignVCenter | Qt::AlignLeft | Qt::WordBreak );
+
+ label = new QLabel( i18n( "Please use the settings dialog to add user-defined fields here." ), this );
+ label->setAlignment( Qt::AlignVCenter | Qt::AlignLeft | Qt::WordBreak );
+ gridLayout->addWidget( label, 0, 1 );
+ }
+ }
+
+}
+#include "entrywidgetuserdefined.moc"
diff --git a/src/entrywidgetuserdefined.h b/src/entrywidgetuserdefined.h
new file mode 100644
index 0000000..bc5e238
--- /dev/null
+++ b/src/entrywidgetuserdefined.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETUSERDEFINED_H
+#define KBIBTEXENTRYWIDGETUSERDEFINED_H
+
+#include <entrywidgettab.h>
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class EntryWidgetUserDefined : public EntryWidgetTab
+ {
+ Q_OBJECT
+ public:
+ EntryWidgetUserDefined( BibTeX::File *bibtexfile, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~EntryWidgetUserDefined();
+
+ bool isModified();
+
+ public slots:
+ void updateGUI( BibTeX::Entry::EntryType entryType, bool enableAll );
+ void apply(BibTeX::Entry *entry);
+ void reset(BibTeX::Entry *entry);
+ void updateWarnings( BibTeX::Entry::EntryType entryType, QListView *listViewWarnings );
+
+ private:
+ QValueList<FieldLineEdit*> m_widgets;
+ void setupGUI();
+
+ };
+
+}
+
+#endif
diff --git a/src/entrywidgetwarningsitem.cpp b/src/entrywidgetwarningsitem.cpp
new file mode 100644
index 0000000..741d1a0
--- /dev/null
+++ b/src/entrywidgetwarningsitem.cpp
@@ -0,0 +1,62 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include "entrywidgetwarningsitem.h"
+
+namespace KBibTeX
+{
+
+ EntryWidgetWarningsItem::EntryWidgetWarningsItem( WarningLevel level, const QString &message, QWidget *widget, QListView *parent, const char* name )
+ : QListViewItem( parent, name ), m_widget( widget )
+ {
+ KIconLoader * loader = KGlobal::instance() ->iconLoader();
+ switch ( level )
+ {
+ case wlInformation:
+ setPixmap( 0, loader->loadIcon( "messagebox_info", KIcon::NoGroup, KIcon::SizeSmall ) );
+ break;
+ case wlWarning:
+ setPixmap( 0, loader->loadIcon( "messagebox_warning", KIcon::NoGroup, KIcon::SizeSmall ) );
+ break;
+ case wlError:
+ setPixmap( 0, loader->loadIcon( "messagebox_critical", KIcon::NoGroup, KIcon::SizeSmall ) );
+ break;
+ default:
+ {
+ // nothing
+ }
+ }
+ setText( 0, message );
+ }
+
+
+ EntryWidgetWarningsItem::~EntryWidgetWarningsItem()
+ {
+ // nothing
+ }
+
+ QWidget *EntryWidgetWarningsItem::widget()
+ {
+ return m_widget;
+ }
+
+}
diff --git a/src/entrywidgetwarningsitem.h b/src/entrywidgetwarningsitem.h
new file mode 100644
index 0000000..2aa2044
--- /dev/null
+++ b/src/entrywidgetwarningsitem.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXENTRYWIDGETWARNINGSITEM_H
+#define KBIBTEXENTRYWIDGETWARNINGSITEM_H
+
+#include <qlistview.h>
+
+class QString;
+
+namespace KBibTeX
+{
+
+ class EntryWidgetWarningsItem : public QListViewItem
+ {
+ public:
+ enum WarningLevel {wlInformation = 1, wlWarning = 2, wlError = 3};
+
+ EntryWidgetWarningsItem( WarningLevel level, const QString &message, QWidget *widget, QListView *parent, const char* name = NULL );
+ ~EntryWidgetWarningsItem();
+
+ QWidget *widget();
+
+ private:
+ QWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/fieldlineedit.cpp b/src/fieldlineedit.cpp
new file mode 100644
index 0000000..ba36fe7
--- /dev/null
+++ b/src/fieldlineedit.cpp
@@ -0,0 +1,369 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qtextedit.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+
+#include <element.h>
+#include <entry.h>
+#include <settings.h>
+#include <value.h>
+#include <valuewidget.h>
+#include "fieldlineedit.h"
+
+namespace KBibTeX
+{
+ FieldLineEdit::FieldLineEdit( const QString& caption, InputType inputType, bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_value( new BibTeX::Value() ), m_caption( caption ), m_lineEdit( NULL ), m_textEdit( NULL ), m_isReadOnly( isReadOnly ), m_enabled( TRUE ), m_inputType( inputType ), m_isModified( FALSE ), m_fieldType( BibTeX::EntryField::ftUnknown ), m_completion( NULL )
+ {
+ setupGUI( name );
+ }
+
+
+ FieldLineEdit::~FieldLineEdit()
+ {
+ delete m_value;
+ }
+
+ void FieldLineEdit::setValue( const BibTeX::Value *value )
+ {
+ delete m_value;
+
+ if ( value != NULL )
+ m_value = new BibTeX::Value( value );
+ else
+ m_value = new BibTeX::Value();
+
+ updateGUI();
+ m_isModified = FALSE;
+ }
+
+ BibTeX::Value *FieldLineEdit::value()
+ {
+ if ( m_value->items.isEmpty() )
+ return NULL;
+ else
+ return new BibTeX::Value( m_value );
+ }
+
+ void FieldLineEdit::setEnabled( bool enabled )
+ {
+ m_enabled = enabled;
+ updateGUI();
+ }
+
+ void FieldLineEdit::setFieldType( BibTeX::EntryField::FieldType fieldType )
+ {
+ m_fieldType = fieldType;
+ Settings * settings = Settings::self();
+ m_completion = settings->completion( m_fieldType );
+
+ if ( m_lineEdit != NULL )
+ {
+ if ( !m_pushButtonString->isOn() )
+ m_lineEdit->setCompletionObject( m_completion );
+ else
+ m_lineEdit->setCompletionObject( settings->completionMacro );
+ QToolTip::add( m_lineEdit, QString( i18n( "BibTeX field '%1'" ) ).arg( BibTeX::EntryField::fieldTypeToString( fieldType ) ) );
+ QWhatsThis::add( m_lineEdit, QString( i18n( "BibTeX field '%1'" ) ).arg( BibTeX::EntryField::fieldTypeToString( fieldType ) ) );
+ }
+ else if ( m_textEdit != NULL )
+ {
+ QToolTip::add( m_textEdit, QString( i18n( "BibTeX field '%1'" ) ).arg( BibTeX::EntryField::fieldTypeToString( fieldType ) ) );
+ QWhatsThis::add( m_textEdit, QString( i18n( "BibTeX field '%1'" ) ).arg( BibTeX::EntryField::fieldTypeToString( fieldType ) ) );
+ }
+
+ }
+
+ QString FieldLineEdit::caption()
+ {
+ return m_caption;
+ }
+
+ bool FieldLineEdit::isEmpty()
+ {
+ return m_value->items.isEmpty();
+ }
+
+ bool FieldLineEdit::isModified()
+ {
+ return m_isModified;
+ }
+
+ FieldLineEdit::ErrorType FieldLineEdit::error()
+ {
+ ErrorType result = etNoError;
+ for ( QValueList<BibTeX::ValueItem*>::ConstIterator it = m_value->items.begin(); result == etNoError && it != m_value->items.end(); ++it )
+ {
+ BibTeX::MacroKey *macroKey = dynamic_cast<BibTeX::MacroKey*>( *it );
+ result = ( macroKey != NULL && !macroKey->isValid() ) ? etInvalidStringKey : etNoError;
+ }
+
+ return result;
+ }
+
+ void FieldLineEdit::slotTextChanged( )
+ {
+ QString text;
+ switch ( m_inputType )
+ {
+ case itSingleLine:
+ text = m_lineEdit->text();
+ break;
+ case itMultiLine:
+ text = m_textEdit->text();
+ break;
+ }
+
+ if ( m_value->items.count() <= 1 )
+ {
+ m_value->items.clear();
+ if ( !text.isEmpty() )
+ {
+ if ( m_pushButtonString->isOn() )
+ m_value->items.append( new BibTeX::MacroKey( text ) );
+ else
+ m_value->items.append( new BibTeX::PlainText( text ) );
+ }
+ m_isModified = TRUE;
+ }
+
+ updateGUI();
+
+ emit textChanged();
+ }
+
+ void FieldLineEdit::slotStringToggled()
+ {
+ if ( m_value->items.count() == 1 )
+ {
+ QString text = m_value->items.first()->text();
+ if ( m_pushButtonString->isOn() )
+ {
+ BibTeX::PlainText *plainText = dynamic_cast<BibTeX::PlainText*>( m_value->items.first() );
+ if ( plainText != NULL )
+ {
+ m_value->items.clear();
+ m_value->items.append( new BibTeX::MacroKey( text ) );
+ }
+ }
+ else
+ {
+ BibTeX::MacroKey *macroKey = dynamic_cast<BibTeX::MacroKey*>( m_value->items.first() );
+ if ( macroKey != NULL )
+ {
+ m_value->items.clear();
+ m_value->items.append( new BibTeX::PlainText( text ) );
+ }
+ }
+ }
+
+ if ( m_lineEdit != NULL )
+ {
+ if ( m_pushButtonString->isOn() )
+ {
+ Settings * settings = Settings::self();
+ m_lineEdit->setCompletionObject( settings->completionMacro );
+ }
+ else
+ m_lineEdit->setCompletionObject( m_completion );
+ }
+
+ updateGUI();
+ emit textChanged();
+ m_isModified = TRUE;
+ }
+
+ void FieldLineEdit::slotComplexClicked()
+ {
+ if ( ValueWidget::execute( m_caption, m_fieldType, m_value, m_isReadOnly, this ) == QDialog::Accepted )
+ {
+ updateGUI();
+ emit textChanged();
+ m_isModified = TRUE;
+ }
+ }
+
+ void FieldLineEdit::setupGUI( const char *name )
+ {
+ Settings * settings = Settings::self();
+
+ char * subname = NULL;
+ if ( name != NULL )
+ subname = new char[ strlen( name ) + 20 ];
+
+ if ( subname != NULL )
+ {
+ strcpy( subname, name );
+ strcat( subname, "_pbstring" );
+ }
+ m_pushButtonString = new QPushButton( this, subname );
+ m_pushButtonString->setIconSet( QIconSet( SmallIcon( "flag" ) ) );
+ m_pushButtonString->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ m_pushButtonString->setToggleButton( TRUE );
+ QToolTip::add( m_pushButtonString, QString( i18n( "Set '%1' to be a string key" ) ).arg( m_caption ) );
+ m_pushButtonString->setEnabled( !m_isReadOnly );
+ connect( m_pushButtonString, SIGNAL( clicked() ), this, SLOT( slotStringToggled() ) );
+
+ if ( subname != NULL )
+ {
+ strcpy( subname, name );
+ strcat( subname, "_pbcomplex" );
+ }
+ m_pushButtonComplex = new QPushButton( this, subname );
+ m_pushButtonComplex->setIconSet( QIconSet( SmallIcon( "leftjust" ) ) );
+ m_pushButtonComplex->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QToolTip::add( m_pushButtonComplex, QString( i18n( "Edit '%1' as a concatenated value" ) ).arg( m_caption ) );
+ connect( m_pushButtonComplex, SIGNAL( clicked() ), this, SLOT( slotComplexClicked() ) );
+
+ QGridLayout * layout = NULL;
+ switch ( m_inputType )
+ {
+ case itSingleLine:
+ {
+ layout = new QGridLayout( this, 2, 3, 0, KDialog::spacingHint() );
+ if ( subname != NULL )
+ {
+ strcpy( subname, name );
+ strcat( subname, "_lineedit" );
+ }
+ m_lineEdit = new KLineEdit( this, subname );
+ m_lineEdit->setReadOnly( m_isReadOnly );
+ if ( settings->editing_UseSpecialFont )
+ m_lineEdit->setFont( settings->editing_SpecialFont );
+ layout->addWidget( m_lineEdit, 0, 0 );
+ setFocusProxy( m_lineEdit );
+ layout->addWidget( m_pushButtonString, 0, 1 );
+ layout->addWidget( m_pushButtonComplex, 0, 2 );
+ QWidget::setTabOrder( m_lineEdit, m_pushButtonString );
+ }
+ break;
+ case itMultiLine:
+ {
+ layout = new QGridLayout( this, 3, 2, 0, KDialog::spacingHint() );
+ layout->setRowStretch( 2, 1 );
+ if ( subname != NULL )
+ {
+ strcpy( subname, name );
+ strcat( subname, "_textedit" );
+ }
+ m_textEdit = new QTextEdit( this, subname );
+ m_textEdit->setReadOnly( m_isReadOnly );
+ if ( settings->editing_UseSpecialFont )
+ m_textEdit->setFont( settings->editing_SpecialFont );
+ layout->addMultiCellWidget( m_textEdit, 0, 2, 0, 0 );
+ setFocusProxy( m_textEdit );
+ layout->addWidget( m_pushButtonString, 0, 1 );
+ layout->addWidget( m_pushButtonComplex, 1, 1 );
+ QWidget::setTabOrder( m_textEdit, m_pushButtonString );
+ }
+ break;
+ }
+
+ QWidget::setTabOrder( m_pushButtonString, m_pushButtonComplex );
+ layout->setRowStretch( layout->numRows() - 1, 1 );
+
+ if ( subname != NULL )
+ delete[] subname;
+
+ enableSignals( TRUE );
+ }
+
+ void FieldLineEdit::updateGUI()
+ {
+ enableSignals( FALSE );
+
+ bool inputEnable = ( m_value->items.count() <= 1 ) && m_enabled;
+ m_pushButtonString->setEnabled( inputEnable && !m_isReadOnly );
+ bool isComplex = !inputEnable && m_value->items.count() > 1;
+
+ if ( m_value->items.count() == 1 )
+ {
+ BibTeX::ValueItem * item = m_value->items.first();
+ m_pushButtonString->setOn( dynamic_cast<BibTeX::MacroKey*>( m_value->items.first() ) != NULL );
+ switch ( m_inputType )
+ {
+ case itSingleLine:
+ if ( QString::compare( m_lineEdit->text(), item->text() ) != 0 )
+ m_lineEdit->setText( item->text() );
+ break;
+ case itMultiLine:
+ if ( QString::compare( m_textEdit->text(), item->text() ) != 0 )
+ m_textEdit->setText( item->text() );
+ break;
+ }
+ }
+ else
+ {
+ switch ( m_inputType )
+ {
+ case itSingleLine:
+ m_lineEdit->setText( isComplex ? i18n( "Concatenated value" ) : "" );
+ break;
+ case itMultiLine:
+ m_textEdit->setText( isComplex ? i18n( "Concatenated value" ) : "" );
+ break;
+ }
+ }
+
+ m_pushButtonComplex->setEnabled( m_enabled );
+
+ switch ( m_inputType )
+ {
+ case itSingleLine:
+ m_lineEdit->setEnabled( inputEnable );
+ m_lineEdit->setReadOnly( m_isReadOnly );
+ break;
+ case itMultiLine:
+ m_textEdit->setEnabled( inputEnable );
+ m_textEdit->setReadOnly( m_isReadOnly );
+ break;
+ }
+
+ enableSignals( TRUE );
+ }
+
+ void FieldLineEdit::enableSignals( bool enabled )
+ {
+ switch ( m_inputType )
+ {
+ case itSingleLine:
+ if ( enabled )
+ connect( m_lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( ) ) );
+ else
+ disconnect( m_lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( ) ) );
+ break;
+ case itMultiLine:
+ if ( enabled )
+ connect( m_textEdit, SIGNAL( textChanged( ) ), this, SLOT( slotTextChanged( ) ) );
+ else
+ disconnect( m_textEdit, SIGNAL( textChanged( ) ), this, SLOT( slotTextChanged( ) ) );
+ break;
+ }
+ }
+}
+#include "fieldlineedit.moc"
diff --git a/src/fieldlineedit.h b/src/fieldlineedit.h
new file mode 100644
index 0000000..e17dde1
--- /dev/null
+++ b/src/fieldlineedit.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXFIELDLINEEDIT_H
+#define KBIBTEXFIELDLINEEDIT_H
+
+#include <qwidget.h>
+
+#include <entryfield.h>
+#include <value.h>
+
+class KLineEdit;
+class QTextEdit;
+class QPushButton;
+class KCompletion;
+
+namespace KBibTeX
+{
+ class FieldLineEdit : public QWidget
+ {
+ Q_OBJECT
+ public:
+ enum InputType {itSingleLine, itMultiLine};
+ enum ErrorType {etNoError, etInvalidStringKey};
+
+ FieldLineEdit( const QString& caption, InputType inputType = itSingleLine, bool readOnly = FALSE, QWidget *parent = 0, const char *name = 0 );
+ ~FieldLineEdit();
+
+ /**
+ * Set the widget to use this value. The widget will make
+ * a deep copy internally and not modify the parameter.
+ * If NULL is passed to this function, the widget will be
+ * initialized with an empty BibTeXValue internally.
+ */
+ void setValue( const BibTeX::Value *value );
+
+ /**
+ * Return the BibTeXValue of this widget. The returned
+ * variable is a deep copy of the widget's internal state.
+ * The returned variable must be delete later by the
+ * function caller.
+ * The function will return NULL if no data is set by the
+ * user for this widget.
+ */
+ BibTeX::Value *value();
+
+ void setEnabled( bool enabled );
+
+ void setFieldType( BibTeX::EntryField::FieldType fieldType );
+
+ QString caption();
+
+ bool isEmpty();
+
+ bool isModified();
+
+ ErrorType error();
+
+ signals:
+ void textChanged( );
+
+ protected slots:
+ void updateGUI();
+
+ private slots:
+ void slotTextChanged();
+ void slotStringToggled();
+ void slotComplexClicked();
+
+ private:
+ BibTeX::Value *m_value;
+ QString m_caption;
+ KLineEdit *m_lineEdit;
+ QTextEdit *m_textEdit;
+ QPushButton *m_pushButtonString;
+ QPushButton *m_pushButtonComplex;
+ bool m_isReadOnly;
+ bool m_enabled;
+ InputType m_inputType;
+ bool m_isModified;
+ BibTeX::EntryField::FieldType m_fieldType;
+ KCompletion *m_completion;
+
+ void setupGUI( const char *name );
+ void enableSignals( bool enabled );
+ };
+
+}
+
+#endif
diff --git a/src/fieldlistview.cpp b/src/fieldlistview.cpp
new file mode 100644
index 0000000..62ba8a6
--- /dev/null
+++ b/src/fieldlistview.cpp
@@ -0,0 +1,455 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qstring.h>
+#include <qregexp.h>
+#include <qlayout.h>
+#include <qheader.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+
+#include <klistview.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+
+#include <value.h>
+#include <valuewidget.h>
+#include <settings.h>
+#include "fieldlistview.h"
+
+namespace KBibTeX
+{
+
+ FieldListView::FieldListView( const QString& caption, const QString& prefixNew, bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_value( new BibTeX::Value() ), m_caption( caption ), m_prefixNew( prefixNew ), m_isReadOnly( isReadOnly ), m_enabled( TRUE ), m_isComplex( FALSE ), m_isModified( FALSE ), m_newValueCounter( 0 ), m_fieldType( BibTeX::EntryField::ftUnknown )
+ {
+ setupGUI();
+ m_listViewElements->installEventFilter( this );
+ m_listViewElements->renameLineEdit() ->installEventFilter( this );
+
+ m_value = new BibTeX::Value();
+ }
+
+
+ FieldListView::~FieldListView()
+ {
+ delete m_value;
+ }
+
+ void FieldListView::setValue( const BibTeX::Value *value )
+ {
+ if ( value != m_value )
+ {
+ if ( m_value != NULL )
+ delete m_value;
+
+ if ( value != NULL )
+ m_value = new BibTeX::Value( value );
+ else
+ m_value = new BibTeX::Value( );
+
+ reset();
+ updateGUI();
+
+ m_isModified = FALSE;
+ }
+ }
+
+ BibTeX::Value *FieldListView::value()
+ {
+ if ( m_value->items.isEmpty() )
+ return NULL;
+ else
+ return new BibTeX::Value( m_value );
+ }
+
+ void FieldListView::setEnabled( bool enabled )
+ {
+ m_enabled = enabled;
+ updateGUI();
+ }
+
+ void FieldListView::setFieldType( BibTeX::EntryField::FieldType fieldType )
+ {
+ m_fieldType = fieldType;
+
+ Settings * settings = Settings::self();
+ m_listViewElements->renameLineEdit() ->setCompletionObject( settings->completion( m_fieldType ) );
+ QToolTip::add( m_listViewElements, QString( i18n( "BibTeX field '%1'" ) ).arg( BibTeX::EntryField::fieldTypeToString( fieldType ) ) );
+ QWhatsThis::add( m_listViewElements, QString( i18n( "BibTeX field '%1'" ) ).arg( BibTeX::EntryField::fieldTypeToString( fieldType ) ) );
+
+ m_value->items.clear();
+ }
+
+ QString FieldListView::caption()
+ {
+ return m_caption;
+ }
+
+ bool FieldListView::isEmpty()
+ {
+ return m_value != NULL ? m_value->items.isEmpty() : TRUE;
+ }
+
+ bool FieldListView::isModified()
+ {
+ return m_isModified;
+ }
+
+ bool FieldListView::eventFilter( QObject *o, QEvent * e )
+ {
+ if ( o == m_listViewElements->renameLineEdit() )
+ {
+ if ( e->type() == QEvent::Hide )
+ itemRenameDone();
+ }
+ else if ( e->type() == QEvent::AccelOverride )
+ {
+ QKeyEvent * ke = static_cast<QKeyEvent*>( e );
+ //override delete action
+ if ( ke->key() == Key_Delete && ke->state() == NoButton )
+ {
+ slotDelete();
+ ke->accept();
+ return true;
+ }
+ else if ( ke->key() == Key_F2 && ke->state() == NoButton )
+ {
+ slotEdit();
+ ke->accept();
+ return true;
+ }
+ else if ( ke->key() == Key_A && ke->state() == ControlButton )
+ {
+ slotAdd();
+ ke->accept();
+ return true;
+ }
+ else if ( ke->key() == Key_Up && ke->state() == ControlButton )
+ {
+ slotUp();
+ ke->accept();
+ return true;
+ }
+ else if ( ke->key() == Key_Down && ke->state() == ControlButton )
+ {
+ slotDown();
+ ke->accept();
+ return true;
+ }
+ else if ( ke->key() == Key_C && ke->state() == ( ControlButton | AltButton ) )
+ {
+ slotComplex();
+ ke->accept();
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ void FieldListView::updateGUI()
+ {
+ disconnect( m_checkBoxEtAl, SIGNAL( toggled( bool ) ), this, SLOT( apply() ) );
+ if ( m_value != NULL && !m_isComplex )
+ {
+ bool isElementSelected = m_listViewElements->selectedItem() != NULL;
+ m_pushButtonAdd->setEnabled( !m_isReadOnly );
+ m_pushButtonEdit->setEnabled( !m_isReadOnly && isElementSelected );
+ m_pushButtonDelete->setEnabled( !m_isReadOnly && isElementSelected );
+ m_pushButtonUp->setEnabled( !m_isReadOnly && isElementSelected && m_listViewElements->selectedItem() != m_listViewElements->firstChild() );
+ m_pushButtonDown->setEnabled( !m_isReadOnly && isElementSelected && m_listViewElements->selectedItem() != m_listViewElements->lastItem() );
+ m_listViewElements->setEnabled( !m_isReadOnly );
+ m_checkBoxEtAl->setEnabled( !m_isReadOnly );
+ }
+ else
+ {
+ m_pushButtonAdd->setEnabled( FALSE );
+ m_pushButtonEdit->setEnabled( FALSE );
+ m_pushButtonDelete->setEnabled( FALSE );
+ m_pushButtonUp->setEnabled( FALSE );
+ m_pushButtonDown->setEnabled( FALSE );
+ m_listViewElements->setEnabled( FALSE );
+ m_checkBoxEtAl->setEnabled( FALSE );
+ }
+ connect( m_checkBoxEtAl, SIGNAL( toggled( bool ) ), this, SLOT( apply() ) );
+ }
+
+ void FieldListView::slotAdd()
+ {
+ if ( isSimple() )
+ {
+ KListViewItem * item = new KListViewItem( m_listViewElements, m_listViewElements->lastItem(), QString( "%1%2" ).arg( m_prefixNew ).arg( ++m_newValueCounter ) );
+ m_listViewElements->setSelected( item, TRUE );
+ updateGUI();
+ QTimer::singleShot( 100, this, SLOT( slotEdit() ) );
+ }
+ }
+
+ void FieldListView::slotEdit()
+ {
+ if ( isSimple() )
+ {
+ KListViewItem * item = static_cast<KListViewItem*>( m_listViewElements->selectedItem() );
+ if ( item != NULL )
+ m_listViewElements->rename( item, 0 );
+ }
+ }
+
+ void FieldListView::slotDelete()
+ {
+ QListViewItem * item = m_listViewElements->selectedItem();
+ if ( isSimple() && item != NULL )
+ {
+ delete item;
+ apply();
+ updateGUI();
+
+ m_isModified = TRUE;
+ }
+ }
+
+ void FieldListView::slotUp()
+ {
+ QListViewItem * item = m_listViewElements->selectedItem();
+ if ( isSimple() && !m_listViewElements->isRenaming() && item != NULL && item -> itemAbove() != NULL )
+ {
+ item->itemAbove() ->moveItem( item );
+ apply();
+ updateGUI();
+
+ m_isModified = TRUE;
+ }
+ }
+
+ void FieldListView::slotDown()
+ {
+ QListViewItem * item = m_listViewElements->selectedItem();
+ if ( isSimple() && !m_listViewElements->isRenaming() && item != NULL && item -> itemBelow() != NULL )
+ {
+ item->moveItem( item->itemBelow() );
+ apply();
+ updateGUI();
+
+ m_isModified = TRUE;
+ }
+ }
+
+ void FieldListView::slotComplex()
+ {
+ if ( !m_listViewElements->isRenaming() && ValueWidget::execute( m_caption, m_fieldType, m_value, m_isReadOnly, this ) == QDialog::Accepted )
+ {
+ reset();
+ updateGUI();
+
+ m_isModified = TRUE;
+ }
+ }
+
+ void FieldListView::slotListViewDoubleClicked( QListViewItem * lvi )
+ {
+ if ( lvi == NULL )
+ slotAdd();
+ }
+
+ void FieldListView::slotItemRenamed( QListViewItem * item, int /*col*/, const QString & text )
+ {
+ if ( text.isEmpty() && isSimple() && item != NULL )
+ {
+ delete item;
+ updateGUI();
+ }
+
+ apply();
+ m_isModified = TRUE;
+ }
+
+ void FieldListView::setupGUI()
+ {
+ Settings * settings = Settings::self();
+
+ QGridLayout * layout = new QGridLayout( this, 8, 2, 0, KDialog::spacingHint() );
+ layout->setRowStretch( 5, 1 );
+
+ m_listViewElements = new KListView( this );
+ layout->addMultiCellWidget( m_listViewElements, 0, 6, 0, 0 );
+ m_listViewElements->renameLineEdit() ->setCompletionObject( settings->completion( m_fieldType ) );
+ m_listViewElements->renameLineEdit() ->setCompletionMode( KGlobalSettings::CompletionPopup );
+ m_listViewElements->renameLineEdit() ->completionObject() ->setIgnoreCase( true );
+ m_listViewElements->setDefaultRenameAction( QListView::Accept );
+ m_listViewElements->addColumn( m_caption );
+ m_listViewElements->setSorting( -1, TRUE );
+ m_listViewElements->setItemsRenameable( TRUE );
+ if ( settings->editing_UseSpecialFont )
+ m_listViewElements->setFont( settings->editing_SpecialFont );
+ m_listViewElements->header() ->setFont( KGlobalSettings::generalFont() );
+
+ m_listViewElements->header() ->setClickEnabled( FALSE );
+ m_listViewElements->header() ->setStretchEnabled( TRUE, 0 );
+ connect( m_listViewElements, SIGNAL( selectionChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_listViewElements, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listViewElements, SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( slotListViewDoubleClicked( QListViewItem * ) ) );
+ connect( m_listViewElements, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listViewElements, SIGNAL( itemRenamed( QListViewItem*, int, const QString& ) ), this, SLOT( slotItemRenamed( QListViewItem*, int, const QString& ) ) );
+
+ m_pushButtonAdd = new QPushButton( i18n( "Add" ), this );
+ layout->addWidget( m_pushButtonAdd, 0, 1 );
+ m_pushButtonAdd->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ connect( m_pushButtonAdd, SIGNAL( clicked() ), this, SLOT( slotAdd() ) );
+ QToolTip::add( m_pushButtonAdd, QString( i18n( "Add new '%1' item (Ctrl+A)" ) ).arg( m_caption ) );
+
+ m_pushButtonEdit = new QPushButton( i18n( "Edit" ), this );
+ layout->addWidget( m_pushButtonEdit, 1, 1 );
+ m_pushButtonEdit->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ connect( m_pushButtonEdit, SIGNAL( clicked() ), this, SLOT( slotEdit() ) );
+ QToolTip::add( m_pushButtonEdit, QString( i18n( "Edit current '%1' item (F2)" ) ).arg( m_caption ) );
+
+ m_pushButtonDelete = new QPushButton( i18n( "Delete" ), this );
+ layout->addWidget( m_pushButtonDelete, 2, 1 );
+ m_pushButtonDelete->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ connect( m_pushButtonDelete, SIGNAL( clicked() ), this, SLOT( slotDelete() ) );
+ QToolTip::add( m_pushButtonDelete, QString( i18n( "Delete current '%1' item (Del)" ) ).arg( m_caption ) );
+
+ m_pushButtonUp = new QPushButton( i18n( "Up" ), this );
+ layout->addWidget( m_pushButtonUp, 3, 1 );
+ m_pushButtonUp->setIconSet( QIconSet( SmallIcon( "up" ) ) );
+ connect( m_pushButtonUp, SIGNAL( clicked() ), this, SLOT( slotUp() ) );
+ QToolTip::add( m_pushButtonUp, QString( i18n( "Move current '%1' item up (Ctrl+Up)" ) ).arg( m_caption ) );
+
+ m_pushButtonDown = new QPushButton( i18n( "Down" ), this );
+ layout->addWidget( m_pushButtonDown, 4, 1 );
+ m_pushButtonDown->setIconSet( QIconSet( SmallIcon( "down" ) ) );
+ connect( m_pushButtonDown, SIGNAL( clicked() ), this, SLOT( slotDown() ) );
+ QToolTip::add( m_pushButtonDown, QString( i18n( "Move current '%1' item down (Ctrl+Down)" ) ).arg( m_caption ) );
+
+ m_pushButtonComplexEdit = new QPushButton( i18n( "Complex..." ), this );
+ layout->addWidget( m_pushButtonComplexEdit, 6, 1 );
+ m_pushButtonComplexEdit->setIconSet( QIconSet( SmallIcon( "leftjust" ) ) );
+ connect( m_pushButtonComplexEdit, SIGNAL( clicked() ), this, SLOT( slotComplex() ) );
+ QToolTip::add( m_pushButtonComplexEdit, QString( i18n( "Edit current '%1' item as a concatenated string (Ctrl+Alt+C)" ) ).arg( m_caption ) );
+
+ m_checkBoxEtAl = new QCheckBox( i18n( "... and others (et al.)" ), this );
+ layout->addMultiCellWidget( m_checkBoxEtAl, 7, 7, 0, 1 );
+ connect( m_checkBoxEtAl, SIGNAL( toggled( bool ) ), this, SLOT( apply() ) );
+ }
+
+ void FieldListView::apply()
+ {
+ QStringList elements;
+ Settings * settings = Settings::self();
+
+ m_value->items.clear();
+
+ for ( QListViewItemIterator it( m_listViewElements ); it.current(); it++ )
+ {
+ QString text = it.current() ->text( 0 );
+ elements.append( text );
+ }
+
+ if ( elements.count() > 0 )
+ {
+ m_value->items.clear();
+ BibTeX::PersonContainer *container = new BibTeX::PersonContainer( settings->editing_FirstNameFirst );
+
+ switch ( m_fieldType )
+ {
+ case BibTeX::EntryField::ftAuthor:
+ case BibTeX::EntryField::ftEditor:
+ {
+ for ( QStringList::ConstIterator it = elements.constBegin(); it != elements.constEnd(); ++it )
+ {
+ BibTeX::Person *person = new BibTeX::Person( *it, settings->editing_FirstNameFirst );
+ container->persons.append( person );
+ }
+ }
+ break;
+ default:
+ kdDebug() << "Don't know how to handle entries of type " << BibTeX::EntryField::fieldTypeToString( m_fieldType ) << endl;
+ }
+
+ if ( m_checkBoxEtAl->isChecked() )
+ container->persons.append( new BibTeX::Person( "others", settings->editing_FirstNameFirst ) );
+
+ if ( !container->persons.isEmpty() )
+ m_value->items.append( container );
+ else
+ delete container;
+
+ settings->addToCompletion( m_value, m_fieldType );
+ }
+ }
+
+ void FieldListView::reset()
+ {
+ disconnect( m_checkBoxEtAl, SIGNAL( toggled( bool ) ), this, SLOT( apply() ) );
+ m_listViewElements->clear();
+ m_checkBoxEtAl->setChecked( FALSE );
+
+ m_isComplex = FALSE;
+ for ( QValueList<BibTeX::ValueItem*>::ConstIterator it = m_value->items.constBegin(); !m_isComplex && it != m_value->items.constEnd(); ++it )
+ {
+ BibTeX::MacroKey *macroKey = dynamic_cast<BibTeX::MacroKey *>( *it );
+ m_isComplex = macroKey != NULL;
+ }
+
+ if ( !m_isComplex )
+ switch ( m_fieldType )
+ {
+ case BibTeX::EntryField::ftAuthor:
+ case BibTeX::EntryField::ftEditor:
+ {
+ for ( QValueList<BibTeX::ValueItem*>::ConstIterator it = m_value->items.constBegin(); it != m_value->items.constEnd(); ++it )
+ {
+ BibTeX::PersonContainer *container = dynamic_cast<BibTeX::PersonContainer *>( *it );
+ if ( container != NULL )
+ for ( QValueList<BibTeX::Person*>::ConstIterator pit = container->persons.constBegin(); pit != container->persons.constEnd(); ++pit )
+ {
+ QString text = ( *pit )->text();
+ if ( text == "others" )
+ m_checkBoxEtAl->setChecked( TRUE );
+ else
+ new QListViewItem( m_listViewElements, m_listViewElements->lastItem(), text );
+ }
+ }
+ }
+ break;
+ default:
+ kdDebug() << "Don't know how to handle entries of type " << BibTeX::EntryField::fieldTypeToString( m_fieldType ) << endl;
+ }
+
+ connect( m_checkBoxEtAl, SIGNAL( toggled( bool ) ), this, SLOT( apply() ) );
+ }
+
+ bool FieldListView::isSimple()
+ {
+ return m_value->items.count() == 0 || ( m_value->items.count() == 1 && dynamic_cast<BibTeX::MacroKey*>( m_value->items.first() ) == NULL );
+ }
+
+ void FieldListView::itemRenameDone()
+ {
+ apply();
+ }
+}
+#include "fieldlistview.moc"
diff --git a/src/fieldlistview.h b/src/fieldlistview.h
new file mode 100644
index 0000000..f8a3baa
--- /dev/null
+++ b/src/fieldlistview.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXFIELDLISTVIEW_H
+#define KBIBTEXFIELDLISTVIEW_H
+
+#include <qwidget.h>
+
+#include <value.h>
+#include <entryfield.h>
+
+class QString;
+class KListView;
+class QListViewItem;
+class QPushButton;
+class QCheckBox;
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class FieldListView : public QWidget
+ {
+ Q_OBJECT
+ public:
+ FieldListView( const QString& caption, const QString& prefixNew, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~FieldListView();
+
+ void setValue( const BibTeX::Value *value );
+ BibTeX::Value *value();
+
+ void setEnabled( bool enabled );
+
+ void setFieldType( BibTeX::EntryField::FieldType fieldType );
+
+ QString caption();
+
+ bool isEmpty();
+
+ bool isModified();
+
+ virtual bool eventFilter( QObject *o, QEvent * e );
+
+ private slots:
+ void updateGUI();
+ void slotAdd();
+ void slotEdit();
+ void slotDelete();
+ void slotUp();
+ void slotDown();
+ void slotComplex();
+ void slotListViewDoubleClicked( QListViewItem * );
+ void slotItemRenamed( QListViewItem * item, int col, const QString & text );
+ void apply();
+
+ private:
+ BibTeX::Value *m_value;
+ QString m_caption;
+ QString m_prefixNew;
+ bool m_isReadOnly;
+ bool m_enabled;
+ bool m_isComplex;
+ bool m_isModified;
+ int m_newValueCounter;
+ BibTeX::EntryField::FieldType m_fieldType;
+ KListView *m_listViewElements;
+ QPushButton *m_pushButtonAdd;
+ QPushButton *m_pushButtonEdit;
+ QPushButton *m_pushButtonDelete;
+ QPushButton *m_pushButtonUp;
+ QPushButton *m_pushButtonDown;
+ QPushButton *m_pushButtonComplexEdit;
+ QCheckBox *m_checkBoxEtAl;
+
+ void setupGUI();
+ void reset();
+ void itemRenameDone();
+ bool isSimple();
+ };
+
+}
+
+#endif
diff --git a/src/file.cpp b/src/file.cpp
new file mode 100644
index 0000000..8b6106e
--- /dev/null
+++ b/src/file.cpp
@@ -0,0 +1,402 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qiodevice.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+
+#include <settings.h>
+#include <file.h>
+#include <entry.h>
+#include <element.h>
+#include <macro.h>
+#include <comment.h>
+#include <fileexporter.h>
+
+namespace BibTeX
+{
+
+ File::File( ) : QObject( ), fileName( QString::null )
+ {
+ // nothing
+ }
+
+ File::~File()
+ {
+ for ( ElementList::iterator it = elements.begin(); it != elements.end(); it++ )
+ delete * it;
+ }
+
+ unsigned int File::count() const
+ {
+ return elements.count();
+ }
+
+ Element* File::at( const unsigned int index )
+ {
+ return *( elements.at( index ) );
+ }
+
+ void File::append( const File *other, const Element *after )
+ {
+ for ( ElementList::ConstIterator it = other->constBegin(); it != other->constEnd(); it++ )
+ appendElement( cloneElement( *it ), after );
+ }
+
+ void File::appendElement( Element *element, const Element *after )
+ {
+ if ( after == NULL )
+ elements.append( element );
+ else
+ {
+ for ( ElementList::iterator it = elements.begin() ; it != elements.end(); it++ )
+ if (( *it ) == after )
+ {
+ elements.insert( ++it, element );
+ break;
+ }
+ }
+ }
+
+ void File::deleteElement( Element *element )
+ {
+ bool found = false;
+ for ( ElementList::iterator it = elements.begin(); it != elements.end(); it++ )
+ if ( ( found = ( *it == element ) ) )
+ {
+ elements.remove( it );
+ delete element;
+ break;
+ }
+
+ if ( !found )
+ qDebug( "BibTeX::File got told to delete an element which is not in this file." );
+ }
+
+ Element* File::cloneElement( Element *element )
+ {
+ Entry * entry = dynamic_cast<Entry*>( element );
+ if ( entry )
+ return new Entry( entry );
+ else
+ {
+ Macro *macro = dynamic_cast<Macro*>( element );
+ if ( macro )
+ return new Macro( macro );
+ else
+ {
+ Comment *comment = dynamic_cast<Comment*>( element );
+ if ( comment )
+ return new Comment( comment );
+ else
+ return NULL;
+ }
+ }
+ }
+
+ Element *File::containsKey( const QString &key )
+ {
+ for ( ElementList::iterator it = elements.begin(); it != elements.end(); it++ )
+ {
+ Entry* entry = dynamic_cast<Entry*>( *it );
+ if ( entry != NULL )
+ {
+ if ( entry->id() == key )
+ return entry;
+ }
+ else
+ {
+ Macro* macro = dynamic_cast<Macro*>( *it );
+ if ( macro != NULL )
+ {
+ if ( macro->key() == key )
+ return macro;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ const Element *File::containsKeyConst( const QString &key ) const
+ {
+ for ( ElementList::const_iterator it = elements.begin(); it != elements.end(); it++ )
+ {
+ Entry* entry = dynamic_cast<Entry*>( *it );
+ if ( entry != NULL )
+ {
+ if ( entry->id() == key )
+ return entry;
+ }
+ else
+ {
+ Macro* macro = dynamic_cast<Macro*>( *it );
+ if ( macro != NULL )
+ {
+ if ( macro->key() == key )
+ return macro;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ QStringList File::allKeys()
+ {
+ QStringList result;
+
+ for ( ElementList::iterator it = elements.begin(); it != elements.end(); it++ )
+ {
+ Entry* entry = dynamic_cast<Entry*>( *it );
+ if ( entry != NULL )
+ result.append( entry->id() );
+ else
+ {
+ Macro* macro = dynamic_cast<Macro*>( *it );
+ if ( macro != NULL )
+ result.append( macro->key() );
+ }
+ }
+
+ return result;
+ }
+
+ QString File::text()
+ {
+ QString result;
+
+ for ( ElementList::iterator it = elements.begin(); it != elements.end(); it++ )
+ {
+ result.append(( *it )->text() );
+ result.append( "\n" );
+ }
+
+ return result;
+ }
+
+ File::ElementList::iterator File::begin()
+ {
+ return elements.begin();
+ }
+
+ File::ElementList::iterator File::end()
+ {
+ return elements.end();
+ }
+
+ File::ElementList::ConstIterator File::constBegin() const
+ {
+ return elements.constBegin();
+ }
+
+ File::ElementList::ConstIterator File::constEnd() const
+ {
+ return elements.constEnd();
+ }
+
+ QStringList File::getAllValuesAsStringList( const EntryField::FieldType fieldType ) const
+ {
+ QStringList result;
+ for ( ElementList::ConstIterator eit = elements.constBegin(); eit != elements.constEnd(); ++eit )
+ {
+ Entry* entry = dynamic_cast<Entry*>( *eit );
+ EntryField * field = NULL;
+ if ( entry != NULL && ( field = entry->getField( fieldType ) ) != NULL )
+ {
+ QValueList<ValueItem*> valueItems = field->value()->items;
+ for ( QValueList<ValueItem*>::ConstIterator vit = valueItems.begin(); vit != valueItems.end(); ++vit )
+ {
+ switch ( fieldType )
+ {
+ case EntryField::ftKeywords :
+ {
+ KeywordContainer *container = dynamic_cast<KeywordContainer*>( *vit );
+ if ( container != NULL )
+ for ( QValueList<Keyword*>::ConstIterator kit = container->keywords.constBegin(); kit != container->keywords.constEnd(); ++kit )
+ {
+ QString text = ( *kit )->text();
+ if ( !result.contains( text ) )
+ result.append( text );
+ }
+ }
+ break;
+ case EntryField::ftEditor :
+ case EntryField::ftAuthor :
+ {
+ PersonContainer *container = dynamic_cast<PersonContainer*>( *vit );
+ if ( container != NULL )
+ for ( QValueList<Person*>::ConstIterator pit = container->persons.constBegin(); pit != container->persons.constEnd(); ++pit )
+ {
+ QString text = ( *pit )->text();
+ if ( !result.contains( text ) )
+ result.append( text );
+ }
+ }
+ break;
+ default:
+ {
+ QString text = ( *vit )->text();
+ if ( !result.contains( text ) )
+ result.append( text );
+ }
+ }
+ }
+ }
+ }
+
+ result.sort();
+ return result;
+ }
+
+ QMap<QString, int> File::getAllValuesAsStringListWithCount( const EntryField::FieldType fieldType ) const
+ {
+ QMap<QString, int> result;
+ for ( ElementList::ConstIterator eit = elements.begin(); eit != elements.end(); ++eit )
+ {
+ Entry* entry = dynamic_cast<Entry*>( *eit );
+ EntryField * field = NULL;
+ if ( entry != NULL && ( field = entry->getField( fieldType ) ) != NULL )
+ {
+ QValueList<ValueItem*> valueItems = field->value()->items;
+ for ( QValueList<ValueItem*>::ConstIterator vit = valueItems.begin(); vit != valueItems.end(); ++vit )
+ {
+ switch ( fieldType )
+ {
+ case EntryField::ftKeywords :
+ {
+ KeywordContainer *container = dynamic_cast<KeywordContainer*>( *vit );
+ if ( container != NULL )
+ for ( QValueList<Keyword*>::ConstIterator kit = container->keywords.constBegin(); kit != container->keywords.constEnd(); ++kit )
+ {
+ QString text = ( *kit )->text();
+ if ( !result.contains( text ) )
+ result[text] = 1;
+ else
+ result[text] += 1;
+ }
+ }
+ break;
+ case EntryField::ftEditor :
+ case EntryField::ftAuthor :
+ {
+ PersonContainer *container = dynamic_cast<PersonContainer*>( *vit );
+ if ( container != NULL )
+ for ( QValueList<Person*>::ConstIterator pit = container->persons.constBegin(); pit != container->persons.constEnd(); ++pit )
+ {
+ QString text = ( *pit )->text();
+ if ( !result.contains( text ) )
+ result[text] = 1;
+ else
+ result[text] += 1;
+ }
+ }
+ break;
+ default:
+ {
+ QString text = ( *vit )->text();
+ if ( !result.contains( text ) )
+ result[text] = 1;
+ else
+ result[text] += 1;
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ void File::replaceValue( const QString& oldText, const QString& newText, const EntryField::FieldType fieldType )
+ {
+ qDebug( "Renaming all occurrences of '%s' to '%s' for fields of type '%s'", oldText.latin1(), newText.latin1(), EntryField::fieldTypeToString( fieldType ).latin1() );
+
+ for ( ElementList::ConstIterator it = elements.begin(); it != elements.end(); it++ )
+ {
+ Entry* entry = dynamic_cast<Entry*>( *it );
+ if ( entry != NULL )
+ {
+ if ( fieldType != EntryField::ftUnknown )
+ {
+ EntryField * field = entry->getField( fieldType );
+ if ( field != NULL )
+ field->value() ->replace( oldText, newText );
+ }
+ }
+ }
+ }
+
+ BibTeX::Entry *File::completeReferencedFieldsConst( const BibTeX::Entry *entry ) const
+ {
+ BibTeX::Entry *myEntry = new BibTeX::Entry( entry );
+ completeReferencedFields( myEntry );
+ return myEntry;
+ }
+
+ void File::completeReferencedFields( BibTeX::Entry *entry ) const
+ {
+ BibTeX::EntryField *crossRefField = entry->getField( BibTeX::EntryField::ftCrossRef );
+ const BibTeX::Entry *parent = NULL;
+ if ( crossRefField != NULL && ( parent = dynamic_cast<const BibTeX::Entry*>( containsKeyConst( crossRefField->value()->text() ) ) ) != NULL )
+ {
+ for ( int ef = ( int )BibTeX::EntryField::ftAbstract; ef <= ( int )BibTeX::EntryField::ftYear; ++ef )
+ {
+ BibTeX::EntryField *entryField = entry->getField(( BibTeX::EntryField::FieldType ) ef );
+ if ( entryField == NULL )
+ {
+ BibTeX::EntryField *parentEntryField = parent->getField(( BibTeX::EntryField::FieldType ) ef );
+ if ( parentEntryField != NULL )
+ {
+ entryField = new BibTeX::EntryField(( BibTeX::EntryField::FieldType )ef );
+ entryField->setValue( parentEntryField->value() );
+ entry->addField( entryField );
+ }
+ }
+ }
+
+ BibTeX::EntryField *entryField = entry->getField( EntryField::ftBookTitle );
+ BibTeX::EntryField *parentEntryField = parent->getField( EntryField::ftTitle );
+ if (( entry->entryType() == Entry::etInProceedings || entry->entryType() == Entry::etInBook ) && entryField == NULL && parentEntryField != NULL )
+ {
+ entryField = new BibTeX::EntryField( EntryField::ftBookTitle );
+ entryField->setValue( parentEntryField->value() );
+ entry->addField( entryField );
+ }
+ }
+
+ for ( int ef = ( int )BibTeX::EntryField::ftAbstract; ef <= ( int )BibTeX::EntryField::ftYear; ++ef )
+ {
+ BibTeX::EntryField *entryField = entry->getField(( BibTeX::EntryField::FieldType ) ef );
+ if ( entryField != NULL && entryField->value() != NULL && !entryField->value()->items.isEmpty() )
+ {
+ MacroKey *macroKey = dynamic_cast<MacroKey*>( entryField->value()->items.first() );
+ const Macro *macro = NULL;
+ if ( macroKey != NULL && ( macro = dynamic_cast<const Macro*>( containsKeyConst( macroKey->text() ) ) ) != NULL )
+ entryField->setValue( macro->value() );
+ }
+ }
+ }
+
+}
+
+#include "file.moc"
+
diff --git a/src/file.h b/src/file.h
new file mode 100644
index 0000000..fcb797a
--- /dev/null
+++ b/src/file.h
@@ -0,0 +1,108 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILE_H
+#define BIBTEXFILE_H
+
+#include <qobject.h>
+#include <qvaluelist.h>
+
+#include <entryfield.h>
+
+class QDir;
+class QString;
+class QChar;
+class QStringList;
+class QWaitCondition;
+class QProcess;
+class QIODevice;
+
+namespace BibTeX
+{
+ class Element;
+ class Entry;
+ class String;
+ class FileExporter;
+
+ static const QString Months[] =
+ {
+ QString( "January" ), QString( "February" ), QString( "March" ), QString( "April" ), QString( "May" ), QString( "June" ), QString( "July" ), QString( "August" ), QString( "September" ), QString( "October" ), QString( "November" ), QString( "December" )
+ };
+
+ static const QString MonthsTriple[] =
+ {
+ QString( "jan" ), QString( "feb" ), QString( "mar" ), QString( "apr" ), QString( "may" ), QString( "jun" ), QString( "jul" ), QString( "aug" ), QString( "sep" ), QString( "oct" ), QString( "nov" ), QString( "dec" )
+ };
+
+ class File : public QObject
+ {
+ Q_OBJECT
+
+ friend class FileExporterXML;
+ friend class FileExporterBibTeX;
+ friend class FileExporterRIS;
+ friend class FileExporter;
+ friend class FileParser;
+
+ public:
+ typedef QValueList<Element*> ElementList;
+
+ enum FileFormat { formatUndefined = 0, formatBibTeX = 1, formatXML = 2, formatHTML = 3, formatPDF = 4, formatPS = 5, formatRTF = 6, formatRIS = 7, formatEndNote = 8, formatISI = 9, formatDocBook5 = 10, formatMODS = 11, formatWordBib = 12, formatAds = 13, formatEndNoteXML = 14 };
+ enum Encoding {encImplicit = 0, encLaTeX = 1, encUTF8 = 2};
+ enum StringProtection { spNone, spParanthesis, spQuote, spBoth };
+
+ File( );
+ ~File();
+
+ unsigned int count() const;
+ Element* at( const unsigned int index );
+ void append( const File *other, const Element *after = NULL );
+ void appendElement( Element *element, const Element *after = NULL );
+ void deleteElement( Element *element );
+ static Element* cloneElement( Element *element );
+
+ Element *containsKey( const QString &key );
+ const Element *containsKeyConst( const QString &key ) const;
+ QStringList allKeys();
+ QString text();
+
+ ElementList::iterator begin();
+ ElementList::iterator end();
+ ElementList::const_iterator constBegin() const;
+ ElementList::const_iterator constEnd() const;
+
+ QStringList getAllValuesAsStringList( const EntryField::FieldType fieldType ) const;
+ QMap<QString, int> getAllValuesAsStringListWithCount( const EntryField::FieldType fieldType ) const;
+ void replaceValue( const QString& oldText, const QString& newText, const EntryField::FieldType fieldType );
+ BibTeX::Entry *completeReferencedFieldsConst( const BibTeX::Entry *entry ) const;
+ void completeReferencedFields( BibTeX::Entry *entry ) const;
+
+ QString fileName;
+
+ protected:
+ ElementList elements;
+
+ private:
+ void clearElements();
+
+ };
+
+}
+
+#endif
diff --git a/src/fileexporter.cpp b/src/fileexporter.cpp
new file mode 100644
index 0000000..b5fe73b
--- /dev/null
+++ b/src/fileexporter.cpp
@@ -0,0 +1,36 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include "fileexporter.h"
+
+namespace BibTeX
+{
+
+ FileExporter::FileExporter() : QObject()
+ {
+ // nothing
+ }
+
+ FileExporter::~FileExporter()
+ {
+ // nothing
+ }
+
+}
+#include "fileexporter.moc"
diff --git a/src/fileexporter.h b/src/fileexporter.h
new file mode 100644
index 0000000..cc60ac0
--- /dev/null
+++ b/src/fileexporter.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTER_H
+#define BIBTEXFILEEXPORTER_H
+
+#include <qobject.h>
+#include <qmutex.h>
+
+#include <file.h>
+
+class QIODevice;
+
+namespace BibTeX
+{
+ class File;
+ class Element;
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporter : public QObject
+ {
+ Q_OBJECT
+ public:
+ FileExporter();
+ ~FileExporter();
+
+ virtual bool save( QIODevice *iodevice, const File *bibtexfile, QStringList *errorLog = NULL ) = 0;
+ virtual bool save( QIODevice *iodevice, const Element* element, QStringList *errorLog = NULL ) = 0;
+
+ signals:
+ void progress( int current, int total );
+
+ public slots:
+ virtual void cancel()
+ {
+ // nothing
+ };
+
+ protected:
+ QMutex m_mutex;
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterbibtex.cpp b/src/fileexporterbibtex.cpp
new file mode 100644
index 0000000..240754d
--- /dev/null
+++ b/src/fileexporterbibtex.cpp
@@ -0,0 +1,491 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <file.h>
+#include <element.h>
+#include <entry.h>
+#include <macro.h>
+#include <preamble.h>
+#include <value.h>
+#include <comment.h>
+#include <encoderlatex.h>
+
+#include "fileexporterbibtex.h"
+
+namespace BibTeX
+{
+
+ FileExporterBibTeX::FileExporterBibTeX() : FileExporter(),
+ m_iconvBufferSize( 16384 ), m_stringOpenDelimiter( '"' ), m_stringCloseDelimiter( '"' ), m_keywordCasing( kcCamelCase ), m_encoding( "latex" ), m_protectCasing( FALSE ), cancelFlag( FALSE )
+ {
+ m_iconvBuffer = new char[m_iconvBufferSize];
+ }
+
+ FileExporterBibTeX::~FileExporterBibTeX()
+ {
+ delete[] m_iconvBuffer;
+ }
+
+ bool FileExporterBibTeX::save( QIODevice* iodevice, const File* bibtexfile, QStringList * /*errorLog*/ )
+ {
+ m_mutex.lock();
+ bool result = TRUE;
+
+ /**
+ * Categorize elements from the bib file into four groups,
+ * to ensure that BibTeX finds all connected elements
+ * in the correct order.
+ */
+
+ QValueList<Comment*> parameterCommentsList;
+ QValueList<Preamble*> preambleList;
+ QValueList<Macro*> macroList;
+ QValueList<Entry*> crossRefingEntryList;
+ QValueList<Element*> remainingList;
+
+ for ( File::ElementList::const_iterator it = bibtexfile->elements.begin(); it != bibtexfile->elements.end() && result && !cancelFlag; it++ )
+ {
+ Preamble *preamble = dynamic_cast<Preamble*>( *it );
+ if ( preamble != NULL )
+ preambleList.append( preamble );
+ else
+ {
+ Macro *macro = dynamic_cast<Macro*>( *it );
+ if ( macro != NULL )
+ macroList.append( macro );
+ else
+ {
+ Entry *entry = dynamic_cast<Entry*>( *it );
+ if (( entry != NULL ) && ( entry->getField( EntryField::ftCrossRef ) != NULL ) )
+ crossRefingEntryList.append( entry );
+ else
+ {
+ Comment *comment = dynamic_cast<Comment*>( *it );
+ QString commentText = QString::null;
+ /** check if this file requests a special encoding */
+ if ( comment != NULL && comment->useCommand() && (( commentText = comment->text().lower() ) ).startsWith( "x-kbibtex-encoding=" ) )
+ {
+ m_encoding = commentText.mid( 19 );
+ qDebug( "Switching encoding to <%s>", m_encoding.latin1() );
+ parameterCommentsList.append( comment );
+ }
+ else
+ remainingList.append( *it );
+ }
+ }
+ }
+ }
+
+ int totalElements = ( int ) bibtexfile->count();
+ int currentPos = 0;
+
+ const char *encodingTo = m_encoding == "latex" ? "utf-8\0" : m_encoding.append( "\0" ).ascii();
+ m_iconvHandle = iconv_open( encodingTo, "utf-8" );
+
+ /** before anything else, write parameter comments */
+ for ( QValueList<Comment*>::iterator it = parameterCommentsList.begin(); it != parameterCommentsList.end() && result && !cancelFlag; it++ )
+ {
+ result &= writeComment( *iodevice, *it );
+ emit progress( ++currentPos, totalElements );
+ }
+
+ /** first, write preambles and strings (macros) at the beginning */
+ for ( QValueList<Preamble*>::iterator it = preambleList.begin(); it != preambleList.end() && result && !cancelFlag; it++ )
+ {
+ result &= writePreamble( *iodevice, *it );
+ emit progress( ++currentPos, totalElements );
+ }
+
+ for ( QValueList<Macro*>::iterator it = macroList.begin(); it != macroList.end() && result && !cancelFlag; it++ )
+ {
+ result &= writeMacro( *iodevice, *it );
+ emit progress( ++currentPos, totalElements );
+ }
+
+ /** second, write cross-referencing elements */
+ for ( QValueList<Entry*>::iterator it = crossRefingEntryList.begin(); it != crossRefingEntryList.end() && result && !cancelFlag; it++ )
+ {
+ result &= writeEntry( *iodevice, *it );
+ emit progress( ++currentPos, totalElements );
+ }
+
+ /** third, write remaining elements */
+ for ( QValueList<Element*>::iterator it = remainingList.begin(); it != remainingList.end() && result && !cancelFlag; it++ )
+ {
+ Entry *entry = dynamic_cast<Entry*>( *it );
+ if ( entry != NULL )
+ result &= writeEntry( *iodevice, entry );
+ else
+ {
+ Comment *comment = dynamic_cast<Comment*>( *it );
+ if ( comment != NULL )
+ result &= writeComment( *iodevice, comment );
+ }
+ emit progress( ++currentPos, totalElements );
+ }
+
+ iconv_close( m_iconvHandle );
+ m_mutex.unlock();
+ return result && !cancelFlag;
+ }
+
+ bool FileExporterBibTeX::save( QIODevice* iodevice, const Element* element, QStringList * /*errorLog*/ )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+
+ const char *encodingTo = m_encoding == "latex" ? "utf-8\0" : m_encoding.append( "\0" ).ascii();
+ m_iconvHandle = iconv_open( encodingTo, "utf-8" );
+
+ const Entry *entry = dynamic_cast<const Entry*>( element );
+ if ( entry != NULL )
+ result |= writeEntry( *iodevice, entry );
+ else
+ {
+ const Macro * macro = dynamic_cast<const Macro*>( element );
+ if ( macro != NULL )
+ result |= writeMacro( *iodevice, macro );
+ else
+ {
+ const Comment * comment = dynamic_cast<const Comment*>( element );
+ if ( comment != NULL )
+ result |= writeComment( *iodevice, comment );
+ else
+ {
+ const Preamble * preamble = dynamic_cast<const Preamble*>( element );
+ if ( preamble != NULL )
+ result |= writePreamble( *iodevice, preamble );
+ }
+ }
+ }
+
+ iconv_close( m_iconvHandle );
+ m_mutex.unlock();
+ return result && !cancelFlag;
+ }
+
+ void FileExporterBibTeX::cancel()
+ {
+ cancelFlag = TRUE;
+ }
+
+ bool FileExporterBibTeX::writeEntry( QIODevice &device, const Entry* entry )
+ {
+ writeString( device, QString( "@%1{ %2" ).arg( applyKeywordCasing( entry->entryTypeString() ) ).arg( entry->id() ) );
+
+ for ( Entry::EntryFields::ConstIterator it = entry->begin(); it != entry->end(); ++it )
+ {
+ EntryField *field = *it;
+ QString text = valueToString( field->value(), field->fieldType(), field->fieldTypeName() );
+ if ( m_protectCasing && dynamic_cast<BibTeX::PlainText*>( field->value()->items.first() ) != NULL && ( field->fieldType() == EntryField::ftTitle || field->fieldType() == EntryField::ftBookTitle || field->fieldType() == EntryField::ftSeries ) )
+ addProtectiveCasing( text );
+ writeString( device, QString( ",\n\t%1 = %2" ).arg( field->fieldTypeName() ).arg( text ) );
+ }
+ writeString( device, "\n}\n\n" );
+ return TRUE;
+ }
+
+ bool FileExporterBibTeX::writeMacro( QIODevice &device, const Macro *macro )
+ {
+ QString text = valueToString( macro->value() );
+ if ( m_protectCasing )
+ addProtectiveCasing( text );
+
+ writeString( device, QString( "@%1{ %2 = %3 }\n\n" ).arg( applyKeywordCasing( "String" ) ).arg( macro->key() ).arg( text ) );
+
+ return TRUE;
+ }
+
+ bool FileExporterBibTeX::writeComment( QIODevice &device, const Comment *comment )
+ {
+ if ( !comment->useCommand() )
+ {
+ QString text = comment->text() ;
+
+ if ( m_encoding == "latex" )
+ text = EncoderLaTeX::currentEncoderLaTeX() ->encode( text );
+
+ QStringList commentLines = QStringList::split( '\n', text );
+ for ( QStringList::Iterator it = commentLines.begin(); it != commentLines.end(); it++ )
+ {
+ writeString( device, ( *it ).append( "\n" ) );
+ }
+ writeString( device, "\n" );
+ }
+ else
+ {
+ QString text = comment->text() ;
+
+ if ( m_encoding == "latex" )
+ text = EncoderLaTeX::currentEncoderLaTeX() ->encode( text );
+
+ writeString( device, QString( "@%1{%2}\n\n" ).arg( applyKeywordCasing( "Comment" ) ).arg( text ) );
+ }
+ return TRUE;
+ }
+
+ bool FileExporterBibTeX::writePreamble( QIODevice &device, const Preamble* preamble )
+ {
+ writeString( device, QString( "@%1{%2}\n\n" ).arg( applyKeywordCasing( "Preamble" ) ).arg( valueToString( preamble->value() ) ) );
+
+ return TRUE;
+ }
+
+ bool FileExporterBibTeX::writeString( QIODevice &device, const QString& text )
+ {
+ size_t utf8datasize = 1;
+ QCString utf8 = text.utf8();
+ char *utf8data = utf8.data();
+ utf8datasize = utf8.length();
+ char *outputdata = m_iconvBuffer;
+ size_t outputdatasize = m_iconvBufferSize;
+
+ size_t result = iconv( m_iconvHandle, &utf8data, &utf8datasize, &outputdata, &outputdatasize );
+ if ( result != 0 )
+ {
+ qWarning( "Cannot convert string using iconv" );
+ return false;
+ }
+
+ if ( device.writeBlock( m_iconvBuffer, m_iconvBufferSize - outputdatasize ) != ( int )( m_iconvBufferSize - outputdatasize ) )
+ {
+ qWarning( "Cannot write string to device" );
+ return false;
+ }
+
+ return true;
+ }
+
+ void FileExporterBibTeX::setStringDelimiter( const QChar& stringOpenDelimiter, const QChar& stringCloseDelimiter )
+ {
+ m_stringOpenDelimiter = stringOpenDelimiter;
+ m_stringCloseDelimiter = stringCloseDelimiter;
+ }
+
+ void FileExporterBibTeX::setKeywordCasing( const KeywordCasing keywordCasing )
+ {
+ m_keywordCasing = keywordCasing;
+ }
+
+ void FileExporterBibTeX::setEncoding( const QString& encoding )
+ {
+ m_encoding = encoding;
+ }
+
+ void FileExporterBibTeX::setEnclosingCurlyBrackets( bool protectCasing )
+ {
+ m_protectCasing = protectCasing;
+ }
+
+ QString FileExporterBibTeX::valueToString( const Value *value, const EntryField::FieldType fieldType, const QString &fieldTypeName )
+ {
+ if ( value == NULL )
+ return "";
+
+ QString result;
+ bool isFirst = TRUE;
+ EncoderLaTeX *encoder = EncoderLaTeX::currentEncoderLaTeX();
+
+ for ( QValueList<ValueItem*>::ConstIterator it = value->items.begin(); it != value->items.end(); ++it )
+ {
+ if ( !isFirst )
+ result.append( " # " );
+ else
+ isFirst = FALSE;
+
+ MacroKey *macroKey = dynamic_cast<MacroKey*>( *it );
+ if ( macroKey != NULL )
+ result.append( macroKey->text() );
+ else
+ {
+ QString text;
+ BibTeX::PersonContainer *personContainer = dynamic_cast<BibTeX::PersonContainer*>( *it );
+ BibTeX::PlainText *plainText = dynamic_cast<BibTeX::PlainText*>( *it );
+ BibTeX::KeywordContainer *keywordContainer = dynamic_cast<BibTeX::KeywordContainer*>( *it );
+
+ if ( plainText != NULL )
+ text = plainText->text();
+ else if ( keywordContainer != NULL )
+ {
+ bool first = TRUE;
+ for ( QValueList<Keyword*>::Iterator it = keywordContainer->keywords.begin(); it != keywordContainer->keywords.end(); ++it )
+ {
+ if ( !first )
+ text.append( ", " );
+ else
+ first = FALSE;
+ text.append(( *it )->text() );
+ }
+ }
+ else if ( personContainer != NULL )
+ {
+ bool first = TRUE;
+ for ( QValueList<Person*>::Iterator it = personContainer->persons.begin(); it != personContainer->persons.end(); ++it )
+ {
+ if ( !first )
+ text.append( " and " );
+ else
+ first = FALSE;
+
+ QString v = ( *it )->firstName();
+ if ( !v.isEmpty() )
+ {
+ bool requiresQuoting = requiresPersonQuoting( v, FALSE );
+ if ( requiresQuoting ) text.append( "{" );
+ text.append( v );
+ if ( requiresQuoting ) text.append( "}" );
+ text.append( " " );
+ }
+
+ v = ( *it )->lastName();
+ if ( !v.isEmpty() )
+ {
+ /** Multi-part surnames (such as "Garcia Marquez") have to be enquoted.
+ * However, "von"-Parts (as in "von Hofmannsthal") must _not_ be enquoted.
+ * Examples:
+ * -- Robson de Souza
+ * -- Hartmann von der Tann
+ * -- Ronaldo de {Assis Moreira} ("Ronaldo de Assis Moreira" works as well)
+ * -- Ailton {Goncalves da Silva}
+ * -- Gloria von {Thurn und Taxis}
+ * Thus we split the von-Parts from the surname (= everything after the first upcase char).
+ * FIXME: Make the personContainer aware of von-Parts and jr-Parts, instead.
+ */
+ QStringList list = QStringList::split( " ", v );
+ QString von;
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ QString str = *it;
+ if ( str != "others" && str[0].category() == QChar::Letter_Lowercase )
+ {
+ von += *it;
+ von += " ";
+ }
+ else
+ break;
+ }
+ if ( !von.isEmpty() )
+ {
+ text.append( von );
+ v = v.right( v.length() - von.length() );
+ }
+ bool requiresQuoting = requiresPersonQuoting( v, TRUE );
+ if ( requiresQuoting ) text.append( "{" );
+ text.append( v );
+ if ( requiresQuoting ) text.append( "}" );
+ }
+ }
+ }
+
+ if ( m_encoding == "latex" )
+ text = encoder->encodeSpecialized( text, fieldType );
+
+ if ( fieldType == EntryField::ftURL || fieldType == EntryField::ftDoi || ( fieldType == EntryField::ftUnknown && fieldTypeName.lower() == "slaccitation" ) )
+ removeBackslashQuoting( text );
+
+ /** if the text to save contains a quote char ("),
+ * force string delimiters to be curly brackets,
+ * as quote chars as string delimiters would result
+ * in parser failures
+ */
+ QChar stringOpenDelimiter = m_stringOpenDelimiter;
+ QChar stringCloseDelimiter = m_stringCloseDelimiter;
+ if ( text.contains( '"' ) && ( m_stringOpenDelimiter == '"' || m_stringCloseDelimiter == '"' ) )
+ {
+ stringOpenDelimiter = '{';
+ stringCloseDelimiter = '}';
+ }
+
+ result.append( stringOpenDelimiter ).append( text ).append( stringCloseDelimiter );
+ }
+ }
+
+ return result;
+ }
+
+ void FileExporterBibTeX::removeBackslashQuoting( QString &text )
+ {
+ text.replace( "\\&", "&" ).replace( "\\#", "#" ).replace( "\\_", "_" ).replace( "\\%", "%" );
+ }
+
+ QString FileExporterBibTeX::applyKeywordCasing( const QString &keyword )
+ {
+ switch ( m_keywordCasing )
+ {
+ case kcLowerCase: return keyword.lower();
+ case kcInitialCapital: return keyword.at( 0 ) + keyword.lower().mid( 1 );
+ case kcCapital: return keyword.upper();
+ default: return keyword;
+ }
+ }
+
+ bool FileExporterBibTeX::requiresPersonQuoting( const QString &text, bool isLastName )
+ {
+ if ( isLastName && !text.contains( " " ) )
+ /** Last name contains NO spaces, no quoting necessary */
+ return FALSE;
+ else if ( isLastName && text[0].category() == QChar::Letter_Lowercase )
+ /** Last name starts with lower case character (e.g. as in "van der Linden") */
+ return FALSE;
+ else if ( !isLastName && !text.contains( " and " ) )
+ /** First name contains no " and " no quoting necessary */
+ return FALSE;
+ else if ( text[0] != '{' || text[text.length()-1] != '}' )
+ /** as either last name contains spaces or first name contains " and " and there is no protective quoting yet, there must be a protective quoting added */
+ return TRUE;
+
+ /** check for cases like "{..}..{..}", which must be surrounded with a protective quoting, too */
+ int bracketCounter = 0;
+ for ( int i = text.length() - 1; i >= 0; --i )
+ {
+ if ( text[i] == '{' )
+ ++bracketCounter;
+ else if ( text[i] == '}' )
+ --bracketCounter;
+ if ( bracketCounter == 0 && i > 0 )
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ void FileExporterBibTeX::addProtectiveCasing( QString &text )
+ {
+ if (( text[0] != '"' || text[text.length()-1] != '"' ) && ( text[0] != '{' || text[text.length()-1] != '}' ) )
+ {
+ /** nothing to protect, as this is no text string */
+ return;
+ }
+
+ bool addBrackets = TRUE;
+
+ if ( text[1] == '{' && text[text.length() - 2] == '}' )
+ {
+ addBrackets = FALSE;
+ int count = 0;
+ for ( int i = text.length() - 2; !addBrackets && i >= 1; --i )
+ if ( text[i] == '{' )++count;
+ else if ( text[i] == '}' )--count;
+ else if ( count == 0 ) addBrackets = TRUE;
+ }
+
+ if ( addBrackets )
+ text.insert( 1, '{' ).insert( text.length(), '}' );
+ }
+
+}
diff --git a/src/fileexporterbibtex.h b/src/fileexporterbibtex.h
new file mode 100644
index 0000000..6606283
--- /dev/null
+++ b/src/fileexporterbibtex.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERBIBTEX_H
+#define BIBTEXFILEEXPORTERBIBTEX_H
+
+#include <iconv.h>
+
+#include <element.h>
+#include <entryfield.h>
+#include <fileexporter.h>
+
+class QChar;
+
+namespace BibTeX
+{
+ class Comment;
+ class Preamble;
+ class Macro;
+
+ /**
+ @author Thomas Fischer
+ */
+
+ class FileExporterBibTeX : public FileExporter
+ {
+ public:
+ enum KeywordCasing {kcLowerCase, kcInitialCapital, kcCamelCase, kcCapital};
+
+ FileExporterBibTeX();
+ ~FileExporterBibTeX();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ void setStringDelimiter( const QChar& stringOpenDelimiter, const QChar& stringCloseDelimiter );
+ void setKeywordCasing( const KeywordCasing keywordCasing );
+ void setEncoding( const QString& encoding );
+ void setEnclosingCurlyBrackets( bool protectCasing );
+
+ public slots:
+ void cancel();
+
+ private:
+ iconv_t m_iconvHandle;
+ char *m_iconvBuffer;
+ const int m_iconvBufferSize;
+
+ QChar m_stringOpenDelimiter;
+ QChar m_stringCloseDelimiter;
+ KeywordCasing m_keywordCasing;
+ QString m_encoding;
+ bool m_protectCasing;
+ bool cancelFlag;
+
+ bool writeEntry( QIODevice &device, const Entry* entry );
+ bool writeMacro( QIODevice &device, const Macro *macro );
+ bool writeComment( QIODevice &device, const Comment *comment );
+ bool writePreamble( QIODevice &device, const Preamble* preamble );
+ bool writeString( QIODevice &device, const QString& text );
+
+ QString valueToString( const Value *value, const EntryField::FieldType fieldType = EntryField::ftUnknown, const QString &fieldTypeName = QString::null );
+
+ void removeBackslashQuoting( QString &text );
+ QString applyKeywordCasing( const QString &keyword );
+ bool requiresPersonQuoting( const QString &text, bool isLastName );
+ void addProtectiveCasing( QString &text );
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterbibutils.cpp b/src/fileexporterbibutils.cpp
new file mode 100644
index 0000000..4de7aeb
--- /dev/null
+++ b/src/fileexporterbibutils.cpp
@@ -0,0 +1,259 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <qapplication.h>
+#include <qbuffer.h>
+#include <qprocess.h>
+#include <qwaitcondition.h>
+
+#include <fileexporterbibtex.h>
+#include "fileexporterbibutils.h"
+
+namespace BibTeX
+{
+
+ FileExporterBibUtils::FileExporterBibUtils( BibTeX::File::FileFormat outputFormat )
+ : FileExporter(), m_outputFormat( outputFormat ), m_bibTeXExporter( new FileExporterBibTeX() )
+ {
+ m_bibTeXExporter->setEncoding( "utf-8" );
+ m_processBuffer = new QBuffer();
+ }
+
+ FileExporterBibUtils::~FileExporterBibUtils()
+ {
+ delete m_processBuffer;
+ delete m_bibTeXExporter;
+ }
+
+ bool FileExporterBibUtils::save( QIODevice* iodevice, const Element* element, QStringList* errorLog )
+ {
+ m_cancelFlag = false;
+ QBuffer bibBuffer;
+ if ( !toBuffer( element, &bibBuffer, errorLog ) )
+ return false;
+ if ( !bufferToXMLbuffer( &bibBuffer ) || m_cancelFlag )
+ return false;
+ return !m_cancelFlag && xmlBufferToIOdevice( iodevice );
+ }
+
+ bool FileExporterBibUtils::save( QIODevice* iodevice, const File* bibtexfile, QStringList* errorLog )
+ {
+ emit progress( 0, 3 );
+ m_cancelFlag = false;
+ QBuffer bibBuffer;
+ if ( !toBuffer( bibtexfile, &bibBuffer, errorLog ) )
+ return false;
+ emit progress( 1, 3 );
+ if ( m_cancelFlag || !bufferToXMLbuffer( &bibBuffer ) )
+ return false;
+ emit progress( 2, 3 );
+ if ( m_cancelFlag || !xmlBufferToIOdevice( iodevice ) )
+ return false;
+ emit progress( 3, 3 );
+ return !m_cancelFlag;
+ }
+
+ void FileExporterBibUtils::cancel()
+ {
+ m_bibTeXExporter->cancel();
+ m_cancelFlag = true;
+ }
+
+ bool FileExporterBibUtils::toBuffer( const File *bibFile, QBuffer *buffer, QStringList* errorLog )
+ {
+ buffer->open( IO_WriteOnly );
+ bool result = m_bibTeXExporter->save( buffer, bibFile, errorLog );
+ buffer->close();
+ return result;
+ }
+
+ bool FileExporterBibUtils::toBuffer( const Element *bibElement, QBuffer *buffer, QStringList* errorLog )
+ {
+ buffer->open( IO_WriteOnly );
+ bool result = m_bibTeXExporter->save( buffer, bibElement, errorLog );
+ buffer->close();
+ return result;
+ }
+
+ bool FileExporterBibUtils::bufferToXMLbuffer( QBuffer *bibBuffer )
+ {
+ QWaitCondition wc;
+
+ m_processBuffer->open( IO_WriteOnly );
+ m_waiting = true;
+ m_process = new QProcess( QStringList::split( ' ', "bib2xml -i utf8" ) );
+ connect( m_process, SIGNAL( processExited() ), this, SLOT( wakeUp() ) );
+ connect( m_process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadyStdout() ) );
+ connect( m_process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadyStderr() ) );
+
+ m_process->start();
+ if ( m_process->isRunning() )
+ {
+ bibBuffer->open( IO_ReadOnly );
+ m_process->writeToStdin( bibBuffer->readAll() );
+ qApp->processEvents();
+ m_process->closeStdin();
+ bibBuffer->close();
+
+ int nothingHappens = 20;
+ while ( m_waiting )
+ {
+ wc.wait( 250 );
+ qApp->processEvents();
+ --nothingHappens;
+ }
+
+ if ( nothingHappens <= 0 )
+ m_process->kill();
+
+ if ( !m_process->normalExit() )
+ {
+ qDebug( "%s did not exit in a clean fashion", m_process->arguments()[0].latin1() );
+ delete m_process;
+ return false;
+ }
+ }
+ else
+ {
+ qDebug( "%s did not start", m_process->arguments()[0].latin1() );
+ delete m_process;
+ return false;
+ }
+
+ m_processBuffer->close();
+
+ delete m_process;
+ return true;
+ }
+
+ bool FileExporterBibUtils::xmlBufferToIOdevice( QIODevice *iodevice )
+ {
+ QWaitCondition wc;
+ m_waiting = true;
+
+ m_process = NULL;
+ switch ( m_outputFormat )
+ {
+ case BibTeX::File::formatISI:
+ m_process = new QProcess( QStringList::split( ' ', "xml2isi" ) );
+ break;
+ case BibTeX::File::formatWordBib:
+ m_process = new QProcess( QStringList::split( ' ', "xml2wordbib" ) );
+ break;
+ case BibTeX::File::formatAds:
+ m_process = new QProcess( QStringList::split( ' ', "xml2ads" ) );
+ break;
+ case BibTeX::File::formatEndNote:
+ m_process = new QProcess( QStringList::split( ' ', "xml2end" ) );
+ break;
+ case BibTeX::File::formatRIS:
+ m_process = new QProcess( QStringList::split( ' ', "xml2ris" ) );
+ break;
+ case BibTeX::File::formatMODS:
+ /* m_process = NULL; */
+ break;
+ default:
+ qDebug( "Cannot handle output format %i", m_outputFormat );
+ return false;
+ }
+
+ if ( m_process != NULL )
+ {
+ connect( m_process, SIGNAL( processExited() ), this, SLOT( wakeUp() ) );
+ connect( m_process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadyStdout() ) );
+ connect( m_process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadyStderr() ) );
+
+ if ( m_process->start() )
+ {
+ QBuffer *tempBuffer = m_processBuffer;
+ m_processBuffer = new QBuffer();
+
+ tempBuffer->open( IO_ReadOnly );
+ m_process->writeToStdin( tempBuffer->readAll() );
+ qApp->processEvents();
+ m_process->closeStdin();
+ tempBuffer->close();
+
+ m_processBuffer->open( IO_WriteOnly );
+ int nothingHappens = 20;
+ while ( m_waiting )
+ {
+ wc.wait( 250 );
+ qApp->processEvents();
+ --nothingHappens;
+ }
+ m_processBuffer->close();
+
+ delete tempBuffer;
+
+ if ( nothingHappens <= 0 )
+ m_process->kill();
+
+ if ( ! m_process->normalExit() )
+ {
+ delete m_process;
+ return false;
+ }
+
+ m_processBuffer->open( IO_ReadOnly );
+ iodevice->writeBlock( m_processBuffer->buffer() );
+ m_processBuffer->close();
+
+ delete m_process;
+ }
+ else
+ {
+ qDebug( "%s did not start", m_process->arguments()[0].latin1() );
+ delete m_process;
+ return false;
+ }
+ }
+ else
+ {
+ m_processBuffer->open( IO_ReadOnly );
+ iodevice->writeBlock( m_processBuffer->buffer() );
+ m_processBuffer->close();
+ }
+
+ return true;
+ }
+
+ void FileExporterBibUtils::wakeUp()
+ {
+ m_waiting = false;
+ }
+
+ void FileExporterBibUtils::slotReadyStdout()
+ {
+ m_processBuffer->writeBlock( m_process->readStdout() );
+ }
+
+ void FileExporterBibUtils::slotReadyStderr()
+ {
+ QByteArray ba = m_process->readStderr();
+ QTextStream bats( ba, IO_ReadOnly );
+ bats.setEncoding( QTextStream::UnicodeUTF8 );
+ qDebug( "%s", bats.read().latin1() );
+ }
+
+}
+#include "fileexporterbibutils.moc"
diff --git a/src/fileexporterbibutils.h b/src/fileexporterbibutils.h
new file mode 100644
index 0000000..978a92d
--- /dev/null
+++ b/src/fileexporterbibutils.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERBIBUTILS_H
+#define BIBTEXFILEEXPORTERBIBUTILS_H
+
+#include <fileexporter.h>
+
+class QProcess;
+class QBuffer;
+
+namespace BibTeX
+{
+ class FileExporterBibTeX;
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class FileExporterBibUtils : public FileExporter
+ {
+ Q_OBJECT
+ public:
+ FileExporterBibUtils( BibTeX::File::FileFormat outputFormat );
+ ~FileExporterBibUtils();
+
+ bool save( QIODevice* iodevice, const Element* element, QStringList* errorLog = NULL );
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList* errorLog = NULL );
+
+ public slots:
+ void cancel();
+
+ private:
+ bool m_cancelFlag;
+ BibTeX::File::FileFormat m_outputFormat;
+ FileExporterBibTeX *m_bibTeXExporter;
+
+ bool m_waiting;
+ QProcess *m_process;
+ QBuffer *m_processBuffer;
+
+ bool toBuffer( const File *bibFile, QBuffer *buffer, QStringList* errorLog);
+ bool toBuffer( const Element *bibFile, QBuffer *buffer, QStringList* errorLog);
+ bool bufferToXMLbuffer( QBuffer *buffer );
+ bool xmlBufferToIOdevice( QIODevice *iodevice );
+
+ private slots:
+ void wakeUp();
+ void slotReadyStdout();
+ void slotReadyStderr();
+ };
+
+}
+
+#endif // BIBTEXFILEEXPORTERBIBUTILS_H
diff --git a/src/fileexporterdocbook5.cpp b/src/fileexporterdocbook5.cpp
new file mode 100644
index 0000000..7a962b6
--- /dev/null
+++ b/src/fileexporterdocbook5.cpp
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qstringlist.h>
+
+#include <file.h>
+#include <fileexporterbibtex.h>
+#include "fileexporterdocbook5.h"
+
+namespace BibTeX
+{
+
+ FileExporterDocBook5::FileExporterDocBook5( const QString& classPath )
+ : FileExporterToolchain(), m_classPath( classPath )
+ {
+ bibTeXFilename = QString( workingDir ).append( "/bibtex-to-docbook5.bib" );
+ outputFilename = QString( workingDir ).append( "/bibtex-to-docbook5.bib.xml" );
+ }
+
+
+ FileExporterDocBook5::~FileExporterDocBook5()
+ {
+ // nothing
+ }
+
+ bool FileExporterDocBook5::save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, bibtexfile, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = runBib2Db5( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileExporterDocBook5::save( QIODevice* iodevice, const Element* element, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, element, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = runBib2Db5( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileExporterDocBook5::runBib2Db5( QIODevice* iodevice, QStringList *errorLog )
+ {
+ QStringList cmdLine;
+ cmdLine << "java" << "-cp" << m_classPath << "net.sf.bib2db5.DB5Converter" << "-O" << "." << "bibtex-to-docbook5.bib";
+
+ if ( runProcess( cmdLine, errorLog ) && writeFileToIODevice( outputFilename, iodevice ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+}
diff --git a/src/fileexporterdocbook5.h b/src/fileexporterdocbook5.h
new file mode 100644
index 0000000..7b5f812
--- /dev/null
+++ b/src/fileexporterdocbook5.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERDOCBOOK5_H
+#define BIBTEXFILEEXPORTERDOCBOOK5_H
+
+#include <fileexportertoolchain.h>
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterDocBook5 : public FileExporterToolchain
+ {
+ public:
+ FileExporterDocBook5(const QString& classPath);
+ ~FileExporterDocBook5();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ void setLaTeXLanguage( const QString& language );
+ void setLaTeXBibliographyStyle( const QString& bibStyle );
+
+ private:
+QString m_classPath;
+ QString bibTeXFilename;
+ QString outputFilename;
+
+ bool runBib2Db5( QIODevice* iodevice, QStringList *errorLog );
+ };
+
+
+}
+
+#endif
diff --git a/src/fileexporterexternal.cpp b/src/fileexporterexternal.cpp
new file mode 100644
index 0000000..6b7e449
--- /dev/null
+++ b/src/fileexporterexternal.cpp
@@ -0,0 +1,179 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qprocess.h>
+#include <qwaitcondition.h>
+#include <qapplication.h>
+#include <qbuffer.h>
+
+#include <fileexporterbibtex.h>
+#include <settings.h>
+#include "fileexporterexternal.h"
+
+namespace BibTeX
+{
+
+ FileExporterExternal::FileExporterExternal( Exporter exporter, File::FileFormat fileformat )
+ : FileExporter(), writeTo( NULL ), m_exporter( exporter ), m_fileformat( fileformat )
+ {
+ wc = new QWaitCondition();
+ }
+
+ FileExporterExternal::~FileExporterExternal()
+ {
+ delete wc;
+ }
+
+ bool FileExporterExternal::save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ bool result = bibtexExporter->save( &buffer, bibtexfile, errorLog );
+ buffer.close();
+ delete bibtexExporter;
+
+ if ( result )
+ result = generateOutput( buffer, iodevice );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileExporterExternal::save( QIODevice* iodevice, const Element* element, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ bool result = bibtexExporter->save( &buffer, element, errorLog );
+ buffer.close();
+ delete bibtexExporter;
+
+ if ( result )
+ result = generateOutput( buffer, iodevice );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileExporterExternal::generateOutput( QBuffer &input, QIODevice *output )
+ {
+ bool result = FALSE;
+
+ QString commandLine;
+ switch ( m_fileformat )
+ {
+ case File::formatHTML:
+ switch ( m_exporter )
+ {
+ case exporterBibTeX2HTML:
+ commandLine = "bibtex2html -s plain -a";
+ break;
+ case exporterBib2XHTML:
+ commandLine = "bib2xhtml -s plain -u";
+ break;
+ case exporterBibConv:
+ commandLine = "bibconv -informat=bibtex -outformat=html";
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ QStringList args = QStringList::split( ' ', commandLine );
+
+ writeTo = new QTextStream( output );
+ writeTo->setEncoding( QTextStream::UnicodeUTF8 );
+
+ QApplication::setOverrideCursor( Qt::waitCursor );
+
+ process = new QProcess( args );
+ connect( process, SIGNAL( processExited() ), this, SLOT( slotProcessExited() ) );
+ connect( process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadProcessOutput() ) );
+ connect( process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadProcessOutput() ) );
+ connect( process, SIGNAL( wroteToStdin() ), this, SLOT( slotWroteToStdin() ) );
+
+ if ( process->start() )
+ {
+ while ( !process->isRunning() )
+ {
+ wc->wait( 250 );
+ qApp->processEvents();
+ }
+ qApp->processEvents();
+ input.open( IO_ReadOnly );
+ QByteArray buf = input.buffer();
+ // qDebug( "buf.size=%i", buf.size() );
+ process->writeToStdin( buf );
+ input.close();
+ qApp->processEvents();
+ while ( process->isRunning() )
+ {
+ wc->wait( 250 );
+ qApp->processEvents();
+ }
+
+ result = process->normalExit();
+ }
+
+ disconnect( process, SIGNAL( wroteToStdin() ), this, SLOT( slotWroteToStdin() ) );
+ disconnect( process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadProcessOutput() ) );
+ disconnect( process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadProcessOutput() ) );
+ disconnect( process, SIGNAL( processExited() ), this, SLOT( slotProcessExited() ) );
+ delete( process );
+ process = NULL;
+ delete writeTo;
+ writeTo = NULL;
+
+ QApplication::restoreOverrideCursor();
+ return result;
+ }
+
+ void FileExporterExternal::slotProcessExited()
+ {
+ wc->wakeAll();
+ }
+
+ void FileExporterExternal::slotReadProcessOutput()
+ {
+ if ( writeTo != NULL )
+ while ( process->canReadLineStdout() )
+ {
+ QString line = process->readLineStdout();
+ // qDebug( "line=%s", line.latin1() );
+ ( *writeTo ) << line.latin1() << endl;
+ }
+ // while ( process->canReadLineStderr() )
+ // {
+ // QString line = process->readLineStderr();
+ // qDebug( "stderr=%s", line.latin1() );
+ // }
+ }
+
+ void FileExporterExternal::slotWroteToStdin()
+ {
+ process->closeStdin();
+ }
+}
+
+#include "fileexporterexternal.moc"
diff --git a/src/fileexporterexternal.h b/src/fileexporterexternal.h
new file mode 100644
index 0000000..463f26a
--- /dev/null
+++ b/src/fileexporterexternal.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTEREXTERNAL_H
+#define BIBTEXFILEEXPORTEREXTERNAL_H
+
+#include <fileexporter.h>
+#include <settings.h>
+
+class QWaitCondition;
+class QProcess;
+class QBuffer;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterExternal : public FileExporter
+ {
+ Q_OBJECT
+ public:
+ enum Exporter { exporterNone = 0, exporterXSLT = 1, exporterBib2XHTML = 2, exporterBibTeX2HTML = 3, exporterBibConv = 4 };
+
+ FileExporterExternal( Exporter exporter, File::FileFormat fileformat );
+ ~FileExporterExternal();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ private:
+ QWaitCondition *wc;
+ QProcess *process;
+ QTextStream *writeTo;
+ Exporter m_exporter;
+ File::FileFormat m_fileformat;
+
+ bool generateOutput( QBuffer &input, QIODevice* output );
+
+ private slots:
+ void slotProcessExited();
+ void slotReadProcessOutput();
+ void slotWroteToStdin();
+
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterpdf.cpp b/src/fileexporterpdf.cpp
new file mode 100644
index 0000000..47b8dad
--- /dev/null
+++ b/src/fileexporterpdf.cpp
@@ -0,0 +1,197 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qfile.h>
+#include <qstringlist.h>
+#include <qurl.h>
+
+#include <settings.h>
+#include <element.h>
+#include <entry.h>
+#include <fileexporterbibtex.h>
+#include "fileexporterpdf.h"
+
+namespace BibTeX
+{
+
+ FileExporterPDF::FileExporterPDF( bool embedFiles )
+ : FileExporterToolchain(), m_latexLanguage( "english" ), m_latexBibStyle( "plain" ), m_embedFiles( embedFiles )
+ {
+ laTeXFilename = QString( workingDir ).append( "/bibtex-to-pdf.tex" );
+ bibTeXFilename = QString( workingDir ).append( "/bibtex-to-pdf.bib" );
+ outputFilename = QString( workingDir ).append( "/bibtex-to-pdf.pdf" );
+ }
+
+ FileExporterPDF::~FileExporterPDF()
+ {
+ // nothing
+ }
+
+ bool FileExporterPDF::save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+ m_embeddedFileList.clear();
+ if ( m_embedFiles )
+ {
+ m_embeddedFileList.append( QString( "%1|%2" ).arg( "BibTeX source" ).arg( bibTeXFilename ) );
+ fillEmbeddedFileList( bibtexfile );
+ }
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, bibtexfile, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = generatePDF( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileExporterPDF::save( QIODevice* iodevice, const Element* element, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+ m_embeddedFileList.clear();
+ if ( m_embedFiles )
+ fillEmbeddedFileList( element );
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, element, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = generatePDF( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ void FileExporterPDF::setLaTeXLanguage( const QString& language )
+ {
+ m_latexLanguage = language;
+ }
+
+ void FileExporterPDF::setLaTeXBibliographyStyle( const QString& bibStyle )
+ {
+ m_latexBibStyle = bibStyle;
+ }
+
+ void FileExporterPDF::setDocumentSearchPaths( const QStringList& searchPaths )
+ {
+ m_searchPaths = searchPaths;
+ }
+
+ bool FileExporterPDF::generatePDF( QIODevice* iodevice, QStringList *errorLog )
+ {
+ QStringList cmdLines = QStringList::split( '|', "pdflatex -halt-on-error bibtex-to-pdf.tex|bibtex bibtex-to-pdf|pdflatex -halt-on-error bibtex-to-pdf.tex|pdflatex -halt-on-error bibtex-to-pdf.tex" );
+
+ if ( writeLatexFile( laTeXFilename ) && runProcesses( cmdLines, errorLog ) && writeFileToIODevice( outputFilename, iodevice ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ bool FileExporterPDF::writeLatexFile( const QString &filename )
+ {
+ QFile latexFile( filename );
+ if ( latexFile.open( IO_WriteOnly ) )
+ {
+ m_embedFiles &= kpsewhich( "embedfile.sty" );
+ QTextStream ts( &latexFile );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << "\\documentclass{article}\n";
+ if ( kpsewhich( "t1enc.dfu" ) )
+ ts << "\\usepackage[T1]{fontenc}\n";
+ if ( kpsewhich( "babel.sty" ) )
+ ts << "\\usepackage[" << m_latexLanguage << "]{babel}\n";
+ if ( kpsewhich( "hyperref.sty" ) )
+ ts << "\\usepackage[pdfproducer={KBibTeX: http://www.t-fischer.net/kbibtex/},pdftex]{hyperref}\n";
+ else if ( kpsewhich( "url.sty" ) )
+ ts << "\\usepackage{url}\n";
+ if ( m_latexBibStyle.startsWith( "apacite" ) && kpsewhich( "apacite.sty" ) )
+ ts << "\\usepackage[bibnewpage]{apacite}\n";
+ if ( m_embedFiles )
+ ts << "\\usepackage{embedfile}\n";
+ ts << "\\bibliographystyle{" << m_latexBibStyle << "}\n";
+ ts << "\\begin{document}\n";
+
+ if ( m_embedFiles )
+ for ( QStringList::ConstIterator it = m_embeddedFileList.begin(); it != m_embeddedFileList.end(); ++it )
+ {
+ QStringList param = QStringList::split( "|", *it );
+ QFile file( param[1] );
+ if ( file.exists() )
+ ts << "\\embedfile[desc={" << param[0] << "}]{" << param[1] << "}\n";
+ }
+
+ ts << "\\nocite{*}\n";
+ ts << "\\bibliography{bibtex-to-pdf}\n";
+ ts << "\\end{document}\n";
+ latexFile.close();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ void FileExporterPDF::fillEmbeddedFileList( const File* bibtexfile )
+ {
+ for ( BibTeX::File::ElementList::ConstIterator it = bibtexfile->constBegin(); it != bibtexfile->constEnd(); ++it )
+ fillEmbeddedFileList( *it );
+ }
+
+ void FileExporterPDF::fillEmbeddedFileList( const Element* element )
+ {
+ const Entry *entry = dynamic_cast<const Entry*>( element );
+ if ( entry != NULL )
+ {
+ QString id = entry->id();
+ QStringList urls = entry->urls();
+ for ( QStringList::Iterator it = urls.begin(); it != urls.end(); ++it )
+ {
+ QUrl url = QUrl( *it );
+ if ( url.isValid() && url.isLocalFile() && !( *it ).endsWith( "/" ) && QFile( url.path() ).exists() )
+ m_embeddedFileList.append( QString( "%1|%2" ).arg( id ).arg( url.path() ) );
+ else
+ for ( QStringList::Iterator path_it = m_searchPaths.begin(); path_it != m_searchPaths.end(); ++path_it )
+ {
+ url = QUrl( QString( *path_it ).append( "/" ).append( *it ) );
+ if ( url.isValid() && url.isLocalFile() && !( *it ).endsWith( "/" ) && QFile( url.path() ).exists() )
+ {
+ m_embeddedFileList.append( QString( "%1|%2" ).arg( id ).arg( url.path() ) );
+ break;
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/fileexporterpdf.h b/src/fileexporterpdf.h
new file mode 100644
index 0000000..5641921
--- /dev/null
+++ b/src/fileexporterpdf.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERPDF_H
+#define BIBTEXFILEEXPORTERPDF_H
+
+#include <fileexportertoolchain.h>
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterPDF : public FileExporterToolchain
+ {
+ public:
+ FileExporterPDF( bool embedFiles = FALSE );
+ ~FileExporterPDF();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ void setLaTeXLanguage( const QString& language );
+ void setLaTeXBibliographyStyle( const QString& bibStyle );
+ void setDocumentSearchPaths( const QStringList& searchPaths );
+
+ private:
+ QString laTeXFilename;
+ QString bibTeXFilename;
+ QString outputFilename;
+ QString m_latexLanguage;
+ QString m_latexBibStyle;
+ bool m_embedFiles;
+ QStringList m_embeddedFileList;
+ QStringList m_searchPaths;
+
+ bool generatePDF( QIODevice* iodevice, QStringList *errorLog );
+ bool writeLatexFile( const QString &filename );
+ void fillEmbeddedFileList( const File* bibtexfile );
+ void fillEmbeddedFileList( const Element* element );
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterps.cpp b/src/fileexporterps.cpp
new file mode 100644
index 0000000..8627836
--- /dev/null
+++ b/src/fileexporterps.cpp
@@ -0,0 +1,135 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qfile.h>
+#include <qstringlist.h>
+
+#include <settings.h>
+#include <element.h>
+#include <fileexporterbibtex.h>
+#include "fileexporterps.h"
+
+namespace BibTeX
+{
+
+ FileExporterPS::FileExporterPS()
+ : FileExporterToolchain(), m_latexLanguage( "english" ), m_latexBibStyle( "plain" )
+ {
+ laTeXFilename = QString( workingDir ).append( "/bibtex-to-ps.tex" );
+ bibTeXFilename = QString( workingDir ).append( "/bibtex-to-ps.bib" );
+ outputFilename = QString( workingDir ).append( "/bibtex-to-ps.ps" );
+ }
+
+ FileExporterPS::~FileExporterPS()
+ {
+ // nothing
+ }
+
+ bool FileExporterPS::save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, bibtexfile, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = generatePS( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileExporterPS::save( QIODevice* iodevice, const Element* element, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, element, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = generatePS( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ void FileExporterPS::setLaTeXLanguage( const QString& language )
+ {
+ m_latexLanguage = language;
+ }
+
+ void FileExporterPS::setLaTeXBibliographyStyle( const QString& bibStyle )
+ {
+ m_latexBibStyle = bibStyle;
+ }
+
+ bool FileExporterPS::generatePS( QIODevice* iodevice, QStringList *errorLog )
+ {
+ QStringList cmdLines = QStringList::split( '|', "latex -halt-on-error bibtex-to-ps.tex|bibtex bibtex-to-ps|latex -halt-on-error bibtex-to-ps.tex|latex -halt-on-error bibtex-to-ps.tex|dvips -o bibtex-to-ps.ps bibtex-to-ps.dvi" );
+
+ if ( writeLatexFile( laTeXFilename ) && runProcesses( cmdLines, errorLog ) && writeFileToIODevice( outputFilename, iodevice ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ bool FileExporterPS::writeLatexFile( const QString &filename )
+ {
+ QFile latexFile( filename );
+ if ( latexFile.open( IO_WriteOnly ) )
+ {
+ QTextStream ts( &latexFile );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << "\\documentclass{article}\n";
+ if ( kpsewhich( "t1enc.dfu" ) )
+ ts << "\\usepackage[T1]{fontenc}\n";
+ if ( kpsewhich( "babel.sty" ) )
+ ts << "\\usepackage[" << m_latexLanguage << "]{babel}\n";
+ if ( kpsewhich( "url.sty" ) )
+ ts << "\\usepackage{url}\n";
+ if ( m_latexBibStyle.startsWith( "apacite" ) && kpsewhich( "apacite.sty" ) )
+ ts << "\\usepackage[bibnewpage]{apacite}\n";
+ ts << "\\bibliographystyle{" << m_latexBibStyle << "}\n";
+ ts << "\\begin{document}\n";
+ ts << "\\nocite{*}\n";
+ ts << "\\bibliography{bibtex-to-ps}\n";
+ ts << "\\end{document}\n";
+ latexFile.close();
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ }
+
+}
diff --git a/src/fileexporterps.h b/src/fileexporterps.h
new file mode 100644
index 0000000..b252fd7
--- /dev/null
+++ b/src/fileexporterps.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERPS_H
+#define BIBTEXFILEEXPORTERPS_H
+
+#include <fileexportertoolchain.h>
+
+class QStringList;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterPS : public FileExporterToolchain
+ {
+ public:
+ FileExporterPS();
+ ~FileExporterPS();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ void setLaTeXLanguage( const QString& language );
+ void setLaTeXBibliographyStyle( const QString& bibStyle );
+
+ private:
+ QString laTeXFilename;
+ QString bibTeXFilename;
+ QString outputFilename;
+ QString m_latexLanguage;
+ QString m_latexBibStyle;
+
+ bool generatePS( QIODevice* iodevice, QStringList *errorLog );
+ bool writeLatexFile( const QString &filename );
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterris.cpp b/src/fileexporterris.cpp
new file mode 100644
index 0000000..37908a7
--- /dev/null
+++ b/src/fileexporterris.cpp
@@ -0,0 +1,200 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qregexp.h>
+
+#include <entry.h>
+
+#include "fileexporterris.h"
+
+namespace BibTeX
+{
+
+ FileExporterRIS::FileExporterRIS() : FileExporter()
+ {
+ // nothing
+ }
+
+ FileExporterRIS::~FileExporterRIS()
+ {
+ // nothing
+ }
+
+ bool FileExporterRIS::save( QIODevice* iodevice, const Element* element, QStringList* /*errorLog*/ )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+ QTextStream stream( iodevice );
+
+ const Entry *entry = dynamic_cast<const Entry*>( element );
+ if ( entry != NULL )
+ result = writeEntry( stream, entry );
+
+ m_mutex.unlock();
+ return result && !m_cancelFlag;
+ }
+
+ bool FileExporterRIS::save( QIODevice* iodevice, const File* bibtexfile, QStringList* /*errorLog*/ )
+ {
+ m_mutex.lock();
+ bool result = TRUE;
+ m_cancelFlag = FALSE;
+ QTextStream stream( iodevice );
+
+ int numElements = (int) bibtexfile->count(), i = 0;
+ emit progress( 0, numElements );
+ for ( File::ElementList::const_iterator it = bibtexfile->elements.begin(); it != bibtexfile->elements.end() && result && !m_cancelFlag; it++ )
+ {
+ Entry *entry = dynamic_cast<Entry*>( *it );
+ if ( entry != NULL )
+ {
+ BibTeX::Entry *myEntry = bibtexfile->completeReferencedFieldsConst( entry );
+ result &= writeEntry( stream, myEntry );
+ delete myEntry;
+ }
+ emit progress( ++i, numElements );
+ }
+
+ m_mutex.unlock();
+ return result && !m_cancelFlag;
+ }
+
+ void FileExporterRIS::cancel()
+ {
+ m_cancelFlag = TRUE;
+ }
+
+ bool FileExporterRIS::writeEntry( QTextStream &stream, const Entry* entry )
+ {
+ bool result = TRUE;
+ qDebug( "Writing Entry" );
+
+ switch ( entry->entryType() )
+ {
+ case Entry::etBook:
+ writeKeyValue( stream, "TY", "BOOK" );
+ break;
+ case Entry::etInBook:
+ writeKeyValue( stream, "TY", "CHAP" );
+ break;
+ case Entry::etInProceedings:
+ writeKeyValue( stream, "TY", "CONF" );
+ break;
+ case Entry::etArticle:
+ writeKeyValue( stream, "TY", "JOUR" );
+ break;
+ case Entry::etTechReport:
+ writeKeyValue( stream, "TY", "RPRT" );
+ break;
+ case Entry::etPhDThesis:
+ writeKeyValue( stream, "TY", "THES" );
+ break;
+ default:
+ writeKeyValue( stream, "TY", "GEN" );
+ }
+
+ QString year = "";
+ QString month = "";
+
+ for ( Entry::EntryFields::ConstIterator it = entry->begin(); result && it != entry->end(); it++ )
+ {
+ EntryField *field = *it;
+
+ if ( field->fieldType() == EntryField::ftUnknown && field->fieldTypeName().startsWith( "RISfield_" ) )
+ result &= writeKeyValue( stream, field->fieldTypeName().right( 2 ), field->value()->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftAuthor )
+ {
+ QStringList authors = QStringList::split( QRegExp( "\\s+(,|and|&)\\s+", FALSE ), field->value() ->simplifiedText() );
+ for ( QStringList::Iterator it = authors.begin(); result && it != authors.end(); ++it )
+ result &= writeKeyValue( stream, "AU", *it );
+ }
+ else if ( field->fieldType() == EntryField::ftEditor )
+ {
+ QStringList authors = QStringList::split( QRegExp( "\\s+(,|and|&)\\s+", FALSE ), field->value() ->simplifiedText() );
+ for ( QStringList::Iterator it = authors.begin(); result && it != authors.end(); ++it )
+ result &= writeKeyValue( stream, "ED", *it );
+ }
+ else if ( field->fieldType() == EntryField::ftTitle )
+ result &= writeKeyValue( stream, "TI", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftJournal )
+ result &= writeKeyValue( stream, "JO", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftChapter )
+ result &= writeKeyValue( stream, "CP", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftISSN )
+ result &= writeKeyValue( stream, "SN", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftISBN )
+ result &= writeKeyValue( stream, "SN", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftVolume )
+ result &= writeKeyValue( stream, "VL", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftNumber )
+ result &= writeKeyValue( stream, "IS", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftNote )
+ result &= writeKeyValue( stream, "N1", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftAbstract )
+ result &= writeKeyValue( stream, "N2", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftPublisher )
+ result &= writeKeyValue( stream, "PB", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftLocation )
+ result &= writeKeyValue( stream, "CY", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftKeywords )
+ result &= writeKeyValue( stream, "KW", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftYear )
+ year = field->value() ->simplifiedText();
+ else if ( field->fieldType() == EntryField::ftMonth )
+ month = field->value() ->simplifiedText();
+ else if ( field->fieldType() == EntryField::ftAddress )
+ result &= writeKeyValue( stream, "AD", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftURL )
+ result &= writeKeyValue( stream, "UR", field->value() ->simplifiedText() );
+ else if ( field->fieldType() == EntryField::ftPages )
+ {
+ QStringList pageRange = QStringList::split( QRegExp( QString( "--|-|%1" ).arg( QChar( 0x2013 ) ) ), field->value() ->simplifiedText() );
+ if ( pageRange.count() == 2 )
+ {
+ result &= writeKeyValue( stream, "SP", pageRange[ 0 ] );
+ result &= writeKeyValue( stream, "EP", pageRange[ 1 ] );
+ }
+ }
+ else if ( field->fieldTypeName().lower() == "doi" )
+ result &= writeKeyValue( stream, "UR", field->value() ->simplifiedText() );
+ }
+
+ if ( !year.isEmpty() || !month.isEmpty() )
+ {
+ result &= writeKeyValue( stream, "PY", QString( "%1/%2//" ).arg( year ).arg( month ) );
+ }
+
+ result &= writeKeyValue( stream, "ER", QString() );
+ stream << endl;
+
+ return result;
+ }
+
+ bool FileExporterRIS::writeKeyValue( QTextStream &stream, const QString& key, const QString&value )
+ {
+ stream << key << " - ";
+ if ( !value.isEmpty() )
+ stream << value;
+ stream << endl;
+ qDebug( "%s - %s", key.latin1(), value.latin1() );
+
+ return TRUE;
+ }
+
+}
diff --git a/src/fileexporterris.h b/src/fileexporterris.h
new file mode 100644
index 0000000..d38107f
--- /dev/null
+++ b/src/fileexporterris.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERRIS_H
+#define BIBTEXFILEEXPORTERRIS_H
+
+#include <fileexporter.h>
+
+namespace BibTeX
+{
+
+ class FileExporterRIS : public FileExporter
+ {
+ public:
+ FileExporterRIS();
+
+ ~FileExporterRIS();
+
+ bool save( QIODevice* iodevice, const Element* element, QStringList* errorLog = NULL );
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList* errorLog = NULL );
+
+ public slots:
+ void cancel();
+
+ private:
+ bool m_cancelFlag;
+
+ bool writeEntry( QTextStream &stream, const Entry* entry );
+ bool writeKeyValue( QTextStream &stream, const QString& key, const QString&value );
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterrtf.cpp b/src/fileexporterrtf.cpp
new file mode 100644
index 0000000..2ed0c49
--- /dev/null
+++ b/src/fileexporterrtf.cpp
@@ -0,0 +1,134 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qfile.h>
+#include <qstringlist.h>
+
+#include <settings.h>
+#include <element.h>
+#include <fileexporterbibtex.h>
+#include "fileexporterrtf.h"
+
+namespace BibTeX
+{
+
+ FileExporterRTF::FileExporterRTF() : FileExporterToolchain(), m_latexLanguage( "english" ), m_latexBibStyle( "plain" )
+ {
+ laTeXFilename = QString( workingDir ).append( "/bibtex-to-rtf.tex" );
+ bibTeXFilename = QString( workingDir ).append( "/bibtex-to-rtf.bib" );
+ outputFilename = QString( workingDir ).append( "/bibtex-to-rtf.rtf" );
+ }
+
+ FileExporterRTF::~FileExporterRTF()
+ {
+ // nothing
+ }
+
+ bool FileExporterRTF::save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, bibtexfile, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = generateRTF( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileExporterRTF::save( QIODevice* iodevice, const Element* element, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ bool result = FALSE;
+
+ QFile bibtexFile( bibTeXFilename );
+ if ( bibtexFile.open( IO_WriteOnly ) )
+ {
+ FileExporter * bibtexExporter = new FileExporterBibTeX();
+ result = bibtexExporter->save( &bibtexFile, element, errorLog );
+ bibtexFile.close();
+ delete bibtexExporter;
+ }
+
+ if ( result )
+ result = generateRTF( iodevice, errorLog );
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ void FileExporterRTF::setLaTeXLanguage( const QString& language )
+ {
+ m_latexLanguage = language;
+ }
+
+ void FileExporterRTF::setLaTeXBibliographyStyle( const QString& bibStyle )
+ {
+ m_latexBibStyle = bibStyle;
+ }
+
+ bool FileExporterRTF::generateRTF( QIODevice* iodevice, QStringList *errorLog )
+ {
+ QStringList cmdLines = QStringList::split( '|', "latex bibtex-to-rtf.tex|bibtex bibtex-to-rtf|latex bibtex-to-rtf.tex|latex2rtf bibtex-to-rtf.tex" );
+
+ if ( writeLatexFile( laTeXFilename ) && runProcesses( cmdLines, errorLog ) && writeFileToIODevice( outputFilename, iodevice ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ bool FileExporterRTF::writeLatexFile( const QString &filename )
+ {
+ QFile latexFile( filename );
+ if ( latexFile.open( IO_WriteOnly ) )
+ {
+ QTextStream ts( &latexFile );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << "\\documentclass{article}\n";
+ if ( kpsewhich( "t1enc.dfu" ) )
+ ts << "\\usepackage[T1]{fontenc}\n";
+ if ( kpsewhich( "babel.sty" ) )
+ ts << "\\usepackage[" << m_latexLanguage << "]{babel}\n";
+ if ( kpsewhich( "url.sty" ) )
+ ts << "\\usepackage{url}\n";
+ if ( m_latexBibStyle.startsWith( "apacite" ) && kpsewhich( "apacite.sty" ) )
+ ts << "\\usepackage[bibnewpage]{apacite}\n";
+ ts << "\\bibliographystyle{" << m_latexBibStyle << "}\n";
+ ts << "\\begin{document}\n";
+ ts << "\\nocite{*}\n";
+ ts << "\\bibliography{bibtex-to-rtf}\n";
+ ts << "\\end{document}\n";
+ latexFile.close();
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ }
+
+}
diff --git a/src/fileexporterrtf.h b/src/fileexporterrtf.h
new file mode 100644
index 0000000..bb916e0
--- /dev/null
+++ b/src/fileexporterrtf.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERRTF_H
+#define BIBTEXFILEEXPORTERRTF_H
+
+#include <fileexportertoolchain.h>
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterRTF : public FileExporterToolchain
+ {
+ public:
+ FileExporterRTF();
+ ~FileExporterRTF();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ void setLaTeXLanguage( const QString& language );
+ void setLaTeXBibliographyStyle( const QString& bibStyle );
+
+ private:
+ QString laTeXFilename;
+ QString bibTeXFilename;
+ QString outputFilename;
+ QString m_latexLanguage;
+ QString m_latexBibStyle;
+
+ bool generateRTF( QIODevice* iodevice, QStringList *errorLog );
+ bool writeLatexFile( const QString &filename );
+ };
+
+}
+
+#endif
diff --git a/src/fileexportertoolchain.cpp b/src/fileexportertoolchain.cpp
new file mode 100644
index 0000000..8e51431
--- /dev/null
+++ b/src/fileexportertoolchain.cpp
@@ -0,0 +1,232 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+#include <qprocess.h>
+#include <qwaitcondition.h>
+#include <qapplication.h>
+#include <qstringlist.h>
+
+#include "fileexportertoolchain.h"
+
+namespace BibTeX
+{
+
+ FileExporterToolchain::FileExporterToolchain()
+ : FileExporter(), m_errorLog( NULL )
+ {
+ m_waitCond = new QWaitCondition();
+ workingDir = createTempDir();
+ }
+
+ FileExporterToolchain::~FileExporterToolchain()
+ {
+ delete m_waitCond;
+ deleteTempDir( workingDir );
+ }
+
+ bool FileExporterToolchain::runProcesses( const QStringList &progs, QStringList *errorLog )
+ {
+ bool result = TRUE;
+ int i = 0;
+
+ emit progress( 0, progs.size() );
+ for ( QStringList::ConstIterator it = progs.begin(); result && it != progs.end(); it++ )
+ {
+ qApp->processEvents();
+ QStringList args = QStringList::split( ' ', *it );
+ result &= runProcess( args, errorLog );
+ emit progress( i++, progs.size() );
+ }
+ qApp->processEvents();
+ return result;
+ }
+
+ bool FileExporterToolchain::runProcess( const QStringList &args, QStringList *errorLog )
+ {
+ bool result = FALSE;
+ QApplication::setOverrideCursor( Qt::waitCursor );
+
+ m_process = new QProcess( args );
+ m_process->setWorkingDirectory( workingDir );
+ connect( m_process, SIGNAL( processExited() ), this, SLOT( slotProcessExited() ) );
+ connect( m_process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadProcessOutput() ) );
+ connect( m_process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadProcessOutput() ) );
+
+ if ( m_process->start() )
+ {
+ m_errorLog = errorLog;
+ int counter = 0;
+ qApp->processEvents();
+ while ( m_process->isRunning() )
+ {
+ m_waitCond->wait( 250 );
+ qApp->processEvents();
+
+ counter++;
+ if ( counter > 400 )
+ m_process->tryTerminate();
+ }
+
+ result = m_process->normalExit() && counter < 400;
+ if ( !result )
+ errorLog->append( QString( "Process '%1' failed." ).arg( args.join( " " ) ) );
+ }
+ else
+ errorLog->append( QString( "Process '%1' was not started." ).arg( args.join( " " ) ) );
+
+
+ disconnect( m_process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadProcessOutput() ) );
+ disconnect( m_process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadProcessOutput() ) );
+ disconnect( m_process, SIGNAL( processExited() ), this, SLOT( slotProcessExited() ) );
+ delete( m_process );
+ m_process = NULL;
+
+ QApplication::restoreOverrideCursor();
+ return result;
+ }
+
+ bool FileExporterToolchain::writeFileToIODevice( const QString &filename, QIODevice *device )
+ {
+ QFile file( filename );
+ if ( file.open( IO_ReadOnly ) )
+ {
+ bool result = TRUE;
+ Q_ULONG buffersize = 0x10000;
+ Q_LONG amount = 0;
+ char* buffer = new char[ buffersize ];
+ do
+ {
+ result = (( amount = file.readBlock( buffer, buffersize ) ) > -1 ) && ( device->writeBlock( buffer, amount ) > -1 );
+ }
+ while ( result && amount > 0 );
+
+ file.close();
+ delete[] buffer;
+ return result;
+ }
+ else
+ return FALSE;
+ }
+
+ QString FileExporterToolchain::createTempDir()
+ {
+ QString result = QString::null;
+ QFile *devrandom = new QFile( "/dev/random" );
+
+ if ( devrandom->open( IO_ReadOnly ) )
+ {
+ Q_UINT32 randomNumber;
+ if ( devrandom->readBlock(( char* ) & randomNumber, sizeof( randomNumber ) ) > 0 )
+ {
+ randomNumber |= 0x10000000;
+ result = QString( "/tmp/bibtex-%1" ).arg( randomNumber, sizeof( randomNumber ) * 2, 16 );
+ if ( !QDir().mkdir( result ) )
+ result = QString::null;
+ }
+ devrandom->close();
+ }
+
+ delete devrandom;
+
+ return result;
+ }
+
+ void FileExporterToolchain::deleteTempDir( const QString& directory )
+ {
+ QDir dir = QDir( directory );
+ QStringList subDirs = dir.entryList( QDir::Dirs );
+ for ( QStringList::Iterator it = subDirs.begin(); it != subDirs.end(); it++ )
+ {
+ if (( QString::compare( *it, "." ) != 0 ) && ( QString::compare( *it, ".." ) != 0 ) )
+ deleteTempDir( *it );
+ }
+ QStringList allEntries = dir.entryList( QDir::All );
+ for ( QStringList::Iterator it = allEntries.begin(); it != allEntries.end(); it++ )
+ dir.remove( *it );
+
+ QDir().rmdir( directory );
+ }
+
+ void FileExporterToolchain::slotProcessExited()
+ {
+ m_waitCond->wakeAll();
+ }
+
+ void FileExporterToolchain::cancel()
+ {
+ if ( m_process != NULL )
+ {
+ qDebug( "Canceling process" );
+ m_process->tryTerminate();
+ m_process->kill();
+ m_waitCond->wakeAll();
+ }
+ }
+
+ void FileExporterToolchain::slotReadProcessOutput()
+ {
+ if ( m_process )
+ {
+ while ( m_process->canReadLineStdout() )
+ {
+ QString line = m_process->readLineStdout();
+ if ( m_errorLog != NULL )
+ m_errorLog->append( line );
+ }
+ while ( m_process->canReadLineStderr() )
+ {
+ QString line = m_process->readLineStderr();
+ if ( m_errorLog != NULL )
+ m_errorLog->append( line );
+ }
+ }
+ }
+
+ bool FileExporterToolchain::kpsewhich( const QString& filename )
+ {
+ bool result = FALSE;
+ int counter = 0;
+
+ QWaitCondition waitCond;
+ QProcess kpsewhich;
+ kpsewhich.addArgument( "kpsewhich" );
+ kpsewhich.addArgument( filename );
+ if ( kpsewhich.start() )
+ {
+ qApp->processEvents();
+ while ( kpsewhich.isRunning() )
+ {
+ waitCond.wait( 250 );
+ qApp->processEvents();
+
+ counter++;
+ if ( counter > 50 )
+ kpsewhich.tryTerminate();
+ }
+
+ result = kpsewhich.exitStatus() == 0 && counter < 50;
+ }
+
+ return result;
+ }
+
+}
+
+#include "fileexportertoolchain.moc"
diff --git a/src/fileexportertoolchain.h b/src/fileexportertoolchain.h
new file mode 100644
index 0000000..76000a1
--- /dev/null
+++ b/src/fileexportertoolchain.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERTOOLCHAIN_H
+#define BIBTEXFILEEXPORTERTOOLCHAIN_H
+
+#include <fileexporter.h>
+
+class QString;
+class QWaitCondition;
+class QProcess;
+class QStringList;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterToolchain : public FileExporter
+ {
+ Q_OBJECT
+ public:
+ FileExporterToolchain();
+ ~FileExporterToolchain();
+
+ public slots:
+ void cancel();
+
+ protected:
+ QString workingDir;
+
+ bool runProcesses( const QStringList &progs, QStringList *errorLog = NULL );
+ bool runProcess( const QStringList &args, QStringList *errorLog = NULL );
+ bool writeFileToIODevice( const QString &filename, QIODevice *device );
+ bool kpsewhich( const QString& filename );
+
+ private:
+ QWaitCondition *m_waitCond;
+ QProcess *m_process;
+ QStringList *m_errorLog;
+
+ QString createTempDir();
+ void deleteTempDir( const QString& directory );
+
+ private slots:
+ void slotProcessExited();
+ void slotReadProcessOutput();
+
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterxml.cpp b/src/fileexporterxml.cpp
new file mode 100644
index 0000000..4dcbee4
--- /dev/null
+++ b/src/fileexporterxml.cpp
@@ -0,0 +1,228 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include <file.h>
+#include <element.h>
+#include <entry.h>
+#include <encoderxml.h>
+#include <macro.h>
+#include <comment.h>
+#include "fileexporterxml.h"
+
+namespace BibTeX
+{
+
+ FileExporterXML::FileExporterXML() : FileExporter()
+ {
+ // nothing
+ }
+
+
+ FileExporterXML::~FileExporterXML()
+ {
+ // nothing
+ }
+
+ bool FileExporterXML::save( QIODevice* iodevice, const File* bibtexfile, QStringList * /*errorLog*/ )
+ {
+ m_mutex.lock();
+ bool result = TRUE;
+ m_cancelFlag = FALSE;
+ QTextStream stream( iodevice );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+
+ stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
+ stream << "<bibliography>" << endl;
+
+ int numElements = (int) bibtexfile->count(), i = 0;
+ emit progress( 0, numElements );
+ for ( File::ElementList::const_iterator it = bibtexfile->elements.begin(); it != bibtexfile->elements.end() && result && !m_cancelFlag; it++ )
+ {
+ Element *element = *it;
+ write( stream, element, bibtexfile );
+ emit progress( ++i, numElements );
+ }
+
+ stream << "</bibliography>" << endl;
+
+ m_mutex.unlock();
+ return result && !m_cancelFlag;
+ }
+
+ bool FileExporterXML::save( QIODevice* iodevice, const Element* element, QStringList * /*errorLog*/ )
+ {
+ QTextStream stream( iodevice );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+
+ stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
+ return write( stream, element );
+ }
+
+ void FileExporterXML::cancel()
+ {
+ m_cancelFlag = TRUE;
+ }
+
+ bool FileExporterXML::write( QTextStream&stream, const Element *element, const File* bibtexfile )
+ {
+ bool result = FALSE;
+
+ const Entry *entry = dynamic_cast<const Entry*>( element );
+ if ( entry != NULL )
+ {
+ if ( bibtexfile != NULL )
+ {
+ entry = bibtexfile->completeReferencedFieldsConst( entry );
+ }
+ result |= writeEntry( stream, entry );
+ if ( bibtexfile != NULL )
+ delete entry;
+ }
+ else
+ {
+ const Macro * macro = dynamic_cast<const Macro*>( element );
+ if ( macro != NULL )
+ result |= writeMacro( stream, macro );
+ else
+ {
+ const Comment * comment = dynamic_cast<const Comment*>( element );
+ if ( comment != NULL )
+ result |= writeComment( stream, comment );
+ else
+ {
+ // preambles are ignored, make no sense in XML files
+ }
+ }
+ }
+
+ return result;
+ }
+
+ bool FileExporterXML::writeEntry( QTextStream &stream, const Entry* entry )
+ {
+ stream << " <entry id=\"" << EncoderXML::currentEncoderXML() ->encode( entry->id() ) << "\" type=\"" << entry->entryTypeString().lower() << "\">" << endl;
+ for ( Entry::EntryFields::const_iterator it = entry->begin(); it != entry->end(); it++ )
+ {
+ EntryField *field = *it;
+ switch ( field->fieldType() )
+ {
+ case EntryField::ftAuthor:
+ case EntryField::ftEditor:
+ {
+ QString tag = field->fieldTypeName().lower();
+ stream << " <" << tag << "s>" << endl;
+ QStringList persons = QStringList::split( QRegExp( "\\s+(,|and|&)+\\s+", FALSE ), EncoderXML::currentEncoderXML() ->encode( valueToString( field->value() ) ) );
+ for ( QStringList::Iterator it = persons.begin(); it != persons.end(); it++ )
+ stream << " <person>" << *it << "</person>" << endl;
+ stream << " </" << tag << "s>" << endl;
+ }
+ break;
+ case EntryField::ftMonth:
+ {
+ stream << " <month";
+ bool ok = FALSE;
+
+ int month = -1;
+ QString tag = "";
+ QString content = "";
+ for ( QValueList<ValueItem*>::ConstIterator it = field->value()->items.begin(); it != field->value()->items.end(); ++it )
+ {
+ if ( dynamic_cast<MacroKey*>( *it ) != NULL )
+ {
+ for ( int i = 0; i < 12; i++ )
+ if ( QString::compare(( *it )->text(), MonthsTriple[ i ] ) == 0 )
+ {
+ if ( month < 1 )
+ {
+ tag = MonthsTriple[ i ];
+ month = i + 1;
+ }
+ content.append( Months[ i ] );
+ ok = TRUE;
+ break;
+ }
+ }
+ else
+ content.append( EncoderXML::currentEncoderXML() ->encode(( *it )->text() ) );
+ }
+
+ if ( !ok )
+ content = EncoderXML::currentEncoderXML() ->encode( field->value()->simplifiedText() ) ;
+ if ( !tag.isEmpty() )
+ stream << " tag=\"" << tag << "\"";
+ if ( month > 0 )
+ stream << " month=\"" << month << "\"";
+ stream << '>' << content;
+ stream << "</month>" << endl;
+ }
+ break;
+ default:
+ {
+ QString tag = field->fieldTypeName().lower();
+ stream << " <" << tag << ">" << EncoderXML::currentEncoderXML() ->encode( valueToString( field->value() ) ) << "</" << tag << ">" << endl;
+ }
+ break;
+ }
+
+ }
+ stream << " </entry>" << endl;
+
+ return TRUE;
+ }
+
+ bool FileExporterXML::writeMacro( QTextStream &stream, const Macro *macro )
+ {
+ stream << " <string key=\"" << macro->key() << "\">";
+ stream << EncoderXML::currentEncoderXML() ->encode( valueToString( macro->value() ) );
+ stream << "</string>" << endl;
+
+ return TRUE;
+ }
+
+ bool FileExporterXML::writeComment( QTextStream &stream, const Comment *comment )
+ {
+ stream << " <comment>" ;
+ stream << EncoderXML::currentEncoderXML() ->encode( comment->text() );
+ stream << "</comment>" << endl;
+
+ return TRUE;
+ }
+
+ QString FileExporterXML::valueToString( Value *value )
+ {
+ QString result;
+ bool isFirst = TRUE;
+
+ for ( QValueList<ValueItem*>::ConstIterator it = value->items.begin(); it != value->items.end(); it++ )
+ {
+ if ( !isFirst )
+ result.append( ' ' );
+ isFirst = FALSE;
+
+ result.append(( *it ) ->simplifiedText() );
+ }
+
+ return result;
+ }
+
+
+}
diff --git a/src/fileexporterxml.h b/src/fileexporterxml.h
new file mode 100644
index 0000000..a4eff65
--- /dev/null
+++ b/src/fileexporterxml.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERXML_H
+#define BIBTEXFILEEXPORTERXML_H
+
+#include <element.h>
+#include <fileexporter.h>
+#include <value.h>
+
+namespace BibTeX
+{
+ class Entry;
+ class Macro;
+ class Comment;
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterXML : public FileExporter
+ {
+ public:
+ FileExporterXML();
+ ~FileExporterXML();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ public slots:
+ void cancel();
+
+ private:
+ bool m_cancelFlag;
+
+ bool write( QTextStream&stream, const Element *element, const File* bibtexfile = NULL );
+ bool writeEntry( QTextStream &stream, const Entry* entry );
+ bool writeMacro( QTextStream &stream, const Macro *macro );
+ bool writeComment( QTextStream &stream, const Comment *comment );
+
+ QString valueToString( Value *value );
+ };
+
+}
+
+#endif
diff --git a/src/fileexporterxslt.cpp b/src/fileexporterxslt.cpp
new file mode 100644
index 0000000..a5a3255
--- /dev/null
+++ b/src/fileexporterxslt.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qbuffer.h>
+
+#include <fileexporterxml.h>
+#include <xsltransform.h>
+
+#include "fileexporterxslt.h"
+
+namespace BibTeX
+{
+
+ FileExporterXSLT::FileExporterXSLT( XSLTransform *transformer )
+ : FileExporter()
+ {
+ m_transformer = transformer;
+ m_exporterXML = new FileExporterXML();
+ }
+
+
+ FileExporterXSLT::~FileExporterXSLT()
+ {
+ delete m_exporterXML;
+ }
+
+ bool FileExporterXSLT::save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ QBuffer buffer;
+
+ buffer.open( IO_WriteOnly );
+ if ( m_exporterXML->save( &buffer, bibtexfile, errorLog ) )
+ {
+ buffer.close();
+ buffer.open( IO_ReadOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ QString xml = ts.read();
+ buffer.close();
+ QString html = m_transformer->transform( xml );
+ QTextStream htmlTS( iodevice );
+ htmlTS.setEncoding( QTextStream::UnicodeUTF8 );
+ htmlTS << html << endl;
+ m_mutex.unlock();
+ return TRUE;
+ }
+
+ m_mutex.unlock();
+ return FALSE;
+ }
+
+ bool FileExporterXSLT::save( QIODevice* iodevice, const Element* element, QStringList *errorLog )
+ {
+ m_mutex.lock();
+ QBuffer buffer;
+
+ buffer.open( IO_WriteOnly );
+ if ( m_exporterXML->save( &buffer, element, errorLog ) )
+ {
+ buffer.close();
+ buffer.open( IO_ReadOnly );
+ QTextStream xmlTS( &buffer );
+ xmlTS.setEncoding( QTextStream::UnicodeUTF8 );
+ QString xml = xmlTS.read();
+ buffer.close();
+ QString html = m_transformer->transform( xml );
+ QTextStream output( iodevice );
+ output.setEncoding( QTextStream::UnicodeUTF8 );
+ output << html << endl;
+ m_mutex.unlock();
+ return TRUE;
+ }
+
+ m_mutex.unlock();
+ return FALSE;
+ }
+
+}
diff --git a/src/fileexporterxslt.h b/src/fileexporterxslt.h
new file mode 100644
index 0000000..0d11e58
--- /dev/null
+++ b/src/fileexporterxslt.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEEXPORTERXSLT_H
+#define BIBTEXFILEEXPORTERXSLT_H
+
+#include <fileexporter.h>
+
+namespace BibTeX
+{
+
+ class XSLTransform;
+ class FileExporterXML;
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileExporterXSLT : public FileExporter
+ {
+ public:
+ FileExporterXSLT( XSLTransform *transformer );
+ ~FileExporterXSLT();
+
+ bool save( QIODevice* iodevice, const File* bibtexfile, QStringList *errorLog = NULL );
+ bool save( QIODevice* iodevice, const Element* element, QStringList *errorLog = NULL );
+
+ private:
+ XSLTransform *m_transformer;
+ FileExporterXML *m_exporterXML;
+ };
+
+}
+
+#endif
diff --git a/src/fileimporter.cpp b/src/fileimporter.cpp
new file mode 100644
index 0000000..65ee792
--- /dev/null
+++ b/src/fileimporter.cpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qbuffer.h>
+
+#include "fileimporter.h"
+
+namespace BibTeX
+{
+
+ FileImporter::FileImporter() : QObject()
+ {
+ // nothing
+ }
+
+ FileImporter::~FileImporter()
+ {
+ // nothing
+ }
+
+ File* FileImporter::load( const QString& text )
+ {
+ if ( text.isNull() || text.isEmpty() )
+ return NULL;
+
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ QTextStream stream( &buffer );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ stream << text;
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ File *result = load( &buffer );
+ buffer.close();
+
+ return result;
+ }
+
+}
+#include "fileimporter.moc"
diff --git a/src/fileimporter.h b/src/fileimporter.h
new file mode 100644
index 0000000..6dfdb2d
--- /dev/null
+++ b/src/fileimporter.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEIMPORTER_H
+#define BIBTEXFILEIMPORTER_H
+
+#include <qobject.h>
+#include <qmutex.h>
+
+class QIODevice;
+
+namespace BibTeX
+{
+ class File;
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileImporter : public QObject
+ {
+ Q_OBJECT
+ public:
+ FileImporter();
+ ~FileImporter();
+
+ File* load( const QString& text );
+ virtual File* load( QIODevice *iodevice ) = 0;
+
+ static bool guessCanDecode( const QString & )
+ {
+ return FALSE;
+ };
+
+ signals:
+ void parseError( int errorId );
+ void progress( int current, int total );
+
+ public slots:
+ virtual void cancel()
+ {
+ // nothing
+ };
+
+ protected:
+ QMutex m_mutex;
+ };
+
+}
+
+#endif
diff --git a/src/fileimporterbibtex.cpp b/src/fileimporterbibtex.cpp
new file mode 100644
index 0000000..5312f0c
--- /dev/null
+++ b/src/fileimporterbibtex.cpp
@@ -0,0 +1,658 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qiodevice.h>
+#include <qregexp.h>
+#include <qapplication.h>
+
+#include <file.h>
+#include <comment.h>
+#include <macro.h>
+#include <preamble.h>
+#include <entry.h>
+#include <element.h>
+#include <encoderlatex.h>
+#include <value.h>
+
+#include "fileimporterbibtex.h"
+
+#define max(a,b) ((a)<(b)?(b):(a))
+
+namespace BibTeX
+{
+ const QString extraAlphaNumChars = QString( "?'`-_:.+/$\\\"&" );
+ const QRegExp htmlRegExp = QRegExp( "</?(a|pre)[^>]*>", false );
+
+ FileImporterBibTeX::FileImporterBibTeX( bool personFirstNameFirst, QString encoding ) : FileImporter(), m_personFirstNameFirst( personFirstNameFirst ), m_currentChar( ' ' ), m_ignoreComments( FALSE ), m_lineBufferSize( 4096 ), m_encoding( encoding )
+ {
+ cancelFlag = FALSE;
+ m_lineBuffer = new char[m_lineBufferSize];
+ m_textStream = NULL;
+ }
+
+
+ FileImporterBibTeX::~FileImporterBibTeX()
+ {
+ delete[] m_lineBuffer;
+ }
+
+ File* FileImporterBibTeX::load( QIODevice *iodevice )
+ {
+ m_mutex.lock();
+ cancelFlag = FALSE;
+
+ QString rawText;
+ const char *encodingFrom = m_encoding == "latex" ? "utf-8\0" : m_encoding.append( "\0" ).ascii();
+ iconv_t iconvHandle = iconv_open( "utf-8", encodingFrom );
+ char *convertedLine = new char[m_lineBufferSize * 4];
+ int len;
+ bool encodingOk = true;
+ while ( encodingOk && iodevice->isReadable() && ( len = iodevice->readLine( m_lineBuffer, m_lineBufferSize ) ) > 0 )
+ {
+ evaluateParameterComments( iconvHandle, m_lineBuffer );
+
+ char *raw = m_lineBuffer;
+ char *enc = convertedLine;
+ size_t encLen = m_lineBufferSize, rawLen = ( size_t )len;
+ size_t result = iconv( iconvHandle, &raw, &rawLen, &enc, &encLen );
+
+ qApp->processEvents();
+
+ if ( result != 0 )
+ {
+ QString problematic = QString( m_lineBuffer ).mid( max( 0, m_lineBufferSize - encLen - 15 ), 30 );
+ if ( problematic.isNull() || problematic.isEmpty() ) problematic = QString( m_lineBuffer );
+ qDebug( "iconv resulted in error code %i for source encoding %s, maybe file is in different encoding? Problem is somewhere here: \"%s\"", result, encodingFrom, problematic.latin1() );
+ encodingOk = false;
+ break;
+ }
+ if ( rawLen > 0 )
+ {
+ qDebug( "iconv could not convert complete string, only %i out of %i chars", len - rawLen, len );
+ encodingOk = false;
+ break;
+ }
+ enc[0] = '\0';
+
+ /** remove leading UTF-8 byte-order mark (BOM) */
+ int offset = 0;
+ while (((( unsigned char )convertedLine[offset] ) == 0xef || (( unsigned char )convertedLine[offset] ) == 0xbb || (( unsigned char )convertedLine[offset] ) == 0xbf ) && offset < 4 )
+ ++offset;
+
+ QString line = QString::fromUtf8( convertedLine + offset );
+ rawText.append( line );
+ }
+ iconv_close( iconvHandle );
+ delete[] convertedLine;
+
+ if ( !encodingOk )
+ {
+ qDebug( "Decoding failed, cannot load file. Please fix encoding manually." );
+ m_mutex.unlock();
+ return NULL;
+ }
+
+ /** Cleaning up code comming from DBLP */
+ rawText = rawText.replace( htmlRegExp, "" );
+ rawText = EncoderLaTeX::currentEncoderLaTeX() ->decode( rawText );
+ unescapeLaTeXChars( rawText );
+ m_textStream = new QTextStream( rawText, IO_ReadOnly );
+ m_textStream->setEncoding( QTextStream::UnicodeUTF8 );
+ m_currentLineNumber = 0;
+ m_posIntCurrentLine = 0;
+ m_currentLine = "";
+
+ File *result = new File();
+ QIODevice *streamDevice = m_textStream->device();
+ while ( !cancelFlag && !m_textStream->atEnd() )
+ {
+ emit progress( streamDevice->at(), streamDevice->size() );
+ qApp->processEvents();
+ Element * element = nextElement();
+ if ( element != NULL )
+ {
+ Comment *comment = dynamic_cast<Comment*>( element );
+ if ( !m_ignoreComments || comment == NULL )
+ result->appendElement( element );
+ else
+ delete element;
+ }
+ qApp->processEvents();
+ }
+ emit progress( streamDevice->size(), streamDevice->size() );
+
+ if ( cancelFlag )
+ {
+ qDebug( "Loading file has been canceled" );
+ delete result;
+ result = NULL;
+ }
+
+ delete m_textStream;
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileImporterBibTeX::guessCanDecode( const QString & rawText )
+ {
+ QString text = EncoderLaTeX::currentEncoderLaTeX() ->decode( rawText );
+ return text.find( QRegExp( "@\\w+\\{.+\\}" ) ) >= 0;
+ }
+
+ void FileImporterBibTeX::setIgnoreComments( bool ignoreComments )
+ {
+ m_ignoreComments = ignoreComments;
+ }
+
+ void FileImporterBibTeX::cancel()
+ {
+ cancelFlag = TRUE;
+ }
+
+ Element *FileImporterBibTeX::nextElement()
+ {
+ Token token = nextToken();
+
+ if ( token == tAt )
+ {
+ QString elementType = readSimpleString();
+ if ( elementType.lower() == "comment" )
+ return readCommentElement();
+ else if ( elementType.lower() == "string" )
+ return readMacroElement();
+ else if ( elementType.lower() == "preamble" )
+ return readPreambleElement();
+ else if ( !elementType.isEmpty() )
+ return readEntryElement( elementType );
+ else
+ {
+ qDebug( "ElementType is empty" );
+ return NULL;
+ }
+ }
+ else if ( token == tUnknown )
+ {
+ qDebug( "Unknown token near line %i, treating as comment", m_currentLineNumber );
+ return readPlainCommentElement();
+ }
+
+ if ( token != tEOF )
+ qDebug( "Don't know how to parse next token near line %i: %s", m_currentLineNumber, tokenidToString( token ).latin1() );
+
+ return NULL;
+ }
+
+ Comment *FileImporterBibTeX::readCommentElement()
+ {
+ while ( m_currentChar != '{' && m_currentChar != '(' && !m_textStream->atEnd() )
+ m_currentChar = nextChar();
+
+ return new Comment( readBracketString( m_currentChar ), TRUE );
+ }
+
+ Comment *FileImporterBibTeX::readPlainCommentElement()
+ {
+ QString result = m_currentChar;
+ result += readLine();
+ m_currentChar = nextChar();
+ while ( !m_textStream->atEnd() && m_currentChar != '@' && !m_currentChar.isSpace() )
+ {
+ result.append( '\n' ).append( m_currentChar );
+ m_currentChar = nextChar();
+ result.append( readLine() );
+ m_currentChar = nextChar();
+ }
+ return new Comment( result, FALSE );
+ }
+
+ Macro *FileImporterBibTeX::readMacroElement()
+ {
+ Token token = nextToken();
+ while ( token != tBracketOpen )
+ {
+ if ( token == tEOF )
+ {
+ qDebug( "Error in parsing unknown macro (near line %i): Opening curly brace ({) expected", m_currentLineNumber );
+ return NULL;
+ }
+ token = nextToken();
+ }
+
+ QString key = readSimpleString();
+ if ( nextToken() != tAssign )
+ {
+ qDebug( "Error in parsing macro '%s' (near line %i): Assign symbol (=) expected", key.latin1(), m_currentLineNumber );
+ return NULL;
+ }
+
+ Macro *macro = new Macro( key );
+ do
+ {
+ bool isStringKey = FALSE;
+ QString text = readString( isStringKey ).replace( QRegExp( "\\s+" ), " " );
+ if ( isStringKey )
+ macro->value()->items.append( new MacroKey( text ) );
+ else
+ macro->value()->items.append( new BibTeX::PlainText( text ) );
+
+ token = nextToken();
+ }
+ while ( token == tDoublecross );
+
+ return macro;
+ }
+
+ Preamble *FileImporterBibTeX::readPreambleElement()
+ {
+ Token token = nextToken();
+ while ( token != tBracketOpen )
+ {
+ if ( token == tEOF )
+ {
+ qDebug( "Error in parsing unknown preamble (near line %i): Opening curly brace ({) expected", m_currentLineNumber );
+ return NULL;
+ }
+ token = nextToken();
+ }
+
+ Preamble *preamble = new Preamble( );
+ do
+ {
+ bool isStringKey = FALSE;
+ QString text = readString( isStringKey ).replace( QRegExp( "\\s+" ), " " );
+ if ( isStringKey )
+ preamble->value()->items.append( new MacroKey( text ) );
+ else
+ preamble->value()->items.append( new BibTeX::PlainText( text ) );
+
+ token = nextToken();
+ }
+ while ( token == tDoublecross );
+
+ return preamble;
+ }
+
+ Entry *FileImporterBibTeX::readEntryElement( const QString& typeString )
+ {
+ Token token = nextToken();
+ while ( token != tBracketOpen )
+ {
+ if ( token == tEOF )
+ {
+ qDebug( "Error in parsing unknown entry (near line %i): Opening curly brace ({) expected", m_currentLineNumber );
+ return NULL;
+ }
+ token = nextToken();
+ }
+
+ QString key = readSimpleString();
+ Entry *entry = new Entry( typeString, key );
+
+ token = nextToken();
+ do
+ {
+ if ( token == tBracketClose || token == tEOF )
+ break;
+ else if ( token != tComma )
+ {
+ qDebug( "Error in parsing entry '%s' (near line %i): Comma symbol (,) expected but got 0x%x (token %s)", key.latin1(), m_currentLineNumber, m_currentChar.unicode(), tokenidToString( token ).latin1() );
+ delete entry;
+ return NULL;
+ }
+
+ QString fieldTypeName = readSimpleString();
+ token = nextToken();
+ if ( fieldTypeName == QString::null || token == tBracketClose )
+ {
+ // entry is buggy, but we still accept it
+ break;
+ }
+ else if ( token != tAssign )
+ {
+ qDebug( "Error in parsing entry '%s' (near line %i): Assign symbol (=) expected after field name '%s'", key.latin1(), m_currentLineNumber, fieldTypeName.latin1() );
+ delete entry;
+ return NULL;
+ }
+
+ /** check for duplicate fields */
+ if ( entry->getField( fieldTypeName ) != NULL )
+ {
+ int i = 1;
+ QString appendix = QString::number( i );
+ while ( entry->getField( fieldTypeName + appendix ) != NULL )
+ {
+ ++i;
+ appendix = QString::number( i );
+ }
+ fieldTypeName += appendix;
+ }
+
+ EntryField *entryField = new EntryField( fieldTypeName );
+
+ token = readValue( entryField->value(), entryField->fieldType() );
+
+ entry->addField( entryField );
+ }
+ while ( TRUE );
+
+ return entry;
+ }
+
+ FileImporterBibTeX::Token FileImporterBibTeX::nextToken()
+ {
+ if ( m_textStream->atEnd() )
+ return tEOF;
+
+ Token curToken = tUnknown;
+
+ while (( m_currentChar.isSpace() || m_currentChar == '\t' ) && !m_textStream->atEnd() )
+ m_currentChar = nextChar();
+
+ switch ( m_currentChar.latin1() )
+ {
+ case '@':
+ curToken = tAt;
+ break;
+ case '{':
+ case '(':
+ curToken = tBracketOpen;
+ break;
+ case '}':
+ case ')':
+ curToken = tBracketClose;
+ break;
+ case ',':
+ curToken = tComma;
+ break;
+ case '=':
+ curToken = tAssign;
+ break;
+ case '#':
+ curToken = tDoublecross;
+ break;
+ default:
+ if ( m_textStream->atEnd() )
+ curToken = tEOF;
+ }
+
+ if ( curToken != tUnknown && curToken != tEOF )
+ m_currentChar = nextChar();
+
+ return curToken;
+ }
+
+ QString FileImporterBibTeX::readString( bool &isStringKey )
+ {
+ while ( m_currentChar.isSpace() )
+ m_currentChar = nextChar();
+
+ isStringKey = FALSE;
+ switch ( m_currentChar.latin1() )
+ {
+ case '{':
+ case '(':
+ return readBracketString( m_currentChar );
+ case '"':
+ return readQuotedString();
+ default:
+ isStringKey = TRUE;
+ return readSimpleString();
+ }
+ }
+
+ QString FileImporterBibTeX::readSimpleString( QChar until )
+ {
+ QString result;
+
+ while ( m_currentChar.isSpace() )
+ m_currentChar = nextChar();
+
+ if ( m_currentChar.isLetterOrNumber() || extraAlphaNumChars.contains( m_currentChar ) )
+ {
+ result.append( m_currentChar );
+ m_currentChar = nextChar();
+ }
+
+ while ( !m_textStream->atEnd() )
+ {
+ if ( until != '\0' )
+ {
+ if ( m_currentChar != until )
+ result.append( m_currentChar );
+ else
+ break;
+ }
+ else
+ if ( m_currentChar.isLetterOrNumber() || extraAlphaNumChars.contains( m_currentChar ) )
+ result.append( m_currentChar );
+ else if ( m_currentChar == "," || m_currentChar == "(" || m_currentChar == ")" || m_currentChar == "{" || m_currentChar == "}" || m_currentChar == "=" || m_currentChar == "#" || m_currentChar == "@" || m_currentChar.isSpace() )
+ break;
+ else
+ {
+ qDebug( "Unknown letter or number: 0x%x", m_currentChar.unicode() );
+ // break;
+ }
+ m_currentChar = nextChar();
+ }
+ return result;
+ }
+
+ QString FileImporterBibTeX::readQuotedString()
+ {
+ QString result;
+ QChar lastChar = m_currentChar;
+ m_currentChar = nextChar();
+ while ( !m_textStream->atEnd() )
+ {
+ if ( m_currentChar != '"' || lastChar == '\\' )
+ result.append( m_currentChar );
+ else
+ break;
+ lastChar = m_currentChar;
+ m_currentChar = nextChar();
+ }
+
+ /** read character after closing " */
+ m_currentChar = nextChar();
+
+ return result;
+ }
+
+ QString FileImporterBibTeX::readLine()
+ {
+ QString result = m_currentLine.mid( m_posIntCurrentLine );
+ m_posIntCurrentLine = m_currentLine.length() + 2;
+ return result;
+ }
+
+ QString FileImporterBibTeX::readBracketString( const QChar openingBracket )
+ {
+ QString result;
+ QChar closingBracket = '}';
+ if ( openingBracket == '(' )
+ closingBracket = ')';
+ int counter = 1;
+ m_currentChar = nextChar();
+ while ( !m_textStream->atEnd() )
+ {
+ if ( m_currentChar == openingBracket )
+ counter++;
+ else if ( m_currentChar == closingBracket )
+ counter--;
+
+ if ( counter == 0 )
+ break;
+ else
+ result.append( m_currentChar );
+ m_currentChar = nextChar();
+ }
+ m_currentChar = nextChar();
+ return result;
+ }
+
+ FileImporterBibTeX::Token FileImporterBibTeX::readValue( Value *value, EntryField::FieldType fieldType )
+ {
+ Token token = tUnknown;
+
+ do
+ {
+ bool isStringKey = FALSE;
+ QString text = readString( isStringKey ).replace( QRegExp( "\\s+" ), " " );
+
+ switch ( fieldType )
+ {
+ case EntryField::ftKeywords:
+ {
+ if ( isStringKey )
+ qDebug( "WARNING: Cannot handle keywords that are macros" );
+ else
+ value->items.append( new KeywordContainer( text ) );
+ }
+ break;
+ case EntryField::ftAuthor:
+ case EntryField::ftEditor:
+ {
+ if ( isStringKey )
+ qDebug( "WARNING: Cannot handle authors/editors that are macros" );
+ else
+ {
+ QStringList persons;
+ splitPersons( text, persons );
+ PersonContainer *container = new PersonContainer( m_personFirstNameFirst );
+ for ( QStringList::ConstIterator pit = persons.constBegin(); pit != persons.constEnd(); ++pit )
+ container->persons.append( new Person( *pit, m_personFirstNameFirst ) );
+ value->items.append( container );
+ }
+ }
+ break;
+ case EntryField::ftPages:
+ text.replace( QRegExp( "\\s*--?\\s*" ), QChar( 0x2013 ) );
+ default:
+ {
+ if ( isStringKey )
+ value->items.append( new MacroKey( text ) );
+ else
+ value->items.append( new BibTeX::PlainText( text ) );
+ }
+ }
+
+ token = nextToken();
+ }
+ while ( token == tDoublecross );
+
+ return token;
+ }
+
+ void FileImporterBibTeX::unescapeLaTeXChars( QString &text )
+ {
+ text.replace( "\\&", "&" );
+ }
+
+ void FileImporterBibTeX::splitPersons( const QString& text, QStringList &persons )
+ {
+ QStringList wordList;
+ QString word;
+ int bracketCounter = 0;
+
+ for ( unsigned int pos = 0;pos < text.length();++pos )
+ {
+ if ( text[pos] == '{' )
+ ++bracketCounter;
+ else if ( text[pos] == '}' )
+ --bracketCounter;
+
+ if ( text[pos] == ' ' || text[pos] == '\n' || text[pos] == '\r' )
+ {
+ if ( word == "and" && bracketCounter == 0 )
+ {
+ persons.append( wordList.join( " " ) );
+ wordList.clear();
+ }
+ else if ( !word.isEmpty() )
+ wordList.append( word );
+
+ word = "";
+ }
+ else
+ word.append( text[pos] );
+ }
+
+ wordList.append( word );
+ persons.append( wordList.join( " " ) );
+ }
+
+ void FileImporterBibTeX::evaluateParameterComments( iconv_t &iconvHandle, const char *cline )
+ {
+ /** simple preliminary checks before expensive conversion to QString */
+ if ( cline[0] == '@' && cline[1] == 'c' )
+ {
+ QString line = QString( cline ).lower();
+ /** check if this file requests a special encoding */
+ if ( line.startsWith( "@comment{x-kbibtex-encoding=" ) && line.endsWith( "}\n" ) )
+ {
+ QString newEncoding = line.mid( 28, line.length() - 30 );
+ qDebug( "x-kbibtex-encoding=<%s>", newEncoding.latin1() );
+ if ( newEncoding == "latex" ) newEncoding = "utf-8";
+ iconv_close( iconvHandle );
+ iconvHandle = iconv_open( "utf-8", newEncoding.append( '\0' ).ascii() );
+ }
+ }
+ }
+
+ QChar FileImporterBibTeX::nextChar()
+ {
+ bool atEndOfLine = m_posIntCurrentLine >= m_currentLine.length();
+
+ while (( m_posIntCurrentLine >= m_currentLine.length() || m_currentLine.isEmpty() || m_currentLine.isNull() ) && !m_textStream->atEnd() )
+ {
+ m_currentLine = m_textStream->readLine();
+ m_posIntCurrentLine = 0;
+ ++m_currentLineNumber;
+ }
+
+ if ( atEndOfLine )
+ return QChar( ' ' );
+ else if ( m_posIntCurrentLine < m_currentLine.length() )
+ {
+ QChar result = m_currentLine[m_posIntCurrentLine];
+ ++m_posIntCurrentLine;
+ return result;
+ }
+
+ return QChar();
+ }
+
+ QString FileImporterBibTeX::tokenidToString( Token token )
+ {
+ switch ( token )
+ {
+ case tAt: return QString( "At" );
+ case tBracketClose: return QString( "BracketClose" );
+ case tBracketOpen: return QString( "BracketOpen" );
+ case tAlphaNumText: return QString( "AlphaNumText" );
+ case tAssign: return QString( "Assign" );
+ case tComma: return QString( "Comma" );
+ case tDoublecross: return QString( "Doublecross" );
+ case tEOF: return QString( "EOF" );
+ case tUnknown: return QString( "Unknown" );
+ default: return QString( "<Unknown>" );
+ }
+ }
+}
diff --git a/src/fileimporterbibtex.h b/src/fileimporterbibtex.h
new file mode 100644
index 0000000..39ab911
--- /dev/null
+++ b/src/fileimporterbibtex.h
@@ -0,0 +1,96 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEIMPORTERBIBTEX_H
+#define BIBTEXFILEIMPORTERBIBTEX_H
+
+#include <iconv.h>
+
+#include <fileimporter.h>
+#include <entryfield.h>
+
+namespace BibTeX
+{
+
+ class Element;
+ class Comment;
+ class Preamble;
+ class Macro;
+ class Entry;
+ class Value;
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileImporterBibTeX : public FileImporter
+ {
+ public:
+ FileImporterBibTeX( bool personFirstNameFirst = FALSE, QString encoding = "latex" );
+ ~FileImporterBibTeX();
+
+ File* load( QIODevice *iodevice );
+ static bool guessCanDecode( const QString & text );
+
+ void setIgnoreComments( bool ignoreComments );
+
+ public slots:
+ void cancel();
+
+ private:
+ enum Token
+ {
+ tAt = 1, tBracketOpen = 2, tBracketClose = 3, tAlphaNumText = 4, tComma = 5, tAssign = 7, tDoublecross = 8, tEOF = 9, tUnknown = 0
+ };
+
+ bool cancelFlag;
+ QTextStream *m_textStream;
+ bool m_personFirstNameFirst;
+ QChar m_currentChar;
+ bool m_ignoreComments;
+ char *m_lineBuffer;
+ const int m_lineBufferSize;
+ QString m_encoding;
+ QString m_currentLine;
+ unsigned int m_posIntCurrentLine;
+ int m_currentLineNumber;
+
+ Comment *readCommentElement();
+ Comment *readPlainCommentElement();
+ Macro *readMacroElement();
+ Preamble *readPreambleElement();
+ Entry *readEntryElement( const QString& typeString );
+ Element *nextElement();
+ Token nextToken();
+ QString readString( bool &isStringKey );
+ QString readSimpleString( QChar until = '\0' );
+ QString readQuotedString();
+ QString readLine();
+ QString readBracketString( const QChar openingBracket );
+ Token readValue( Value *value, EntryField::FieldType fieldType );
+
+ void unescapeLaTeXChars( QString &text );
+ void splitPersons( const QString& test, QStringList &persons );
+ void evaluateParameterComments( iconv_t &iconvHandle, const char *line );
+ QChar nextChar();
+ QString tokenidToString( Token token );
+ };
+
+}
+
+#endif
diff --git a/src/fileimporterbibutils.cpp b/src/fileimporterbibutils.cpp
new file mode 100644
index 0000000..bd2b622
--- /dev/null
+++ b/src/fileimporterbibutils.cpp
@@ -0,0 +1,296 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <stdio.h>
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qprocess.h>
+#include <qstringlist.h>
+#include <qbuffer.h>
+#include <qwaitcondition.h>
+#include <qapplication.h>
+
+#include <file.h>
+#include <encoderlatex.h>
+#include "fileimporterbibutils.h"
+
+namespace BibTeX
+{
+
+ FileImporterBibUtils::FileImporterBibUtils( BibTeX::File::FileFormat inputFormat )
+ : FileImporter(), m_workingDir( createTempDir() ), m_inputFormat( inputFormat ), m_bibTeXImporter( new FileImporterBibTeX( false, "utf-8" ) )
+ {
+ m_processBuffer = new QBuffer();
+ }
+
+ FileImporterBibUtils::~FileImporterBibUtils()
+ {
+ delete m_processBuffer;
+ deleteTempDir( m_workingDir );
+ delete m_bibTeXImporter;
+ }
+
+ File* FileImporterBibUtils::load( QIODevice *iodevice )
+ {
+ m_cancelFlag = false;
+ if ( !iodevice->isReadable() )
+ {
+ qDebug( "iodevice is not readable" );
+ return NULL;
+ }
+ if ( !iodevice->isOpen() )
+ {
+ qDebug( "iodevice is not open" );
+ return NULL;
+ }
+
+ if ( !iodeviceToXMLbuffer( iodevice ) || m_cancelFlag )
+ return NULL;
+
+ return xmlBufferToBibTeXFile();
+ }
+
+ bool FileImporterBibUtils::guessCanDecode( const QString & text )
+ {
+ return guessInputFormat( text ) != BibTeX::File::formatUndefined;
+ }
+
+ File::FileFormat FileImporterBibUtils::guessInputFormat( const QString &text )
+ {
+ if ( text.find( "TY - " ) >= 0 )
+ return BibTeX::File::formatRIS;
+ else if ( text.find( "%A " ) >= 0 )
+ return BibTeX::File::formatEndNote;
+ else if ( text.find( "FN ISI Export Format" ) >= 0 )
+ return BibTeX::File::formatISI;
+ else
+ return BibTeX::File::formatUndefined;
+ }
+
+ void FileImporterBibUtils::cancel()
+ {
+ m_bibTeXImporter->cancel();
+ m_cancelFlag = true;
+ }
+
+ bool FileImporterBibUtils::iodeviceToXMLbuffer( QIODevice *iodevice )
+ {
+ QWaitCondition wc;
+
+ m_processBuffer->open( IO_WriteOnly );
+ m_process = NULL;
+ switch ( m_inputFormat )
+ {
+ case BibTeX::File::formatISI:
+ m_process = new QProcess( QStringList::split( ' ', "isi2xml -i utf8 -u" ) );
+ break;
+ case BibTeX::File::formatWordBib:
+ m_process = new QProcess( QStringList::split( ' ', "wordbib2xml -i utf8 -u" ) );
+ break;
+ case BibTeX::File::formatAds:
+ m_process = new QProcess( QStringList::split( ' ', "ads2xml -i utf8 -u" ) );
+ break;
+ case BibTeX::File::formatEndNote:
+ m_process = new QProcess( QStringList::split( ' ', "end2xml -i utf8 -u" ) );
+ break;
+ case BibTeX::File::formatEndNoteXML:
+ m_process = new QProcess( QStringList::split( ' ', "endx2xml -i utf8 -u" ) );
+ break;
+ case BibTeX::File::formatRIS:
+ m_process = new QProcess( QStringList::split( ' ', "ris2xml -i utf8 -u" ) );
+ break;
+ case BibTeX::File::formatMODS:
+ /* m_process = NULL; */
+ break;
+ default:
+ qDebug( "Cannot handle input format %i", m_inputFormat );
+ return false;
+ }
+
+ if ( m_process != NULL )
+ {
+ m_waiting = true;
+ connect( m_process, SIGNAL( processExited() ), this, SLOT( wakeUp() ) );
+ connect( m_process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadyStdout() ) );
+ connect( m_process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadyStderr() ) );
+
+ m_process->start();
+ if ( m_process->isRunning() )
+ {
+ QByteArray inData = iodevice->readAll();
+ m_process->writeToStdin( inData );
+ qApp->processEvents();
+ m_process->closeStdin();
+
+ int nothingHappens = 20;
+ while ( m_waiting )
+ {
+ wc.wait( 250 );
+ qApp->processEvents();
+ --nothingHappens;
+ }
+
+ if ( nothingHappens <= 0 )
+ m_process->kill();
+
+ if ( !m_process->normalExit() )
+ {
+ qDebug( "%s did not exit in a clean fashion", m_process->arguments()[0].latin1() );
+ delete m_process;
+ return false;
+ }
+ }
+ else
+ {
+ qDebug( "%s did not start", m_process->arguments()[0].latin1() );
+ delete m_process;
+ return false;
+ }
+ }
+ else
+ {
+ m_processBuffer->writeBlock( iodevice->readAll() );
+ }
+
+ m_processBuffer->close();
+
+ delete m_process;
+ return true;
+ }
+
+ BibTeX::File* FileImporterBibUtils::xmlBufferToBibTeXFile()
+ {
+ QWaitCondition wc;
+
+ m_waiting = true;
+ m_process = new QProcess( QStringList::split( ' ', "xml2bib -i utf8 -o utf8 -sk" ) );
+ connect( m_process, SIGNAL( processExited() ), this, SLOT( wakeUp() ) );
+ connect( m_process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadyStdout() ) );
+ connect( m_process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadyStderr() ) );
+
+ if ( m_process->start() )
+ {
+ QBuffer *tempBuffer = m_processBuffer;
+ m_processBuffer = new QBuffer();
+
+ tempBuffer->open( IO_ReadOnly );
+ m_process->writeToStdin( tempBuffer->readAll() );
+ qApp->processEvents();
+ m_process->closeStdin();
+ tempBuffer->close();
+
+ m_processBuffer->open( IO_WriteOnly );
+ int nothingHappens = 20;
+ while ( m_waiting )
+ {
+ wc.wait( 250 );
+ qApp->processEvents();
+ --nothingHappens;
+ }
+ m_processBuffer->close();
+
+ if ( nothingHappens <= 0 )
+ m_process->kill();
+
+ delete tempBuffer;
+
+ if ( ! m_process->normalExit() )
+ {
+ delete m_process;
+ return NULL;
+ }
+
+ m_processBuffer->open( IO_ReadOnly );
+ File *bibTeXFile = m_bibTeXImporter->load( m_processBuffer );
+ m_processBuffer->close();
+
+ delete m_process;
+ return bibTeXFile;
+ }
+ else
+ {
+ delete m_process;
+ return NULL;
+ }
+
+ delete m_process;
+ return NULL;
+ }
+
+ QString FileImporterBibUtils::createTempDir()
+ {
+ QString result = QString::null;
+ QFile *devrandom = new QFile( "/dev/random" );
+
+ if ( devrandom->open( IO_ReadOnly ) )
+ {
+ Q_UINT32 randomNumber;
+ if ( devrandom->readBlock(( char* ) & randomNumber, sizeof( randomNumber ) ) > 0 )
+ {
+ randomNumber |= 0x10000000;
+ result = QString( "/tmp/bibtex-%1" ).arg( randomNumber, sizeof( randomNumber ) * 2, 16 );
+ if ( !QDir().mkdir( result ) )
+ result = QString::null;
+ }
+ devrandom->close();
+ }
+
+ delete devrandom;
+
+ return result;
+ }
+
+ void FileImporterBibUtils::deleteTempDir( const QString& directory )
+ {
+ QDir dir = QDir( directory );
+ QStringList subDirs = dir.entryList( QDir::Dirs );
+ for ( QStringList::Iterator it = subDirs.begin(); it != subDirs.end(); it++ )
+ {
+ if (( QString::compare( *it, "." ) != 0 ) && ( QString::compare( *it, ".." ) != 0 ) )
+ deleteTempDir( *it );
+ }
+ QStringList allEntries = dir.entryList( QDir::All );
+ for ( QStringList::Iterator it = allEntries.begin(); it != allEntries.end(); it++ )
+ dir.remove( *it );
+
+ QDir().rmdir( directory );
+ }
+
+ void FileImporterBibUtils::wakeUp()
+ {
+ m_waiting = false;
+ }
+
+ void FileImporterBibUtils::slotReadyStdout()
+ {
+ m_processBuffer->writeBlock( m_process->readStdout() );
+ }
+
+ void FileImporterBibUtils::slotReadyStderr()
+ {
+ QByteArray ba = m_process->readStderr();
+ QTextStream bats( ba, IO_ReadOnly );
+ bats.setEncoding( QTextStream::UnicodeUTF8 );
+ qDebug( "%s", bats.read().latin1() );
+ }
+
+}
+#include "fileimporterbibutils.moc"
+
diff --git a/src/fileimporterbibutils.h b/src/fileimporterbibutils.h
new file mode 100644
index 0000000..8fd0635
--- /dev/null
+++ b/src/fileimporterbibutils.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef BIBTEXFILEIMPORTBIBUTILS_H
+#define BIBTEXFILEIMPORTBIBUTILS_H
+
+#include <file.h>
+#include <fileimporter.h>
+#include <fileimporterbibtex.h>
+
+class QBuffer;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class FileImporterBibUtils : public FileImporter
+ {
+ Q_OBJECT
+ public:
+ FileImporterBibUtils( BibTeX::File::FileFormat inputFormat );
+ ~FileImporterBibUtils();
+
+ File* load( QIODevice *iodevice );
+ static bool guessCanDecode( const QString & text );
+ static File::FileFormat guessInputFormat( const QString &text );
+
+ public slots:
+ void cancel();
+
+ private:
+ bool m_cancelFlag;
+ QString m_workingDir;
+ BibTeX::File::FileFormat m_inputFormat;
+ FileImporterBibTeX *m_bibTeXImporter;
+
+ bool m_waiting;
+ QProcess *m_process;
+ QBuffer *m_processBuffer;
+
+ bool iodeviceToXMLbuffer( QIODevice *iodevice );
+ File* xmlBufferToBibTeXFile();
+ QString createTempDir();
+ void deleteTempDir( const QString& directory );
+
+ private slots:
+ void wakeUp();
+ void slotReadyStdout();
+ void slotReadyStderr();
+ };
+
+}
+
+#endif // BIBTEXFILEIMPORTBIBUTILS_H
diff --git a/src/fileimporterexternal.cpp b/src/fileimporterexternal.cpp
new file mode 100644
index 0000000..3b23946
--- /dev/null
+++ b/src/fileimporterexternal.cpp
@@ -0,0 +1,150 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qprocess.h>
+#include <qwaitcondition.h>
+#include <qapplication.h>
+#include <qbuffer.h>
+
+#include <fileimporterbibtex.h>
+#include "fileimporterexternal.h"
+
+namespace BibTeX
+{
+
+ FileImporterExternal::FileImporterExternal( Importer importer, File::FileFormat fileformat )
+ : FileImporter(), m_importer( importer ), m_fileformat( fileformat )
+ {
+ wc = new QWaitCondition();
+ }
+
+
+ FileImporterExternal::~FileImporterExternal()
+ {
+ delete wc;
+ }
+
+ File* FileImporterExternal::load( QIODevice *iodevice )
+ {
+ m_mutex.lock();
+ File * result = NULL;
+ QBuffer buffer;
+
+ if ( fetchInput( iodevice, buffer ) )
+ {
+ buffer.open( IO_ReadOnly );
+ FileImporter * bibtexImporter = new FileImporterBibTeX();
+ result = bibtexImporter->load( &buffer );
+ buffer.close();
+ delete bibtexImporter;
+ }
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ void FileImporterExternal::cancel()
+ {
+ if ( process != NULL )
+ process->kill();
+ }
+
+ bool FileImporterExternal::fetchInput( QIODevice *input, QBuffer &output )
+ {
+ bool result = FALSE;
+
+ QString commandLine;
+ switch ( m_fileformat )
+ {
+ default:
+ return FALSE;
+ }
+ QStringList args = QStringList::split( ' ', commandLine );
+
+ output.open( IO_WriteOnly );
+ writeTo = new QTextStream( &output );
+ writeTo->setEncoding( QTextStream::UnicodeUTF8 );
+
+ QApplication::setOverrideCursor( Qt::waitCursor );
+
+ process = new QProcess( args );
+ connect( process, SIGNAL( processExited() ), this, SLOT( slotProcessExited() ) );
+ connect( process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadProcessOutput() ) );
+ connect( process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadProcessOutput() ) );
+ connect( process, SIGNAL( wroteToStdin() ), this, SLOT( slotWroteToStdin() ) );
+
+ if ( process->start() )
+ {
+ while ( !process->isRunning() )
+ {
+ wc->wait( 250 );
+ qApp->processEvents();
+ }
+ qApp->processEvents();
+ QByteArray buf = input->readAll();
+ process->writeToStdin( buf );
+ qApp->processEvents();
+ while ( process->isRunning() )
+ {
+ wc->wait( 250 );
+ qApp->processEvents();
+ }
+
+ result = process->normalExit();
+ }
+
+ disconnect( process, SIGNAL( wroteToStdin() ), this, SLOT( slotWroteToStdin() ) );
+ disconnect( process, SIGNAL( readyReadStdout() ), this, SLOT( slotReadProcessOutput() ) );
+ disconnect( process, SIGNAL( readyReadStderr() ), this, SLOT( slotReadProcessOutput() ) );
+ disconnect( process, SIGNAL( processExited() ), this, SLOT( slotProcessExited() ) );
+ delete( process );
+ process = NULL;
+ delete writeTo;
+ writeTo = NULL;
+ output.close();
+
+ QApplication::restoreOverrideCursor();
+ return result;
+ }
+
+ void FileImporterExternal::slotProcessExited()
+ {
+ wc->wakeAll();
+ }
+
+ void FileImporterExternal::slotReadProcessOutput()
+ {
+ if ( writeTo != NULL )
+ while ( process->canReadLineStdout() )
+ {
+ QString line = process->readLineStdout();
+ // qDebug( "line=%s", line.latin1() );
+ ( *writeTo ) << line.latin1();
+ ( *writeTo ) << endl;
+ }
+ }
+
+ void FileImporterExternal::slotWroteToStdin()
+ {
+ process->closeStdin();
+ }
+
+
+}
+#include "fileimporterexternal.moc"
diff --git a/src/fileimporterexternal.h b/src/fileimporterexternal.h
new file mode 100644
index 0000000..423ee45
--- /dev/null
+++ b/src/fileimporterexternal.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEIMPORTEREXTERNAL_H
+#define BIBTEXFILEIMPORTEREXTERNAL_H
+
+#include <fileimporter.h>
+#include <file.h>
+#include <settings.h>
+
+class QWaitCondition;
+class QProcess;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer
+ */
+ class FileImporterExternal : public FileImporter
+ {
+ Q_OBJECT
+ public:
+ enum Importer {importerNone = 0, importerBibConv = 4};
+
+ FileImporterExternal( Importer importer, File::FileFormat fileformat );
+ ~FileImporterExternal();
+
+ File* load( QIODevice *iodevice );
+ // FIXME: this is a stub:
+ static bool guessCanDecode( const QString & )
+ {
+ return TRUE;
+ };
+
+ public slots:
+ void cancel();
+
+ private:
+ QWaitCondition *wc;
+ QProcess *process;
+ QTextStream *writeTo;
+ Importer m_importer;
+ File::FileFormat m_fileformat;
+
+ bool fetchInput( QIODevice *input, QBuffer &output );
+
+ private slots:
+ void slotProcessExited();
+ void slotReadProcessOutput();
+ void slotWroteToStdin();
+ };
+
+}
+
+#endif
diff --git a/src/fileimporterris.cpp b/src/fileimporterris.cpp
new file mode 100644
index 0000000..0e5e3da
--- /dev/null
+++ b/src/fileimporterris.cpp
@@ -0,0 +1,517 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qapplication.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+
+#include <entry.h>
+
+#include "fileimporterris.h"
+
+namespace BibTeX
+{
+
+ FileImporterRIS::FileImporterRIS() : FileImporter()
+ {
+ // TODO
+ }
+
+
+ FileImporterRIS::~FileImporterRIS()
+ {
+ // TODO
+ }
+
+ File* FileImporterRIS::load( QIODevice *iodevice )
+ {
+ m_mutex.lock();
+ cancelFlag = FALSE;
+ m_refNr = 0;
+ QTextStream textStream( iodevice );
+
+ File *result = new File();
+ QIODevice *streamDevice = textStream.device();
+ while ( !cancelFlag && !textStream.atEnd() )
+ {
+ emit progress( streamDevice->at(), streamDevice->size() );
+ qApp->processEvents();
+ Element * element = nextElement( textStream );
+ if ( element != NULL )
+ result->appendElement( element );
+ qApp->processEvents();
+ }
+ emit progress( streamDevice->size(), streamDevice->size() );
+
+ if ( cancelFlag )
+ {
+ delete result;
+ result = NULL;
+ }
+
+ m_mutex.unlock();
+ return result;
+ }
+
+ bool FileImporterRIS::guessCanDecode( const QString & text )
+ {
+ return text.find( "TY - " ) >= 0;
+ }
+
+ void FileImporterRIS::cancel()
+ {
+ cancelFlag = TRUE;
+ }
+
+ Element *FileImporterRIS::nextElement( QTextStream &textStream )
+ {
+ RISitemList list = readElement( textStream );
+ if ( list.empty() )
+ return NULL;
+
+ Entry::EntryType entryType = Entry::etMisc;
+ Entry *entry = new Entry( entryType, QString( "RIS_%1" ).arg( m_refNr++ ) );
+ QStringList authorList, editorList, keywordList;
+ QString journalName, abstract, startPage, endPage, date;
+ int fieldNr = 0;
+
+ for ( RISitemList::iterator it = list.begin(); it != list.end(); ++it )
+ {
+ if (( *it ).key == "TY" )
+ {
+ if (( *it ).value.startsWith( "BOOK" ) || ( *it ).value.startsWith( "SER" ) )
+ entryType = Entry::etBook;
+ else if (( *it ).value.startsWith( "CHAP" ) )
+ entryType = Entry::etInBook;
+ else if (( *it ).value.startsWith( "CONF" ) )
+ entryType = Entry::etInProceedings;
+ else if (( *it ).value.startsWith( "JFULL" ) || ( *it ).value.startsWith( "JOUR" ) || ( *it ).value.startsWith( "MGZN" ) )
+ entryType = Entry::etArticle;
+ else if (( *it ).value.startsWith( "RPRT" ) )
+ entryType = Entry::etTechReport;
+ else if (( *it ).value.startsWith( "THES" ) )
+ entryType = Entry::etPhDThesis;
+ entry->setEntryType( entryType );
+ }
+ else if (( *it ).key == "AU" || ( *it ).key == "A1" )
+ {
+ authorList.append(( *it ).value );
+ }
+ else if (( *it ).key == "ED" || ( *it ).key == "A2" )
+ {
+ editorList.append(( *it ).value );
+ }
+ else if (( *it ).key == "ID" )
+ {
+ entry->setId(( *it ).value );
+ }
+ else if (( *it ).key == "Y1" || ( *it ).key == "PY" )
+ {
+ date = ( *it ).value;
+ }
+ else if (( *it ).key == "Y2" )
+ {
+ if ( date.isEmpty() )
+ date = ( *it ).value;
+ }
+ else if (( *it ).key == "N1" /*|| ( *it ).key == "N2"*/ )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftNote );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftNote );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "N2" )
+ {
+ if ( abstract.isEmpty() )
+ abstract = ( *it ).value ;
+ }
+ else if (( *it ).key == "AB" )
+ {
+ abstract = ( *it ).value ;
+ }
+ else if (( *it ).key == "KW" )
+ {
+ QString text = ( *it ).value;
+ QRegExp splitRegExp;
+ if ( text.contains( ";" ) )
+ splitRegExp = QRegExp( "\\s*[;\\n]\\s*" );
+ else if ( text.contains( "," ) )
+ splitRegExp = QRegExp( "\\s*[,\\n]\\s*" );
+ else
+ splitRegExp = QRegExp( "\\n" );
+ QStringList newKeywords = QStringList::split( splitRegExp, text, FALSE );
+ for ( QStringList::Iterator it = newKeywords.begin(); it != newKeywords.end();
+ ++it )
+ keywordList.append( *it );
+ }
+ else if (( *it ).key == "TI" || ( *it ).key == "T1" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftTitle );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftTitle );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "T3" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftSeries );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftSeries );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "JA" || ( *it ).key == "J1" || ( *it ).key == "J2" )
+ {
+ if ( journalName.isEmpty() )
+ journalName = ( *it ).value;
+ }
+ else if (( *it ).key == "JF" || ( *it ).key == "JO" )
+ {
+ journalName = ( *it ).value;
+ }
+ else if (( *it ).key == "VL" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftVolume );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftVolume );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "CP" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftVolume );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftChapter );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "IS" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftNumber );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftNumber );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "PB" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftPublisher );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftPublisher );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "SN" )
+ {
+ BibTeX::EntryField::FieldType fieldType = entryType == Entry::etBook || entryType == Entry::etInBook ? BibTeX::EntryField::ftISBN : BibTeX::EntryField::ftISSN;
+ BibTeX::EntryField * field = entry->getField( fieldType );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( fieldType );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "CY" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftLocation );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftLocation );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "AD" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftAddress );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftAddress );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "L1" )
+ {
+ BibTeX::EntryField * field = entry->getField( "PDF" );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( "PDF" );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "UR" )
+ {
+ BibTeX::EntryField * field = NULL;
+ if (( *it ).value.contains( "dx.doi.org" ) )
+ {
+ field = entry->getField( "DOI" );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( "DOI" );
+ entry->addField( field );
+ }
+ }
+ else
+ {
+ field = entry->getField( BibTeX::EntryField::ftURL );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftURL );
+ entry->addField( field );
+ }
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ else if (( *it ).key == "SP" )
+ {
+ startPage = ( *it ).value;
+ }
+ else if (( *it ).key == "EP" )
+ {
+ endPage = ( *it ).value;
+ }
+ else
+ {
+ QString fieldName = QString( "RISfield_%1_%2" ).arg( fieldNr++ ).arg(( *it ).key.left( 2 ) );
+ BibTeX::EntryField * field = new BibTeX::EntryField( fieldName );
+ entry->addField( field );
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText(( *it ).value ) );
+ field->setValue( value );
+ }
+ }
+
+ if ( !authorList.empty() )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftAuthor );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftAuthor );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ BibTeX::PersonContainer *container = new BibTeX::PersonContainer();
+ value->items.append( container );
+ for ( QStringList::Iterator pit = authorList.begin(); pit != authorList.end();++pit )
+ container->persons.append( new BibTeX::Person( *pit ) );
+ field->setValue( value );
+ }
+
+ if ( !editorList.empty() )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftEditor );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftEditor );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ BibTeX::PersonContainer *container = new BibTeX::PersonContainer();
+ value->items.append( container );
+ for ( QStringList::Iterator pit = authorList.begin(); pit != authorList.end();++pit )
+ container->persons.append( new BibTeX::Person( *pit ) );
+ field->setValue( value );
+ }
+
+ if ( !keywordList.empty() )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftKeywords );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftKeywords );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ BibTeX::KeywordContainer *container = new BibTeX::KeywordContainer();
+ value->items.append( container );
+ for ( QStringList::Iterator pit = keywordList.begin(); pit != keywordList.end();++pit )
+ container->keywords.append( new BibTeX::Keyword( *pit ) );
+ field->setValue( value );
+ }
+
+ if ( !journalName.isEmpty() )
+ {
+ BibTeX::EntryField * field = entry->getField( entryType == Entry::etInBook || entryType == Entry::etInProceedings ? BibTeX::EntryField::ftBookTitle : BibTeX::EntryField::ftJournal );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftJournal );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText( journalName ) );
+ field->setValue( value );
+ }
+
+ if ( !abstract.isEmpty() )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftAbstract );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftAbstract );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText( abstract ) );
+ field->setValue( value );
+ }
+
+ if ( !startPage.isEmpty() || !endPage.isEmpty() )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftPages );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftPages );
+ entry->addField( field );
+ }
+ QString page;
+ if ( startPage.isEmpty() )
+ page = endPage;
+ else if ( endPage.isEmpty() )
+ page = startPage;
+ else
+ page = startPage + QChar( 0x2013 ) + endPage;
+
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText( page ) );
+ field->setValue( value );
+ }
+
+ QStringList dateFragments = QStringList::split( "/", date );
+ if ( dateFragments.count() > 0 )
+ {
+ bool ok;
+ int year = dateFragments[ 0 ].toInt( &ok );
+ if ( ok && year > 1000 && year < 3000 )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftYear );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftYear );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText( QString::number( year ) ) );
+ field->setValue( value );
+ }
+ }
+ if ( dateFragments.count() > 1 )
+ {
+ bool ok;
+ int month = dateFragments[ 0 ].toInt( &ok );
+ if ( ok && month > 0 && month < 13 )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftMonth );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftMonth );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::PlainText( QString::number( month ) ) );
+ field->setValue( value );
+ }
+ }
+
+ return entry;
+ }
+
+ FileImporterRIS::RISitemList FileImporterRIS::readElement( QTextStream &textStream )
+ {
+ RISitemList result;
+ QString line = textStream.readLine();
+ while ( !line.startsWith( "TY - " ) && !textStream.eof() )
+ line = textStream.readLine();
+ if ( textStream.eof() )
+ return result;
+
+ QString key, value;
+ while ( !line.startsWith( "ER -" ) && !textStream.eof() )
+ {
+ if ( line.mid( 2, 3 ) == " -" )
+ {
+ if ( !value.isEmpty() )
+ {
+ RISitem item;
+ item.key = key;
+ item.value = value;
+ result.append( item );
+ }
+
+ key = line.left( 2 );
+ value = line.mid( 6 ).stripWhiteSpace();
+ }
+ else if ( line.length() > 1 )
+ value += "\n" + line.stripWhiteSpace();
+
+ line = textStream.readLine();
+ }
+ if ( !value.isEmpty() )
+ {
+ RISitem item;
+ item.key = key;
+ item.value = value;
+ result.append( item );
+ }
+
+ return result;
+ }
+}
diff --git a/src/fileimporterris.h b/src/fileimporterris.h
new file mode 100644
index 0000000..11c52e9
--- /dev/null
+++ b/src/fileimporterris.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXFILEIMPORTERRIS_H
+#define BIBTEXFILEIMPORTERRIS_H
+
+#include <fileimporter.h>
+#include <entry.h>
+
+class QTextStream;
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class FileImporterRIS : public FileImporter
+ {
+ public:
+ FileImporterRIS();
+ ~FileImporterRIS();
+
+ File* load( QIODevice *iodevice );
+ static bool guessCanDecode( const QString & text );
+
+ public slots:
+ void cancel();
+
+ private:
+ typedef struct
+ {
+ QString key;
+ QString value;
+ }
+ RISitem;
+ typedef QValueList<RISitem> RISitemList;
+
+ bool cancelFlag;
+ int m_refNr;
+
+ Element *nextElement( QTextStream &textStream );
+ RISitemList readElement( QTextStream &textStream );
+ };
+
+}
+
+#endif
diff --git a/src/findduplicates.cpp b/src/findduplicates.cpp
new file mode 100644
index 0000000..ddcf5a8
--- /dev/null
+++ b/src/findduplicates.cpp
@@ -0,0 +1,444 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <math.h>
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qapplication.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprogress.h>
+
+#include <element.h>
+#include <entry.h>
+#include <file.h>
+#include <preamble.h>
+#include <macro.h>
+#include "findduplicates.h"
+
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<(b)?(a):(b))
+
+namespace KBibTeX
+{
+ const unsigned int FindDuplicates::maxDistance = 0xffffff;
+
+ FindDuplicates::FindDuplicates( DuplicateCliqueList &result, unsigned int sensitivity, BibTeX::File *file, QWidget *parent )
+ : QObject( NULL, NULL ), m_doCancel( false )
+ {
+ if ( file->count() < 2 )
+ return;
+
+ int len = file->count() * ( file->count() - 1 ) / 2;
+ unsigned int *distVector = new unsigned int[len];
+ memset( distVector, 0xff, sizeof( unsigned int )*len );
+ QMap<BibTeX::Element*, int> mapElementToIndex;
+
+ QApplication::setOverrideCursor( Qt::waitCursor );
+ KProgressDialog *progDlg = new KProgressDialog( parent, NULL, i18n( "Find Duplicates" ), i18n( "Searching for duplicates..." ), true );
+ connect( progDlg, SIGNAL( cancelClicked() ), this, SLOT( slotCancel() ) );
+ progDlg->progressBar()->setTotalSteps( len );
+
+ determineDistances( file, distVector, mapElementToIndex, progDlg );
+ progDlg->progressBar()->setValue( len );
+
+ if ( !m_doCancel )
+ buildClique( result, file, distVector, mapElementToIndex, sensitivity );
+
+ delete progDlg;
+ delete[] distVector;
+ QApplication::restoreOverrideCursor();
+ }
+
+ /**
+ * Determine the distance between elements either from two different BibTeX
+ * files (merging operation) or within the same file (find duplicates).
+ * Inter-element distances will be written into the distance vector.
+ * @param file BibTeX file
+ * @param distVector inter-element distance vector
+ * @param mapElementToIndex map from elements to indices (will be written)
+ * @param progDlg progress dialog to write status information to
+ */
+ void FindDuplicates::determineDistances( BibTeX::File *file, unsigned int *distVector, QMap<BibTeX::Element*, int> &mapElementToIndex, KProgressDialog *progDlg )
+ {
+ int progress = 0, i = 0;
+ for ( BibTeX::File::ElementList::ConstIterator it1 = file->constBegin(); !m_doCancel && it1 != file->constEnd(); ++it1, ++i )
+ {
+ BibTeX::Entry *entryA = dynamic_cast<BibTeX::Entry*>( *it1 );
+ if ( entryA != NULL )
+ {
+ mapElementToIndex.insert( entryA, i );
+
+ int j = i + 1;
+ for ( BibTeX::File::ElementList::ConstIterator it2 = ++BibTeX::File::ElementList::ConstIterator( it1 ); !m_doCancel && it2 != file->constEnd(); ++it2, ++j )
+ {
+ BibTeX::Entry *entryB = dynamic_cast<BibTeX::Entry*>( *it2 );
+ if ( entryB == NULL ) continue;
+
+ unsigned int d = entryDistance( entryA, entryB );
+ distVector[arrayOffset( i, j )] = d;
+
+ progDlg->progressBar()->setValue( ++progress );
+ qApp->processEvents();
+ }
+ }
+ else
+ {
+ BibTeX::Macro *macroA = dynamic_cast<BibTeX::Macro*>( *it1 );
+ if ( macroA != NULL )
+ {
+ mapElementToIndex.insert( macroA, i );
+
+ int j = i + 1;
+ for ( BibTeX::File::ElementList::ConstIterator it2 = ++BibTeX::File::ElementList::ConstIterator( it1 ); !m_doCancel && it2 != file->constEnd(); ++it2, ++j )
+ {
+ BibTeX::Macro *macroB = dynamic_cast<BibTeX::Macro*>( *it2 );
+ if ( macroB == NULL ) continue;
+
+ distVector[arrayOffset( i, j )] = macroDistance( macroA, macroB );
+
+ progDlg->progressBar()->setValue( ++progress );
+ qApp->processEvents();
+ }
+ }
+ else
+ {
+ BibTeX::Preamble *preambleA = dynamic_cast<BibTeX::Preamble*>( *it1 );
+ if ( preambleA != NULL )
+ {
+ mapElementToIndex.insert( preambleA, i );
+
+ int j = i + 1;
+ for ( BibTeX::File::ElementList::ConstIterator it2 = ++BibTeX::File::ElementList::ConstIterator( it1 ); !m_doCancel && it2 != file->constEnd(); ++it2, ++j )
+ {
+ BibTeX::Preamble *preambleB = dynamic_cast<BibTeX::Preamble*>( *it2 );
+ if ( preambleB == NULL ) continue;
+
+ distVector[arrayOffset( i, j )] = preambleDistance( preambleA, preambleB );
+
+ progDlg->progressBar()->setValue( ++progress );
+ qApp->processEvents();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Build a list of clique of BibTeX elements with a distance below the
+ * sensitivity threshold. The list of cliques is added to the cliqueList
+ * parameter.
+ * @param cliqueList List of cliques found in this function
+ * @param file BibTeX file
+ * @param distVector inter-element distance vector
+ * @param mapElementToIndex map from elements to indices
+ * @param sensitivity sensitivity threshold value
+ */
+ void FindDuplicates::buildClique( DuplicateCliqueList &cliqueList, BibTeX::File *file, unsigned int *distVector, QMap<BibTeX::Element*, int> &mapElementToIndex, unsigned int sensitivity )
+ {
+ int usedLen = file->count();
+ bool* used = new bool[usedLen];
+ memset( used, false, sizeof( bool ) * usedLen );
+ QValueList<BibTeX::Element*> queue;
+ for ( BibTeX::File::ElementList::ConstIterator it1 = file->constBegin(); it1 != file->constEnd(); ++it1 )
+ {
+ /** current element must be either entry, preamble, or macro */
+ BibTeX::Element *elem1 = dynamic_cast<BibTeX::Entry*>( *it1 );
+ if ( elem1 == NULL )
+ elem1 = dynamic_cast<BibTeX::Macro*>( *it1 );
+ if ( elem1 == NULL )
+ elem1 = dynamic_cast<BibTeX::Preamble*>( *it1 );
+ /** skip element otherwise or if already used */
+ if ( elem1 == NULL || used[mapElementToIndex[elem1]] ) continue;
+
+ DuplicateClique clique;
+
+ queue.clear();
+ queue.append( elem1 );
+ used[mapElementToIndex[elem1]] = true;
+
+ while ( !queue.isEmpty() )
+ {
+ elem1 = *( queue.begin() );
+ queue.remove( queue.begin() );
+ int curIndex = mapElementToIndex[elem1];
+ clique.append( elem1 );
+
+ for ( BibTeX::File::ElementList::ConstIterator it2 = file->constBegin(); it2 != file->constEnd(); ++it2 )
+ {
+ /** current element must be either entry, preamble, or macro */
+ BibTeX::Element *elem2 = dynamic_cast<BibTeX::Entry*>( *it2 );
+ int otherIndex=mapElementToIndex[elem2];
+ if ( elem2 == NULL )
+ elem2 = dynamic_cast<BibTeX::Macro*>( *it2 );
+ if ( elem2 == NULL )
+ elem2 = dynamic_cast<BibTeX::Preamble*>( *it2 );
+ /** skip element otherwise or if already used */
+ if ( elem2 == NULL || used[( otherIndex = mapElementToIndex[elem2] )] )
+ continue;
+
+ unsigned int distance = distVector[arrayOffset( curIndex, otherIndex )];
+
+ if ( distance <= sensitivity )
+ {
+ queue.append( elem2 );
+ used[otherIndex ] = true;
+ }
+ }
+ }
+
+ if ( clique.size() > 1 )
+ cliqueList.append( clique );
+ }
+ delete[] used;
+ }
+
+ /**
+ * Distance between two BibTeX entries, scaled by maxDistance.
+ */
+ unsigned int FindDuplicates::entryDistance( BibTeX::Entry *entryA, BibTeX::Entry *entryB )
+ {
+ double titleValue = levenshteinDistance( extractTitle( entryA ), extractTitle( entryB ) );
+ double authorValue = levenshteinDistance( authorsLastName( entryA ), authorsLastName( entryB ) );
+ double yearValue = extractYear( entryA ) - extractYear( entryB );
+ yearValue = min( 1.0, yearValue * yearValue / 100.0 );
+ unsigned int distance = ( unsigned int )( maxDistance * ( titleValue * 0.6 + authorValue * 0.3 + yearValue * 0.1 ) );
+
+ return distance;
+ }
+
+ /**
+ * Distance between two BibTeX macros, scaled by maxDistance.
+ */
+ unsigned int FindDuplicates::macroDistance( BibTeX::Macro *macroA, BibTeX::Macro *macroB )
+ {
+ double keyValue = levenshteinDistance( extractMacroKey( macroA ), extractMacroKey( macroB ) );
+ double valueValue = levenshteinDistance( extractMacroValue( macroA ), extractMacroValue( macroB ) );
+ unsigned int distance = ( unsigned int )( maxDistance * ( keyValue * 0.7 + valueValue * 0.3 ) );
+
+ return distance;
+ }
+
+ unsigned int FindDuplicates::preambleDistance( BibTeX::Preamble *preambleA, BibTeX::Preamble *preambleB )
+ {
+ return ( unsigned int )( maxDistance * levenshteinDistance( preambleA->value()->text(), preambleB->value()->text() ) );
+ }
+
+ FindDuplicates::~FindDuplicates()
+ {
+// nothing
+ }
+
+ /**
+ * Determine the Levenshtein distance between two sentences,
+ * where each sentence is in a string (not split into single words).
+ * See also http://en.wikipedia.org/wiki/Levenshtein_distance
+ * @param s first sentence
+ * @param t second sentence
+ * @return distance between both sentences
+ */
+ double FindDuplicates::levenshteinDistance( const QString &s, const QString &t )
+ {
+ const QRegExp nonWordRegExp( "[^a-zA-Z']+" );
+ if ( s == QString::null || t == QString::null ) return 1.0;
+ return levenshteinDistance( QStringList::split( nonWordRegExp, s ), QStringList::split( nonWordRegExp, t ) );
+ }
+
+ /**
+ * Determine the Levenshtein distance between two words.
+ * See also http://en.wikipedia.org/wiki/Levenshtein_distance
+ * @param s first word
+ * @param t second word
+ * @return distance between both words
+ */
+ double FindDuplicates::levenshteinDistanceWord( const QString &s, const QString &t )
+ {
+ QString mys = s.lower(), myt = t.lower();
+ int m = s.length(), n = t.length();
+ if ( m < 1 && n < 1 ) return 0.0;
+ if ( m < 1 || n < 1 ) return 1.0;
+
+ int **d = new int*[m+1];
+ for ( int i = 0; i <= m; ++i ) {d[i] = new int[n+1]; d[i][0] = i;}
+ for ( int i = 0; i <= n; ++i ) d[0][i] = i;
+
+ for ( int i = 1; i <= m;++i )
+ for ( int j = 1; j <= n;++j )
+ {
+ d[i][j] = d[i-1][j] + 1;
+ int c = d[i][j-1] + 1;
+ if ( c < d[i][j] ) d[i][j] = c;
+ c = d[i-1][j-1] + ( mys[i-1] == myt[j-1] ? 0 : 1 );
+ if ( c < d[i][j] ) d[i][j] = c;
+ }
+
+ double result = d[m][n];
+ for ( int i = 0; i <= m; ++i ) delete[] d[i];
+ delete [] d;
+
+ result = result / ( double )max( m, n );
+ result *= result;
+ return result;
+ }
+
+ /**
+ * Determine the Levenshtein distance between two sentences (list of words).
+ * See also http://en.wikipedia.org/wiki/Levenshtein_distance
+ * @param s first sentence
+ * @param t second sentence
+ * @return distance between both sentences
+ */
+ double FindDuplicates::levenshteinDistance( const QStringList &s, const QStringList &t )
+ {
+ int m = s.size(), n = t.size();
+ if ( m < 1 && n < 1 ) return 0.0;
+ if ( m < 1 || n < 1 ) return 1.0;
+
+ double **d = new double*[m+1];
+ for ( int i = 0; i <= m; ++i ) {d[i] = new double[n+1]; d[i][0] = i;}
+ for ( int i = 0; i <= n; ++i ) d[0][i] = i;
+
+ for ( int i = 1; i <= m;++i )
+ for ( int j = 1; j <= n;++j )
+ {
+ d[i][j] = d[i-1][j] + 1;
+ double c = d[i][j-1] + 1;
+ if ( c < d[i][j] ) d[i][j] = c;
+ c = d[i-1][j-1] + levenshteinDistanceWord( s[i-1], t[j-1] );
+ if ( c < d[i][j] ) d[i][j] = c;
+ }
+
+ double result = d[m][n];
+ for ( int i = 0; i <= m; ++i ) delete[] d[i];
+ delete [] d;
+
+ result = result / ( double )max( m, n );
+
+ return result;
+ }
+
+ /**
+ * Linearize a two-dimensional triangle matrix
+ */
+ int FindDuplicates::arrayOffset( int a, int b )
+ {
+ if ( a == b )
+ return -1;
+ else if ( b < a )
+ {
+ int swap = a;
+ a = b;
+ b = swap;
+ }
+
+ return ( b * ( b - 1 ) / 2 + a );
+ }
+
+ /**
+ * Determine title for a given entry
+ */
+ QString FindDuplicates::extractTitle( BibTeX::Entry *entry )
+ {
+ /** retrieve field holding title information for entry */
+ BibTeX::EntryField *field = entry->getField( BibTeX::EntryField::ftTitle );
+ if ( field == NULL )
+ return QString::null; /** no title field available */
+
+ /** *fetch value item holding title */
+ BibTeX::ValueItem *valueItem = field->value()->items.isEmpty() ? NULL : field->value()->items.first();
+ if ( valueItem == NULL )
+ return QString::null; /** no value item found or is empty */
+
+ return valueItem->text(); // TODO: Perform some postprocessing?
+ }
+
+ /**
+ * Determine list of authors for a given entry
+ */
+ QStringList FindDuplicates::authorsLastName( BibTeX::Entry *entry )
+ {
+ QStringList result;
+
+ /** retrieve field holding authors information for entry */
+ BibTeX::EntryField *field = entry->getField( BibTeX::EntryField::ftAuthor );
+ if ( field == NULL )
+ return result; /** no author field available */
+
+ /** fetch container holding list of author names */
+ BibTeX::PersonContainer *personContainer = field != NULL ? dynamic_cast<BibTeX::PersonContainer*>( field->value()->items.isEmpty() ? NULL : field->value()->items.first() ) : NULL;
+ if ( personContainer == NULL || personContainer->persons.isEmpty() )
+ return result; /** container not found or is empty */
+
+ /** iterate through container and fetch each author's last name */
+ for ( QValueList<BibTeX::Person*>::ConstIterator it = personContainer->persons.begin(); it != personContainer->persons.end(); ++it )
+ result.append(( *it )->lastName() );
+
+ return result;
+ }
+
+ /**
+ * Determine year for a given entry
+ */
+ int FindDuplicates::extractYear( BibTeX::Entry *entry )
+ {
+ /** retrieve field holding year information for entry */
+ BibTeX::EntryField *field = entry->getField( BibTeX::EntryField::ftYear );
+ if ( field == NULL )
+ return -1; /** no year field available */
+
+ /** *fetch value item holding year */
+ BibTeX::ValueItem *valueItem = field != NULL ? ( field->value()->items.isEmpty() ? NULL : field->value()->items.first() ) : NULL;
+ if ( valueItem == NULL )
+ return -1; /** no value item found or is empty */
+
+ /** parse value item's text */
+ bool ok = FALSE;
+ int year = QString( valueItem->text() ).toInt( &ok );
+ if ( !ok ) year = -1;
+
+ return year;
+ }
+
+ /**
+ * Determine key from a given macro
+ */
+ QString FindDuplicates::extractMacroKey( BibTeX::Macro *macro )
+ {
+ return macro->key();
+ }
+
+ /**
+ * Determine key from a given macro
+ */
+ QString FindDuplicates::extractMacroValue( BibTeX::Macro *macro )
+ {
+ return macro->value()->text();
+ }
+
+ void FindDuplicates::slotCancel()
+ {
+ m_doCancel = true;
+ }
+}
+#include "findduplicates.moc"
diff --git a/src/findduplicates.h b/src/findduplicates.h
new file mode 100644
index 0000000..e1a2fce
--- /dev/null
+++ b/src/findduplicates.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXFINDDUPLICATES_H
+#define KBIBTEXFINDDUPLICATES_H
+
+#include <qobject.h>
+
+class KProgressDialog;
+class QWidget;
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class FindDuplicates : public QObject
+ {
+ Q_OBJECT
+ public:
+ typedef QValueList<BibTeX::Element*> DuplicateClique;
+ typedef QValueList<DuplicateClique> DuplicateCliqueList;
+
+ /**
+ * Find duplicates in a given BibTeX file. The sensitivity parameter controls the distance between two elements where both elements are considered to be duplicates. The parent object is used as a progress dialog's parent.
+ * @param file
+ * @param sensitivity
+ * @param parent
+ * @return
+ */
+ FindDuplicates( DuplicateCliqueList &result, unsigned int sensitivity, BibTeX::File *file, QWidget *parent );
+
+ ~FindDuplicates();
+
+ /**
+ * Maximum sensitivity
+ */
+ static const unsigned int maxDistance;
+
+ protected:
+ void determineDistances( BibTeX::File *file, unsigned int *distVector, QMap<BibTeX::Element*, int> &mapElementToIndex, KProgressDialog *progDlg );
+ void buildClique( DuplicateCliqueList &result, BibTeX::File *file, unsigned int *distVector, QMap<BibTeX::Element*, int> &mapElementToIndex, unsigned int sensitivity );
+ unsigned int entryDistance( BibTeX::Entry *entryA, BibTeX::Entry *entryB );
+ unsigned int macroDistance( BibTeX::Macro *macroA, BibTeX::Macro *macroB );
+ unsigned int preambleDistance( BibTeX::Preamble *preambleA, BibTeX::Preamble *preambleB );
+
+ static QString extractTitle( BibTeX::Entry *entry );
+ static QStringList authorsLastName( BibTeX::Entry *entry );
+ static int extractYear( BibTeX::Entry *entry );
+ static QString extractMacroKey( BibTeX::Macro *macro );
+ static QString extractMacroValue( BibTeX::Macro *macro );
+
+ private:
+ bool m_doCancel;
+
+ double levenshteinDistance( const QStringList &s, const QStringList &t );
+ double levenshteinDistance( const QString &s, const QString &t );
+ double levenshteinDistanceWord( const QString &s, const QString &t );
+ int arrayOffset( int a, int b );
+ void sort( unsigned int *array, int len );
+
+ private slots:
+ void slotCancel();
+ };
+
+}
+
+#endif
diff --git a/src/hi128-app-kbibtex.png b/src/hi128-app-kbibtex.png
new file mode 100644
index 0000000..f8a9b2a
--- /dev/null
+++ b/src/hi128-app-kbibtex.png
Binary files differ
diff --git a/src/hi16-app-kbibtex.png b/src/hi16-app-kbibtex.png
new file mode 100644
index 0000000..7dfd6f5
--- /dev/null
+++ b/src/hi16-app-kbibtex.png
Binary files differ
diff --git a/src/hi22-app-kbibtex.png b/src/hi22-app-kbibtex.png
new file mode 100644
index 0000000..1bc9bd3
--- /dev/null
+++ b/src/hi22-app-kbibtex.png
Binary files differ
diff --git a/src/hi32-app-kbibtex.png b/src/hi32-app-kbibtex.png
new file mode 100644
index 0000000..9641f3b
--- /dev/null
+++ b/src/hi32-app-kbibtex.png
Binary files differ
diff --git a/src/hi48-app-kbibtex.png b/src/hi48-app-kbibtex.png
new file mode 100644
index 0000000..b150dd6
--- /dev/null
+++ b/src/hi48-app-kbibtex.png
Binary files differ
diff --git a/src/hi64-app-kbibtex.png b/src/hi64-app-kbibtex.png
new file mode 100644
index 0000000..d322215
--- /dev/null
+++ b/src/hi64-app-kbibtex.png
Binary files differ
diff --git a/src/idsuggestions.cpp b/src/idsuggestions.cpp
new file mode 100644
index 0000000..5704c1e
--- /dev/null
+++ b/src/idsuggestions.cpp
@@ -0,0 +1,363 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qregexp.h>
+
+#include <klocale.h>
+
+#include <encoderlatex.h>
+#include <file.h>
+#include <settings.h>
+#include <entry.h>
+#include "idsuggestions.h"
+
+namespace KBibTeX
+{
+ const QRegExp IdSuggestions::unwantedChars = QRegExp( "[^-_:/=+a-zA-Z0-9]+" );
+
+ IdSuggestions::IdSuggestions()
+ {
+// nothing
+ }
+
+
+ IdSuggestions::~IdSuggestions()
+ {
+// nothing
+ }
+
+ /**
+ * Determine list of authors or editors for a given entry
+ */
+ QStringList IdSuggestions::authorsLastName( BibTeX::Entry *entry )
+ {
+ QStringList result;
+
+ /** retrieve field holding authors information for entry */
+ BibTeX::EntryField *field = entry->getField( BibTeX::EntryField::ftAuthor );
+ if ( field == NULL )
+ {
+ /** no author field available, try editor
+ patch by Jurgen Spitzmuller <[email protected]> */
+ field = entry->getField( BibTeX::EntryField::ftEditor );
+ if ( field == NULL )
+ {
+ return result; /** neither author nor editor available */
+ }
+ }
+
+ /** fetch container holding list of author names */
+ BibTeX::PersonContainer *personContainer = field != NULL ? dynamic_cast<BibTeX::PersonContainer*>( field->value()->items.isEmpty() ? NULL : field->value()->items.first() ) : NULL;
+ if ( personContainer == NULL || personContainer->persons.isEmpty() )
+ return result; /** container not found or is empty */
+
+ /** iterate through container and fetch each author's last name */
+ for ( QValueList<BibTeX::Person*>::ConstIterator it = personContainer->persons.begin(); it != personContainer->persons.end(); ++it )
+ {
+ result.append( normalizeText(( *it )->lastName() ) );
+ }
+
+ return result;
+ }
+
+ /**
+ * Normalize a given text by removing spaces or other unwanted characters,
+ * replace some accented and special characters by plain ASCII transliterations
+ */
+ QString IdSuggestions::normalizeText( const QString& text )
+ {
+ QString result = text;
+
+ for ( int i = text.length() - 1; i >= 0; --i )
+ result[i] = QChar( BibTeX::EncoderLaTeX::unicodeToASCII( result[i].unicode() ) );
+
+ return result.replace( unwantedChars, "" );
+ }
+
+ QString IdSuggestions::resolveConflict( BibTeX::File *file, const QString &id, BibTeX::Element *element )
+ {
+ QString result = id;
+ BibTeX::Element *hit = file->containsKey( id ) ;
+ if ( hit != NULL && hit != element )
+ {
+ int i = 0;
+ do
+ {
+ result = QString( "%1-%2" ).arg( id ).arg( ++i );
+ hit = file->containsKey( result );
+ }
+ while ( hit != NULL && hit != element );
+ }
+ return result;
+ }
+
+ /**
+ * Determine year for a given entry
+ */
+ int IdSuggestions::extractYear( BibTeX::Entry *entry )
+ {
+ /** retrieve field holding year information for entry */
+ BibTeX::EntryField *field = entry->getField( BibTeX::EntryField::ftYear );
+ if ( field == NULL )
+ return -1; /** no year field available */
+
+ /** fetch value item holding year */
+ BibTeX::ValueItem *valueItem = field != NULL ? ( field->value()->items.isEmpty() ? NULL : field->value()->items.first() ) : NULL;
+ if ( valueItem == NULL )
+ return -1; /** no value item found or is empty */
+
+ /** parse value item's text */
+ bool ok = FALSE;
+ QRegExp yearRegExp( "\\b(\\d{2})?\\d{2}\\b" );
+ yearRegExp.search( valueItem->text() );
+ int year = QString( yearRegExp.cap( 0 ) ).toInt( &ok );
+ if ( !ok ) year = -1;
+
+ return year;
+ }
+
+ /**
+ * Determine title for a given entry
+ */
+ QString IdSuggestions::extractTitle( BibTeX::Entry *entry )
+ {
+ /** retrieve field holding title information for entry */
+ BibTeX::EntryField *field = entry->getField( BibTeX::EntryField::ftTitle );
+ if ( field == NULL )
+ return QString::null; /** no title field available */
+
+ /** *fetch value item holding title */
+ BibTeX::ValueItem *valueItem = field->value()->items.isEmpty() ? NULL : field->value()->items.first();
+ if ( valueItem == NULL )
+ return QString::null; /** no value item found or is empty */
+
+ return valueItem->text();
+ }
+
+ QStringList IdSuggestions::createSuggestions( BibTeX::File *file, BibTeX::Entry *entry )
+ {
+ Settings * settings = Settings::self();
+ const QStringList& formatStrList = settings->idSuggestions_formatStrList;
+ QStringList result;
+ QStringList allKeys = file != NULL ? file->allKeys() : QStringList();
+ entry = new BibTeX::Entry( entry );
+ if ( file != NULL )
+ file->completeReferencedFields( entry );
+
+ for ( QStringList::ConstIterator it = formatStrList.begin(); it != formatStrList.end(); ++it )
+ {
+ QString id = formatId( entry, *it );
+ if ( id.isEmpty() || result.contains( id ) )
+ continue;
+ if ( !result.contains( id ) )
+ result.append( id );
+ }
+
+ delete entry;
+
+ return result;
+ }
+
+ QString IdSuggestions::createDefaultSuggestion( BibTeX::File *file, BibTeX::Entry *entry )
+ {
+ Settings * settings = Settings::self();
+ if ( settings->idSuggestions_default < 0 || settings->idSuggestions_default >= ( int )settings->idSuggestions_formatStrList.size() )
+ return QString::null;
+
+ entry = new BibTeX::Entry( entry );
+ if ( file != NULL )
+ file->completeReferencedFields( entry );
+
+ QString result = formatId( entry, settings->idSuggestions_formatStrList[settings->idSuggestions_default] );
+
+ delete entry;
+ return result;
+ }
+
+ QString IdSuggestions::formatId( BibTeX::Entry *entry, const QString& formatStr )
+ {
+ QString id;
+ QStringList tokenList = QStringList::split( '|', formatStr );
+ for ( QStringList::ConstIterator tit = tokenList.begin(); tit != tokenList.end(); ++tit )
+ id.append( translateToken( entry, *tit ) );
+
+ return id;
+ }
+
+ QString IdSuggestions::translateToken( BibTeX::Entry *entry, const QString& token )
+ {
+ switch ( token[0] )
+ {
+ case 'a': return translateAuthorsToken( entry, token.mid( 1 ), aOnlyFirst );
+ case 'A': return translateAuthorsToken( entry, token.mid( 1 ), aAll );
+ case 'z': return translateAuthorsToken( entry, token.mid( 1 ), aNotFirst );
+ case 'y':
+ {
+ int year = extractYear( entry );
+ if ( year > -1 )
+ return QString::number( year % 100 + 100 ).mid( 1 );
+ else
+ return QString::null;
+ }
+ case 'Y':
+ {
+ int year = extractYear( entry );
+ if ( year > -1 )
+ return QString::number( year % 10000 + 10000 ).mid( 1 );
+ else
+ return QString::null;
+ }
+ case 't': return translateTitleToken( entry, token.mid( 1 ), FALSE );
+ case 'T': return translateTitleToken( entry, token.mid( 1 ), TRUE );
+ case '"': return token.mid( 1 );
+ default: return QString::null;
+ }
+ }
+
+ QString IdSuggestions::translateAuthorsToken( BibTeX::Entry *entry, const QString& token, Authors selectAuthors )
+ {
+ struct IdSuggestionTokenInfo ati = evalToken( token );
+ QString result;
+ bool first = true, firstInserted = true;
+ QStringList authors = authorsLastName( entry );
+ for ( QStringList::ConstIterator it = authors.begin(); it != authors.end(); ++it )
+ {
+ QString author = normalizeText( *it ).left( ati.len );
+ if ( selectAuthors == aAll || ( selectAuthors == aOnlyFirst && first ) || ( selectAuthors == aNotFirst && !first ) )
+ {
+ if ( !firstInserted )
+ result.append( ati.inBetween );
+ result.append( author );
+ firstInserted = false;
+ }
+ first = false;
+ }
+
+ if ( ati.toUpper )
+ result = result.upper();
+ else if ( ati.toLower )
+ result = result.lower();
+
+ return result;
+ }
+
+ struct IdSuggestionTokenInfo IdSuggestions::evalToken( const QString& token )
+ {
+ unsigned int pos = 0;
+ struct IdSuggestionTokenInfo result;
+ result.len = 0x00ffffff;
+ result.toLower = FALSE;
+ result.toUpper = FALSE;
+ result.inBetween = QString::null;
+
+ if ( token.length() > pos )
+ {
+ int dv = token[pos].digitValue();
+ if ( dv > -1 )
+ {
+ result.len = dv;
+ ++pos;
+ }
+ }
+
+ if ( token.length() > pos )
+ {
+ result.toLower = token[pos] == 'l';
+ result.toUpper = token[pos] == 'u';
+ if ( result.toUpper || result.toLower )
+ ++pos;
+ }
+
+ if ( token.length() > pos + 1 && token[pos] == '"' )
+ result.inBetween = token.mid( pos + 1 );
+
+ return result;
+ }
+
+ QString IdSuggestions::translateTitleToken( BibTeX::Entry *entry, const QString& token, bool removeSmallWords )
+ {
+ struct IdSuggestionTokenInfo tti = evalToken( token );
+ Settings * settings = Settings::self();
+ const QStringList smallWords = settings->idSuggestions_smallWords;
+
+ QString result;
+ bool first = TRUE;
+ QStringList titleWords = QStringList::split( QRegExp( "\\s+" ), extractTitle( entry ) );
+ for ( QStringList::ConstIterator it = titleWords.begin(); it != titleWords.end(); ++it )
+ {
+ if ( first )
+ first = FALSE;
+ else
+ result.append( tti.inBetween );
+
+ QString lowerText = ( *it ).lower();
+ if ( !removeSmallWords || !smallWords.contains( lowerText ) )
+ result.append( normalizeText( *it ).left( tti.len ) );
+ }
+
+ if ( tti.toUpper )
+ result = result.upper();
+ else if ( tti.toLower )
+ result = result.lower();
+
+ return result;
+ }
+
+ /** convert a formatting string into a human readable version (even translated) */
+ QString IdSuggestions::formatStrToHuman( const QString& formatStr )
+ {
+ bool first = TRUE;
+ QString text;
+ QStringList elements = QStringList::split( '|', formatStr );
+ for ( QStringList::iterator it = elements.begin();it != elements.end();++it )
+ {
+ if ( first ) first = FALSE; else text.append( "\n" );
+ if (( *it )[0] == 'a' || ( *it )[0] == 'A' || ( *it )[0] == 'z' )
+ {
+ struct IdSuggestionTokenInfo info = evalToken(( *it ).mid( 1 ) );
+ if (( *it )[0] == 'a' ) text.append( i18n( "First author only" ) );
+ else if (( *it )[0] == 'z' ) text.append( i18n( "All but first author" ) );
+ else text.append( i18n( "All authors" ) );
+
+ int n = info.len;
+ if ( info.len < 0x00ffffff ) text.append( i18n( ", but only first letter of each last name", ", but only first %n letters of each last name", n ) );
+ if ( info.toUpper ) text.append( i18n( ", in upper case" ) );
+ else if ( info.toLower ) text.append( i18n( ", in lower case" ) );
+ if ( info.inBetween != QString::null ) text.append( QString( i18n( ", with '%1' in between" ) ).arg( info.inBetween ) );
+ }
+ else if (( *it )[0] == 'y' ) text.append( i18n( "Year (2 digits)" ) );
+ else if (( *it )[0] == 'Y' ) text.append( i18n( "Year (4 digits)" ) );
+ else if (( *it )[0] == 't' || ( *it )[0] == 'T' )
+ {
+ struct IdSuggestionTokenInfo info = evalToken(( *it ).mid( 1 ) );
+ text.append( i18n( "Title" ) );
+ int n = info.len;
+ if ( info.len < 0x00ffffff ) text.append( i18n( ", but only first letter of each word", ", but only first %n letters of each word", n ) );
+ if ( info.toUpper ) text.append( i18n( ", in upper case" ) );
+ else if ( info.toLower ) text.append( i18n( ", in lower case" ) );
+ if ( info.inBetween != QString::null ) text.append( QString( i18n( ", with '%1' in between" ) ).arg( info.inBetween ) );
+ if (( *it )[0] == 'T' ) text.append( i18n( ", small words removed" ) );
+ }
+ else if (( *it )[0] == '"' ) text.append( QString( i18n( "Text: '%1'" ) ).arg(( *it ).mid( 1 ) ) );
+ else text.append( "?" );
+ }
+
+ return text;
+ }
+}
diff --git a/src/idsuggestions.h b/src/idsuggestions.h
new file mode 100644
index 0000000..a1bd022
--- /dev/null
+++ b/src/idsuggestions.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXIDSUGGESTIONS_H
+#define KBIBTEXIDSUGGESTIONS_H
+
+#include <qstringlist.h>
+
+#include <file.h>
+#include <entry.h>
+
+namespace KBibTeX
+{
+ struct IdSuggestionTokenInfo
+ {
+ unsigned int len;
+ bool toLower;
+ bool toUpper;
+ QString inBetween;
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class IdSuggestions
+ {
+ public:
+ static QStringList createSuggestions( BibTeX::File *file, BibTeX::Entry *entry );
+ static QString createDefaultSuggestion( BibTeX::File *file, BibTeX::Entry *entry );
+ static QString formatStrToHuman( const QString& formatStr );
+ static struct IdSuggestionTokenInfo evalToken( const QString& token );
+ static QString formatId( BibTeX::Entry *entry, const QString& formatStr );
+ static QString resolveConflict( BibTeX::File *file, const QString &id, BibTeX::Element *element = NULL );
+
+ static const QStringList smallWords;
+
+ private:
+ enum Authors {aAll, aOnlyFirst, aNotFirst};
+
+ static const QRegExp unwantedChars;
+ static const QChar asciiizeSource[];
+ static const QString asciiizeTarget[];
+
+ IdSuggestions();
+ ~IdSuggestions();
+
+ static QStringList authorsLastName( BibTeX::Entry *entry );
+ static QString normalizeText( const QString& text );
+ static QString asciiizeText( const QString& text );
+ static int extractYear( BibTeX::Entry *entry );
+ static QString extractTitle( BibTeX::Entry *entry );
+ static QString translateToken( BibTeX::Entry *entry, const QString& token );
+ static QString translateAuthorsToken( BibTeX::Entry *entry, const QString& token, Authors selectAuthors );
+ static QString translateTitleToken( BibTeX::Entry *entry, const QString& token, bool removeSmallWords );
+ };
+
+}
+
+#endif
diff --git a/src/idsuggestionswidget.cpp b/src/idsuggestionswidget.cpp
new file mode 100644
index 0000000..d2d371f
--- /dev/null
+++ b/src/idsuggestionswidget.cpp
@@ -0,0 +1,567 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qlayout.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qobjectlist.h>
+#include <qscrollview.h>
+
+#include <kglobalsettings.h>
+#include <klineedit.h>
+#include <kpopupmenu.h>
+#include <kcombobox.h>
+#include <kpushbutton.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include <idsuggestions.h>
+#include <fileimporter.h>
+#include <fileimporterbibtex.h>
+#include "idsuggestionswidget.h"
+
+#define min(a,b) ((a)>(b)?(b):(a))
+#define max(a,b) ((a)<(b)?(b):(a))
+
+namespace KBibTeX
+{
+ QString IdSuggestionsWidget::exampleBibTeXEntry = "@Article{ dijkstra1983terminationdetect,\nauthor = {Edsger W. Dijkstra and W. H. J. Feijen and A. J. M. {van Gasteren}},\ntitle = {{Derivation of a Termination Detection Algorithm for Distributed Computations}},\njournal = {Information Processing Letters},\nvolume = 16,\nnumber = 5,\npages = {217--219},\nmonth = jun,\nyear = 1983\n}";
+
+ IdSuggestionComponent::IdSuggestionComponent( const QString& title, QWidget *parent ): QFrame( parent ), m_toBeDeleted( false ), m_title( title ), m_parent( parent )
+ {
+ setFrameShape( QFrame::Panel );
+ setFrameShadow( QFrame::Sunken );
+ setLineWidth( 1 );
+ }
+
+ QWidget *IdSuggestionComponent::moveWidgets( QWidget *parent )
+ {
+ QWidget *container = new QWidget( parent );
+ QVBoxLayout *layout = new QVBoxLayout( container, 0, KDialog::spacingHint() );
+ m_pushButtonUp = new KPushButton( QIconSet( SmallIcon( "up" ) ), i18n( "Up" ), container );
+ m_pushButtonDown = new KPushButton( QIconSet( SmallIcon( "down" ) ), i18n( "Down" ), container );
+ m_pushButtonDel = new KPushButton( QIconSet( SmallIcon( "remove" ) ), i18n( "Delete" ), container );
+ layout->addWidget( m_pushButtonUp );
+ layout->addWidget( m_pushButtonDown );
+ layout->addWidget( m_pushButtonDel );
+ layout->addStretch( 10 );
+ connect( m_pushButtonUp, SIGNAL( clicked() ), this, SLOT( slotUp() ) );
+ connect( m_pushButtonDown, SIGNAL( clicked() ), this, SLOT( slotDown() ) );
+ connect( m_pushButtonDel, SIGNAL( clicked() ), this, SLOT( slotDelete() ) );
+ return container;
+ }
+
+ void IdSuggestionComponent::setEnableUpDown( bool enableUp, bool enableDown )
+ {
+ m_pushButtonUp->setEnabled( enableUp );
+ m_pushButtonDown->setEnabled( enableDown );
+ }
+
+ void IdSuggestionComponent::slotUp()
+ {
+ QVBoxLayout *layout = dynamic_cast<QVBoxLayout*>( m_parent->layout() );
+ if ( layout == NULL ) return;
+ int oldPos = layout->findWidget( this );
+ if ( oldPos > 0 )
+ {
+ layout->remove( this );
+ layout->insertWidget( oldPos - 1, this );
+ emit moved();
+ }
+ }
+
+ void IdSuggestionComponent::slotDown()
+ {
+ QVBoxLayout *layout = dynamic_cast<QVBoxLayout*>( m_parent->layout() );
+ if ( layout == NULL ) return;
+ int oldPos = layout->findWidget( this );
+ int componentCount = dynamic_cast<IdSuggestionsWidget*>( m_parent->parent()->parent()->parent() )->numComponents();
+ if ( oldPos < componentCount - 1 )
+ {
+ layout->remove( this );
+ layout->insertWidget( oldPos + 1, this );
+ emit moved();
+ }
+ }
+
+ void IdSuggestionComponent::slotDelete()
+ {
+ m_toBeDeleted = true;
+ emit deleted();
+ delete this;
+ }
+
+ IdSuggestionComponentAuthor::IdSuggestionComponentAuthor( const QString &text, QWidget *parent ): IdSuggestionComponent( i18n( "Author" ), parent )
+ {
+ QGridLayout *layout = new QGridLayout( this, 6, 4, KDialog::marginHint(), KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( m_title, this );
+ QFont labelFont( label->font() );
+ labelFont.setBold( TRUE );
+ label->setFont( labelFont );
+ label->setBackgroundColor( KGlobalSettings::highlightColor() );
+ label->setPaletteForegroundColor( KGlobalSettings::highlightedTextColor() );
+ label->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ layout->addMultiCellWidget( label, 0, 0, 0, 2 );
+
+ m_comboBoxWhichAuthors = new KComboBox( false, this );
+ layout->addMultiCellWidget( m_comboBoxWhichAuthors, 1, 1, 0, 1 );
+ m_comboBoxWhichAuthors->insertItem( i18n( "All authors" ) );
+ m_comboBoxWhichAuthors->insertItem( i18n( "First author only" ) );
+ m_comboBoxWhichAuthors->insertItem( i18n( "All but first author" ) );
+ switch ( text[0] )
+ {
+ case 'a': m_comboBoxWhichAuthors->setCurrentItem( 1 ); break;
+ case 'z': m_comboBoxWhichAuthors->setCurrentItem( 2 ); break;
+ default: m_comboBoxWhichAuthors->setCurrentItem( 0 );
+ }
+ connect( m_comboBoxWhichAuthors, SIGNAL( activated( const QString& ) ), SIGNAL( modified() ) );
+
+ struct IdSuggestionTokenInfo info = IdSuggestions::evalToken( text.mid( 1 ) );
+
+ label = new QLabel( i18n( "Casing:" ), this );
+ layout->addWidget( label, 2, 0 );
+ m_comboBoxCasing = new KComboBox( FALSE, this );
+ label->setBuddy( m_comboBoxCasing );
+ layout->addWidget( m_comboBoxCasing, 2, 1 );
+ m_comboBoxCasing->insertItem( i18n( "No change" ) );
+ m_comboBoxCasing->insertItem( i18n( "Lower case" ) );
+ m_comboBoxCasing->insertItem( i18n( "Upper case" ) );
+ if ( info.toLower )
+ m_comboBoxCasing->setCurrentItem( 1 );
+ else if ( info.toUpper )
+ m_comboBoxCasing->setCurrentItem( 2 );
+ else
+ m_comboBoxCasing->setCurrentItem( 0 );
+ connect( m_comboBoxCasing, SIGNAL( activated( const QString& ) ), SIGNAL( modified() ) );
+
+ label = new QLabel( i18n( "Only first letters:" ), this );
+ layout->addWidget( label, 3, 0 );
+ m_spinBoxLen = new QSpinBox( this );
+ label->setBuddy( m_spinBoxLen );
+ layout->addWidget( m_spinBoxLen, 3, 1 );
+ m_spinBoxLen->setMinValue( 0 );
+ m_spinBoxLen->setMaxValue( 9 );
+ m_spinBoxLen->setSpecialValueText( i18n( "Complete name" ) );
+ m_spinBoxLen->setValue( info.len > 9 ? 0 : info.len );
+ m_spinBoxLen->setMinimumWidth( m_spinBoxLen->fontMetrics().width( i18n( "Complete name" ) ) + 32 );
+ connect( m_spinBoxLen, SIGNAL( valueChanged( int ) ), SIGNAL( modified() ) );
+
+ label = new QLabel( i18n( "Text between authors:" ), this );
+ layout->addWidget( label, 4, 0 );
+ m_lineEditInBetween = new KLineEdit( this );
+ label->setBuddy( m_lineEditInBetween );
+ layout->addWidget( m_lineEditInBetween, 4, 1 );
+ m_lineEditInBetween->setText( info.inBetween );
+ connect( m_lineEditInBetween, SIGNAL( textChanged( const QString& ) ), SIGNAL( modified() ) );
+
+ layout->setRowStretch( 5, 1 );
+ layout->setColStretch( 1, 1 );
+ layout->setColSpacing( 2, KDialog::spacingHint() * 3 );
+ layout->addMultiCellWidget( moveWidgets( this ), 0, 5, 3, 3 );
+ }
+
+ QString IdSuggestionComponentAuthor::text() const
+ {
+ if ( m_toBeDeleted ) return QString::null;
+
+ QString result;
+ switch ( m_comboBoxWhichAuthors->currentItem() )
+ {
+ case 1: result = "a"; break;
+ case 2: result = "z"; break;
+ default: result = "A";
+ }
+ if ( m_spinBoxLen->value() > 0 && m_spinBoxLen->value() <= 9 ) result.append( QString::number( m_spinBoxLen->value() ) );
+ if ( m_comboBoxCasing->currentItem() == 1 ) result.append( "l" );
+ else if ( m_comboBoxCasing->currentItem() == 2 ) result.append( "u" );
+ if ( !m_lineEditInBetween->text().isEmpty() ) result.append( '"' ).append( m_lineEditInBetween->text() );
+
+ return result;
+ }
+
+ IdSuggestionComponentTitle::IdSuggestionComponentTitle( const QString &text, QWidget *parent ): IdSuggestionComponent( i18n( "Title" ), parent )
+ {
+ QGridLayout *layout = new QGridLayout( this, 6, 4, KDialog::marginHint(), KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( m_title, this );
+ QFont labelFont( label->font() );
+ labelFont.setBold( TRUE );
+ label->setFont( labelFont );
+ label->setBackgroundColor( KGlobalSettings::highlightColor() );
+ label->setPaletteForegroundColor( KGlobalSettings::highlightedTextColor() );
+ label->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ layout->addMultiCellWidget( label, 0, 0, 0, 2 );
+
+ m_checkBoxRemoveSmallWords = new QCheckBox( i18n( "Remove small words" ), this );
+ layout->addMultiCellWidget( m_checkBoxRemoveSmallWords, 1, 1, 0, 1 );
+ m_checkBoxRemoveSmallWords->setChecked( text[0] == 'T' );
+ connect( m_checkBoxRemoveSmallWords, SIGNAL( toggled( bool ) ), SIGNAL( modified() ) );
+
+ struct IdSuggestionTokenInfo info = IdSuggestions::evalToken( text.mid( 1 ) );
+
+ label = new QLabel( i18n( "Casing:" ), this );
+ layout->addWidget( label, 2, 0 );
+ m_comboBoxCasing = new KComboBox( FALSE, this );
+ label->setBuddy( m_comboBoxCasing );
+ layout->addWidget( m_comboBoxCasing, 2, 1 );
+ m_comboBoxCasing->insertItem( i18n( "No change" ) );
+ m_comboBoxCasing->insertItem( i18n( "Lower case" ) );
+ m_comboBoxCasing->insertItem( i18n( "Upper case" ) );
+ if ( info.toLower )
+ m_comboBoxCasing->setCurrentItem( 1 );
+ else if ( info.toUpper )
+ m_comboBoxCasing->setCurrentItem( 2 );
+ else
+ m_comboBoxCasing->setCurrentItem( 0 );
+ connect( m_comboBoxCasing, SIGNAL( textChanged( const QString& ) ), SIGNAL( modified() ) );
+
+ label = new QLabel( i18n( "Only first letters:" ), this );
+ layout->addWidget( label, 3, 0 );
+ m_spinBoxLen = new QSpinBox( this );
+ label->setBuddy( m_spinBoxLen );
+ layout->addWidget( m_spinBoxLen, 3, 1 );
+ m_spinBoxLen->setMinValue( 0 );
+ m_spinBoxLen->setMaxValue( 9 );
+ m_spinBoxLen->setSpecialValueText( i18n( "Complete title" ) );
+ m_spinBoxLen->setValue( info.len > 9 ? 0 : info.len );
+ m_spinBoxLen->setMinimumWidth( m_spinBoxLen->fontMetrics().width( i18n( "Complete title" ) ) + 32 );
+ connect( m_spinBoxLen, SIGNAL( valueChanged( int ) ), SIGNAL( modified() ) );
+
+ label = new QLabel( i18n( "Text between words:" ), this );
+ layout->addWidget( label, 4, 0 );
+ m_lineEditInBetween = new KLineEdit( this );
+ label->setBuddy( m_lineEditInBetween );
+ layout->addWidget( m_lineEditInBetween, 4, 1 );
+ m_lineEditInBetween->setText( info.inBetween );
+ connect( m_lineEditInBetween, SIGNAL( textChanged( const QString& ) ), SIGNAL( modified() ) );
+
+ layout->setRowStretch( 5, 1 );
+ layout->setColStretch( 1, 1 );
+ layout->setColSpacing( 2, KDialog::spacingHint() *2 );
+ layout->addMultiCellWidget( moveWidgets( this ), 0, 5, 3, 3 );
+ }
+
+ QString IdSuggestionComponentTitle::text() const
+ {
+ if ( m_toBeDeleted ) return QString::null;
+
+ QString result = m_checkBoxRemoveSmallWords->isChecked() ? "T" : "t";
+ if ( m_spinBoxLen->value() > 0 && m_spinBoxLen->value() <= 9 ) result.append( QString::number( m_spinBoxLen->value() ) );
+ if ( m_comboBoxCasing->currentItem() == 1 ) result.append( "l" );
+ else if ( m_comboBoxCasing->currentItem() == 2 ) result.append( "u" );
+ if ( !m_lineEditInBetween->text().isEmpty() ) result.append( '"' ).append( m_lineEditInBetween->text() );
+
+ return result;
+ }
+
+ IdSuggestionComponentYear::IdSuggestionComponentYear( const QString &text, QWidget *parent ): IdSuggestionComponent( i18n( "Year" ), parent )
+ {
+ QGridLayout *layout = new QGridLayout( this, 3, 4, KDialog::marginHint(), KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( m_title, this );
+ QFont labelFont( label->font() );
+ labelFont.setBold( TRUE );
+ label->setFont( labelFont );
+ label->setBackgroundColor( KGlobalSettings::highlightColor() );
+ label->setPaletteForegroundColor( KGlobalSettings::highlightedTextColor() );
+ label->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ layout->addMultiCellWidget( label, 0, 0, 0, 2 );
+
+ label = new QLabel( i18n( "Year:" ), this );
+ layout->addWidget( label, 1, 0 );
+ m_comboBoxDigits = new KComboBox( this );
+ label->setBuddy( m_comboBoxDigits );
+ layout->addWidget( m_comboBoxDigits, 1, 1 );
+ m_comboBoxDigits->insertItem( i18n( "2 digits" ) );
+ m_comboBoxDigits->insertItem( i18n( "4 digits" ) );
+ m_comboBoxDigits->setCurrentItem( text[0] == 'y' ? 0 : 1 );
+ connect( m_comboBoxDigits, SIGNAL( activated( int ) ), SIGNAL( modified() ) );
+
+ layout->setColStretch( 1, 1 );
+ layout->setRowStretch( 2, 1 );
+ layout->setColSpacing( 2, KDialog::spacingHint() *2 );
+ layout->addMultiCellWidget( moveWidgets( this ), 0, 2, 3, 3 );
+ }
+
+ QString IdSuggestionComponentYear::text() const
+ {
+ if ( m_toBeDeleted ) return QString::null;
+ return m_comboBoxDigits->currentItem() == 0 ? "y" : "Y";
+ }
+
+ IdSuggestionComponentText::IdSuggestionComponentText( const QString &text, QWidget *parent ): IdSuggestionComponent( i18n( "Text" ), parent )
+ {
+ QGridLayout *layout = new QGridLayout( this, 3, 4, KDialog::marginHint(), KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( m_title, this );
+ QFont labelFont( label->font() );
+ labelFont.setBold( TRUE );
+ label->setFont( labelFont );
+ label->setBackgroundColor( KGlobalSettings::highlightColor() );
+ label->setPaletteForegroundColor( KGlobalSettings::highlightedTextColor() );
+ label->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ layout->addMultiCellWidget( label, 0, 0, 0, 2 );
+
+ label = new QLabel( i18n( "Text in between:" ), this );
+ layout->addWidget( label, 1, 0 );
+ m_lineEditInBetween = new KLineEdit( this );
+ label->setBuddy( m_lineEditInBetween );
+ layout->addWidget( m_lineEditInBetween, 1, 1 );
+ m_lineEditInBetween->setText( text.mid( 1 ) );
+ connect( m_lineEditInBetween, SIGNAL( textChanged( const QString& ) ), SIGNAL( modified() ) );
+
+ layout->setColStretch( 1, 1 );
+ layout->setRowStretch( 2, 1 );
+ layout->setColSpacing( 2, KDialog::spacingHint() * 2 );
+ layout->addMultiCellWidget( moveWidgets( this ), 0, 2, 3, 3 );
+ }
+
+ QString IdSuggestionComponentText::text() const
+ {
+ if ( m_toBeDeleted ) return QString::null;
+ return m_lineEditInBetween->text().isEmpty() ? QString::null : QString( "\"" ).append( m_lineEditInBetween->text() );
+ }
+
+ IdSuggestionsScrollView::IdSuggestionsScrollView( QWidget *parent, const char*name ): QScrollView( parent, name ), m_widget( NULL )
+ {
+ setMinimumHeight( 256 );
+ setHScrollBarMode( QScrollView::AlwaysOff );
+ setVScrollBarMode( QScrollView::AlwaysOn );
+ setLineWidth( 0 );
+ }
+
+ IdSuggestionsScrollView::~IdSuggestionsScrollView()
+ {
+ // nothing
+ }
+
+ void IdSuggestionsScrollView::viewportResizeEvent( QResizeEvent * )
+ {
+ if ( m_widget != NULL )
+ m_widget->setFixedWidth( viewport()->width() );
+ }
+
+ IdSuggestionsWidget::IdSuggestionsWidget( const QString &formatStr, KDialogBase *parent, const char *name )
+ : QWidget( parent, name ), m_originalFormatStr( formatStr ), m_parent( parent )
+ {
+ BibTeX::FileImporter *importer = new BibTeX::FileImporterBibTeX( false );
+ BibTeX::File *file = importer->load( exampleBibTeXEntry );
+ m_example = new BibTeX::Entry( dynamic_cast<BibTeX::Entry*>( *( file->begin() ) ) );
+ delete file;
+ delete importer;
+
+ setupGUI();
+ reset( formatStr );
+ }
+
+ IdSuggestionsWidget::~IdSuggestionsWidget()
+ {
+ // nothing
+ }
+
+ int IdSuggestionsWidget::numComponents()
+ {
+ return m_componentCount;
+ }
+
+ QDialog::DialogCode IdSuggestionsWidget::execute( QString &formatStr, QWidget *parent, const char *name )
+ {
+ KDialogBase * dlg = new KDialogBase( parent, name, true, i18n( "Edit Id Suggestions" ), KDialogBase::Ok | KDialogBase::Cancel );
+ IdSuggestionsWidget* ui = new IdSuggestionsWidget( formatStr, dlg, "IdSuggestionsWidget" );
+ dlg->setMainWidget( ui );
+
+ QDialog::DialogCode result = ( QDialog::DialogCode ) dlg->exec();
+ if ( result == QDialog::Accepted )
+ ui->apply( formatStr );
+
+ delete( ui );
+ delete( dlg );
+
+ return result;
+ }
+
+ void IdSuggestionsWidget::reset( const QString& formatStr )
+ {
+ QLayoutIterator it = m_listOfComponents->layout()->iterator();
+ QLayoutItem *child;
+ while (( child = it.current() ) != 0 )
+ {
+ IdSuggestionComponent *component = dynamic_cast<IdSuggestionComponent*>( child->widget() );
+ ++it;
+ if ( component != NULL )
+ delete component;
+ }
+
+ m_componentCount = 0;
+ QStringList lines = QStringList::split( '|', formatStr );
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end();++it )
+ {
+ IdSuggestionComponent *component = NULL;
+ if (( *it )[0] == 'a' || ( *it )[0] == 'A' )
+ component = new IdSuggestionComponentAuthor( *it, m_listOfComponents );
+ else if (( *it )[0] == 't' || ( *it )[0] == 'T' )
+ component = new IdSuggestionComponentTitle( *it, m_listOfComponents );
+ else if (( *it )[0] == 'y' || ( *it )[0] == 'Y' )
+ component = new IdSuggestionComponentYear( *it, m_listOfComponents );
+ else if (( *it )[0] == '"' )
+ component = new IdSuggestionComponentText( *it, m_listOfComponents );
+
+ if ( component != NULL )
+ {
+ ++m_componentCount;
+ connect( component, SIGNAL( moved() ), this, SLOT( updateGUI() ) );
+ connect( component, SIGNAL( deleted() ), this, SLOT( componentDeleted() ) );
+ connect( component, SIGNAL( modified() ), this, SLOT( updateExample() ) );
+ }
+ }
+
+ m_listOfComponents->adjustSize();
+ m_scrollViewComponents->verticalScrollBar()->adjustSize();
+ updateGUI();
+ m_scrollViewComponents->resize( m_scrollViewComponents->width(), min( 384, m_listOfComponents->height() + 2 ) );
+ }
+
+ void IdSuggestionsWidget::apply( QString& formatStr )
+ {
+ bool first = TRUE;
+ formatStr = "";
+ QLayoutIterator it = m_listOfComponents->layout()->iterator();
+ QLayoutItem *child;
+ while (( child = it.current() ) != 0 )
+ {
+ IdSuggestionComponent *component = dynamic_cast<IdSuggestionComponent*>( child->widget() );
+ QString text = QString::null;
+ if ( component != NULL && ( text = component->text() ) != QString::null )
+ {
+ if ( first ) first = FALSE; else formatStr.append( "|" );
+ formatStr.append( text );
+ }
+ ++it;
+ }
+ }
+
+ void IdSuggestionsWidget::setupGUI()
+ {
+ QGridLayout *gridLayout = new QGridLayout( this, 3, 2, 0, KDialog::spacingHint() );
+ gridLayout->setRowStretch( 2, 1 );
+ gridLayout->setColStretch( 0, 1 );
+
+ m_labelExample = new QLabel( this );
+ gridLayout->addMultiCellWidget( m_labelExample, 0, 1, 0, 0 );
+
+ m_pushButtonAdd = new KPushButton( i18n( "Add" ), this );
+ gridLayout->addWidget( m_pushButtonAdd, 1, 1 );
+
+ m_scrollViewComponents = new IdSuggestionsScrollView( this );
+ m_listOfComponents = new QWidget( m_scrollViewComponents->viewport() );
+ m_scrollViewComponents->setMainWidget( m_listOfComponents );
+ m_scrollViewComponents->addChild( m_listOfComponents );
+ gridLayout->addMultiCellWidget( m_scrollViewComponents, 2, 2, 0, 1 );
+ QVBoxLayout *listLayout = new QVBoxLayout( m_listOfComponents, 0, KDialog::spacingHint() );
+ listLayout->setAutoAdd( TRUE );
+
+ KPopupMenu *addMenu = new KPopupMenu( m_pushButtonAdd );
+ addMenu->insertItem( i18n( "Author" ), 1 );
+ addMenu->insertItem( i18n( "Year" ), 2 );
+ addMenu->insertItem( i18n( "Title" ), 3 );
+ addMenu->insertItem( i18n( "Text" ), 4 );
+ connect( addMenu, SIGNAL( activated( int ) ), this, SLOT( addMenuActivated( int ) ) );
+ m_pushButtonAdd->setPopup( addMenu );
+ }
+
+ void IdSuggestionsWidget::addMenuActivated( int id )
+ {
+ IdSuggestionComponent *comp = NULL;
+ if ( id == 1 )
+ comp = new IdSuggestionComponentAuthor( "a", m_listOfComponents );
+ else if ( id == 2 )
+ comp = new IdSuggestionComponentYear( "y", m_listOfComponents );
+ else if ( id == 3 )
+ comp = new IdSuggestionComponentTitle( "t", m_listOfComponents );
+ else if ( id == 4 )
+ comp = new IdSuggestionComponentText( "", m_listOfComponents );
+
+ if ( comp != NULL )
+ {
+ ++m_componentCount;
+
+ comp->show();
+
+ connect( comp, SIGNAL( moved() ), this, SLOT( updateGUI() ) );
+ connect( comp, SIGNAL( deleted() ), this, SLOT( componentDeleted() ) );
+ connect( comp, SIGNAL( modified() ), this, SLOT( updateExample() ) );
+ m_listOfComponents->adjustSize();
+ m_scrollViewComponents->ensureVisible( 10, m_listOfComponents->height() - 2 );
+ updateGUI();
+ }
+ }
+
+ void IdSuggestionsWidget::updateGUI()
+ {
+ QLayoutIterator it = m_listOfComponents->layout()->iterator();
+ QLayoutItem *child = NULL;
+ IdSuggestionComponent *lastComponent = NULL;
+ bool first = TRUE;
+ int i = 0;
+ while (( child = it.current() ) != 0 )
+ {
+ IdSuggestionComponent *component = dynamic_cast<IdSuggestionComponent*>( child->widget() );
+ ++it;
+ if ( component != NULL )
+ {
+ if ( first )
+ {
+ first = FALSE;
+ component->setEnableUpDown( FALSE, m_componentCount > 1 );
+ }
+ else
+ component->setEnableUpDown( TRUE, i < m_componentCount - 1 );
+
+ ++i;
+ lastComponent = component;
+ }
+ }
+
+ if ( lastComponent != NULL )
+ lastComponent->setEnableUpDown( m_componentCount > 1, FALSE );
+
+ m_scrollViewComponents->updateGeometry();
+ m_parent->enableButtonOK( m_componentCount > 0 );
+ updateExample();
+ }
+
+ void IdSuggestionsWidget::componentDeleted()
+ {
+ --m_componentCount;
+ updateGUI();
+ }
+
+ void IdSuggestionsWidget::updateExample()
+ {
+ QString formatStr;
+ apply( formatStr );
+ QString formatted = IdSuggestions::formatId( m_example, formatStr );
+ m_labelExample->setText( QString( i18n( "<qt>Example:<br/><b>%1</b></qt>" ) ).arg( formatted ) );
+ }
+
+}
+#include "idsuggestionswidget.moc"
diff --git a/src/idsuggestionswidget.h b/src/idsuggestionswidget.h
new file mode 100644
index 0000000..103029c
--- /dev/null
+++ b/src/idsuggestionswidget.h
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXIDSUGGESTIONSWIDGET_H
+#define KBIBTEXIDSUGGESTIONSWIDGET_H
+
+#include <qwidget.h>
+#include <qdialog.h>
+
+class QCheckBox;
+class QScrollView;
+class QSpinBox;
+class KComboBox;
+class KLineEdit;
+class KPushButton;
+
+namespace KBibTeX
+{
+ class IdSuggestionComponent: public QFrame
+ {
+ Q_OBJECT
+ public:
+ IdSuggestionComponent( const QString& title, QWidget *parent );
+ virtual QString text() const = 0;
+ void setEnableUpDown( bool enableUp, bool enableDown );
+
+ signals:
+ void modified();
+ void moved();
+ void deleted();
+
+ protected:
+ QWidget *moveWidgets( QWidget *parent );
+
+ bool m_toBeDeleted;
+ QString m_title;
+ QWidget *m_parent;
+ KPushButton *m_pushButtonDel;
+ KPushButton *m_pushButtonUp;
+ KPushButton *m_pushButtonDown;
+
+ protected slots:
+ void slotUp();
+ void slotDown();
+ void slotDelete();
+ };
+
+ class IdSuggestionComponentAuthor: public IdSuggestionComponent
+ {
+ public:
+ IdSuggestionComponentAuthor( const QString &text, QWidget *parent );
+ QString text() const;
+ protected:
+ KComboBox *m_comboBoxWhichAuthors;
+ KComboBox *m_comboBoxCasing;
+ KLineEdit *m_lineEditInBetween;
+ QSpinBox *m_spinBoxLen;
+ };
+
+ class IdSuggestionComponentTitle: public IdSuggestionComponent
+ {
+ public:
+ IdSuggestionComponentTitle( const QString &text, QWidget *parent );
+ QString text() const;
+ protected:
+ QCheckBox *m_checkBoxRemoveSmallWords;
+ KComboBox *m_comboBoxCasing;
+ KLineEdit *m_lineEditInBetween;
+ QSpinBox *m_spinBoxLen;
+ };
+
+ class IdSuggestionComponentYear: public IdSuggestionComponent
+ {
+ public:
+ IdSuggestionComponentYear( const QString &text, QWidget *parent );
+ QString text() const;
+ protected:
+ KComboBox *m_comboBoxDigits;
+ };
+
+ class IdSuggestionComponentText: public IdSuggestionComponent
+ {
+ public:
+ IdSuggestionComponentText( const QString &text, QWidget *parent );
+ QString text() const;
+ protected:
+ KLineEdit *m_lineEditInBetween;
+ };
+
+ class IdSuggestionsScrollView : public QScrollView
+ {
+ Q_OBJECT
+ public:
+ IdSuggestionsScrollView( QWidget *parent, const char*name = NULL );
+ ~IdSuggestionsScrollView();
+
+ void setMainWidget( QWidget *widget ) {m_widget = widget;}
+
+ protected:
+ void viewportResizeEvent( QResizeEvent * );
+
+ private:
+ QWidget *m_widget;
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class IdSuggestionsWidget : public QWidget
+ {
+ Q_OBJECT
+ public:
+ ~IdSuggestionsWidget();
+ int numComponents();
+
+ static QDialog::DialogCode execute( QString &formatStr, QWidget *parent = 0, const char *name = 0 );
+
+ protected:
+ IdSuggestionsWidget( const QString &formatStr, KDialogBase *parent, const char *name = 0 );
+
+ QString m_originalFormatStr;
+ int m_componentCount;
+
+ void reset( const QString& formatStr );
+ void apply( QString& formatStr );
+
+ private:
+ static QString exampleBibTeXEntry;
+ BibTeX::Entry *m_example;
+ IdSuggestionsScrollView *m_scrollViewComponents;
+ QLabel *m_labelExample;
+ QWidget *m_listOfComponents;
+ KPushButton *m_pushButtonAdd;
+ KDialogBase *m_parent;
+
+ void setupGUI();
+
+ private slots:
+ void addMenuActivated( int id );
+ void updateGUI();
+ void componentDeleted();
+ void updateExample();
+ };
+
+}
+
+#endif
diff --git a/src/iso5426converter.cpp b/src/iso5426converter.cpp
new file mode 100644
index 0000000..3b40d5d
--- /dev/null
+++ b/src/iso5426converter.cpp
@@ -0,0 +1,892 @@
+/***************************************************************************
+ copyright : (C) 2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+// This class is adapted from Iso5426ToUnicode from the MARC4J project, available
+// from http://marc4j.tigris.org, with the following notice:
+// * Copyright (C) 2002 Bas Peters ([email protected])
+// * Copyright (C) 2002 Yves Pratter ([email protected])
+//
+// That source was released under the terms of the GNU Lesser General Public
+// License, version 2.1. In accordance with Condition 3 of that license,
+// I am applying the terms of the GNU General Public License to the source
+// code, and including a large portion of it here
+
+#include "iso5426converter.h"
+#include <kdebug.h>
+
+#include <qstring.h>
+
+using KBibTeX::Iso5426Converter;
+
+QString Iso5426Converter::toUtf8(const QCString& text_) {
+ const uint len = text_.length();
+ QString result;
+ result.reserve(len);
+ uint pos = 0;
+ for(uint i = 0; i < len; ++i) {
+ uchar c = text_[i];
+ if(isAscii(c)) {
+ result[pos++] = c;
+ } else if(isCombining(c) && hasNext(i, len)) {
+ // this is a hack
+ // use the diaeresis instead of umlaut
+ // works for SUDOC
+ if(c == 0xC9) {
+ c = 0xC8;
+ }
+ QChar d = getCombiningChar(c * 256 + text_[i + 1]);
+ if(!d.isNull()) {
+ result[pos++] = d;
+ ++i;
+ } else {
+ result[pos++] = getChar(c);
+ }
+ } else {
+ result[pos++] = getChar(c);
+ }
+ }
+ result.squeeze();
+ return result;
+}
+
+inline
+bool Iso5426Converter::hasNext(uint pos, uint len) {
+ return pos < (len - 1);
+}
+
+inline
+bool Iso5426Converter::isAscii(uchar c) {
+ return c <= 0x7F;
+}
+
+inline
+bool Iso5426Converter::isCombining(uchar c) {
+ return c >= 0xC0 && c <= 0xDF;
+}
+
+// Source : http://www.itscj.ipsj.or.jp/ISO-IR/053.pdf
+QChar Iso5426Converter::getChar(uchar c) {
+ switch(c) {
+ case 0xA1:
+ return 0x00A1; // 2/1 inverted exclamation mark
+ case 0xA2:
+ return 0x201C; // 2/2 left low double quotation mark
+ case 0xA3:
+ return 0x00A3; // 2/3 pound sign
+ case 0xA4:
+ return 0x0024; // 2/4 dollar sign
+ case 0xA5:
+ return 0x00A5; // 2/5 yen sign
+ case 0xA6:
+ return 0x2020; // 2/6 single dagger
+ case 0xA7:
+ return 0x00A7; // 2/7 paragraph (section)
+ case 0xA8:
+ return 0x2032; // 2/8 prime
+ case 0xA9:
+ return 0x2018; // 2/9 left high single quotation mark
+ case 0xAA:
+ return 0x201C; // 2/10 left high double quotation mark
+ case 0xAB:
+ return 0x00AB; // 2/11 left angle quotation mark
+ case 0xAC:
+ return 0x266D; // 2/12 music flat
+ case 0xAD:
+ return 0x00A9; // 2/13 copyright sign
+ case 0xAE:
+ return 0x2117; // 2/14 sound recording copyright sign
+ case 0xAF:
+ return 0x00AE; // 2/15 trade mark sign
+
+ case 0xB0:
+ return 0x0639; // 3/0 ayn [ain]
+ case 0xB1:
+ return 0x0623; // 3/1 alif/hamzah [alef with hamza above]
+ case 0xB2:
+ return 0x2018; // 3/2 left low single quotation mark
+ // 3/3 (this position shall not be used)
+ // 3/4 (this position shall not be used)
+ // 3/5 (this position shall not be used)
+ case 0xB6:
+ return 0x2021; // 3/6 double dagger
+ case 0xB7:
+ return 0x00B7; // 3/7 middle dot
+ case 0xB8:
+ return 0x2033; // 3/8 double prime
+ case 0xB9:
+ return 0x2019; // 3/9 right high single quotation mark
+ case 0xBA:
+ return 0x201D; // 3/10 right high double quotation mark
+ case 0xBB:
+ return 0x00BB; // 3/11 right angle quotation mark
+ case 0xBC:
+ return 0x266F; // 3/12 musical sharp
+ case 0xBD:
+ return 0x02B9; // 3/13 mjagkij znak
+ case 0xBE:
+ return 0x02BA; // 3/14 tverdyj znak
+ case 0xBF:
+ return 0x00BF; // 3/15 inverted question mark
+
+ // 4/0 to 5/15 diacritic characters
+
+ // 6/0 (this position shall not be used)
+ case 0xE1:
+ return 0x00C6; // 6/1 CAPITAL DIPHTHONG A WITH E
+ case 0xE2:
+ return 0x0110; // 6/2 CAPITAL LETTER D WITH STROKE
+ // 6/3 (this position shall not be used)
+ // 6/4 (this position shall not be used)
+ // 6/5 (this position shall not be used)
+ case 0xE6:
+ return 0x0132; // 6/6 CAPITAL LETTER IJ
+ // 6/7 (this position shall not be used)
+ case 0xE8:
+ return 0x0141; // 6/8 CAPITAL LETTER L WITH STROKE
+ case 0xE9:
+ return 0x00D8; // 6/9 CAPITAL LETTER O WITH SOLIDUS [oblique stroke]
+ case 0xEA:
+ return 0x0152; // 6/10 CAPITAL DIPHTONG OE
+ // 6/11 (this position shall not be used)
+ case 0xEC:
+ return 0x00DE; // 6/12 CAPITAL LETTER THORN
+ // 6/13 (this position shall not be used)
+ // 6/14 (this position shall not be used)
+ // 6/15 (this position shall not be used)
+
+ // 7/0 (this position shall not be used)
+ case 0xF1:
+ return 0x00E6; // 7/1 small diphthong a with e
+ // 7/4 (this position shall not be used)
+ case 0xF5:
+ return 0x0131; // 7/5 small letter i without dot
+ case 0xF6:
+ return 0x0133; // 7/6 small letter ij
+ // 7/7 (this position shall not be used)
+ case 0xF8:
+ return 0x0142; // 7/8 small letter l with stroke
+ case 0xF9:
+ return 0x00F8; // 7/9 small letter o with solidus (oblique stroke)
+ case 0xFA:
+ return 0x0153; // 7/10 small diphtong oe
+ case 0xFB:
+ return 0x00DF; // 7/11 small letter sharp s
+ case 0xFC:
+ return 0x00FE; // 7/12 small letter thorn
+ // 7/13 (this position shall not be used)
+ // 7/14 (this position shall not be used)
+ default:
+ return c;
+ }
+}
+
+QChar Iso5426Converter::getCombiningChar(uint c) {
+ switch(c) {
+ // 4/0 low rising tone mark
+ case 0xC041:
+ return 0x1EA2; // CAPITAL A WITH HOOK ABOVE
+ case 0xC045:
+ return 0x1EBA; // CAPITAL E WITH HOOK ABOVE
+ case 0xC049:
+ return 0x1EC8; // CAPITAL I WITH HOOK ABOVE
+ case 0xC04F:
+ return 0x1ECE; // CAPITAL O WITH HOOK ABOVE
+ case 0xC055:
+ return 0x1EE6; // CAPITAL U WITH HOOK ABOVE
+ case 0xC059:
+ return 0x1EF6; // CAPITAL Y WITH HOOK ABOVE
+ case 0xC061:
+ return 0x1EA3; // small a with hook above
+ case 0xC065:
+ return 0x1EBB; // small e with hook above
+ case 0xC069:
+ return 0x1EC9; // small i with hook above
+ case 0xC06F:
+ return 0x1ECF; // small o with hook above
+ case 0xC075:
+ return 0x1EE7; // small u with hook above
+ case 0xC079:
+ return 0x1EF7; // small y with hook above
+
+ // 4/1 grave accent
+ case 0xC141:
+ return 0x00C0; // CAPITAL A WITH GRAVE ACCENT
+ case 0xC145:
+ return 0x00C8; // CAPITAL E WITH GRAVE ACCENT
+ case 0xC149:
+ return 0x00CC; // CAPITAL I WITH GRAVE ACCENT
+ case 0xC14F:
+ return 0x00D2; // CAPITAL O WITH GRAVE ACCENT
+ case 0xC155:
+ return 0x00D9; // CAPITAL U WITH GRAVE ACCENT
+ case 0xC157:
+ return 0x1E80; // CAPITAL W WITH GRAVE
+ case 0xC159:
+ return 0x1EF2; // CAPITAL Y WITH GRAVE
+ case 0xC161:
+ return 0x00E0; // small a with grave accent
+ case 0xC165:
+ return 0x00E8; // small e with grave accent
+ case 0xC169:
+ return 0x00EC; // small i with grave accent
+ case 0xC16F:
+ return 0x00F2; // small o with grave accent
+ case 0xC175:
+ return 0x00F9; // small u with grave accent
+ case 0xC177:
+ return 0x1E81; // small w with grave
+ case 0xC179:
+ return 0x1EF3; // small y with grave
+
+ // 4/2 acute accent
+ case 0xC241:
+ return 0x00C1; // CAPITAL A WITH ACUTE ACCENT
+ case 0xC243:
+ return 0x0106; // CAPITAL C WITH ACUTE ACCENT
+ case 0xC245:
+ return 0x00C9; // CAPITAL E WITH ACUTE ACCENT
+ case 0xC247:
+ return 0x01F4; // CAPITAL G WITH ACUTE
+ case 0xC249:
+ return 0x00CD; // CAPITAL I WITH ACUTE ACCENT
+ case 0xC24B:
+ return 0x1E30; // CAPITAL K WITH ACUTE
+ case 0xC24C:
+ return 0x0139; // CAPITAL L WITH ACUTE ACCENT
+ case 0xC24D:
+ return 0x1E3E; // CAPITAL M WITH ACUTE
+ case 0xC24E:
+ return 0x0143; // CAPITAL N WITH ACUTE ACCENT
+ case 0xC24F:
+ return 0x00D3; // CAPITAL O WITH ACUTE ACCENT
+ case 0xC250:
+ return 0x1E54; // CAPITAL P WITH ACUTE
+ case 0xC252:
+ return 0x0154; // CAPITAL R WITH ACUTE ACCENT
+ case 0xC253:
+ return 0x015A; // CAPITAL S WITH ACUTE ACCENT
+ case 0xC255:
+ return 0x00DA; // CAPITAL U WITH ACUTE ACCENT
+ case 0xC257:
+ return 0x1E82; // CAPITAL W WITH ACUTE
+ case 0xC259:
+ return 0x00DD; // CAPITAL Y WITH ACUTE ACCENT
+ case 0xC25A:
+ return 0x0179; // CAPITAL Z WITH ACUTE ACCENT
+ case 0xC261:
+ return 0x00E1; // small a with acute accent
+ case 0xC263:
+ return 0x0107; // small c with acute accent
+ case 0xC265:
+ return 0x00E9; // small e with acute accent
+ case 0xC267:
+ return 0x01F5; // small g with acute
+ case 0xC269:
+ return 0x00ED; // small i with acute accent
+ case 0xC26B:
+ return 0x1E31; // small k with acute
+ case 0xC26C:
+ return 0x013A; // small l with acute accent
+ case 0xC26D:
+ return 0x1E3F; // small m with acute
+ case 0xC26E:
+ return 0x0144; // small n with acute accent
+ case 0xC26F:
+ return 0x00F3; // small o with acute accent
+ case 0xC270:
+ return 0x1E55; // small p with acute
+ case 0xC272:
+ return 0x0155; // small r with acute accent
+ case 0xC273:
+ return 0x015B; // small s with acute accent
+ case 0xC275:
+ return 0x00FA; // small u with acute accent
+ case 0xC277:
+ return 0x1E83; // small w with acute
+ case 0xC279:
+ return 0x00FD; // small y with acute accent
+ case 0xC27A:
+ return 0x017A; // small z with acute accent
+ case 0xC2E1:
+ return 0x01FC; // CAPITAL AE WITH ACUTE
+ case 0xC2F1:
+ return 0x01FD; // small ae with acute
+
+ // 4/3 circumflex accent
+ case 0xC341:
+ return 0x00C2; // CAPITAL A WITH CIRCUMFLEX ACCENT
+ case 0xC343:
+ return 0x0108; // CAPITAL C WITH CIRCUMFLEX
+ case 0xC345:
+ return 0x00CA; // CAPITAL E WITH CIRCUMFLEX ACCENT
+ case 0xC347:
+ return 0x011C; // CAPITAL G WITH CIRCUMFLEX
+ case 0xC348:
+ return 0x0124; // CAPITAL H WITH CIRCUMFLEX
+ case 0xC349:
+ return 0x00CE; // CAPITAL I WITH CIRCUMFLEX ACCENT
+ case 0xC34A:
+ return 0x0134; // CAPITAL J WITH CIRCUMFLEX
+ case 0xC34F:
+ return 0x00D4; // CAPITAL O WITH CIRCUMFLEX ACCENT
+ case 0xC353:
+ return 0x015C; // CAPITAL S WITH CIRCUMFLEX
+ case 0xC355:
+ return 0x00DB; // CAPITAL U WITH CIRCUMFLEX
+ case 0xC357:
+ return 0x0174; // CAPITAL W WITH CIRCUMFLEX
+ case 0xC359:
+ return 0x0176; // CAPITAL Y WITH CIRCUMFLEX
+ case 0xC35A:
+ return 0x1E90; // CAPITAL Z WITH CIRCUMFLEX
+ case 0xC361:
+ return 0x00E2; // small a with circumflex accent
+ case 0xC363:
+ return 0x0109; // small c with circumflex
+ case 0xC365:
+ return 0x00EA; // small e with circumflex accent
+ case 0xC367:
+ return 0x011D; // small g with circumflex
+ case 0xC368:
+ return 0x0125; // small h with circumflex
+ case 0xC369:
+ return 0x00EE; // small i with circumflex accent
+ case 0xC36A:
+ return 0x0135; // small j with circumflex
+ case 0xC36F:
+ return 0x00F4; // small o with circumflex accent
+ case 0xC373:
+ return 0x015D; // small s with circumflex
+ case 0xC375:
+ return 0x00FB; // small u with circumflex
+ case 0xC377:
+ return 0x0175; // small w with circumflex
+ case 0xC379:
+ return 0x0177; // small y with circumflex
+ case 0xC37A:
+ return 0x1E91; // small z with circumflex
+
+ // 4/4 tilde
+ case 0xC441:
+ return 0x00C3; // CAPITAL A WITH TILDE
+ case 0xC445:
+ return 0x1EBC; // CAPITAL E WITH TILDE
+ case 0xC449:
+ return 0x0128; // CAPITAL I WITH TILDE
+ case 0xC44E:
+ return 0x00D1; // CAPITAL N WITH TILDE
+ case 0xC44F:
+ return 0x00D5; // CAPITAL O WITH TILDE
+ case 0xC455:
+ return 0x0168; // CAPITAL U WITH TILDE
+ case 0xC456:
+ return 0x1E7C; // CAPITAL V WITH TILDE
+ case 0xC459:
+ return 0x1EF8; // CAPITAL Y WITH TILDE
+ case 0xC461:
+ return 0x00E3; // small a with tilde
+ case 0xC465:
+ return 0x1EBD; // small e with tilde
+ case 0xC469:
+ return 0x0129; // small i with tilde
+ case 0xC46E:
+ return 0x00F1; // small n with tilde
+ case 0xC46F:
+ return 0x00F5; // small o with tilde
+ case 0xC475:
+ return 0x0169; // small u with tilde
+ case 0xC476:
+ return 0x1E7D; // small v with tilde
+ case 0xC479:
+ return 0x1EF9; // small y with tilde
+
+ // 4/5 macron
+ case 0xC541:
+ return 0x0100; // CAPITAL A WITH MACRON
+ case 0xC545:
+ return 0x0112; // CAPITAL E WITH MACRON
+ case 0xC547:
+ return 0x1E20; // CAPITAL G WITH MACRON
+ case 0xC549:
+ return 0x012A; // CAPITAL I WITH MACRON
+ case 0xC54F:
+ return 0x014C; // CAPITAL O WITH MACRON
+ case 0xC555:
+ return 0x016A; // CAPITAL U WITH MACRON
+ case 0xC561:
+ return 0x0101; // small a with macron
+ case 0xC565:
+ return 0x0113; // small e with macron
+ case 0xC567:
+ return 0x1E21; // small g with macron
+ case 0xC569:
+ return 0x012B; // small i with macron
+ case 0xC56F:
+ return 0x014D; // small o with macron
+ case 0xC575:
+ return 0x016B; // small u with macron
+ case 0xC5E1:
+ return 0x01E2; // CAPITAL AE WITH MACRON
+ case 0xC5F1:
+ return 0x01E3; // small ae with macron
+
+ // 4/6 breve
+ case 0xC641:
+ return 0x0102; // CAPITAL A WITH BREVE
+ case 0xC645:
+ return 0x0114; // CAPITAL E WITH BREVE
+ case 0xC647:
+ return 0x011E; // CAPITAL G WITH BREVE
+ case 0xC649:
+ return 0x012C; // CAPITAL I WITH BREVE
+ case 0xC64F:
+ return 0x014E; // CAPITAL O WITH BREVE
+ case 0xC655:
+ return 0x016C; // CAPITAL U WITH BREVE
+ case 0xC661:
+ return 0x0103; // small a with breve
+ case 0xC665:
+ return 0x0115; // small e with breve
+ case 0xC667:
+ return 0x011F; // small g with breve
+ case 0xC669:
+ return 0x012D; // small i with breve
+ case 0xC66F:
+ return 0x014F; // small o with breve
+ case 0xC675:
+ return 0x016D; // small u with breve
+
+ // 4/7 dot above
+ case 0xC742:
+ return 0x1E02; // CAPITAL B WITH DOT ABOVE
+ case 0xC743:
+ return 0x010A; // CAPITAL C WITH DOT ABOVE
+ case 0xC744:
+ return 0x1E0A; // CAPITAL D WITH DOT ABOVE
+ case 0xC745:
+ return 0x0116; // CAPITAL E WITH DOT ABOVE
+ case 0xC746:
+ return 0x1E1E; // CAPITAL F WITH DOT ABOVE
+ case 0xC747:
+ return 0x0120; // CAPITAL G WITH DOT ABOVE
+ case 0xC748:
+ return 0x1E22; // CAPITAL H WITH DOT ABOVE
+ case 0xC749:
+ return 0x0130; // CAPITAL I WITH DOT ABOVE
+ case 0xC74D:
+ return 0x1E40; // CAPITAL M WITH DOT ABOVE
+ case 0xC74E:
+ return 0x1E44; // CAPITAL N WITH DOT ABOVE
+ case 0xC750:
+ return 0x1E56; // CAPITAL P WITH DOT ABOVE
+ case 0xC752:
+ return 0x1E58; // CAPITAL R WITH DOT ABOVE
+ case 0xC753:
+ return 0x1E60; // CAPITAL S WITH DOT ABOVE
+ case 0xC754:
+ return 0x1E6A; // CAPITAL T WITH DOT ABOVE
+ case 0xC757:
+ return 0x1E86; // CAPITAL W WITH DOT ABOVE
+ case 0xC758:
+ return 0x1E8A; // CAPITAL X WITH DOT ABOVE
+ case 0xC759:
+ return 0x1E8E; // CAPITAL Y WITH DOT ABOVE
+ case 0xC75A:
+ return 0x017B; // CAPITAL Z WITH DOT ABOVE
+ case 0xC762:
+ return 0x1E03; // small b with dot above
+ case 0xC763:
+ return 0x010B; // small c with dot above
+ case 0xC764:
+ return 0x1E0B; // small d with dot above
+ case 0xC765:
+ return 0x0117; // small e with dot above
+ case 0xC766:
+ return 0x1E1F; // small f with dot above
+ case 0xC767:
+ return 0x0121; // small g with dot above
+ case 0xC768:
+ return 0x1E23; // small h with dot above
+ case 0xC76D:
+ return 0x1E41; // small m with dot above
+ case 0xC76E:
+ return 0x1E45; // small n with dot above
+ case 0xC770:
+ return 0x1E57; // small p with dot above
+ case 0xC772:
+ return 0x1E59; // small r with dot above
+ case 0xC773:
+ return 0x1E61; // small s with dot above
+ case 0xC774:
+ return 0x1E6B; // small t with dot above
+ case 0xC777:
+ return 0x1E87; // small w with dot above
+ case 0xC778:
+ return 0x1E8B; // small x with dot above
+ case 0xC779:
+ return 0x1E8F; // small y with dot above
+ case 0xC77A:
+ return 0x017C; // small z with dot above
+
+ // 4/8 trema, diaresis
+ case 0xC820:
+ return 0x00A8; // diaeresis
+ case 0xC841:
+ return 0x00C4; // CAPITAL A WITH DIAERESIS
+ case 0xC845:
+ return 0x00CB; // CAPITAL E WITH DIAERESIS
+ case 0xC848:
+ return 0x1E26; // CAPITAL H WITH DIAERESIS
+ case 0xC849:
+ return 0x00CF; // CAPITAL I WITH DIAERESIS
+ case 0xC84F:
+ return 0x00D6; // CAPITAL O WITH DIAERESIS
+ case 0xC855:
+ return 0x00DC; // CAPITAL U WITH DIAERESIS
+ case 0xC857:
+ return 0x1E84; // CAPITAL W WITH DIAERESIS
+ case 0xC858:
+ return 0x1E8C; // CAPITAL X WITH DIAERESIS
+ case 0xC859:
+ return 0x0178; // CAPITAL Y WITH DIAERESIS
+ case 0xC861:
+ return 0x00E4; // small a with diaeresis
+ case 0xC865:
+ return 0x00EB; // small e with diaeresis
+ case 0xC868:
+ return 0x1E27; // small h with diaeresis
+ case 0xC869:
+ return 0x00EF; // small i with diaeresis
+ case 0xC86F:
+ return 0x00F6; // small o with diaeresis
+ case 0xC874:
+ return 0x1E97; // small t with diaeresis
+ case 0xC875:
+ return 0x00FC; // small u with diaeresis
+ case 0xC877:
+ return 0x1E85; // small w with diaeresis
+ case 0xC878:
+ return 0x1E8D; // small x with diaeresis
+ case 0xC879:
+ return 0x00FF; // small y with diaeresis
+
+ // 4/9 umlaut
+ case 0xC920:
+ return 0x00A8; // [diaeresis]
+
+ // 4/10 circle above
+ case 0xCA41:
+ return 0x00C5; // CAPITAL A WITH RING ABOVE
+ case 0xCAAD:
+ return 0x016E; // CAPITAL U WITH RING ABOVE
+ case 0xCA61:
+ return 0x00E5; // small a with ring above
+ case 0xCA75:
+ return 0x016F; // small u with ring above
+ case 0xCA77:
+ return 0x1E98; // small w with ring above
+ case 0xCA79:
+ return 0x1E99; // small y with ring above
+
+ // 4/11 high comma off centre
+
+ // 4/12 inverted high comma centred
+
+ // 4/13 double acute accent
+ case 0xCD4F:
+ return 0x0150; // CAPITAL O WITH DOUBLE ACUTE
+ case 0xCD55:
+ return 0x0170; // CAPITAL U WITH DOUBLE ACUTE
+ case 0xCD6F:
+ return 0x0151; // small o with double acute
+ case 0xCD75:
+ return 0x0171; // small u with double acute
+
+ // 4/14 horn
+ case 0xCE54:
+ return 0x01A0; // LATIN CAPITAL LETTER O WITH HORN
+ case 0xCE55:
+ return 0x01AF; // LATIN CAPITAL LETTER U WITH HORN
+ case 0xCE74:
+ return 0x01A1; // latin small letter o with horn
+ case 0xCE75:
+ return 0x01B0; // latin small letter u with horn
+
+ // 4/15 caron (hacek)
+ case 0xCF41:
+ return 0x01CD; // CAPITAL A WITH CARON
+ case 0xCF43:
+ return 0x010C; // CAPITAL C WITH CARON
+ case 0xCF44:
+ return 0x010E; // CAPITAL D WITH CARON
+ case 0xCF45:
+ return 0x011A; // CAPITAL E WITH CARON
+ case 0xCF47:
+ return 0x01E6; // CAPITAL G WITH CARON
+ case 0xCF49:
+ return 0x01CF; // CAPITAL I WITH CARON
+ case 0xCF4B:
+ return 0x01E8; // CAPITAL K WITH CARON
+ case 0xCF4C:
+ return 0x013D; // CAPITAL L WITH CARON
+ case 0xCF4E:
+ return 0x0147; // CAPITAL N WITH CARON
+ case 0xCF4F:
+ return 0x01D1; // CAPITAL O WITH CARON
+ case 0xCF52:
+ return 0x0158; // CAPITAL R WITH CARON
+ case 0xCF53:
+ return 0x0160; // CAPITAL S WITH CARON
+ case 0xCF54:
+ return 0x0164; // CAPITAL T WITH CARON
+ case 0xCF55:
+ return 0x01D3; // CAPITAL U WITH CARON
+ case 0xCF5A:
+ return 0x017D; // CAPITAL Z WITH CARON
+ case 0xCF61:
+ return 0x01CE; // small a with caron
+ case 0xCF63:
+ return 0x010D; // small c with caron
+ case 0xCF64:
+ return 0x010F; // small d with caron
+ case 0xCF65:
+ return 0x011B; // small e with caron
+ case 0xCF67:
+ return 0x01E7; // small g with caron
+ case 0xCF69:
+ return 0x01D0; // small i with caron
+ case 0xCF6A:
+ return 0x01F0; // small j with caron
+ case 0xCF6B:
+ return 0x01E9; // small k with caron
+ case 0xCF6C:
+ return 0x013E; // small l with caron
+ case 0xCF6E:
+ return 0x0148; // small n with caron
+ case 0xCF6F:
+ return 0x01D2; // small o with caron
+ case 0xCF72:
+ return 0x0159; // small r with caron
+ case 0xCF73:
+ return 0x0161; // small s with caron
+ case 0xCF74:
+ return 0x0165; // small t with caron
+ case 0xCF75:
+ return 0x01D4; // small u with caron
+ case 0xCF7A:
+ return 0x017E; // small z with caron
+
+ // 5/0 cedilla
+ case 0xD020:
+ return 0x00B8; // cedilla
+ case 0xD043:
+ return 0x00C7; // CAPITAL C WITH CEDILLA
+ case 0xD044:
+ return 0x1E10; // CAPITAL D WITH CEDILLA
+ case 0xD047:
+ return 0x0122; // CAPITAL G WITH CEDILLA
+ case 0xD048:
+ return 0x1E28; // CAPITAL H WITH CEDILLA
+ case 0xD04B:
+ return 0x0136; // CAPITAL K WITH CEDILLA
+ case 0xD04C:
+ return 0x013B; // CAPITAL L WITH CEDILLA
+ case 0xD04E:
+ return 0x0145; // CAPITAL N WITH CEDILLA
+ case 0xD052:
+ return 0x0156; // CAPITAL R WITH CEDILLA
+ case 0xD053:
+ return 0x015E; // CAPITAL S WITH CEDILLA
+ case 0xD054:
+ return 0x0162; // CAPITAL T WITH CEDILLA
+ case 0xD063:
+ return 0x00E7; // small c with cedilla
+ case 0xD064:
+ return 0x1E11; // small d with cedilla
+ case 0xD067:
+ return 0x0123; // small g with cedilla
+ case 0xD068:
+ return 0x1E29; // small h with cedilla
+ case 0xD06B:
+ return 0x0137; // small k with cedilla
+ case 0xD06C:
+ return 0x013C; // small l with cedilla
+ case 0xD06E:
+ return 0x0146; // small n with cedilla
+ case 0xD072:
+ return 0x0157; // small r with cedilla
+ case 0xD073:
+ return 0x015F; // small s with cedilla
+ case 0xD074:
+ return 0x0163; // small t with cedilla
+
+ // 5/1 rude
+
+ // 5/2 hook to left
+
+ // 5/3 ogonek (hook to right)
+ case 0xD320:
+ return 0x02DB; // ogonek
+ case 0xD341:
+ return 0x0104; // CAPITAL A WITH OGONEK
+ case 0xD345:
+ return 0x0118; // CAPITAL E WITH OGONEK
+ case 0xD349:
+ return 0x012E; // CAPITAL I WITH OGONEK
+ case 0xD34F:
+ return 0x01EA; // CAPITAL O WITH OGONEK
+ case 0xD355:
+ return 0x0172; // CAPITAL U WITH OGONEK
+ case 0xD361:
+ return 0x0105; // small a with ogonek
+ case 0xD365:
+ return 0x0119; // small e with ogonek
+ case 0xD369:
+ return 0x012F; // small i with ogonek
+ case 0xD36F:
+ return 0x01EB; // small o with ogonek
+ case 0xD375:
+ return 0x0173; // small u with ogonek
+
+ // 5/4 circle below
+ case 0xD441:
+ return 0x1E00; // CAPITAL A WITH RING BELOW
+ case 0xD461:
+ return 0x1E01; // small a with ring below
+
+ // 5/5 half circle below
+ case 0xF948:
+ return 0x1E2A; // CAPITAL H WITH BREVE BELOW
+ case 0xF968:
+ return 0x1E2B; // small h with breve below
+
+ // 5/6 dot below
+ case 0xD641:
+ return 0x1EA0; // CAPITAL A WITH DOT BELOW
+ case 0xD642:
+ return 0x1E04; // CAPITAL B WITH DOT BELOW
+ case 0xD644:
+ return 0x1E0C; // CAPITAL D WITH DOT BELOW
+ case 0xD645:
+ return 0x1EB8; // CAPITAL E WITH DOT BELOW
+ case 0xD648:
+ return 0x1E24; // CAPITAL H WITH DOT BELOW
+ case 0xD649:
+ return 0x1ECA; // CAPITAL I WITH DOT BELOW
+ case 0xD64B:
+ return 0x1E32; // CAPITAL K WITH DOT BELOW
+ case 0xD64C:
+ return 0x1E36; // CAPITAL L WITH DOT BELOW
+ case 0xD64D:
+ return 0x1E42; // CAPITAL M WITH DOT BELOW
+ case 0xD64E:
+ return 0x1E46; // CAPITAL N WITH DOT BELOW
+ case 0xD64F:
+ return 0x1ECC; // CAPITAL O WITH DOT BELOW
+ case 0xD652:
+ return 0x1E5A; // CAPITAL R WITH DOT BELOW
+ case 0xD653:
+ return 0x1E62; // CAPITAL S WITH DOT BELOW
+ case 0xD654:
+ return 0x1E6C; // CAPITAL T WITH DOT BELOW
+ case 0xD655:
+ return 0x1EE4; // CAPITAL U WITH DOT BELOW
+ case 0xD656:
+ return 0x1E7E; // CAPITAL V WITH DOT BELOW
+ case 0xD657:
+ return 0x1E88; // CAPITAL W WITH DOT BELOW
+ case 0xD659:
+ return 0x1EF4; // CAPITAL Y WITH DOT BELOW
+ case 0xD65A:
+ return 0x1E92; // CAPITAL Z WITH DOT BELOW
+ case 0xD661:
+ return 0x1EA1; // small a with dot below
+ case 0xD662:
+ return 0x1E05; // small b with dot below
+ case 0xD664:
+ return 0x1E0D; // small d with dot below
+ case 0xD665:
+ return 0x1EB9; // small e with dot below
+ case 0xD668:
+ return 0x1E25; // small h with dot below
+ case 0xD669:
+ return 0x1ECB; // small i with dot below
+ case 0xD66B:
+ return 0x1E33; // small k with dot below
+ case 0xD66C:
+ return 0x1E37; // small l with dot below
+ case 0xD66D:
+ return 0x1E43; // small m with dot below
+ case 0xD66E:
+ return 0x1E47; // small n with dot below
+ case 0xD66F:
+ return 0x1ECD; // small o with dot below
+ case 0xD672:
+ return 0x1E5B; // small r with dot below
+ case 0xD673:
+ return 0x1E63; // small s with dot below
+ case 0xD674:
+ return 0x1E6D; // small t with dot below
+ case 0xD675:
+ return 0x1EE5; // small u with dot below
+ case 0xD676:
+ return 0x1E7F; // small v with dot below
+ case 0xD677:
+ return 0x1E89; // small w with dot below
+ case 0xD679:
+ return 0x1EF5; // small y with dot below
+ case 0xD67A:
+ return 0x1E93; // small z with dot below
+
+ // 5/7 double dot below
+ case 0xD755:
+ return 0x1E72; // CAPITAL U WITH DIAERESIS BELOW
+ case 0xD775:
+ return 0x1E73; // small u with diaeresis below
+
+ // 5/8 underline
+ case 0xD820:
+ return 0x005F; // underline
+
+ // 5/9 double underline
+ case 0xD920:
+ return 0x2017; // double underline
+
+ // 5/10 small low vertical bar
+ case 0xDA20:
+ return 0x02CC; //
+
+ // 5/11 circumflex below
+
+ // 5/12 (this position shall not be used)
+
+ // 5/13 left half of ligature sign and of double tilde
+
+ // 5/14 right half of ligature sign
+
+ // 5/15 right half of double tilde
+
+ default:
+ kdDebug() << "Iso5426Converter::getCombiningChar() - no match for " << c << endl;
+ return QChar();
+ }
+}
diff --git a/src/iso5426converter.h b/src/iso5426converter.h
new file mode 100644
index 0000000..f13873b
--- /dev/null
+++ b/src/iso5426converter.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ copyright : (C) 2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef KBIBTEX_ISO5426CONVERTER_H
+#define KBIBTEX_ISO5426CONVERTER_H
+
+class QCString;
+class QString;
+class QChar;
+
+#include <qglobal.h>
+
+namespace KBibTeX {
+
+/**
+ * @author Robby Stephenson
+ */
+class Iso5426Converter {
+public:
+ static QString toUtf8(const QCString& text);
+
+private:
+ static bool hasNext(uint pos, uint len);
+ static bool isAscii(uchar c);
+ static bool isCombining(uchar c);
+
+ static QChar getChar(uchar c);
+ static QChar getCombiningChar(uint i);
+};
+
+} // end namespace
+
+#endif
diff --git a/src/iso6937converter.cpp b/src/iso6937converter.cpp
new file mode 100644
index 0000000..66a5154
--- /dev/null
+++ b/src/iso6937converter.cpp
@@ -0,0 +1,606 @@
+/***************************************************************************
+ copyright : (C) 2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+// This class is adapted from Iso6937ToUnicode from the MARC4J project, available
+// from http://marc4j.tigris.org, with the following notice:
+// * Copyright (C) 2002 Bas Peters ([email protected])
+// * Copyright (C) 2002 Yves Pratter ([email protected])
+//
+// That source was released under the terms of the GNU Lesser General Public
+// License, version 2.1. In accordance with Condition 3 of that license,
+// I am applying the terms of the GNU General Public License to the source
+// code, and including a large portion of it here
+
+#include "iso6937converter.h"
+#include <kdebug.h>
+
+#include <qstring.h>
+
+using KBibTeX::Iso6937Converter;
+
+QString Iso6937Converter::toUtf8(const QCString& text_) {
+ const uint len = text_.length();
+ QString result;
+ result.reserve(len);
+ uint pos = 0;
+ for(uint i = 0; i < len; ++i) {
+ uchar c = text_[i];
+ if(isAscii(c)) {
+ result[pos++] = c;
+ } else if(isCombining(c) && hasNext(i, len)) {
+ QChar d = getCombiningChar(c * 256 + text_[i + 1]);
+ if(!d.isNull()) {
+ result[pos++] = d;
+ ++i;
+ } else {
+ result[pos++] = getChar(c);
+ }
+ } else {
+ result[pos++] = getChar(c);
+ }
+ }
+ result.squeeze();
+ return result;
+}
+
+inline
+bool Iso6937Converter::hasNext(uint pos, uint len) {
+ return pos < (len - 1);
+}
+
+inline
+bool Iso6937Converter::isAscii(uchar c) {
+ return c <= 0x7F;
+}
+
+inline
+bool Iso6937Converter::isCombining(uchar c) {
+ return c >= 0xC0 && c <= 0xDF;
+}
+
+// Source : http://anubis.dkuug.dk/JTC1/SC2/WG3/docs/6937cd.pdf
+QChar Iso6937Converter::getChar(uchar c) {
+ switch(c) {
+ case 0xA0:
+ return 0x00A0; // 10/00 NO-BREAK SPACE
+ case 0xA1:
+ return 0x00A1; // 10/01 INVERTED EXCLAMATION MARK
+ case 0xA2:
+ return 0x00A2; // 10/02 CENT SIGN
+ case 0xA3:
+ return 0x00A3; // 10/03 POUND SIGN
+ // 10/04 (This position shall not be used)
+ case 0xA5:
+ return 0x00A5; // 10/05 YEN SIGN
+ // 10/06 (This position shall not be used)
+ case 0xA7:
+ return 0x00A7; // 10/07 SECTION SIGN
+ case 0xA8:
+ return 0x00A4; // 10/08 CURRENCY SIGN
+ case 0xA9:
+ return 0x2018; // 10/09 LEFT SINGLE QUOTATION MARK
+ case 0xAA:
+ return 0x201C; // 10/10 LEFT DOUBLE QUOTATION MARK
+ case 0xAB:
+ return 0x00AB; // 10/11 LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ case 0xAC:
+ return 0x2190; // 10/12 LEFTWARDS ARROW
+ case 0xAD:
+ return 0x2191; // 10/13 UPWARDS ARROW
+ case 0xAE:
+ return 0x2192; // 10/14 RIGHTWARDS ARROW
+ case 0xAF:
+ return 0x2193; // 10/15 DOWNWARDS ARROW
+
+ case 0xB0:
+ return 0x00B0; // 11/00 DEGREE SIGN
+ case 0xB1:
+ return 0x00B1; // 11/01 PLUS-MINUS SIGN
+ case 0xB2:
+ return 0x00B2; // 11/02 SUPERSCRIPT TWO
+ case 0xB3:
+ return 0x00B3; // 11/03 SUPERSCRIPT THREE
+ case 0xB4:
+ return 0x00D7; // 11/04 MULTIPLICATION SIGN
+ case 0xB5:
+ return 0x00B5; // 11/05 MICRO SIGN
+ case 0xB6:
+ return 0x00B6; // 11/06 PILCROW SIGN
+ case 0xB7:
+ return 0x00B7; // 11/07 MIDDLE DOT
+ case 0xB8:
+ return 0x00F7; // 11/08 DIVISION SIGN
+ case 0xB9:
+ return 0x2019; // 11/09 RIGHT SINGLE QUOTATION MARK
+ case 0xBA:
+ return 0x201D; // 11/10 RIGHT DOUBLE QUOTATION MARK
+ case 0xBB:
+ return 0x00BB; // 11/11 RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ case 0xBC:
+ return 0x00BC; // 11/12 VULGAR FRACTION ONE QUARTER
+ case 0xBD:
+ return 0x00BD; // 11/13 VULGAR FRACTION ONE HALF
+ case 0xBE:
+ return 0x00BE; // 11/14 VULGAR FRACTION THREE QUARTERS
+ case 0xBF:
+ return 0x00BF; // 11/15 INVERTED QUESTION MARK
+
+ // 4/0 to 5/15 diacritic characters
+
+ case 0xD0:
+ return 0x2015; // 13/00 HORIZONTAL BAR
+ case 0xD1:
+ return 0x00B9; // 13/01 SUPERSCRIPT ONE
+ case 0xD2:
+ return 0x2117; // 13/02 REGISTERED SIGN
+ case 0xD3:
+ return 0x00A9; // 13/03 COPYRIGHT SIGN
+ case 0xD4:
+ return 0x00AE; // 13/04 TRADE MARK SIGN
+ case 0xD5:
+ return 0x266A; // 13/05 EIGHTH NOTE
+ case 0xD6:
+ return 0x00AC; // 13/06 NOT SIGN
+ case 0xD7:
+ return 0x00A6; // 13/07 BROKEN BAR
+ // 13/08 (This position shall not be used)
+ // 13/09 (This position shall not be used)
+ // 13/10 (This position shall not be used)
+ // 13/11 (This position shall not be used)
+ case 0xDC:
+ return 0x215B; // 13/12 VULGAR FRACTION ONE EIGHTH
+ case 0xDF:
+ return 0x215E; // 13/15 VULGAR FRACTION SEVEN EIGHTHS
+
+ case 0xE0:
+ return 0x2126; // 14/00 OHM SIGN
+ case 0xE1:
+ return 0x00C6; // 14/01 LATIN CAPITAL LETTER AE
+ case 0xE2:
+ return 0x0110; // 14/02 LATIN CAPITAL LETTER D WITH STROKE
+ case 0xE3:
+ return 0x00AA; // 14/03 FEMININE ORDINAL INDICATOR
+ case 0xE4:
+ return 0x0126; // 14/04 LATIN CAPITAL LETTER H WITH STROKE
+ // 14/05 (This position shall not be used)
+ case 0xE6:
+ return 0x0132; // 14/06 LATIN CAPITAL LIGATURE IJ
+ case 0xE7:
+ return 0x013F; // 14/07 LATIN CAPITAL LETTER L WITH MIDDLE DOT
+ case 0xE8:
+ return 0x0141; // 14/08 LATIN CAPITAL LETTER L WITH STROKE
+ case 0xE9:
+ return 0x00D8; // 14/09 LATIN CAPITAL LETTER O WITH STROKE
+ case 0xEA:
+ return 0x0152; // 14/10 LATIN CAPITAL LIGATURE OE
+ case 0xEB:
+ return 0x00BA; // 14/11 MASCULINE ORDINAL INDICATOR
+ case 0xEC:
+ return 0x00DE; // 14/12 LATIN CAPITAL LETTER THORN
+ case 0xED:
+ return 0x0166; // 14/13 LATIN CAPITAL LETTER T WITH STROKE
+ case 0xEE:
+ return 0x014A; // 14/14 LATIN CAPITAL LETTER ENG
+ case 0xEF:
+ return 0x0149; // 14/15 LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+
+ case 0xF0:
+ return 0x0138; // 15/00 LATIN SMALL LETTER KRA
+ case 0xF1:
+ return 0x00E6; // 15/01 LATIN SMALL LETTER AE
+ case 0xF2:
+ return 0x0111; // 15/02 LATIN SMALL LETTER D WITH STROKE
+ case 0xF3:
+ return 0x00F0; // 15/03 LATIN SMALL LETTER ETH
+ case 0xF4:
+ return 0x0127; // 15/04 LATIN SMALL LETTER H WITH STROKE
+ case 0xF5:
+ return 0x0131; // 15/05 LATIN SMALL LETTER DOTLESS I
+ case 0xF6:
+ return 0x0133; // 15/06 LATIN SMALL LIGATURE IJ
+ case 0xF7:
+ return 0x0140; // 15/07 LATIN SMALL LETTER L WITH MIDDLE DOT
+ case 0xF8:
+ return 0x0142; // 15/08 LATIN SMALL LETTER L WITH STROKE
+ case 0xF9:
+ return 0x00F8; // 15/09 LATIN SMALL LETTER O WITH STROKE
+ case 0xFA:
+ return 0x0153; // 15/10 LATIN SMALL LIGATURE OE
+ case 0xFB:
+ return 0x00DF; // 15/11 LATIN SMALL LETTER SHARP S
+ case 0xFC:
+ return 0x00FE; // 15/12 LATIN SMALL LETTER THORN
+ case 0xFD:
+ return 0x0167; // 15/13 LATIN SMALL LETTER T WITH STROKE
+ case 0xFE:
+ return 0x014B; // 15/14 LATIN SMALL LETTER ENG
+ case 0xFF:
+ return 0x00AD; // 15/15 SOFT HYPHEN$
+ default:
+ return c;
+ }
+}
+
+QChar Iso6937Converter::getCombiningChar(uint c) {
+ switch(c) {
+ // 12/00 (This position shall not be used)
+
+ // 12/01 non-spacing grave accent
+ case 0xC141:
+ return 0x00C0; // LATIN CAPITAL LETTER A WITH GRAVE
+ case 0xC145:
+ return 0x00C8; // LATIN CAPITAL LETTER E WITH GRAVE
+ case 0xC149:
+ return 0x00CC; // LATIN CAPITAL LETTER I WITH GRAVE
+ case 0xC14F:
+ return 0x00D2; // LATIN CAPITAL LETTER O WITH GRAVE
+ case 0xC155:
+ return 0x00D9; // LATIN CAPITAL LETTER U WITH GRAVE
+ case 0xC161:
+ return 0x00E0; // LATIN SMALL LETTER A WITH GRAVE
+ case 0xC165:
+ return 0x00E8; // LATIN SMALL LETTER E WITH GRAVE
+ case 0xC169:
+ return 0x00EC; // LATIN SMALL LETTER I WITH GRAVE
+ case 0xC16F:
+ return 0x00F2; // LATIN SMALL LETTER O WITH GRAVE
+ case 0xC175:
+ return 0x00F9; // LATIN SMALL LETTER U WITH GRAVE
+
+ // 12/02 non-spacing acute accent
+ case 0xC220:
+ return 0x00B4; // ACUTE ACCENT
+ case 0xC241:
+ return 0x00C1; // LATIN CAPITAL LETTER A WITH ACUTE
+ case 0xC243:
+ return 0x0106; // LATIN CAPITAL LETTER C WITH ACUTE
+ case 0xC245:
+ return 0x00C9; // LATIN CAPITAL LETTER E WITH ACUTE
+ case 0xC249:
+ return 0x00CD; // LATIN CAPITAL LETTER I WITH ACUTE
+ case 0xC24C:
+ return 0x0139; // LATIN CAPITAL LETTER L WITH ACUTE
+ case 0xC24E:
+ return 0x0143; // LATIN CAPITAL LETTER N WITH ACUTE
+ case 0xC24F:
+ return 0x00D3; // LATIN CAPITAL LETTER O WITH ACUTE
+ case 0xC252:
+ return 0x0154; // LATIN CAPITAL LETTER R WITH ACUTE
+ case 0xC253:
+ return 0x015A; // LATIN CAPITAL LETTER S WITH ACUTE
+ case 0xC255:
+ return 0x00DA; // LATIN CAPITAL LETTER U WITH ACUTE
+ case 0xC259:
+ return 0x00DD; // LATIN CAPITAL LETTER Y WITH ACUTE
+ case 0xC25A:
+ return 0x0179; // LATIN CAPITAL LETTER Z WITH ACUTE
+ case 0xC261:
+ return 0x00E1; // LATIN SMALL LETTER A WITH ACUTE
+ case 0xC263:
+ return 0x0107; // LATIN SMALL LETTER C WITH ACUTE
+ case 0xC265:
+ return 0x00E9; // LATIN SMALL LETTER E WITH ACUTE
+ case 0xC267:
+ return 0x01F5; // LATIN SMALL LETTER G WITH CEDILLA(4)
+ case 0xC269:
+ return 0x00ED; // LATIN SMALL LETTER I WITH ACUTE
+ case 0xC26C:
+ return 0x013A; // LATIN SMALL LETTER L WITH ACUTE
+ case 0xC26E:
+ return 0x0144; // LATIN SMALL LETTER N WITH ACUTE
+ case 0xC26F:
+ return 0x00F3; // LATIN SMALL LETTER O WITH ACUTE
+ case 0xC272:
+ return 0x0155; // LATIN SMALL LETTER R WITH ACUTE
+ case 0xC273:
+ return 0x015B; // LATIN SMALL LETTER S WITH ACUTE
+ case 0xC275:
+ return 0x00FA; // LATIN SMALL LETTER U WITH ACUTE
+ case 0xC279:
+ return 0x00FD; // LATIN SMALL LETTER Y WITH ACUTE
+ case 0xC27A:
+ return 0x017A; // LATIN SMALL LETTER Z WITH ACUTE
+
+ // 12/03 non-spacing circumflex accent
+ case 0xC341:
+ return 0x00C2; // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+ case 0xC343:
+ return 0x0108; // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+ case 0xC345:
+ return 0x00CA; // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+ case 0xC347:
+ return 0x011C; // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+ case 0xC348:
+ return 0x0124; // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+ case 0xC349:
+ return 0x00CE; // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+ case 0xC34A:
+ return 0x0134; // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+ case 0xC34F:
+ return 0x00D4; // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+ case 0xC353:
+ return 0x015C; // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+ case 0xC355:
+ return 0x00DB; // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+ case 0xC357:
+ return 0x0174; // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+ case 0xC359:
+ return 0x0176; // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+ case 0xC361:
+ return 0x00E2; // LATIN SMALL LETTER A WITH CIRCUMFLEX
+ case 0xC363:
+ return 0x0109; // LATIN SMALL LETTER C WITH CIRCUMFLEX
+ case 0xC365:
+ return 0x00EA; // LATIN SMALL LETTER E WITH CIRCUMFLEX
+ case 0xC367:
+ return 0x011D; // LATIN SMALL LETTER G WITH CIRCUMFLEX
+ case 0xC368:
+ return 0x0125; // LATIN SMALL LETTER H WITH CIRCUMFLEX
+ case 0xC369:
+ return 0x00EE; // LATIN SMALL LETTER I WITH CIRCUMFLEX
+ case 0xC36A:
+ return 0x0135; // LATIN SMALL LETTER J WITH CIRCUMFLEX
+ case 0xC36F:
+ return 0x00F4; // LATIN SMALL LETTER O WITH CIRCUMFLEX
+ case 0xC373:
+ return 0x015D; // LATIN SMALL LETTER S WITH CIRCUMFLEX
+ case 0xC375:
+ return 0x00FB; // LATIN SMALL LETTER U WITH CIRCUMFLEX
+ case 0xC377:
+ return 0x0175; // LATIN SMALL LETTER W WITH CIRCUMFLEX
+ case 0xC379:
+ return 0x0177; // LATIN SMALL LETTER Y WITH CIRCUMFLEX
+
+ // 12/04 non-spacing tilde
+ case 0xC441:
+ return 0x00C3; // LATIN CAPITAL LETTER A WITH TILDE
+ case 0xC449:
+ return 0x0128; // LATIN CAPITAL LETTER I WITH TILDE
+ case 0xC44E:
+ return 0x00D1; // LATIN CAPITAL LETTER N WITH TILDE
+ case 0xC44F:
+ return 0x00D5; // LATIN CAPITAL LETTER O WITH TILDE
+ case 0xC455:
+ return 0x0168; // LATIN CAPITAL LETTER U WITH TILDE
+ case 0xC461:
+ return 0x00E3; // LATIN SMALL LETTER A WITH TILDE
+ case 0xC469:
+ return 0x0129; // LATIN SMALL LETTER I WITH TILDE
+ case 0xC46E:
+ return 0x00F1; // LATIN SMALL LETTER N WITH TILDE
+ case 0xC46F:
+ return 0x00F5; // LATIN SMALL LETTER O WITH TILDE
+ case 0xC475:
+ return 0x0169; // LATIN SMALL LETTER U WITH TILDE
+
+ // 12/05 non-spacing macron
+ case 0xC541:
+ return 0x0100; // LATIN CAPITAL LETTER A WITH MACRON
+ case 0xC545:
+ return 0x0112; // LATIN CAPITAL LETTER E WITH MACRON
+ case 0xC549:
+ return 0x012A; // LATIN CAPITAL LETTER I WITH MACRON
+ case 0xC54F:
+ return 0x014C; // LATIN CAPITAL LETTER O WITH MACRON
+ case 0xC555:
+ return 0x016A; // LATIN CAPITAL LETTER U WITH MACRON
+ case 0xC561:
+ return 0x0101; // LATIN SMALL LETTER A WITH MACRON
+ case 0xC565:
+ return 0x0113; // LATIN SMALL LETTER E WITH MACRON
+ case 0xC569:
+ return 0x012B; // LATIN SMALL LETTER I WITH MACRON
+ case 0xC56F:
+ return 0x014D; // LATIN SMALL LETTER O WITH MACRON
+ case 0xC575:
+ return 0x016B; // LATIN SMALL LETTER U WITH MACRON
+
+ // 12/06 non-spacing breve
+ case 0xC620:
+ return 0x02D8; // BREVE
+ case 0xC641:
+ return 0x0102; // LATIN CAPITAL LETTER A WITH BREVE
+ case 0xC647:
+ return 0x011E; // LATIN CAPITAL LETTER G WITH BREVE
+ case 0xC655:
+ return 0x016C; // LATIN CAPITAL LETTER U WITH BREVE
+ case 0xC661:
+ return 0x0103; // LATIN SMALL LETTER A WITH BREVE
+ case 0xC667:
+ return 0x011F; // LATIN SMALL LETTER G WITH BREVE
+ case 0xC675:
+ return 0x016D; // LATIN SMALL LETTER U WITH BREVE
+
+ // 12/07 non-spacing dot above
+ case 0xC743:
+ return 0x010A; // LATIN CAPITAL LETTER C WITH DOT ABOVE
+ case 0xC745:
+ return 0x0116; // LATIN CAPITAL LETTER E WITH DOT ABOVE
+ case 0xC747:
+ return 0x0120; // LATIN CAPITAL LETTER G WITH DOT ABOVE
+ case 0xC749:
+ return 0x0130; // LATIN CAPITAL LETTER I WITH DOT ABOVE
+ case 0xC75A:
+ return 0x017B; // LATIN CAPITAL LETTER Z WITH DOT ABOVE
+ case 0xC763:
+ return 0x010B; // LATIN SMALL LETTER C WITH DOT ABOVE
+ case 0xC765:
+ return 0x0117; // LATIN SMALL LETTER E WITH DOT ABOVE
+ case 0xC767:
+ return 0x0121; // LATIN SMALL LETTER G WITH DOT ABOVE
+ case 0xC77A:
+ return 0x017C; // LATIN SMALL LETTER Z WITH DOT ABOVE
+
+ // 12/08 non-spacing diaeresis
+ case 0xC820:
+ return 0x00A8; // DIAERESIS
+ case 0xC841:
+ return 0x00C4; // LATIN CAPITAL LETTER A WITH DIAERESIS
+ case 0xC845:
+ return 0x00CB; // LATIN CAPITAL LETTER E WITH DIAERESIS
+ case 0xC849:
+ return 0x00CF; // LATIN CAPITAL LETTER I WITH DIAERESIS
+ case 0xC84F:
+ return 0x00D6; // LATIN CAPITAL LETTER O WITH DIAERESIS
+ case 0xC855:
+ return 0x00DC; // LATIN CAPITAL LETTER U WITH DIAERESIS
+ case 0xC859:
+ return 0x0178; // LATIN CAPITAL LETTER Y WITH DIAERESIS
+ case 0xC861:
+ return 0x00E4; // LATIN SMALL LETTER A WITH DIAERESIS
+ case 0xC865:
+ return 0x00EB; // LATIN SMALL LETTER E WITH DIAERESIS
+ case 0xC869:
+ return 0x00EF; // LATIN SMALL LETTER I WITH DIAERESIS
+ case 0xC86F:
+ return 0x00F6; // LATIN SMALL LETTER O WITH DIAERESIS
+ case 0xC875:
+ return 0x00FC; // LATIN SMALL LETTER U WITH DIAERESIS
+ case 0xC879:
+ return 0x00FF; // LATIN SMALL LETTER Y WITH DIAERESIS
+
+ // 12/09 (This position shall not be used)
+
+ // 12/10 non-spacing ring above
+ case 0xCA20:
+ return 0x02DA; // RING ABOVE
+ case 0xCA41:
+ return 0x00C5; // LATIN CAPITAL LETTER A WITH RING ABOVE
+ case 0xCAAD:
+ return 0x016E; // LATIN CAPITAL LETTER U WITH RING ABOVE
+ case 0xCA61:
+ return 0x00E5; // LATIN SMALL LETTER A WITH RING ABOVE
+ case 0xCA75:
+ return 0x016F; // LATIN SMALL LETTER U WITH RING ABOVE
+
+ // 12/11 non-spacing cedilla
+ case 0xCB20:
+ return 0x00B8; // CEDILLA
+ case 0xCB43:
+ return 0x00C7; // LATIN CAPITAL LETTER C WITH CEDILLA
+ case 0xCB47:
+ return 0x0122; // LATIN CAPITAL LETTER G WITH CEDILLA
+ case 0xCB4B:
+ return 0x0136; // LATIN CAPITAL LETTER K WITH CEDILLA
+ case 0xCB4C:
+ return 0x013B; // LATIN CAPITAL LETTER L WITH CEDILLA
+ case 0xCB4E:
+ return 0x0145; // LATIN CAPITAL LETTER N WITH CEDILLA
+ case 0xCB52:
+ return 0x0156; // LATIN CAPITAL LETTER R WITH CEDILLA
+ case 0xCB53:
+ return 0x015E; // LATIN CAPITAL LETTER S WITH CEDILLA
+ case 0xCB54:
+ return 0x0162; // LATIN CAPITAL LETTER T WITH CEDILLA
+ case 0xCB63:
+ return 0x00E7; // LATIN SMALL LETTER C WITH CEDILLA
+ // case 0xCB67: return 0x0123; // small g with cedilla
+ case 0xCB6B:
+ return 0x0137; // LATIN SMALL LETTER K WITH CEDILLA
+ case 0xCB6C:
+ return 0x013C; // LATIN SMALL LETTER L WITH CEDILLA
+ case 0xCB6E:
+ return 0x0146; // LATIN SMALL LETTER N WITH CEDILLA
+ case 0xCB72:
+ return 0x0157; // LATIN SMALL LETTER R WITH CEDILLA
+ case 0xCB73:
+ return 0x015F; // LATIN SMALL LETTER S WITH CEDILLA
+ case 0xCB74:
+ return 0x0163; // LATIN SMALL LETTER T WITH CEDILLA
+
+ // 12/12 (This position shall not be used)
+
+ // 12/13 non-spacing double acute accent
+ case 0xCD4F:
+ return 0x0150; // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+ case 0xCD55:
+ return 0x0170; // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+ case 0xCD6F:
+ return 0x0151; // LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ case 0xCD75:
+ return 0x0171; // LATIN SMALL LETTER U WITH DOUBLE ACUTE
+
+ // 12/14 non-spacing ogonek
+ case 0xCE20:
+ return 0x02DB; // ogonek
+ case 0xCE41:
+ return 0x0104; // LATIN CAPITAL LETTER A WITH OGONEK
+ case 0xCE45:
+ return 0x0118; // LATIN CAPITAL LETTER E WITH OGONEK
+ case 0xCE49:
+ return 0x012E; // LATIN CAPITAL LETTER I WITH OGONEK
+ case 0xCE55:
+ return 0x0172; // LATIN CAPITAL LETTER U WITH OGONEK
+ case 0xCE61:
+ return 0x0105; // LATIN SMALL LETTER A WITH OGONEK
+ case 0xCE65:
+ return 0x0119; // LATIN SMALL LETTER E WITH OGONEK
+ case 0xCE69:
+ return 0x012F; // LATIN SMALL LETTER I WITH OGONEK
+ case 0xCE75:
+ return 0x0173; // LATIN SMALL LETTER U WITH OGONEK
+
+ // 12/15 non-spacing caron
+ case 0xCF20:
+ return 0x02C7; // CARON
+ case 0xCF43:
+ return 0x010C; // LATIN CAPITAL LETTER C WITH CARON
+ case 0xCF44:
+ return 0x010E; // LATIN CAPITAL LETTER D WITH CARON
+ case 0xCF45:
+ return 0x011A; // LATIN CAPITAL LETTER E WITH CARON
+ case 0xCF4C:
+ return 0x013D; // LATIN CAPITAL LETTER L WITH CARON
+ case 0xCF4E:
+ return 0x0147; // LATIN CAPITAL LETTER N WITH CARON
+ case 0xCF52:
+ return 0x0158; // LATIN CAPITAL LETTER R WITH CARON
+ case 0xCF53:
+ return 0x0160; // LATIN CAPITAL LETTER S WITH CARON
+ case 0xCF54:
+ return 0x0164; // LATIN CAPITAL LETTER T WITH CARON
+ case 0xCF5A:
+ return 0x017D; // LATIN CAPITAL LETTER Z WITH CARON
+ case 0xCF63:
+ return 0x010D; // LATIN SMALL LETTER C WITH CARON
+ case 0xCF64:
+ return 0x010F; // LATIN SMALL LETTER D WITH CARON
+ case 0xCF65:
+ return 0x011B; // LATIN SMALL LETTER E WITH CARON
+ case 0xCF6C:
+ return 0x013E; // LATIN SMALL LETTER L WITH CARON
+ case 0xCF6E:
+ return 0x0148; // LATIN SMALL LETTER N WITH CARON
+ case 0xCF72:
+ return 0x0159; // LATIN SMALL LETTER R WITH CARON
+ case 0xCF73:
+ return 0x0161; // LATIN SMALL LETTER S WITH CARON
+ case 0xCF74:
+ return 0x0165; // LATIN SMALL LETTER T WITH CARON
+ case 0xCF7A:
+ return 0x017E; // LATIN SMALL LETTER Z WITH CARON
+
+ default:
+ kdDebug() << "Iso6937Converter::getCombiningChar() - no match for " << c << endl;
+ return QChar();
+ }
+}
diff --git a/src/iso6937converter.h b/src/iso6937converter.h
new file mode 100644
index 0000000..a72efcd
--- /dev/null
+++ b/src/iso6937converter.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ copyright : (C) 2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef KBIBTEX_ISO6937CONVERTER_H
+#define KBIBTEX_ISO6937CONVERTER_H
+
+class QCString;
+class QString;
+class QChar;
+
+namespace KBibTeX {
+
+/**
+ * @author Robby Stephenson
+ */
+class Iso6937Converter {
+public:
+ static QString toUtf8(const QCString& text);
+
+private:
+ static bool hasNext(unsigned int pos, unsigned int len);
+ static bool isAscii(unsigned char c);
+ static bool isCombining(unsigned char c);
+
+ static QChar getChar(unsigned char c);
+ static QChar getCombiningChar(unsigned int c);
+};
+
+} // end namespace
+
+#endif
diff --git a/src/kbibtex.desktop b/src/kbibtex.desktop
new file mode 100644
index 0000000..5c9d9c3
--- /dev/null
+++ b/src/kbibtex.desktop
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Name=KBibTeX
+Exec=kbibtex %U %i -caption "%c"
+Icon=kbibtex
+Type=Application
+X-DocPath=kbibtex/kbibtex.html
+Comment=A BibTeX editor for KDE
+Comment[de]=Ein BibTeX-Editor für KDE
+MimeType=text/x-bibtex;
+Categories=Qt;KDE;Office;
+X-KDE-HasTempFileOption=true
+X-DCOP-ServiceType=Unique
diff --git a/src/kbibtex.lsm b/src/kbibtex.lsm
new file mode 100644
index 0000000..4ebf200
--- /dev/null
+++ b/src/kbibtex.lsm
@@ -0,0 +1,15 @@
+Begin3
+Title: KBibTeX -- A BibTeX editor for KDE3
+Version: 0.2.3.91
+Entered-date:
+Description: A KDE3 program to create and edit BibTeX files for LaTeX
+Keywords: KDE BibTeX
+Author: Thomas Fischer <[email protected]>
+Maintained-by: Thomas Fischer <[email protected]>
+Home-page: http://www.unix-ag.uni-kl.de/~fischer/kbibtex/
+Alternate-site:
+Primary-site: www.unix-ag.uni-kl.de /~fischer/kbibtex/download
+ 640kB kbibtex-0.2.3.91.tar.bz2
+Platform: Linux. Needs KDE 3.x
+Copying-policy: GPL
+End
diff --git a/src/kbibtex_part.cpp b/src/kbibtex_part.cpp
new file mode 100644
index 0000000..3a5f16a
--- /dev/null
+++ b/src/kbibtex_part.cpp
@@ -0,0 +1,758 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <string>
+#include <fcntl.h>
+
+#include <qstring.h>
+#include <qsplitter.h>
+#include <qtimer.h>
+#include <qvaluelist.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qbuffer.h>
+#include <qtoolbutton.h>
+#include <qtabwidget.h>
+#include <qlabel.h>
+#include <qtextedit.h>
+#include <qclipboard.h>
+#include <kinstance.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <klistview.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <ktempfile.h>
+#include <kconfigdialog.h>
+#include <kstatusbar.h>
+#include <kglobalsettings.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <kshortcut.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kxmlguifactory.h>
+#include <kpopupmenu.h>
+#include <kio/netaccess.h>
+#include <kmainwindow.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <entry.h>
+#include <documentlistviewitem.h>
+#include <documentlistview.h>
+#include <fileexporter.h>
+#include <fileexporterbibtex.h>
+#include <fileexporterxml.h>
+#include <fileexporterxslt.h>
+#include <settings.h>
+#include <encoderlatex.h>
+#include "kbibtex_part.h"
+
+const QString inPipeFilename = QDir::homeDirPath() + "/.kbibtex.in";
+
+KBibTeXPart::KBibTeXPart( QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name )
+ : KParts::ReadWritePart( parent, name ), m_defInitCounter( 0 ), m_settingsDlg( NULL ), m_initializationDone( FALSE ), m_inPipe( NULL )
+{
+ m_mainWindow = dynamic_cast<KMainWindow*>( parent );
+ if ( m_mainWindow == NULL )
+ kdDebug( ) << "Cannot determine main window" << endl;
+
+ // we need an instance
+ setInstance( KBibTeXPartFactory::instance() );
+
+ // set our XML-UI resource file
+ setXMLFile( "kbibtex_part.rc" );
+
+ // setup GUI elements
+ setupGUI( parentWidget, widgetName );
+
+ // create our actions
+ setupActions();
+
+ // we are read-write by default
+ setReadWrite( TRUE );
+
+ // we are not modified since we haven't done anything yet
+ setModified( FALSE );
+
+ // read configuration
+ readSettings();
+
+ QTimer::singleShot( 100, this, SLOT( slotDeferredInitialization() ) );
+}
+
+KBibTeXPart::~KBibTeXPart()
+{
+ BibTeX::EncoderLaTeX::deleteCurrentEncoderLaTeX();
+
+ if ( m_settingsDlg != NULL )
+ delete m_settingsDlg;
+}
+
+void KBibTeXPart::setReadWrite( bool rw )
+{
+ if ( rw )
+ {
+ connect( m_documentWidget, SIGNAL( modified( ) ), this, SLOT( setModified( ) ) );
+ m_actionEditElement->setText( i18n( "&Edit" ) );
+ }
+ else
+ {
+ disconnect( m_documentWidget, SIGNAL( modified( ) ), this, SLOT( setModified( ) ) );
+ m_actionEditElement->setText( i18n( "&View" ) );
+ }
+ ReadWritePart::setReadWrite( rw );
+ m_documentWidget->setReadOnly( !rw );
+}
+
+void KBibTeXPart::setModified( bool modified )
+{
+ // get a handle on our Save action and make sure it is valid
+ KAction * save = actionCollection() ->action( KStdAction::stdName( KStdAction::Save ) );
+
+ if ( save )
+ {
+ // if so, we either enable or disable it based on the current
+ // state
+ save->setEnabled( modified );
+
+ // in any event, we want our parent to do it's thing
+ KParts::ReadWritePart::setModified( modified );
+ }
+}
+
+bool KBibTeXPart::queryClose()
+{
+ writeSettings();
+
+ if ( !isReadWrite() || !isModified() )
+ return TRUE;
+
+ QString docName = url().fileName();
+ if ( docName.isEmpty() ) docName = i18n( "Untitled" );
+
+ int res = KMessageBox::warningYesNoCancel( widget(),
+ i18n( "The document '%1' has been modified.\n"
+ "Do you want to save your changes or discard them?" ).arg( docName ),
+ i18n( "Close Document" ), KStdGuiItem::save(), KStdGuiItem::discard() );
+
+ bool abortClose = false;
+ bool handled = false;
+
+ switch ( res )
+ {
+ case KMessageBox::Yes :
+ sigQueryClose( &handled, &abortClose );
+ if ( !handled )
+ {
+ if ( m_url.isEmpty() )
+ return saveAs();
+ else
+ save();
+ }
+ else if ( abortClose ) return FALSE;
+ return waitSaveComplete();
+ case KMessageBox::No :
+ return TRUE;
+ default:
+ return FALSE;
+ }
+
+}
+
+bool KBibTeXPart::closeURL()
+{
+ writeSettings();
+
+ if ( isReadWrite() && isModified() )
+ {
+ if ( !queryClose() )
+ return false;
+ }
+ // Not modified => ok and delete temp file.
+ return KParts::ReadOnlyPart::closeURL();
+}
+
+bool KBibTeXPart::openFile()
+{
+ return m_documentWidget->open( m_file, FALSE );
+}
+
+/**
+ * Save document to a filename as given in String m_file.
+ */
+bool KBibTeXPart::saveFile()
+{
+ if ( isReadWrite() == FALSE )
+ return FALSE;
+
+ if ( !url().isValid() || url().isEmpty() )
+ return saveAs();
+ else
+ {
+ /** make backup if defined by the user */
+ KBibTeX::Settings * settings = KBibTeX::Settings::self( NULL );
+ settings->createBackup( url(), widget() );
+
+ KTempFile tempBibFile = KTempFile( locateLocal( "tmp", "bibsave" ) );
+ tempBibFile.setAutoDelete( TRUE );
+ bool success = m_documentWidget->save( tempBibFile.file() );
+ tempBibFile.close();
+ if ( success )
+ {
+ QString usedFileName = m_file;
+ QFileInfo fi( usedFileName );
+ if ( !fi.readLink().isNull() && KMessageBox::questionYesNo( widget(), QString( i18n( "The selected filename \"%1\" is a symbolic link pointing to \"%2\".\nReplace the link with a new file or overwrite the existing file the link points to?" ) ).arg( usedFileName ).arg(KBibTeX::Settings::resolveLink( m_file, fi.readLink() ) ), i18n( "Symbolic Link" ), KGuiItem( i18n( "Replace link" ) ), KGuiItem( i18n( "Overwrite file the link points to" ) ) ) == KMessageBox::No )
+ usedFileName = KBibTeX::Settings::resolveLink( m_file, fi.readLink() );
+
+ m_documentWidget->dirWatch().stopScan();
+ success = KIO::NetAccess::file_copy( KURL( tempBibFile.name() ), KURL( usedFileName ), -1, true, false, widget() );
+ m_documentWidget->dirWatch().startScan();
+ }
+
+ return success;
+ }
+}
+
+void KBibTeXPart::slotFileSaveAs()
+{
+ saveAs();
+}
+
+bool KBibTeXPart::saveAs()
+{
+ bool result = FALSE;
+ KBibTeX::Settings * settings = KBibTeX::Settings::self( NULL );
+
+ QString startDir = ! url().isEmpty() ? url().url() : QDir::currentDirPath();
+ KURL saveURL = KFileDialog::getSaveURL( startDir, "*.bib|" + i18n( "BibTeX (*.bib)" ) + "\n*.ris|" + i18n( "Reference Manager (*.ris)" ) +
+ ( settings->external_xml2bibAvailable ? "\n*.ref *.refer *.rfr *.txt|" + i18n( "EndNote (Refer format) (*.ref *.refer *.rfr *.txt)" ) + "\n*.isi *.cgi|" + i18n( "ISI Web of Knowledge (*.isi *.cgi)" ) : "" ) + "\n*.xml|" + ( settings->external_xml2bibAvailable ? i18n( "DocBook 5 or MODS (*.xml)" ) : i18n( "DocBook 5 (*.xml)" ) ), widget() );
+
+ if ( saveURL.isValid() && !saveURL.isEmpty() )
+ {
+ if ( KIO::NetAccess::exists( saveURL, FALSE, widget() ) && KMessageBox::warningContinueCancel( widget(), i18n( "A file named '%1' already exists. Are you sure you want to overwrite it?" ).arg( saveURL.filename() ), QString::null, i18n( "Overwrite" ) ) != KMessageBox::Continue )
+ return result;
+
+ if ( ReadWritePart::saveAs( saveURL ) )
+ {
+ emit signalAddRecentURL( saveURL );
+ result = TRUE;
+ }
+ }
+
+ return result;
+}
+
+void KBibTeXPart::slotFileExport()
+{
+ KBibTeX::Settings * settings = KBibTeX::Settings::self( NULL );
+ QString startDir = ! url().isEmpty() ? url().url() : QDir::currentDirPath();
+ KURL exportURL = KFileDialog::getSaveURL( startDir, "*.pdf|" + i18n( "Portable Document File (*.pdf)" ) + "\n*.ps|" + i18n( "PostScript (*.ps)" ) + "\n*.ris|" + i18n( "Reference Manager (*.ris)" ) + ( settings->external_xml2bibAvailable ? "\n*.ref *.refer *.rfr *.txt|" + i18n( "EndNote (Refer format) (*.ref *.refer *.rfr *.txt)" ) + "\n*.isi *.cgi|" + i18n( "ISI Web of Knowledge (*.isi *.cgi)" ) : "" ) + "\n*.xml|" + ( settings->external_xml2bibAvailable ? i18n( "DocBook 5 or MODS (*.xml)" ) : i18n( "DocBook 5 (*.xml)" ) ) + "\n*.html|" + i18n( "Hypertext Markup Langage (*.html)" ) + "\n*.rtf|" + i18n( "Rich Text Format (*.rtf)" ), widget() );
+
+ if ( exportURL.isValid() && !exportURL.isEmpty() )
+ {
+ if ( KIO::NetAccess::exists( exportURL, FALSE, widget() ) )
+ {
+ if ( KMessageBox::warningContinueCancel( widget(), i18n( "A file named '%1' already exists. Are you sure you want to overwrite it?" ).arg( exportURL.filename() ), QString::null, i18n( "Overwrite" ) ) != KMessageBox::Continue )
+ return ;
+
+ /** make backup if defined by the user */
+ KBibTeX::Settings * settings = KBibTeX::Settings::self( NULL );
+ settings->createBackup( exportURL, widget() );
+ }
+
+ KTempFile tempBibFile = KTempFile( locateLocal( "tmp", "bibexport" ) );
+ tempBibFile.setAutoDelete( TRUE );
+ BibTeX::File::FileFormat format = BibTeX::File::formatBibTeX;
+ if ( exportURL.fileName().endsWith( ".rtf", FALSE ) )
+ format = BibTeX::File::formatRTF;
+ else if ( exportURL.fileName().endsWith( ".pdf", FALSE ) )
+ format = BibTeX::File::formatPDF;
+ else if ( exportURL.fileName().endsWith( ".ps", FALSE ) )
+ format = BibTeX::File::formatPS;
+ else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && ( exportURL.fileName().endsWith( ".ref", FALSE ) || exportURL.fileName().endsWith( ".refer", FALSE ) || exportURL.fileName().endsWith( ".txt", FALSE ) || exportURL.fileName().endsWith( ".rfr", FALSE ) ) )
+ format = BibTeX::File::formatEndNote;
+ else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && ( exportURL.fileName().endsWith( ".isi", FALSE ) || exportURL.fileName().endsWith( ".cgi", FALSE ) ) )
+ format = BibTeX::File::formatISI;
+ else if ( exportURL.fileName().endsWith( ".ris", FALSE ) )
+ format = BibTeX::File::formatRIS;
+ else if ( exportURL.fileName().endsWith( ".xml", FALSE ) )
+ {
+ QStringList options = QStringList::split( '|', ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable ? "DocBook5|MODS|internal XML" : "DocBook5|internal XML" ) );
+ bool ok = false;
+ QString answer = KInputDialog::getItem( i18n( "Choose file format" ), QString( i18n( "Choose file format of file '%1':" ) ).arg( exportURL.fileName() ), options, 0, false, &ok, widget() );
+ if ( ok && !answer.isNull() && answer == "DocBook5" )
+ format = BibTeX::File::formatDocBook5;
+ else if ( ok && !answer.isNull() && answer == "MODS" )
+ format = BibTeX::File::formatMODS;
+ else if ( ok && !answer.isNull() && answer == "internal XML" )
+ format = BibTeX::File::formatXML;
+ }
+ else if ( exportURL.fileName().endsWith( ".html", FALSE ) )
+ format = BibTeX::File::formatHTML;
+ else
+ {
+ QStringList options = QStringList::split( '|', ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable ? "BibTeX|EndNote|ISI|RIS" : "BibTeX|RIS" ) );
+ bool ok = false;
+ QString answer = KInputDialog::getItem( i18n( "Choose file format" ), QString( i18n( "Choose file format of file '%1':" ) ).arg( exportURL.fileName() ), options, 0, false, &ok, widget() );
+ if ( ok && !answer.isNull() && answer == "BibTeX" )
+ format = BibTeX::File::formatBibTeX;
+ else if ( ok && !answer.isNull() && answer == "EndNote" )
+ format = BibTeX::File::formatEndNote;
+ else if ( ok && !answer.isNull() && answer == "ISI" )
+ format = BibTeX::File::formatISI;
+ else if ( ok && !answer.isNull() && answer == "RIS" )
+ format = BibTeX::File::formatRIS;
+ }
+
+ QStringList errorLog;
+
+ bool error = !m_documentWidget->save( tempBibFile.file(), format, i18n( "Exporting" ), &errorLog ) ;
+ if ( !error )
+ {
+ tempBibFile.close();
+ error = !KIO::NetAccess::file_copy( KURL( tempBibFile.name() ), exportURL, -1, TRUE, FALSE, widget() );
+ }
+
+ if ( error )
+ {
+#if (KDE_VERSION_MINOR>=4) && (KDE_VERSION_MAJOR>=3)
+ if ( !errorLog.empty() )
+ KMessageBox::errorList( widget(), QString( i18n( "File could not be exported in '%1'." ) ).arg( exportURL.prettyURL() ).append( i18n( "\n\nSee the following error log for details." ) ), errorLog, i18n( "Exporting failed" ) );
+ else
+#endif
+ KMessageBox::error( widget(), QString( i18n( "File could not be exported to '%1'." ) ).arg( exportURL.prettyURL() ), i18n( "Exporting failed" ) );
+ }
+
+ }
+
+}
+
+void KBibTeXPart::slotFileStatistics()
+{
+ m_documentWidget->showStatistics();
+}
+
+void KBibTeXPart::slotFileFindDups()
+{
+ m_documentWidget->findDuplicates();
+}
+
+void KBibTeXPart::slotFileMerge()
+{
+ KBibTeX::Settings * settings = KBibTeX::Settings::self( NULL );
+ QString startDir = ! url().isEmpty() ? url().url() : QDir::currentDirPath();
+ KURL mergeURL = KFileDialog::getOpenURL( startDir, QString( "*.bib *.ris" ) +
+ ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable ? " *.xml *.ref *.refer *.rfr *.txt *.isi *.cgi" : "" ) + "|" + i18n( "Supported Bibliographies" ) + "\n*.bib|" + i18n( "BibTeX (*.bib)" ) + "\n*.ris|" + i18n( "Reference Manager (*.ris)" ) + ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable ? "\n*.ref *.refer *.rfr *.txt|" + i18n( "EndNote (Refer format) (*.ref *.refer *.rfr *.txt)" ) + "\n*.isi *.cgi|" + i18n( "ISI Web of Knowledge (*.isi *.cgi)" ) + "\n*.xml|" + i18n( "MODS or EndNote XML (*.xml)" ) : "" ) + "\n*|" + i18n( "All files (*.*)" )
+ , widget() );
+
+ if ( !mergeURL.isValid() || mergeURL.isEmpty() )
+ return;
+
+ QString extension = mergeURL.fileName();
+ int extPos = extension.find( '.' );
+ if ( extPos < 0 )
+ return;
+ extension = extension.mid( extPos );
+
+ if ( !KIO::NetAccess::exists( mergeURL, TRUE, widget() ) )
+ {
+ KMessageBox::error( widget(), i18n( "The given file could not be read, check if it exists or if it is readable for the current user." ) );
+ return ;
+ }
+
+ KTempFile tempBibFile = KTempFile( locateLocal( "tmp", "bibmerge" ), extension );
+ tempBibFile.setAutoDelete( TRUE );
+ bool error = !KIO::NetAccess::file_copy( mergeURL, KURL( tempBibFile.name() ), -1, TRUE, FALSE, widget() );
+
+ if ( !error )
+ error = !m_documentWidget->open( tempBibFile.name(), TRUE );
+
+ tempBibFile.close();
+
+ if ( error )
+ {
+ KMessageBox::error( widget(), i18n( "The given file could not be merged." ) );
+ return;
+ }
+ else
+ setModified( TRUE );
+}
+
+void KBibTeXPart::slotPreferences()
+{
+ if ( !m_settingsDlg )
+ m_settingsDlg = new KBibTeX::SettingsDlg( widget(), "settings_dlg" );
+
+ m_documentWidget->saveState();
+ if ( m_settingsDlg->exec() == QDialog::Accepted )
+ m_documentWidget->restoreState();
+}
+
+void KBibTeXPart::setupGUI( QWidget *parentWidget, const char *name )
+{
+ m_documentWidget = new KBibTeX::DocumentWidget( !isReadWrite(), parentWidget, name );
+
+ // notify the part that this is our internal widget
+ setWidget( m_documentWidget );
+}
+
+void KBibTeXPart::setupActions()
+{
+ if ( isReadWrite() )
+ {
+ KStdAction::save( this, SLOT( save() ), actionCollection() ) ->setToolTip( i18n( "Save the current file" ) );
+ KStdAction::saveAs( this, SLOT( slotFileSaveAs() ), actionCollection() ) ->setToolTip( i18n( "Save the current file under a new filename" ) );
+ }
+ m_actionFileStatistics = new KAction( i18n( "Statistics..." ), CTRL + SHIFT + Key_I, this, SLOT( slotFileStatistics() ), actionCollection(), "file_statistics" );
+ m_actionFileFindDups = new KAction( i18n( "Find Duplicates..." ), CTRL + SHIFT + Key_D, this, SLOT( slotFileFindDups() ), actionCollection(), "file_finddups" );
+ m_actionFileExport = new KAction( i18n( "Export..." ), SmallIconSet( "goto" ), CTRL + Key_E, this, SLOT( slotFileExport() ), actionCollection(), "file_export" );
+ m_actionFileExport->setToolTip( i18n( "Export to a different file format" ) );
+ m_actionFileMerge = new KAction( i18n( "Merge..." ), SmallIconSet( "reload" ), CTRL + Key_M, this, SLOT( slotFileMerge() ), actionCollection(), "file_merge" );
+ m_actionFileMerge->setToolTip( i18n( "Merge BibTeX entries from another file" ) );
+
+ m_actionEditCut = KStdAction::cut( m_documentWidget, SLOT( cutElements() ), actionCollection() );
+ m_actionEditCut->setToolTip( i18n( "Cut the selected BibTeX elements to the clipboard" ) );
+ m_actionEditCut->setEnabled( FALSE );
+ m_actionEditCopy = KStdAction::copy( m_documentWidget, SLOT( copyElements() ), actionCollection() );
+ m_actionEditCopy->setToolTip( i18n( "Copy the selected BibTeX elements to the clipboard" ) );
+ m_actionEditCopy->setEnabled( FALSE );
+ m_actionEditUndo = KStdAction::undo( m_documentWidget, SLOT( undoEditor() ), actionCollection() );
+ connect( m_documentWidget, SIGNAL( undoChanged( bool ) ), this, SLOT( slotUndoChanged( bool ) ) );
+ m_actionEditCopyRef = new KAction( i18n( "Copy &Reference" ), CTRL + SHIFT + Key_C, m_documentWidget, SLOT( copyRefElements() ), actionCollection(), "edit_copyref" );
+ m_actionEditCopyRef->setToolTip( i18n( "Copy a reference of the selected BibTeX elements to the clipboard" ) );
+ m_actionEditCopyRef->setEnabled( FALSE );
+ m_actionEditPaste = KStdAction::paste( m_documentWidget, SLOT( pasteElements() ), actionCollection() );
+ m_actionEditPaste->setToolTip( i18n( "Paste BibTeX elements from the clipboard" ) );
+ m_actionEditSelectAll = KStdAction::selectAll( m_documentWidget, SLOT( selectAll() ), actionCollection() );
+ m_actionEditSelectAll->setToolTip( i18n( "Select all BibTeX elements" ) );
+ m_actionElementSendToLyX = new KAction( i18n( "Send Reference to &LyX" ), CTRL + SHIFT + Key_L, m_documentWidget, SLOT( sendSelectedToLyx() ), actionCollection(), "element_sendtolyx" );
+ m_actionElementSendToLyX->setToolTip( i18n( "Send a reference of the selected BibTeX elements to LyX" ) );
+ m_actionElementSendToLyX->setEnabled( FALSE );
+ m_actionEditFind = KStdAction::find( m_documentWidget, SLOT( find() ), actionCollection() );
+ m_actionEditFind->setToolTip( i18n( "Find text" ) );
+ m_actionEditFindNext = KStdAction::findNext( m_documentWidget, SLOT( findNext() ), actionCollection() );
+ m_actionEditFindNext->setToolTip( i18n( "Find next occurrence" ) );
+ m_actionEditFind->setEnabled( FALSE );
+ m_actionEditFindNext->setEnabled( FALSE );
+
+ m_actionSearchOnlineDatabases = new KAction( i18n( "Search Online Databases" ), SmallIconSet( "network" ), CTRL + SHIFT + Key_S, m_documentWidget, SLOT( onlineSearch() ), actionCollection(), "search_onlinedatabases" );
+ m_actionSearchOnlineDatabases->setToolTip( i18n( "Search online databases to import bibliography data" ) );
+
+ m_actionMenuSearchWebsites = new KActionMenu( i18n( "Search Document Online" ), actionCollection(), "search_document_online" );
+ m_actionMenuSearchWebsites->setToolTip( i18n( "Search websites for the selected BibTeX element" ) );
+ connect( m_actionMenuSearchWebsites->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotSearchWebsites( int ) ) );
+ m_actionMenuSearchWebsites->setEnabled( FALSE );
+
+ m_actionViewShowColumns = new KActionMenu( i18n( "&Show Columns" ), actionCollection(), "view_showcolumns" );
+ m_actionViewShowColumns->setToolTip( i18n( "Select columns to show in the main list" ) );
+ m_actionViewDocument = new KActionMenu( i18n( "View Document" ), actionCollection(), "view_document" );
+ m_actionViewDocument->setToolTip( i18n( "View the documents associated with this BibTeX entry" ) );
+ m_actionViewDocument->setEnabled( FALSE );
+ m_actionViewFirstDocument = new KAction( i18n( "View Primary Document" ), 0, m_documentWidget, SLOT( slotViewFirstDocument() ), actionCollection(), "view_first_document" );
+ m_actionViewFirstDocument->setShortcut( Qt::Key_F4 );
+ m_actionViewDocumentOnlineRef = new KAction( i18n( "View Primary Online Reference" ), 0, m_documentWidget, SLOT( slotViewFirstDocumentsOnlineRef() ), actionCollection(), "view_first_documents_online_ref" );
+ m_actionViewDocumentOnlineRef->setShortcut( Qt::Key_F5 );
+ m_actionAssignKeywords = new KActionMenu( i18n( "Assign Keywords" ), actionCollection(), "assign_keywords" );
+ m_actionAssignKeywords->setToolTip( i18n( "Assign keywords to this entry" ) );
+ m_actionAssignKeywords->setEnabled( FALSE );
+ m_actionNormalizeIds = new KAction( i18n( "Normalize Entry Ids" ), 0, m_documentWidget, SLOT( slotNormalizeIds() ), actionCollection( ), "normalize_ids" );
+ m_actionNormalizeIds->setToolTip( i18n( "Set entry ids as specified in the id suggestion settings" ) );
+ m_actionNormalizeIds->setEnabled( FALSE );
+
+ m_actionPreferences = KStdAction::preferences( this, SLOT( slotPreferences() ), actionCollection() );
+ m_actionPreferences->setToolTip( i18n( "Configure KBibTeX" ) );
+ KAction *actionSourceEditor = new KAction( i18n( "Configure Source View..." ), 0, m_documentWidget, SLOT( configureEditor() ), actionCollection(), "options_configure_editor" );
+ actionSourceEditor ->setToolTip( i18n( "Configure the Source Editor" ) );
+
+ ( new KAction( i18n( "Article" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_article" ) ) ->setToolTip( i18n( "Add an article to the BibTeX file" ) );
+ ( new KAction( i18n( "Book" ), "element_new_entry_book", CTRL + Key_B, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_book" ) ) ->setToolTip( i18n( "Add a book to the BibTeX file" ) );
+ ( new KAction( i18n( "Booklet" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_booklet" ) ) ->setToolTip( i18n( "Add a booklet to the BibTeX file" ) );
+ ( new KAction( i18n( "Electronic (IEEE)" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_electronic" ) ) ->setToolTip( i18n( "Add an electronic reference (IEEE) to the BibTeX file" ) );
+ ( new KAction( i18n( "InBook" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_inbook" ) ) ->setToolTip( i18n( "Add a part of a book to the BibTeX file" ) );
+ ( new KAction( i18n( "InCollection" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_incollection" ) ) ->setToolTip( i18n( "Add a publication which is part of some collection to the BibTeX file" ) );
+ ( new KAction( i18n( "InProceedings" ), "element_new_entry_inproceedings", CTRL + Key_I, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_inproceedings" ) ) ->setToolTip( i18n( "Add a publication which is part of some proceedings to the BibTeX file" ) );
+ ( new KAction( i18n( "Manual" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_manual" ) ) ->setToolTip( i18n( "Add a manual to the BibTeX file" ) );
+ ( new KAction( i18n( "MastersThesis" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_mastersthesis" ) ) ->setToolTip( i18n( "Add a master or diploma thesis to the BibTeX file" ) );
+ ( new KAction( i18n( "Misc" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_misc" ) ) ->setToolTip( i18n( "Add a not specified document or reference to the BibTeX file" ) );
+ ( new KAction( i18n( "PhDThesis" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_phdthesis" ) ) ->setToolTip( i18n( "Add a PhD thesis to the BibTeX file" ) );
+ ( new KAction( i18n( "Proceedings" ), "element_new_entry_phdthesis" , CTRL + Key_P, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_proceedings" ) ) ->setToolTip( i18n( "Add some proceedings to the BibTeX file" ) );
+ ( new KAction( i18n( "TechReport" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_techreport" ) ) ->setToolTip( i18n( "Add a technical report to the BibTeX file" ) );
+ ( new KAction( i18n( "Unpublished" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_entry_unpublished" ) ) ->setToolTip( i18n( "Add an unpublished document to the BibTeX file" ) );
+ ( new KAction( i18n( "Preamble" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_preamble" ) ) ->setToolTip( i18n( "Add a preamble to the BibTeX file" ) );
+ ( new KAction( i18n( "Comment" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_comment" ) ) ->setToolTip( i18n( "Add a comment to the BibTeX file" ) );
+ ( new KAction( i18n( "Macro" ), 0, this, SLOT( slotNewElement() ), actionCollection(), "element_new_macro" ) ) ->setToolTip( i18n( "Add a macro to the BibTeX file" ) );
+
+ m_actionEditElement = new KAction( i18n( "&Edit" ), 0, m_documentWidget, SLOT( editElement() ), actionCollection(), "element_edit" );
+ m_actionEditElement->setToolTip( i18n( "Edit the selected BibTeX element" ) );
+ m_actionEditElement->setEnabled( FALSE );
+ m_actionDeleteElement = new KAction( i18n( "&Delete" ), 0, m_documentWidget, SLOT( deleteElements() ), actionCollection(), "element_delete" );
+ m_actionDeleteElement->setToolTip( i18n( "Delete the selected BibTeX elements" ) );
+ m_actionDeleteElement->setEnabled( FALSE );
+
+ m_actionShowComments = new KToggleAction( i18n( "Show &Comments" ), 0, this, SLOT( slotToggleShowSpecialElements() ), actionCollection(), "view_showcomments" );
+ m_actionShowComments->setToolTip( i18n( "Show the comments of a BibTeX document" ) );
+ m_actionShowMacros = new KToggleAction( i18n( "Show &Macros" ), 0, this, SLOT( slotToggleShowSpecialElements() ), actionCollection(), "view_showmacros" );
+ m_actionShowMacros->setToolTip( i18n( "Show the macros of a BibTeX document" ) );
+
+ m_actionUseInPipe = new KToggleAction( i18n( "Accept input from other programs" ), 0, this , SLOT( slotUseInPipe() ), actionCollection(), "useinpipe" );
+
+ connect( m_documentWidget, SIGNAL( listViewSelectionChanged( int ) ), this, SLOT( slotUpdateMenu( int ) ) );
+
+ if ( m_mainWindow != NULL )
+ {
+ KStatusBar * statusBar = m_mainWindow->statusBar();
+ if ( statusBar != NULL )
+ {
+ connect( actionCollection(), SIGNAL( actionStatusText( const QString & ) ), statusBar, SLOT( message( const QString & ) ) );
+ connect( actionCollection(), SIGNAL( clearStatusText() ), statusBar, SLOT( clear() ) );
+ }
+ }
+
+ actionCollection() ->setHighlightingEnabled( true );
+
+ KActionMenu *acmElementNew = new KActionMenu( i18n( "&New" ), QIconSet( SmallIcon( "filenew" ) ), actionCollection(), "element_new" );
+ acmElementNew->setToolTip( i18n( "Add a new element to this BibTeX document" ) );
+ acmElementNew->setEnabled( FALSE );
+}
+
+bool KBibTeXPart::slotNewElement()
+{
+ if ( isReadWrite() && sender() )
+ {
+ QString elementType;
+
+ if ( strncmp( sender() ->name(), "element_new_entry_", 18 ) == 0 )
+ elementType = QString( sender() ->name() + 18 );
+ else if ( strcmp( sender() ->name(), "element_new_comment" ) == 0 )
+ elementType = "comment";
+ else if ( strcmp( sender() ->name(), "element_new_macro" ) == 0 )
+ elementType = "macro";
+ else if ( strcmp( sender() ->name(), "element_new_preamble" ) == 0 )
+ elementType = "preamble";
+ else
+ return FALSE;
+
+ bool result = m_documentWidget->newElement( elementType );
+ if ( result )
+ setModified( TRUE );
+ return result;
+ }
+
+ return FALSE;
+}
+
+void KBibTeXPart::readSettings()
+{
+ KBibTeX::Settings * settings = KBibTeX::Settings::self();
+ KConfig * config = KBibTeXPartFactory::instance() ->config();
+ settings->load( config );
+
+ m_actionShowComments->setChecked( settings->editing_ShowComments );
+ m_actionShowMacros->setChecked( settings->editing_ShowMacros );
+}
+
+void KBibTeXPart::writeSettings()
+{
+ if ( !m_initializationDone )
+ return ;
+
+ KBibTeX::Settings * settings = KBibTeX::Settings::self();
+ m_documentWidget->saveState();
+
+ KConfig * config = KBibTeXPartFactory::instance() ->config();
+
+ settings->editing_ShowComments = m_actionShowComments->isChecked();
+ settings->editing_ShowMacros = m_actionShowMacros->isChecked();
+
+ settings->save( config );
+
+ config->sync();
+}
+
+void KBibTeXPart::slotUpdateMenu( int numSelectedItems )
+{
+ m_documentWidget->updateViewDocumentMenu();
+ m_documentWidget->updateAssignKeywords();
+
+ m_actionEditElement->setEnabled( numSelectedItems == 1 );
+ m_actionDeleteElement->setEnabled( isReadWrite() && numSelectedItems > 0 );
+ m_actionEditCut->setEnabled( isReadWrite() && numSelectedItems > 0 );
+ m_actionEditCopy->setEnabled( numSelectedItems > 0 );
+ m_actionEditCopyRef->setEnabled( numSelectedItems > 0 );
+ m_actionElementSendToLyX->setEnabled( numSelectedItems > 0 );
+ m_actionMenuSearchWebsites->setEnabled( numSelectedItems == 1 );
+ m_actionViewDocument->setEnabled( numSelectedItems == 1 && m_actionViewDocument->popupMenu() ->count() > 0 );
+ m_actionAssignKeywords->setEnabled( numSelectedItems > 0 );
+ m_actionNormalizeIds->setEnabled( numSelectedItems > 0 && isReadWrite() );
+}
+
+void KBibTeXPart::slotUndoChanged( bool undoAvailable )
+{
+ m_actionEditUndo->setEnabled( undoAvailable );
+}
+
+void KBibTeXPart::slotUseInPipe()
+{
+ if ( m_inPipe == NULL && QFile::exists( inPipeFilename ) )
+ {
+ KMessageBox::error( widget(), QString( i18n( "Some other KBibTeX instance is using the pipe.\nIf this assumption is wrong, please delete '%1'." ) ).arg( inPipeFilename ), i18n( "Pipe already in use" ) );
+ }
+ else
+ {
+ if ( m_inPipe != NULL )
+ {
+// remove pipe
+ m_inPipe->close();
+ m_inPipe->remove();
+ delete m_inPipe;
+ m_inPipe = NULL;
+ QFile::remove( inPipeFilename );
+ }
+ else
+ {
+// create pipe
+ if ( ::mkfifo( inPipeFilename.latin1(), 0600 ) == 0 )
+ {
+ m_inPipe = new QFile( inPipeFilename );
+ if ( !m_inPipe->open( IO_ReadOnly ) || fcntl( m_inPipe->handle(), F_SETFL, O_NONBLOCK ) < 0 )
+ {
+ m_inPipe->close();
+ m_inPipe = NULL;
+ }
+ if ( m_inPipe == NULL )
+ QFile::remove( inPipeFilename );
+ }
+
+ if ( m_inPipe == NULL )
+ KMessageBox::error( widget(), QString( i18n( "Could not create pipe at '%1'." ) ).arg( inPipeFilename ), i18n( "Error creating pipe" ) );
+ }
+ }
+
+ m_actionUseInPipe->setChecked( m_inPipe != NULL );
+}
+
+void KBibTeXPart::slotSearchWebsites( int id )
+{
+ KBibTeX::Settings * settings = KBibTeX::Settings::self();
+ m_documentWidget->searchWebsites( settings->searchURLs[ id - 1 ] ->url, settings->searchURLs[ id - 1 ] ->includeAuthor );
+}
+
+void KBibTeXPart::slotToggleShowSpecialElements()
+{
+ KBibTeX::Settings * settings = KBibTeX::Settings::self();
+ settings->editing_ShowComments = m_actionShowComments->isChecked();
+ settings->editing_ShowMacros = m_actionShowMacros->isChecked();
+
+ m_documentWidget->updateViews();
+}
+
+bool KBibTeXPart::save()
+{
+ if ( !url().isValid() || url().isEmpty() )
+ return saveAs();
+ else
+ return KParts::ReadWritePart::save();
+}
+
+void KBibTeXPart::slotDeferredInitialization()
+{
+ if ( factory() != NULL )
+ {
+ m_documentWidget->setFactory( factory(), this );
+ m_documentWidget->deferredInitialization();
+ m_initializationDone = TRUE;
+ }
+ else
+ {
+ m_defInitCounter++;
+
+ if ( m_defInitCounter > 5 )
+ {
+ KMessageBox::sorry( widget(), i18n( "The KBibTeX part has problems to initialize itself. Only limited functionality will be available." ), i18n( "KBibTeX Part" ) );
+ return ;
+ }
+ QTimer::singleShot( 250, this, SLOT( slotDeferredInitialization() ) );
+ }
+}
+
+// It's usually safe to leave the factory code alone.. with the
+// notable exception of the KAboutData data
+#include <kaboutdata.h>
+#include <klocale.h>
+
+KInstance* KBibTeXPartFactory::s_instance = 0L;
+KAboutData* KBibTeXPartFactory::s_about = 0L;
+
+KBibTeXPartFactory::KBibTeXPartFactory()
+ : KParts::Factory()
+{
+ // nothing
+}
+
+KBibTeXPartFactory::~KBibTeXPartFactory()
+{
+ delete s_instance;
+ delete s_about;
+
+ s_instance = 0L;
+}
+
+KParts::Part* KBibTeXPartFactory::createPartObject( QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name,
+ const char *classname, const QStringList & /* args */ )
+{
+ // Create an instance of our Part
+ KBibTeXPart * obj = new KBibTeXPart( parentWidget, widgetName, parent, name );
+
+ // See if we are to be read-write or not
+ if ( QCString( classname ) == "KParts::ReadOnlyPart" )
+ obj->setReadWrite( false );
+
+ return obj;
+}
+
+KInstance* KBibTeXPartFactory::instance()
+{
+ if ( !s_instance )
+ {
+ s_about = new KAboutData( "kbibtexpart", I18N_NOOP( "KBibTeXPart" ), "0.2.3.91" );
+ s_about->addAuthor( "Thomas Fischer", 0, "[email protected]" );
+ s_instance = new KInstance( s_about );
+ }
+ return s_instance;
+}
+
+extern "C"
+{
+ void* init_libkbibtexpart()
+ {
+ return new KBibTeXPartFactory;
+ }
+};
+
+#include "kbibtex_part.moc"
+
diff --git a/src/kbibtex_part.desktop b/src/kbibtex_part.desktop
new file mode 100644
index 0000000..57cba41
--- /dev/null
+++ b/src/kbibtex_part.desktop
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=KBibTeXPart
+Name[et]=KBibTeX komponent
+Name[hi]=KBibTeXपार्ट
+Name[sv]=KBibTeX-del
+Name[ta]=KBibTeXபாகம்
+Name[xx]=xxKBibTeXPartxx
+Name[pl]=Moduł KBibTeX
+Name[pt_BR]=Parte do KBibTeX
+Name[de]=Einbettungsfähige Komponente von KBibTeX
+MimeType=text/x-bibtex;application/x-endnote-library;
+ServiceTypes=KParts/ReadOnlyPart,KParts/ReadWritePart
+X-KDE-Library=libkbibtexpart
+Type=Service
diff --git a/src/kbibtex_part.h b/src/kbibtex_part.h
new file mode 100644
index 0000000..f9a045a
--- /dev/null
+++ b/src/kbibtex_part.h
@@ -0,0 +1,169 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+#ifndef _KBIBTEXPART_H_
+#define _KBIBTEXPART_H_
+
+#include <kparts/part.h>
+#include <kparts/factory.h>
+
+#include <element.h>
+#include <xsltransform.h>
+#include <documentwidget.h>
+#include <settingsdlg.h>
+
+class QWidget;
+class QTextEdit;
+class QFile;
+class QLabel;
+class QTabWidget;
+class QPainter;
+class QListViewItem;
+class QProgressDialog;
+class KURL;
+class KListView;
+class KAction;
+class KActionMenu;
+class KToggleAction;
+class KMainWindow;
+
+class KBibTeXPart : public KParts::ReadWritePart
+{
+ Q_OBJECT
+
+public:
+ KBibTeXPart( QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name );
+
+ virtual ~KBibTeXPart();
+
+ void setReadWrite( bool rw );
+
+ void setModified( bool modified );
+
+ bool saveAs();
+ bool queryClose();
+ virtual bool closeURL();
+
+public slots:
+ virtual bool save();
+
+signals:
+ void signalAddRecentURL( const KURL& );
+
+protected:
+ virtual bool openFile();
+ virtual bool saveFile();
+
+protected slots:
+ void slotFileSaveAs();
+ void slotFileMerge();
+ void slotFileExport();
+ void slotFileStatistics();
+ void slotFileFindDups();
+ void slotPreferences();
+
+private slots:
+ bool slotNewElement();
+ void slotSearchWebsites( int id );
+ void slotToggleShowSpecialElements();
+ void slotDeferredInitialization();
+ void slotUpdateMenu( int numSelectedItems );
+ void slotUndoChanged( bool undoAvailable );
+ void slotUseInPipe();
+
+private:
+ enum SearchDirection
+ {
+ sdForward, sdBackward
+ };
+ enum SaveStatus
+ {
+ ssSave, ssExport, ssFailed
+ };
+
+ int m_defInitCounter;
+ QLabel *m_preview;
+ QProgressDialog *m_progressDialog;
+ KBibTeX::DocumentWidget *m_documentWidget;
+ KBibTeX::SettingsDlg *m_settingsDlg;
+ KAction *m_actionFileMerge;
+ KAction *m_actionFileExport;
+ KAction *m_actionFileStatistics;
+ KAction *m_actionFileFindDups;
+ KAction *m_actionEditUndo;
+ KAction *m_actionElementSendToLyX;
+ KAction *m_actionEditElement;
+ KAction *m_actionDeleteElement;
+ KAction *m_actionEditCut;
+ KAction *m_actionEditCopy;
+ KAction *m_actionEditCopyRef;
+ KAction *m_actionEditPaste;
+ KAction *m_actionEditSelectAll;
+ KAction *m_actionEditFind;
+ KAction *m_actionEditFindNext;
+ KAction *m_actionPreferences;
+ KAction *m_actionSearchOnlineDatabases;
+ KActionMenu *m_actionViewDocument;
+ KAction *m_actionViewFirstDocument;
+ KAction *m_actionViewDocumentOnlineRef;
+ KActionMenu *m_actionAssignKeywords;
+ KAction *m_actionNormalizeIds;
+ KActionMenu *m_actionMenuSearchWebsites;
+ KActionMenu *m_actionViewShowColumns;
+ KAction *m_actionSearchNCBI;
+ KToggleAction *m_actionUseInPipe;
+ KToggleAction *m_actionShowComments;
+ KToggleAction *m_actionShowMacros;
+ KMainWindow *m_mainWindow;
+ QValueList<KBibTeX::WebQuery*> webQueryList;
+ bool m_initializationDone;
+ QFile *m_inPipe;
+
+ void readSettings();
+ void writeSettings();
+
+ void setupGUI( QWidget *parentWidget, const char *name );
+ void setupActions();
+
+signals:
+ void progressCancel();
+};
+
+class KInstance;
+class KAboutData;
+
+class KBibTeXPartFactory : public KParts::Factory
+{
+ Q_OBJECT
+public:
+ KBibTeXPartFactory();
+ virtual ~KBibTeXPartFactory();
+ virtual KParts::Part* createPartObject( QWidget * parentWidget, const char * widgetName,
+ QObject * parent, const char * name,
+ const char * classname, const QStringList & /* args */ );
+ static KInstance* instance();
+
+private:
+ static KInstance* s_instance;
+ static KAboutData* s_about;
+};
+
+#endif // _KBIBTEXPART_H_
diff --git a/src/kbibtex_part.rc b/src/kbibtex_part.rc
new file mode 100644
index 0000000..9c970d9
--- /dev/null
+++ b/src/kbibtex_part.rc
@@ -0,0 +1,158 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kbibtex_part" version="1">
+<MenuBar>
+ <Menu name="file">
+ <Action name="file_merge"/>
+ <Action name="file_save"/>
+ <Action name="file_save_as"/>
+ <Action name="file_export"/>
+ <Separator/>
+ <Action name="file_statistics"/>
+ <Action name="file_finddups"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_undo" />
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_copyref"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="edit_select_all"/>
+ <Separator/>
+ <Action name="edit_find"/>
+ <Action name="edit_find_next"/>
+ </Menu>
+ <Menu name="element"><text>E&amp;lement</text>
+ <Menu name="element_new"><text>&amp;New</text>
+ <Action name="element_new_entry_article" />
+ <Action name="element_new_entry_book" />
+ <Action name="element_new_entry_booklet" />
+ <Action name="element_new_entry_electronic" />
+ <Action name="element_new_entry_inbook" />
+ <Action name="element_new_entry_incollection" />
+ <Action name="element_new_entry_inproceedings" />
+ <Action name="element_new_entry_manual" />
+ <Action name="element_new_entry_mastersthesis" />
+ <Action name="element_new_entry_misc" />
+ <Action name="element_new_entry_phdthesis" />
+ <Action name="element_new_entry_proceedings" />
+ <Action name="element_new_entry_techreport" />
+ <Action name="element_new_entry_unpublished" />
+ <Separator/>
+ <Action name="element_new_preamble" />
+ <Action name="element_new_comment" />
+ <Action name="element_new_macro" />
+ </Menu>
+ <Action name="element_edit" />
+ <Action name="element_delete" />
+ <Separator/>
+ <Action name="search_document_online"/>
+ <Action name="view_document"/>
+ <Action name="assign_keywords"/>
+ <Action name="normalize_ids"/>
+ <Separator/>
+ <Action name="element_sendtolyx"/>
+ <Separator/>
+ <Action name="search_onlinedatabases"/>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="view_showmacros" />
+ <Action name="view_showcomments" />
+ <Action name="view_showcolumns" />
+ </Menu>
+ <Menu name="settings"><text>Se&amp;ttings</text>
+ <Action name="show_statusbar" append="show_merge"/>
+ <!-- <Action name="useinpipe" /> -->
+ <Action name="options_configure" />
+ <Action name="options_configure_editor" />
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar">
+ <Action name="file_save"/>
+</ToolBar>
+<Menu name="popup_bibtexlist">
+ <Menu name="element_new"><text>&amp;New</text>
+ <Action name="element_new_entry_article" />
+ <Action name="element_new_entry_book" />
+ <Action name="element_new_entry_booklet" />
+ <Action name="element_new_entry_electronic" />
+ <Action name="element_new_entry_inbook" />
+ <Action name="element_new_entry_incollection" />
+ <Action name="element_new_entry_inproceedings" />
+ <Action name="element_new_entry_manual" />
+ <Action name="element_new_entry_mastersthesis" />
+ <Action name="element_new_entry_misc" />
+ <Action name="element_new_entry_phdthesis" />
+ <Action name="element_new_entry_proceedings" />
+ <Action name="element_new_entry_techreport" />
+ <Action name="element_new_entry_unpublished" />
+ <Separator/>
+ <Action name="element_new_preamble" />
+ <Action name="element_new_comment" />
+ <Action name="element_new_macro" />
+ </Menu>
+ <Action name="element_edit" />
+ <Action name="element_delete" />
+ <Separator/>
+ <Action name="search_document_online"/>
+ <Action name="view_document"/>
+ <Action name="assign_keywords"/>
+ <Action name="normalize_ids"/>
+ <Separator/>
+ <Action name="element_sendtolyx"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_copyref"/>
+ <Action name="edit_paste"/>
+</Menu>
+<Menu name="popup_newelements">
+ <Action name="element_new_entry_article" />
+ <Action name="element_new_entry_book" />
+ <Action name="element_new_entry_booklet" />
+ <Action name="element_new_entry_electronic" />
+ <Action name="element_new_entry_inbook" />
+ <Action name="element_new_entry_incollection" />
+ <Action name="element_new_entry_inproceedings" />
+ <Action name="element_new_entry_manual" />
+ <Action name="element_new_entry_mastersthesis" />
+ <Action name="element_new_entry_misc" />
+ <Action name="element_new_entry_phdthesis" />
+ <Action name="element_new_entry_proceedings" />
+ <Action name="element_new_entry_techreport" />
+ <Action name="element_new_entry_unpublished" />
+ <Separator/>
+ <Action name="element_new_preamble" />
+ <Action name="element_new_comment" />
+ <Action name="element_new_macro" />
+</Menu>
+<Menu name="ktexteditor_popup" noMerge="1">
+ <Menu name="element_new"><text>&amp;New</text>
+ <Action name="element_new_entry_article" />
+ <Action name="element_new_entry_book" />
+ <Action name="element_new_entry_booklet" />
+ <Action name="element_new_entry_electronic" />
+ <Action name="element_new_entry_inbook" />
+ <Action name="element_new_entry_incollection" />
+ <Action name="element_new_entry_inproceedings" />
+ <Action name="element_new_entry_manual" />
+ <Action name="element_new_entry_mastersthesis" />
+ <Action name="element_new_entry_misc" />
+ <Action name="element_new_entry_phdthesis" />
+ <Action name="element_new_entry_proceedings" />
+ <Action name="element_new_entry_techreport" />
+ <Action name="element_new_entry_unpublished" />
+ <Separator/>
+ <Action name="element_new_preamble" />
+ <Action name="element_new_comment" />
+ <Action name="element_new_macro" />
+ </Menu>
+ <Separator/>
+ <Action name="edit_undo" />
+ <Separator/>
+ <Action name="edit_cut" />
+ <Action name="edit_copy" />
+ <Action name="edit_paste" />
+</Menu>
+</kpartgui>
diff --git a/src/kbibtex_shell.rc b/src/kbibtex_shell.rc
new file mode 100644
index 0000000..58b4937
--- /dev/null
+++ b/src/kbibtex_shell.rc
@@ -0,0 +1,31 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kbibtex_shell" version="1">
+<MenuBar>
+ <Menu noMerge="1" name="file"><text>&amp;File</text>
+ <Action name="file_new"/>
+ <Action name="file_open"/>
+ <Action name="file_open_recent"/>
+ <Merge/>
+ <Separator/>
+ <Action name="file_close"/>
+ </Menu>
+ <Merge/>
+ <Menu noMerge="1" name="settings"><text>Se&amp;ttings</text>
+ <Action name="options_show_toolbar"/>
+ <Action name="options_show_statusbar"/>
+ <Merge name="show_merge"/>
+ <Separator/>
+ <Action name="options_configure_keybinding"/>
+ <Action name="options_configure_toolbars"/>
+ <Action name="options_configure"/>
+ <Merge name="configure_merge"/>
+ <Separator/>
+ <Merge/>
+ </Menu>
+</MenuBar>
+<ToolBar noMerge="1" name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="file_new"/>
+ <Action name="file_open_recent"/>
+ <Merge/>
+</ToolBar>
+</kpartgui>
diff --git a/src/kbibtexshell.cpp b/src/kbibtexshell.cpp
new file mode 100644
index 0000000..e3182dd
--- /dev/null
+++ b/src/kbibtexshell.cpp
@@ -0,0 +1,387 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qprocess.h>
+
+#include <kkeydialog.h>
+#include <kencodingfiledialog.h>
+#include <kconfig.h>
+#include <kurl.h>
+#include <kactionclasses.h>
+#include <kedittoolbar.h>
+#include <kdebug.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kio/netaccess.h>
+#include <klibloader.h>
+#include <kmessagebox.h>
+#include <kstatusbar.h>
+#include <klocale.h>
+
+#include <kbibtex_part.h>
+#include "kbibtexshell.h"
+
+KBibTeXShell::KBibTeXShell( QWidget* parentWidget, const char* name )
+ : KParts::MainWindow( parentWidget, name ), m_part( NULL ), m_parentWidget( parentWidget )
+{
+ // set the shell's ui resource file
+ setXMLFile( "kbibtex_shell.rc" );
+
+ // then, setup our actions
+ setupActions();
+
+ // and a status bar
+ statusBar() ->show();
+
+ // this routine will find and load our Part. it finds the Part by
+ // name which is a bad idea usually.. but it's alright in this
+ // case since our Part is made for this Shell
+ KLibFactory *factory = KLibLoader::self() ->factory( "libkbibtexpart" );
+ if ( factory )
+ {
+ // now that the Part is loaded, we cast it to a Part to get
+ // our hands on it
+ m_part = static_cast<KParts::ReadWritePart *>( factory->create( this, "kbibtex_part", "KParts::ReadWritePart" ) );
+
+ if ( m_part )
+ {
+ // tell the KParts::MainWindow that this is indeed the main widget
+ setCentralWidget( m_part->widget() );
+
+ // and integrate the part's GUI with the shell's
+ createGUI( m_part );
+ }
+
+ }
+ else
+ {
+ // if we couldn't find our Part, we exit since the Shell by
+ // itself can't do anything useful
+ KMessageBox::error( this, i18n( "Could not find our part!" ) );
+ kapp->quit();
+ // we return here, cause kapp->quit() only means "exit the
+ // next time we enter the event loop...
+ return ;
+ }
+
+ // apply the saved mainwindow settings, if any, and ask the mainwindow
+ // to automatically save settings if changed: window size, toolbar
+ // position, icon size, etc.
+ setAutoSaveSettings();
+
+ readConfig();
+
+#ifdef HAVE_YAZ
+ kdDebug() << "Using YAZ to access Z39.50 databases" << endl;
+#else // HAVE_YAZ
+ kdDebug() << "YAZ not linked to KBibTeX. No access to Z39.50 databases possible" << endl;
+#endif // HAVE_YAZ
+
+}
+
+KBibTeXShell::~KBibTeXShell()
+{
+ // nothing
+}
+
+bool KBibTeXShell::openURL( const KURL& url )
+{
+ if ( url.isEmpty() )
+ return false;
+
+ // About this function, the style guide (
+ // http://developer.kde.org/documentation/standards/kde/style/basics/index.html )
+ // says that it should open a new window if the document is _not_
+ // in its initial state. This is what we do here.
+
+ // If there is no part yet created, create new one...
+
+ if ( m_part->url().isEmpty() && !m_part->isModified() )
+ {
+ if ( !m_part->openURL( url ) )
+ return FALSE;
+ }
+ else
+ {
+ KBibTeXShell *shell = new KBibTeXShell();
+
+ if ( !shell->part() ->openURL( url ) )
+ return FALSE;
+ else
+ initializePart( shell->part() );
+ shell->show();
+ }
+
+ m_recentFiles->addURL( url );
+ return TRUE;
+}
+
+KParts::ReadWritePart * KBibTeXShell::part()
+{
+ return m_part;
+}
+
+void KBibTeXShell::readConfig( KConfig *config )
+{
+ config->setGroup( "Session" );
+ m_recentFiles->loadEntries( config );
+ m_recentFiles->setEnabled( true ); // force enabling
+ m_recentFiles->setToolTip( i18n( "Click to open a file\nClick and hold to open a recent file" ) );
+}
+
+void KBibTeXShell::writeConfig( KConfig *config )
+{
+ config->setGroup( "Session" );
+ m_recentFiles->saveEntries( config );
+ config->sync();
+}
+
+void KBibTeXShell::readConfig()
+{
+ KConfig * config = kapp->config();
+ readConfig( config );
+}
+
+void KBibTeXShell::writeConfig()
+{
+ KConfig * config = kapp->config();
+ writeConfig( config );
+}
+
+QString KBibTeXShell::encoding()
+{
+ return "utf8";
+}
+
+void KBibTeXShell::slotAddRecentURL( const KURL&url )
+{
+ m_recentFiles->addURL( url );
+}
+
+void KBibTeXShell::setupActions()
+{
+ KAction * action;
+
+ action = KStdAction::openNew( this, SLOT( slotFileNew() ), actionCollection() );
+ action ->setToolTip( i18n( "Create a new window for a new BibTeX file" ) );
+ KAction *actionOpen = KStdAction::open( this, SLOT( slotFileOpen() ), actionCollection() );
+ actionOpen->setToolTip( i18n( "Open an existing BibTeX file" ) );
+
+ m_recentFiles = KStdAction::openRecent( this, SLOT( slotFileOpen( const KURL& ) ), actionCollection() );
+ m_recentFiles->setWhatsThis( i18n( "This lists files which you have opened recently, and allows you to easily open them again." ) );
+ connect( m_recentFiles, SIGNAL( activated() ), actionOpen, SLOT( activate() ) );
+
+ action = KStdAction::close( this, SLOT( slotFileClose() ), actionCollection() );
+ action->setToolTip( i18n( "Close this KBibTeX window" ) );
+ // action = KStdAction::quit( kapp, SLOT( closeAllWindows() ), actionCollection() );
+ // action->setToolTip( i18n( "Close all windows and quit KBibTeX" ) );
+
+ m_statusbarAction = KStdAction::showStatusbar( this, SLOT( optionsShowStatusbar() ), actionCollection() );
+ m_statusbarAction->setToolTip( i18n( "Show or hide the window's status bar" ) );
+
+ KStdAction::keyBindings( this, SLOT( optionsConfigureKeys() ), actionCollection() ) ->setToolTip( i18n( "Configure key bindings for KBibTeX" ) );
+ KStdAction::configureToolbars( this, SLOT( optionsConfigureToolbars() ), actionCollection() ) ->setToolTip( i18n( "Configure the tool bar for KBibTeX" ) );
+
+ connect( actionCollection(), SIGNAL( actionStatusText( const QString & ) ), this, SLOT( slotActionStatusText( const QString & ) ) );
+ connect( actionCollection(), SIGNAL( clearStatusText( ) ), statusBar(), SLOT( clear() ) );
+}
+
+void KBibTeXShell::slotActionStatusText( const QString &text )
+{
+ KStatusBar * stb = statusBar();
+
+ if ( stb )
+ stb->message( text );
+}
+
+void KBibTeXShell::saveProperties( KConfig* /*config*/ )
+{
+ // the 'config' object points to the session managed
+ // config file. anything you write here will be available
+ // later when this app is restored
+}
+
+void KBibTeXShell::readProperties( KConfig* /*config*/ )
+{
+ // the 'config' object points to the session managed
+ // config file. this function is automatically called whenever
+ // the app is being restored. read in here whatever you wrote
+ // in 'saveProperties'
+}
+
+void KBibTeXShell::optionsShowStatusbar()
+{
+ // this is all very cut and paste code for showing/hiding the
+ // statusbar
+ if ( m_statusbarAction->isChecked() )
+ statusBar() ->show();
+ else
+ statusBar() ->hide();
+}
+
+void KBibTeXShell::optionsConfigureKeys()
+{
+ KKeyDialog dlg( false, this );
+ QPtrList<KXMLGUIClient> clients = guiFactory()->clients();
+ for ( QPtrListIterator<KXMLGUIClient> it( clients ); it.current(); ++it )
+ {
+ dlg.insert(( *it )->actionCollection() );
+ }
+ dlg.configure();
+}
+
+void KBibTeXShell::optionsConfigureToolbars()
+{
+#if defined(KDE_MAKE_VERSION)
+# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0)
+ saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );
+# else
+ saveMainWindowSettings( KGlobal::config() );
+# endif
+#else
+ saveMainWindowSettings( KGlobal::config() );
+#endif
+
+ // use the standard toolbar editor
+ KEditToolbar dlg( factory() );
+ connect( &dlg, SIGNAL( newToolbarConfig() ),
+ this, SLOT( applyNewToolbarConfig() ) );
+ dlg.exec();
+}
+
+void KBibTeXShell::applyNewToolbarConfig()
+{
+#if defined(KDE_MAKE_VERSION)
+# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0)
+ applyMainWindowSettings( KGlobal::config(), autoSaveGroup() );
+# else
+ applyMainWindowSettings( KGlobal::config() );
+# endif
+#else
+ applyMainWindowSettings( KGlobal::config() );
+#endif
+}
+
+bool KBibTeXShell::queryClose()
+{
+ if ( m_part && !m_part ->closeURL() )
+ return FALSE;
+
+ writeConfig();
+
+ return KParts::MainWindow::queryClose();
+}
+
+void KBibTeXShell::slotFileNew()
+{
+ // this slot is called whenever the File->New menu is selected,
+ // the New shortcut is pressed (usually CTRL+N) or the New toolbar
+ // button is clicked
+
+ // About this function, the style guide (
+ // http://developer.kde.org/documentation/standards/kde/style/basics/index.html )
+ // says that it should open a new window if the document is _not_
+ // in its initial state. This is what we do here..
+ if ( ! m_part->url().isEmpty() || m_part->isModified() )
+ {
+ ( new KBibTeXShell() ) ->show();
+ };
+}
+
+/**
+ * Show a file open dialog where a user can select one or several
+ * files for opening.
+ */
+void KBibTeXShell::slotFileOpen()
+{
+ bool bibUtilsAvailable = checkExternalToolAvailable( "xml2bib" ) && checkExternalToolAvailable( "end2xml" );
+ QString startDir = ! m_part->url().isEmpty() ? m_part->url().url() : QDir::currentDirPath();
+ KURL mergeURL = KFileDialog::getOpenURL( startDir, QString( "*.bib *.ris" ) +
+ ( bibUtilsAvailable ? " *.xml *.ref *.refer *.rfr *.txt *.isi *.cgi" : "" ) + "|" + i18n( "Supported Bibliographies" ) + "\n*.bib|" + i18n( "BibTeX (*.bib)" ) + "\n*.ris|" + i18n( "Reference Manager (*.ris)" ) + ( bibUtilsAvailable ? "\n*.ref *.refer *.rfr *.txt|" + i18n( "EndNote (Refer format) (*.ref *.refer *.rfr *.txt)" ) + "\n*.isi *.cgi|" + i18n( "ISI Web of Knowledge (*.isi *.cgi)" ) + "\n*.xml|" + i18n( "MODS or EndNote XML (*.xml)" ) : "" ) + "\n*|" + i18n( "All files (*.*)" )
+ , widget() );
+ slotFileOpen( mergeURL );
+}
+
+
+/**
+ * Open a given url in a new window.
+ */
+void KBibTeXShell::slotFileOpen( const KURL& url )
+{
+ if ( url.isEmpty() ) return ;
+
+ if ( !KIO::NetAccess::exists( url, TRUE, this ) )
+ {
+ m_recentFiles->removeURL( url );
+ KMessageBox::error( this, i18n( "The given file could not be read, check if it exists or if it is readable for the current user." ) );
+ return ;
+ }
+
+ if ( m_part->url().isEmpty() && !m_part->isModified() )
+ // we open the file in this window...
+ openURL( url );
+ else
+ {
+ // we open the file in a new window...
+ KBibTeXShell * shell = new KBibTeXShell();
+ if ( shell->openURL( url ) )
+ {
+ initializePart( shell->part() );
+ shell->show();
+ }
+ else
+ {
+ KMessageBox::error( this, i18n( "Could not open file '%1'." ).arg( url.path() ) );
+ }
+ }
+
+}
+
+/**
+ * Close currrent window
+ */
+void KBibTeXShell::slotFileClose()
+{
+ close();
+}
+
+void KBibTeXShell::initializePart( KParts::ReadWritePart* part )
+{
+ if ( part )
+ {
+ connect( static_cast<KBibTeXPart*>( part ), SIGNAL( signalAddRecentURL( const KURL & ) ), this, SLOT( slotAddRecentURL( const KURL& ) ) );
+ }
+}
+
+bool KBibTeXShell::checkExternalToolAvailable( const QString &binary )
+{
+ QProcess *process = new QProcess( binary );
+ bool ok = process->start();
+ ok &= process->normalExit();
+ if ( process->isRunning() )
+ {
+ process->kill();
+ ok = true;
+ }
+ delete process;
+ return ok;
+}
+
+
+#include "kbibtexshell.moc"
diff --git a/src/kbibtexshell.h b/src/kbibtexshell.h
new file mode 100644
index 0000000..b52d577
--- /dev/null
+++ b/src/kbibtexshell.h
@@ -0,0 +1,100 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+#ifndef _KBIBTEXSHELL_H_
+#define _KBIBTEXSHELL_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kapplication.h>
+#include <kparts/mainwindow.h>
+
+class QWidget;
+class QFrame;
+
+class KToggleAction;
+class KConfig;
+class KRecentFilesAction;
+
+class KBibTeXShell : public KParts::MainWindow
+{
+ Q_OBJECT
+
+public:
+ KBibTeXShell( QWidget* parentWidget = 0, const char* name = 0 );
+
+ virtual ~KBibTeXShell();
+
+ bool openURL( const KURL& url );
+
+ KParts::ReadWritePart *part();
+
+ //config file functions
+public:
+ void readConfig( KConfig * );
+ void writeConfig( KConfig * );
+
+ void readConfig();
+ void writeConfig();
+
+public:
+ static QString encoding();
+
+public slots:
+ void slotAddRecentURL( const KURL& );
+
+protected:
+ virtual bool queryClose( );
+
+private slots:
+ void slotFileNew();
+ void slotFileOpen();
+ void slotFileOpen( const KURL& url );
+ void slotFileClose();
+ void optionsShowStatusbar();
+ void optionsConfigureKeys();
+ void optionsConfigureToolbars();
+
+ void applyNewToolbarConfig();
+
+ void slotActionStatusText( const QString &text );
+
+private:
+ KParts::ReadWritePart *m_part;
+ QWidget* m_parentWidget;
+
+ KToggleAction *m_statusbarAction;
+
+ KRecentFilesAction *m_recentFiles;
+
+ void saveProperties( KConfig * );
+ void readProperties( KConfig * );
+
+ void setupAccel();
+ void setupActions();
+
+ void initializePart( KParts::ReadWritePart* );
+
+ bool checkExternalToolAvailable( const QString &binary );
+};
+
+#endif // _KBIBTEXSHELL_H_
diff --git a/src/latin1literal.h b/src/latin1literal.h
new file mode 100644
index 0000000..97c4cfc
--- /dev/null
+++ b/src/latin1literal.h
@@ -0,0 +1,99 @@
+/***************************************************************************
+ copyright : (C) 2003-2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+// this code was original published to the kde-core-devel email list
+// copyright 2003 Harri Porten <[email protected]>
+// Originally licensed under LGPL, included here under GPL v2
+
+#ifndef LATIN1LITERAL_H
+#define LATIN1LITERAL_H
+
+#include <qstring.h>
+
+namespace KBibTeX {
+
+/**
+ * A class for explicit marking of string literals encoded in the ISO
+ * 8859-1 character set. Allows for efficient, still (in terms of the
+ * chosen encoding) safe comparison with QString instances. To be used
+ * like this:
+ *
+ * \code
+ * QString s = .....
+ * if (s == Latin1Literal("o")) { ..... }
+ * \endcode
+ *
+ */
+#define Latin1Literal(s) \
+ KBibTeX::Latin1LiteralInternal((s), sizeof(s)/sizeof(char)-1)
+
+class Latin1LiteralInternal {
+
+public:
+ Latin1LiteralInternal(const char* s, size_t l)
+ : str(s), len(s ? l : (size_t)-1) { }
+
+ // this is lazy, leave these public since I can't figure out
+ // how to declare a friend function that works for gcc 2.95
+ const char* str;
+ size_t len;
+};
+
+} // end namespace
+
+inline
+bool operator==(const QString& s1, const KBibTeX::Latin1LiteralInternal& s2) {
+ const QChar* uc = s1.unicode();
+ const char* c = s2.str;
+ if(!c || !uc) {
+ return (!c && !uc);
+ }
+
+ const size_t& l = s2.len;
+ if(s1.length() != l) {
+ return false;
+ }
+
+ for(size_t i = 0; i < l; ++i, ++uc, ++c) {
+ if(uc->unicode() != static_cast<uchar>(*c)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+inline
+bool operator!=(const QString& s1, const KBibTeX::Latin1LiteralInternal& s2) {
+ return !(s1 == s2);
+}
+
+inline
+bool operator==(const KBibTeX::Latin1LiteralInternal& s1, const QString& s2) {
+ return s2 == s1;
+}
+
+inline
+bool operator!=(const KBibTeX::Latin1LiteralInternal& s1, const QString& s2) {
+ return !(s2 == s1);
+}
+
+#endif
diff --git a/src/macro.cpp b/src/macro.cpp
new file mode 100644
index 0000000..4958e6f
--- /dev/null
+++ b/src/macro.cpp
@@ -0,0 +1,115 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include "macro.h"
+
+namespace BibTeX
+{
+
+ Macro::Macro( const QString &key )
+ : Element(), m_key( key ), m_value( new Value() )
+ {
+ // nothing
+ }
+
+ Macro::Macro( Macro *other )
+ : Element(), m_value( NULL )
+ {
+ copyFrom( other );
+ }
+
+ Macro::~Macro()
+ {
+ delete m_value;
+ }
+
+ void Macro::setKey( const QString &key )
+ {
+ m_key = key;
+ }
+
+ QString Macro::key() const
+ {
+ return m_key;
+ }
+
+ Value *Macro::value() const
+ {
+ return m_value;
+ }
+
+ void Macro::setValue( Value *value )
+ {
+ if ( value != m_value )
+ {
+ delete m_value;
+
+ if ( value != NULL )
+ m_value = new Value( value );
+ else
+ m_value = NULL;
+ }
+ }
+
+ bool Macro::containsPattern( const QString& pattern, EntryField::FieldType fieldType, FilterType filterType, bool caseSensitive ) const
+ {
+ QString text = QString( m_key ).append( m_value->simplifiedText() );
+
+ if ( filterType == ftExact )
+ {
+ /** check for exact match */
+ return fieldType == EntryField::ftUnknown && text.contains( pattern, caseSensitive );
+ }
+ else
+ {
+ /** for each word in the search pattern ... */
+ QStringList words = QStringList::split( QRegExp( "\\s+" ), pattern );
+ unsigned int hits = 0;
+ for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it )
+ {
+ /** check if word is contained in text */
+ if ( fieldType == EntryField::ftUnknown && text.contains( *it, caseSensitive ) )
+ ++hits;
+ }
+
+ /** return success depending on filter type and number of hits */
+ return ( ( filterType == ftAnyWord && hits > 0 ) || ( filterType == ftEveryWord && hits == words.count() ) );
+ }
+ }
+
+ Element* Macro::clone()
+ {
+ return new Macro( this );
+ }
+
+ void Macro::copyFrom( Macro *other )
+ {
+ m_key = other->m_key;
+ if ( m_value != NULL ) delete m_value;
+ m_value = new Value( other->m_value );
+ }
+
+ QString Macro::text() const
+ {
+ return m_key + "=" + m_value->text();
+ }
+}
diff --git a/src/macro.h b/src/macro.h
new file mode 100644
index 0000000..ae42bdc
--- /dev/null
+++ b/src/macro.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXMACRO_H
+#define BIBTEXMACRO_H
+
+#include <element.h>
+#include <entryfield.h>
+#include <value.h>
+
+class QString;
+
+namespace BibTeX
+{
+ class Macro : public Element
+ {
+ public:
+ Macro( const QString &key );
+ Macro( Macro *other );
+ virtual ~Macro();
+
+ void setKey( const QString &key );
+ QString key() const;
+
+ Value *value() const;
+ void setValue( Value *value );
+
+ bool containsPattern( const QString& pattern, EntryField::FieldType fieldType = EntryField::ftUnknown, FilterType filterType = BibTeX::Element::ftExact, bool caseSensitive = FALSE ) const;
+
+ Element* clone();
+ void copyFrom( Macro *other );
+ QString text() const;
+
+ private:
+ QString m_key;
+ Value *m_value;
+ };
+
+}
+
+#endif
diff --git a/src/macrowidget.cpp b/src/macrowidget.cpp
new file mode 100644
index 0000000..5acca02
--- /dev/null
+++ b/src/macrowidget.cpp
@@ -0,0 +1,99 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <klineedit.h>
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <element.h>
+#include <fileexporterbibtex.h>
+#include <fileimporterbibtex.h>
+#include <fieldlineedit.h>
+
+#include "macrowidget.h"
+
+namespace KBibTeX
+{
+ QDialog::DialogCode MacroWidget::execute( BibTeX::Macro *macro, bool isReadOnly, QWidget *parent, const char *name )
+ {
+ KDialogBase * dlg = new KDialogBase( parent, name, TRUE, i18n( "Edit BibTeX Macro" ), KDialogBase::Ok | KDialogBase::Cancel );
+ MacroWidget* macroWidget = new MacroWidget( macro, isReadOnly, dlg, "MacroWidget" );
+
+ dlg->setMainWidget( macroWidget );
+ connect( dlg, SIGNAL( okClicked() ), macroWidget, SLOT( apply() ) );
+
+ QDialog::DialogCode result = ( QDialog::DialogCode ) dlg->exec();
+
+ delete( macroWidget );
+ delete( dlg );
+
+ return result;
+ }
+
+ MacroWidget::MacroWidget( BibTeX::Macro *bibtexmacro, bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_isReadOnly( isReadOnly ), m_bibtexmacro( bibtexmacro )
+ {
+ setupGUI();
+ reset();
+ }
+
+ MacroWidget::~MacroWidget()
+ {
+ // nothing
+ }
+
+ void MacroWidget::apply()
+ {
+ m_bibtexmacro->setKey( m_lineEditMacroId->text() );
+ BibTeX::Value *value = m_fieldLineEditMacroValue->value();
+ m_bibtexmacro->setValue( value );
+ }
+
+ void MacroWidget::reset()
+ {
+ m_lineEditMacroId->setText( m_bibtexmacro->key() );
+ m_fieldLineEditMacroValue->setValue( m_bibtexmacro->value() );
+ }
+
+ void MacroWidget::setupGUI()
+ {
+ setMinimumWidth( 384 );
+
+ QVBoxLayout * layout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "Macro &id:" ), this );
+ layout->addWidget( label );
+ m_lineEditMacroId = new KLineEdit( this, "m_lineEditMacroId" );
+ m_lineEditMacroId->setReadOnly( m_isReadOnly );
+ layout->addWidget( m_lineEditMacroId );
+ label->setBuddy( m_lineEditMacroId );
+
+ label = new QLabel( i18n( "Macro &value:" ), this );
+ layout->addWidget( label );
+ m_fieldLineEditMacroValue = new KBibTeX::FieldLineEdit( i18n( "Macro" ), KBibTeX::FieldLineEdit::itMultiLine, m_isReadOnly, this, "m_fieldLineEditMacroValue" );
+ layout->addWidget( m_fieldLineEditMacroValue );
+ label->setBuddy( m_fieldLineEditMacroValue );
+ }
+}
+
+#include "macrowidget.moc"
diff --git a/src/macrowidget.h b/src/macrowidget.h
new file mode 100644
index 0000000..38d65ec
--- /dev/null
+++ b/src/macrowidget.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+* Copyright ( C ) 2004 - 2005 by Thomas Fischer *
+* fischer@unix - ag.uni - kl.de *
+* *
+* This program is free software; you can redistribute it and / or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* ( at your option ) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111 - 1307, USA. *
+**************************************************************************/
+#ifndef MACROWIDGET_H
+#define MACROWIDGET_H
+
+#include <qwidget.h>
+
+#include <macro.h>
+#include <fieldlineedit.h>
+
+class KLineEdit;
+
+namespace KBibTeX
+{
+ class MacroWidget : public QWidget
+ {
+ Q_OBJECT
+ public:
+ static QDialog::DialogCode execute( BibTeX::Macro *macro, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+
+ private slots:
+ void apply();
+ void reset();
+
+ private:
+ bool m_isReadOnly;
+ BibTeX::Macro* m_bibtexmacro;
+ KLineEdit *m_lineEditMacroId;
+ KBibTeX::FieldLineEdit *m_fieldLineEditMacroValue;
+
+ MacroWidget( BibTeX::Macro *bibtexmacro, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~MacroWidget();
+
+ void setupGUI();
+
+ };
+}
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..ecec2b0
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,128 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+// #define UNIQUEAPP 1
+
+#include <qframe.h>
+#include <qpixmap.h>
+#ifdef UNIQUEAPP
+#include <kuniqueapplication.h>
+#else // UNIQUEAPP
+#include <kapplication.h>
+#endif // UNIQUEAPP
+#include <kmessagebox.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include "kbibtexshell.h"
+
+static const char description[] =
+ I18N_NOOP( "A BibTeX editor for KDE" );
+
+static const char version[] = "0.2.3.91";
+
+static KCmdLineOptions options[] =
+{
+ { "+[URL]", I18N_NOOP( "Document to open." ), 0
+ },
+ KCmdLineLastOption
+};
+
+#ifdef UNIQUEAPP
+class KBibTeXApplication: public KUniqueApplication
+#else // UNIQUEAPP
+class KBibTeXApplication: public KApplication
+#endif // UNIQUEAPP
+{
+public:
+#ifdef UNIQUEAPP
+ KBibTeXApplication() : KUniqueApplication()
+ {
+// nothing
+ }
+
+ int newInstance()
+ {
+#else // UNIQUEAPP
+ KBibTeXApplication() : KApplication()
+ {
+#endif // UNIQUEAPP
+ // see if we are starting with session management
+ if ( isRestored() )
+ {
+ RESTORE( KBibTeXShell );
+ }
+ else
+ {
+ // no session.. just start up normally
+ KCmdLineArgs * args = KCmdLineArgs::parsedArgs();
+
+ if ( args->count() == 0 )
+ {
+ KBibTeXShell * shell = new KBibTeXShell();
+ shell->show();
+ }
+ else
+ {
+ for ( int i = 0 ; i < args->count(); i++ )
+ {
+ KBibTeXShell *shell = new KBibTeXShell();
+ if ( shell->openURL( args->url( i ) ) )
+ shell->show();
+ else
+ {
+ kdDebug() << "Couldn't open file " << args->url( i ).path() << endl;
+ KMessageBox::error( NULL, i18n( "Could not open file '%1'." ).arg( args->url( i ).path() ) );
+ }
+ }
+ }
+ args->clear();
+ }
+
+#ifdef UNIQUEAPP
+ return 0;
+#endif // UNIQUEAPP
+
+ }
+};
+
+int main( int argc, char **argv )
+{
+ KAboutData about( "kbibtex", I18N_NOOP( "KBibTeX" ), version, description,
+ KAboutData::License_GPL, "(C) 2004-2009 Thomas Fischer", 0, "http://www.unix-ag.uni-kl.de/~fischer/kbibtex/", "[email protected]" );
+ about.addAuthor( "Thomas Fischer", 0, "[email protected]" );
+ about.setTranslator( I18N_NOOP( "NAME OF TRANSLATORS" ), I18N_NOOP( "EMAIL OF TRANSLATORS" ) );
+ KCmdLineArgs::init( argc, argv, &about );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+#ifdef UNIQUEAPP
+ if ( !KUniqueApplication::start() )
+ {
+ kdDebug() << "Reusing existing KBibTeX instance" << endl;
+ return 0;
+ }
+#endif // UNIQUEAPP
+
+ KBibTeXApplication app;
+ return app.exec();
+}
diff --git a/src/mergeelements.cpp b/src/mergeelements.cpp
new file mode 100644
index 0000000..9ad05d7
--- /dev/null
+++ b/src/mergeelements.cpp
@@ -0,0 +1,864 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <cmath>
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qprogressbar.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <ktextedit.h>
+#include <klistview.h>
+#include <kconfig.h>
+#include <kwin.h>
+
+#include <macro.h>
+#include <comment.h>
+#include <preamble.h>
+#include <macrowidget.h>
+#include <entrywidget.h>
+#include <preamblewidget.h>
+#include <settings.h>
+#include <fileexporterbibtex.h>
+#include "mergeelements.h"
+
+namespace KBibTeX
+{
+ MergeElementsCliqueItem::MergeElementsCliqueItem( BibTeX::Entry* _entry, BibTeX::Macro* _macro, BibTeX::Preamble* _preamble, QListView *parent )
+ : QCheckListItem( parent, _entry == NULL ?( _macro == NULL ? _preamble->value()->text() : _macro->key() ) : _entry->id(), QCheckListItem::CheckBox ), entry( _entry ), macro( _macro ), preamble( _preamble )
+ {
+ // nothing
+ }
+
+ void MergeElementsCliqueItem::stateChange( bool )
+ {
+ emit stateChanged( this );
+ };
+
+ MergeEntriesAlternativesController::MergeEntriesAlternativesController( const QString &label, QListView *parent )
+ : QCheckListItem( parent, label, QCheckListItem::RadioButtonController ), fieldType( BibTeX::EntryField::ftUnknown ), fieldName( label )
+ {
+ // nothing
+ }
+
+ MergeEntriesAlternativesController::MergeEntriesAlternativesController( BibTeX::EntryField::FieldType _fieldType, QListView *parent )
+ : QCheckListItem( parent, BibTeX::EntryField::fieldTypeToString( _fieldType ), QCheckListItem::RadioButtonController ), fieldType( _fieldType ), fieldName( BibTeX::EntryField::fieldTypeToString( _fieldType ) )
+ {
+ // nothing
+ }
+
+ MergeMacrosAlternativesController::MergeMacrosAlternativesController( bool isKey, QListView *parent )
+ : QCheckListItem( parent, isKey ? i18n( "Key" ) : i18n( "Value" ), QCheckListItem::RadioButtonController )
+ {
+ // nothing
+ }
+
+ MergeEntriesAlternativesItem::MergeEntriesAlternativesItem( BibTeX::EntryField *_field, MergeEntriesAlternativesController *parent )
+ : QCheckListItem( parent, _field->value()->text(), QCheckListItem::RadioButton ), field( _field )
+ {
+ // nothing
+ }
+
+ MergeMacrosAlternativesItem::MergeMacrosAlternativesItem( BibTeX::Value *_value, MergeMacrosAlternativesController *parent )
+ : QCheckListItem( parent, _value->text(), QCheckListItem::RadioButton ), value( _value )
+ {
+ // nothing
+ }
+
+ MergeElementsAlternativesId::MergeElementsAlternativesId( const QString & _id, MergeEntriesAlternativesController *parent ) : QCheckListItem( parent, _id, QCheckListItem::RadioButton ), id( _id )
+ {
+ // nothing
+ }
+
+ MergeMacroAlternativesKey::MergeMacroAlternativesKey( const QString & _key, MergeMacrosAlternativesController *parent ) : QCheckListItem( parent, _key, QCheckListItem::RadioButton ), key( _key )
+ {
+ // nothing
+ }
+
+ MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( const QString & _typeString, MergeEntriesAlternativesController *parent )
+ : QCheckListItem( parent, _typeString, QCheckListItem::RadioButton ), typeString( _typeString ), type( BibTeX::Entry::entryTypeFromString( _typeString ) )
+ {
+ // nothing
+ }
+
+ MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( BibTeX::Entry::EntryType _type, MergeEntriesAlternativesController *parent )
+ : QCheckListItem( parent, BibTeX::Entry::entryTypeToString( _type ), QCheckListItem::RadioButton ), typeString( BibTeX::Entry::entryTypeToString( _type ) ), type( _type )
+ {
+ // nothing
+ }
+
+ MergePreambleAlternativesController::MergePreambleAlternativesController( QListView *parent )
+ : QCheckListItem( parent, i18n( "Preamble text" ), QCheckListItem::RadioButtonController )
+ {
+ // nothing
+ }
+
+ MergePreambleAlternatives::MergePreambleAlternatives( const QString &_text, MergePreambleAlternativesController *parent )
+ :QCheckListItem( parent, _text, QCheckListItem::RadioButton ), text( _text )
+ {
+ // nothing
+ }
+
+ MergeElements::MergeElements( QWidget *parent )
+ : KDialogBase( parent, "MergeElements", true, "undefined", Ok | Cancel | User1 | User2, User1, true, KGuiItem( i18n( "Next" ), "next" ), KGuiItem( i18n( "Previous" ), "previous" ) ), m_currentCliqueIndex( 0 )
+ {
+ setupGUI();
+ }
+
+ MergeElements::~MergeElements()
+ {
+ KConfig * config = kapp->config();
+ config->setGroup( "MergeElements" );
+ saveWindowSize( config );
+ }
+
+ void MergeElements::setupGUI()
+ {
+ QWidget *vboxContainer = new QWidget( this );
+ setMainWidget( vboxContainer );
+ QBoxLayout *vboxLayout = new QVBoxLayout( vboxContainer, 0, KDialog::spacingHint() );
+ vboxLayout->setResizeMode( QLayout::Minimum );
+
+ QLabel *label = new QLabel( i18n( "Select elements to merge. At least two elements must be checked to perform a merge operation. Checked entries will be replaced by the merged element, unchecked elements will be kept." ), vboxContainer );
+ label->setAlignment( Qt::WordBreak );
+ vboxLayout->addWidget( label );
+ m_listViewClique = new KListView( vboxContainer );
+ m_listViewClique->addColumn( i18n( "Entry/Macro Id" ) );
+ m_listViewClique->setFullWidth( true );
+ m_listViewClique->setAllColumnsShowFocus( true );
+ vboxLayout->addWidget( m_listViewClique );
+ vboxLayout->setStretchFactor( m_listViewClique, 1 );
+ label->setBuddy( m_listViewClique );
+
+ m_progressBar = new QProgressBar( vboxContainer );
+ vboxLayout->addWidget( m_progressBar );
+
+ vboxLayout->addSpacing( KDialog::spacingHint() * 2 );
+
+ label = new QLabel( i18n( "Choose from this list which alternatives you want to keep in the merged element." ), vboxContainer );
+ label->setAlignment( Qt::WordBreak );
+ vboxLayout->addWidget( label );
+ m_listViewAlternatives = new KListView( vboxContainer );
+ m_listViewAlternatives->addColumn( i18n( "Field/Key" ) );
+ m_listViewAlternatives->setFullWidth( true );
+ m_listViewAlternatives->setAllColumnsShowFocus( true );
+ vboxLayout->addWidget( m_listViewAlternatives );
+ vboxLayout->setStretchFactor( m_listViewAlternatives, 3 );
+ label->setBuddy( m_listViewAlternatives );
+
+ connect( m_listViewClique, SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( slotPreviewElement( QListViewItem * ) ) );
+ connect( this, SIGNAL( user1Clicked() ), this, SLOT( slotNextClique() ) );
+ connect( this, SIGNAL( user2Clicked() ), this, SLOT( slotPreviousClique() ) );
+ connect( this, SIGNAL( okClicked() ), this, SLOT( saveCurrentMergeSet() ) );
+ }
+
+ void MergeElements::setClique( int cliqueIndex )
+ {
+ if ( m_currentCliqueIndex != cliqueIndex )
+ saveCurrentMergeSet();
+ m_currentCliqueIndex = cliqueIndex;
+
+ m_listViewClique->clear();
+ FindDuplicates::DuplicateClique clique = m_duplicateCliqueList[cliqueIndex];
+
+ for ( FindDuplicates::DuplicateClique::Iterator it = clique.begin(); it != clique.end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ {
+ MergeElementsCliqueItem *item = new MergeElementsCliqueItem( entry, NULL, NULL, m_listViewClique );
+ connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
+ }
+ else
+ {
+ BibTeX::Macro *macro = dynamic_cast<BibTeX::Macro*>( *it );
+ if ( macro != NULL )
+ {
+ MergeElementsCliqueItem *item = new MergeElementsCliqueItem( NULL, macro, NULL, m_listViewClique );
+ connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
+ }
+ else
+ {
+ BibTeX::Preamble *preamble = dynamic_cast<BibTeX::Preamble*>( *it );
+ if ( preamble!=NULL )
+ {
+ MergeElementsCliqueItem *item = new MergeElementsCliqueItem( NULL, NULL, preamble, m_listViewClique );
+ connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
+ }
+ }
+ }
+ }
+ restoreCurrentMergeSet();
+
+ enableButton( User1, ( cliqueIndex < ( int )( m_duplicateCliqueList.size() ) - 1 ) && m_duplicateCliqueList.size() > 1 );
+ enableButton( User2, cliqueIndex > 0 && m_duplicateCliqueList.size() > 1 );
+ m_progressBar->setProgress( cliqueIndex, m_duplicateCliqueList.size() - 1 );
+ }
+
+ void MergeElements::saveCurrentMergeSet()
+ {
+ if ( m_mergeSetList[m_currentCliqueIndex] == NULL )
+ m_mergeSetList[m_currentCliqueIndex] = new MergeSet;
+ else
+ {
+ m_mergeSetList[m_currentCliqueIndex]->entries.clear();
+ m_mergeSetList[m_currentCliqueIndex]->fields.clear();
+ }
+ m_mergeSetList[m_currentCliqueIndex]->type = BibTeX::Entry::etUnknown;
+ m_mergeSetList[m_currentCliqueIndex]->typeString = QString::null;
+ m_mergeSetList[m_currentCliqueIndex]->id = QString::null;
+ m_mergeSetList[m_currentCliqueIndex]->macroKey = QString::null;
+ m_mergeSetList[m_currentCliqueIndex]->macroValue = NULL;
+ m_mergeSetList[m_currentCliqueIndex]->preambleText=QString::null;
+
+ for ( QListViewItemIterator it( m_listViewClique, QListViewItemIterator::Checked ); it.current(); ++it )
+ {
+ MergeElementsCliqueItem *eci = dynamic_cast<MergeElementsCliqueItem*>( *it );
+ BibTeX::Entry *entry = eci->entry;
+ if ( entry != NULL )
+ m_mergeSetList[m_currentCliqueIndex]->entries.append( entry );
+ BibTeX::Macro *macro = eci->macro;
+ if ( macro != NULL )
+ m_mergeSetList[m_currentCliqueIndex]->macros.append( macro );
+ BibTeX::Preamble *preamble = eci->preamble;
+ if ( preamble !=NULL )
+ m_mergeSetList[m_currentCliqueIndex]->preambles.append( preamble );
+ }
+
+ for ( QListViewItemIterator it( m_listViewAlternatives, QListViewItemIterator::Checked ); it.current(); ++it )
+ {
+ MergeEntriesAlternativesItem *item = dynamic_cast<MergeEntriesAlternativesItem*>( *it );
+ if ( item != NULL )
+ {
+ BibTeX::EntryField *field = item->field;
+ m_mergeSetList[m_currentCliqueIndex]->fields.append( field );
+ }
+ else
+ {
+ MergeElementsAlternativesId *item = dynamic_cast<MergeElementsAlternativesId*>( *it );
+ if ( item != NULL )
+ m_mergeSetList[m_currentCliqueIndex]->id = item->id;
+ else
+ {
+ MergeEntriesAlternativesEntryType *itemT = dynamic_cast<MergeEntriesAlternativesEntryType*>( *it );
+ if ( itemT != NULL )
+ {
+ m_mergeSetList[m_currentCliqueIndex]->typeString = itemT->typeString;
+ m_mergeSetList[m_currentCliqueIndex]->type = itemT->type;
+ }
+ else
+ {
+ MergeMacroAlternativesKey *itemK = dynamic_cast<MergeMacroAlternativesKey*>( *it );
+ if ( itemK != NULL )
+ m_mergeSetList[m_currentCliqueIndex]->macroKey = itemK->key;
+ else
+ {
+ MergeMacrosAlternativesItem *itemMA = dynamic_cast<MergeMacrosAlternativesItem*>( *it );
+ if ( itemMA != NULL )
+ m_mergeSetList[m_currentCliqueIndex]->macroValue = itemMA->value;
+ else
+ {
+ MergePreambleAlternatives *itemP=dynamic_cast<MergePreambleAlternatives*>( *it );
+ if ( itemP!=NULL )
+ m_mergeSetList[m_currentCliqueIndex]->preambleText=itemP->text;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void MergeElements::restoreCurrentMergeSet()
+ {
+ if ( m_mergeSetList[m_currentCliqueIndex] == NULL )
+ {
+ m_listViewAlternatives->clear();
+ return;
+ }
+
+ for ( QListViewItemIterator it( m_listViewClique ); it.current(); ++it )
+ {
+ MergeElementsCliqueItem *item = dynamic_cast<MergeElementsCliqueItem*>( *it );
+ BibTeX::Entry *entry = item->entry;
+ BibTeX::Macro *macro = item->macro;
+ BibTeX::Preamble *preamble = item->preamble;
+ if ( entry != NULL )
+ for ( QValueList<BibTeX::Entry*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->entries.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->entries.end(); ++it2 )
+ {
+ if ( entry->id() == ( *it2 )->id() )
+ {
+ item->setOn( true );
+ break;
+ }
+ }
+ else if ( macro != NULL )
+ {
+ for ( QValueList<BibTeX::Macro*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->macros.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->macros.end(); ++it2 )
+ if ( macro->key() == ( *it2 )->key() )
+ {
+ item->setOn( true );
+ break;
+ }
+ }
+ else if ( preamble!=NULL )
+ for ( QValueList<BibTeX::Preamble*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->preambles.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->preambles.end(); ++it2 )
+ if ( preamble->value()->text() == ( *it2 )->value()->text() )
+ {
+ item->setOn( true );
+ break;
+ }
+ }
+
+ slotRefreshAlternatives();
+
+ for ( QListViewItemIterator it( m_listViewAlternatives ); it.current(); ++it )
+ {
+ MergeEntriesAlternativesItem *item = dynamic_cast<MergeEntriesAlternativesItem*>( *it );
+ if ( item != NULL )
+ {
+ for ( QValueList<BibTeX::EntryField*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->fields.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->fields.end(); ++it2 )
+ if ( item->field->fieldTypeName().lower() == ( *it2 )->fieldTypeName().lower() && item->field->value()->text() == ( *it2 )->value()->text() )
+ {
+ item->setOn( true );
+ break;
+ }
+ }
+ else
+ {
+ MergeElementsAlternativesId *item = dynamic_cast<MergeElementsAlternativesId*>( *it );
+ if ( item != NULL )
+ {
+ if ( item->id == m_mergeSetList[m_currentCliqueIndex]->id )
+ item->setOn( true );
+ }
+ else
+ {
+ MergeEntriesAlternativesEntryType *item = dynamic_cast<MergeEntriesAlternativesEntryType*>( *it );
+ if ( item != NULL )
+ {
+ if (( item->type != BibTeX::Entry::etUnknown && item->type == m_mergeSetList[m_currentCliqueIndex]->type ) || ( item->typeString.lower() == m_mergeSetList[m_currentCliqueIndex]->typeString.lower() ) )
+ item->setOn( true );
+ }
+ else
+ {
+ MergeMacrosAlternativesItem *mai = dynamic_cast<MergeMacrosAlternativesItem*>( *it );
+ if ( mai != NULL )
+ {
+ if ( mai->value == m_mergeSetList[m_currentCliqueIndex]->macroValue )
+ mai->setOn( true );
+ }
+ else
+ {
+ MergeMacroAlternativesKey *mak = dynamic_cast<MergeMacroAlternativesKey*>( *it );
+ if ( mak != NULL )
+ {
+ if ( mak->key == m_mergeSetList[m_currentCliqueIndex]->macroKey )
+ mak->setOn( true );
+ }
+ else
+ {
+ MergePreambleAlternatives *mpa =dynamic_cast<MergePreambleAlternatives*>( *it );
+ if ( mpa!=NULL )
+ {
+ if ( mpa->text==m_mergeSetList[m_currentCliqueIndex]->preambleText )
+ mpa->setOn( true );
+ }
+ else
+ qDebug( "Item is of unknown type" );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void MergeElements::applyMergeSet( BibTeX::File *bibTeXFile, BibTeX::File *otherBibTeXFile )
+ {
+ int n = m_duplicateCliqueList.size();
+ for ( int i = 0; i < n; ++i )
+ {
+ if ( m_mergeSetList[i] == NULL ) continue;
+
+ if ( !m_mergeSetList[i]->entries.isEmpty() )
+ {
+ QString id = m_mergeSetList[i]->id == QString::null ? ( *m_mergeSetList[i]->entries.begin() )->id() : m_mergeSetList[i]->id;
+
+ BibTeX::Entry *newEntry = NULL;
+ if ( m_mergeSetList[i]->type == BibTeX::Entry::etUnknown )
+ {
+ if ( m_mergeSetList[i]->typeString == QString::null )
+ {
+ BibTeX::Entry *firstEntry = *m_mergeSetList[i]->entries.begin();
+ if ( firstEntry->entryType() == BibTeX::Entry::etUnknown )
+ newEntry = new BibTeX::Entry( firstEntry->entryTypeString(), id );
+ else
+ newEntry = new BibTeX::Entry( firstEntry->entryType(), id );
+ }
+ else
+ newEntry = new BibTeX::Entry( m_mergeSetList[i]->typeString, id );
+ }
+ else
+ newEntry = new BibTeX::Entry( m_mergeSetList[i]->type, id );
+
+ for ( QValueList<BibTeX::EntryField*>::Iterator it = m_mergeSetList[i]->fields.begin(); it != m_mergeSetList[i]->fields.end(); ++it )
+ {
+ newEntry->addField( new BibTeX::EntryField( *it ) );
+ }
+
+ for ( QValueList<BibTeX::Entry*>::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it )
+ for ( QValueList<BibTeX::EntryField*>::ConstIterator fIt = ( *it )->begin(); fIt != ( *it )->end(); ++fIt )
+ if ( newEntry->getField(( *fIt )->fieldTypeName() ) == NULL )
+ {
+ newEntry->addField( new BibTeX::EntryField( *fIt ) );
+ }
+
+ for ( QValueList<BibTeX::Entry*>::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( bibTeXFile->containsKey(( *it )->id() ) );
+ if ( entry != NULL )
+ bibTeXFile->deleteElement( entry );
+ else
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( otherBibTeXFile->containsKey(( *it )->id() ) );
+ if ( entry != NULL )
+ otherBibTeXFile->deleteElement( entry );
+ }
+ }
+ bibTeXFile->appendElement( newEntry );
+ }
+ else if ( !m_mergeSetList[i]->macros.isEmpty() )
+ {
+ BibTeX::Macro *newMacro = new BibTeX::Macro( m_mergeSetList[i]->macroKey );
+ newMacro->setValue( m_mergeSetList[i]->macroValue );
+
+ for ( QValueList<BibTeX::Macro*>::Iterator it = m_mergeSetList[i]->macros.begin(); it != m_mergeSetList[i]->macros.end(); ++it )
+ {
+ bibTeXFile->deleteElement( *it );
+ if ( otherBibTeXFile != NULL )
+ otherBibTeXFile->deleteElement( *it );
+ }
+
+ bibTeXFile->appendElement( newMacro );
+ }
+ else if ( !m_mergeSetList[i]->preambles.isEmpty() )
+ {
+ BibTeX::Preamble *newPreamble = new BibTeX::Preamble( m_mergeSetList[i]->preambleText );
+
+ for ( QValueList<BibTeX::Preamble*>::Iterator it = m_mergeSetList[i]->preambles.begin(); it != m_mergeSetList[i]->preambles.end(); ++it )
+ {
+ bibTeXFile->deleteElement( *it );
+ if ( otherBibTeXFile != NULL )
+ otherBibTeXFile->deleteElement( *it );
+ }
+
+ bibTeXFile->appendElement( newPreamble );
+ }
+ }
+ }
+
+ int MergeElements::mergeDuplicates( BibTeX::File *bibTeXFile )
+ {
+ setCaption( i18n( "Find Duplicates" ) );
+ Settings * settings = Settings::self( NULL );
+ int sensitivity = ( int )( FindDuplicates::maxDistance / exp( log( 10 ) * settings->editing_findDuplicatesSensitivity / 10.0 ) );
+ qDebug( "sensitivity= %i / %i", sensitivity, FindDuplicates::maxDistance );
+ FindDuplicates findDuplicates( m_duplicateCliqueList, sensitivity, bibTeXFile, parentWidget( true ) );
+
+ if ( m_duplicateCliqueList.isEmpty() )
+ {
+ KMessageBox::information( parentWidget( true ), i18n( "No duplicates found." ), i18n( "Find Duplicates" ) );
+ return QDialog::Rejected;
+ }
+
+ m_mergeSetList = new MergeSet*[m_duplicateCliqueList.size()];
+ memset( m_mergeSetList, 0, sizeof( MergeSet* )*m_duplicateCliqueList.size() );
+
+ qDebug( "%i cliques", m_duplicateCliqueList.size() );
+ setClique( 0 );
+
+ int result = exec();
+ if ( result == QDialog::Accepted )
+ applyMergeSet( bibTeXFile );
+
+ delete[] m_mergeSetList;
+
+ return result;
+ }
+
+ void MergeElements::slotRefreshAlternatives()
+ {
+ QMap<BibTeX::EntryField::FieldType, MergeEntriesAlternativesController*> mapFieldToController;
+ QMap<BibTeX::EntryField::FieldType, First> firstEntryData;
+ bool first = true;
+ MergePreambleAlternativesController* preambleController = NULL;
+ MergeMacrosAlternativesController* macroKeyController = NULL;
+ MergeMacrosAlternativesController* macroValueController = NULL;
+ MergeEntriesAlternativesController *idController = NULL;
+ MergeEntriesAlternativesController *typeController = NULL;
+ QString firstId = QString::null;
+ QString firstMacroKey = QString::null;
+ BibTeX::Value *firstMacroValue = NULL;
+ QString firstPreambleText = QString::null;
+ BibTeX::Entry::EntryType firstType = BibTeX::Entry::etUnknown;
+ QString firstTypeString = QString::null;
+
+ m_listViewAlternatives->clear();
+
+ for ( QListViewItemIterator it( m_listViewClique, QListViewItemIterator::Checked ); it.current(); ++it )
+ {
+ MergeElementsCliqueItem *meci = dynamic_cast<MergeElementsCliqueItem*>( *it );
+ BibTeX::Entry *entry = NULL;
+ BibTeX::Macro *macro = NULL;
+ BibTeX::Preamble *preamble = NULL;
+ if ( meci != NULL && ( entry = meci->entry ) != NULL )
+ {
+ if ( first )
+ {
+ firstId = entry->id();
+ firstType = entry->entryType();
+ firstTypeString = entry->entryTypeString();
+ for ( BibTeX::Entry::EntryFields::const_iterator efi = entry->begin(); efi != entry->end(); ++efi )
+ {
+ First first;
+ first.entry = entry;
+ first.field = *efi;
+ firstEntryData.insert(( *efi )->fieldType(), first );
+ }
+ }
+ else
+ {
+ if ( idController == NULL )
+ {
+ if ( entry->id() != firstId )
+ {
+ idController = new MergeEntriesAlternativesController( i18n( "Id" ), m_listViewAlternatives );
+ idController->setOpen( true );
+ MergeElementsAlternativesId *item = new MergeElementsAlternativesId( firstId, idController );
+ item->setOn( true );
+ new MergeElementsAlternativesId( entry->id(), idController );
+ }
+ }
+ else
+ {
+ QString thisText = entry->id();
+ bool isNew = true;
+ for ( QListViewItem *cur = idController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
+ {
+ MergeElementsAlternativesId *meai = dynamic_cast<MergeElementsAlternativesId*>( cur );
+ isNew = meai->id != thisText;
+ }
+ if ( isNew )
+ new MergeElementsAlternativesId( thisText, idController );
+ }
+
+ if ( typeController == NULL )
+ {
+ if (( firstType != BibTeX::Entry::etUnknown && entry->entryType() != firstType ) || ( entry->entryTypeString().lower() != entry->entryTypeString().lower() ) )
+ {
+ typeController = new MergeEntriesAlternativesController( i18n( "Type" ), m_listViewAlternatives );
+ typeController->setOpen( true );
+ MergeEntriesAlternativesEntryType *item = firstType != BibTeX::Entry::etUnknown ? new MergeEntriesAlternativesEntryType( firstType, typeController ) : new MergeEntriesAlternativesEntryType( firstTypeString, typeController );
+ item->setOn( true );
+ if ( entry->entryType() != BibTeX::Entry::etUnknown )
+ new MergeEntriesAlternativesEntryType( entry->entryType(), typeController );
+ else
+ new MergeEntriesAlternativesEntryType( entry->entryTypeString(), typeController );
+ }
+ }
+ else
+ {
+ QString typeString = entry->entryTypeString();
+ BibTeX::Entry::EntryType type = entry->entryType();
+ bool isNew = true;
+ for ( QListViewItem *cur = typeController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
+ {
+ MergeEntriesAlternativesEntryType *meat = dynamic_cast<MergeEntriesAlternativesEntryType*>( cur );
+ isNew = type == BibTeX::Entry::etUnknown && meat->typeString != typeString || meat->type != type;
+ }
+ if ( isNew )
+ {
+ if ( type != BibTeX::Entry::etUnknown )
+ new MergeEntriesAlternativesEntryType( type, typeController );
+ else
+ new MergeEntriesAlternativesEntryType( typeString, typeController );
+ }
+ }
+
+ for ( BibTeX::Entry::EntryFields::const_iterator efi = entry->begin(); efi != entry->end(); ++efi )
+ if ( mapFieldToController.contains(( *efi )->fieldType() ) )
+ {
+ MergeEntriesAlternativesController *controller = mapFieldToController[( *efi )->fieldType()];
+ QString thisText = ( *efi )->value()->text();
+ bool isNew = true;
+ for ( QListViewItem *cur = controller->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
+ {
+ MergeEntriesAlternativesItem *meai = dynamic_cast<MergeEntriesAlternativesItem*>( cur );
+ isNew = meai->field->value()->text() != thisText;
+ }
+ if ( isNew )
+ new MergeEntriesAlternativesItem( *efi, controller );
+ }
+ else if ( firstEntryData.contains(( *efi )->fieldType() ) )
+ {
+ QString firstText = firstEntryData[( *efi )->fieldType()].field->value()->text();
+ QString thisText = ( *efi )->value()->text();
+ if ( firstText != thisText )
+ {
+ MergeEntriesAlternativesController *controller = new MergeEntriesAlternativesController(( *efi )->fieldType(), m_listViewAlternatives );
+ controller->setOpen( true );
+ MergeEntriesAlternativesItem *item = new MergeEntriesAlternativesItem( firstEntryData[( *efi )->fieldType()].field, controller );
+ item->setOn( true );
+ item = new MergeEntriesAlternativesItem( *efi, controller );
+ mapFieldToController.insert(( *efi )->fieldType(), controller );
+ }
+ }
+ else
+ {
+ First first;
+ first.entry = entry;
+ first.field = *efi;
+ firstEntryData.insert(( *efi )->fieldType(), first );
+ }
+ }
+ }
+ else if ( meci != NULL && ( macro = meci->macro ) != NULL )
+ {
+ if ( first )
+ {
+ firstMacroKey = macro->key();
+ firstMacroValue = macro->value();
+ }
+ else
+ {
+ if ( macroKeyController == NULL )
+ {
+ if ( macro->key() != firstMacroKey )
+ {
+ macroKeyController = new MergeMacrosAlternativesController( true, m_listViewAlternatives );
+ macroKeyController->setOpen( true );
+ MergeMacroAlternativesKey *item = new MergeMacroAlternativesKey( firstMacroKey, macroKeyController );
+ item->setOn( true );
+ new MergeMacroAlternativesKey( macro->key(), macroKeyController );
+ }
+ }
+ else
+ {
+ QString thisText = macro->key();
+ bool isNew = true;
+ for ( QListViewItem *cur = macroKeyController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
+ {
+ MergeMacroAlternativesKey *mak = dynamic_cast<MergeMacroAlternativesKey*>( cur );
+ isNew = mak->key != thisText;
+ }
+ if ( isNew )
+ new MergeMacroAlternativesKey( thisText, macroKeyController );
+ }
+ }
+
+ if ( macroValueController == NULL )
+ {
+ if ( firstMacroValue->text() != macro->value()->text() )
+ {
+ macroValueController = new MergeMacrosAlternativesController( false, m_listViewAlternatives );
+ macroValueController->setOpen( true );
+ MergeMacrosAlternativesItem *item = new MergeMacrosAlternativesItem( firstMacroValue, macroValueController );
+ item->setOn( true );
+ new MergeMacrosAlternativesItem( macro->value(), macroValueController );
+ }
+ }
+ else
+ {
+ QString macroString = macro->value()->text();
+ bool isNew = true;
+ for ( QListViewItem *cur = macroValueController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
+ {
+ MergeMacrosAlternativesItem *mai = dynamic_cast<MergeMacrosAlternativesItem*>( cur );
+ isNew = macroString != mai->value->text();
+ }
+ if ( isNew )
+ new MergeMacrosAlternativesItem( macro->value(), macroValueController );
+ }
+ }
+ else if ( meci != NULL && ( preamble = meci->preamble ) != NULL )
+ {
+ if ( first )
+ firstPreambleText = preamble->value()->text();
+ else
+ {
+ if ( preambleController == NULL )
+ {
+ if ( preamble->value()->text() != firstPreambleText )
+ {
+ preambleController = new MergePreambleAlternativesController( m_listViewAlternatives );
+ preambleController->setOpen( true );
+ MergePreambleAlternatives *item = new MergePreambleAlternatives( firstPreambleText, preambleController );
+ item->setOn( true );
+ new MergePreambleAlternatives( preamble->value()->text(), preambleController );
+ }
+ }
+ else
+ {
+ QString thisText = preamble->value()->text();
+ bool isNew = true;
+ for ( QListViewItem *cur = preambleController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
+ {
+ MergePreambleAlternatives *mpa = dynamic_cast<MergePreambleAlternatives*>( cur );
+ isNew = mpa->text != thisText;
+ }
+ if ( isNew )
+ new MergePreambleAlternatives( thisText, preambleController );
+ }
+ }
+ }
+ first = false;
+ }
+ }
+
+ void MergeElements::slotNextClique()
+ {
+ if ( m_currentCliqueIndex < ( int )( m_duplicateCliqueList.size() ) - 1 )
+ {
+ setClique( m_currentCliqueIndex + 1 );
+ }
+ else
+ enableButton( User1, false );
+ }
+
+ void MergeElements::slotPreviousClique()
+ {
+ if ( m_currentCliqueIndex > 0 )
+ {
+ setClique( m_currentCliqueIndex - 1 );
+ }
+ else
+ enableButton( User2, false );
+ }
+
+ void MergeElements::slotPreviewElement( QListViewItem *item )
+ {
+ MergeElementsCliqueItem *meci = dynamic_cast<MergeElementsCliqueItem*>( item );
+ if ( meci != NULL && meci->entry != NULL )
+ KBibTeX::EntryWidget::execute( meci->entry, NULL, TRUE, FALSE, this );
+ else if ( meci != NULL && meci->macro != NULL )
+ KBibTeX::MacroWidget::execute( meci->macro, TRUE, this );
+ else if ( meci!=NULL&& meci->preamble!=NULL )
+ KBibTeX::PreambleWidget::execute( meci->preamble, TRUE, this );
+ }
+
+ /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
+ void MergeElements::saveWindowSize( KConfig *config ) const
+ {
+ int scnum = QApplication::desktop()->screenNumber( parentWidget() );
+ QRect desk = QApplication::desktop()->screenGeometry( scnum );
+ int w, h;
+#if defined Q_WS_X11
+ // save maximalization as desktop size + 1 in that direction
+ KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
+ w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
+ h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
+#else
+ if ( isMaximized() )
+ {
+ w = desk.width() + 1;
+ h = desk.height() + 1;
+ }
+ //TODO: add "Maximized" property instead "+1" hack
+#endif
+ QRect size( desk.width(), w, desk.height(), h );
+ bool defaultSize = false;//( size == d->defaultWindowSize );
+ QString widthString = QString::fromLatin1( "Width %1" ).arg( desk.width() );
+ QString heightString = QString::fromLatin1( "Height %1" ).arg( desk.height() );
+ if ( !config->hasDefault( widthString ) && defaultSize )
+ config->revertToDefault( widthString );
+ else
+ config->writeEntry( widthString, w );
+
+ if ( !config->hasDefault( heightString ) && defaultSize )
+ config->revertToDefault( heightString );
+ else
+ config->writeEntry( heightString, h );
+ }
+
+ void MergeElements::showEvent( QShowEvent * )
+ {
+ qDebug( "showEvent" );
+ QTimer::singleShot( 10, this, SLOT( slotRestore() ) );
+ }
+
+ void MergeElements::slotRestore()
+ {
+ qDebug( "slotRestore" );
+ KConfig * config = kapp->config();
+ config->setGroup( "MergeElements" );
+ restoreWindowSize( config );
+ }
+
+ /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
+ void MergeElements::restoreWindowSize( KConfig *config )
+ {
+ // restore the size
+ int scnum = QApplication::desktop()->screenNumber( parentWidget() );
+ QRect desk = QApplication::desktop()->screenGeometry( scnum );
+ QSize size( config->readNumEntry( QString::fromLatin1( "Width %1" ).arg( desk.width() ), 0 ),
+ config->readNumEntry( QString::fromLatin1( "Height %1" ).arg( desk.height() ), 0 ) );
+ if ( size.isEmpty() )
+ {
+ // try the KDE 2.0 way
+ size = QSize( config->readNumEntry( QString::fromLatin1( "Width" ), 0 ),
+ config->readNumEntry( QString::fromLatin1( "Height" ), 0 ) );
+ if ( !size.isEmpty() )
+ {
+ // make sure the other resolutions don't get old settings
+ config->writeEntry( QString::fromLatin1( "Width" ), 0 );
+ config->writeEntry( QString::fromLatin1( "Height" ), 0 );
+ }
+ }
+ if ( !size.isEmpty() )
+ {
+#ifdef Q_WS_X11
+ int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
+ | ( size.height() > desk.height() ? NET::MaxVert : 0 );
+ if (( state & NET::Max ) == NET::Max )
+ ; // no resize
+ else if (( state & NET::MaxHoriz ) == NET::MaxHoriz )
+ resize( width(), size.height() );
+ else if (( state & NET::MaxVert ) == NET::MaxVert )
+ resize( size.width(), height() );
+ else
+ resize( size );
+ // QWidget::showMaximized() is both insufficient and broken
+ KWin::setState( winId(), state );
+#else
+ if ( size.width() > desk.width() || size.height() > desk.height() )
+ setWindowState( WindowMaximized );
+ else
+ resize( size );
+#endif
+ }
+ }
+
+}
+#include "mergeelements.moc"
diff --git a/src/mergeelements.h b/src/mergeelements.h
new file mode 100644
index 0000000..88c011e
--- /dev/null
+++ b/src/mergeelements.h
@@ -0,0 +1,179 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXMERGEELEMENTS_H
+#define KBIBTEXMERGEELEMENTS_H
+
+#include <kdialogbase.h>
+
+#include <findduplicates.h>
+#include <file.h>
+#include <entry.h>
+
+class KPushButton;
+class KTextEdit;
+class KListView;
+class QProgressBar;
+
+namespace KBibTeX
+{
+ class MergeElementsCliqueItem : public QObject, public QCheckListItem
+ {
+ Q_OBJECT
+ public:
+ MergeElementsCliqueItem( BibTeX::Entry* entry, BibTeX::Macro* macro, BibTeX::Preamble* preamble, QListView *parent );
+ BibTeX::Entry* entry;
+ BibTeX::Macro* macro;
+ BibTeX::Preamble* preamble;
+
+ protected:
+ void stateChange( bool );
+
+ signals:
+ void stateChanged( MergeElementsCliqueItem* );
+ };
+
+ class MergeEntriesAlternativesController: public QCheckListItem
+ {
+ public:
+ MergeEntriesAlternativesController( const QString &label, QListView *parent );
+ MergeEntriesAlternativesController( BibTeX::EntryField::FieldType fieldType, QListView *parent );
+ BibTeX::EntryField::FieldType fieldType;
+ const QString fieldName;
+ };
+
+ class MergeMacrosAlternativesController: public QCheckListItem
+ {
+ public:
+ MergeMacrosAlternativesController( bool isKey, QListView *parent );
+ };
+
+
+ class MergeEntriesAlternativesItem: public QCheckListItem
+ {
+ public:
+ MergeEntriesAlternativesItem( BibTeX::EntryField *field, MergeEntriesAlternativesController *parent );
+ BibTeX::EntryField *field;
+ };
+
+ class MergeMacrosAlternativesItem: public QCheckListItem
+ {
+ public:
+ MergeMacrosAlternativesItem( BibTeX::Value *value, MergeMacrosAlternativesController *parent );
+ BibTeX::Value *value;
+ };
+
+ class MergeElementsAlternativesId: public QCheckListItem
+ {
+ public:
+ MergeElementsAlternativesId( const QString &id, MergeEntriesAlternativesController *parent );
+ QString id;
+ };
+
+ class MergeMacroAlternativesKey: public QCheckListItem
+ {
+ public:
+ MergeMacroAlternativesKey( const QString &key, MergeMacrosAlternativesController *parent );
+ QString key;
+ };
+
+
+ class MergeEntriesAlternativesEntryType: public QCheckListItem
+ {
+ public:
+ MergeEntriesAlternativesEntryType( const QString &typeString, MergeEntriesAlternativesController *parent );
+ MergeEntriesAlternativesEntryType( BibTeX::Entry::EntryType type, MergeEntriesAlternativesController *parent );
+ QString typeString;
+ BibTeX::Entry::EntryType type;
+ };
+
+ class MergePreambleAlternativesController: public QCheckListItem
+ {
+ public:
+ MergePreambleAlternativesController( QListView *parent );
+ };
+
+ class MergePreambleAlternatives: public QCheckListItem
+ {
+ public:
+ MergePreambleAlternatives( const QString &text, MergePreambleAlternativesController *parent );
+ QString text;
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class MergeElements : public KDialogBase
+ {
+ Q_OBJECT
+ public:
+ MergeElements( QWidget *parent );
+ ~MergeElements();
+ int mergeDuplicates( BibTeX::File *bibTeXFile );
+
+ protected:
+ void showEvent( QShowEvent * );
+
+ protected slots:
+ void slotRefreshAlternatives();
+ void slotNextClique();
+ void slotPreviousClique();
+ void slotPreviewElement( QListViewItem *item );
+ void saveCurrentMergeSet();
+ void slotRestore();
+
+ private:
+ typedef struct
+ {
+ BibTeX::Macro *macro;
+ BibTeX::Entry *entry;
+ BibTeX::EntryField *field;
+ } First;
+
+ typedef struct
+ {
+ QValueList<BibTeX::Macro*> macros;
+ QValueList<BibTeX::Entry*> entries;
+ QValueList<BibTeX::EntryField*> fields;
+ QValueList<BibTeX::Preamble*> preambles;
+ QString macroKey;
+ BibTeX::Value *macroValue;
+ QString id, typeString;
+ BibTeX::Entry::EntryType type;
+ QString preambleText;
+ } MergeSet;
+
+ KListView *m_listViewClique;
+ KListView *m_listViewAlternatives;
+ QProgressBar *m_progressBar;
+ FindDuplicates::DuplicateCliqueList m_duplicateCliqueList;
+ MergeSet **m_mergeSetList;
+ int m_currentCliqueIndex;
+
+ void setupGUI();
+ void setClique( int cliqueIndex );
+ void restoreCurrentMergeSet();
+ void applyMergeSet( BibTeX::File *bibTeXFile, BibTeX::File *otherBibTeXFile = NULL );
+ void restoreWindowSize( KConfig *config );
+ void saveWindowSize( KConfig *config ) const;
+ };
+
+}
+
+#endif // KBIBTEXMERGEELEMENTS_H
diff --git a/src/messagehandler.cpp b/src/messagehandler.cpp
new file mode 100644
index 0000000..273a5eb
--- /dev/null
+++ b/src/messagehandler.cpp
@@ -0,0 +1,44 @@
+/***************************************************************************
+ copyright : (C) 2005-2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "messagehandler.h"
+
+#include <kmessagebox.h>
+
+namespace KBibTeX {
+
+// all messages go to manager
+void ManagerMessage::send(const QString& message_, Type type_) {
+// Fetch::Manager::self()->updateStatus(message_);
+ // plus errors get a message box
+ if(type_ == Error) {
+ KMessageBox::sorry(NULL, message_); // FIXME: some widget instead of NULL
+ } else if(type_ == Warning) {
+ KMessageBox::information(NULL, message_); // FIXME: some widget instead of NULL
+ }
+}
+
+void ManagerMessage::infoList(const QString& message_, const QStringList& list_) {
+ KMessageBox::informationList(NULL, message_, list_); // FIXME: some widget instead of NULL
+}
+
+}
diff --git a/src/messagehandler.h b/src/messagehandler.h
new file mode 100644
index 0000000..00fcbe9
--- /dev/null
+++ b/src/messagehandler.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ copyright : (C) 2005-2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef KBIBTEX_MESSAGEHANDLER_H
+#define KBIBTEX_MESSAGEHANDLER_H
+
+class QString;
+class QStringList;
+
+namespace KBibTeX {
+
+/**
+ * @author Robby Stephenson
+ */
+class MessageHandler {
+public:
+ enum Type { Status, Warning, Error, ListError };
+
+ MessageHandler() {}
+ virtual ~MessageHandler() {}
+
+ virtual void send(const QString& message, Type type) = 0;
+ virtual void infoList(const QString& message, const QStringList& list) = 0;
+};
+
+class ManagerMessage : public MessageHandler {
+public:
+ ManagerMessage() : MessageHandler() {}
+ virtual ~ManagerMessage() {}
+
+ virtual void send(const QString& message, Type type);
+ virtual void infoList(const QString& message, const QStringList& list);
+};
+
+} // end namespace
+
+#endif
diff --git a/src/preamble.cpp b/src/preamble.cpp
new file mode 100644
index 0000000..1b03a0f
--- /dev/null
+++ b/src/preamble.cpp
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include "preamble.h"
+
+namespace BibTeX
+{
+
+ Preamble::Preamble() : Element(), m_value( new Value() )
+ {
+// TODO
+ }
+
+ Preamble::Preamble( const QString& text ) : Element()
+ {
+ m_value = new Value( text, false );
+ }
+
+ Preamble::Preamble( Preamble *other ): Element(), m_value( NULL )
+ {
+ copyFrom( other );
+ }
+
+ Preamble::~Preamble()
+ {
+ delete m_value;
+ }
+
+ Value *Preamble::value() const
+ {
+ return m_value;
+ }
+
+ void Preamble::setValue( Value *value )
+ {
+ if ( value != m_value )
+ {
+ delete m_value;
+
+ if ( value != NULL )
+ m_value = new Value( value );
+ else
+ m_value = NULL;
+ }
+ }
+
+ bool Preamble::containsPattern( const QString& pattern, EntryField::FieldType fieldType, FilterType filterType, bool caseSensitive ) const
+ {
+ QString text = m_value->simplifiedText();
+
+ if ( filterType == ftExact )
+ {
+ /** check for exact match */
+ return fieldType == EntryField::ftUnknown && text.contains( pattern, caseSensitive );
+ }
+ else
+ {
+ /** for each word in the search pattern ... */
+ QStringList words = QStringList::split( QRegExp( "\\s+" ), pattern );
+ unsigned int hits = 0;
+ for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it )
+ {
+ /** check if word is contained in text */
+ if ( fieldType == EntryField::ftUnknown && text.contains( *it, caseSensitive ) )
+ ++hits;
+ }
+
+ /** return success depending on filter type and number of hits */
+ return (( filterType == ftAnyWord && hits > 0 ) || ( filterType == ftEveryWord && hits == words.count() ) );
+ }
+ }
+
+ Element* Preamble::clone()
+ {
+ return new Preamble( this );
+ }
+
+ void Preamble::copyFrom( Preamble *other )
+ {
+ if ( m_value != NULL ) delete m_value;
+ m_value = new Value( other->m_value );
+ }
+
+ QString Preamble::text() const
+ {
+ return "Preamble: " + m_value->text();
+ }
+}
diff --git a/src/preamble.h b/src/preamble.h
new file mode 100644
index 0000000..fc6da9d
--- /dev/null
+++ b/src/preamble.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef BIBTEXPREAMBLE_H
+#define BIBTEXPREAMBLE_H
+
+#include <element.h>
+
+namespace BibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class Preamble : public Element
+ {
+ public:
+ Preamble( );
+ Preamble( const QString& text );
+ Preamble( Preamble *other );
+ virtual ~Preamble();
+
+ Value *value() const;
+ void setValue( Value *value );
+
+ bool containsPattern( const QString& pattern, EntryField::FieldType fieldType = EntryField::ftUnknown, FilterType filterType = BibTeX::Element::ftExact, bool caseSensitive = FALSE ) const;
+
+ Element* clone();
+ void copyFrom( Preamble *other );
+ QString text() const;
+
+ private:
+ Value *m_value;
+ };
+
+}
+
+#endif // BIBTEXPREAMBLE_H
diff --git a/src/preamblewidget.cpp b/src/preamblewidget.cpp
new file mode 100644
index 0000000..a1cc0c1
--- /dev/null
+++ b/src/preamblewidget.cpp
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kdialogbase.h>
+#include <klocale.h>
+
+#include "preamblewidget.h"
+
+namespace KBibTeX
+{
+
+ QDialog::DialogCode PreambleWidget::execute( BibTeX::Preamble *preamble, bool isReadOnly, QWidget *parent, const char *name )
+ {
+ KDialogBase * dlg = new KDialogBase( parent, name, TRUE, i18n( "Edit BibTeX Preamble" ), KDialogBase::Ok | KDialogBase::Cancel );
+ PreambleWidget* preambleWidget = new PreambleWidget( preamble, isReadOnly, dlg, "PreambleWidget" );
+
+ dlg->setMainWidget( preambleWidget );
+ connect( dlg, SIGNAL( okClicked() ), preambleWidget, SLOT( apply() ) );
+
+ QDialog::DialogCode result = ( QDialog::DialogCode ) dlg->exec();
+
+ delete( preambleWidget );
+ delete( dlg );
+
+ return result;
+ }
+
+ PreambleWidget::PreambleWidget( BibTeX::Preamble *bibtexpreamble, bool isReadOnly, QWidget *parent, const char *name ) : QWidget( parent, name ), m_isReadOnly( isReadOnly ), m_bibtexpreamble( bibtexpreamble )
+ {
+ setupGUI();
+ reset();
+ }
+
+
+ PreambleWidget::~PreambleWidget()
+ {
+// nothing
+ }
+
+ void PreambleWidget::apply()
+ {
+ BibTeX::Value *value = m_fieldLineEditPreambleValue->value();
+ m_bibtexpreamble->setValue( value );
+ }
+
+ void PreambleWidget::reset()
+ {
+ m_fieldLineEditPreambleValue->setValue( m_bibtexpreamble->value() );
+ }
+
+ void PreambleWidget::setupGUI()
+ {
+ setMinimumWidth( 384 );
+
+ QVBoxLayout * layout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "&Preamble:" ), this );
+ layout->addWidget( label );
+ m_fieldLineEditPreambleValue = new KBibTeX::FieldLineEdit( i18n( "Preamble" ), KBibTeX::FieldLineEdit::itMultiLine, m_isReadOnly, this, "m_fieldLineEditPreambleValue" );
+ layout->addWidget( m_fieldLineEditPreambleValue );
+ label->setBuddy( m_fieldLineEditPreambleValue );
+ }
+
+}
+#include "preamblewidget.moc"
diff --git a/src/preamblewidget.h b/src/preamblewidget.h
new file mode 100644
index 0000000..f08ba47
--- /dev/null
+++ b/src/preamblewidget.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXPREAMBLEWIDGET_H
+#define KBIBTEXPREAMBLEWIDGET_H
+
+#include <qwidget.h>
+#include <qdialog.h>
+
+#include <preamble.h>
+#include <fieldlineedit.h>
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class PreambleWidget : public QWidget
+ {
+ Q_OBJECT
+ public:
+ static QDialog::DialogCode execute( BibTeX::Preamble *preamble, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+
+ private slots:
+ void apply();
+ void reset();
+
+ private:
+ bool m_isReadOnly;
+ BibTeX::Preamble* m_bibtexpreamble;
+ KBibTeX::FieldLineEdit *m_fieldLineEditPreambleValue;
+
+ PreambleWidget( BibTeX::Preamble *bibtexpreamble, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~PreambleWidget();
+
+ void setupGUI();
+
+ };
+
+}
+
+#endif
diff --git a/src/searchbar.cpp b/src/searchbar.cpp
new file mode 100644
index 0000000..113bb4d
--- /dev/null
+++ b/src/searchbar.cpp
@@ -0,0 +1,192 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <qlistbox.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <qlabel.h>
+
+#include <kcombobox.h>
+#include <kpushbutton.h>
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+#include <settings.h>
+#include "searchbar.h"
+
+namespace KBibTeX
+{
+
+ SearchBar::SearchBar( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+ {
+ m_timerInput = new QTimer( this );
+ connect( m_timerInput, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
+
+ setupGUI();
+ }
+
+ SearchBar::~SearchBar()
+ {
+ delete m_timerInput;
+ }
+
+ void SearchBar::setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client )
+ {
+ KPopupMenu * menu = static_cast<KPopupMenu*>( factory -> container( "popup_newelements", client ) );
+ Settings * settings = Settings::self();
+ m_pushButtonAddElement->setPopup( menu );
+ m_comboboxFilter->setHistoryItems( settings->editing_FilterHistory );
+ }
+
+ void SearchBar::restoreState()
+ {
+ Settings * settings = Settings::self();
+ if ( settings->editing_UseSpecialFont )
+ m_comboboxFilter->setFont( settings->editing_SpecialFont );
+ else
+ m_comboboxFilter->setFont( KGlobalSettings::generalFont() );
+ }
+
+ void SearchBar::setSearch( const QString&text, BibTeX::Element::FilterType filterType, BibTeX::EntryField::FieldType fieldType )
+ {
+ m_comboboxFilter->setCurrentText( text );
+ switch ( filterType )
+ {
+ case BibTeX::Element::ftExact: m_comboboxFilterType->setCurrentItem( 0 ); break;
+ case BibTeX::Element::ftEveryWord: m_comboboxFilterType->setCurrentItem( 1 ); break;
+ case BibTeX::Element::ftAnyWord: m_comboboxFilterType->setCurrentItem( 2 ); break;
+ }
+ m_comboboxRestrictTo->setCurrentItem(( int ) fieldType + 1 );
+ }
+
+ void SearchBar::setupGUI()
+ {
+ QBoxLayout * layout = new QHBoxLayout( this, 3 /* KDialog::marginHint()*/, KDialog::spacingHint() );
+ KIconLoader iconLoader = KIconLoader( "kbibtex" );
+
+ m_pushButtonAddElement = new KPushButton( this );
+ m_pushButtonAddElement->setIconSet( QIconSet( BarIcon( "add" ) ) );
+ layout->addWidget( m_pushButtonAddElement );
+ QToolTip::add( m_pushButtonAddElement, i18n( "Add a new BibTeX entry, comment or macro to this file" ) );
+
+ m_pushButtonSearchOnlineDatabases = new KPushButton( this );
+ m_pushButtonSearchOnlineDatabases->setIconSet( QIconSet( BarIcon( "network" ) ) );
+ layout->addWidget( m_pushButtonSearchOnlineDatabases );
+ QToolTip::add( m_pushButtonSearchOnlineDatabases, i18n( "Add a new BibTeX entry from an online database" ) );
+ connect( m_pushButtonSearchOnlineDatabases, SIGNAL( clicked() ), this, SIGNAL( onlineSearch() ) );
+
+ layout->insertSpacing( 2, KDialog::spacingHint() );
+
+ m_pushButtonClearSearchText = new KPushButton( this );
+ m_pushButtonClearSearchText->setIconSet( QIconSet( BarIcon( "locationbar_erase" ) ) );
+ layout->addWidget( m_pushButtonClearSearchText );
+ QToolTip::add( m_pushButtonClearSearchText, i18n( "Erase current search pattern" ) );
+ m_pushButtonClearSearchText->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+
+ QLabel *label = new QLabel( i18n( "&Search:" ), this );
+ layout->addWidget( label );
+
+ m_comboboxFilter = new KHistoryCombo( TRUE, this, "search_combobox" );
+ layout->addWidget( m_comboboxFilter );
+ label->setBuddy( m_comboboxFilter );
+ m_comboboxFilter->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
+ m_comboboxFilter->setMaxCount( 256 );
+
+ m_comboboxFilterType = new KComboBox( FALSE, this );
+ m_comboboxFilterType->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred );
+ layout->addWidget( m_comboboxFilterType );
+
+ m_comboboxFilterType->insertItem( i18n( "Exact" ) );
+ m_comboboxFilterType->insertItem( i18n( "Every word" ) );
+ m_comboboxFilterType->insertItem( i18n( "Any word" ) );
+ m_comboboxFilterType->setCurrentItem( 1 );
+
+ label = new QLabel( i18n( "Restrict to:" ), this );
+ layout->addWidget( label );
+ m_comboboxRestrictTo = new KComboBox( FALSE, this );
+ m_comboboxRestrictTo->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred );
+ layout->addWidget( m_comboboxRestrictTo );
+ label->setBuddy( m_comboboxRestrictTo );
+
+ m_comboboxRestrictTo->insertItem( i18n( "All fields" ) );
+ for ( int i = ( int ) BibTeX::EntryField::ftAbstract; i <= ( int ) BibTeX::EntryField::ftYear; i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType ) i;
+ m_comboboxRestrictTo->insertItem( Settings::fieldTypeToI18NString( fieldType ) );
+ }
+
+ connect( m_comboboxFilter->lineEdit(), SIGNAL( textChanged( const QString & ) ), this, SLOT( slotKeyPressed() ) );
+ connect( m_comboboxFilter, SIGNAL( activated( const QString& ) ), m_comboboxFilter, SLOT( addToHistory( const QString& ) ) );
+ connect( m_pushButtonClearSearchText, SIGNAL( clicked() ), this, SLOT( slotClear() ) );
+ connect( m_comboboxFilterType, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotAnnounceDoSearch() ) );
+ connect( m_comboboxFilter, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotAnnounceDoSearch() ) );
+ connect( m_comboboxFilter->lineEdit(), SIGNAL( returnPressed() ), this, SLOT( slotAnnounceDoSearch() ) );
+ connect( m_comboboxFilterType, SIGNAL( activated( int ) ), this, SLOT( slotTimeout() ) );
+ connect( m_comboboxRestrictTo, SIGNAL( activated( int ) ), this, SLOT( slotTimeout() ) );
+
+ setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
+ }
+
+ void SearchBar::slotClear()
+ {
+ m_comboboxFilter->lineEdit() ->clear();
+ m_comboboxRestrictTo->setCurrentItem( 0 );
+ m_comboboxFilterType->setCurrentItem( 1 );
+ m_comboboxFilter->setFocus();
+ }
+
+ void SearchBar::slotTimeout()
+ {
+ BibTeX::EntryField::FieldType fieldType = BibTeX::EntryField::ftUnknown;
+ if ( m_comboboxRestrictTo->currentItem() > 0 )
+ fieldType = ( BibTeX::EntryField::FieldType )( m_comboboxRestrictTo->currentItem() - 1 + ( int ) BibTeX::EntryField::ftAbstract );
+
+ Settings * settings = Settings::self();
+ settings->editing_FilterHistory = m_comboboxFilter->historyItems();
+
+ BibTeX::Element::FilterType filterType = BibTeX::Element::ftExact;
+ if ( m_comboboxFilterType->currentItem() == 1 ) filterType = BibTeX::Element::ftEveryWord;
+ else if ( m_comboboxFilterType->currentItem() == 2 ) filterType = BibTeX::Element::ftAnyWord;
+
+ emit doSearch( m_comboboxFilter->currentText(), filterType, fieldType );
+ }
+
+ void SearchBar::slotAnnounceDoSearch()
+ {
+ if ( m_timerInput->isActive() )
+ m_timerInput->stop();
+
+ m_timerInput->start( 0, true );
+ }
+
+ void SearchBar::slotKeyPressed()
+ {
+ Settings * settings = Settings::self();
+ if ( settings->editing_SearchBarClearField )
+ m_comboboxRestrictTo->setCurrentItem( 0 );
+ }
+
+}
+#include "searchbar.moc"
diff --git a/src/searchbar.h b/src/searchbar.h
new file mode 100644
index 0000000..e733d42
--- /dev/null
+++ b/src/searchbar.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXSEARCHBAR_H
+#define KBIBTEXSEARCHBAR_H
+
+#include <qwidget.h>
+
+#include <kxmlguifactory.h>
+
+#include <documentlistview.h>
+#include <entryfield.h>
+
+class QTimer;
+class KPushButton;
+class KPopupMenu;
+class KHistoryCombo;
+class KComboBox;
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer
+ */
+ class SearchBar : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SearchBar( QWidget *parent = 0, const char *name = "search_bar" );
+ ~SearchBar();
+
+ void setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client );
+ void restoreState();
+
+ signals:
+ void doSearch( const QString &text, BibTeX::Element::FilterType, BibTeX::EntryField::FieldType fieldType );
+ void onlineSearch();
+
+ public slots:
+ void setSearch( const QString&text, BibTeX::Element::FilterType, BibTeX::EntryField::FieldType fieldType );
+
+ private:
+ KPushButton *m_pushButtonClearSearchText;
+ KHistoryCombo *m_comboboxFilter;
+ QTimer *m_timerInput;
+ KPushButton *m_pushButtonAddElement;
+ KPushButton *m_pushButtonSearchOnlineDatabases;
+ KComboBox *m_comboboxFilterType;
+ KComboBox *m_comboboxRestrictTo;
+
+ void setupGUI();
+
+ private slots:
+ void slotClear();
+ void slotTimeout();
+ void slotAnnounceDoSearch();
+ void slotKeyPressed();
+ };
+
+}
+
+#endif
diff --git a/src/settings.cpp b/src/settings.cpp
new file mode 100644
index 0000000..67b4d2f
--- /dev/null
+++ b/src/settings.cpp
@@ -0,0 +1,966 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qstring.h>
+#include <qprocess.h>
+#include <qstringlist.h>
+#include <qfont.h>
+#include <qregexp.h>
+#include <qwaitcondition.h>
+#include <qprocess.h>
+#include <qapplication.h>
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kbibtex_part.h>
+#include <kdebug.h>
+#include <kio/netaccess.h>
+
+#include <entryfield.h>
+#include <element.h>
+#include <entry.h>
+#include <macro.h>
+#include "settings.h"
+
+namespace KBibTeX
+{
+ Settings* Settings::staticSettings = new Settings();
+ QStringList Settings::m_lyxRcFileNames = QStringList::split( '|', QDir::home().canonicalPath() + "/.lyx/lyxrc" + '|' + QDir::home().canonicalPath() + "/.lyx/preferences" );
+
+ const QRegExp Settings::noIdChars( "[^-.:/+_a-zA-Z0-9]" );
+
+ Settings::Settings()
+ {
+ checkExternalToolsAvailable();
+
+ KStandardDirs * kstd = KGlobal::dirs();
+ external_XSLTStylesheetHTML = kstd->findResource( "data", "kbibtexpart/xslt/html.xsl" );
+ if ( external_XSLTStylesheetHTML == NULL )
+ KMessageBox::error( NULL, i18n( "Could not determine filename for XSLT file" ), i18n( "Initialization failed" ) );
+
+ int numCompletions = BibTeX::EntryField::ftYear - BibTeX::EntryField::ftAbstract + 4;
+ m_completion = new KCompletion * [ numCompletions ];
+ for ( int i = 0; i < numCompletions; ++i )
+ {
+ m_completion[ i ] = new KCompletion();
+ m_completion[ i ] ->setIgnoreCase( TRUE );
+ }
+ completionMacro = new KCompletion();
+ completionMacro->setIgnoreCase( FALSE );
+
+ currentBibTeXFile = NULL;
+ }
+
+ Settings::~Settings()
+ {
+ int numCompletions = BibTeX::EntryField::ftYear - BibTeX::EntryField::ftAbstract + 4;
+ for ( int i = 0; i < numCompletions; ++i )
+ delete m_completion[ i ];
+ delete[] m_completion;
+ delete completionMacro;
+
+ for ( QValueList<SearchURL*>::ConstIterator it = searchURLs.begin(); it != searchURLs.end(); ++it )
+ delete *it;
+ }
+
+ Settings* Settings::self( BibTeX::File *bibtexFile )
+ {
+ if ( bibtexFile != NULL )
+ staticSettings->currentBibTeXFile = bibtexFile;
+ return staticSettings;
+ }
+
+ void Settings::load( KConfig * config )
+ {
+ config->setGroup( "FileIO" );
+ fileIO_Encoding = config->readEntry( "Encoding", "latex" );
+ if ( fileIO_Encoding.length() == 1 ) fileIO_Encoding = "latex"; // due to old scheme where digits were used
+ fileIO_ExportLanguage = config->readEntry( "ExportLanguage", "english" );
+ fileIO_ExportBibliographyStyle = config->readEntry( "ExportBibliographyStyle", "plain" );
+ fileIO_ExporterHTML = ( BibTeX::FileExporterExternal::Exporter ) config->readNumEntry( "ExporterHTML", ( int ) BibTeX::FileExporterExternal::exporterNone );
+ fileIO_BibtexStringOpenDelimiter = config->readEntry( "BibtexStringOpenDelimiter", "\"" ).at( 0 );
+ fileIO_BibtexStringCloseDelimiter = config->readEntry( "BibtexStringCloseDelimiter", "\"" ).at( 0 );
+ fileIO_KeywordCasing = ( BibTeX::FileExporterBibTeX::KeywordCasing ) config->readNumEntry( "KeywordCasing", ( int ) BibTeX::FileExporterBibTeX::kcCamelCase );
+ fileIO_EmbedFiles = config->readBoolEntry( "EmbedFiles", FALSE );
+ fileIO_EnclosingCurlyBrackets = config->readBoolEntry( "EnclosingCurlyBrackets", FALSE );
+ fileIO_useBibUtils = config->readBoolEntry( "UseBibUtils", TRUE );
+ updateBib2Db5ClassPath( config->readEntry( "Bib2Db5BasePath", QString::null ) );
+ fileIO_NumberOfBackups = config->readNumEntry( "NumberOfBackups", 0 );
+
+ config->setGroup( "Editing" );
+ editing_SearchBarClearField = config->readBoolEntry( "SearchBarClearField", false );
+ editing_EnableAllFields = config->readBoolEntry( "EnableAllFields", false );
+ editing_MainListDoubleClickAction = config->readNumEntry( "MainListDoubleClickAction", 0 );
+ editing_MainListSortingColumn = config->readNumEntry( "MainListSortingColumn", 1 );
+ editing_MainListSortingOrder = config->readNumEntry( "MainListSortingOrder", 1 );
+ editing_MainListColumnsWidth = config->readIntListEntry( "MainListColumnsWidth" );
+ editing_MainListColumnsIndex = config->readIntListEntry( "MainListColumnsIndex" );
+ editing_FilterHistory = config->readListEntry( "FilterHistory" );
+ editing_ShowComments = config->readBoolEntry( "ShowComments", TRUE );
+ editing_ShowMacros = config->readBoolEntry( "ShowMacros", TRUE );
+ editing_HorSplitterSizes = config->readIntListEntry( "HorizontalSplitterSizes" );
+ editing_VertSplitterSizes = config->readIntListEntry( "VerticalSplitterSizes" );
+ QFont defaultFont = KGlobalSettings::generalFont();
+ editing_SpecialFont = config->readFontEntry( "SpecialFont", &defaultFont );
+ editing_UseSpecialFont = config->readBoolEntry( "UseSpecialFont", FALSE );
+ editing_FirstNameFirst = config->readBoolEntry( "FirstNameFirst", FALSE );
+ editing_DocumentSearchPaths = config->readListEntry( "DocumentSearchPath" );
+ editing_DragAction = ( DragAction ) config->readNumEntry( "DragAction", ( int ) COPYREFERENCE );
+
+ if ( editing_MainListColumnsWidth.isEmpty() || editing_MainListColumnsIndex.isEmpty() )
+ {
+ editing_MainListColumnsWidth.clear();
+ editing_MainListColumnsIndex.clear();
+
+ int column = 0;
+ // for type and id column
+ editing_MainListColumnsWidth.append( 0xffff );
+ editing_MainListColumnsWidth.append( 0xffff );
+ editing_MainListColumnsIndex.append( column++ );
+ editing_MainListColumnsIndex.append( column++ );
+
+ for ( int i = 0; i <= ( int ) BibTeX::EntryField::ftYear - ( int ) BibTeX::EntryField::ftAbstract; i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType )( i + ( int ) BibTeX::EntryField::ftAbstract );
+ if ( fieldType == BibTeX::EntryField::ftAuthor || fieldType == BibTeX::EntryField::ftTitle )
+ editing_MainListColumnsWidth.append( 0xffff );
+ else
+ editing_MainListColumnsWidth.append( 0 );
+ editing_MainListColumnsIndex.append( column++ );
+ }
+ }
+ editing_findDuplicatesSensitivity = config->readNumEntry( "FindDuplicatesSensitivity", 12 );
+
+ config->setGroup( "SearchURLs" );
+ searchURLs.clear();
+ for ( int i = 1; i < 1024; i++ )
+ {
+ QString descr = config->readEntry( QString( "SearchURLDescription%1" ).arg( i ), QString::null );
+ QString url = config->readEntry( QString( "SearchURL%1" ).arg( i ), QString::null );
+ bool includeAuthor = config->readBoolEntry( QString( "IncludeAuthor%1" ).arg( i ), FALSE );
+ if ( descr != QString::null && url != QString::null )
+ {
+ SearchURL * searchURL = new SearchURL;
+ searchURL->description = descr;
+ searchURL->url = url;
+ searchURL->includeAuthor = includeAuthor;
+ searchURLs.append( searchURL );
+ }
+ else
+ break;
+ }
+
+ if ( searchURLs.count() == 0 )
+ restoreDefaultSearchURLs();
+
+ config->setGroup( "Keyword" );
+ keyword_GlobalList = config->readListEntry( "GlobalList" );
+ keyword_GlobalList.sort();
+
+ config->setGroup( "OnlineSearchDatabase" );
+ webQuery_LastEngine = config->readNumEntry( "LastEngine", 0 );
+ webQuery_LastSearchTerm = config->readEntry( "LastSearchTerm", "" );
+ webQuery_LastNumberOfResults = config->readNumEntry( "LastNumberOfResults", 10 );
+ webQuery_ImportAll = config->readBoolEntry( "ImportAll", FALSE );
+
+ config->setGroup( "IdSuggestions" );
+ idSuggestions_formatStrList = config->readListEntry( "FormatStrList" );
+ if ( idSuggestions_formatStrList.count() == 0 )
+ {
+ idSuggestions_formatStrList = QStringList::split( ',', "A,A2|y,A3|y,A4|y|\":|T5,al|\":|T,al|y,al|Y,Al\"-|\"-|y,Al\"+|Y,al|y|T,al|Y|T3,al|Y|T3l,a|\":|Y|\":|T1,a|y,A|\":|Y" );
+ idSuggestions_default = -1;
+ idSuggestions_forceDefault = FALSE;
+ }
+ else
+ {
+ idSuggestions_default = config->readNumEntry( "Default", -1 );
+ idSuggestions_forceDefault = config->readBoolEntry( "ForceDefault", FALSE );
+ }
+ idSuggestions_smallWords = config->readListEntry( "SmallWords" );
+ if ( idSuggestions_smallWords.count() == 0 )
+ idSuggestions_smallWords = QStringList::split( '|', "and|on|in|the|of|at|a|an|with|for|from" );
+ idSuggestions_smallWords.sort();
+
+ config->setGroup( "UserDefinedInputFields" );
+ QStringList names = config->readListEntry( "Names" );
+ QStringList labels = config->readListEntry( "Labels" );
+ QStringList inputtypes = config->readListEntry( "InputTypes" );
+
+ userDefinedInputFields.clear();
+ for ( unsigned int i = 0; i < names.size();++i )
+ {
+ UserDefinedInputFields *udif = new UserDefinedInputFields();
+ udif->name = names[i];
+ udif->label = labels[i];
+ udif->inputType = ( inputtypes[i] == "single" ? FieldLineEdit::itSingleLine : FieldLineEdit::itMultiLine );
+ userDefinedInputFields << udif;
+ }
+
+ // web query history/default values
+ m_webQueryDefaults = config->entryMap( "WebQuery" );
+
+#ifdef HAVE_YAZ
+ z3950clearAll();
+ z3950loadUser( config );
+ z3950loadDefault();
+#endif // HAVE_YAZ
+ }
+
+ void Settings::save( KConfig * config )
+ {
+ config->setGroup( "FileIO" );
+ config->writeEntry( "Encoding", fileIO_Encoding );
+ config->writeEntry( "ExportLanguage", fileIO_ExportLanguage );
+ config->writeEntry( "ExportBibliographyStyle", fileIO_ExportBibliographyStyle );
+ config->writeEntry( "ExporterHTML", ( int ) fileIO_ExporterHTML );
+ config->writeEntry( "BibtexStringOpenDelimiter", QString( fileIO_BibtexStringOpenDelimiter ) );
+ config->writeEntry( "BibtexStringCloseDelimiter", QString( fileIO_BibtexStringCloseDelimiter ) );
+ config->writeEntry( "KeywordCasing", ( int ) fileIO_KeywordCasing );
+ config->writeEntry( "EmbedFiles", fileIO_EmbedFiles );
+ config->writeEntry( "EnclosingCurlyBrackets", fileIO_EnclosingCurlyBrackets );
+ config->writeEntry( "UseBibUtils", fileIO_useBibUtils );
+ config->writeEntry( "Bib2Db5BasePath", fileIO_bib2db5BasePath );
+ config->writeEntry( "NumberOfBackups", fileIO_NumberOfBackups );
+
+ config->setGroup( "Editing" );
+ config->writeEntry( "SearchBarClearField", editing_SearchBarClearField );
+ config->writeEntry( "EnableAllFields", editing_EnableAllFields );
+ config->writeEntry( "MainListDoubleClickAction", editing_MainListDoubleClickAction );
+ config->writeEntry( "MainListSortingColumn", editing_MainListSortingColumn );
+ config->writeEntry( "MainListSortingOrder", editing_MainListSortingOrder );
+ config->writeEntry( "MainListColumnsWidth", editing_MainListColumnsWidth );
+ config->writeEntry( "MainListColumnsIndex", editing_MainListColumnsIndex );
+ config->writeEntry( "FilterHistory", editing_FilterHistory );
+ config->writeEntry( "ShowComments", editing_ShowComments );
+ config->writeEntry( "ShowMacros", editing_ShowMacros );
+ config->writeEntry( "HorizontalSplitterSizes", editing_HorSplitterSizes );
+ config->writeEntry( "VerticalSplitterSizes", editing_VertSplitterSizes );
+ config->writeEntry( "SpecialFont", editing_SpecialFont );
+ config->writeEntry( "UseSpecialFont", editing_UseSpecialFont );
+ config->writeEntry( "FirstNameFirst", editing_FirstNameFirst );
+ config->writeEntry( "DocumentSearchPath", editing_DocumentSearchPaths );
+ config->writeEntry( "DragAction", editing_DragAction );
+ config->writeEntry( "FindDuplicatesSensitivity", editing_findDuplicatesSensitivity );
+
+ config->setGroup( "SearchURLs" );
+ int i = 1;
+ for ( QValueList<SearchURL*>::ConstIterator it = searchURLs.begin(); it != searchURLs.end(); ++it, ++i )
+ {
+ config->writeEntry( QString( "SearchURLDescription%1" ).arg( i ), ( *it ) ->description );
+ config->writeEntry( QString( "SearchURL%1" ).arg( i ), ( *it ) ->url );
+ config->writeEntry( QString( "IncludeAuthor%1" ).arg( i ), ( *it ) ->includeAuthor );
+ }
+
+ config->setGroup( "Keyword" );
+ config->writeEntry( "GlobalList", keyword_GlobalList );
+
+ config->setGroup( "OnlineSearchDatabase" );
+ config->writeEntry( "LastEngine", webQuery_LastEngine );
+ config->writeEntry( "LastSearchTerm", webQuery_LastSearchTerm );
+ config->writeEntry( "LastNumberOfResults", webQuery_LastNumberOfResults );
+ config->writeEntry( "ImportAll", webQuery_ImportAll );
+
+ config->setGroup( "IdSuggestions" );
+ config->writeEntry( "FormatStrList", idSuggestions_formatStrList );
+ config->writeEntry( "Default", idSuggestions_default );
+ config->writeEntry( "ForceDefault", idSuggestions_forceDefault );
+ config->writeEntry( "SmallWords", idSuggestions_smallWords );
+
+ config->setGroup( "UserDefinedInputFields" );
+ QStringList names, labels, inputtype;
+ for ( QValueList<UserDefinedInputFields*>::iterator it = userDefinedInputFields.begin(); it != userDefinedInputFields.end();++it )
+ {
+ names << ( *it )->name;
+ labels << ( *it )->label;
+ inputtype << (( *it )->inputType == FieldLineEdit::itMultiLine ? "multi" : "single" );
+ }
+ config->writeEntry( "Names", names );
+ config->writeEntry( "Labels", labels );
+ config->writeEntry( "InputTypes", inputtype );
+
+ config->setGroup( "WebQuery" );
+ for ( QMap<QString, QString>::Iterator it = m_webQueryDefaults.begin(); it != m_webQueryDefaults.end(); ++it )
+ config->writeEntry( it.key(), it.data() );
+
+#ifdef HAVE_YAZ
+ z3950saveUser( config );
+#endif // HAVE_YAZ
+ }
+
+ void Settings::checkExternalToolsAvailable()
+ {
+ external_bibconvAvailable = checkExternalToolAvailable( "bibconv" );
+ external_bibtex2htmlAvailable = checkExternalToolAvailable( "bibtex2html" );
+ external_bib2xhtmlAvailable = checkExternalToolAvailable( "bib2xhtml" );
+ external_latex2rtfAvailable = checkExternalToolAvailable( "latex2rtf" );
+ external_xml2bibAvailable = checkExternalToolAvailable( "xml2bib" );
+ external_end2xmlAvailable = checkExternalToolAvailable( "end2xml" );
+ external_ris2xmlAvailable = checkExternalToolAvailable( "ris2xml" );
+ }
+
+ bool Settings::updateBib2Db5ClassPath( const QString& newBasePath, bool testOnly )
+ {
+ QString bib2db5ClassPath = QString::null;
+ QDir bib2db5BaseDir( newBasePath );
+ QStringList list = bib2db5BaseDir.entryList( "antlr-runtime*.jar" );
+ if ( !list.isEmpty() )
+ {
+ bib2db5ClassPath = bib2db5BaseDir.absPath() + "/" + list[0];
+ list = bib2db5BaseDir.entryList( "bib2db5*.jar" );
+ if ( !list.isEmpty() )
+ bib2db5ClassPath += ":" + bib2db5BaseDir.absPath() + "/" + list[0];
+ else
+ bib2db5ClassPath = QString::null;
+ }
+ else
+ bib2db5ClassPath = QString::null;
+ if ( bib2db5ClassPath == QString::null )
+ kdDebug() << "Base path for bib2db5 is invalid (\"" << newBasePath << "\")" << endl;
+
+ if ( !testOnly )
+ {
+ fileIO_bib2db5BasePath = newBasePath;
+ fileIO_bib2db5ClassPath = bib2db5ClassPath;
+ }
+
+ return bib2db5ClassPath != QString::null;
+ }
+
+ bool Settings::checkExternalToolAvailable( const QString &binary )
+ {
+ QProcess *process = new QProcess( binary );
+ bool ok = process->start();
+ ok &= process->normalExit();
+ if ( process->isRunning() )
+ {
+ process->kill();
+ ok = true;
+ }
+ delete process;
+ return ok;
+ }
+
+ QString Settings::detectLyXInPipe()
+ {
+ QString result = QString::null;
+ for ( QStringList::Iterator it = m_lyxRcFileNames.begin(); result.isNull() && it != m_lyxRcFileNames.end(); ++it )
+ {
+ QString lyxRcFileName = *it;
+ QFile lyxRcFile( lyxRcFileName );
+
+ kdDebug() << "detectLyXInPipe: looking for " << lyxRcFileName << endl;
+ if ( lyxRcFile.exists() && lyxRcFile.open( IO_ReadOnly ) )
+ {
+ QTextStream input( &lyxRcFile );
+ while ( result.isNull() && !input.atEnd() )
+ {
+ QString line = input.readLine();
+ if ( line.startsWith( "\\serverpipe ", FALSE ) )
+ {
+ QStringList cols = QStringList::split( QRegExp( "\\s+\"|\"" ), line );
+ if ( cols.size() >= 2 )
+ {
+ result = cols[ 1 ] + ".in";
+ kdDebug() << "detectLyXInPipe: testing " << result << " from config file" << endl;
+ if ( !QFile::exists( result ) )
+ kdDebug() << "LyX in pipe '" << result << "' from " << lyxRcFileName << " does not exist" << endl;
+ }
+ }
+ }
+ lyxRcFile.close();
+ }
+ }
+
+ if ( result.isNull() )
+ {
+ result = QDir::home().canonicalPath() + "/.lyx/lyxpipe.in";
+ kdDebug() << "detectLyXInPipe: testing " << result << endl;
+ if ( !QFile::exists( result ) )
+ result = QString::null;
+ }
+
+ if ( result.isNull() )
+ {
+ result = QDir::home().canonicalPath() + "/.lyx/.lyxpipe.in";
+ kdDebug() << "detectLyXInPipe: testing " << result << endl;
+ if ( !QFile::exists( result ) )
+ result = QString::null;
+ }
+
+ if ( result.isNull() )
+ {
+ result = QDir::home().canonicalPath() + "/.lyxpipe.in";
+ kdDebug() << "detectLyXInPipe: testing " << result << endl;
+ if ( !QFile::exists( result ) )
+ result = QString::null;
+ }
+
+ kdDebug() << "detectLyXInPipe: using " << ( result.isNull() ? "<INVALID>" : result ) << endl;
+ return result;
+ }
+
+ QString Settings::getWebQueryDefault( const QString &key )
+ {
+ return m_webQueryDefaults[key];
+ }
+
+ void Settings::setWebQueryDefault( const QString &key, const QString& value )
+ {
+ m_webQueryDefaults[key] = value;
+ }
+
+ void Settings::addToCompletion( BibTeX::File *file )
+ {
+ for ( BibTeX::File::ElementList::iterator it = file->begin(); it != file->end(); it++ )
+ addToCompletion( *it );
+ }
+
+ void Settings::addToCompletion( BibTeX::Element *element )
+ {
+ BibTeX::Entry * entry = dynamic_cast<BibTeX::Entry*>( element );
+ BibTeX::Macro * macro = dynamic_cast<BibTeX::Macro*>( element );
+ if ( entry != NULL )
+ {
+ for ( BibTeX::Entry::EntryFields::ConstIterator ite = entry->begin(); ite != entry->end(); ite++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( *ite ) ->fieldType();
+ BibTeX::Value *value = ( *ite ) ->value();
+ addToCompletion( value, fieldType );
+ }
+ }
+ else if ( macro != NULL )
+ completionMacro->addItem( macro->key() );
+ }
+
+ void Settings::addToCompletion( BibTeX::Value *value, BibTeX::EntryField::FieldType fieldType )
+ {
+ int index = completionFieldTypeToIndex( fieldType );
+
+ for ( QValueList<BibTeX::ValueItem*>::ConstIterator itv = value->items.begin(); itv != value->items.end(); itv++ )
+ {
+ BibTeX::PlainText *plainText = dynamic_cast<BibTeX::PlainText*>( *itv );
+ if ( plainText != NULL )
+ m_completion[ index ] ->addItem( plainText->text() );
+ else
+ {
+ BibTeX::PersonContainer *personContainer = dynamic_cast<BibTeX::PersonContainer*>( *itv );
+ if ( personContainer != NULL )
+ for ( QValueList<BibTeX::Person*>::Iterator itp = personContainer->persons.begin();itp != personContainer->persons.end(); ++itp )
+ {
+ m_completion[ index ] ->addItem(( *itp )->text( TRUE ) );
+ m_completion[ index ] ->addItem(( *itp )->text( FALSE ) );
+ }
+ else
+ {
+ BibTeX::KeywordContainer *keywordContainer = dynamic_cast<BibTeX::KeywordContainer*>( *itv );
+ if ( keywordContainer != NULL )
+ for ( QValueList<BibTeX::Keyword*>::Iterator itk = keywordContainer->keywords.begin();itk != keywordContainer->keywords.end(); ++itk )
+ m_completion[ index ] ->addItem(( *itk )->text() );
+ }
+ }
+ }
+ }
+
+ KCompletion *Settings::completion( BibTeX::EntryField::FieldType fieldType )
+ {
+ return m_completion[ completionFieldTypeToIndex( fieldType )];
+ }
+
+ int Settings::completionFieldTypeToIndex( BibTeX::EntryField::FieldType fieldType )
+ {
+ int index = 0;
+ if ( fieldType == BibTeX::EntryField::ftEditor )
+ fieldType = BibTeX::EntryField::ftAuthor;
+ if ( fieldType != BibTeX::EntryField::ftUnknown )
+ index = ( int )( fieldType - BibTeX::EntryField::ftAbstract ) + 1;
+ return index;
+ }
+
+ void Settings::restoreDefaultSearchURLs()
+ {
+ QStringList defaultDescriptions;
+ defaultDescriptions.append( "Google Scholar" );
+ defaultDescriptions.append( "Google .bib Search" );
+ defaultDescriptions.append( "Google Document Search" );
+ defaultDescriptions.append( "Google" );
+ defaultDescriptions.append( "CiteSeer" );
+ defaultDescriptions.append( "PubMed" );
+ defaultDescriptions.append( "PubMed Central" );
+ defaultDescriptions.append( "DBLP (Computer Science)" );
+ defaultDescriptions.append( "citebase" );
+ defaultDescriptions.append( "BASE" );
+ defaultDescriptions.append( "Forschungsportal.Net" );
+ defaultDescriptions.append( "scirus" );
+ defaultDescriptions.append( "ScientificCommons" );
+ defaultDescriptions.append( "Amatex (US)" );
+ defaultDescriptions.append( "SpringerLink" );
+
+ QValueList<SearchURL*> toDelete;
+ for ( QValueList<SearchURL*>::ConstIterator it = searchURLs.begin(); it != searchURLs.end(); ++it )
+ {
+ if ( defaultDescriptions.contains(( *it ) ->description ) )
+ {
+ toDelete.append( *it );
+ }
+ }
+
+ for ( QValueList<SearchURL*>::ConstIterator it = toDelete.begin(); it != toDelete.end(); ++it )
+ {
+ delete *it;
+ searchURLs.remove( *it );
+ }
+
+ SearchURL *searchURL = new SearchURL;
+ searchURL->description = "Google";
+ searchURL->url = "http://www.google.com/search?q=%1&ie=UTF-8&oe=UTF-8";
+ searchURL->includeAuthor = TRUE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "Google Scholar";
+ searchURL->url = "http://scholar.google.com/scholar?q=%1&ie=UTF-8&oe=UTF-8";
+ searchURL->includeAuthor = TRUE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "Google .bib Search";
+ searchURL->url = "http://www.google.com/search?q=%1%20filetype%3Abib&ie=UTF-8&oe=UTF-8";
+ searchURL->includeAuthor = TRUE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "Google Document Search";
+ searchURL->url = "http://www.google.com/search?q=%1%20filetype%3Apdf%20OR%20filetype%3Aps&ie=UTF-8&oe=UTF-8";
+ searchURL->includeAuthor = TRUE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "PubMed";
+ searchURL->url = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=pubmed&cmd=search&pmfilter_Fulltext=on&pmfilter_Relevance=on&term=%1&search=Find+Articles";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "PubMed Central";
+ searchURL->url = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=pubmed&cmd=search&term=%1";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "Amatex (US)";
+ searchURL->url = "http://www.2ndminute.org:8080/amatex/search.do?querry=%1&suchart=kwd&lang=DE";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "DBLP (Computer Science)";
+ searchURL->url = "http://www.informatik.uni-trier.de/ley/dbbin/dblpquery.cgi?title=%1";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "CiteSeer";
+ searchURL->url = "http://citeseer.ist.psu.edu/cis?q=%1&submit=Search+Documents";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "citebase";
+ searchURL->url = "http://www.citebase.org/search?type=metadata&author=&title=%1&publication=&yearfrom=&yearuntil=&order=DESC&rank=paperimpact&submitted=Search";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "BASE";
+ searchURL->url = "http://digital.ub.uni-bielefeld.de/index.php?q=%1&s=free";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "Forschungsportal.Net";
+ searchURL->url = "http://www.forschungsportal.net/fpj/q/?q=%1&pp=5&art=dok&html=1&pdf=1&ps=1&dvi=1";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "scirus";
+ searchURL->url = "http://www.scirus.com/srsapp/search?q=%1&ds=jnl&ds=nom&ds=web&g=s&t=all";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "ScientificCommons";
+ searchURL->url = "http://en.scientificcommons.org/#search_string=%1";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+
+ searchURL = new SearchURL;
+ searchURL->description = "SpringerLink";
+ searchURL->url = "http://www.springerlink.com/content/?k=%1";
+ searchURL->includeAuthor = FALSE;
+ searchURLs.append( searchURL );
+ }
+
+ QString Settings::fieldTypeToI18NString( const BibTeX::EntryField::FieldType fieldType )
+ {
+ switch ( fieldType )
+ {
+ case BibTeX::EntryField::ftAbstract:
+ return QString( i18n( "Abstract" ) );
+ case BibTeX::EntryField::ftAddress:
+ return QString( i18n( "Address" ) );
+ case BibTeX::EntryField::ftAnnote:
+ return QString( i18n( "Annote" ) );
+ case BibTeX::EntryField::ftAuthor:
+ return QString( i18n( "Author" ) );
+ case BibTeX::EntryField::ftBookTitle:
+ return QString( i18n( "Book Title" ) );
+ case BibTeX::EntryField::ftChapter:
+ return QString( i18n( "Chapter" ) );
+ case BibTeX::EntryField::ftCrossRef:
+ return QString( i18n( "Crossref" ) );
+ case BibTeX::EntryField::ftDoi:
+ return QString( i18n( "DOI" ) );
+ case BibTeX::EntryField::ftEdition:
+ return QString( i18n( "Edition" ) );
+ case BibTeX::EntryField::ftEditor:
+ return QString( i18n( "Editor" ) );
+ case BibTeX::EntryField::ftHowPublished:
+ return QString( i18n( "How Published" ) );
+ case BibTeX::EntryField::ftInstitution:
+ return QString( i18n( "Institution" ) );
+ case BibTeX::EntryField::ftISBN:
+ return QString( i18n( "ISBN" ) );
+ case BibTeX::EntryField::ftISSN:
+ return QString( i18n( "ISSN" ) );
+ case BibTeX::EntryField::ftJournal:
+ return QString( i18n( "Journal" ) );
+ case BibTeX::EntryField::ftKey:
+ return QString( i18n( "Key" ) );
+ case BibTeX::EntryField::ftKeywords:
+ return QString( i18n( "Keywords" ) );
+ case BibTeX::EntryField::ftLocalFile:
+ return QString( i18n( "Local File" ) );
+ case BibTeX::EntryField::ftLocation:
+ return QString( i18n( "Location" ) );
+ case BibTeX::EntryField::ftMonth:
+ return QString( i18n( "Month" ) );
+ case BibTeX::EntryField::ftNote:
+ return QString( i18n( "Note" ) );
+ case BibTeX::EntryField::ftNumber:
+ return QString( i18n( "Number" ) );
+ case BibTeX::EntryField::ftOrganization:
+ return QString( i18n( "Organization" ) );
+ case BibTeX::EntryField::ftPages:
+ return QString( i18n( "Pages" ) );
+ case BibTeX::EntryField::ftPublisher:
+ return QString( i18n( "Publisher" ) );
+ case BibTeX::EntryField::ftSeries:
+ return QString( i18n( "Series" ) );
+ case BibTeX::EntryField::ftSchool:
+ return QString( i18n( "School" ) );
+ case BibTeX::EntryField::ftTitle:
+ return QString( i18n( "Title" ) );
+ case BibTeX::EntryField::ftType:
+ return QString( i18n( "Type" ) );
+ case BibTeX::EntryField::ftURL:
+ return QString( i18n( "URL" ) );
+ case BibTeX::EntryField::ftVolume:
+ return QString( i18n( "Volume" ) );
+ case BibTeX::EntryField::ftYear:
+ return QString( i18n( "Year" ) );
+ default:
+ return QString( i18n( "Unknown" ) );
+ }
+ }
+
+ QString Settings::entryTypeToI18NString( const BibTeX::Entry::EntryType entryType )
+ {
+ switch ( entryType )
+ {
+ case BibTeX::Entry::etArticle:
+ return QString( i18n( "Article" ) );
+ case BibTeX::Entry::etBook:
+ return QString( i18n( "Book" ) );
+ case BibTeX::Entry::etBooklet:
+ return QString( i18n( "Booklet" ) );
+ case BibTeX::Entry::etCollection:
+ return QString( i18n( "Collection" ) );
+ case BibTeX::Entry::etElectronic:
+ return QString( i18n( "Electronic" ) );
+ case BibTeX::Entry::etInBook:
+ return QString( i18n( "InBook" ) );
+ case BibTeX::Entry::etInCollection:
+ return QString( i18n( "InCollection" ) );
+ case BibTeX::Entry::etInProceedings:
+ return QString( i18n( "InProceedings" ) );
+ case BibTeX::Entry::etManual:
+ return QString( i18n( "Manual" ) );
+ case BibTeX::Entry::etMastersThesis:
+ return QString( i18n( "MastersThesis" ) );
+ case BibTeX::Entry::etMisc:
+ return QString( i18n( "Misc" ) );
+ case BibTeX::Entry::etPhDThesis:
+ return QString( i18n( "PhDThesis" ) );
+ case BibTeX::Entry::etProceedings:
+ return QString( i18n( "Proceedings" ) );
+ case BibTeX::Entry::etTechReport:
+ return QString( i18n( "TechReport" ) );
+ case BibTeX::Entry::etUnpublished:
+ return QString( i18n( "Unpublished" ) );
+ default:
+ return QString( i18n( "Unknown" ) );
+ }
+ }
+
+ KURL Settings::doiURL( const QString& doiText )
+ {
+ KURL result( doiText );
+ if ( result.isValid() )
+ return result;
+
+ result = KURL( QString( "http://dx.doi.org/%1" ).arg( doiText ) );
+ if ( result.isValid() )
+ return result;
+
+ return KURL();
+ }
+
+ bool Settings::kpsewhich( const QString& filename )
+ {
+ bool result = FALSE;
+ int counter = 0;
+
+ QWaitCondition waitCond;
+ QProcess kpsewhich;
+ kpsewhich.addArgument( "kpsewhich" );
+ kpsewhich.addArgument( filename );
+ if ( kpsewhich.start() )
+ {
+ qApp->processEvents();
+ while ( kpsewhich.isRunning() )
+ {
+ waitCond.wait( 250 );
+ qApp->processEvents();
+
+ counter++;
+ if ( counter > 50 )
+ kpsewhich.tryTerminate();
+ }
+
+ result = kpsewhich.exitStatus() == 0 && counter < 50;
+ }
+
+ return result;
+ }
+
+ KURL Settings::locateFile( const QString& filename, const QString& bibTeXFileName, QWidget *window )
+ {
+ QString _filename = filename;
+ QString userHome = QString( getenv( "HOME" ) );
+ if ( _filename.contains( "~/" ) && !userHome.isEmpty() ) _filename = _filename.replace( "~/", userHome.append( "/" ) );
+
+ KURL url( _filename );
+ if ( url.isValid() && ( !url.isLocalFile() || KIO::NetAccess::exists( url, TRUE, window ) ) )
+ return url;
+
+ if ( bibTeXFileName != QString::null )
+ {
+ QString path = KURL( bibTeXFileName ).directory( FALSE, FALSE );
+ url = KURL( path + "/" + _filename );
+ if ( url.isValid() && KIO::NetAccess::exists( url, TRUE, window ) )
+ return url;
+ }
+
+ Settings* settings = self( NULL );
+ for ( QStringList::Iterator it = settings->editing_DocumentSearchPaths.begin(); it != settings->editing_DocumentSearchPaths.end(); ++it )
+ {
+ url = KURL( *it + "/" + _filename );
+ if ( url.isValid() && KIO::NetAccess::exists( url, TRUE, window ) )
+ return url;
+ }
+
+ return KURL();
+ }
+
+ KURL Settings::locateFile( const QString& filename, QWidget *window )
+ {
+ return locateFile( filename, currentBibTeXFile == NULL ? QString::null : currentBibTeXFile->fileName, window );
+ }
+
+ QString Settings::resolveLink( const QString& originalFilename, const QString& linkFilename )
+ {
+ if ( linkFilename[0] == '/' )
+ return linkFilename;
+ QFileInfo fiO( originalFilename );
+ QFileInfo fiL( fiO.dirPath( TRUE ) + "/" + linkFilename );
+ return fiL.absFilePath();
+ }
+
+ bool Settings::openUrl( const KURL& url, QWidget *parent )
+ {
+ QStringList args;
+ args << "xdg-open" << url.prettyURL();
+ QProcess proc( args, parent, "Settings::openUrl" );
+ return proc.start();
+ }
+
+
+#ifdef HAVE_YAZ
+ void Settings::z3950clearAll()
+ {
+ z3950_ServerList.clear();
+ }
+
+ void Settings::z3950loadDefault()
+ {
+ QString z3950serverConfigFile = locate( "appdata", "z3950-servers.cfg" );
+ if ( !z3950serverConfigFile.isEmpty() )
+ {
+ KConfig z3950serverConfig( z3950serverConfigFile, true, false );
+ QStringList serverList = z3950serverConfig.groupList();
+ for ( QStringList::ConstIterator it = serverList.begin(); it != serverList.end(); ++it )
+ if ( !z3950_ServerList.contains( *it ) )
+ {
+ z3950serverConfig.setGroup( *it );
+
+ Z3950Server server;
+ server.name = z3950serverConfig.readEntry( "Name" );
+ server.host = z3950serverConfig.readEntry( "Host" );
+ server.port = z3950serverConfig.readNumEntry( "Port", 2100 );
+ server.database = z3950serverConfig.readEntry( "Database" );
+ server.charset = z3950serverConfig.readEntry( "Charset" );
+ server.syntax = z3950serverConfig.readEntry( "Syntax" );
+ server.user = z3950serverConfig.readEntry( "User" );
+ server.password = z3950serverConfig.readEntry( "Password" );
+ server.locale = z3950serverConfig.readEntry( "Locale" );
+
+ z3950_ServerList[*it] = server;
+ }
+ }
+ }
+
+ void Settings::z3950loadUser( KConfig * config )
+ {
+ config->setGroup( "Z3950Server" );
+ int i = 0;
+ QString key = config->readEntry( QString( "Key%1" ).arg( i ) );
+ while ( key != QString::null )
+ {
+ Z3950Server server;
+ server.name = config->readEntry( QString( "Name%1" ).arg( i ) );
+ server.host = config->readEntry( QString( "Host%1" ).arg( i ) );
+ server.port = config->readNumEntry( QString( "Port%1" ).arg( i ), 2100 );
+ server.database = config->readEntry( QString( "Database%1" ).arg( i ) );
+ server.charset = config->readEntry( QString( "Charset%1" ).arg( i ) );
+ server.syntax = config->readEntry( QString( "Syntax%1" ).arg( i ) );
+ server.user = config->readEntry( QString( "User%1" ).arg( i ) );
+ server.password = config->readEntry( QString( "Password%1" ).arg( i ) );
+ server.locale = config->readEntry( QString( "Locale%1" ).arg( i ) );
+ z3950_ServerList[key] = server;
+
+ ++i;
+ key = config->readEntry( QString( "Key%1" ).arg( i ) );
+ }
+ }
+
+ void Settings::z3950saveUser( KConfig *config )
+ {
+ config->deleteGroup( "Z3950Server" );
+ config->setGroup( "Z3950Server" );
+ int i = 0;
+
+ QString z3950serverConfigFile = locate( "appdata", "z3950-servers.cfg" );
+ if ( !z3950serverConfigFile.isEmpty() )
+ {
+ KConfig z3950serverConfig( z3950serverConfigFile, true, false );
+ for ( QMap<QString, Z3950Server>::Iterator it = z3950_ServerList.begin(); it != z3950_ServerList.end(); ++it )
+ {
+ bool notInDefault = !z3950serverConfig.hasGroup( it.key() );
+ if ( !notInDefault )
+ {
+ z3950serverConfig.setGroup( it.key() );
+ notInDefault = z3950serverConfig.readEntry( "Name", it.data().name ) != it.data().name || z3950serverConfig.readEntry( "Host", it.data().host ) != it.data().host || z3950serverConfig.readNumEntry( "Port", it.data().port ) != it.data().port || z3950serverConfig.readEntry( "Database", it.data().database ) != it.data().database || z3950serverConfig.readEntry( "Charset", it.data().charset ) != it.data().charset || z3950serverConfig.readEntry( "Syntax", it.data().syntax ) != it.data().syntax || z3950serverConfig.readEntry( "User", it.data().user ) != it.data().user || z3950serverConfig.readEntry( "Password", it.data().password ) != it.data().password || z3950serverConfig.readEntry( "Locale", it.data().locale ) != it.data().locale || z3950serverConfig.readEntry( "User", it.data().user ) != it.data().user;
+ }
+
+ if ( notInDefault )
+ {
+ config->writeEntry( QString( "Key%1" ).arg( i ), it.key() );
+ config->writeEntry( QString( "Name%1" ).arg( i ), it.data().name );
+ config->writeEntry( QString( "Host%1" ).arg( i ), it.data().host );
+ config->writeEntry( QString( "Port%1" ).arg( i ), it.data().port );
+ config->writeEntry( QString( "Database%1" ).arg( i ), it.data().database );
+ config->writeEntry( QString( "Charset%1" ).arg( i ), it.data().charset );
+ config->writeEntry( QString( "Syntax%1" ).arg( i ), it.data().syntax );
+ config->writeEntry( QString( "User%1" ).arg( i ), it.data().user );
+ config->writeEntry( QString( "Password%1" ).arg( i ), it.data().password );
+ config->writeEntry( QString( "Locale%1" ).arg( i ), it.data().locale );
+ ++i;
+ }
+ }
+ }
+ }
+
+#endif // HAVE_YAZ
+
+ /** Create backup of file as specified in fileIO_NumberOfBackups */
+ bool Settings::createBackup( const KURL &url, QWidget *window )
+ {
+ QString basename = url.prettyURL();
+
+ qDebug( "Making %i backups of URL %s", fileIO_NumberOfBackups, basename.latin1() );
+
+ for ( int i = fileIO_NumberOfBackups; i > 2; --i )
+ {
+ KURL backupN( basename + "~" + QString::number( i ) );
+ KURL backupNmm( basename + "~" + QString::number( i - 1 ) );
+ if ( KIO::NetAccess::exists( backupNmm, true, window ) )
+ {
+ if ( !KIO::NetAccess::file_copy( backupNmm, backupN, -1, true, false, false ) )
+ return false;
+ }
+ }
+
+ if ( fileIO_NumberOfBackups >= 2 )
+ {
+ KURL backupN( basename + "~2" );
+ KURL backupNmm( basename + "~" );
+ if ( KIO::NetAccess::exists( backupNmm, true, window ) )
+ {
+ if ( !KIO::NetAccess::file_copy( backupNmm, backupN, -1, true, false, false ) )
+ return false;
+ }
+ }
+ if ( fileIO_NumberOfBackups >= 1 )
+ {
+ KURL backupN( basename + "~" );
+ KURL backupNmm( basename );
+ if ( KIO::NetAccess::exists( backupNmm, true, window ) )
+ {
+ if ( !KIO::NetAccess::file_copy( backupNmm, backupN, -1, true, false, false ) )
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+}
diff --git a/src/settings.h b/src/settings.h
new file mode 100644
index 0000000..ff8275b
--- /dev/null
+++ b/src/settings.h
@@ -0,0 +1,205 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstringlist.h>
+
+#include <kcompletion.h>
+
+#include <file.h>
+#include <fieldlineedit.h>
+#include <fileexporterbibtex.h>
+#include <fileexporterexternal.h>
+#include <entryfield.h>
+#include <entry.h>
+
+class KConfig;
+class KStandardDirs;
+class KURL;
+class QString;
+class QRegExp;
+class QChar;
+class QFont;
+
+namespace KBibTeX
+{
+ class Settings
+ {
+ public:
+ struct SearchURL
+ {
+ QString description;
+ QString url;
+ bool includeAuthor;
+ };
+
+ struct UserDefinedInputFields
+ {
+ QString name;
+ QString label;
+ FieldLineEdit::InputType inputType;
+ };
+
+ static Settings* self( BibTeX::File *bibtexFile = NULL );
+
+ void load( KConfig * config );
+ void save( KConfig * config );
+
+ static QString fieldTypeToI18NString( const BibTeX::EntryField::FieldType fieldType );
+ static QString entryTypeToI18NString( const BibTeX::Entry::EntryType entryType );
+
+ static KURL doiURL( const QString& doiText );
+ static bool kpsewhich( const QString& filename );
+ static KURL locateFile( const QString& filename, const QString& bibTeXFileName = QString::null, QWidget *window = NULL );
+ KURL locateFile( const QString& filename, QWidget *window = NULL );
+ static QString resolveLink( const QString& originalFilename, const QString& linkFilename );
+ static bool openUrl( const KURL& url, QWidget *parent );
+
+#ifdef HAVE_YAZ
+ void z3950clearAll();
+ void z3950loadDefault();
+ void z3950loadUser( KConfig * config );
+ void z3950saveUser( KConfig *config );
+ typedef struct Z3950Server_
+ {
+ QString charset, database, host, locale, name, syntax, user, password;
+ int port;
+ } Z3950Server;
+ QMap<QString, Z3950Server> z3950_ServerList;
+#endif // HAVE_YAZ
+
+ enum DragAction {COPYREFERENCE = 1, COPYBIBTEX = 2};
+
+ // FileIO section
+ QString fileIO_Encoding;
+ QString fileIO_ExportLanguage;
+ QString fileIO_ExportBibliographyStyle;
+ QChar fileIO_BibtexStringOpenDelimiter;
+ QChar fileIO_BibtexStringCloseDelimiter;
+ BibTeX::FileExporterBibTeX::KeywordCasing fileIO_KeywordCasing;
+ BibTeX::FileExporterExternal::Exporter fileIO_ExporterHTML;
+ bool fileIO_EmbedFiles;
+ bool fileIO_EnclosingCurlyBrackets;
+ bool fileIO_useBibUtils;
+ QString fileIO_bib2db5BasePath;
+ QString fileIO_bib2db5ClassPath;
+ int fileIO_NumberOfBackups;
+
+ bool updateBib2Db5ClassPath( const QString& newBasePath, bool testOnly = false );
+
+ // Editing section
+ bool editing_SearchBarClearField;
+ bool editing_EnableAllFields;
+ int editing_MainListDoubleClickAction;
+ int editing_MainListSortingColumn;
+ int editing_MainListSortingOrder;
+ QStringList editing_FilterHistory;
+ bool editing_ShowMacros;
+ bool editing_ShowComments;
+ QValueList<int> editing_MainListColumnsWidth;
+ QValueList<int> editing_MainListColumnsIndex;
+ QValueList<int> editing_HorSplitterSizes;
+ QValueList<int> editing_VertSplitterSizes;
+ QFont editing_SpecialFont;
+ bool editing_UseSpecialFont;
+ bool editing_FirstNameFirst;
+ QStringList editing_DocumentSearchPaths;
+ DragAction editing_DragAction;
+ int editing_findDuplicatesSensitivity;
+
+ // SearchURLs section
+ QValueList<SearchURL*> searchURLs;
+
+ // UserDefinedInputFields section
+ QValueList<UserDefinedInputFields*> userDefinedInputFields;
+
+ // External section
+ QString external_XSLTStylesheetHTML;
+ bool external_bibconvAvailable;
+ bool external_bibtex2htmlAvailable;
+ bool external_bib2xhtmlAvailable;
+ bool external_latex2rtfAvailable;
+ bool external_xml2bibAvailable;
+ bool external_end2xmlAvailable;
+ bool external_ris2xmlAvailable;
+
+ // Id Suggestions
+ QStringList idSuggestions_formatStrList;
+ int idSuggestions_default;
+ bool idSuggestions_forceDefault;
+ QStringList idSuggestions_smallWords;
+
+ // Auto-completion for user fields (non-persistant)
+ void addToCompletion( BibTeX::File *file );
+ void addToCompletion( BibTeX::Element *element );
+ void addToCompletion( BibTeX::Value *value, BibTeX::EntryField::FieldType fieldType );
+ KCompletion* completion( BibTeX::EntryField::FieldType fieldType );
+ KCompletion* completionMacro;
+
+ // Keyword list
+ QStringList keyword_GlobalList;
+
+ // Online Database Search;
+ int webQuery_LastEngine;
+ QString webQuery_LastSearchTerm;
+ int webQuery_LastNumberOfResults;
+ bool webQuery_ImportAll;
+
+ // Current BibTeX file
+ BibTeX::File *currentBibTeXFile;
+
+ void restoreDefaultSearchURLs();
+
+ QString detectLyXInPipe();
+
+ // web query history/default values
+ QString getWebQueryDefault( const QString &key );
+ void setWebQueryDefault( const QString &key, const QString& value );
+
+ // characters that do match this regexp are
+ // not allowed in entry ids or macro keys
+ static const QRegExp noIdChars;
+
+ /** Create backup of file as specified in fileIO_NumberOfBackups */
+ bool createBackup( const KURL &url, QWidget *window = NULL );
+
+ private:
+ static Settings* staticSettings;
+ KCompletion **m_completion;
+ static QStringList m_lyxRcFileNames;
+
+ QMap<QString, QString> m_webQueryDefaults;
+
+ Settings();
+ ~Settings();
+
+ bool checkExternalToolAvailable( const QString &binary );
+ void checkExternalToolsAvailable();
+
+ int completionFieldTypeToIndex( BibTeX::EntryField::FieldType fieldType );
+ };
+}
+
+#endif
diff --git a/src/settingsdlg.cpp b/src/settingsdlg.cpp
new file mode 100644
index 0000000..938dc6b
--- /dev/null
+++ b/src/settingsdlg.cpp
@@ -0,0 +1,137 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+#include <qlayout.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <settingsfileio.h>
+#include <settingsediting.h>
+#include <settingssearchurl.h>
+#include <settingsidsuggestions.h>
+#include <settingskeyword.h>
+#include <settingsuserdefinedinput.h>
+#ifdef HAVE_YAZ
+#include <settingsz3950.h>
+#endif // HAVE_YAZ
+#include "settingsdlg.h"
+
+namespace KBibTeX
+{
+ SettingsDlg::SettingsDlg( QWidget *parent, const char *name )
+ : KDialogBase( Tabbed, i18n( "Configure" ), Ok | Apply | Cancel, Ok, parent, name, true )
+ {
+ QFrame * page = addPage( i18n( "&Editing" ) );
+ QVBoxLayout *layout = new QVBoxLayout( page, 0, spacingHint() );
+ m_editing = new SettingsEditing( page );
+ layout->addWidget( m_editing );
+ connect( m_editing, SIGNAL( configChanged() ), this, SLOT( slotConfigChanged() ) );
+
+ page = addPage( i18n( "&File Open&&Save" ) );
+ layout = new QVBoxLayout( page, 0, spacingHint() );
+ m_fileIO = new SettingsFileIO( page );
+ layout->addWidget( m_fileIO );
+ connect( m_fileIO, SIGNAL( configChanged() ), this, SLOT( slotConfigChanged() ) );
+
+ page = addPage( i18n( "&Search URLs" ) );
+ layout = new QVBoxLayout( page, 0, spacingHint() );
+ m_searchURL = new SettingsSearchURL( page );
+ layout->addWidget( m_searchURL );
+ connect( m_searchURL, SIGNAL( configChanged() ), this, SLOT( slotConfigChanged() ) );
+
+ page = addPage( i18n( "Global &Keywords" ), QString::null, SmallIcon( "package" ) );
+ layout = new QVBoxLayout( page, 0, spacingHint() );
+ m_keyword = new SettingsKeyword( page );
+ layout->addWidget( m_keyword );
+ connect( m_keyword, SIGNAL( configChanged() ), this, SLOT( slotConfigChanged() ) );
+
+ page = addPage( i18n( "Id Suggestions" ) );
+ layout = new QVBoxLayout( page, 0, spacingHint() );
+ m_idSuggestions = new SettingsIdSuggestions( page );
+ layout->addWidget( m_idSuggestions );
+ connect( m_idSuggestions, SIGNAL( configChanged() ), this, SLOT( slotConfigChanged() ) );
+
+ page = addPage( i18n( "User Defined Fields" ) );
+ layout = new QVBoxLayout( page, 0, spacingHint() );
+ m_userDefinedInput = new SettingsUserDefinedInput( page );
+ layout->addWidget( m_userDefinedInput );
+ connect( m_userDefinedInput, SIGNAL( configChanged() ), this, SLOT( slotConfigChanged() ) );
+
+#ifdef HAVE_YAZ
+ page = addPage( i18n( "Z39.50" ) );
+ layout = new QVBoxLayout( page, 0, spacingHint() );
+ m_z3950config = new SettingsZ3950( page );
+ layout->addWidget( m_z3950config );
+ connect( m_z3950config, SIGNAL( configChanged() ), this, SLOT( slotConfigChanged() ) );
+#endif // HAVE_YAZ
+
+ connect( this, SIGNAL( applyClicked() ), SLOT( slotApplySettings() ) );
+ }
+
+
+ SettingsDlg::~SettingsDlg()
+ {
+ // nothing
+ }
+
+ int SettingsDlg::exec()
+ {
+ m_fileIO->readData();
+ m_editing->readData();
+ m_searchURL->readData();
+ m_keyword->readData();
+ m_idSuggestions->readData();
+ m_userDefinedInput->readData();
+#ifdef HAVE_YAZ
+ m_z3950config->readData();
+#endif // HAVE_YAZ
+ enableButton( Apply, FALSE );
+
+ return KDialogBase::exec();
+ }
+
+ void SettingsDlg::slotConfigChanged()
+ {
+ enableButton( Apply, TRUE );
+ }
+
+ void SettingsDlg::slotApplySettings()
+ {
+ m_fileIO->applyData();
+ m_editing->applyData();
+ m_searchURL->applyData();
+ m_keyword->applyData();
+ m_idSuggestions->applyData();
+ m_userDefinedInput->applyData();
+#ifdef HAVE_YAZ
+ m_z3950config->applyData();
+#endif // HAVE_YAZ
+ enableButton( Apply, FALSE );
+ }
+
+ void SettingsDlg::accept()
+ {
+ slotApplySettings();
+ KDialogBase::accept();
+ }
+}
+
+#include "settingsdlg.moc"
diff --git a/src/settingsdlg.h b/src/settingsdlg.h
new file mode 100644
index 0000000..e256349
--- /dev/null
+++ b/src/settingsdlg.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef SETTINGSDLG_H
+#define SETTINGSDLG_H
+
+#include <kdialogbase.h>
+
+namespace KBibTeX
+{
+ class SettingsFileIO;
+ class SettingsEditing;
+ class SettingsSearchURL;
+ class SettingsKeyword;
+ class SettingsIdSuggestions;
+ class SettingsUserDefinedInput;
+#ifdef HAVE_YAZ
+ class SettingsZ3950;
+#endif // HAVE_YAZ
+
+ class SettingsDlg : public KDialogBase
+ {
+ Q_OBJECT
+ public:
+ SettingsDlg( QWidget *parent = 0, const char *name = "SETTINGsdlg" );
+
+ ~SettingsDlg();
+
+ public slots:
+ virtual int exec();
+
+ protected slots:
+ void slotConfigChanged();
+ void slotApplySettings();
+ virtual void accept();
+
+ private:
+ SettingsFileIO *m_fileIO;
+ SettingsEditing *m_editing;
+ SettingsSearchURL *m_searchURL;
+ SettingsKeyword *m_keyword;
+ SettingsIdSuggestions *m_idSuggestions;
+ SettingsUserDefinedInput *m_userDefinedInput;
+#ifdef HAVE_YAZ
+ SettingsZ3950 *m_z3950config;
+#endif // HAVE_YAZ
+ };
+}
+
+#endif
diff --git a/src/settingsediting.cpp b/src/settingsediting.cpp
new file mode 100644
index 0000000..e5c71fc
--- /dev/null
+++ b/src/settingsediting.cpp
@@ -0,0 +1,331 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qdir.h>
+#include <qheader.h>
+#include <qcombobox.h>
+#include <qslider.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qgroupbox.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+
+#include <kpushbutton.h>
+#include <kdirselectdialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <kfontdialog.h>
+#include <kurlcompletion.h>
+
+#include <documentlistview.h>
+#include "settingsediting.h"
+
+namespace KBibTeX
+{
+ const QChar SettingsEditing::pathListSeparator = QChar( ';' );
+
+ SettingsEditingPaths::SettingsEditingPaths( QStringList& pathList, QWidget*parent, const char *name )
+ : QWidget( parent, name ), m_pathList( pathList )
+ {
+ QGridLayout *layout = new QGridLayout( this, 5, 3, 0, KDialog::spacingHint() );
+ setMinimumWidth( 480 );
+
+ QLabel *label = new QLabel( i18n( "Path to add:" ), this );
+ layout->addWidget( label, 0, 0 );
+ m_urlRequesterNewPath = new KURLRequester( this );
+ m_urlRequesterNewPath->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+ m_urlRequesterNewPath->completionObject()->setDir( QDir::currentDirPath() );
+ label->setBuddy( m_urlRequesterNewPath );
+ layout->addWidget( m_urlRequesterNewPath, 1, 0 );
+ QToolTip::add( m_urlRequesterNewPath->button(), i18n( "Select a path to add" ) );
+ m_pushButtonAddDir = new KPushButton( i18n( "Add" ), this );
+ m_pushButtonAddDir->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ m_pushButtonAddDir->setEnabled( FALSE );
+ QToolTip::add( m_pushButtonAddDir, i18n( "Add chosen path to list" ) );
+ layout->addWidget( m_pushButtonAddDir, 1, 2 );
+
+ label = new QLabel( i18n( "List of paths:" ), this );
+ layout->addWidget( label, 2, 0 );
+ m_listViewPathList = new KListView( this );
+ m_listViewPathList->addColumn( i18n( "Path" ) );
+ m_listViewPathList->header()->setClickEnabled( false );
+ m_listViewPathList->setFullWidth( true );
+ label->setBuddy( m_listViewPathList );
+ layout->addMultiCellWidget( m_listViewPathList, 3, 4, 0, 1 );
+ m_pushButtonDelDir = new KPushButton( i18n( "Delete" ), this );
+ layout->addWidget( m_pushButtonDelDir, 3, 2 );
+ m_pushButtonDelDir->setEnabled( FALSE );
+ m_pushButtonDelDir->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ QToolTip::add( m_pushButtonDelDir, i18n( "Remove selected path from list" ) );
+
+ layout->setRowStretch( 4, 1 );
+ layout->setColStretch( 0, 1 );
+
+ connect( m_urlRequesterNewPath, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ connect( m_urlRequesterNewPath, SIGNAL( urlSelected( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ connect( m_pushButtonAddDir, SIGNAL( clicked() ), this, SLOT( slotAddDir() ) );
+ connect( m_listViewPathList, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) );
+ connect( m_pushButtonDelDir, SIGNAL( clicked() ), this, SLOT( slotDelDir() ) );
+
+ for ( QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it )
+ new QListViewItem( m_listViewPathList, *it );
+ }
+
+ bool SettingsEditingPaths::execute( QWidget *parent, QStringList &pathList )
+ {
+ KDialogBase *dlg = new KDialogBase( parent, "SettingsEditingPathsDialog", true, i18n( "Edit Document Search Paths" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, false );
+ SettingsEditingPaths *sep = new SettingsEditingPaths( pathList, dlg, "SettingsEditingPaths" );
+ dlg->setMainWidget( sep );
+ connect( dlg, SIGNAL( apply() ), sep, SLOT( slotApply() ) );
+ connect( dlg, SIGNAL( okClicked() ), sep, SLOT( slotApply() ) );
+
+ bool result = dlg->exec() == QDialog::Accepted;
+ delete dlg;
+
+ return result;
+ }
+
+ void SettingsEditingPaths::slotApply()
+ {
+ m_pathList.clear();
+ QListViewItem *item = m_listViewPathList->firstChild();
+ while ( item != NULL )
+ {
+ m_pathList.append( item->text( 0 ) );
+ item = item->nextSibling();
+ }
+ }
+
+ void SettingsEditingPaths::slotTextChanged( const QString&text )
+ {
+ QDir pathObj( text );
+ m_pushButtonAddDir->setEnabled( pathObj.exists() && pathObj.isReadable() );
+ }
+
+ void SettingsEditingPaths::slotAddDir()
+ {
+ QString path = m_urlRequesterNewPath->lineEdit()->text();
+ QDir pathObj( path );
+ if ( pathObj.exists() && pathObj.isReadable() )
+ {
+ QListViewItem *item = new KListViewItem( m_listViewPathList, path );
+ m_listViewPathList->ensureItemVisible( item );
+ m_listViewPathList->setSelected( item, TRUE );
+ slotSelectionChanged();
+ }
+ else
+ KMessageBox::error( this, QString( i18n( "Folder '%1' does not exist or is not readable." ) ).arg( path ) );
+ }
+
+ void SettingsEditingPaths::slotSelectionChanged()
+ {
+ m_pushButtonDelDir->setEnabled( m_listViewPathList->selectedItem() != NULL );
+ }
+
+ void SettingsEditingPaths::slotDelDir()
+ {
+ m_listViewPathList->takeItem( m_listViewPathList->selectedItem() );
+ slotSelectionChanged();
+ }
+
+ SettingsEditing::SettingsEditing( QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_findDuplicatesSensitivityMin( 3 ), m_findDuplicatesSensitivityMax( 13 )
+ {
+ QGroupBox * group = NULL;
+ QVBoxLayout *layout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ group = new QGroupBox( 2, Qt::Horizontal, i18n( "Main List" ), this );
+ layout->addWidget( group );
+ QLabel *label = new QLabel( i18n( "&Sorting:" ), group );
+ m_comboBoxSortingColumn = new QComboBox( FALSE, group );
+ m_comboBoxSortingColumn->insertItem( i18n( "Element Type" ) );
+ m_comboBoxSortingColumn->insertItem( i18n( "Entry Id" ) );
+ for ( int i = 0; i <= ( int ) BibTeX::EntryField::ftYear - ( int ) BibTeX::EntryField::ftAbstract; i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType )( i + ( int ) BibTeX::EntryField::ftAbstract );
+ QString label = Settings::fieldTypeToI18NString( fieldType );
+ m_comboBoxSortingColumn->insertItem( label );
+ }
+ label->setBuddy( m_comboBoxSortingColumn );
+
+ label = new QLabel( i18n( "So&rting order:" ), group );
+ m_comboBoxSortingOrder = new QComboBox( FALSE, group );
+ m_comboBoxSortingOrder->insertItem( i18n( "Ascending" ) );
+ m_comboBoxSortingOrder->insertItem( i18n( "Descending" ) );
+ label->setBuddy( m_comboBoxSortingOrder );
+
+ label = new QLabel( i18n( "&Double click action:" ), group );
+ m_comboBoxDoubleClickAction = new QComboBox( FALSE, group );
+ m_comboBoxDoubleClickAction->insertItem( i18n( "Edit element" ) );
+ m_comboBoxDoubleClickAction->insertItem( i18n( "Open document" ) );
+ label->setBuddy( m_comboBoxDoubleClickAction );
+
+ label = new QLabel( i18n( "On dragging with mouse:" ), group );
+ m_comboBoxDragAction = new QComboBox( FALSE, group );
+ m_comboBoxDragAction->insertItem( i18n( "Copy reference (\\cite{...})" ) );
+ m_comboBoxDragAction->insertItem( i18n( "Copy BibTeX text (@article{...})" ) );
+ label->setBuddy( m_comboBoxDragAction );
+
+ group = new QGroupBox( 1, Qt::Vertical, i18n( "Entry Editing" ), this );
+ layout->addWidget( group );
+ m_checkBoxEnableAllFields = new QCheckBox( i18n( "Enable all &fields for editing" ), group );
+
+ group = new QGroupBox( 1, Qt::Vertical, i18n( "Search Bar" ), this );
+ layout->addWidget( group );
+ m_checkBoxSearchBarClearField = new QCheckBox( i18n( "Reset field filter when changing filter text" ), group );
+
+ group = new QGroupBox( 2, Qt::Horizontal, i18n( "Presentation" ), this );
+ layout->addWidget( group );
+ m_checkBoxUseSpecialFont = new QCheckBox( i18n( "Use special &font" ), group );
+ m_pushButtonSpecialFont = new QPushButton( group );
+ label = new QLabel( i18n( "Author and editor names:" ), group );
+ m_comboBoxNameOrder = new QComboBox( group );
+ label->setBuddy( m_comboBoxNameOrder );
+ m_comboBoxNameOrder->insertItem( i18n( "John Doe" ) );
+ m_comboBoxNameOrder->insertItem( i18n( "Doe, John" ) );
+ QToolTip::add( m_comboBoxNameOrder, i18n( "Show names as 'John Doe' instead of 'Doe, John'" ) );
+ QWhatsThis::add( m_comboBoxNameOrder, i18n( "Show names as 'John Doe' instead of 'Doe, John'.\n\nTakes only effect after the next start of KBibTeX." ) );
+
+ group = new QGroupBox( 1, Qt::Vertical, i18n( "Document Search Paths" ), this );
+ layout->addWidget( group );
+ KPushButton *btnSelectDocumentSearchPath = new KPushButton( SmallIcon( "fileopen" ), i18n( "Edit Search Paths" ), group );
+
+ group = new QGroupBox( 1, Qt::Vertical, i18n( "Find Duplicates" ), this );
+ layout->addWidget( group );
+ label = new QLabel( i18n( "Sensitivity:" ), group );
+ QWidget *spacer = new QWidget( group );
+ spacer->setFixedSize( KDialog::spacingHint() * 3, KDialog::spacingHint() );
+ QLabel *label2 = new QLabel( i18n( "Low" ), group );
+ m_sliderBarFindDuplicatesSensitivity = new QSlider( Qt::Horizontal, group );
+ m_sliderBarFindDuplicatesSensitivity->setMinValue( m_findDuplicatesSensitivityMin );
+ m_sliderBarFindDuplicatesSensitivity->setMaxValue( m_findDuplicatesSensitivityMax );
+ m_sliderBarFindDuplicatesSensitivity->setLineStep( 1 );
+ m_sliderBarFindDuplicatesSensitivity->setPageStep( 5 );
+ label->setBuddy( m_sliderBarFindDuplicatesSensitivity );
+ label2 = new QLabel( i18n( "High" ), group );
+
+ layout->addStretch();
+
+ connect( m_checkBoxSearchBarClearField, SIGNAL( toggled( bool ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_checkBoxEnableAllFields, SIGNAL( toggled( bool ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxDoubleClickAction, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxDragAction, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxSortingColumn, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxSortingOrder, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_pushButtonSpecialFont, SIGNAL( clicked() ), this, SLOT( slotSelectSpecialFont() ) );
+ connect( m_checkBoxUseSpecialFont, SIGNAL( toggled( bool ) ), m_pushButtonSpecialFont, SLOT( setEnabled( bool ) ) );
+ connect( m_checkBoxUseSpecialFont, SIGNAL( toggled( bool ) ), this, SLOT( slotConfigChanged() ) );
+ connect( btnSelectDocumentSearchPath, SIGNAL( clicked() ), this, SLOT( slotSelectDocumentSearchPath() ) );
+ }
+
+
+ SettingsEditing::~SettingsEditing()
+ {
+ // nothing
+ }
+
+ void SettingsEditing::applyData()
+ {
+ Settings * settings = Settings::self();
+
+ settings->editing_SearchBarClearField = m_checkBoxSearchBarClearField->isChecked();
+ settings->editing_EnableAllFields = m_checkBoxEnableAllFields->isChecked();
+ settings->editing_MainListSortingColumn = m_comboBoxSortingColumn->currentItem();
+ settings->editing_MainListSortingOrder = m_comboBoxSortingOrder->currentItem() == 0 ? 1 : -1;
+ settings->editing_MainListDoubleClickAction = m_comboBoxDoubleClickAction->currentItem();
+ settings->editing_DragAction = m_comboBoxDragAction->currentItem() == 0 ? Settings::COPYREFERENCE : Settings::COPYBIBTEX;
+
+ settings->editing_UseSpecialFont = m_checkBoxUseSpecialFont->isChecked();
+ settings->editing_SpecialFont = m_specialFont;
+
+ settings->editing_FirstNameFirst = m_comboBoxNameOrder->currentItem() == 0;
+
+ settings->editing_DocumentSearchPaths.clear();
+ for ( QStringList::Iterator it = m_documentSearchPaths.begin(); it != m_documentSearchPaths.end(); ++it )
+ settings->editing_DocumentSearchPaths.append( *it );
+
+ settings->editing_findDuplicatesSensitivity = ( m_findDuplicatesSensitivityMin + m_findDuplicatesSensitivityMax ) - m_sliderBarFindDuplicatesSensitivity->value();
+ }
+
+ void SettingsEditing::readData()
+ {
+ Settings * settings = Settings::self();
+
+ m_checkBoxSearchBarClearField->setChecked( settings->editing_SearchBarClearField );
+ m_checkBoxEnableAllFields->setChecked( settings->editing_EnableAllFields );
+ m_comboBoxSortingColumn->setCurrentItem( settings->editing_MainListSortingColumn );
+ m_comboBoxSortingOrder->setCurrentItem( settings->editing_MainListSortingOrder == 1 ? 0 : 1 );
+ m_comboBoxDoubleClickAction->setCurrentItem( settings->editing_MainListDoubleClickAction );
+ m_comboBoxDragAction->setCurrentItem( settings->editing_DragAction == Settings::COPYREFERENCE ? 0 : 1 );
+
+ m_checkBoxUseSpecialFont->setChecked( settings->editing_UseSpecialFont );
+ m_specialFont = settings->editing_SpecialFont;
+ updateFontData();
+ m_pushButtonSpecialFont->setEnabled( m_checkBoxUseSpecialFont->isChecked() );
+
+ m_comboBoxNameOrder->setCurrentItem( settings->editing_FirstNameFirst ? 0 : 1 );
+
+ m_documentSearchPaths.clear();
+ for ( QStringList::Iterator it = settings->editing_DocumentSearchPaths.begin(); it != settings->editing_DocumentSearchPaths.end(); ++it )
+ m_documentSearchPaths.append( *it );
+
+ m_sliderBarFindDuplicatesSensitivity->setValue(( m_findDuplicatesSensitivityMin + m_findDuplicatesSensitivityMax ) - settings->editing_findDuplicatesSensitivity );
+ }
+
+ void SettingsEditing::slotConfigChanged()
+ {
+ emit configChanged();
+ }
+
+ void SettingsEditing::slotSelectSpecialFont()
+ {
+ int result = KFontDialog::getFont( m_specialFont );
+ if ( result == KFontDialog::Accepted )
+ {
+ updateFontData();
+ emit configChanged();
+ }
+ }
+
+ void SettingsEditing::slotSelectDocumentSearchPath()
+ {
+ if ( editPathList( m_documentSearchPaths ) )
+ slotConfigChanged();
+ }
+
+ void SettingsEditing::updateFontData()
+ {
+ m_pushButtonSpecialFont->setText( m_specialFont.family() );
+ m_pushButtonSpecialFont->setFont( m_specialFont );
+ }
+
+ bool SettingsEditing::editPathList( QStringList &pathList )
+ {
+ return SettingsEditingPaths::execute( this, pathList );
+ }
+}
+
+#include "settingsediting.moc"
diff --git a/src/settingsediting.h b/src/settingsediting.h
new file mode 100644
index 0000000..b938f4e
--- /dev/null
+++ b/src/settingsediting.h
@@ -0,0 +1,100 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef SETTINGSEDITING_H
+#define SETTINGSEDITING_H
+
+#include <qwidget.h>
+
+class QCheckBox;
+class QPushButton;
+class QComboBox;
+class QSlider;
+
+class KPushButton;
+class KURLRequester;
+class KListView;
+
+namespace KBibTeX
+{
+ class SettingsEditingPaths: public QWidget
+ {
+ Q_OBJECT
+ protected:
+ SettingsEditingPaths( QStringList& pathList, QWidget*parent = 0, const char *name = 0 );
+
+ public:
+ static bool execute( QWidget *parent, QStringList &pathList );
+
+ public slots:
+ void slotApply();
+ void slotTextChanged( const QString&text );
+ void slotAddDir();
+ void slotSelectionChanged();
+ void slotDelDir();
+
+ private:
+ QStringList &m_pathList;
+ KURLRequester *m_urlRequesterNewPath;
+ KPushButton *m_pushButtonAddDir;
+ KListView *m_listViewPathList;
+ KPushButton *m_pushButtonDelDir;
+ };
+
+ class SettingsEditing : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SettingsEditing( QWidget *parent = 0, const char *name = 0 );
+ ~SettingsEditing();
+
+ void applyData();
+ void readData();
+
+ signals:
+ void configChanged();
+
+ protected slots:
+ void slotConfigChanged();
+ void slotSelectSpecialFont();
+ void slotSelectDocumentSearchPath();
+
+ private:
+ QCheckBox *m_checkBoxEnableAllFields;
+ QCheckBox *m_checkBoxSearchBarClearField;
+ QComboBox *m_comboBoxSortingColumn;
+ QComboBox *m_comboBoxSortingOrder;
+ QComboBox *m_comboBoxDoubleClickAction;
+ QComboBox *m_comboBoxDragAction;
+ QCheckBox *m_checkBoxUseSpecialFont;
+ QPushButton *m_pushButtonSpecialFont;
+ QFont m_specialFont;
+ QComboBox *m_comboBoxNameOrder;
+ QStringList m_documentSearchPaths;
+ static const QChar pathListSeparator;
+ QSlider *m_sliderBarFindDuplicatesSensitivity;
+
+ void updateFontData();
+ bool editPathList( QStringList &pathList );
+
+ const int m_findDuplicatesSensitivityMin, m_findDuplicatesSensitivityMax;
+ };
+}
+
+#endif // SETTINGSEDITING_H
diff --git a/src/settingsfileio.cpp b/src/settingsfileio.cpp
new file mode 100644
index 0000000..7cceedf
--- /dev/null
+++ b/src/settingsfileio.cpp
@@ -0,0 +1,341 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+#include <qhbuttongroup.h>
+#include <qbuttongroup.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <kdirselectdialog.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+
+#include <settings.h>
+#include <file.h>
+#include "settingsfileio.h"
+
+namespace KBibTeX
+{
+ static const QString encodingList[] =
+ {
+ "LaTeX", "437", "500", "500V1", "850", "851", "852", "855", "856", "857", "860", "861", "862", "863", "864", "865", "866", "866NAV", "869", "874", "904", "1026", "1046", "1047", "8859_1", "8859_2", "8859_3", "8859_4", "8859_5", "8859_6", "8859_7", "8859_8", "8859_9", "10646-1:1993", "10646-1:1993/UCS4/", "ANSI_X3.4-1968", "ANSI_X3.4-1986", "ANSI_X3.4", "ANSI_X3.110-1983", "ANSI_X3.110", "ARABIC", "ARABIC7", "ARMSCII-8", "ASCII", "ASMO-708", "ASMO_449", "BALTIC", "BIG-5", "BIG-FIVE", "BIG5-HKSCS", "BIG5", "BIG5HKSCS", "BIGFIVE", "BRF", "BS_4730", "CA", "CN-BIG5", "CN-GB", "CN", "CP-AR", "CP-GR", "CP-HU", "CP037", "CP038", "CP273", "CP274", "CP275", "CP278", "CP280", "CP281", "CP282", "CP284", "CP285", "CP290", "CP297", "CP367", "CP420", "CP423", "CP424", "CP437", "CP500", "CP737", "CP775", "CP803", "CP813", "CP819", "CP850", "CP851", "CP852", "CP855", "CP856", "CP857", "CP860", "CP861", "CP862", "CP863", "CP864", "CP865", "CP866", "CP866NAV", "CP868", "CP869", "CP870", "CP871", "CP874", "CP875", "CP880", "CP891", "CP901", "CP902", "CP903", "CP904", "CP905", "CP912", "CP915", "CP916", "CP918", "CP920", "CP921", "CP922", "CP930", "CP932", "CP933", "CP935", "CP936", "CP937", "CP939", "CP949", "CP950", "CP1004", "CP1008", "CP1025", "CP1026", "CP1046", "CP1047", "CP1070", "CP1079", "CP1081", "CP1084", "CP1089", "CP1097", "CP1112", "CP1122", "CP1123", "CP1124", "CP1125", "CP1129", "CP1130", "CP1132", "CP1133", "CP1137", "CP1140", "CP1141", "CP1142", "CP1143", "CP1144", "CP1145", "CP1146", "CP1147", "CP1148", "CP1149", "CP1153", "CP1154", "CP1155", "CP1156", "CP1157", "CP1158", "CP1160", "CP1161", "CP1162", "CP1163", "CP1164", "CP1166", "CP1167", "CP1250", "CP1251", "CP1252", "CP1253", "CP1254", "CP1255", "CP1256", "CP1257", "CP1258", "CP1361", "CP1364", "CP1371", "CP1388", "CP1390", "CP1399", "CP4517", "CP4899", "CP4909", "CP4971", "CP5347", "CP9030", "CP9066", "CP9448", "CP10007", "CP12712", "CP16804", "CPIBM861", "CSA7-1", "CSA7-2", "CSASCII", "CSA_T500-1983", "CSA_T500", "CSA_Z243.4-1985-1", "CSA_Z243.4-1985-2", "CSA_Z243.419851", "CSA_Z243.419852", "CSDECMCS", "CSEBCDICATDE", "CSEBCDICATDEA", "CSEBCDICCAFR", "CSEBCDICDKNO", "CSEBCDICDKNOA", "CSEBCDICES", "CSEBCDICESA", "CSEBCDICESS", "CSEBCDICFISE", "CSEBCDICFISEA", "CSEBCDICFR", "CSEBCDICIT", "CSEBCDICPT", "CSEBCDICUK", "CSEBCDICUS", "CSEUCKR", "CSEUCPKDFMTJAPANESE", "CSGB2312", "CSHPROMAN8", "CSIBM037", "CSIBM038", "CSIBM273", "CSIBM274", "CSIBM275", "CSIBM277", "CSIBM278", "CSIBM280", "CSIBM281", "CSIBM284", "CSIBM285", "CSIBM290", "CSIBM297", "CSIBM420", "CSIBM423", "CSIBM424", "CSIBM500", "CSIBM803", "CSIBM851", "CSIBM855", "CSIBM856", "CSIBM857", "CSIBM860", "CSIBM863", "CSIBM864", "CSIBM865", "CSIBM866", "CSIBM868", "CSIBM869", "CSIBM870", "CSIBM871", "CSIBM880", "CSIBM891", "CSIBM901", "CSIBM902", "CSIBM903", "CSIBM904", "CSIBM905", "CSIBM918", "CSIBM921", "CSIBM922", "CSIBM930", "CSIBM932", "CSIBM933", "CSIBM935", "CSIBM937", "CSIBM939", "CSIBM943", "CSIBM1008", "CSIBM1025", "CSIBM1026", "CSIBM1097", "CSIBM1112", "CSIBM1122", "CSIBM1123", "CSIBM1124", "CSIBM1129", "CSIBM1130", "CSIBM1132", "CSIBM1133", "CSIBM1137", "CSIBM1140", "CSIBM1141", "CSIBM1142", "CSIBM1143", "CSIBM1144", "CSIBM1145", "CSIBM1146", "CSIBM1147", "CSIBM1148", "CSIBM1149", "CSIBM1153", "CSIBM1154", "CSIBM1155", "CSIBM1156", "CSIBM1157", "CSIBM1158", "CSIBM1160", "CSIBM1161", "CSIBM1163", "CSIBM1164", "CSIBM1166", "CSIBM1167", "CSIBM1364", "CSIBM1371", "CSIBM1388", "CSIBM1390", "CSIBM1399", "CSIBM4517", "CSIBM4899", "CSIBM4909", "CSIBM4971", "CSIBM5347", "CSIBM9030", "CSIBM9066", "CSIBM9448", "CSIBM12712", "CSIBM16804", "CSIBM11621162", "CSISO4UNITEDKINGDOM", "CSISO10SWEDISH", "CSISO11SWEDISHFORNAMES", "CSISO14JISC6220RO", "CSISO15ITALIAN", "CSISO16PORTUGESE", "CSISO17SPANISH", "CSISO18GREEK7OLD", "CSISO19LATINGREEK", "CSISO21GERMAN", "CSISO25FRENCH", "CSISO27LATINGREEK1", "CSISO49INIS", "CSISO50INIS8", "CSISO51INISCYRILLIC", "CSISO58GB1988", "CSISO60DANISHNORWEGIAN", "CSISO60NORWEGIAN1", "CSISO61NORWEGIAN2", "CSISO69FRENCH", "CSISO84PORTUGUESE2", "CSISO85SPANISH2", "CSISO86HUNGARIAN", "CSISO88GREEK7", "CSISO89ASMO449", "CSISO90", "CSISO92JISC62991984B", "CSISO99NAPLPS", "CSISO103T618BIT", "CSISO111ECMACYRILLIC", "CSISO121CANADIAN1", "CSISO122CANADIAN2", "CSISO139CSN369103", "CSISO141JUSIB1002", "CSISO143IECP271", "CSISO150", "CSISO150GREEKCCITT", "CSISO151CUBA", "CSISO153GOST1976874", "CSISO646DANISH", "CSISO2022CN", "CSISO2022JP", "CSISO2022JP2", "CSISO2022KR", "CSISO2033", "CSISO5427CYRILLIC", "CSISO5427CYRILLIC1981", "CSISO5428GREEK", "CSISO10367BOX", "CSISOLATIN1", "CSISOLATIN2", "CSISOLATIN3", "CSISOLATIN4", "CSISOLATIN5", "CSISOLATIN6", "CSISOLATINARABIC", "CSISOLATINCYRILLIC", "CSISOLATINGREEK", "CSISOLATINHEBREW", "CSKOI8R", "CSKSC5636", "CSMACINTOSH", "CSNATSDANO", "CSNATSSEFI", "CSN_369103", "CSPC8CODEPAGE437", "CSPC775BALTIC", "CSPC850MULTILINGUAL", "CSPC862LATINHEBREW", "CSPCP852", "CSSHIFTJIS", "CSUCS4", "CSUNICODE", "CSWINDOWS31J", "CUBA", "CWI-2", "CWI", "CYRILLIC", "DE", "DEC-MCS", "DEC", "DECMCS", "DIN_66003", "DK", "DS2089", "DS_2089", "E13B", "EBCDIC-AT-DE-A", "EBCDIC-AT-DE", "EBCDIC-BE", "EBCDIC-BR", "EBCDIC-CA-FR", "EBCDIC-CP-AR1", "EBCDIC-CP-AR2", "EBCDIC-CP-BE", "EBCDIC-CP-CA", "EBCDIC-CP-CH", "EBCDIC-CP-DK", "EBCDIC-CP-ES", "EBCDIC-CP-FI", "EBCDIC-CP-FR", "EBCDIC-CP-GB", "EBCDIC-CP-GR", "EBCDIC-CP-HE", "EBCDIC-CP-IS", "EBCDIC-CP-IT", "EBCDIC-CP-NL", "EBCDIC-CP-NO", "EBCDIC-CP-ROECE", "EBCDIC-CP-SE", "EBCDIC-CP-TR", "EBCDIC-CP-US", "EBCDIC-CP-WT", "EBCDIC-CP-YU", "EBCDIC-CYRILLIC", "EBCDIC-DK-NO-A", "EBCDIC-DK-NO", "EBCDIC-ES-A", "EBCDIC-ES-S", "EBCDIC-ES", "EBCDIC-FI-SE-A", "EBCDIC-FI-SE", "EBCDIC-FR", "EBCDIC-GREEK", "EBCDIC-INT", "EBCDIC-INT1", "EBCDIC-IS-FRISS", "EBCDIC-IT", "EBCDIC-JP-E", "EBCDIC-JP-KANA", "EBCDIC-PT", "EBCDIC-UK", "EBCDIC-US", "EBCDICATDE", "EBCDICATDEA", "EBCDICCAFR", "EBCDICDKNO", "EBCDICDKNOA", "EBCDICES", "EBCDICESA", "EBCDICESS", "EBCDICFISE", "EBCDICFISEA", "EBCDICFR", "EBCDICISFRISS", "EBCDICIT", "EBCDICPT", "EBCDICUK", "EBCDICUS", "ECMA-114", "ECMA-118", "ECMA-128", "ECMA-CYRILLIC", "ECMACYRILLIC", "ELOT_928", "ES", "ES2", "EUC-CN", "EUC-JISX0213", "EUC-JP-MS", "EUC-JP", "EUC-KR", "EUC-TW", "EUCCN", "EUCJP-MS", "EUCJP-OPEN", "EUCJP-WIN", "EUCJP", "EUCKR", "EUCTW", "FI", "FR", "GB", "GB2312", "GB13000", "GB18030", "GBK", "GB_1988-80", "GB_198880", "GEORGIAN-ACADEMY", "GEORGIAN-PS", "GOST_19768-74", "GOST_19768", "GOST_1976874", "GREEK-CCITT", "GREEK", "GREEK7-OLD", "GREEK7", "GREEK7OLD", "GREEK8", "GREEKCCITT", "HEBREW", "HP-ROMAN8", "HPROMAN8", "HU", "IBM-803", "IBM-856", "IBM-901", "IBM-902", "IBM-921", "IBM-922", "IBM-930", "IBM-932", "IBM-933", "IBM-935", "IBM-937", "IBM-939", "IBM-943", "IBM-1008", "IBM-1025", "IBM-1046", "IBM-1047", "IBM-1097", "IBM-1112", "IBM-1122", "IBM-1123", "IBM-1124", "IBM-1129", "IBM-1130", "IBM-1132", "IBM-1133", "IBM-1137", "IBM-1140", "IBM-1141", "IBM-1142", "IBM-1143", "IBM-1144", "IBM-1145", "IBM-1146", "IBM-1147", "IBM-1148", "IBM-1149", "IBM-1153", "IBM-1154", "IBM-1155", "IBM-1156", "IBM-1157", "IBM-1158", "IBM-1160", "IBM-1161", "IBM-1162", "IBM-1163", "IBM-1164", "IBM-1166", "IBM-1167", "IBM-1364", "IBM-1371", "IBM-1388", "IBM-1390", "IBM-1399", "IBM-4517", "IBM-4899", "IBM-4909", "IBM-4971", "IBM-5347", "IBM-9030", "IBM-9066", "IBM-9448", "IBM-12712", "IBM-16804", "IBM037", "IBM038", "IBM256", "IBM273", "IBM274", "IBM275", "IBM277", "IBM278", "IBM280", "IBM281", "IBM284", "IBM285", "IBM290", "IBM297", "IBM367", "IBM420", "IBM423", "IBM424", "IBM437", "IBM500", "IBM775", "IBM803", "IBM813", "IBM819", "IBM848", "IBM850", "IBM851", "IBM852", "IBM855", "IBM856", "IBM857", "IBM860", "IBM861", "IBM862", "IBM863", "IBM864", "IBM865", "IBM866", "IBM866NAV", "IBM868", "IBM869", "IBM870", "IBM871", "IBM874", "IBM875", "IBM880", "IBM891", "IBM901", "IBM902", "IBM903", "IBM904", "IBM905", "IBM912", "IBM915", "IBM916", "IBM918", "IBM920", "IBM921", "IBM922", "IBM930", "IBM932", "IBM933", "IBM935", "IBM937", "IBM939", "IBM943", "IBM1004", "IBM1008", "IBM1025", "IBM1026", "IBM1046", "IBM1047", "IBM1089", "IBM1097", "IBM1112", "IBM1122", "IBM1123", "IBM1124", "IBM1129", "IBM1130", "IBM1132", "IBM1133", "IBM1137", "IBM1140", "IBM1141", "IBM1142", "IBM1143", "IBM1144", "IBM1145", "IBM1146", "IBM1147", "IBM1148", "IBM1149", "IBM1153", "IBM1154", "IBM1155", "IBM1156", "IBM1157", "IBM1158", "IBM1160", "IBM1161", "IBM1162", "IBM1163", "IBM1164", "IBM1166", "IBM1167", "IBM1364", "IBM1371", "IBM1388", "IBM1390", "IBM1399", "IBM4517", "IBM4899", "IBM4909", "IBM4971", "IBM5347", "IBM9030", "IBM9066", "IBM9448", "IBM12712", "IBM16804", "IEC_P27-1", "IEC_P271", "INIS-8", "INIS-CYRILLIC", "INIS", "INIS8", "INISCYRILLIC", "ISIRI-3342", "ISIRI3342", "ISO-2022-CN-EXT", "ISO-2022-CN", "ISO-2022-JP-2", "ISO-2022-JP-3", "ISO-2022-JP", "ISO-2022-KR", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "ISO-10646", "ISO-10646/UCS2/", "ISO-10646/UCS4/", "ISO-10646/UTF-8/", "ISO-10646/UTF8/", "ISO-CELTIC", "ISO-IR-4", "ISO-IR-6", "ISO-IR-8-1", "ISO-IR-9-1", "ISO-IR-10", "ISO-IR-11", "ISO-IR-14", "ISO-IR-15", "ISO-IR-16", "ISO-IR-17", "ISO-IR-18", "ISO-IR-19", "ISO-IR-21", "ISO-IR-25", "ISO-IR-27", "ISO-IR-37", "ISO-IR-49", "ISO-IR-50", "ISO-IR-51", "ISO-IR-54", "ISO-IR-55", "ISO-IR-57", "ISO-IR-60", "ISO-IR-61", "ISO-IR-69", "ISO-IR-84", "ISO-IR-85", "ISO-IR-86", "ISO-IR-88", "ISO-IR-89", "ISO-IR-90", "ISO-IR-92", "ISO-IR-98", "ISO-IR-99", "ISO-IR-100", "ISO-IR-101", "ISO-IR-103", "ISO-IR-109", "ISO-IR-110", "ISO-IR-111", "ISO-IR-121", "ISO-IR-122", "ISO-IR-126", "ISO-IR-127", "ISO-IR-138", "ISO-IR-139", "ISO-IR-141", "ISO-IR-143", "ISO-IR-144", "ISO-IR-148", "ISO-IR-150", "ISO-IR-151", "ISO-IR-153", "ISO-IR-155", "ISO-IR-156", "ISO-IR-157", "ISO-IR-166", "ISO-IR-179", "ISO-IR-193", "ISO-IR-197", "ISO-IR-199", "ISO-IR-203", "ISO-IR-209", "ISO-IR-226", "ISO/TR_11548-1/", "ISO646-CA", "ISO646-CA2", "ISO646-CN", "ISO646-CU", "ISO646-DE", "ISO646-DK", "ISO646-ES", "ISO646-ES2", "ISO646-FI", "ISO646-FR", "ISO646-FR1", "ISO646-GB", "ISO646-HU", "ISO646-IT", "ISO646-JP-OCR-B", "ISO646-JP", "ISO646-KR", "ISO646-NO", "ISO646-NO2", "ISO646-PT", "ISO646-PT2", "ISO646-SE", "ISO646-SE2", "ISO646-US", "ISO646-YU", "ISO2022CN", "ISO2022CNEXT", "ISO2022JP", "ISO2022JP2", "ISO2022KR", "ISO6937", "ISO8859-1", "ISO8859-2", "ISO8859-3", "ISO8859-4", "ISO8859-5", "ISO8859-6", "ISO8859-7", "ISO8859-8", "ISO8859-9", "ISO8859-10", "ISO8859-11", "ISO8859-13", "ISO8859-14", "ISO8859-15", "ISO8859-16", "ISO11548-1", "ISO88591", "ISO88592", "ISO88593", "ISO88594", "ISO88595", "ISO88596", "ISO88597", "ISO88598", "ISO88599", "ISO885910", "ISO885911", "ISO885913", "ISO885914", "ISO885915", "ISO885916", "ISO_646.IRV:1991", "ISO_2033-1983", "ISO_2033", "ISO_5427-EXT", "ISO_5427", "ISO_5427:1981", "ISO_5427EXT", "ISO_5428", "ISO_5428:1980", "ISO_6937-2", "ISO_6937-2:1983", "ISO_6937", "ISO_6937:1992", "ISO_8859-1", "ISO_8859-1:1987", "ISO_8859-2", "ISO_8859-2:1987", "ISO_8859-3", "ISO_8859-3:1988", "ISO_8859-4", "ISO_8859-4:1988", "ISO_8859-5", "ISO_8859-5:1988", "ISO_8859-6", "ISO_8859-6:1987", "ISO_8859-7", "ISO_8859-7:1987", "ISO_8859-7:2003", "ISO_8859-8", "ISO_8859-8:1988", "ISO_8859-9", "ISO_8859-9:1989", "ISO_8859-10", "ISO_8859-10:1992", "ISO_8859-14", "ISO_8859-14:1998", "ISO_8859-15", "ISO_8859-15:1998", "ISO_8859-16", "ISO_8859-16:2001", "ISO_9036", "ISO_10367-BOX", "ISO_10367BOX", "ISO_11548-1", "ISO_69372", "IT", "JIS_C6220-1969-RO", "JIS_C6229-1984-B", "JIS_C62201969RO", "JIS_C62291984B", "JOHAB", "JP-OCR-B", "JP", "JS", "JUS_I.B1.002", "KOI-7", "KOI-8", "KOI8-R", "KOI8-T", "KOI8-U", "KOI8", "KOI8R", "KOI8U", "KSC5636", "L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8", "L10", "LATIN-9", "LATIN-GREEK-1", "LATIN-GREEK", "LATIN1", "LATIN2", "LATIN3", "LATIN4", "LATIN5", "LATIN6", "LATIN7", "LATIN8", "LATIN10", "LATINGREEK", "LATINGREEK1", "MAC-CYRILLIC", "MAC-IS", "MAC-SAMI", "MAC-UK", "MAC", "MACCYRILLIC", "MACINTOSH", "MACIS", "MACUK", "MACUKRAINIAN", "MIK", "MS-ANSI", "MS-ARAB", "MS-CYRL", "MS-EE", "MS-GREEK", "MS-HEBR", "MS-MAC-CYRILLIC", "MS-TURK", "MS932", "MS936", "MSCP949", "MSCP1361", "MSMACCYRILLIC", "MSZ_7795.3", "MS_KANJI", "NAPLPS", "NATS-DANO", "NATS-SEFI", "NATSDANO", "NATSSEFI", "NC_NC0010", "NC_NC00-10", "NC_NC00-10:81", "NF_Z_62-010", "NF_Z_62-010_(1973)", "NF_Z_62-010_1973", "NF_Z_62010", "NF_Z_62010_1973", "NO", "NO2", "NS_4551-1", "NS_4551-2", "NS_45511", "NS_45512", "OS2LATIN1", "OSF00010001", "OSF00010002", "OSF00010003", "OSF00010004", "OSF00010005", "OSF00010006", "OSF00010007", "OSF00010008", "OSF00010009", "OSF0001000A", "OSF00010020", "OSF00010100", "OSF00010101", "OSF00010102", "OSF00010104", "OSF00010105", "OSF00010106", "OSF00030010", "OSF0004000A", "OSF0005000A", "OSF05010001", "OSF100201A4", "OSF100201A8", "OSF100201B5", "OSF100201F4", "OSF100203B5", "OSF1002011C", "OSF1002011D", "OSF1002035D", "OSF1002035E", "OSF1002035F", "OSF1002036B", "OSF1002037B", "OSF10010001", "OSF10020025", "OSF10020111", "OSF10020115", "OSF10020116", "OSF10020118", "OSF10020122", "OSF10020129", "OSF10020352", "OSF10020354", "OSF10020357", "OSF10020359", "OSF10020360", "OSF10020364", "OSF10020365", "OSF10020366", "OSF10020367", "OSF10020370", "OSF10020387", "OSF10020388", "OSF10020396", "OSF10020402", "OSF10020417", "PT", "PT2", "PT154", "R8", "RK1048", "ROMAN8", "RUSCII", "SE", "SE2", "SEN_850200_B", "SEN_850200_C", "SHIFT-JIS", "SHIFT_JIS", "SHIFT_JISX0213", "SJIS-OPEN", "SJIS-WIN", "SJIS", "SS636127", "STRK1048-2002", "ST_SEV_358-88", "T.61-8BIT", "T.61", "T.618BIT", "TCVN-5712", "TCVN", "TCVN5712-1", "TCVN5712-1:1993", "TIS-620", "TIS620-0", "TIS620.2529-1", "TIS620.2533-0", "TIS620", "TS-5881", "TSCII", "UCS-2", "UCS-2BE", "UCS-2LE", "UCS-4", "UCS-4BE", "UCS-4LE", "UCS2", "UCS4", "UHC", "UJIS", "UK", "UNICODE", "UNICODEBIG", "UNICODELITTLE", "US-ASCII", "US", "UTF-7", "UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE", "UTF-32", "UTF-32BE", "UTF-32LE", "UTF7", "UTF8", "UTF16", "UTF16BE", "UTF16LE", "UTF32", "UTF32BE", "UTF32LE", "VISCII", "WCHAR_T", "WIN-SAMI-2", "WINBALTRIM", "WINDOWS-31J", "WINDOWS-874", "WINDOWS-936", "WINDOWS-1250", "WINDOWS-1251", "WINDOWS-1252", "WINDOWS-1253", "WINDOWS-1254", "WINDOWS-1255", "WINDOWS-1256", "WINDOWS-1257", "WINDOWS-1258", "WINSAMI2", "WS2", "YU"
+ };
+ static const QString LanguagesI18N = i18n( "English|German|French|Spanish|Swedish" );
+ static const QString Languages[] =
+ {
+ "english", "german", "french", "spanish", "swedish"
+ };
+ static const QString BibliographyStyles = i18n( "plain|achemso (American Chemical Society)|alpha|unsrt|abbrv|acm (Association of Computing Machinery)|apacite|apalike|authordate|ieeetr|natbib|siam" );
+ static const QString StringDelimiters = "\"...\"|{...}|(...)";
+ static const QString KeywordCasing = "@inproceedings|@Inproceedings|@InProceedings|@INPROCEEDINGS";
+
+ SettingsFileIO::SettingsFileIO( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+ {
+ setupGUI();
+ }
+
+ SettingsFileIO::~SettingsFileIO()
+ {
+ // nothing
+ }
+
+ void SettingsFileIO::applyData()
+ {
+ Settings * settings = Settings::self();
+
+ settings->fileIO_Encoding = m_comboBoxEncoding->currentText().lower();
+ QString delimiters = m_comboBoxStringDelimiters->currentText();
+ settings->fileIO_BibtexStringOpenDelimiter = delimiters.at( 0 ) ;
+ settings->fileIO_BibtexStringCloseDelimiter = delimiters.at( 4 ) ;
+
+ switch ( m_comboBoxKeywordCasing->currentItem() )
+ {
+ case 0:
+ settings->fileIO_KeywordCasing = BibTeX::FileExporterBibTeX::kcLowerCase;
+ break;
+ case 1:
+ settings->fileIO_KeywordCasing = BibTeX::FileExporterBibTeX::kcInitialCapital;
+ break;
+ case 3:
+ settings->fileIO_KeywordCasing = BibTeX::FileExporterBibTeX::kcCapital;
+ break;
+ default:
+ settings->fileIO_KeywordCasing = BibTeX::FileExporterBibTeX::kcCamelCase;
+ }
+
+ settings->fileIO_EnclosingCurlyBrackets = m_checkBoxProtectCasing->isChecked();
+
+ settings->fileIO_ExportLanguage = Languages[ m_comboBoxLanguage->currentItem()];
+ settings->fileIO_ExportBibliographyStyle = m_comboBoxBibliographyStyle->currentText().section( ' ', 0, 0 );
+
+ if ( m_comboBoxExportSystemHTML->isEnabled() )
+ {
+ QString text = m_comboBoxExportSystemHTML->currentText();
+ if ( text == "bib2xhtml" )
+ settings->fileIO_ExporterHTML = BibTeX::FileExporterExternal::exporterBib2XHTML;
+ else if ( text == "bibtex2html" )
+ settings->fileIO_ExporterHTML = BibTeX::FileExporterExternal::exporterBibTeX2HTML;
+ else if ( text == "bibconv" )
+ settings->fileIO_ExporterHTML = BibTeX::FileExporterExternal::exporterBibConv;
+ else
+ settings->fileIO_ExporterHTML = BibTeX::FileExporterExternal::exporterXSLT;
+ }
+ else
+ settings->fileIO_ExporterHTML = BibTeX::FileExporterExternal::exporterNone;
+
+ settings->fileIO_EmbedFiles = m_checkBoxEmbedFiles->isChecked();
+
+ settings->updateBib2Db5ClassPath( m_bib2db5BasePath );
+
+ if ( m_checkBoxUseBibUtils->isEnabled() )
+ settings->fileIO_useBibUtils = m_checkBoxUseBibUtils->isChecked();
+
+ settings->fileIO_NumberOfBackups = m_spinBoxNumberOfBackups->value();
+ }
+
+ void SettingsFileIO::readData()
+ {
+ Settings * settings = Settings::self();
+
+ m_comboBoxEncoding->setCurrentItem( 0 );
+ for ( int i = sizeof( encodingList ) / sizeof( encodingList[0] ) - 1; i >= 0; --i )
+ if ( encodingList[i].lower() == settings->fileIO_Encoding )
+ {
+ m_comboBoxEncoding->setCurrentItem( i );
+ break;
+ }
+
+ QString toMatch = QString( settings->fileIO_BibtexStringOpenDelimiter ).append( "..." ).append( settings->fileIO_BibtexStringCloseDelimiter );
+ QStringList delimiterList = QStringList::split( '|', StringDelimiters );
+ int i = 0;
+ for ( QStringList::Iterator it = delimiterList.begin(); it != delimiterList.end(); ++it, i++ )
+ if (( *it ) == toMatch )
+ {
+ m_comboBoxStringDelimiters->setCurrentItem( i );
+ break;
+ }
+
+ switch ( settings->fileIO_KeywordCasing )
+ {
+ case BibTeX::FileExporterBibTeX::kcLowerCase:
+ m_comboBoxKeywordCasing->setCurrentItem( 0 );
+ break;
+ case BibTeX::FileExporterBibTeX::kcInitialCapital:
+ m_comboBoxKeywordCasing->setCurrentItem( 1 );
+ break;
+ case BibTeX::FileExporterBibTeX::kcCapital:
+ m_comboBoxKeywordCasing->setCurrentItem( 3 );
+ break;
+ default:
+ m_comboBoxKeywordCasing->setCurrentItem( 2 );
+ }
+
+ m_checkBoxProtectCasing->setChecked( settings->fileIO_EnclosingCurlyBrackets );
+
+ for ( int i = 0; i < m_comboBoxLanguage->count(); i++ )
+ if ( Languages[ i ] == settings->fileIO_ExportLanguage )
+ {
+ m_comboBoxLanguage->setCurrentItem( i );
+ break;
+ }
+
+ m_comboBoxBibliographyStyle->setCurrentText( settings->fileIO_ExportBibliographyStyle );
+
+ m_comboBoxExportSystemHTML->clear();
+
+ m_comboBoxExportSystemHTML->insertItem( i18n( "XSLT Stylesheet" ) );
+ if ( settings->fileIO_ExporterHTML == BibTeX::FileExporterExternal::exporterXSLT )
+ m_comboBoxExportSystemHTML->setCurrentItem( m_comboBoxExportSystemHTML->count() - 1 );
+ if ( settings->external_bib2xhtmlAvailable )
+ {
+ m_comboBoxExportSystemHTML->insertItem( "bib2xhtml" );
+ if ( settings->fileIO_ExporterHTML == BibTeX::FileExporterExternal::exporterBib2XHTML )
+ m_comboBoxExportSystemHTML->setCurrentItem( m_comboBoxExportSystemHTML->count() - 1 );
+ }
+ if ( settings->external_bibtex2htmlAvailable )
+ {
+ m_comboBoxExportSystemHTML->insertItem( "bibtex2html" );
+ if ( settings->fileIO_ExporterHTML == BibTeX::FileExporterExternal::exporterBibTeX2HTML )
+ m_comboBoxExportSystemHTML->setCurrentItem( m_comboBoxExportSystemHTML->count() - 1 );
+ }
+ if ( settings->external_bibconvAvailable )
+ {
+ m_comboBoxExportSystemHTML->insertItem( "bibconv" );
+ if ( settings->fileIO_ExporterHTML == BibTeX::FileExporterExternal::exporterBibConv )
+ m_comboBoxExportSystemHTML->setCurrentItem( m_comboBoxExportSystemHTML->count() - 1 );
+ }
+
+ if ( m_comboBoxExportSystemHTML->count() == 0 )
+ {
+ m_comboBoxExportSystemHTML->insertItem( i18n( "No exporter available" ) );
+ m_comboBoxExportSystemHTML->setEnabled( FALSE );
+ }
+
+ m_checkBoxEmbedFiles->setChecked( settings->fileIO_EmbedFiles );
+
+ m_bib2db5BasePath = settings->fileIO_bib2db5BasePath;
+ m_lineeditBib2Db5Path->setText( m_bib2db5BasePath );
+
+ if ( m_checkBoxUseBibUtils->isEnabled() )
+ m_checkBoxUseBibUtils->setChecked( settings->fileIO_useBibUtils );
+
+ m_spinBoxNumberOfBackups->setValue( settings->fileIO_NumberOfBackups );
+ }
+
+ void SettingsFileIO::slotConfigChanged()
+ {
+ emit configChanged();
+ }
+
+ void SettingsFileIO::slotBib2db5BasePath()
+ {
+ KURL newPath = KDirSelectDialog::selectDirectory( m_bib2db5BasePath, true, this, i18n( "Path to the jar files for bib2db5" ) );
+ if ( !newPath.isEmpty() && newPath.isValid() && newPath.isLocalFile() )
+ {
+ m_bib2db5BasePath = newPath.directory() + QDir::separator() + newPath.fileName();
+ m_lineeditBib2Db5Path->setText( m_bib2db5BasePath );
+ slotCheckBib2Db5Path();
+ }
+ }
+
+ void SettingsFileIO::slotCheckBib2Db5Path()
+ {
+ if ( !Settings::self()->updateBib2Db5ClassPath( m_lineeditBib2Db5Path->text(), true ) )
+ {
+ KMessageBox::error( this, i18n( "To export DocBook5 bibliographies, the path to the jar file for bib2db5 has to be set first." ), i18n( "Invalid path for bib2db5" ) );
+ }
+ }
+
+ void SettingsFileIO::setupGUI()
+ {
+ QVBoxLayout * layout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QGroupBox *groupBox = new QGroupBox( 2, Horizontal, i18n( "BibTeX Import and Export" ), this );
+ layout->addWidget( groupBox );
+ QLabel *label = new QLabel( i18n( "&Encoding:" ), groupBox );
+ m_comboBoxEncoding = new QComboBox( groupBox );
+ label->setBuddy( m_comboBoxEncoding );
+ label = new QLabel( i18n( "Text &delimiters:" ), groupBox );
+ m_comboBoxStringDelimiters = new QComboBox( groupBox );
+ label->setBuddy( m_comboBoxStringDelimiters );
+ label = new QLabel( i18n( "Keyword casing:" ), groupBox );
+ m_comboBoxKeywordCasing = new QComboBox( groupBox );
+ label->setBuddy( m_comboBoxKeywordCasing );
+ label = new QLabel( i18n( "Protect title's casing:" ), groupBox );
+ m_checkBoxProtectCasing = new QCheckBox( i18n( "Put curly brackets around" ), groupBox );
+ QToolTip::add( m_checkBoxProtectCasing, i18n( "Put curly brackets around title and other selected fields." ) );
+ QWhatsThis::add( m_checkBoxProtectCasing, i18n( "Put curly brackets around title and other selected fields to protect them from case changes in certain BibTeX styles." ) );
+
+ groupBox = new QGroupBox( 2, Horizontal, i18n( "PDF, PostScript and Rich Text Format Export" ), this );
+ layout->addWidget( groupBox );
+ QWhatsThis::add( groupBox, i18n( "Select the layout of the resulting PDF, PostScript or Rich Text Format document when exporting a BibTeX file." ) );
+ label = new QLabel( i18n( "&Language:" ), groupBox );
+ m_comboBoxLanguage = new QComboBox( groupBox );
+ label->setBuddy( m_comboBoxLanguage );
+ label = new QLabel( i18n( "&Biblography style:" ), groupBox );
+ m_comboBoxBibliographyStyle = new QComboBox( TRUE, groupBox );
+ label->setBuddy( m_comboBoxBibliographyStyle );
+
+ groupBox = new QGroupBox( 1, Horizontal, i18n( "PDF Export" ), this );
+ layout->addWidget( groupBox );
+ m_checkBoxEmbedFiles = new QCheckBox( i18n( "Embed local files into PDF if possible" ), groupBox );
+ QWhatsThis::add( m_checkBoxEmbedFiles, i18n( "<qt>If checked, KBibTeX tries to embed all referenced files for the BibTeX entries into the exported PDF file.<br/>This requires that you have installed <tt>embedfile.sty</tt>.</qt>" ) );
+
+ groupBox = new QGroupBox( 2, Horizontal, i18n( "XML Export" ), this );
+ layout->addWidget( groupBox );
+ label->setBuddy( m_comboBoxEncoding );
+ label = new QLabel( i18n( "Path to the jar files for bib2db5:" ), groupBox );
+ QWidget *container = new QWidget( groupBox );
+ QBoxLayout *containerLayout = new QHBoxLayout( container, 0, KDialog::spacingHint() );
+ m_lineeditBib2Db5Path = new KLineEdit( container );
+ m_lineeditBib2Db5Path->setReadOnly( true );
+ containerLayout->addWidget( m_lineeditBib2Db5Path );
+ containerLayout->setStretchFactor( m_lineeditBib2Db5Path, 10 );
+ KPushButton *buttonBib2Db5 = new KPushButton( container );
+ label->setBuddy( buttonBib2Db5 );
+ containerLayout->addWidget( buttonBib2Db5 );
+ containerLayout->setStretchFactor( buttonBib2Db5, 1 );
+ buttonBib2Db5->setIconSet( QIconSet( SmallIcon( "folder_open" ) ) );
+ label->setBuddy( buttonBib2Db5 );
+ connect( buttonBib2Db5, SIGNAL( clicked() ), this, SLOT( slotBib2db5BasePath() ) );
+
+ groupBox = new QGroupBox( 2, Horizontal, i18n( "Export Systems" ), this );
+ layout->addWidget( groupBox );
+ label = new QLabel( i18n( "HTML:" ), groupBox );
+ m_comboBoxExportSystemHTML = new QComboBox( FALSE, groupBox );
+ label->setBuddy( m_comboBoxExportSystemHTML );
+
+ groupBox = new QGroupBox( 1, Horizontal, i18n( "BibUtils" ), this );
+ layout->addWidget( groupBox );
+ m_checkBoxUseBibUtils = new QCheckBox( i18n( "Always use BibUtils" ), groupBox );
+ QToolTip::add( m_checkBoxUseBibUtils, i18n( "If possible, use BibUtils to import and export alien bibliography." ) );
+ QWhatsThis::add( m_checkBoxUseBibUtils, i18n( "If possible, use BibUtils to import and export alien bibliography such as RIS.\nIf unchecked, prefer internal import and export library." ) );
+ /** command line tools from BibUtils must be available to enable this option */
+ m_checkBoxUseBibUtils->setEnabled( Settings::self()->external_xml2bibAvailable && Settings::self()->external_ris2xmlAvailable );
+
+ groupBox = new QGroupBox( 2, Horizontal, i18n( "Backups" ), this );
+ layout->addWidget( groupBox );
+ label = new QLabel( i18n( "Number of Backups:" ), groupBox );
+ m_spinBoxNumberOfBackups = new QSpinBox( 0, 15, 1, groupBox, "m_spinBoxNumberOfBackups" );
+ m_spinBoxNumberOfBackups->setSpecialValueText( "No backups" );
+ label->setBuddy( m_spinBoxNumberOfBackups );
+
+ layout->addStretch( 1 );
+
+ for ( unsigned int i = 0; i < sizeof( encodingList ) / sizeof( encodingList[0] ); ++i )
+ m_comboBoxEncoding->insertItem( encodingList[i] );
+
+ QStringList delimiterList = QStringList::split( '|', StringDelimiters );
+ m_comboBoxStringDelimiters->insertStringList( delimiterList );
+
+ QStringList keywordCasingList = QStringList::split( '|', KeywordCasing );
+ m_comboBoxKeywordCasing->insertStringList( keywordCasingList );
+
+ QStringList langList = QStringList::split( '|', LanguagesI18N );
+ m_comboBoxLanguage->insertStringList( langList );
+
+ QStringList bibList = QStringList::split( '|', BibliographyStyles );
+ bibList.sort();
+ m_comboBoxBibliographyStyle->insertStringList( bibList );
+
+ connect( m_comboBoxEncoding, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxStringDelimiters, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxKeywordCasing, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxLanguage, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxBibliographyStyle, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ connect( m_comboBoxExportSystemHTML, SIGNAL( activated( int ) ), this, SLOT( slotConfigChanged() ) );
+ }
+
+}
+#include "settingsfileio.moc"
diff --git a/src/settingsfileio.h b/src/settingsfileio.h
new file mode 100644
index 0000000..2697473
--- /dev/null
+++ b/src/settingsfileio.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef SETTINGSFILEIO_H
+#define SETTINGSFILEIO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+
+class QComboBox;
+class QCheckBox;
+class QSpinBox;
+class KLineEdit;
+
+namespace KBibTeX
+{
+ class SettingsFileIO : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SettingsFileIO( QWidget *parent = 0, const char *name = 0 );
+ ~SettingsFileIO();
+
+ void applyData();
+ void readData();
+
+ signals:
+ void configChanged();
+
+ protected slots:
+ void slotConfigChanged();
+ void slotBib2db5BasePath();
+ void slotCheckBib2Db5Path();
+
+ private:
+ QComboBox *m_comboBoxEncoding;
+ QComboBox *m_comboBoxStringDelimiters;
+ QComboBox *m_comboBoxKeywordCasing;
+ QCheckBox *m_checkBoxProtectCasing;
+ QComboBox *m_comboBoxLanguage;
+ QComboBox *m_comboBoxBibliographyStyle;
+ QCheckBox *m_checkBoxEmbedFiles;
+ QComboBox *m_comboBoxExportSystemHTML;
+ QCheckBox *m_checkBoxUseBibUtils;
+ KLineEdit *m_lineeditBib2Db5Path;
+ QString m_bib2db5BasePath;
+ QSpinBox *m_spinBoxNumberOfBackups;
+
+ void setupGUI();
+
+ };
+}
+
+#endif
diff --git a/src/settingsidsuggestions.cpp b/src/settingsidsuggestions.cpp
new file mode 100644
index 0000000..7d53327
--- /dev/null
+++ b/src/settingsidsuggestions.cpp
@@ -0,0 +1,400 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qtimer.h>
+#include <qvalidator.h>
+#include <qheader.h>
+#include <qlabel.h>
+
+#include <kinputdialog.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <klineedit.h>
+
+#include <idsuggestions.h>
+#include <idsuggestionswidget.h>
+#include <settings.h>
+#include <fileimporter.h>
+#include <fileimporterbibtex.h>
+#include "settingsidsuggestions.h"
+
+namespace KBibTeX
+{
+ QString SettingsIdSuggestions::exampleBibTeXEntry = "@Article{ dijkstra1983terminationdetect,\nauthor = {Edsger W. Dijkstra and W. H. J. Feijen and A. J. M. {van Gasteren}},\ntitle = {{Derivation of a Termination Detection Algorithm for Distributed Computations}},\njournal = {Information Processing Letters},\nvolume = 16,\nnumber = 5,\npages = {217--219},\nmonth = jun,\nyear = 1983\n}";
+
+ IdSuggestionsListViewItem::IdSuggestionsListViewItem( KListView *list, const QString& plainText, BibTeX::Entry *example ): KListViewItem( list ), m_original( plainText ), m_example( example )
+ {
+ KListViewItem::setText( 0, parse( plainText ) );
+ KListViewItem::setMultiLinesEnabled( TRUE );
+ }
+
+ IdSuggestionsListViewItem::IdSuggestionsListViewItem( KListView *list, KListViewItem *prev, const QString& plainText, BibTeX::Entry *example ): KListViewItem( list, prev ), m_original( plainText ), m_example( example )
+ {
+ KListViewItem::setText( 0, parse( plainText ) );
+ KListViewItem::setMultiLinesEnabled( TRUE );
+ }
+
+ void IdSuggestionsListViewItem::setText( int col, const QString& text )
+ {
+ if ( col == 0 )
+ KListViewItem::setText( 0, parse( text ) );
+ else
+ KListViewItem::setText( col, text );
+ }
+
+ int IdSuggestionsListViewItem::width( const QFontMetrics & fm, const QListView *, int c ) const
+ {
+ int max = 100;
+ QStringList lines = QStringList::split( '\n', text( c ) );
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
+ {
+ int w = fm.width( *it );
+ if ( w > max ) max = w;
+ }
+
+ return max + 36;
+ }
+
+ QString IdSuggestionsListViewItem::originalText() const
+ {
+ return m_original;
+ }
+
+ QString IdSuggestionsListViewItem::parse( const QString&plainText )
+ {
+ m_original = plainText;
+ QString result = IdSuggestions::formatStrToHuman( plainText );
+ if ( m_example != NULL )
+ {
+ result.append( QString( i18n( "\nExample: %1" ) ).arg( IdSuggestions::formatId( m_example, plainText ) ) );
+ }
+ return result;
+ }
+
+ SettingsIdSuggestions::SettingsIdSuggestions( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+ {
+ m_validator = new QRegExpValidator( QRegExp( "[^\\s]+" ), this );
+ setupGUI();
+
+ BibTeX::FileImporter *importer = new BibTeX::FileImporterBibTeX( false );
+ BibTeX::File *file = importer->load( exampleBibTeXEntry );
+ m_example = new BibTeX::Entry( dynamic_cast<BibTeX::Entry*>( *( file->begin() ) ) );
+ delete file;
+ delete importer;
+ }
+
+ SettingsIdSuggestions::~SettingsIdSuggestions()
+ {
+ delete m_example;
+ delete m_validator;
+ }
+
+ void SettingsIdSuggestions::applyData()
+ {
+ Settings * settings = Settings::self();
+
+ settings->idSuggestions_formatStrList.clear();
+ settings->idSuggestions_default = -1;
+ settings->idSuggestions_forceDefault = m_checkBoxForceDefault->isChecked();
+ int i = 0;
+ for ( QListViewItemIterator it( m_listIdSuggestions ); it.current(); ++i, ++it )
+ {
+ IdSuggestionsListViewItem *item = dynamic_cast<IdSuggestionsListViewItem*>( *it );
+ settings->idSuggestions_formatStrList.append( item->originalText() );
+ if ( item == m_defaultSuggestionItem )
+ settings->idSuggestions_default = i;
+ }
+ settings->idSuggestions_smallWords.clear();
+ for ( QListViewItemIterator it( m_listSmallWords ); it.current(); ++it )
+ settings->idSuggestions_smallWords << it.current()->text( 0 );
+ }
+
+ void SettingsIdSuggestions::readData()
+ {
+ Settings * settings = Settings::self();
+
+ IdSuggestionsListViewItem *prev = NULL;
+ m_listIdSuggestions->clear();
+ m_defaultSuggestionItem = NULL;
+ m_checkBoxForceDefault->setChecked( settings->idSuggestions_forceDefault );
+ m_checkBoxForceDefault->setEnabled( settings->idSuggestions_default >= 0 );
+ int i = 0;
+ for ( QStringList::ConstIterator it = settings->idSuggestions_formatStrList.begin(); it != settings->idSuggestions_formatStrList.end(); ++i, ++it )
+ {
+ prev = new IdSuggestionsListViewItem( m_listIdSuggestions, prev, *it, m_example );
+ prev->setPixmap( 0, SmallIcon( "filter" ) );
+ if ( i == settings->idSuggestions_default )
+ m_defaultSuggestionItem = prev;
+ }
+
+ if ( m_defaultSuggestionItem != NULL )
+ m_defaultSuggestionItem->setPixmap( 0, SmallIcon( "favorites" ) );
+
+ m_listSmallWords->clear();
+ for ( QStringList::ConstIterator it = settings->idSuggestions_smallWords.begin(); it != settings->idSuggestions_smallWords.end(); ++it )
+ new KListViewItem( m_listSmallWords, *it );
+ m_lineEditSmallWords->setText( "" );
+ slotListSmallWordsChanged();
+
+ updateGUI();
+ }
+
+ void SettingsIdSuggestions::slotConfigChanged()
+ {
+ emit configChanged();
+ }
+
+ void SettingsIdSuggestions::slotNewIdSuggestion()
+ {
+ IdSuggestionsListViewItem * item = new IdSuggestionsListViewItem( m_listIdSuggestions, "a|Y|T", m_example );
+ item->setPixmap( 0, SmallIcon( "filter" ) );
+ m_listIdSuggestions->setSelected( item, TRUE );
+ QTimer::singleShot( 100, this, SLOT( slotEditIdSuggestion() ) );
+ }
+
+ void SettingsIdSuggestions::slotEditIdSuggestion()
+ {
+ IdSuggestionsListViewItem * item = static_cast<IdSuggestionsListViewItem*>( m_listIdSuggestions->selectedItem() );
+ if ( item != NULL )
+ {
+ QString formatStr = item->originalText();
+ if ( IdSuggestionsWidget::execute( formatStr, this ) == QDialog::Accepted )
+ {
+ item->setText( 0, formatStr );
+ emit configChanged();
+ }
+ }
+ updateGUI();
+ }
+
+ void SettingsIdSuggestions::slotDeleteIdSuggestion()
+ {
+ IdSuggestionsListViewItem * item = static_cast<IdSuggestionsListViewItem*>( m_listIdSuggestions->selectedItem() );
+ if ( item != NULL )
+ {
+ if ( m_defaultSuggestionItem == item )
+ m_defaultSuggestionItem = NULL;
+ m_checkBoxForceDefault->setEnabled( m_defaultSuggestionItem != NULL );
+
+ delete item;
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsIdSuggestions::slotMoveUpIdSuggestion()
+ {
+ IdSuggestionsListViewItem * item = dynamic_cast<IdSuggestionsListViewItem*>( m_listIdSuggestions->selectedItem() );
+ if ( item != NULL && item -> itemAbove() != NULL )
+ {
+ IdSuggestionsListViewItem *itemAbove = dynamic_cast<IdSuggestionsListViewItem*>( item->itemAbove() );
+ QString text = item->originalText();
+ item->setText( 0, itemAbove->originalText( ) );
+ itemAbove->setText( 0, text );
+ m_listIdSuggestions->setCurrentItem( itemAbove );
+ m_listIdSuggestions->ensureItemVisible( itemAbove );
+
+ if ( m_defaultSuggestionItem == itemAbove )
+ {
+ itemAbove->setPixmap( 0, SmallIcon( "filter" ) );
+ m_defaultSuggestionItem = item;
+ }
+ else if ( m_defaultSuggestionItem == item )
+ {
+ item->setPixmap( 0, SmallIcon( "filter" ) );
+ m_defaultSuggestionItem = itemAbove;
+ }
+ if ( m_defaultSuggestionItem != NULL )
+ m_defaultSuggestionItem->setPixmap( 0, SmallIcon( "favorites" ) );
+ }
+ }
+
+ void SettingsIdSuggestions::slotMoveDownIdSuggestion()
+ {
+ IdSuggestionsListViewItem * item = dynamic_cast<IdSuggestionsListViewItem*>( m_listIdSuggestions->selectedItem() );
+ if ( item != NULL && item -> itemBelow() != NULL )
+ {
+ IdSuggestionsListViewItem *itemBelow = dynamic_cast<IdSuggestionsListViewItem*>( item->itemBelow() );
+ QString text = item->originalText();
+ item->setText( 0, itemBelow->originalText( ) );
+ itemBelow->setText( 0, text );
+ m_listIdSuggestions->setCurrentItem( itemBelow );
+ m_listIdSuggestions->ensureItemVisible( itemBelow );
+
+ if ( m_defaultSuggestionItem == itemBelow )
+ {
+ itemBelow->setPixmap( 0, SmallIcon( "filter" ) );
+ m_defaultSuggestionItem = item;
+ }
+ else if ( m_defaultSuggestionItem == item )
+ {
+ item->setPixmap( 0, SmallIcon( "filter" ) );
+ m_defaultSuggestionItem = itemBelow;
+ }
+ if ( m_defaultSuggestionItem != NULL )
+ m_defaultSuggestionItem->setPixmap( 0, SmallIcon( "favorites" ) );
+ }
+ }
+
+ void SettingsIdSuggestions::slotToggleDefault()
+ {
+ if ( m_defaultSuggestionItem != NULL )
+ m_defaultSuggestionItem->setPixmap( 0, SmallIcon( "filter" ) );
+
+ QListViewItem *item = m_listIdSuggestions->selectedItem();
+ if ( item == m_defaultSuggestionItem )
+ m_defaultSuggestionItem = NULL;
+ else
+ {
+ m_defaultSuggestionItem = item;
+ m_defaultSuggestionItem->setPixmap( 0, SmallIcon( "favorites" ) );
+ }
+ m_checkBoxForceDefault->setEnabled( m_defaultSuggestionItem != NULL );
+ }
+
+ void SettingsIdSuggestions::slotEditSmallWordsChanged( const QString &newWord )
+ {
+ bool result = !newWord.isEmpty();
+
+ for ( QListViewItemIterator it( m_listSmallWords ); result && it.current(); ++it )
+ result &= it.current()->text( 0 ) != newWord;
+
+ m_buttonAddSmallWord->setEnabled( result );
+ }
+
+ void SettingsIdSuggestions::slotAddSmallWord()
+ {
+ new KListViewItem( m_listSmallWords, m_lineEditSmallWords->text() );
+ m_lineEditSmallWords->setText( "" );
+ emit configChanged();
+ }
+
+ void SettingsIdSuggestions::slotDeleteSmallWord()
+ {
+ bool changed = false;
+ QListViewItemIterator it( m_listSmallWords, QListViewItemIterator::Selected );
+ while ( it.current() )
+ {
+ QListViewItem *cur = it.current();
+ ++it;
+ delete cur;
+ changed = true;
+ }
+
+ if ( changed )
+ emit configChanged();
+ }
+
+ void SettingsIdSuggestions::slotListSmallWordsChanged()
+ {
+ QListViewItemIterator it( m_listSmallWords, QListViewItemIterator::Selected );
+ m_buttonDeleteSmallWord->setEnabled( it.current() != NULL );
+ }
+
+ void SettingsIdSuggestions::updateGUI()
+ {
+ QListViewItem *item = m_listIdSuggestions->selectedItem();
+ bool selected = item != NULL;
+ m_buttonEditIdSuggestion->setEnabled( selected );
+ m_buttonDeleteIdSuggestion->setEnabled( selected );
+ m_buttonMoveDownIdSuggestion->setEnabled( selected && item->itemBelow() != NULL );
+ m_buttonMoveUpIdSuggestion->setEnabled( selected && item->itemAbove() != NULL );
+ m_buttonToggleDefault->setEnabled( selected );
+ }
+
+ void SettingsIdSuggestions::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 13, 2, 0, KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( 6, 2 );
+ gridLayout->setRowSpacing( 8, KDialog::spacingHint() );
+ gridLayout->setRowStretch( 12, 1 );
+ gridLayout->setColStretch( 0, 1 );
+
+ m_listIdSuggestions = new KListView( this );
+ m_listIdSuggestions->setSorting( -1, FALSE );
+ m_listIdSuggestions->addColumn( i18n( "Id Suggestions" ) );
+ m_listIdSuggestions->header()->setClickEnabled( FALSE );
+ m_listIdSuggestions->setFullWidth( true );
+ gridLayout->addMultiCellWidget( m_listIdSuggestions, 0, 6, 0, 0 );
+ connect( m_listIdSuggestions, SIGNAL( selectionChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_listIdSuggestions, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listIdSuggestions, SIGNAL( doubleClicked( QListViewItem*, const QPoint &, int ) ), this, SLOT( slotEditIdSuggestion() ) );
+
+ m_buttonNewIdSuggestion = new KPushButton( i18n( "id suggestion", "New" ), this );
+ m_buttonNewIdSuggestion->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ gridLayout->addWidget( m_buttonNewIdSuggestion, 0, 1 );
+ connect( m_buttonNewIdSuggestion, SIGNAL( clicked() ), this, SLOT( slotNewIdSuggestion() ) );
+ m_buttonEditIdSuggestion = new KPushButton( i18n( "id suggestion", "Edit" ), this );
+ m_buttonEditIdSuggestion->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ gridLayout->addWidget( m_buttonEditIdSuggestion, 1, 1 );
+ connect( m_buttonEditIdSuggestion, SIGNAL( clicked() ), this, SLOT( slotEditIdSuggestion() ) );
+ m_buttonDeleteIdSuggestion = new KPushButton( i18n( "id suggestion", "Delete" ), this );
+ m_buttonDeleteIdSuggestion->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ gridLayout->addWidget( m_buttonDeleteIdSuggestion, 2, 1 );
+ connect( m_buttonDeleteIdSuggestion, SIGNAL( clicked() ), this, SLOT( slotDeleteIdSuggestion() ) );
+ m_buttonMoveUpIdSuggestion = new KPushButton( i18n( "id suggestion", "Up" ), this );
+ m_buttonMoveUpIdSuggestion->setIconSet( QIconSet( SmallIcon( "up" ) ) );
+ gridLayout->addWidget( m_buttonMoveUpIdSuggestion, 3, 1 );
+ connect( m_buttonMoveUpIdSuggestion, SIGNAL( clicked() ), this, SLOT( slotMoveUpIdSuggestion() ) );
+ m_buttonMoveDownIdSuggestion = new KPushButton( i18n( "id suggestion", "Down" ), this );
+ m_buttonMoveDownIdSuggestion->setIconSet( QIconSet( SmallIcon( "down" ) ) );
+ gridLayout->addWidget( m_buttonMoveDownIdSuggestion, 4, 1 );
+ connect( m_buttonMoveDownIdSuggestion, SIGNAL( clicked() ), this, SLOT( slotMoveDownIdSuggestion() ) );
+ m_buttonToggleDefault = new KPushButton( i18n( "Toogle default" ), this );
+ m_buttonToggleDefault->setIconSet( QIconSet( SmallIcon( "favorites" ) ) );
+ gridLayout->addWidget( m_buttonToggleDefault, 5, 1 );
+ connect( m_buttonToggleDefault, SIGNAL( clicked() ), this, SLOT( slotToggleDefault() ) );
+
+ m_checkBoxForceDefault = new QCheckBox( i18n( "Use default id suggestion when editing new entries" ), this );
+ gridLayout->addMultiCellWidget( m_checkBoxForceDefault, 7, 7, 0, 1 );
+
+ QLabel *label = new QLabel( i18n( "Small Words:" ), this );
+ gridLayout->addMultiCellWidget( label, 9, 9, 0, 1 );
+ m_lineEditSmallWords = new KLineEdit( this );
+ label->setBuddy( m_lineEditSmallWords );
+ gridLayout->addWidget( m_lineEditSmallWords, 10, 0 );
+ connect( m_lineEditSmallWords, SIGNAL( textChanged( const QString & ) ), this, SLOT( slotEditSmallWordsChanged( const QString & ) ) );
+ m_buttonAddSmallWord = new KPushButton( i18n( "Add" ), this );
+ m_buttonAddSmallWord->setEnabled( false );
+ m_buttonAddSmallWord->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ gridLayout->addWidget( m_buttonAddSmallWord, 10, 1 );
+ connect( m_buttonAddSmallWord, SIGNAL( clicked() ), this, SLOT( slotAddSmallWord() ) );
+
+ m_listSmallWords = new KListView( this );
+ m_listSmallWords->addColumn( i18n( "Small Words" ) );
+ m_listSmallWords->header()->setClickEnabled( true );
+ m_listSmallWords->setFullWidth( true );
+ connect( m_listSmallWords, SIGNAL( selectionChanged() ), this, SLOT( slotListSmallWordsChanged() ) );
+ connect( m_listSmallWords, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( slotListSmallWordsChanged() ) );
+ gridLayout->addMultiCellWidget( m_listSmallWords, 11, 12, 0, 0 );
+ m_buttonDeleteSmallWord = new KPushButton( i18n( "Delete" ), this );
+ m_buttonDeleteSmallWord->setEnabled( false );
+ m_buttonDeleteSmallWord->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ gridLayout->addWidget( m_buttonDeleteSmallWord, 11, 1 );
+ connect( m_buttonDeleteSmallWord, SIGNAL( clicked() ), this, SLOT( slotDeleteSmallWord() ) );
+ }
+}
+
+#include "settingsidsuggestions.moc"
diff --git a/src/settingsidsuggestions.h b/src/settingsidsuggestions.h
new file mode 100644
index 0000000..cbde362
--- /dev/null
+++ b/src/settingsidsuggestions.h
@@ -0,0 +1,108 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXSETTINGSIDSUGGESTIONS_H
+#define KBIBTEXSETTINGSIDSUGGESTIONS_H
+
+#include <qwidget.h>
+
+#include <klistview.h>
+
+#include <entry.h>
+
+class QRegExpValidator;
+class QCheckBox;
+
+class KPushButton;
+class KLineEdit;
+
+namespace KBibTeX
+{
+
+ class IdSuggestionsListViewItem: public KListViewItem
+ {
+ public:
+ IdSuggestionsListViewItem( KListView *, const QString&, BibTeX::Entry *example );
+ IdSuggestionsListViewItem( KListView *, KListViewItem *, const QString&, BibTeX::Entry *example );
+ void setText( int, const QString& );
+ QString originalText() const;
+ int width( const QFontMetrics &, const QListView *, int ) const;
+
+ private:
+ QString m_original;
+ BibTeX::Entry *m_example;
+ QString parse( const QString& );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class SettingsIdSuggestions : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SettingsIdSuggestions( QWidget *parent = 0, const char *name = 0 );
+ ~SettingsIdSuggestions();
+
+ void applyData();
+ void readData();
+
+ signals:
+ void configChanged();
+
+ protected slots:
+ void slotConfigChanged();
+
+ private slots:
+ void slotNewIdSuggestion();
+ void slotEditIdSuggestion();
+ void slotDeleteIdSuggestion();
+ void slotMoveUpIdSuggestion();
+ void slotMoveDownIdSuggestion();
+ void slotToggleDefault();
+ void slotEditSmallWordsChanged( const QString & );
+ void slotAddSmallWord();
+ void slotDeleteSmallWord();
+ void slotListSmallWordsChanged();
+ void updateGUI();
+
+ private:
+ KListView *m_listIdSuggestions;
+ KPushButton *m_buttonNewIdSuggestion;
+ KPushButton *m_buttonEditIdSuggestion;
+ KPushButton *m_buttonDeleteIdSuggestion;
+ KPushButton *m_buttonMoveUpIdSuggestion;
+ KPushButton *m_buttonMoveDownIdSuggestion;
+ KPushButton *m_buttonToggleDefault;
+ QCheckBox *m_checkBoxForceDefault;
+ KListView *m_listSmallWords;
+ KLineEdit *m_lineEditSmallWords;
+ KPushButton *m_buttonAddSmallWord;
+ KPushButton *m_buttonDeleteSmallWord;
+ QRegExpValidator *m_validator;
+ QListViewItem *m_defaultSuggestionItem;
+ static QString exampleBibTeXEntry;
+ BibTeX::Entry *m_example;
+
+ void setupGUI();
+ };
+
+}
+
+#endif
diff --git a/src/settingskeyword.cpp b/src/settingskeyword.cpp
new file mode 100644
index 0000000..6667e01
--- /dev/null
+++ b/src/settingskeyword.cpp
@@ -0,0 +1,194 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qheader.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+
+#include <klistview.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+#include <file.h>
+#include <entryfield.h>
+#include <value.h>
+#include <entry.h>
+#include <settings.h>
+#include "settingskeyword.h"
+
+namespace KBibTeX
+{
+
+ SettingsKeyword::SettingsKeyword( QWidget *parent, const char *name ) : QWidget( parent, name ), m_keywords( NULL )
+ {
+ setupGUI();
+ }
+
+ SettingsKeyword::~SettingsKeyword()
+ {
+ // nothing
+ }
+
+ void SettingsKeyword::applyData()
+ {
+ Settings * settings = Settings::self();
+ settings->keyword_GlobalList.clear();
+ for ( QListViewItemIterator it = QListViewItemIterator( m_listKeywords ); it.current() != NULL; ++it )
+ settings->keyword_GlobalList.append( it.current() ->text( 0 ) );
+ settings->keyword_GlobalList.sort();
+ }
+
+ void SettingsKeyword::readData()
+ {
+ Settings * settings = Settings::self();
+ m_listKeywords->clear();
+ for ( QStringList::Iterator it = settings->keyword_GlobalList.begin(); it != settings->keyword_GlobalList.end(); ++it )
+ {
+ KListViewItem *item = new KListViewItem( m_listKeywords, *it );
+ item->setPixmap( 0, SmallIcon( "package" ) );
+ }
+
+// Settings * settings = Settings::self();
+ BibTeX::File *bibtexFile = settings->currentBibTeXFile;
+// m_keywordsFromFile.clear();
+ if ( bibtexFile != NULL )
+// {
+ m_keywordsFromFile = bibtexFile->getAllValuesAsStringList( BibTeX::EntryField::ftKeywords );
+
+ m_buttonImportKeywords->setEnabled( m_keywordsFromFile.size() > 0 );
+ }
+
+ void SettingsKeyword::slotNewKeyword()
+ {
+ KListViewItem * item = new KListViewItem( m_listKeywords, i18n( "New Keyword" ) );
+ item->setPixmap( 0, SmallIcon( "package" ) );
+ m_listKeywords->setSelected( item, TRUE );
+ m_listKeywords->ensureItemVisible( item );
+ QTimer::singleShot( 100, this, SLOT( slotEditKeyword() ) );
+ }
+
+ void SettingsKeyword::slotEditKeyword()
+ {
+ KListViewItem * item = static_cast<KListViewItem*>( m_listKeywords->selectedItem() );
+ if ( item != NULL )
+ {
+ m_oldText = item->text( 0 );
+ m_listKeywords->rename( item, 0 );
+ }
+ }
+
+ void SettingsKeyword::slotDeleteKeyword()
+ {
+ KListViewItem * item = static_cast<KListViewItem*>( m_listKeywords->selectedItem() );
+ if ( item != NULL )
+ {
+ delete item;
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsKeyword::slotImportKeywords()
+ {
+ int numImported = m_keywordsFromFile.size();
+ for ( QListViewItemIterator it = QListViewItemIterator( m_listKeywords ); it.current() != NULL; ++it )
+ {
+ QString text = it.current() ->text( 0 );
+ if ( !m_keywordsFromFile.contains( text ) )
+ m_keywordsFromFile.append( text );
+ else
+ numImported--;
+ }
+
+ m_keywordsFromFile.sort();
+ m_listKeywords->clear();
+ for ( QStringList::Iterator it = m_keywordsFromFile.begin(); it != m_keywordsFromFile.end(); ++it )
+ {
+ KListViewItem *item = new KListViewItem( m_listKeywords, *it );
+ item->setPixmap( 0, SmallIcon( "package" ) );
+ }
+
+ KMessageBox::information( this, i18n( "1 keyword has been imported.", "%n keywords have been imported.", numImported ), i18n( "Keywords imported" ) );
+
+ m_buttonImportKeywords->setEnabled( FALSE );
+ }
+
+ void SettingsKeyword::slotItemRenamed( QListViewItem *item )
+ {
+ QString newText = item->text( 0 ).stripWhiteSpace();
+ if ( newText.isEmpty() )
+ item->setText( 0, m_oldText );
+ else
+ {
+ item->setText( 0, newText );
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsKeyword::updateGUI()
+ {
+ bool selected = m_listKeywords->selectedItem() != NULL;
+ m_buttonEditKeyword->setEnabled( selected );
+ m_buttonDeleteKeyword->setEnabled( selected );
+ }
+
+ void SettingsKeyword::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 5, 2, 0, KDialog::spacingHint(), "gridLayout" );
+
+ m_listKeywords = new KListView( this );
+ m_listKeywords->addColumn( i18n( "Keywords" ) );
+ m_listKeywords->header()->setClickEnabled( FALSE );
+ m_listKeywords->setFullWidth( true );
+ gridLayout->addMultiCellWidget( m_listKeywords, 0, 4, 0, 0 );
+
+ m_buttonNewKeyword = new QPushButton( i18n( "keyword", "New" ), this );
+ m_buttonNewKeyword->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ gridLayout->addWidget( m_buttonNewKeyword, 0, 1 );
+ m_buttonEditKeyword = new QPushButton( i18n( "keyword", "Edit" ), this );
+ m_buttonEditKeyword->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ gridLayout->addWidget( m_buttonEditKeyword, 1, 1 );
+ m_buttonDeleteKeyword = new QPushButton( i18n( "keyword", "Delete" ), this );
+ m_buttonDeleteKeyword->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ gridLayout->addWidget( m_buttonDeleteKeyword, 2, 1 );
+
+ m_buttonImportKeywords = new QPushButton( i18n( "keyword", "Import" ), this );
+ m_buttonImportKeywords->setIconSet( QIconSet( SmallIcon( "openfile" ) ) );
+ QToolTip::add( m_buttonImportKeywords, "Import all keywords from the current BibTeX file" );
+ gridLayout->addWidget( m_buttonImportKeywords, 4, 1 );
+ connect( m_buttonImportKeywords, SIGNAL( clicked() ), this, SLOT( slotImportKeywords() ) );
+
+ connect( m_buttonNewKeyword, SIGNAL( clicked() ), this, SLOT( slotNewKeyword() ) );
+ connect( m_buttonEditKeyword, SIGNAL( clicked() ), this, SLOT( slotEditKeyword() ) );
+ connect( m_buttonDeleteKeyword, SIGNAL( clicked() ), this, SLOT( slotDeleteKeyword() ) );
+ connect( m_listKeywords, SIGNAL( selectionChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_listKeywords, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listKeywords, SIGNAL( doubleClicked( QListViewItem*, const QPoint &, int ) ), this, SLOT( slotEditKeyword() ) );
+ connect( m_listKeywords, SIGNAL( itemRenamed( QListViewItem* ) ), this, SLOT( slotItemRenamed( QListViewItem* ) ) );
+
+ updateGUI();
+ }
+
+}
+#include "settingskeyword.moc"
diff --git a/src/settingskeyword.h b/src/settingskeyword.h
new file mode 100644
index 0000000..516dfcb
--- /dev/null
+++ b/src/settingskeyword.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXSETTINGSKEYWORD_H
+#define KBIBTEXSETTINGSKEYWORD_H
+
+#include <qwidget.h>
+
+class KListView;
+class QPushButton;
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class SettingsKeyword : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SettingsKeyword( QWidget *parent = 0, const char *name = 0 );
+ ~SettingsKeyword();
+
+ void applyData();
+ void readData();
+
+ signals:
+ void configChanged();
+
+ private slots:
+ void slotNewKeyword();
+ void slotEditKeyword();
+ void slotDeleteKeyword();
+ void slotImportKeywords();
+ void slotItemRenamed( QListViewItem * );
+ void updateGUI();
+
+ private:
+ QStringList *m_keywords;
+ QStringList m_keywordsFromFile;
+ KListView *m_listKeywords;
+ QPushButton *m_buttonNewKeyword;
+ QPushButton *m_buttonEditKeyword;
+ QPushButton *m_buttonDeleteKeyword;
+ QPushButton *m_buttonImportKeywords;
+ QString m_oldText;
+
+ void setupGUI();
+ };
+}
+
+#endif
diff --git a/src/settingssearchurl.cpp b/src/settingssearchurl.cpp
new file mode 100644
index 0000000..3adfd6f
--- /dev/null
+++ b/src/settingssearchurl.cpp
@@ -0,0 +1,221 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qheader.h>
+#include <qcombobox.h>
+
+#include <kiconloader.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kdialogbase.h>
+#include <kmessagebox.h>
+
+#include <settings.h>
+#include "settingssearchurl.h"
+
+namespace KBibTeX
+{
+ SettingsSearchURL::SettingsSearchURL( QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_counter( 1 )
+ {
+ setupGUI();
+ }
+
+
+ SettingsSearchURL::~SettingsSearchURL()
+ {
+ // nothing
+ }
+
+ void SettingsSearchURL::applyData()
+ {
+ Settings * settings = Settings::self();
+ settings->searchURLs.clear();
+ for ( QListViewItemIterator it( m_listviewSearchURLs ); it.current(); it++ )
+ {
+ Settings::SearchURL *searchURL = new Settings::SearchURL;
+ searchURL->description = it.current() ->text( 0 );
+ searchURL->includeAuthor = it.current() ->text( 1 ) == i18n( "Yes" );
+ searchURL->url = it.current() ->text( 2 );
+ settings->searchURLs.append( searchURL );
+ }
+ }
+
+ void SettingsSearchURL::readData()
+ {
+ Settings * settings = Settings::self();
+
+ m_listviewSearchURLs->clear();
+ for ( QValueList<Settings::SearchURL*>::ConstIterator it = settings->searchURLs.begin(); it != settings->searchURLs.end(); ++it )
+ {
+ KListViewItem *item = new KListViewItem( m_listviewSearchURLs, ( *it ) ->description, ( *it ) ->includeAuthor ? i18n( "Yes" ) : i18n( "No" ), ( *it ) ->url );
+ item->setPixmap( 0, SmallIcon( "html" ) );
+ }
+ }
+
+ void SettingsSearchURL::slotNew()
+ {
+ urlDialog();
+ emit configChanged();
+ updateGUI();
+ }
+
+ void SettingsSearchURL::slotDelete()
+ {
+ QListViewItem * item = m_listviewSearchURLs->selectedItem();
+ if ( item != NULL )
+ {
+ m_listviewSearchURLs->removeItem( item );
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsSearchURL::slotEdit()
+ {
+ QListViewItem * item = m_listviewSearchURLs->selectedItem();
+ if ( item != NULL )
+ {
+ urlDialog( item );
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsSearchURL::slotReset()
+ {
+ if ( KMessageBox:: warningContinueCancel( this, i18n( "The list of URLs will be checked and known entries will be replaced by the program standards. Search entries you have defined by yourself will be kept most likely." ), i18n( "Reset list of URLs" ), KGuiItem( i18n( "Reset" ), "reload" ) ) == KMessageBox::Continue )
+ {
+ Settings::self() ->restoreDefaultSearchURLs();
+ readData();
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsSearchURL::updateGUI()
+ {
+ bool enable = m_listviewSearchURLs->selectedItem() != NULL;
+ m_pushbuttonEdit->setEnabled( enable );
+ m_pushbuttonDelete->setEnabled( enable );
+ }
+
+ void SettingsSearchURL::setupGUI()
+ {
+ QGridLayout * layout = new QGridLayout( this, 5, 2, 0, KDialog::spacingHint() );
+ layout->setRowStretch( 3, 1 );
+ layout->setColStretch( 0, 1 );
+
+ m_listviewSearchURLs = new KListView( this );
+ layout->addMultiCellWidget( m_listviewSearchURLs, 0, 4, 0, 0 );
+ m_listviewSearchURLs->setAllColumnsShowFocus( TRUE );
+ m_listviewSearchURLs->addColumn( i18n( "Description" ) );
+ m_listviewSearchURLs->addColumn( i18n( "Author" ) );
+ m_listviewSearchURLs->addColumn( i18n( "URL" ) );
+ m_listviewSearchURLs->header()->setClickEnabled( FALSE );
+ m_listviewSearchURLs->setFullWidth( true );
+ m_listviewSearchURLs->setMinimumWidth( 384 );
+
+ m_pushbuttonNew = new KPushButton( i18n( "search url", "New" ), this );
+ m_pushbuttonNew->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ layout->addWidget( m_pushbuttonNew, 0, 1 );
+
+ m_pushbuttonEdit = new KPushButton( i18n( "search url", "Edit" ), this );
+ m_pushbuttonEdit->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ layout->addWidget( m_pushbuttonEdit, 1, 1 );
+
+ m_pushbuttonDelete = new KPushButton( i18n( "search url", "Delete" ), this );
+ m_pushbuttonDelete->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ layout->addWidget( m_pushbuttonDelete, 2, 1 );
+
+ m_pushbuttonReset = new KPushButton( i18n( "search url", "Reset" ), this );
+ m_pushbuttonReset->setIconSet( QIconSet( SmallIcon( "reload" ) ) );
+ layout->addWidget( m_pushbuttonReset, 4, 1 );
+
+ connect( m_pushbuttonNew, SIGNAL( clicked() ), this, SLOT( slotNew() ) );
+ connect( m_pushbuttonEdit, SIGNAL( clicked() ), this, SLOT( slotEdit() ) );
+ connect( m_listviewSearchURLs, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int ) ), this, SLOT( slotEdit() ) );
+ connect( m_pushbuttonDelete, SIGNAL( clicked() ), this, SLOT( slotDelete() ) );
+ connect( m_pushbuttonReset, SIGNAL( clicked() ), this, SLOT( slotReset() ) );
+ connect( m_listviewSearchURLs, SIGNAL( selectionChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listviewSearchURLs, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listviewSearchURLs, SIGNAL( onItem( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+
+ updateGUI();
+ }
+
+ void SettingsSearchURL::urlDialog( QListViewItem * item )
+ {
+ KDialogBase * dlg = new KDialogBase( this, "urldialog", TRUE, item == NULL ? i18n( "New URL" ) : i18n( "Edit URL" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, TRUE );
+ QWidget *container = new QWidget( dlg, "container" );
+ QGridLayout *layout = new QGridLayout( container, 3, 2, 0, KDialog::spacingHint() );
+ QLabel *label = new QLabel( i18n( "Description:" ), container );
+ layout->addWidget( label, 0, 0 );
+ QLineEdit *descr = new QLineEdit( container );
+ label->setBuddy( descr );
+ layout->addWidget( descr, 0, 1 );
+ label = new QLabel( i18n( "URL:" ), container );
+ layout->addWidget( label, 1, 0 );
+ QLineEdit *url = new QLineEdit( container );
+ layout->addWidget( url, 1, 1 );
+ label->setBuddy( url );
+ url->setMinimumWidth( 384 );
+ QToolTip::add( url, i18n( "Within the URL, '%1' will be replaced by the search term." ) );
+ label = new QLabel( i18n( "Include Author:" ), container );
+ layout->addWidget( label, 2, 0 );
+ QComboBox *cbIncludeAuthor = new QComboBox( FALSE, container );
+ layout->addWidget( cbIncludeAuthor, 2, 1 );
+ label->setBuddy( cbIncludeAuthor );
+ cbIncludeAuthor->insertItem( i18n( "Yes" ) );
+ cbIncludeAuthor->insertItem( i18n( "No" ) );
+
+ dlg->setMainWidget( container );
+
+ if ( item != NULL )
+ {
+ descr->setText( item->text( 0 ) );
+ url->setText( item->text( 2 ) );
+ cbIncludeAuthor->setCurrentItem( item->text( 1 ) == i18n( "Yes" ) ? 0 : 1 );
+ }
+
+ if ( dlg->exec() == QDialog::Accepted )
+ {
+ if ( item == NULL )
+ {
+ KListViewItem *item = new KListViewItem( m_listviewSearchURLs, descr->text(), cbIncludeAuthor->currentItem() == 0 ? i18n( "Yes" ) : i18n( "No" ), url->text() );
+ item->setPixmap( 0, SmallIcon( "html" ) );
+ }
+ else
+ {
+ item->setText( 0, descr->text() );
+ item->setText( 1, cbIncludeAuthor->currentItem() == 0 ? i18n( "Yes" ) : i18n( "No" ) );
+ item->setText( 2, url->text() );
+ }
+ }
+
+ delete dlg;
+ }
+}
+
+#include "settingssearchurl.moc"
diff --git a/src/settingssearchurl.h b/src/settingssearchurl.h
new file mode 100644
index 0000000..7cc4f5a
--- /dev/null
+++ b/src/settingssearchurl.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef SETTINGSSEARCHURL_H
+#define SETTINGSSEARCHURL_H
+
+#include <qwidget.h>
+
+class QLineEdit;
+class KPushButton;
+class KListView;
+class QListViewItem;
+
+namespace KBibTeX
+{
+ class SettingsSearchURL : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SettingsSearchURL( QWidget *parent = 0, const char *name = 0 );
+ ~SettingsSearchURL();
+
+ void applyData();
+ void readData();
+
+ signals:
+ void configChanged();
+
+ private slots:
+ void slotNew();
+ void slotEdit();
+ void slotDelete();
+ void slotReset();
+ void updateGUI();
+
+ private:
+ KPushButton *m_pushbuttonNew;
+ KPushButton *m_pushbuttonEdit;
+ KPushButton *m_pushbuttonDelete;
+ KListView *m_listviewSearchURLs;
+ KPushButton *m_pushbuttonReset;
+
+ int m_counter;
+
+ void setupGUI();
+
+ void urlDialog( QListViewItem * item = NULL );
+
+ };
+}
+
+#endif
diff --git a/src/settingsuserdefinedinput.cpp b/src/settingsuserdefinedinput.cpp
new file mode 100644
index 0000000..dc903bc
--- /dev/null
+++ b/src/settingsuserdefinedinput.cpp
@@ -0,0 +1,264 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qlayout.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+
+#include <kdialog.h>
+#include <kdialogbase.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <klistview.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+#include <settings.h>
+#include <fieldlineedit.h>
+#include "settingsuserdefinedinput.h"
+
+namespace KBibTeX
+{
+
+ SettingsUserDefinedInput::SettingsUserDefinedInput( QWidget *parent, const char *name ) : QWidget( parent, name )
+ {
+ setupGUI();
+ }
+
+ SettingsUserDefinedInput::~SettingsUserDefinedInput()
+ {
+ // nothing
+ }
+
+ void SettingsUserDefinedInput::applyData()
+ {
+ Settings *settings = Settings::self( NULL );
+ settings->userDefinedInputFields.clear();
+ for ( QListViewItemIterator it( m_listFields ); it.current(); ++it )
+ {
+ Settings::UserDefinedInputFields *udif = new Settings::UserDefinedInputFields();
+ udif->name = it.current()->text( 0 );
+ udif->label = it.current()->text( 1 );
+ udif->inputType = it.current()->text( 2 ) == i18n( "Single line" ) ? FieldLineEdit::itSingleLine : FieldLineEdit::itMultiLine;
+ settings->userDefinedInputFields << udif;
+ }
+ }
+
+ void SettingsUserDefinedInput::readData()
+ {
+ m_listFields->clear();
+ Settings *settings = Settings::self( NULL );
+ KListViewItem *prev = NULL;
+ for ( QValueList<Settings::UserDefinedInputFields*>::iterator it = settings->userDefinedInputFields.begin(); it != settings->userDefinedInputFields.end(); ++it )
+ {
+ prev = new KListViewItem( m_listFields, prev, ( *it )->name, ( *it )->label, ( *it )->inputType == FieldLineEdit::itMultiLine ? i18n( "Multiple lines" ) : i18n( "Single line" ) );
+ }
+ }
+
+ void SettingsUserDefinedInput::slotNewField()
+ {
+ fieldDialog();
+ emit configChanged();
+ updateGUI();
+ }
+
+ void SettingsUserDefinedInput::slotEditField()
+ {
+ QListViewItem * item = m_listFields->selectedItem();
+ if ( item != NULL )
+ {
+ fieldDialog( item );
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsUserDefinedInput::slotDeleteField()
+ {
+ QListViewItem * item = m_listFields->selectedItem();
+ if ( item != NULL )
+ {
+ m_listFields->removeItem( item );
+ emit configChanged();
+ }
+ updateGUI();
+ }
+
+ void SettingsUserDefinedInput::slotMoveUpField()
+ {
+ QListViewItem *item = m_listFields->selectedItem();
+ if ( item != NULL && item -> itemAbove() != NULL )
+ {
+ QListViewItem *itemAbove = item->itemAbove();
+ for ( int i = 0; i < 3; ++i )
+ {
+ QString text = item->text( i );
+ item->setText( i, itemAbove->text( i ) );
+ itemAbove->setText( i, text );
+ }
+ m_listFields->setCurrentItem( itemAbove );
+ m_listFields->ensureItemVisible( itemAbove );
+ updateGUI();
+ }
+ }
+
+ void SettingsUserDefinedInput::slotMoveDownField()
+ {
+ QListViewItem *item = m_listFields->selectedItem();
+ if ( item != NULL && item -> itemBelow() != NULL )
+ {
+ QListViewItem *itemBelow = item->itemBelow();
+ for ( int i = 0; i < 3; ++i )
+ {
+ QString text = item->text( i );
+ item->setText( i, itemBelow->text( i ) );
+ itemBelow->setText( i, text );
+ }
+ m_listFields->setCurrentItem( itemBelow );
+ m_listFields->ensureItemVisible( itemBelow );
+ updateGUI();
+ }
+ }
+
+ void SettingsUserDefinedInput::updateGUI()
+ {
+ QListViewItem *item = m_listFields->selectedItem();
+ bool selected = item != NULL;
+ m_buttonEditField->setEnabled( selected );
+ m_buttonDeleteField->setEnabled( selected );
+ m_buttonMoveDownField->setEnabled( selected && item->itemBelow() != NULL );
+ m_buttonMoveUpField->setEnabled( selected && item->itemAbove() != NULL );
+ }
+
+ void SettingsUserDefinedInput::updateDialogGUI()
+ {
+ bool enable = !m_lineEditName->text().isEmpty() && !m_lineEditLabel->text().isEmpty();
+ fieldDlg->enableButtonOK( enable );
+ fieldDlg->enableButtonApply( enable );
+ }
+
+ void SettingsUserDefinedInput::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 6, 2, 0, KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( 5, 1 );
+ gridLayout->setColStretch( 0, 1 );
+
+ m_listFields = new KListView( this );
+ m_listFields->setSorting( -1, FALSE );
+ m_listFields->addColumn( i18n( "Name" ) );
+ m_listFields->header()->setClickEnabled( FALSE );
+ m_listFields->addColumn( i18n( "Label" ) );
+ m_listFields->header()->setClickEnabled( FALSE );
+ m_listFields->addColumn( i18n( "Type" ) );
+ m_listFields->header()->setClickEnabled( FALSE );
+ m_listFields->header()->setClickEnabled( FALSE );
+ m_listFields->setFullWidth( true );
+ m_listFields->setMinimumWidth( 128 );
+ m_listFields->setAllColumnsShowFocus( TRUE );
+ gridLayout->addMultiCellWidget( m_listFields, 0, 5, 0, 0 );
+
+ m_buttonNewField = new KPushButton( i18n( "user-defined input", "New" ), this );
+ m_buttonNewField->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ gridLayout->addWidget( m_buttonNewField, 0, 1 );
+ m_buttonEditField = new KPushButton( i18n( "user-defined input", "Edit" ), this );
+ m_buttonEditField->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ gridLayout->addWidget( m_buttonEditField, 1, 1 );
+ m_buttonDeleteField = new KPushButton( i18n( "user-defined input", "Delete" ), this );
+ m_buttonDeleteField->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ gridLayout->addWidget( m_buttonDeleteField, 2, 1 );
+ m_buttonMoveUpField = new KPushButton( i18n( "user-defined input", "Up" ), this );
+ m_buttonMoveUpField->setIconSet( QIconSet( SmallIcon( "up" ) ) );
+ gridLayout->addWidget( m_buttonMoveUpField, 3, 1 );
+ connect( m_buttonMoveUpField, SIGNAL( clicked() ), this, SLOT( slotMoveUpField() ) );
+ m_buttonMoveDownField = new KPushButton( i18n( "user-defined input", "Down" ), this );
+ m_buttonMoveDownField->setIconSet( QIconSet( SmallIcon( "down" ) ) );
+ gridLayout->addWidget( m_buttonMoveDownField, 4, 1 );
+ connect( m_buttonMoveDownField, SIGNAL( clicked() ), this, SLOT( slotMoveDownField() ) );
+
+ connect( m_buttonNewField, SIGNAL( clicked() ), this, SLOT( slotNewField() ) );
+ connect( m_buttonEditField, SIGNAL( clicked() ), this, SLOT( slotEditField() ) );
+ connect( m_buttonDeleteField, SIGNAL( clicked() ), this, SLOT( slotDeleteField() ) );
+ connect( m_listFields, SIGNAL( selectionChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_listFields, SIGNAL( doubleClicked( QListViewItem*, const QPoint &, int ) ), this, SLOT( slotEditField() ) );
+ connect( m_listFields, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+
+ updateGUI();
+ }
+
+ void SettingsUserDefinedInput::fieldDialog( QListViewItem * item )
+ {
+ fieldDlg = new KDialogBase( this, "fieldDialog", TRUE, item == NULL ? i18n( "New Field" ) : i18n( "Edit Field" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, TRUE );
+ QWidget *container = new QWidget( fieldDlg, "container" );
+ QGridLayout *layout = new QGridLayout( container, 3, 2, 0, KDialog::spacingHint() );
+ QLabel *label = new QLabel( i18n( "Name:" ), container );
+ layout->addWidget( label, 0, 0 );
+ m_lineEditName = new KLineEdit( container );
+ label->setBuddy( m_lineEditName );
+ layout->addWidget( m_lineEditName, 0, 1 );
+ label = new QLabel( i18n( "Label:" ), container );
+ layout->addWidget( label, 1, 0 );
+ m_lineEditLabel = new KLineEdit( container );
+ layout->addWidget( m_lineEditLabel, 1, 1 );
+ label->setBuddy( m_lineEditLabel );
+ m_lineEditLabel->setMinimumWidth( 384 );
+ label = new QLabel( i18n( "Input Type:" ), container );
+ layout->addWidget( label, 2, 0 );
+ KComboBox *comboBoxInputType = new KComboBox( FALSE, container );
+ layout->addWidget( comboBoxInputType, 2, 1 );
+ label->setBuddy( comboBoxInputType );
+ comboBoxInputType->insertItem( i18n( "Single line" ) );
+ comboBoxInputType->insertItem( i18n( "Multiple lines" ) );
+
+ fieldDlg->setMainWidget( container );
+
+ if ( item != NULL )
+ {
+ m_lineEditName->setText( item->text( 0 ) );
+ m_lineEditLabel->setText( item->text( 1 ) );
+ comboBoxInputType->setCurrentItem( item->text( 2 ) == i18n( "Single line" ) ? 0 : 1 );
+ fieldDlg->enableButton( KDialogBase::Ok, true );
+ }
+ else
+ fieldDlg->enableButton( KDialogBase::Ok, false );
+
+ connect( m_lineEditName, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateDialogGUI() ) );
+ connect( m_lineEditLabel, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateDialogGUI() ) );
+ if ( fieldDlg->exec() == QDialog::Accepted )
+ {
+ if ( item == NULL )
+ {
+ /*KListViewItem *item = */
+ new KListViewItem( m_listFields, m_lineEditName->text(), m_lineEditLabel->text(), comboBoxInputType->currentItem() == 0 ? i18n( "Single line" ) : i18n( "Multiple lines" ) );
+ }
+ else
+ {
+ item->setText( 0, m_lineEditName->text() );
+ item->setText( 1, m_lineEditLabel->text() );
+ item->setText( 2, comboBoxInputType->currentItem() == 0 ? i18n( "Single line" ) : i18n( "Multiple lines" ) );
+ }
+ }
+
+ delete fieldDlg;
+ }
+}
+#include "settingsuserdefinedinput.moc"
diff --git a/src/settingsuserdefinedinput.h b/src/settingsuserdefinedinput.h
new file mode 100644
index 0000000..a06d7b0
--- /dev/null
+++ b/src/settingsuserdefinedinput.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXSETTINGSUSERDEFINEDINPUT_H
+#define KBIBTEXSETTINGSUSERDEFINEDINPUT_H
+
+#include <qwidget.h>
+
+class KListView;
+class KPushButton;
+class KDialogBase;
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class SettingsUserDefinedInput : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SettingsUserDefinedInput( QWidget *parent = 0, const char *name = 0 );
+ ~SettingsUserDefinedInput();
+
+ void applyData();
+ void readData();
+
+ signals:
+ void configChanged();
+
+ private slots:
+ void slotNewField();
+ void slotEditField();
+ void slotDeleteField();
+ void slotMoveUpField();
+ void slotMoveDownField();
+ void updateGUI();
+ void updateDialogGUI();
+
+ private:
+ KListView *m_listFields;
+ KPushButton *m_buttonNewField;
+ KPushButton *m_buttonEditField;
+ KPushButton *m_buttonDeleteField;
+ KPushButton *m_buttonMoveUpField;
+ KPushButton *m_buttonMoveDownField;
+ KDialogBase *fieldDlg;
+ KLineEdit *m_lineEditLabel;
+ KLineEdit *m_lineEditName;
+
+ void setupGUI();
+ void fieldDialog( QListViewItem * item = NULL );
+ };
+
+}
+
+#endif
diff --git a/src/settingsz3950.cpp b/src/settingsz3950.cpp
new file mode 100644
index 0000000..d2c3858
--- /dev/null
+++ b/src/settingsz3950.cpp
@@ -0,0 +1,364 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_YAZ
+
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qregexp.h>
+
+#include <klistview.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+#include <kdialogbase.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+
+#include "settingsz3950.h"
+
+namespace KBibTeX
+{
+
+ ServerListViewItem::ServerListViewItem( KListView *list, const QString &_id, Settings::Z3950Server& _server, bool _newItem )
+ : KListViewItem( list, _server.name, _server.database ), server( _server ), id( _id ), newItem( _newItem )
+ {
+ // nothing
+ }
+
+ ServerListViewItem::ServerListViewItem( KListViewItem *item, const QString &_id, Settings::Z3950Server& _server, bool _newItem )
+ : KListViewItem( item, _server.name, _server.database ), server( _server ), id( _id ), newItem( _newItem )
+ {
+ // nothing
+ }
+
+ void ServerListViewItem::refresh( )
+ {
+ setText( 0, server.name );
+ setText( 1, server.database );
+ }
+
+ SettingsZ3950Edit::SettingsZ3950Edit( QString &id, Settings::Z3950Server& _server, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_id( id ), m_server( _server ), m_lineEditId( NULL )
+ {
+ QGridLayout *layout = new QGridLayout( this, 10, 2 , 0, KDialog::spacingHint() );
+ QLabel *label = NULL;
+
+ label = new QLabel( i18n( "Name:" ), this );
+ layout->addWidget( label, 1, 0 );
+ m_lineEditName = new KLineEdit( m_server.name, this );
+ layout->addWidget( m_lineEditName, 1, 1 );
+ label->setBuddy( m_lineEditName );
+
+ label = new QLabel( i18n( "Database:" ), this );
+ layout->addWidget( label, 2, 0 );
+ m_lineEditDatabase = new KLineEdit( m_server.database, this );
+ layout->addWidget( m_lineEditDatabase, 2, 1 );
+ label->setBuddy( m_lineEditDatabase );
+
+ label = new QLabel( i18n( "Host:" ), this );
+ layout->addWidget( label, 3, 0 );
+ m_lineEditHost = new KLineEdit( m_server.host, this );
+ layout->addWidget( m_lineEditHost, 3, 1 );
+ label->setBuddy( m_lineEditHost );
+
+ label = new QLabel( i18n( "Port:" ), this );
+ layout->addWidget( label, 4, 0 );
+ m_spinBoxPort = new QSpinBox( this );
+ m_spinBoxPort->setMinValue( 1 );
+ m_spinBoxPort->setMaxValue( 65535 );
+ m_spinBoxPort->setValue( m_server.port );
+ layout->addWidget( m_spinBoxPort, 4, 1 );
+ label->setBuddy( m_spinBoxPort );
+
+ label = new QLabel( i18n( "User:" ), this );
+ layout->addWidget( label, 5, 0 );
+ m_lineEditUser = new KLineEdit( m_server.user, this );
+ layout->addWidget( m_lineEditUser, 5, 1 );
+ label->setBuddy( m_lineEditUser );
+
+ label = new QLabel( i18n( "Password:" ), this );
+ layout->addWidget( label, 6, 0 );
+ m_lineEditPassword = new KLineEdit( m_server.password, this );
+ layout->addWidget( m_lineEditPassword, 6, 1 );
+ label->setBuddy( m_lineEditPassword );
+
+ label = new QLabel( i18n( "Syntax:" ), this );
+ layout->addWidget( label, 7, 0 );
+ m_comboBoxSyntax = new KComboBox( true, this );
+ layout->addWidget( m_comboBoxSyntax, 7, 1 );
+ label->setBuddy( m_comboBoxSyntax );
+ m_comboBoxSyntax->insertItem( "grs-1" );
+ m_comboBoxSyntax->insertItem( "marc21" );
+ m_comboBoxSyntax->insertItem( "mods" );
+ m_comboBoxSyntax->insertItem( "unimarc" );
+ m_comboBoxSyntax->insertItem( "usmarc" );
+ m_comboBoxSyntax->setCurrentText( m_server.syntax );
+
+ label = new QLabel( i18n( "Locale:" ), this );
+ layout->addWidget( label, 8, 0 );
+ m_comboBoxLocale = new KComboBox( true, this );
+ m_comboBoxLocale->setCurrentText( m_server.locale );
+ layout->addWidget( m_comboBoxLocale, 8, 1 );
+ label->setBuddy( m_comboBoxLocale );
+
+ label = new QLabel( i18n( "Charset:" ), this );
+ layout->addWidget( label, 9, 0 );
+ m_comboBoxCharset = new KComboBox( true, this );
+ layout->addWidget( m_comboBoxCharset, 9, 1 );
+ label->setBuddy( m_comboBoxCharset );
+ m_comboBoxCharset->insertItem( "iso-5426" );
+ m_comboBoxCharset->insertItem( "iso-8859-1" );
+ m_comboBoxCharset->insertItem( "marc8" );
+ m_comboBoxCharset->insertItem( "marc-8" );
+ m_comboBoxCharset->insertItem( "utf-8" );
+ m_comboBoxCharset->setCurrentText( m_server.charset );
+ }
+
+ SettingsZ3950Edit::~SettingsZ3950Edit()
+ {
+ // nothing
+ }
+
+ int SettingsZ3950Edit::execute( QWidget *parent, QString &id, Settings::Z3950Server &server )
+ {
+ KDialogBase *dlg = new KDialogBase( parent, "SettingsZ3950Edit", true, i18n( "Edit Z39.50 Server" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, false );
+ SettingsZ3950Edit *edit = new SettingsZ3950Edit( id, server, dlg, "SettingsZ3950Edit" );
+ dlg->setMainWidget( edit );
+ connect( dlg, SIGNAL( apply() ), edit, SLOT( slotApply() ) );
+ connect( dlg, SIGNAL( okClicked() ), edit, SLOT( slotApply() ) );
+
+ return dlg->exec();
+ }
+
+ void SettingsZ3950Edit::slotApply()
+ {
+ m_server.charset = m_comboBoxCharset->currentText();
+ m_server.database = m_lineEditDatabase->text();
+ m_server.host = m_lineEditHost->text();
+ m_server.locale = m_comboBoxLocale->currentText();
+ m_server.name = m_lineEditName->text();
+ m_server.syntax = m_comboBoxSyntax->currentText();
+ m_server.user = m_lineEditUser->text();
+ m_server.password = m_lineEditPassword->text();
+ m_server.port = m_spinBoxPort->value();
+
+ if ( m_id.isEmpty() )
+ {
+ m_id = QString( m_server.name ).lower().replace( QRegExp( "[^a-z0-9]" ), "" );
+ qDebug( "Setting id to %s", m_id.latin1() );
+ }
+ }
+
+ SettingsZ3950::SettingsZ3950( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+ {
+ setupGUI();
+ }
+
+ SettingsZ3950::~SettingsZ3950()
+ {
+ // nothing
+ }
+
+ void SettingsZ3950::applyData()
+ {
+ Settings *settings = Settings::self();
+ settings->z3950_ServerList.clear();
+
+ for ( QListViewItemIterator it( m_listServers ); it.current(); ++it )
+ {
+ ServerListViewItem *item = dynamic_cast<ServerListViewItem*>( *it );
+ settings->z3950_ServerList[item->id] = item->server;
+ }
+ }
+
+ void SettingsZ3950::readData()
+ {
+ Settings *settings = Settings::self();
+ m_listServers->clear();
+
+ for ( QMap<QString, Settings::Z3950Server>::Iterator it = settings->z3950_ServerList.begin(); it != settings-> z3950_ServerList.end(); ++it )
+ {
+ ServerListViewItem *item = new ServerListViewItem( m_listServers, it.key(), it.data(), false );
+ item->setPixmap( 0, SmallIcon( "server" ) );
+ }
+
+ updateGUI();
+ }
+
+ void SettingsZ3950::slotNewServer()
+ {
+ Settings::Z3950Server server;
+ server.port = 2100;
+ ServerListViewItem * item = new ServerListViewItem( m_listServers, "", server, true );
+ item->setPixmap( 0, SmallIcon( "server" ) );
+ m_listServers->setSelected( item, TRUE );
+ QTimer::singleShot( 100, this, SLOT( slotEditServer() ) );
+ }
+
+ void SettingsZ3950::slotEditServer()
+ {
+ ServerListViewItem * item = static_cast<ServerListViewItem*>( m_listServers->selectedItem() );
+ if ( item != NULL )
+ {
+ if ( SettingsZ3950Edit::execute( this, item->id, item->server ) == QDialog::Accepted )
+ {
+ item->refresh();
+ emit configChanged();
+ }
+ else if ( item->newItem )
+ {
+ delete item;
+ updateGUI();
+ }
+ }
+ }
+
+ void SettingsZ3950::slotDeleteServer()
+ {
+ delete m_listServers->selectedItem();
+ emit configChanged();
+ updateGUI();
+ }
+
+ void SettingsZ3950::slotMoveUpServer()
+ {
+ ServerListViewItem * item = dynamic_cast<ServerListViewItem*>( m_listServers->selectedItem() );
+ ServerListViewItem *itemAbove = NULL;
+ if ( item != NULL && ( itemAbove = dynamic_cast<ServerListViewItem*>( item->itemAbove() ) ) != NULL )
+ {
+ Settings::Z3950Server server = item->server;
+ item->server = itemAbove->server;
+ itemAbove->server = server;
+ QString id = item->id;
+ item->id = itemAbove->id;
+ itemAbove->id = id;
+ for ( int i = 0; i < 2; ++i )
+ {
+ QString swap = item->text( i );
+ item->setText( i, itemAbove->text( i ) );
+ itemAbove->setText( i, swap );
+ }
+ m_listServers->setCurrentItem( itemAbove );
+ m_listServers->ensureItemVisible( itemAbove );
+ }
+ }
+
+ void SettingsZ3950::slotMoveDownServer()
+ {
+ ServerListViewItem * item = dynamic_cast<ServerListViewItem*>( m_listServers->selectedItem() );
+ ServerListViewItem *itemBelow = NULL;
+ if ( item != NULL && ( itemBelow = dynamic_cast<ServerListViewItem*>( item->itemBelow() ) ) != NULL )
+ {
+ Settings::Z3950Server server = item->server;
+ item->server = itemBelow->server;
+ itemBelow->server = server;
+ QString id = item->id;
+ item->id = itemBelow->id;
+ itemBelow->id = id;
+ for ( int i = 0; i < 2; ++i )
+ {
+ QString swap = item->text( i );
+ item->setText( i, itemBelow->text( i ) );
+ itemBelow->setText( i, swap );
+ }
+ m_listServers->setCurrentItem( itemBelow );
+ m_listServers->ensureItemVisible( itemBelow );
+ }
+ }
+
+ void SettingsZ3950::slotResetToDefault()
+ {
+ if ( KMessageBox::warningContinueCancel( this, i18n( "All Z39.50 server configurations will be reset to defaults." ), i18n( "Reset to Default" ), KGuiItem( i18n( "Reset" ), "reload" ) ) == KMessageBox::Continue )
+ {
+ Settings *settings = Settings::self();
+ settings->z3950clearAll();
+ settings->z3950loadDefault();
+ readData();
+ }
+ }
+
+ void SettingsZ3950::updateGUI()
+ {
+ QListViewItem *item = m_listServers->selectedItem();
+ bool selected = item != NULL;
+ m_buttonEditServer->setEnabled( selected );
+ m_buttonDeleteServer->setEnabled( selected );
+ m_buttonMoveDownServer->setEnabled( selected && item->itemBelow() != NULL );
+ m_buttonMoveUpServer->setEnabled( selected && item->itemAbove() != NULL );
+ }
+
+ void SettingsZ3950::setupGUI()
+ {
+ QGridLayout * gridLayout = new QGridLayout( this, 7, 2, 0, KDialog::spacingHint(), "gridLayout" );
+ gridLayout->setRowStretch( 5, 1 );
+ gridLayout->setColStretch( 0, 1 );
+
+ m_listServers = new KListView( this );
+ m_listServers->setSorting( -1, FALSE );
+ m_listServers->addColumn( i18n( "z3950 server", "Name" ) );
+ m_listServers->addColumn( i18n( "z3950 server", "Database" ) );
+ m_listServers->header()->setClickEnabled( FALSE );
+ m_listServers->setFullWidth( true );
+ m_listServers->setAllColumnsShowFocus( true );
+ gridLayout->addMultiCellWidget( m_listServers, 0, 7, 0, 0 );
+ connect( m_listServers, SIGNAL( selectionChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_listServers, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listServers, SIGNAL( doubleClicked( QListViewItem*, const QPoint &, int ) ), this, SLOT( slotEditServer() ) );
+
+ m_buttonNewServer = new KPushButton( i18n( "z3950 server", "New" ), this );
+ m_buttonNewServer->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ gridLayout->addWidget( m_buttonNewServer, 0, 1 );
+ connect( m_buttonNewServer, SIGNAL( clicked() ), this, SLOT( slotNewServer() ) );
+ m_buttonEditServer = new KPushButton( i18n( "z3950 server", "Edit" ), this );
+ m_buttonEditServer->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ gridLayout->addWidget( m_buttonEditServer, 1, 1 );
+ connect( m_buttonEditServer, SIGNAL( clicked() ), this, SLOT( slotEditServer() ) );
+ m_buttonDeleteServer = new KPushButton( i18n( "z3950 server", "Delete" ), this );
+ m_buttonDeleteServer->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ gridLayout->addWidget( m_buttonDeleteServer, 2, 1 );
+ connect( m_buttonDeleteServer, SIGNAL( clicked() ), this, SLOT( slotDeleteServer() ) );
+ m_buttonMoveUpServer = new KPushButton( i18n( "z3950 server", "Up" ), this );
+ m_buttonMoveUpServer->setIconSet( QIconSet( SmallIcon( "up" ) ) );
+ gridLayout->addWidget( m_buttonMoveUpServer, 3, 1 );
+ connect( m_buttonMoveUpServer, SIGNAL( clicked() ), this, SLOT( slotMoveUpServer() ) );
+ m_buttonMoveDownServer = new KPushButton( i18n( "z3950 server", "Down" ), this );
+ m_buttonMoveDownServer->setIconSet( QIconSet( SmallIcon( "down" ) ) );
+ gridLayout->addWidget( m_buttonMoveDownServer, 4, 1 );
+ connect( m_buttonMoveDownServer, SIGNAL( clicked() ), this, SLOT( slotMoveDownServer() ) );
+
+ m_buttonResetToDefault = new KPushButton( i18n( "z3950 server", "Reset" ), this );
+ m_buttonResetToDefault->setIconSet( QIconSet( SmallIcon( "reload" ) ) );
+ gridLayout->addWidget( m_buttonResetToDefault, 6, 1 );
+ connect( m_buttonResetToDefault, SIGNAL( clicked() ), this, SLOT( slotResetToDefault() ) );
+ }
+
+}
+#include "settingsz3950.moc"
+
+#endif // HAVE_YAZ
diff --git a/src/settingsz3950.h b/src/settingsz3950.h
new file mode 100644
index 0000000..1b694db
--- /dev/null
+++ b/src/settingsz3950.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_YAZ
+
+#ifndef KBIBTEXSETTINGSZ3950_H
+#define KBIBTEXSETTINGSZ3950_H
+
+#include <qwidget.h>
+
+#include <settings.h>
+
+class QSpinBox;
+class KPushButton;
+class KListView;
+class KLineEdit;
+class KComboBox;
+
+namespace KBibTeX
+{
+ class ServerListViewItem: public KListViewItem
+ {
+ public:
+ ServerListViewItem( KListView *, const QString &, Settings::Z3950Server& server, bool newItem );
+ ServerListViewItem( KListViewItem *, const QString &, Settings::Z3950Server& server, bool newItem );
+
+ void refresh();
+
+ public:
+ Settings::Z3950Server server;
+ QString id;
+ bool newItem;
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class SettingsZ3950Edit : public QWidget
+ {
+ Q_OBJECT
+ public:
+ ~SettingsZ3950Edit();
+
+ static int execute( QWidget *parent, QString &id, Settings::Z3950Server &server );
+
+ protected slots:
+ void slotApply();
+
+ protected:
+ SettingsZ3950Edit( QString &id, Settings::Z3950Server&, QWidget *parent = 0, const char *name = 0 );
+
+ private:
+ QString& m_id;
+ Settings::Z3950Server& m_server;
+ KLineEdit *m_lineEditId;
+ KLineEdit *m_lineEditName;
+ KLineEdit *m_lineEditHost;
+ QSpinBox *m_spinBoxPort;
+ KLineEdit *m_lineEditDatabase;
+ KLineEdit *m_lineEditUser;
+ KLineEdit *m_lineEditPassword;
+ KComboBox *m_comboBoxSyntax;
+ KComboBox *m_comboBoxLocale;
+ KComboBox *m_comboBoxCharset;
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class SettingsZ3950 : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SettingsZ3950( QWidget *parent = 0, const char *name = 0 );
+ ~SettingsZ3950();
+
+ void applyData();
+ void readData();
+
+ signals:
+ void configChanged();
+
+ private slots:
+ void slotNewServer();
+ void slotEditServer();
+ void slotDeleteServer();
+ void slotMoveUpServer();
+ void slotMoveDownServer();
+ void slotResetToDefault();
+ void updateGUI();
+
+ private:
+ KListView *m_listServers;
+ KPushButton *m_buttonNewServer;
+ KPushButton *m_buttonEditServer;
+ KPushButton *m_buttonDeleteServer;
+ KPushButton *m_buttonMoveUpServer;
+ KPushButton *m_buttonMoveDownServer;
+ KPushButton *m_buttonResetToDefault;
+
+ void setupGUI();
+ };
+
+}
+
+#endif
+
+#endif // HAVE_YAZ
diff --git a/src/sidebar.cpp b/src/sidebar.cpp
new file mode 100644
index 0000000..399cabf
--- /dev/null
+++ b/src/sidebar.cpp
@@ -0,0 +1,255 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qheader.h>
+#include <qapplication.h>
+#include <qtooltip.h>
+#include <qstring.h>
+#include <qtoolbutton.h>
+
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <klistview.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <settings.h>
+#include <entry.h>
+#include "sidebar.h"
+
+namespace KBibTeX
+{
+
+ const BibTeX::EntryField::FieldType SideBar::importantFields[ 6 ] =
+ {
+ BibTeX::EntryField::ftAuthor, BibTeX::EntryField::ftBookTitle, BibTeX::EntryField::ftJournal, BibTeX::EntryField::ftTitle, BibTeX::EntryField::ftYear, BibTeX::EntryField::ftKeywords
+ };
+
+ SideBar::SideBar( bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_bibtexFile( NULL ), m_isReadOnly( isReadOnly ), m_popupMenu( NULL )
+ {
+ setupGUI();
+ }
+
+ SideBar::~SideBar()
+ {
+ // nothing
+ }
+
+ void SideBar::restoreState()
+ {
+ Settings * settings = Settings::self();
+ if ( settings->editing_UseSpecialFont )
+ m_listAvailableItems->setFont( settings->editing_SpecialFont );
+ else
+ m_listAvailableItems->setFont( KGlobalSettings::generalFont() );
+ m_listAvailableItems->header() ->setFont( KGlobalSettings::generalFont() );
+ }
+
+ void SideBar::refreshLists( BibTeX::File *bibtexFile )
+ {
+ if ( bibtexFile != NULL )
+ m_bibtexFile = bibtexFile;
+
+ QApplication::setOverrideCursor( Qt::waitCursor );
+ setEnabled( FALSE );
+
+ BibTeX::EntryField::FieldType fieldType = m_buttonToggleShowAll->isOn() ? ( BibTeX::EntryField::FieldType )( m_listTypeList->currentItem() + ( int ) BibTeX::EntryField::ftAbstract ) : importantFields[ m_listTypeList->currentItem()];
+
+ m_listAvailableItems->clear();
+ if ( m_bibtexFile != NULL )
+ {
+ QMap<QString, int> allValues = m_bibtexFile->getAllValuesAsStringListWithCount( fieldType );
+ for ( QMap<QString, int>::ConstIterator it = allValues.constBegin(); it != allValues.constEnd();++it )
+ {
+ QString text = it.key();
+ if ( !text.startsWith( "other" ) )
+ new SideBarListViewItem( m_listAvailableItems, QString::number( it.data() ), text );
+ }
+ }
+
+ setEnabled( TRUE );
+ QApplication::restoreOverrideCursor();
+ }
+
+ void SideBar::resizeEvent( QResizeEvent *event )
+ {
+ QSize widgetSize = size();
+ setEnabled( widgetSize.width() > 3 && widgetSize.height() > 3 );
+ QWidget::resizeEvent( event );
+ }
+
+ void SideBar::setupGUI()
+ {
+ QGridLayout * layout = new QGridLayout( this, 2, 3, 0, KDialog::spacingHint() );
+ layout->setColStretch( 0, 0 );
+ layout->setColStretch( 1, 10 );
+ layout->setColStretch( 2, 0 );
+
+ m_buttonToggleShowAll = new QToolButton( this );
+ layout->addWidget( m_buttonToggleShowAll, 0, 0 );
+ QIconSet showAllPixmap = KGlobal::iconLoader() ->loadIconSet( "taskbar", KIcon::Small );
+ m_buttonToggleShowAll->setIconSet( showAllPixmap );
+ m_buttonToggleShowAll->setToggleButton( TRUE );
+ QToolTip::add( m_buttonToggleShowAll, i18n( "Toggle between showing all fields or only important fields" ) );
+
+ m_listTypeList = new QComboBox( FALSE, this );
+ layout->addWidget( m_listTypeList, 0, 1 );
+ QToolTip::add( m_listTypeList, i18n( "Filter this sidebar for a given field" ) );
+
+ m_buttonToggleMultiSelect = new QToolButton( this );
+ layout->addWidget( m_buttonToggleMultiSelect, 0, 2 );
+ showAllPixmap = KGlobal::iconLoader() ->loadIconSet( "planner", KIcon::Small );
+ m_buttonToggleMultiSelect->setIconSet( showAllPixmap );
+ m_buttonToggleMultiSelect->setToggleButton( TRUE );
+ QToolTip::add( m_buttonToggleMultiSelect, i18n( "Toggle between selecting only one item or multiple items (AND-connected in search)" ) );
+
+ m_listAvailableItems = new KListView( this );
+ m_listAvailableItems->addColumn( i18n( "#" ) );
+ m_listAvailableItems->addColumn( i18n( "Items" ) );
+ m_listAvailableItems->setAllColumnsShowFocus( TRUE );
+ m_listAvailableItems->setFullWidth( true );
+ m_listAvailableItems->setSorting( 1 );
+ layout->addMultiCellWidget( m_listAvailableItems, 1, 1, 0, 2 );
+
+ m_popupMenu = new KPopupMenu( m_listAvailableItems );
+ m_popupMenu->insertItem( i18n( "Rename all occurrences" ), this, SLOT( startRenaming() ) );
+
+ connect( m_listAvailableItems, SIGNAL( selectionChanged() ), this, SLOT( prepareSearch() ) );
+ connect( m_listTypeList, SIGNAL( activated( int ) ), this, SLOT( refreshLists() ) );
+ connect( m_buttonToggleShowAll, SIGNAL( toggled( bool ) ), this, SLOT( toggleShowAll( bool ) ) );
+ connect( m_buttonToggleMultiSelect, SIGNAL( toggled( bool ) ), this, SLOT( toggleMultiSelect( bool ) ) );
+ connect( m_listAvailableItems, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ), this, SLOT( showContextMenu( QListViewItem*, const QPoint& ) ) );
+ connect( m_listAvailableItems, SIGNAL( itemRenamed( QListViewItem*, int, const QString& ) ), this, SLOT( endRenaming( QListViewItem*, int, const QString& ) ) );
+
+ toggleShowAll( FALSE );
+ }
+
+ void SideBar::setReadOnly( bool isReadOnly )
+ {
+ m_isReadOnly = isReadOnly;
+ }
+
+
+ void SideBar::prepareSearch()
+ {
+ BibTeX::EntryField::FieldType fieldType = m_buttonToggleShowAll->isOn() ? ( BibTeX::EntryField::FieldType )( m_listTypeList->currentItem() + ( int ) BibTeX::EntryField::ftAbstract ) : importantFields[ m_listTypeList->currentItem()];
+
+ QString text = "";
+ int countSelected = 0;
+ for ( QListViewItemIterator it( m_listAvailableItems, QListViewItemIterator::Selected ); it.current(); ++it, ++countSelected )
+ {
+ if ( !text.isEmpty() ) text += " ";
+ text += it.current()->text( 1 );
+ }
+
+ emit selected( text, countSelected <= 1 ? BibTeX::Element::ftExact : BibTeX::Element::ftEveryWord, fieldType );
+ }
+
+ void SideBar::toggleShowAll( bool showAll )
+ {
+ m_listTypeList->clear();
+
+ if ( showAll )
+ {
+ for ( int i = ( int ) BibTeX::EntryField::ftAbstract; i <= ( int ) BibTeX::EntryField::ftYear; i++ )
+ {
+ BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType ) i;
+ m_listTypeList->insertItem( Settings::fieldTypeToI18NString( fieldType ) );
+ }
+ m_listTypeList->setCurrentItem(( int ) BibTeX::EntryField::ftAuthor );
+ }
+ else
+ {
+ for ( int i = 0; i < 6;i++ )
+ m_listTypeList->insertItem( Settings::fieldTypeToI18NString( importantFields[ i ] ) );
+ m_listTypeList->setCurrentItem( 0 );
+ }
+
+ refreshLists();
+ }
+
+ void SideBar::toggleMultiSelect( bool multiSelect )
+ {
+ m_listAvailableItems->setSelectionMode( multiSelect ? QListView::Extended : QListView::Single );
+ m_listAvailableItems->clearSelection();
+ prepareSearch();
+ }
+
+ void SideBar::showContextMenu( QListViewItem * item, const QPoint & pos )
+ {
+ if ( item != NULL && !m_isReadOnly && m_popupMenu != NULL )
+ m_popupMenu->exec( pos );
+ }
+
+ void SideBar::startRenaming()
+ {
+ QListViewItem * item = m_listAvailableItems->selectedItem();
+ if ( item == NULL )
+ item = m_listAvailableItems->currentItem();
+
+ if ( item != NULL )
+ {
+ m_oldText = item->text( 1 );
+ item->setRenameEnabled( 1, TRUE );
+ item->startRename( 1 );
+ }
+ }
+
+ void SideBar::endRenaming( QListViewItem * item, int , const QString & text )
+ {
+ item->setRenameEnabled( 1, FALSE );
+ BibTeX::EntryField::FieldType fieldType = m_buttonToggleShowAll->isOn() ? ( BibTeX::EntryField::FieldType )( m_listTypeList->currentItem() + ( int ) BibTeX::EntryField::ftAbstract ) : importantFields[ m_listTypeList->currentItem()];
+ m_bibtexFile->replaceValue( m_oldText, text, fieldType );
+
+ m_listAvailableItems->clearSelection();
+ m_listAvailableItems->setSelected( item, true );
+ prepareSearch();
+
+ emit valueRenamed();
+ }
+
+ SideBarListViewItem::SideBarListViewItem( QListView *parent, QString label1, QString label2 ) : QListViewItem( parent, label1, label2 )
+ {
+// nothing
+ }
+
+ int SideBarListViewItem::compare( QListViewItem* item, int column, bool ascending ) const
+ {
+ if ( column == 0 )
+ {
+ bool ok = FALSE;
+ int ownValue = text( 0 ).toInt( &ok );
+ if ( ok )
+ {
+ int otherValue = item->text( 0 ).toInt( &ok );
+ if ( ok )
+ {
+ return ownValue < otherValue ? -1 : ( ownValue > otherValue ? 1 : 0 );
+ }
+ }
+ }
+
+ return QListViewItem::compare( item, column, ascending );
+ }
+}
+#include "sidebar.moc"
diff --git a/src/sidebar.h b/src/sidebar.h
new file mode 100644
index 0000000..250cd8c
--- /dev/null
+++ b/src/sidebar.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXSIDEBAR_H
+#define KBIBTEXSIDEBAR_H
+
+#include <qwidget.h>
+#include <qlistview.h>
+
+#include <entryfield.h>
+#include <file.h>
+
+class QComboBox;
+class QToolButton;
+class KListView;
+class QListViewItem;
+class KPopupMenu;
+
+namespace KBibTeX
+{
+ class SideBar : public QWidget
+ {
+ Q_OBJECT
+ public:
+ SideBar( bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~SideBar();
+
+ void restoreState();
+ void setReadOnly( bool isReadOnly );
+
+ signals:
+ void selected( const QString& text, BibTeX::Element::FilterType, BibTeX::EntryField::FieldType fieldType );
+ void valueRenamed();
+
+ public slots:
+ void refreshLists( BibTeX::File *bibtexFile = NULL );
+
+ protected:
+ void resizeEvent( QResizeEvent *event );
+
+ private:
+ BibTeX::File *m_bibtexFile;
+ QToolButton *m_buttonToggleShowAll;
+ QToolButton *m_buttonToggleMultiSelect;
+ QComboBox *m_listTypeList;
+ KListView *m_listAvailableItems;
+ static const BibTeX::EntryField::FieldType importantFields[ 6 ];
+ bool m_isReadOnly;
+ KPopupMenu *m_popupMenu;
+ QString m_oldText;
+
+ void setupGUI();
+
+ private slots:
+ void prepareSearch();
+ void toggleShowAll( bool showAll );
+ void toggleMultiSelect( bool showAll );
+ void showContextMenu( QListViewItem * item, const QPoint & pos );
+ void startRenaming();
+ void endRenaming( QListViewItem * item, int col, const QString & text );
+ };
+
+ class SideBarListViewItem: QListViewItem
+ {
+ public:
+ SideBarListViewItem( QListView *parent, QString label1, QString label2 );
+
+ int compare( QListViewItem* item, int column, bool ascending ) const;
+ };
+
+}
+
+#endif
diff --git a/src/value.cpp b/src/value.cpp
new file mode 100644
index 0000000..c31514e
--- /dev/null
+++ b/src/value.cpp
@@ -0,0 +1,465 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include "value.h"
+
+namespace BibTeX
+{
+
+ ValueTextInterface::ValueTextInterface( const ValueTextInterface* other ) : m_text( other->text() )
+ {
+// nothing
+ }
+
+ ValueTextInterface::ValueTextInterface( const QString& text ) : m_text( text )
+ {
+// nothing
+ }
+
+ void ValueTextInterface::setText( const QString& text )
+ {
+ m_text = text;
+ }
+
+ QString ValueTextInterface::text() const
+ {
+ return m_text;
+ }
+
+ QString ValueTextInterface::simplifiedText() const
+ {
+ return text().replace( QRegExp( "\\\\[A-Za-z0-9]+" ), "" ).replace( '{', "" ).replace( '}', "" );
+ }
+
+ void ValueTextInterface::replace( const QString &before, const QString &after )
+ {
+ if ( before == text() || before == simplifiedText() )
+ setText( after );
+ }
+
+ bool ValueTextInterface::containsPattern( const QString &pattern, bool caseSensitive )
+ {
+ return text().contains( pattern, caseSensitive ) || simplifiedText().contains( pattern, caseSensitive );
+ }
+
+ ValueItem::ValueItem( const QString& text ) : ValueTextInterface( text )
+ {
+// nothing
+ }
+
+ Keyword::Keyword( Keyword *other ) : ValueTextInterface( other )
+ {
+// nothing
+ }
+
+ Keyword::Keyword( const QString& text ) : ValueTextInterface( text )
+ {
+// nothing
+ }
+
+ Keyword *Keyword::clone()
+ {
+ return new Keyword( text() );
+ }
+
+ KeywordContainer::KeywordContainer(): ValueItem( "" )
+ {
+// nothing
+ }
+
+ KeywordContainer::KeywordContainer( const QString& text ) : ValueItem( text )
+ {
+ setText( text );
+ }
+
+ KeywordContainer::KeywordContainer( KeywordContainer *other ) : ValueItem( QString::null )
+ {
+ for ( QValueList<Keyword*>::Iterator it = other->keywords.begin(); it != other->keywords.end(); ++it )
+ keywords.append(( *it )->clone() );
+ }
+
+ KeywordContainer::KeywordContainer( const QStringList& list ) : ValueItem( QString::null )
+ {
+ setList( list );
+ }
+
+ ValueItem *KeywordContainer::clone()
+ {
+ return new KeywordContainer( this );
+ }
+
+ void KeywordContainer::setList( const QStringList& list )
+ {
+ keywords.clear();
+ for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
+ keywords.append( new Keyword( *it ) );
+ }
+
+ void KeywordContainer::append( const QString& text )
+ {
+ bool contains = FALSE;
+
+ for ( QValueList<Keyword*>::ConstIterator it = keywords.begin(); !contains && it != keywords.end(); ++it )
+ contains = QString::compare(( *it )->text(), text ) == 0;
+
+ if ( contains == 0 )
+ keywords.append( new Keyword( text ) );
+ }
+
+ void KeywordContainer::remove( const QString& text )
+ {
+ bool contains = FALSE;
+ for ( QValueList<Keyword*>::Iterator it = keywords.begin(); !contains && it != keywords.end(); ++it )
+ if ( QString::compare(( *it )->text(), text ) == 0 )
+ {
+ keywords.remove( it );
+ break;
+ }
+ }
+
+ void KeywordContainer::setText( const QString& text )
+ {
+ ValueItem::setText( text );
+
+ QRegExp splitRegExp;
+ if ( text.contains( ";" ) )
+ splitRegExp = QRegExp( "\\s*;\\s*" );
+ else
+ splitRegExp = QRegExp( "\\s*,\\s*" );
+
+ keywords.clear();
+ QStringList keywordList = QStringList::split( splitRegExp, text, FALSE );
+ for ( QStringList::ConstIterator it = keywordList.begin(); it != keywordList.end(); ++it )
+ keywords.append( new Keyword( *it ) );
+ }
+
+ QString KeywordContainer::text() const
+ {
+ QString result;
+ bool first = true;
+ for ( QValueList<Keyword*>::ConstIterator it = keywords.begin(); it != keywords.end(); ++it )
+ {
+ if ( !first )
+ result.append( "; " );
+ else first = false;
+ result.append(( *it )->text() );
+ }
+ return result;
+ }
+
+ void KeywordContainer::replace( const QString &before, const QString &after )
+ {
+ for ( QValueList<Keyword*>::ConstIterator it = keywords.begin(); it != keywords.end(); ++it )
+ ( *it )->replace( before, after );
+ }
+
+ Person::Person( const QString& text, bool firstNameFirst ) : ValueTextInterface( text ), m_firstNameFirst( firstNameFirst )
+ {
+ setText( text );
+ }
+
+ Person::Person( const QString& firstName, const QString& lastName, bool firstNameFirst ) : ValueTextInterface( QString( firstName ).append( " " ).append( lastName ) ), m_firstName( firstName ), m_lastName( lastName ), m_firstNameFirst( firstNameFirst )
+ {
+// nothing
+ }
+
+ Person *Person::clone()
+ {
+ return new Person( m_firstName, m_lastName, m_firstNameFirst );
+ }
+
+ void Person::setText( const QString& text )
+ {
+ ValueTextInterface::setText( text );
+
+ QStringList segments;
+ bool containsComma = splitName( text, segments );
+ m_firstName = "";
+ m_lastName = "";
+
+ if ( segments.isEmpty() )
+ return;
+
+ if ( !containsComma )
+ {
+ /** PubMed uses a special writing style for names, where the last name is followed by single capital letter, each being the first letter of each first name */
+ /** So, check how many single capital letters are at the end of the given segment list */
+ int singleCapitalLettersCounter = 0;
+ int p = segments.count() - 1;
+ while ( segments[p].length() == 1 && segments[p].compare( segments[p].upper() ) == 0 )
+ {
+ --p;
+ ++singleCapitalLettersCounter;
+ }
+
+ if ( singleCapitalLettersCounter > 0 )
+ {
+ /** this is a special case for names from PubMed, which are formatted like "Fischer T" */
+ /** all segment values until the first single letter segment are last name parts */
+ for ( int i = 0; i < p; ++i )
+ m_lastName.append( segments[i] ).append( " " );
+ m_lastName.append( segments[p] );
+ /** single letter segments are first name parts */
+ for ( unsigned int i = p + 1; i < segments.count() - 1; ++i )
+ m_firstName.append( segments[i] ).append( " " );
+ m_firstName.append( segments[segments.count() - 1] );
+ }
+ else
+ {
+ int from = segments.count() - 1;
+ m_lastName = segments[from];
+ /** check for lower case parts of the last name such as "van", "von", "de", ... */
+ while ( from > 0 )
+ {
+ if ( segments[from - 1].compare( segments[from - 1].lower() ) != 0 )
+ break;
+ --from;
+ m_lastName.prepend( " " );
+ m_lastName.prepend( segments[from] );
+ }
+
+ if ( from > 0 )
+ {
+ /** there are segments left for the first name */
+ m_firstName = *segments.begin();
+ for ( QStringList::Iterator it = ++segments.begin(); from > 1; ++it, --from )
+ {
+ m_firstName.append( " " );
+ m_firstName.append( *it );
+ }
+ }
+ }
+ }
+ else
+ {
+ bool inLastName = TRUE;
+ for ( unsigned int i = 0; i < segments.count();++i )
+ {
+ if ( segments[i] == "," )
+ inLastName = FALSE;
+ else if ( inLastName )
+ {
+ if ( !m_lastName.isEmpty() ) m_lastName.append( " " );
+ m_lastName.append( segments[i] );
+ }
+ else
+ {
+ if ( !m_firstName.isEmpty() ) m_firstName.append( " " );
+ m_firstName.append( segments[i] );
+ }
+ }
+ }
+ }
+
+ QString Person::text() const
+ {
+ return text( m_firstNameFirst );
+ }
+
+ QString Person::text( bool firstNameFirst ) const
+ {
+
+ if ( m_firstName.isEmpty() )
+ return m_lastName;
+ else
+ return firstNameFirst ? m_firstName + " " + m_lastName : m_lastName + ", " + m_firstName;
+ }
+
+ QString Person::firstName()
+ {
+ return m_firstName;
+ }
+ QString Person::lastName()
+ {
+ return m_lastName;
+ }
+
+ /** Splits a name into single words. If the name's text was reversed (Last, First), the result will be true and the comma will be added to segments. Otherwise the functions result will be false. This function respects protecting {...}. */
+ bool Person::splitName( const QString& text, QStringList& segments )
+ {
+ int bracketCounter = 0;
+ bool result = FALSE;
+ QString buffer = "";
+
+ for ( unsigned int pos = 0; pos < text.length(); ++pos )
+ {
+ if ( text[pos] == '{' )
+ ++bracketCounter;
+ else if ( text[pos] == '}' )
+ --bracketCounter;
+
+ if ( text[pos] == ' ' && bracketCounter == 0 )
+ {
+ if ( !buffer.isEmpty() )
+ {
+ segments.append( buffer );
+ buffer = "";
+ }
+ }
+ else if ( text[pos] == ',' && bracketCounter == 0 )
+ {
+ if ( !buffer.isEmpty() )
+ {
+ segments.append( buffer );
+ buffer = "";
+ }
+ segments.append( "," );
+ result = TRUE;
+ }
+ else
+ buffer.append( text[pos] );
+ }
+
+ if ( !buffer.isEmpty() )
+ segments.append( buffer );
+
+ return result;
+ }
+
+ PersonContainer::PersonContainer( bool firstNameFirst ) : ValueItem( QString::null ), m_firstNameFirst( firstNameFirst )
+ {
+ // nothing
+ }
+
+ PersonContainer::PersonContainer( const QString& text, bool firstNameFirst ) : ValueItem( text ), m_firstNameFirst( firstNameFirst )
+ {
+ persons.append( new Person( text, m_firstNameFirst ) );
+ }
+
+ ValueItem *PersonContainer::clone()
+ {
+ PersonContainer *result = new PersonContainer( m_firstNameFirst );
+ for ( QValueList<Person*>::ConstIterator it = persons.begin(); it != persons.end(); ++it )
+ result->persons.append(( *it )->clone() );
+
+ return result;
+ }
+
+ void PersonContainer::setText( const QString& text )
+ {
+ ValueTextInterface::setText( text );
+ qDebug( "You cannot set a text ('%s') to a Value object", text.latin1() );
+ }
+
+ QString PersonContainer::text() const
+ {
+ QString result;
+ bool first = TRUE;
+
+ for ( QValueList<Person*>::ConstIterator it = persons.begin(); it != persons.end(); ++it )
+ {
+ if ( !first )
+ result.append( " and " );
+ else
+ first = FALSE;
+ result.append(( *it )->text() );
+ }
+
+ return result;
+ }
+
+ void PersonContainer::replace( const QString &before, const QString &after )
+ {
+ for ( QValueList<Person*>::ConstIterator it = persons.begin(); it != persons.end(); ++it )
+ ( *it )->replace( before, after );
+ }
+
+ MacroKey::MacroKey( const QString& text ) : ValueItem( text )
+ {
+ m_isValid = isValidInternal();
+ }
+
+ ValueItem *MacroKey::clone()
+ {
+ return new MacroKey( text() );
+ }
+
+ void MacroKey::setText( const QString& text )
+ {
+ ValueItem::setText( text );
+ m_isValid = isValidInternal();
+ }
+
+ bool MacroKey::isValid()
+ {
+ return m_isValid;
+ }
+
+ bool MacroKey::isValidInternal()
+ {
+ return !text().contains( QRegExp( "![-.:/+_a-zA-Z0-9]" ) );
+ }
+
+ PlainText::PlainText( const QString& text ) : ValueItem( text )
+ {
+ // nothing
+ }
+
+ ValueItem *PlainText::clone()
+ {
+ return new PlainText( text() );
+ }
+
+ Value::Value() : ValueTextInterface( QString::null )
+ {
+ // nothing
+ }
+
+ Value::Value( const Value *other ) : ValueTextInterface( other )
+ {
+ for ( QValueList<ValueItem*>::ConstIterator it = other->items.begin(); it != other->items.end(); ++it )
+ items.append(( *it )->clone() );
+ }
+
+ Value::Value( const QString& text, bool isMacroKey ): ValueTextInterface( text )
+ {
+ ValueItem *item = NULL;
+ if ( isMacroKey )
+ item = new MacroKey( text );
+ else
+ item = new PlainText( text );
+ items.append( item );
+ }
+
+ void Value::setText( const QString& text )
+ {
+ ValueTextInterface::setText( text );
+ qDebug( "You cannot set a text ('%s') to a Value object", text.latin1() );
+ }
+
+ QString Value::text() const
+ {
+ QString result;
+
+ for ( QValueList<ValueItem*>::ConstIterator it = items.begin(); it != items.end(); ++it )
+ result.append(( *it )->text() );
+
+ return result;
+ }
+
+ void Value::replace( const QString &before, const QString &after )
+ {
+ for ( QValueList<ValueItem*>::ConstIterator it = items.begin(); it != items.end(); ++it )
+ ( *it )->replace( before, after );
+ }
+}
diff --git a/src/value.h b/src/value.h
new file mode 100644
index 0000000..3c7d876
--- /dev/null
+++ b/src/value.h
@@ -0,0 +1,162 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXVALUE_H
+#define BIBTEXVALUE_H
+
+#include <qvaluelist.h>
+
+class QStringList;
+
+namespace BibTeX
+{
+ class ValueTextInterface
+ {
+ public:
+ ValueTextInterface( const ValueTextInterface* other );
+ ValueTextInterface( const QString& text );
+ virtual ~ValueTextInterface() {};
+
+ virtual void setText( const QString& text );
+ virtual QString text() const;
+ QString simplifiedText() const;
+ virtual void replace( const QString &before, const QString &after );
+ virtual bool containsPattern( const QString &pattern, bool caseSensitive );
+
+ private:
+ QString m_text;
+ };
+
+ class ValueItem: public ValueTextInterface
+ {
+ public:
+ ValueItem( const QString& text );
+
+ virtual ValueItem *clone()
+ {
+ return NULL;
+ };
+ };
+
+ class Keyword: public ValueTextInterface
+ {
+ public:
+ Keyword( Keyword *other );
+ Keyword( const QString& text );
+
+ Keyword *clone();
+ };
+
+ class KeywordContainer: public ValueItem
+ {
+ public:
+ KeywordContainer();
+ KeywordContainer( const QString& text );
+ KeywordContainer( KeywordContainer *other );
+ KeywordContainer( const QStringList& list );
+
+ ValueItem *clone();
+ void setList( const QStringList& list );
+ void append( const QString& text );
+ void remove( const QString& text );
+ void setText( const QString& text );
+ QString text() const;
+ void replace( const QString &before, const QString &after );
+
+ QValueList<Keyword*> keywords;
+ };
+
+ class Person: public ValueTextInterface
+ {
+ public:
+ Person( const QString& text, bool firstNameFirst = FALSE );
+ Person( const QString& firstName, const QString& lastName, bool firstNameFirst = FALSE );
+
+ Person *clone();
+ void setText( const QString& text );
+ QString text() const;
+ QString text( bool firstNameFirst ) const;
+
+ QString firstName();
+ QString lastName();
+
+ protected:
+ QString m_firstName;
+ QString m_lastName;
+ bool m_firstNameFirst;
+
+ bool splitName( const QString& text, QStringList& segments );
+ };
+
+ class PersonContainer: public ValueItem
+ {
+ public:
+ PersonContainer( bool firstNameFirst = FALSE );
+ PersonContainer( const QString& text, bool firstNameFirst = FALSE );
+
+ ValueItem *clone();
+ void setText( const QString& text );
+ QString text() const;
+ void replace( const QString &before, const QString &after );
+
+ QValueList<Person*> persons;
+
+ private:
+ bool m_firstNameFirst;
+ };
+
+ class MacroKey: public ValueItem
+ {
+ private:
+ bool m_isValid;
+ bool isValidInternal();
+
+ public:
+ MacroKey( const QString& text );
+
+ ValueItem *clone();
+
+ void setText( const QString& text );
+ bool isValid();
+ };
+
+ class PlainText: public ValueItem
+ {
+ public:
+ PlainText( const QString& text );
+
+ ValueItem *clone();
+ };
+
+ class Value: public ValueTextInterface
+ {
+ public:
+ Value();
+ Value( const Value *other );
+ Value( const QString& text, bool isMacroKey = false );
+
+ void setText( const QString& text );
+ QString text() const;
+ void replace( const QString &before, const QString &after );
+
+ QValueList<ValueItem*> items;
+ };
+}
+
+#endif
diff --git a/src/valuewidget.cpp b/src/valuewidget.cpp
new file mode 100644
index 0000000..1455a9e
--- /dev/null
+++ b/src/valuewidget.cpp
@@ -0,0 +1,254 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qlistview.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qheader.h>
+#include <qpushbutton.h>
+
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <value.h>
+#include <settings.h>
+#include "valuewidget.h"
+
+namespace KBibTeX
+{
+
+ QDialog::DialogCode ValueWidget::execute( const QString& title, BibTeX::EntryField::FieldType fieldType, BibTeX::Value *value, bool isReadOnly, QWidget *parent, const char *name )
+ {
+ KDialogBase * dlg = new KDialogBase( parent, name, TRUE, QString( i18n( "Edit field '%1'" ) ).arg( title ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, TRUE );
+
+ ValueWidget* valueWidget = new ValueWidget( fieldType, value, isReadOnly, dlg, "kbibtexvaluewidget" );
+ dlg->setMainWidget( valueWidget );
+ connect( dlg, SIGNAL( okClicked() ), valueWidget, SLOT( apply() ) );
+
+ QDialog::DialogCode result = ( QDialog::DialogCode )dlg->exec();
+ if ( isReadOnly ) result = QDialog::Rejected;
+
+ delete( valueWidget );
+ delete( dlg );
+
+ return result;
+ }
+
+ ValueWidget::ValueWidget( BibTeX::EntryField::FieldType fieldType, BibTeX::Value *value, bool isReadOnly, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_fieldType( fieldType ), m_value( value ), m_newValueCounter( 0 ), m_isReadOnly( isReadOnly )
+ {
+ setupGUI();
+ reset();
+ updateGUI();
+ }
+
+
+ ValueWidget::~ValueWidget()
+ {
+ // nothing
+ }
+
+ void ValueWidget::applyList( QStringList& list )
+ {
+ if ( m_fieldType == BibTeX::EntryField::ftKeywords )
+ {
+ BibTeX::KeywordContainer *container = new BibTeX::KeywordContainer();
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ container->keywords.append( new BibTeX::Keyword( *it ) );
+ m_value->items.append( container );
+ }
+ else if ( m_fieldType == BibTeX::EntryField::ftAuthor || m_fieldType == BibTeX::EntryField::ftEditor )
+ {
+ Settings * settings = Settings::self();
+ BibTeX::PersonContainer *container = new BibTeX::PersonContainer();
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ container->persons.append( new BibTeX::Person( *it, settings->editing_FirstNameFirst ) );
+ m_value->items.append( container );
+ }
+ else
+ {
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ m_value->items.append( new BibTeX::PlainText( *it ) );
+ }
+
+ list.clear();
+ }
+
+ void ValueWidget::apply( )
+ {
+ if ( m_isReadOnly ) return;
+
+ QStringList list;
+ m_value->items.clear();
+ QListViewItem *item = m_listViewValue->firstChild();
+ while ( item != NULL )
+ {
+ QCheckListItem * checkItem = dynamic_cast<QCheckListItem*>( item );
+ QString text = checkItem->text( 0 );
+
+ if ( checkItem->state() == QCheckListItem::On )
+ {
+ if ( !list.isEmpty() ) applyList( list );
+ m_value->items.append( new BibTeX::MacroKey( text ) );
+ }
+ else
+ list.append( text );
+ item = item->nextSibling();
+ }
+
+ if ( !list.isEmpty() )
+ applyList( list );
+ }
+
+ void ValueWidget::reset( )
+ {
+ m_listViewValue->clear();
+
+ QCheckListItem *after = NULL;
+ for ( QValueList<BibTeX::ValueItem*>::ConstIterator it = m_value->items.begin(); it != m_value->items.end(); ++it )
+ {
+ BibTeX::MacroKey *macroKey = dynamic_cast<BibTeX::MacroKey*>( *it );
+ QCheckListItem *item = new QCheckListItem( m_listViewValue, after, ( *it )->text(), QCheckListItem::CheckBox );
+ after = item;
+ item->setState( macroKey != NULL ? QCheckListItem::On : QCheckListItem::Off );
+ item->setRenameEnabled( 0, !m_isReadOnly );
+ }
+ }
+
+ void ValueWidget::slotAdd()
+ {
+ QCheckListItem * item = new QCheckListItem( m_listViewValue, m_listViewValue->lastItem(), QString( i18n( "May only contain ASCII characters, in case of doubt keep English form", "NewValue%1" ) ).arg( m_newValueCounter++ ), QCheckListItem::CheckBox );
+ item->setState( QCheckListItem::Off );
+ item->setRenameEnabled( 0, !m_isReadOnly );
+ m_listViewValue->setSelected( item, TRUE );
+ slotEdit();
+ }
+
+ void ValueWidget::slotEdit()
+ {
+ QListViewItem * item = m_listViewValue->selectedItem();
+ if ( item != NULL )
+ item->startRename( 0 );
+ }
+
+ void ValueWidget::slotToggle()
+ {
+ QListViewItem * item = m_listViewValue->selectedItem();
+ if ( item != NULL )
+ {
+ QCheckListItem * checkItem = dynamic_cast<QCheckListItem*>( item );
+ if ( checkItem != NULL )
+ checkItem->setOn( !checkItem->isOn() );
+ }
+ }
+
+ void ValueWidget::slotDelete()
+ {
+ QListViewItem * item = m_listViewValue->selectedItem();
+ if ( item != NULL )
+ delete item;
+ updateGUI();
+ }
+
+ void ValueWidget::slotUp()
+ {
+ QListViewItem * item = m_listViewValue->selectedItem();
+ if ( item != NULL && item -> itemAbove() != NULL )
+ {
+ item->itemAbove() ->moveItem( item );
+ updateGUI();
+ }
+ }
+
+ void ValueWidget::slotDown()
+ {
+ QListViewItem * item = m_listViewValue->selectedItem();
+ if ( item != NULL && item -> itemBelow() != NULL )
+ {
+ item->moveItem( item->itemBelow() );
+ updateGUI();
+ }
+ }
+
+ void ValueWidget::updateGUI()
+ {
+ bool isElementSelected = m_listViewValue->selectedItem() != NULL;
+ m_pushButtonEdit->setEnabled( !m_isReadOnly && isElementSelected );
+ m_pushButtonToggle->setEnabled( !m_isReadOnly && isElementSelected );
+ m_pushButtonDelete->setEnabled( !m_isReadOnly && isElementSelected );
+ m_pushButtonUp->setEnabled( !m_isReadOnly && isElementSelected && m_listViewValue->selectedItem() != m_listViewValue->firstChild() );
+ m_pushButtonDown->setEnabled( !m_isReadOnly && isElementSelected && m_listViewValue->selectedItem() != m_listViewValue->lastItem() );
+ }
+
+ void ValueWidget::setupGUI()
+ {
+ QGridLayout * layout = new QGridLayout( this, 8, 2, 0, KDialog::spacingHint() );
+ layout->setRowStretch( 7, 1 );
+
+ QLabel *label = new QLabel( i18n( "Checked entries are string keys, unchecked entries are quoted text." ), this );
+ layout->addWidget( label, 0, 0 );
+
+ m_listViewValue = new QListView( this );
+ layout->addMultiCellWidget( m_listViewValue, 1, 7, 0, 0 );
+ m_listViewValue->setDefaultRenameAction( m_isReadOnly ? QListView::Reject : QListView::Accept );
+ m_listViewValue->addColumn( i18n( "Text" ) );
+ m_listViewValue->setSorting( -1, TRUE );
+ m_listViewValue->setAllColumnsShowFocus( TRUE );
+ m_listViewValue->header() ->setClickEnabled( FALSE );
+ m_listViewValue->header() ->setStretchEnabled( TRUE, 0 );
+ m_listViewValue->setEnabled( !m_isReadOnly );
+ connect( m_listViewValue, SIGNAL( selectionChanged() ), this, SLOT( updateGUI() ) );
+ connect( m_listViewValue, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+ connect( m_listViewValue, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( updateGUI() ) );
+
+ m_pushButtonAdd = new QPushButton( i18n( "Add" ), this );
+ layout->addWidget( m_pushButtonAdd, 1, 1 );
+ m_pushButtonAdd->setIconSet( QIconSet( SmallIcon( "add" ) ) );
+ m_pushButtonAdd->setEnabled( !m_isReadOnly );
+ connect( m_pushButtonAdd, SIGNAL( clicked() ), this, SLOT( slotAdd() ) );
+
+ m_pushButtonEdit = new QPushButton( i18n( "Edit" ), this );
+ layout->addWidget( m_pushButtonEdit, 2, 1 );
+ m_pushButtonEdit->setIconSet( QIconSet( SmallIcon( "edit" ) ) );
+ connect( m_pushButtonEdit, SIGNAL( clicked() ), this, SLOT( slotEdit() ) );
+
+ m_pushButtonToggle = new QPushButton( i18n( "Toggle" ), this );
+ layout->addWidget( m_pushButtonToggle, 3, 1 );
+ m_pushButtonToggle->setIconSet( QIconSet( SmallIcon( "flag" ) ) );
+ connect( m_pushButtonToggle, SIGNAL( clicked() ), this, SLOT( slotToggle() ) );
+
+ m_pushButtonDelete = new QPushButton( i18n( "Delete" ), this );
+ layout->addWidget( m_pushButtonDelete, 4, 1 );
+ m_pushButtonDelete->setIconSet( QIconSet( SmallIcon( "editdelete" ) ) );
+ connect( m_pushButtonDelete, SIGNAL( clicked() ), this, SLOT( slotDelete() ) );
+
+ m_pushButtonUp = new QPushButton( i18n( "Up" ), this );
+ layout->addWidget( m_pushButtonUp, 5, 1 );
+ m_pushButtonUp->setIconSet( QIconSet( SmallIcon( "up" ) ) );
+ connect( m_pushButtonUp, SIGNAL( clicked() ), this, SLOT( slotUp() ) );
+
+ m_pushButtonDown = new QPushButton( i18n( "Down" ), this );
+ layout->addWidget( m_pushButtonDown, 6, 1 );
+ m_pushButtonDown->setIconSet( QIconSet( SmallIcon( "down" ) ) );
+ connect( m_pushButtonDown, SIGNAL( clicked() ), this, SLOT( slotDown() ) );
+ }
+
+}
+#include "valuewidget.moc"
diff --git a/src/valuewidget.h b/src/valuewidget.h
new file mode 100644
index 0000000..094bf1a
--- /dev/null
+++ b/src/valuewidget.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXVALUEWIDGET_H
+#define KBIBTEXVALUEWIDGET_H
+
+#include <qwidget.h>
+#include <qdialog.h>
+
+#include <value.h>
+#include <entryfield.h>
+
+class QListView;
+class QPushButton;
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class ValueWidget : public QWidget
+ {
+ Q_OBJECT
+ public:
+ static QDialog::DialogCode execute( const QString& title, BibTeX::EntryField::FieldType fieldType, BibTeX::Value *value, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+
+ private slots:
+ void apply( );
+ void reset( );
+ void slotAdd();
+ void slotEdit();
+ void slotToggle();
+ void slotDelete();
+ void slotUp();
+ void slotDown();
+ void updateGUI();
+
+ private:
+ BibTeX::EntryField::FieldType m_fieldType;
+ BibTeX::Value *m_value;
+ QListView *m_listViewValue;
+ QPushButton *m_pushButtonAdd;
+ QPushButton *m_pushButtonEdit;
+ QPushButton *m_pushButtonToggle;
+ QPushButton *m_pushButtonDelete;
+ QPushButton *m_pushButtonUp;
+ QPushButton *m_pushButtonDown;
+ int m_newValueCounter;
+ bool m_isReadOnly;
+
+ ValueWidget( BibTeX::EntryField::FieldType fieldType, BibTeX::Value *value, bool isReadOnly, QWidget *parent = 0, const char *name = 0 );
+ ~ValueWidget();
+
+ void setupGUI();
+ void applyList( QStringList& list );
+ };
+
+}
+
+#endif
diff --git a/src/webquery.cpp b/src/webquery.cpp
new file mode 100644
index 0000000..f1b44e3
--- /dev/null
+++ b/src/webquery.cpp
@@ -0,0 +1,637 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qtimer.h>
+#include <qheader.h>
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qframe.h>
+#include <qwidgetstack.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qapplication.h>
+#include <qeventloop.h>
+#include <qbuffer.h>
+
+#include <klocale.h>
+#include <kcombobox.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kurllabel.h>
+#include <klineedit.h>
+#include <kapplication.h>
+#include <kpushbutton.h>
+#include <kprogress.h>
+#include <kcompletion.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kwin.h>
+
+#include <settings.h>
+#include <idsuggestions.h>
+#include <entrywidget.h>
+#include <webqueryarxiv.h>
+#include <webquerybibsonomy.h>
+#include <webquerycsb.h>
+#include <webquerycitebase.h>
+#include <webqueryciteseerx.h>
+#include <webquerydblp.h>
+#include <webquerygooglescholar.h>
+#include <webqueryieeexplore.h>
+#include <webquerymathscinet.h>
+#include <webquerypubmed.h>
+#include <webquerysciencedirect.h>
+#include <webqueryspireshep.h>
+#ifdef HAVE_YAZ
+#include <webqueryz3950.h>
+#endif // HAVE_YAZ
+#include <webqueryzmath.h>
+#include "webquery.h"
+
+#define min(a,b) ((a)>(b)?(b):(a))
+
+namespace KBibTeX
+{
+ WebQueryWidget::WebQueryWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name ), lineEditQuery( NULL ), spinBoxMaxHits( NULL )
+ {
+// nothing
+ }
+
+ bool WebQueryWidget::searchPossible()
+ {
+ return lineEditQuery != NULL && !lineEditQuery->text().stripWhiteSpace().replace( '$', "" ).isEmpty();
+ }
+
+ void WebQueryWidget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearSearchText );
+ QLabel *label = new QLabel( i18n( "Search &term:" ), this );
+ hLayout->addWidget( label );
+ lineEditQuery = new KLineEdit( this );
+ hLayout->addWidget( lineEditQuery );
+ label->setBuddy( lineEditQuery );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ hLayout->setStretchFactor( lineEditQuery, 4 );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+
+ label = new QLabel( i18n( "&Number of results:" ), this );
+ hLayout->addWidget( label );
+ spinBoxMaxHits = new QSpinBox( 1, 250, 1, this );
+ spinBoxMaxHits->setValue( 10 );
+ hLayout->addWidget( spinBoxMaxHits );
+ label->setBuddy( spinBoxMaxHits );
+
+ vLayout->addStretch( 0 );
+
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+ }
+
+ void WebQueryWidget::slotTextChanged( const QString& text )
+ {
+ slotTextChanged( text, false );
+ }
+
+ void WebQueryWidget::slotTextChanged( const QString& text, bool delayed )
+ {
+ bool doEnable = !text.stripWhiteSpace().replace( '$', "" ).isEmpty();
+ if ( delayed && doEnable )
+ QTimer::singleShot( 100, this, SLOT( slotEnableSearchTrue() ) );
+ else if ( !delayed )
+ emit enableSearch( doEnable );
+ }
+
+ void WebQueryWidget::slotEnableSearchTrue()
+ {
+ emit enableSearch( true );
+ }
+
+ WebQuery::WebQuery( QWidget *parent ): QObject(), m_parent( parent ), m_progressDialog( NULL ), m_currentJob( NULL )
+ {
+// nothing
+ }
+
+ WebQuery::~WebQuery()
+ {
+ if ( m_progressDialog != NULL )
+ delete m_progressDialog;
+ }
+
+ void WebQuery::query()
+ {
+ if ( m_progressDialog != NULL )
+ delete m_progressDialog;
+ m_aborted = false;
+ m_progressDialog = new KProgressDialog( m_parent, "WebQuery_progressDialog", i18n( "Searching" ), QString( i18n( "Searching %1" ) ).arg( title() ) );
+ m_progressDialog->progressBar()->setMinimumWidth( 256 );
+ m_progressDialog->setAutoClose( true );
+ m_progressDialog->setMinimumDuration( 10 );
+ m_progressDialog->setEnabled( true );
+ connect( m_progressDialog, SIGNAL( cancelClicked() ), this, SLOT( slotCancelQuery() ) );
+ }
+
+ void WebQuery::cancelQuery()
+ {
+ // nothing
+ }
+
+ void WebQuery::slotCancelQuery()
+ {
+ m_aborted = true;
+ cancelQuery();
+ }
+
+ void WebQuery::setEndSearch( WebQuery::Status status )
+ {
+ if ( m_progressDialog != NULL )
+ m_progressDialog->hide();
+ emit endSearch( status );
+ }
+
+ void WebQuery::setNumStages( int numStages )
+ {
+ m_currentStage = 0;
+ m_numStages = numStages;
+ m_progressDialog->progressBar()->setTotalSteps( m_numStages * 100 );
+ }
+
+ void WebQuery::enterNextStage()
+ {
+ ++m_currentStage;
+ if ( m_progressDialog != NULL )
+ m_progressDialog->progressBar()->setProgress( m_currentStage * 100 );
+ }
+
+ QString WebQuery::download( const KURL& url )
+ {
+ QString data = downloadHTML( url );
+ if ( data == QString::null )
+ return QString::null;
+
+ /** post-processing */
+ if ( data != QString::null )
+ {
+ data.replace( QRegExp( "</?(p|br)[^>]*>" ), "\n" );
+ data.replace( QRegExp( "</?[^>]*>" ), "" );
+ data.replace( "@import", "" );/// JavaScript import?
+ }
+
+ return data;
+ }
+
+ QString WebQuery::downloadHTML( const KURL& url )
+ {
+ if ( m_currentJob != NULL ) return QString::null;
+
+ qDebug( "WebQuery::download( %s )", url.prettyURL().latin1() );
+
+ m_incomingData = "";
+ m_currentJobTotalSize = -1;
+ m_currentJob = KIO::get( url, false, false );
+ connect( m_currentJob, SIGNAL( totalSize( KIO::Job*, KIO::filesize_t ) ), this, SLOT( slotSetJobTotalSize( KIO::Job*, KIO::filesize_t ) ) );
+ connect( m_currentJob, SIGNAL( processedSize( KIO::Job*, KIO::filesize_t ) ), this, SLOT( slotSetJobProcessedSize( KIO::Job*, KIO::filesize_t ) ) );
+ connect( m_currentJob, SIGNAL( data( KIO::Job*, const QByteArray & ) ), this, SLOT( slotJobData( KIO::Job*, const QByteArray & ) ) );
+ connect( m_currentJob, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotJobFinished( KIO::Job* ) ) );
+
+ qApp->eventLoop()->enterLoop();
+
+ return m_incomingData;
+ }
+
+ BibTeX::File *WebQuery::downloadBibTeXFile( const KURL& url, QTextStream::Encoding encoding )
+ {
+ QString data = download( url );
+ if ( data == QString::null )
+ return NULL;
+
+ BibTeX::FileImporterBibTeX importer( FALSE );
+ importer.setIgnoreComments( TRUE );
+ QBuffer buffer;
+
+ buffer.open( IO_WriteOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( encoding );
+ ts << data << endl;
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ BibTeX::File *result = importer.load( &buffer );
+ buffer.close();
+
+ return result;
+ }
+
+ void WebQuery::slotSetJobTotalSize( KIO::Job *job, KIO::filesize_t size )
+ {
+ if ( job != m_currentJob ) return;
+ m_currentJobTotalSize = size;
+ }
+
+ void WebQuery::slotSetJobProcessedSize( KIO::Job *job, KIO::filesize_t size )
+ {
+ if ( job != m_currentJob ) return;
+ if ( m_currentJobTotalSize <= 0 ) m_currentJobTotalSize = size;
+ m_progressDialog->progressBar()->setProgress( m_currentStage * 100 + min( 100, size * 100 / m_currentJobTotalSize ) );
+ }
+
+ void WebQuery::slotJobData( KIO::Job *job, const QByteArray &data )
+ {
+ if ( job != m_currentJob ) return;
+ QCString dataStr = QCString( data, data.size() + 1 );
+ if ( data.size() > 0 )
+ m_incomingData.append( dataStr );
+ }
+
+ void WebQuery::slotJobFinished( KIO::Job *job )
+ {
+ if ( job != m_currentJob ) return;
+ m_currentJob = NULL;
+ if ( job->error() )
+ {
+ job->showErrorDialog();
+ m_incomingData = QString::null;
+ }
+ enterNextStage();
+ qApp->eventLoop()->exitLoop();
+ }
+
+ WebQueryWizard::WebQueryWizard( KDialogBase *dlg, const char* name ) : QWidget( dlg, name ), m_dlg( dlg ), m_pushButtonSearch( NULL )
+ {
+ setupGUI( );
+
+ Settings *settings = Settings::self( NULL );
+ m_comboBoxEngines->setCurrentItem( settings->webQuery_LastEngine );
+ otherEngineSelected( settings->webQuery_LastEngine );
+ m_checkBoxImportAll->setChecked( settings->webQuery_ImportAll );
+ m_pushButtonSearch->setEnabled( false );
+ }
+
+ WebQueryWizard::~WebQueryWizard()
+ {
+ KConfig * config = kapp->config();
+ config->setGroup( "WebQueryWizard" );
+ saveWindowSize( config );
+ }
+
+ void WebQueryWizard::showEvent( QShowEvent * )
+ {
+ KConfig * config = kapp->config();
+ config->setGroup( "WebQueryWizard" );
+ restoreWindowSize( config );
+ }
+
+ int WebQueryWizard::execute( QWidget *parent, QValueList<BibTeX::Entry*> &results )
+ {
+ KDialogBase *dlg = new KDialogBase( parent, "WebQueryWizard", true, i18n( "Import" ), KDialogBase::Ok | KDialogBase::Cancel, ( KDialogBase::ButtonCode )0, true );
+ WebQueryWizard *wiz = new WebQueryWizard( dlg, "WebQueryWizard" );
+ dlg->setButtonOK( KGuiItem( i18n( "&Import" ), "import", i18n( "Import selected items" ) ) );
+ dlg->setMainWidget( wiz );
+ connect( wiz, SIGNAL( changeButtonOK( bool ) ), dlg, SLOT( enableButtonOK( bool ) ) );
+ dlg->enableButtonOK( false );
+
+ results.clear();
+ int result = dlg->exec();
+ if ( result == QDialog::Accepted )
+ {
+ QListViewItemIterator it = wiz->m_checkBoxImportAll->isChecked() ? QListViewItemIterator( wiz->m_listViewResults ) : QListViewItemIterator( wiz->m_listViewResults, QListViewItemIterator::Selected );
+ while ( it.current() )
+ {
+ ResultsListViewItem *item = dynamic_cast<ResultsListViewItem*>( it.current() );
+ results.append( new BibTeX::Entry( item->entry() ) );
+ ++it;
+ }
+ }
+
+ Settings *settings = Settings::self( NULL );
+ settings->webQuery_LastEngine = wiz->m_comboBoxEngines->currentItem();
+ settings->webQuery_ImportAll = wiz->m_checkBoxImportAll->isChecked();
+
+ delete dlg;
+
+ return result;
+ }
+
+ void WebQueryWizard::previewEntry( QListViewItem *item )
+ {
+ ResultsListViewItem *rlvi = dynamic_cast<ResultsListViewItem*>( item );
+ if ( rlvi != NULL )
+ {
+ BibTeX::Entry *entry = rlvi->entry();
+ KBibTeX::EntryWidget::execute( entry, NULL, TRUE, FALSE );
+ }
+ }
+
+ void WebQueryWizard::importEnableChanging( )
+ {
+ QListViewItemIterator it( m_listViewResults, QListViewItemIterator::Selected );
+
+ emit changeButtonOK(( m_checkBoxImportAll->isChecked() && m_listViewResults->childCount() > 0 ) || it.current() != NULL );
+ }
+
+ void WebQueryWizard::otherEngineSelected( int index )
+ {
+ if ( index < 0 || index >= ( int )m_webQueries.size() ) return;
+
+ m_pushButtonSearch->setCaption( QString( i18n( "Search %1" ) ).arg( m_webQueries[index]->title() ) );
+ m_disclaimerLabel->setText( m_webQueries[index]->disclaimer() );
+ m_disclaimerLabel->setURL( m_webQueries[index]->disclaimerURL() );
+ QToolTip::remove( m_disclaimerLabel );
+ QToolTip::add( m_disclaimerLabel, m_webQueries[index]->disclaimerURL() );
+ m_widgetStackQueries->raiseWidget( m_webQueries[index]->widget() );
+ m_pushButtonSearch->setEnabled( m_webQueries[index]->widget()->searchPossible() );
+ }
+
+ void WebQueryWizard::startSearch()
+ {
+ if ( !m_pushButtonSearch->isEnabled() )
+ {
+ kdDebug() << "WebQueryWizard::startSearch not enabled" << endl;
+ return;
+ }
+
+ int index = m_comboBoxEngines->currentItem();
+
+ setEnabled( FALSE );
+ m_dlg->enableButtonCancel( FALSE );
+ QApplication::setOverrideCursor( Qt::waitCursor );
+ m_listViewResults->clear();
+ connect( m_webQueries[index], SIGNAL( foundEntry( BibTeX::Entry*, bool ) ), this, SLOT( addHit( BibTeX::Entry*, bool ) ) );
+ connect( m_webQueries[index], SIGNAL( endSearch( WebQuery::Status ) ), this, SLOT( endSearch( WebQuery::Status ) ) );
+
+ m_webQueries[index]->query();
+ }
+
+ void WebQueryWizard::endSearch( WebQuery::Status status )
+ {
+ int index = m_comboBoxEngines->currentItem();
+ disconnect( m_webQueries[index], SIGNAL( foundEntry( BibTeX::Entry*, bool ) ), this, SLOT( addHit( BibTeX::Entry*, bool ) ) );
+ disconnect( m_webQueries[index], SIGNAL( endSearch( WebQuery::Status ) ), this, SLOT( endSearch( WebQuery::Status ) ) );
+ setEnabled( TRUE );
+ m_dlg->enableButtonCancel( TRUE );
+ importEnableChanging();
+ QApplication::restoreOverrideCursor();
+ if ( status == WebQuery::statusInsufficientPermissions )
+ KMessageBox::sorry( this, i18n( "You do not have the necessary permissions to query data from this service." ) );
+ }
+
+ void WebQueryWizard::addHit( BibTeX::Entry *entry, bool keepId )
+ {
+ Settings * settings = Settings::self();
+ if ( !keepId && settings->idSuggestions_default >= 0 )
+ entry->setId( IdSuggestions::createDefaultSuggestion( NULL, entry ) );
+ new ResultsListViewItem( m_listViewResults, new BibTeX::Entry( entry ) );
+ }
+
+ void WebQueryWizard::enableSearch( bool enabled )
+ {
+ m_pushButtonSearch->setEnabled( enabled );
+ }
+
+ void WebQueryWizard::openURL( const QString& url )
+ {
+ Settings::openUrl( KURL( url ), this );
+ }
+
+ void WebQueryWizard::setupGUI()
+ {
+ Settings * settings = Settings::self();
+ setMinimumSize( 640, 384 );
+ QGridLayout *layout = new QGridLayout( this, 5, 4, 0, KDialog::spacingHint() );
+ layout->setColStretch( 2, 1 );
+ layout->setRowStretch( 3, 1 );
+
+ QLabel *label = new QLabel( i18n( "&Engine:" ), this );
+ layout->addWidget( label, 0, 0 );
+ m_comboBoxEngines = new KComboBox( FALSE, this );
+ label->setBuddy( m_comboBoxEngines );
+ layout->addWidget( m_comboBoxEngines, 0, 1 );
+ connect( m_comboBoxEngines, SIGNAL( activated( int ) ), this, SLOT( otherEngineSelected( int ) ) );
+
+ m_widgetStackQueries = new QWidgetStack( this );
+ layout->addMultiCellWidget( m_widgetStackQueries, 1, 2, 0, 2 );
+ setupQueries();
+
+ m_pushButtonSearch = new KPushButton( i18n( "&Search" ), this );
+ layout->addWidget( m_pushButtonSearch, 0, 3 );
+ m_pushButtonSearch->setIconSet( QIconSet( SmallIcon( "find" ) ) );
+ m_pushButtonSearch->setEnabled( FALSE );
+
+ m_listViewResults = new KListView( this );
+ m_listViewResults->addColumn( i18n( "Year" ), 64 );
+ m_listViewResults->addColumn( i18n( "Author" ), 128 );
+ m_listViewResults->addColumn( i18n( "Title" ), 512 );
+ if ( settings->editing_UseSpecialFont )
+ m_listViewResults->setFont( settings->editing_SpecialFont );
+ else
+ m_listViewResults->setFont( KGlobalSettings::generalFont() );
+ m_listViewResults->header() ->setFont( KGlobalSettings::generalFont() );
+ m_listViewResults->setAllColumnsShowFocus( TRUE );
+ m_listViewResults->setFullWidth( true );
+ m_listViewResults->setSelectionMode( QListView::Extended );
+ layout->addMultiCellWidget( m_listViewResults, 3, 3, 0, 3 );
+ connect( m_listViewResults, SIGNAL( executed( QListViewItem* ) ), this, SLOT( previewEntry( QListViewItem* ) ) );
+ connect( m_listViewResults, SIGNAL( returnPressed( QListViewItem* ) ), this, SLOT( previewEntry( QListViewItem* ) ) );
+
+ QHBoxLayout *horizontalLayout = new QHBoxLayout();
+ layout->addMultiCellLayout( horizontalLayout, 4, 4, 0, 3 );
+ m_disclaimerLabel = new KURLLabel( this );
+ horizontalLayout->addWidget( m_disclaimerLabel );
+ horizontalLayout->setStretchFactor( m_disclaimerLabel, 4 );
+ m_checkBoxImportAll = new QCheckBox( i18n( "Import all hits" ), this );
+ m_checkBoxImportAll->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ horizontalLayout->addWidget( m_checkBoxImportAll );
+
+ connect( m_disclaimerLabel, SIGNAL( leftClickedURL( const QString& ) ), this, SLOT( openURL( const QString& ) ) );
+ connect( m_listViewResults, SIGNAL( selectionChanged( ) ), this, SLOT( importEnableChanging( ) ) );
+ connect( m_listViewResults, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( importEnableChanging( ) ) );
+ connect( m_checkBoxImportAll, SIGNAL( toggled( bool ) ), this, SLOT( importEnableChanging( ) ) );
+ connect( m_pushButtonSearch, SIGNAL( clicked() ), this, SLOT( startSearch() ) );
+ }
+
+ void WebQueryWizard::setupQueries()
+ {
+ WebQuery *query = new WebQueryArXiv( this );
+ m_webQueries.append( query );
+ // query = new WebQueryAmatex( this );
+ // m_webQueries.append( query );
+ query = new WebQueryBibSonomy( this );
+ m_webQueries.append( query );
+ query = new WebQueryCitebase( this );
+ m_webQueries.append( query );
+ query = new WebQueryCiteSeerX( this );
+ m_webQueries.append( query );
+ query = new WebQueryCSB( this );
+ m_webQueries.append( query );
+ query = new WebQueryDBLP( this );
+ m_webQueries.append( query );
+ query = new WebQueryGoogleScholar( this );
+ m_webQueries.append( query );
+ query = new WebQueryIEEExplore( this );
+ m_webQueries.append( query );
+ query = new WebQueryMathSciNet( this );
+ m_webQueries.append( query );
+ query = new WebQueryPubMed( this );
+ m_webQueries.append( query );
+ query = new WebQueryScienceDirect( this );
+ m_webQueries.append( query );
+ query = new WebQuerySpiresHep( this );
+ m_webQueries.append( query );
+#ifdef HAVE_YAZ
+ query = new WebQueryZ3950( this );
+ m_webQueries.append( query );
+#endif // HAVE_YAZ
+ query = new WebQueryZMATH( this );
+ m_webQueries.append( query );
+
+ for ( QValueList<WebQuery*>::Iterator it = m_webQueries.begin(); it != m_webQueries.end(); ++it )
+ {
+ m_comboBoxEngines->insertItem(( *it )->title() );
+ m_widgetStackQueries->addWidget(( *it )->widget() );
+ connect(( *it )->widget(), SIGNAL( enableSearch( bool ) ), this, SLOT( enableSearch( bool ) ) );
+ connect(( *it )->widget(), SIGNAL( startSearch() ), this, SLOT( startSearch() ) );
+ }
+ }
+
+ /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
+ void WebQueryWizard::saveWindowSize( KConfig *config ) const
+ {
+ int scnum = QApplication::desktop()->screenNumber( parentWidget() );
+ QRect desk = QApplication::desktop()->screenGeometry( scnum );
+ int w, h;
+#if defined Q_WS_X11
+ // save maximalization as desktop size + 1 in that direction
+ KWin::WindowInfo info = KWin::windowInfo( m_dlg->winId(), NET::WMState );
+ w = info.state() & NET::MaxHoriz ? desk.width() + 1 : m_dlg->width();
+ h = info.state() & NET::MaxVert ? desk.height() + 1 : m_dlg->height();
+#else
+ if ( isMaximized() )
+ {
+ w = desk.width() + 1;
+ h = desk.height() + 1;
+ }
+ //TODO: add "Maximized" property instead "+1" hack
+#endif
+ QRect size( desk.width(), w, desk.height(), h );
+ bool defaultSize = false;//( size == d->defaultWindowSize );
+ QString widthString = QString::fromLatin1( "Width %1" ).arg( desk.width() );
+ QString heightString = QString::fromLatin1( "Height %1" ).arg( desk.height() );
+ if ( !config->hasDefault( widthString ) && defaultSize )
+ config->revertToDefault( widthString );
+ else
+ config->writeEntry( widthString, w );
+
+ if ( !config->hasDefault( heightString ) && defaultSize )
+ config->revertToDefault( heightString );
+ else
+ config->writeEntry( heightString, h );
+ }
+
+ /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
+ void WebQueryWizard::restoreWindowSize( KConfig *config )
+ {
+ // restore the size
+ int scnum = QApplication::desktop()->screenNumber( parentWidget() );
+ QRect desk = QApplication::desktop()->screenGeometry( scnum );
+ QSize size( config->readNumEntry( QString::fromLatin1( "Width %1" ).arg( desk.width() ), 0 ),
+ config->readNumEntry( QString::fromLatin1( "Height %1" ).arg( desk.height() ), 0 ) );
+ if ( size.isEmpty() )
+ {
+ // try the KDE 2.0 way
+ size = QSize( config->readNumEntry( QString::fromLatin1( "Width" ), 0 ),
+ config->readNumEntry( QString::fromLatin1( "Height" ), 0 ) );
+ if ( !size.isEmpty() )
+ {
+ // make sure the other resolutions don't get old settings
+ config->writeEntry( QString::fromLatin1( "Width" ), 0 );
+ config->writeEntry( QString::fromLatin1( "Height" ), 0 );
+ }
+ }
+ if ( !size.isEmpty() )
+ {
+#ifdef Q_WS_X11
+ int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
+ | ( size.height() > desk.height() ? NET::MaxVert : 0 );
+ if (( state & NET::Max ) == NET::Max )
+ ; // no resize
+ else if (( state & NET::MaxHoriz ) == NET::MaxHoriz )
+ m_dlg->resize( width(), size.height() );
+ else if (( state & NET::MaxVert ) == NET::MaxVert )
+ m_dlg->resize( size.width(), height() );
+ else
+ m_dlg->resize( size );
+ // QWidget::showMaximized() is both insufficient and broken
+ KWin::setState( m_dlg->winId(), state );
+#else
+ if ( size.width() > desk.width() || size.height() > desk.height() )
+ m_dlg->setWindowState( WindowMaximized );
+ else
+ m_dlg->resize( size );
+#endif
+ }
+ }
+
+ ResultsListViewItem::ResultsListViewItem( QListView * parent, BibTeX::Entry * entry ) : QListViewItem( parent ), m_entry( entry )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftTitle );
+ if ( field != NULL && field->value() != NULL )
+ setText( 2, field ->value() ->text().replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
+ field = entry->getField( BibTeX::EntryField::ftAuthor );
+ if ( field != NULL && field->value() != NULL )
+ {
+ BibTeX::PersonContainer* personContainer = dynamic_cast<BibTeX::PersonContainer*>( field->value()->items.first() );
+ if ( personContainer != NULL )
+ {
+ QStringList authors;
+ QValueList<BibTeX::Person*> list = personContainer->persons;
+ for ( QValueList<BibTeX::Person*>::ConstIterator it = list.begin(); it != list.end(); ++it )
+ authors.append(( *it ) ->text() );
+ setText( 1, authors.join( " and " ).replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
+ }
+ else setText( 1, field ->value() ->text().replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
+ }
+ field = entry->getField( BibTeX::EntryField::ftYear );
+ if ( field != NULL && field->value() != NULL )
+ setText( 0, field ->value() ->text().replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
+ }
+
+ ResultsListViewItem::~ResultsListViewItem()
+ {
+ if ( m_entry != NULL )
+ delete m_entry;
+ }
+
+ BibTeX::Entry* ResultsListViewItem::entry()
+ {
+ return m_entry;
+ }
+
+}
+#include "webquery.moc"
diff --git a/src/webquery.h b/src/webquery.h
new file mode 100644
index 0000000..f4b46b4
--- /dev/null
+++ b/src/webquery.h
@@ -0,0 +1,179 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXWEBQUERY_H
+#define KBIBTEXWEBQUERY_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include <kdialogbase.h>
+#include <klistview.h>
+#include <klineedit.h>
+#include <kio/jobclasses.h>
+#include <kprogress.h>
+
+#include "entry.h"
+
+class QWidget;
+class QFrame;
+class QCheckBox;
+class QSpinBox;
+class KComboBox;
+class KListView;
+class KPushButton;
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryWidget : public QWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryWidget( QWidget *parent, const char *name = 0 );
+ virtual bool searchPossible();
+
+ KLineEdit *lineEditQuery;
+ QSpinBox *spinBoxMaxHits;
+
+ protected:
+ virtual void init();
+
+ signals:
+ void enableSearch( bool );
+ void startSearch();
+
+ protected slots:
+ void slotTextChanged( const QString& );
+ void slotTextChanged( const QString&, bool delayed );
+
+ private slots:
+ void slotEnableSearchTrue();
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQuery : public QObject
+ {
+ Q_OBJECT
+ public:
+ enum Status { statusSuccess, statusError, statusAborted, statusInvalidQuery, statusInsufficientPermissions };
+
+ WebQuery( QWidget *parent );
+ virtual ~WebQuery();
+
+ virtual void query();
+
+ virtual QString title() { return "no_title"; };
+ virtual QString disclaimer() = 0;
+ virtual QString disclaimerURL() = 0;
+
+ virtual WebQueryWidget *widget() = 0;
+
+ signals:
+ void foundEntry( BibTeX::Entry*, bool );
+ void endSearch( WebQuery::Status );
+
+ protected:
+ bool m_aborted;
+ QWidget *m_parent;
+ KProgressDialog *m_progressDialog;
+
+ virtual void cancelQuery();
+
+ void setEndSearch( WebQuery::Status );
+ void setNumStages( int numStages );
+ void enterNextStage();
+ QString download( const KURL& url );
+ QString downloadHTML( const KURL& url );
+ BibTeX::File *downloadBibTeXFile( const KURL& url, QTextStream::Encoding = QTextStream::UnicodeUTF8 );
+
+ private:
+ int m_currentStage;
+ int m_numStages;
+ KIO::TransferJob *m_currentJob;
+ int m_currentJobTotalSize;
+ QString m_incomingData;
+
+ private slots:
+ void slotCancelQuery();
+ void slotSetJobTotalSize( KIO::Job *job, KIO::filesize_t size );
+ void slotSetJobProcessedSize( KIO::Job *job, KIO::filesize_t size );
+ void slotJobData( KIO::Job *job, const QByteArray &data );
+ void slotJobFinished( KIO::Job *job );
+ };
+
+ class WebQueryWizard: public QWidget
+ {
+ Q_OBJECT
+ public:
+ ~WebQueryWizard();
+
+ static int execute( QWidget *parent, QValueList<BibTeX::Entry*> &results );
+
+ signals:
+ void changeButtonOK( bool state );
+
+ protected:
+ KListView *m_listViewResults;
+ KComboBox *m_comboBoxEngines;
+ QWidgetStack *m_widgetStackQueries;
+ KURLLabel *m_disclaimerLabel;
+ QCheckBox *m_checkBoxImportAll;
+ QValueList<WebQuery*> m_webQueries;
+ KDialogBase *m_dlg;
+
+ WebQueryWizard( KDialogBase *dlg, const char* name = 0 );
+ void showEvent( QShowEvent * );
+
+ private slots:
+ void previewEntry( QListViewItem *item );
+ void importEnableChanging( );
+ void otherEngineSelected( int index );
+ void startSearch();
+ void endSearch( WebQuery::Status );
+ void addHit( BibTeX::Entry*, bool keepId = false );
+ void enableSearch( bool );
+ void openURL( const QString& );
+
+ private:
+ KPushButton *m_pushButtonSearch;
+
+ void setupGUI( );
+ void setupQueries();
+ void restoreWindowSize( KConfig *config );
+ void saveWindowSize( KConfig *config ) const;
+ };
+
+ class ResultsListViewItem: public QListViewItem
+ {
+ public:
+ ResultsListViewItem( QListView * parent, BibTeX::Entry *entry );
+ ~ResultsListViewItem();
+
+ BibTeX::Entry* entry();
+ private:
+ BibTeX::Entry *m_entry;
+ };
+}
+
+#endif
diff --git a/src/webqueryamatex.cpp b/src/webqueryamatex.cpp
new file mode 100644
index 0000000..8fcbb31
--- /dev/null
+++ b/src/webqueryamatex.cpp
@@ -0,0 +1,123 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qapplication.h>
+#include <qregexp.h>
+#include <qbuffer.h>
+#include <qspinbox.h>
+
+#include <klineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <kurl.h>
+
+#include <fileimporterbibtex.h>
+#include "webqueryamatex.h"
+
+namespace KBibTeX
+{
+ WebQueryAmatexWidget::WebQueryAmatexWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+ }
+
+ WebQueryAmatex::WebQueryAmatex( QWidget* parent ): WebQuery( parent )
+ {
+ m_widget = new WebQueryAmatexWidget( parent );
+ }
+
+ WebQueryAmatex::~WebQueryAmatex()
+ {
+ delete m_widget;
+ }
+
+ QString WebQueryAmatex::title()
+ {
+ return i18n( "Amatex" );
+ }
+
+ QString WebQueryAmatex::disclaimer()
+ {
+ return i18n( "About Amatex" );
+ }
+
+ QString WebQueryAmatex::disclaimerURL()
+ {
+ return QString( "http://www.2ndminute.org:8080/amatex/pages/about.jsp" );
+ }
+
+ WebQueryWidget *WebQueryAmatex::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryAmatex::query()
+ {
+ WebQuery::query();
+ int numberOfResults = m_widget->spinBoxMaxHits->value();
+ setNumStages( 1 );
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" ).replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ KURL url = KURL( QString( "http://www.2ndminute.org:8080/amatex/search.do?lang=US&querry=%1&suchart=kwd" ).arg( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ) );
+
+ QString key = searchTerm.replace( QRegExp( "[^-_+A-Za-z0-9]" ), "" );
+ int count = 0;
+ BibTeX::File *tmpBibFile = downloadBibTeXFile( url );
+ if ( tmpBibFile != NULL && !m_aborted )
+ {
+ for ( BibTeX::File::ElementList::iterator it = tmpBibFile->begin(); !m_aborted && count < numberOfResults && it != tmpBibFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ {
+ entry->setId( QString( "Amatex_%1_%2" ).arg( key ).arg( ++count ) );
+ emit foundEntry( entry, false );
+ }
+ }
+
+ delete tmpBibFile;
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ emit endSearch( WebQuery::statusAborted );
+
+ if ( tmpBibFile != NULL )
+ delete tmpBibFile;
+ }
+
+}
+#include "webqueryamatex.moc"
diff --git a/src/webqueryamatex.h b/src/webqueryamatex.h
new file mode 100644
index 0000000..d2486da
--- /dev/null
+++ b/src/webqueryamatex.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYAMATEX_H
+#define KBIBTEXWEBQUERYAMATEX_H
+
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryAmatexWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryAmatexWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryAmatex : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryAmatex( QWidget* parent );
+ virtual ~WebQueryAmatex();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQueryAmatexWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/webqueryarxiv.cpp b/src/webqueryarxiv.cpp
new file mode 100644
index 0000000..f24fa44
--- /dev/null
+++ b/src/webqueryarxiv.cpp
@@ -0,0 +1,568 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qbuffer.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+
+#include <fileimporterbibtex.h>
+#include <encoderxml.h>
+#include <settings.h>
+#include "webqueryarxiv.h"
+
+namespace KBibTeX
+{
+ WebQueryArXivWidget::WebQueryArXivWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "ArXiv" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+ WebQueryArXiv::WebQueryArXiv( QWidget* parent )
+ : WebQuery( parent ), m_arXivServer( "www.arxiv.org" ),
+
+ /** examples:
+ Journal of Inefficient Algorithms 5 (2003) 35-39
+ Astrophys.J. 578 (2002) L103-L106
+ New J. Phys. 10 (2008) 033023
+ Physics Letters A 297 (2002) 4-8
+ Appl.Phys. B75 (2002) 655-665
+ JHEP 0611 (2006) 045
+ */
+ m_jourRef1( "^([a-zA-Z. ]+[a-zA-Z.])\\s*(\\d+)\\s+\\((\\d{4})\\)\\s+([0-9A-Z]+)(-([0-9A-Z]+))?$" ),
+
+ /** examples:
+ Journal of Inefficient Algorithms, Vol. 93, No. 2 (2009), pp. 42-51
+ International Journal of Quantum Information, Vol. 1, No. 4 (2003) 427-441
+ Stud. Hist. Phil. Mod. Phys., Vol 33 no 3 (2003), pp. 441-468
+ */
+ m_jourRef2( "^([a-zA-Z. ]+[a-zA-Z.]),\\s+Vol\\.?\\s+(\\d+)[,]?\\s+No\\.?\\s+(\\d+)\\s+\\((\\d{4})\\)[,]?\\s+(pp\\.\\s+)?(\\d+)(-(\\d+))?$" ),
+
+ /** examples:
+ Journal of Inefficient Algorithms, volume 4, number 1, pp. 12-21, 2008
+ Scientometrics, volume 69, number 3, pp. 669-687, 2006
+ */
+ m_jourRef3( "^([a-zA-Z. ]+),\\s+volume\\s+(\\d+),\\s+number\\s+(\\d+),\\s+pp\\.\\s+(\\d+)(-(\\d+))?,\\s+(\\d{4})$" ),
+
+ /** examples:
+ Journal of Inefficient Algorithms 4(1): 101-122, 2010
+ JHEP0809:131,2008
+ Phys.Rev.D78:013004,2008
+ Lect.NotesPhys.690:107-127,2006
+ Europhys. Letters 70:1-7 (2005)
+ Journal of Conflict Resolution 51(1): 58 - 88 (2007)
+ Journal of Artificial Intelligence Research (JAIR), 9:247-293
+ */
+ m_jourRef4( "^([a-zA-Z. ()]+)[,]?\\s*(\\d+)(\\((\\d+)\\))?:\\s*(\\d+)(\\s*-\\s*(\\d+))?(,\\s*(\\d{4})|\\s+\\((\\d{4})\\))?$" ),
+
+ /** examples:
+ Journal of Inefficient Algorithms vol. 31, 4 2000
+ Phys. Rev. A 71, 032339 (2005)
+ Phys. Rev. Lett. 91, 027901 (2003)
+ Phys. Rev. A 78, 013620 (2008)
+ Phys. Rev. E 62, 1842 (2000)
+ Rev. Mod. Phys. 79, 555 (2007)
+ J. Math. Phys. 49, 032105 (2008)
+ New J. Phys. 8, 58 (2006)
+ Phys. Rev. Lett. 91, 217905 (2003).
+ Physical Review B vol. 66, 161320(R) (2002)
+ ??? Phys. Rev. Lett. 89, 057902(1--4) (2002).
+ ??? J. Mod. Opt., 54, 2211 (2007)
+ */
+ m_jourRef5( "^([a-zA-Z. ]+)\\s+(vol\\.\\s+)?(\\d+),\\s+(\\d+)(\\([A-Z]+\\))?\\s+\\((\\d{4})\\)[.]?$" ),
+
+ /** examples:
+ Journal of Inefficient Algorithms, 11(2) (1999) 42-55
+ Learned Publishing, 20(1) (January 2007) 16-22
+ */
+ m_jourRef6( "^([a-zA-Z. ]+),\\s+(\\d+)\\((\\d+)\\)\\s+(\\(([A-Za-z]+\\s+)?(\\d{4})\\))?\\s+(\\d+)(-(\\d+))?$" ),
+
+ m_reJour( "^([a-zA-Z. ]+)" ), m_reYear( "\\b((18|19|20)\\d{2})\\b" ), m_rePages( "\\b([1-9]\\d{0,2})\\s*[-]+\\s*([1-9]\\d{0,2})\\b" )
+ {
+ m_importer = new BibTeX::FileImporterBibTeX( FALSE );
+ m_importer->setIgnoreComments( TRUE );
+ m_widget = new WebQueryArXivWidget( parent );
+ }
+
+ WebQueryArXiv::~WebQueryArXiv()
+ {
+ delete m_widget;
+ delete m_importer;
+ }
+
+ QString WebQueryArXiv::title()
+ {
+ return i18n( "arXiv" );
+ }
+
+ QString WebQueryArXiv::disclaimer()
+ {
+ return i18n( "arXiv is an archive for preprints" );
+ }
+
+ QString WebQueryArXiv::disclaimerURL()
+ {
+ return "http://www.arxiv.org/";
+ }
+
+ WebQueryWidget *WebQueryArXiv::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryArXiv::cancelQuery()
+ {
+ m_urls.clear();
+ // FIXME: The following code crashes KBibTeX:
+ // if ( m_currentJob != NULL ) m_currentJob->kill( FALSE );
+ }
+
+ void WebQueryArXiv::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "ArXiv", m_widget->lineEditQuery->text() );
+
+ m_urls.clear();
+ m_numberOfResults = m_widget->spinBoxMaxHits->value();
+ setNumStages( m_numberOfResults + 1 );
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ QStringList queryWords = QStringList::split( QRegExp( "\\s+" ), searchTerm );
+ if ( searchTerm.isEmpty() || queryWords.size() == 0 )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ QString query;
+ for ( unsigned int i = 0; i < queryWords.size() - 1; ++i )
+ query = query.append( "AND " ).append( queryWords[i] ).append( " " );
+ query.append( queryWords[queryWords.size()-1] );
+
+ KURL url = KURL( QString( "http://www.arxiv.org/find/all/1/all:+%2/0/1/0/all/0/1?per_page=%1" ).arg( m_numberOfResults ).arg( query.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ) );
+ m_currentJobMutex.lock();
+ KIO::Job *job = KIO::storedGet( url, FALSE, FALSE );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( unlockJob( KIO::Job * ) ) );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( arXivResult( KIO::Job * ) ) );
+ }
+
+ void WebQueryArXiv::unlockJob( KIO::Job * )
+ {
+ m_currentJobMutex.unlock();
+ }
+
+ void WebQueryArXiv::arXivResult( KIO::Job *job )
+ {
+ if ( job->error() == 0 && !m_aborted )
+ {
+ enterNextStage();
+
+ QBuffer data;
+ data.open( IO_WriteOnly );
+ data.writeBlock( dynamic_cast<KIO::StoredTransferJob*>( job )->data() );
+ data.close();
+ data.open( IO_ReadOnly );
+ QTextStream ts( &data );
+ QString result = ts.read();
+ data.close();
+
+ int p = -1;
+ m_totalHits = 0;
+ m_receivedHits = 0;
+ while ( !m_aborted && ( int ) m_totalHits < m_numberOfResults && ( p = result.find( "arXiv:", p + 1 ) ) >= 0 )
+ {
+ int p2 = result.find( "<", p + 2 );
+ QString hit = result.mid( p + 6, p2 - p - 6 );
+ ++m_totalHits;
+ p = p2 + 1;
+
+
+ KURL url = KURL( QString( "http://%2/abs/%1" ).arg( hit ).arg( m_arXivServer ) );
+ m_urls.append( url );
+ }
+
+ if ( m_totalHits == 0 )
+ setEndSearch( WebQuery::statusSuccess );
+ else if ( !m_urls.isEmpty() )
+ {
+ KURL url = m_urls.first();
+ m_urls.remove( url );
+ fetchFromAbstract( url );
+ }
+ }
+ else
+ setEndSearch( WebQuery::statusError );
+ }
+
+ void WebQueryArXiv::fetchFromAbstract( const KURL &abstractURL )
+ {
+ m_aborted = false;
+ m_currentJobMutex.lock();
+ KIO::Job *job = KIO::storedGet( abstractURL, FALSE, FALSE );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( unlockJob( KIO::Job * ) ) );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( arXivAbstractResult( KIO::Job * ) ) );
+ }
+
+ void WebQueryArXiv::arXivAbstractResult( KIO::Job *job )
+ {
+ if ( job->error() == 0 && !m_aborted )
+ {
+ ++m_receivedHits;
+ enterNextStage();
+
+ QBuffer data;
+ data.open( IO_WriteOnly );
+ data.writeBlock( dynamic_cast<KIO::StoredTransferJob*>( job )->data() );
+ data.close();
+ data.open( IO_ReadOnly );
+ QTextStream ts( &data );
+ QString result = BibTeX::EncoderXML::currentEncoderXML()->decode( ts.read() );
+ data.close();
+
+ /** find id */
+ int p = result.find( "arXiv:", 0 );
+ if ( p < 0 ) return;
+ int p2 = result.find( "<", p + 2 );
+ if ( p2 < 0 ) return;
+ QString id = result.mid( p + 6, p2 - p - 6 );
+
+ /** find cite_as */
+ QString citeas = "";
+ p = result.find( "Cite&nbsp;as", 0 );
+ p = result.find( ">arXiv:", p );
+ p2 = result.find( "</", p );
+ if ( p >= 0 && p2 >= 0 )
+ citeas = result.mid( p + 7, p2 - p - 7 );
+
+ BibTeX::Entry * entry = new BibTeX::Entry( BibTeX::Entry::etMisc, citeas.isEmpty() ? ( id.isEmpty() ? QString( "arXiv" ).append( m_receivedHits ) : id ) : citeas );
+
+ /** find abstract */
+ p = result.find( "Abstract:</span>", 0 );
+ if ( p < 0 ) return;
+ p2 = result.find( "</blockq", p + 14 );
+ if ( p2 < 0 ) return;
+ QString abstract = result.mid( p + 16, p2 - p - 16 ).replace( QRegExp( "\\s+" ), " " ).replace( QRegExp( "^\\s+|\\s+$" ), "" ).replace( QRegExp( "<[^>]+>" ), "" );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftAbstract );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( abstract ) );
+
+ /** find authors */
+ BibTeX::PersonContainer *personContainer = new BibTeX::PersonContainer( Settings::self()->editing_FirstNameFirst );
+ p = -1;
+ while (( p = result.find( "/au:", p + 1 ) ) > 0 )
+ {
+ p = result.find( ">", p + 1 );
+ p2 = result.find( "<", p + 1 );
+ QString author = result.mid( p + 1, p2 - p - 1 );
+ personContainer->persons.append( new BibTeX::Person( author ) );
+ }
+ if ( personContainer->persons.isEmpty() )
+ delete personContainer;
+ else
+ {
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftAuthor );
+ entry->addField( field );
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( personContainer );
+ field->setValue( value );
+ }
+
+ /** find title */
+ p = result.find( "Title:</span>", 0 );
+ p2 = result.find( "<", p + 10 );
+ if ( p >= 0 && p2 >= 0 )
+ {
+ QString title = result.mid( p + 13, p2 - p - 13 ).replace( QRegExp( "\\s+" ), " " ).replace( QRegExp( "^\\s+|\\s+$" ), "" );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftTitle );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( title ) );
+ }
+
+ /** find month and year */
+ p = result.find( "Submitted on", 0 );
+ while (( p2 = result.find( "last revised", p + 1 ) ) >= 0 )
+ p = p2;
+ p2 = result.find( QRegExp( "\\d\\d\\d\\d" ), p );
+ bool ok = FALSE;
+ int year = result.mid( p2, 4 ).toInt( &ok );
+ if ( !ok ) year = 0;
+ if ( year > 1000 )
+ {
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftYear );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( QString::number( year ) ) );
+ }
+ p2 = result.find( QRegExp( "\\b[A-Z][a-z]{2}\\b" ), p );
+ if ( p2 >= 0 )
+ {
+ QString month = result.mid( p2, 3 ).lower();
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftMonth );
+ entry->addField( field );
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::MacroKey( month ) );
+ field->setValue( value );
+ }
+
+ /** find DOI */
+ p = result.find( "http://dx.doi.org/", 0 );
+ p2 = result.find( "\"", p + 1 );
+ if ( p >= 0 && p2 >= 0 )
+ {
+ QString doi = result.mid( p, p2 - p );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftDoi );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( doi ) );
+ }
+
+ /** find keywords */
+ p = result.find( "<td class=\"tablecell subjects\">", 0 );
+ p2 = result.find( "</td>", p + 1 );
+ if ( p >= 0 && p2 >= 0 )
+ {
+ QString keywords = result.mid( p + 31, p2 - p - 31 ).replace( QRegExp( "</?span[^>]*>" ), "" );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftKeywords );
+ entry->addField( field );
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::KeywordContainer( keywords ) );
+ field->setValue( value );
+ }
+
+ /** find ACM classes */
+ p = result.find( "<td class=\"tablecell acm-classes\">", 0 );
+ p2 = result.find( "</td>", p + 1 );
+ if ( p >= 0 && p2 >= 0 )
+ {
+ QString acmclasses = result.mid( p + 34, p2 - p - 34 );
+ BibTeX::EntryField * field = new BibTeX::EntryField( "acm-classes" );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( acmclasses ) );
+ }
+
+ /** find versions */
+ for ( int v = 1; !m_aborted && v < 20; ++v )
+ {
+ p = result.find( QString( ">[v%1]<" ).arg( v ), 0 );
+ if ( p < 0 ) break;
+
+ int p3 = result.findRev( "href=\"", p );
+ if ( p3 >= 0 && p3 > p - 40 )
+ {
+ p2 = result.find( "\">", p3 );
+ if ( p2 >= 0 )
+ {
+ QString url = result.mid( p3 + 6, p2 - p3 - 6 );
+ BibTeX::EntryField * field = new BibTeX::EntryField( QString( "v%1url" ).arg( v ) );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( QString( "http://www.arxiv.org" ).append( url ) ) );
+ }
+ }
+ p = result.find( "</b>", p + 1 );
+ p2 = result.find( "<br", p + 1 );
+ if ( p >= 0 && p2 >= 0 )
+ {
+ QString version = result.mid( p + 5, p2 - p - 5 );
+ BibTeX::EntryField * field = new BibTeX::EntryField( QString( "v%1descr" ).arg( v ) );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( version ) );
+ }
+ }
+
+ /** find tech report reference */
+ p = result.find( "<td class=\"tablecell report-number\">", 0 );
+ p2 = result.find( "</td>", p + 1 );
+ if ( p >= 0 && p2 >= 0 )
+ {
+ QString techRepNr = result.mid( p + 36, p2 - p - 36 );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftNumber );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( techRepNr ) );
+ entry->setEntryType( BibTeX::Entry::etTechReport );
+ }
+
+ /** find journal reference */
+ p = result.find( "<td class=\"tablecell jref\">", 0 );
+ p2 = result.find( "</td>", p + 1 );
+ if ( p >= 0 && p2 >= 0 )
+ {
+ QString jref = result.mid( p + 27, p2 - p - 27 );
+ jref.replace( "\n", " " );
+
+ QString jTitle = "";
+ QString jVol = "";
+ QString jNo = "";
+ QString jYear = "";
+ QString jPage1 = "";
+ QString jPage2 = "";
+
+ // m_jourRef1( "^([a-zA-Z. ]+[a-zA-Z.])\\s*(\\d+)\\s+\\((\\d{4})\\)\\s+([0-9A-Z]+)(-([0-9A-Z]+))?$" )
+ if ( m_jourRef1.search( jref ) == 0 )
+ {
+ jTitle = m_jourRef1.cap( 1 );
+ jVol = m_jourRef1.cap( 2 );
+ jYear = m_jourRef1.cap( 3 );
+ jPage1 = m_jourRef1.cap( 4 );
+ jPage2 = m_jourRef1.cap( 6 );
+ }
+ // m_jourRef2( "^([a-zA-Z. ]+[a-zA-Z.]),\s+Vol[.]?\s+(\d+)[,]?\s+No[.]?\s+(\d+)\s+\((\d{4})\)[,]?\s+(pp\.\s+)?(\d+)(-(\d+))?$" )
+ else if ( m_jourRef2.search( jref ) == 0 )
+ {
+ jTitle = m_jourRef2.cap( 1 );
+ jVol = m_jourRef2.cap( 2 );
+ jNo = m_jourRef2.cap( 3 );
+ jYear = m_jourRef2.cap( 4 );
+ jPage1 = m_jourRef2.cap( 6 );
+ jPage2 = m_jourRef2.cap( 8 );
+ }
+ // m_jourRef3( "^([a-zA-Z. ]+),\\s+volume\\s+(\\d+),\\s+number\\s+(\\d+),\\s+pp\\.\\s+(\\d+)(-(\\d+))?,\\s+(\\d{4})$" )
+ else if ( m_jourRef3.search( jref ) == 0 )
+ {
+ jTitle = m_jourRef3.cap( 1 );
+ jVol = m_jourRef3.cap( 2 );
+ jNo = m_jourRef3.cap( 3 );
+ jPage1 = m_jourRef3.cap( 4 );
+ jPage2 = m_jourRef3.cap( 6 );
+ jYear = m_jourRef3.cap( 7 );
+ }
+ // m_jourRef4("^([a-zA-Z. ()]+[a-zA-Z.()])[,]?\\s*(\\d+)(\\((\\d+)\\))?:\\s*(\\d+)(\\s*-\\s*(\\d+))?(,\\s*(\\d{4})|\\s+\\((\\d{4})\\))?$")
+ else if ( m_jourRef4.search( jref ) == 0 )
+ {
+ jTitle = m_jourRef4.cap( 1 );
+ jVol = m_jourRef4.cap( 2 );
+ jNo = m_jourRef4.cap( 4 );
+ jPage1 = m_jourRef4.cap( 5 );
+ jPage2 = m_jourRef4.cap( 7 );
+ jYear = m_jourRef4.cap( 9 ).append( m_jourRef4.cap( 10 ) );
+ }
+ // m_jourRef5("^([a-zA-Z. ]+)\\s+(vol\\.\\s+)?(\\d+),\\s+(\\d+)(\\([A-Z]+\\))?\\s+\\((\\d{4})\\)[.]?$")
+ else if ( m_jourRef5.search( jref ) == 0 )
+ {
+ jTitle = m_jourRef5.cap( 1 );
+ jVol = m_jourRef5.cap( 3 );
+ jPage1 = m_jourRef5.cap( 4 );
+ jYear = m_jourRef5.cap( 6 );
+ }
+ // m_jourRef6("^([a-zA-Z. ]+),\\s+(\\d+)\\((\\d+)\\)\\s+(\\(([A-Za-z]+\\s+)?(\\d{4})\\))?\\s+(\\d+)(-(\\d+))?$")
+ else if ( m_jourRef6.search( jref ) == 0 )
+ {
+ jTitle = m_jourRef6.cap( 1 );
+ jVol = m_jourRef6.cap( 2 );
+ jNo = m_jourRef6.cap( 3 );
+ jYear = m_jourRef6.cap( 6 );
+ jPage1 = m_jourRef6.cap( 7 );
+ jPage2 = m_jourRef6.cap( 9 );
+ }
+ else
+ {
+ if ( m_reJour.search( jref ) == 0 )
+ jTitle = m_reJour.cap( 1 );
+ if ( m_reYear.search( jref ) == 0 )
+ jYear = m_reYear.cap( 1 );
+ if ( m_rePages.search( jref ) > -1 )
+ {
+ jPage1 = m_rePages.cap( 1 );
+ jPage2 = m_rePages.cap( 2 );
+ }
+ }
+
+ if ( !jTitle.isEmpty() )
+ {
+ entry->deleteField( BibTeX::EntryField::ftJournal );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftJournal );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( jTitle ) );
+ entry->setEntryType( BibTeX::Entry::etArticle );
+ }
+ if ( !jVol.isEmpty() )
+ {
+ entry->deleteField( BibTeX::EntryField::ftVolume );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftVolume );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( jVol ) );
+ }
+ if ( !jNo.isEmpty() )
+ {
+ entry->deleteField( BibTeX::EntryField::ftNumber );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftNumber );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( jNo ) );
+ }
+ if ( !jYear.isEmpty() )
+ {
+ entry->deleteField( BibTeX::EntryField::ftYear );
+ entry->deleteField( BibTeX::EntryField::ftMonth );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftYear );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( jYear ) );
+ }
+ if ( !jPage1.isEmpty() )
+ {
+ entry->deleteField( BibTeX::EntryField::ftPages );
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftPages );
+ entry->addField( field );
+ QString text = jPage1;
+ if ( !jPage2.isEmpty() ) text.append( "--" ).append( jPage2 );
+ field->setValue( new BibTeX::Value( text ) );
+ }
+ }
+
+ if ( result.find( QRegExp( "Ph\\.?D\\.? Thesis", FALSE ), 0 ) >= 0 )
+ entry->setEntryType( BibTeX::Entry::etPhDThesis );
+
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftURL );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( QString( "http://arxiv.org/abs/%1" ).arg( id ) ) );
+
+ field = new BibTeX::EntryField( "pdf" );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( QString( "http://arxiv.org/pdf/%1" ).arg( id ) ) );
+
+ emit foundEntry( entry, false );
+
+ if ( m_totalHits == m_receivedHits )
+ setEndSearch( WebQuery::statusSuccess );
+ else if ( !m_urls.isEmpty() )
+ {
+ KURL url = m_urls.first();
+ m_urls.remove( url );
+ m_currentJobMutex.lock();
+ KIO::Job *job = KIO::storedGet( url, FALSE, FALSE );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( unlockJob( KIO::Job * ) ) );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( arXivAbstractResult( KIO::Job * ) ) );
+ }
+ else
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else
+ setEndSearch( WebQuery::statusError );
+ }
+
+}
+#include "webqueryarxiv.moc"
diff --git a/src/webqueryarxiv.h b/src/webqueryarxiv.h
new file mode 100644
index 0000000..6bebb9b
--- /dev/null
+++ b/src/webqueryarxiv.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYARXIV_H
+#define KBIBTEXWEBQUERYARXIV_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+
+#include <kio/job.h>
+
+#include <fileimporterbibtex.h>
+#include <webquery.h>
+
+class QBuffer;
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryArXivWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryArXivWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryArXiv : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryArXiv( QWidget* parent );
+ virtual ~WebQueryArXiv();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ void fetchFromAbstract( const KURL &abstractURL );
+
+ protected:
+ void cancelQuery();
+
+ private slots:
+ void arXivResult( KIO::Job *job );
+ void unlockJob( KIO::Job *job );
+ void arXivAbstractResult( KIO::Job *job );
+
+ private:
+ QString m_lastHit;
+ BibTeX::FileImporterBibTeX *m_importer;
+ QString m_arXivServer;
+ int m_numberOfResults, m_totalHits, m_receivedHits;
+ QMutex m_currentJobMutex;
+ QValueList<KURL> m_urls;
+ WebQueryArXivWidget *m_widget;
+
+ QRegExp m_jourRef1, m_jourRef2, m_jourRef3, m_jourRef4, m_jourRef5, m_jourRef6, m_reJour, m_reYear, m_rePages;
+ };
+}
+
+#endif
diff --git a/src/webquerybibsonomy.cpp b/src/webquerybibsonomy.cpp
new file mode 100644
index 0000000..135d72b
--- /dev/null
+++ b/src/webquerybibsonomy.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qapplication.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <kurl.h>
+
+#include <settings.h>
+#include <fileimporterbibtex.h>
+#include "webquerybibsonomy.h"
+
+namespace KBibTeX
+{
+ WebQueryBibSonomyWidget::WebQueryBibSonomyWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "BibSonomy" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+
+ WebQueryBibSonomy::WebQueryBibSonomy( QWidget* parent ): WebQuery( parent )
+ {
+ m_widget = new WebQueryBibSonomyWidget( parent );
+ }
+
+ WebQueryBibSonomy::~WebQueryBibSonomy()
+ {
+ delete m_widget;
+ }
+
+ QString WebQueryBibSonomy::title()
+ {
+ return i18n( "BibSonomy" );
+ }
+
+ QString WebQueryBibSonomy::disclaimer()
+ {
+ return i18n( "BibSonomy bookmark sharing system" );
+ }
+
+ QString WebQueryBibSonomy::disclaimerURL()
+ {
+ return "http://www.bibsonomy.org/help/about/";
+ }
+
+ WebQueryWidget *WebQueryBibSonomy::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryBibSonomy::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "BibSonomy", m_widget->lineEditQuery->text() );
+
+ setNumStages( 1 );
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ int numberOfResults = m_widget->spinBoxMaxHits->value();
+
+ KURL url = KURL( QString( "http://www.bibsonomy.org/bib/search/%2?items=%1" ).arg( numberOfResults ) .arg( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ) );
+
+ BibTeX::File *bibFile = downloadBibTeXFile( url );
+ if ( bibFile != NULL && !m_aborted )
+ {
+ for ( BibTeX::File::ElementList::iterator it = bibFile->begin(); it != bibFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ emit foundEntry( entry, false );
+ }
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+
+ if ( bibFile != NULL )
+ delete bibFile;
+ }
+}
+#include "webquerybibsonomy.moc"
diff --git a/src/webquerybibsonomy.h b/src/webquerybibsonomy.h
new file mode 100644
index 0000000..216771a
--- /dev/null
+++ b/src/webquerybibsonomy.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYBIBSONOMY_H
+#define KBIBTEXWEBQUERYBIBSONOMY_H
+
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryBibSonomyWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryBibSonomyWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+
+ class WebQueryBibSonomy : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryBibSonomy( QWidget* parent );
+ virtual ~WebQueryBibSonomy();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQueryBibSonomyWidget *m_widget;
+ };
+}
+
+#endif
diff --git a/src/webquerycitebase.cpp b/src/webquerycitebase.cpp
new file mode 100644
index 0000000..a12f400
--- /dev/null
+++ b/src/webquerycitebase.cpp
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qapplication.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qspinbox.h>
+
+#include <klineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <kurl.h>
+
+#include <settings.h>
+#include <fileimporterbibtex.h>
+#include "webquerycitebase.h"
+
+namespace KBibTeX
+{
+ WebQueryCitebaseWidget::WebQueryCitebaseWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "Citebase" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+
+ WebQueryCitebase::WebQueryCitebase( QWidget* parent ): WebQuery( parent )
+ {
+ m_widget = new WebQueryCitebaseWidget( parent );
+ }
+
+ WebQueryCitebase::~WebQueryCitebase()
+ {
+ delete m_widget;
+ }
+
+ QString WebQueryCitebase::title()
+ {
+ return i18n( "Citebase" );
+ }
+
+ QString WebQueryCitebase::disclaimer()
+ {
+ return i18n( "Citebase citation index" );
+ }
+
+ QString WebQueryCitebase::disclaimerURL()
+ {
+ return "http://www.citebase.org/";
+ }
+
+ WebQueryWidget *WebQueryCitebase::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryCitebase::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "Citebase", m_widget->lineEditQuery->text() );
+
+ setNumStages( 1 );
+ int numberOfResults = m_widget->spinBoxMaxHits->value();
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ KURL url = KURL( QString( "http://www.citebase.org/search?submitted=Search&author=&maxrows=%1&yearfrom=&format=BibTeX&order=DESC&type=metadata&title=%2&publication=&yearuntil=&rank=paperimpact" ).arg( numberOfResults ).arg( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ) );
+ BibTeX::File *tmpBibFile = downloadBibTeXFile( url );
+ if ( tmpBibFile != NULL && !m_aborted )
+ {
+ int count = numberOfResults;
+ for ( BibTeX::File::ElementList::iterator it = tmpBibFile->begin(); count > 0 && it != tmpBibFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ {
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ --count;
+ }
+ }
+
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+
+ if ( tmpBibFile != NULL )
+ delete tmpBibFile;
+ }
+}
+#include "webquerycitebase.moc"
diff --git a/src/webquerycitebase.h b/src/webquerycitebase.h
new file mode 100644
index 0000000..346d1e4
--- /dev/null
+++ b/src/webquerycitebase.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYCITEBASE_H
+#define KBIBTEXWEBQUERYCITEBASE_H
+
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryCitebaseWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryCitebaseWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryCitebase : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryCitebase( QWidget* parent );
+ virtual ~WebQueryCitebase();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQueryCitebaseWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/webqueryciteseerx.cpp b/src/webqueryciteseerx.cpp
new file mode 100644
index 0000000..d5d244e
--- /dev/null
+++ b/src/webqueryciteseerx.cpp
@@ -0,0 +1,318 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Jacob Kanev <[email protected]>, *
+ * Thomas Fischer <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qregexp.h>
+#include <qbuffer.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+#include <kdebug.h>
+
+#include <fileimporterbibtex.h>
+#include <encoderxml.h>
+#include <settings.h>
+#include "webqueryciteseerx.h"
+
+using BibTeX::Value;
+using BibTeX::Entry;
+using BibTeX::EntryField;
+
+namespace KBibTeX
+{
+
+ //_______________________________________________________________________________________________________________
+ // Construct widget
+
+ WebQueryCiteSeerXWidget::WebQueryCiteSeerXWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "CiteSeerX" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // Construct
+
+ WebQueryCiteSeerX::WebQueryCiteSeerX( QWidget* parent )
+ : WebQuery( parent ), m_citeSeerXServer( "citeseerx.ist.psu.edu" )
+ {
+ m_widget = new WebQueryCiteSeerXWidget( parent );
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // Destroy
+
+ WebQueryCiteSeerX::~WebQueryCiteSeerX()
+ {
+ delete m_widget;
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // GUI string
+
+ QString WebQueryCiteSeerX::title()
+ {
+ return i18n( "CiteSeerX" );
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // GUI info
+
+ QString WebQueryCiteSeerX::disclaimer()
+ {
+ return i18n( "About CiteSeerX" );
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // URL for disclaimer
+
+ QString WebQueryCiteSeerX::disclaimerURL()
+ {
+ return "http://citeseerx.ist.psu.edu/about/site";
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // return pointer to widget
+
+ WebQueryWidget *WebQueryCiteSeerX::widget()
+ {
+ return m_widget;
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // user has pressed "Cancel"
+
+ void WebQueryCiteSeerX::cancelQuery()
+ {
+ m_queryQueue.clear();
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // main function -- collects all queries for one search
+
+ void WebQueryCiteSeerX::query()
+ {
+ // store CiteSeerX as future default
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "CiteSeerX", m_widget->lineEditQuery->text() );
+
+ // read number of desired results from GUI
+ m_queryQueue.clear();
+ m_desiredHits = m_widget->spinBoxMaxHits->value();
+ // one for each entry, and one for each page of 10 links
+ setNumStages( m_desiredHits + ( m_desiredHits / 10 + 1 ) );
+
+ // prepare search term
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ QStringList queryWords = QStringList::split( QRegExp( "\\s+" ), searchTerm );
+
+ if ( searchTerm.isEmpty() || queryWords.size() == 0 )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ // build query from search term
+ QString query;
+
+ for ( uint i = 0; i < queryWords.size(); ++i )
+ {
+ if ( i ) query += " AND ";
+
+ query += queryWords[i];
+ }
+
+ query = query.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+
+ // schedule jobs
+ DataRequest dr;
+ dr.url = KURL( QString( "http://citeseerx.ist.psu.edu/search?q=" ).append( query ).append( "&submit=Search&sort=rel" ) );
+ dr.parser = &WebQueryCiteSeerX::parseSummaryPage;
+ m_queryQueue.push_back( dr );
+
+ // start job queue
+ nextJob();
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // process results from current job
+
+ void WebQueryCiteSeerX::parseSummaryPage( const QString& data )
+ {
+ // regexp. for finding paper entries (example: href="/viewdoc/summary;jsessionid=12345ABCD?doi=10.1.1.108.9937")
+ QRegExp paperXpr( "href=\"(/viewdoc/summary[^?]*\\?doi=[^\"]+)\"" );
+
+ // count paper results and schedule single paper URLs
+
+ for ( int p = paperXpr.search( data ); p >= 0; p = paperXpr.search( data, p + paperXpr.matchedLength() ) )
+ {
+ if ( ++m_receivedHits > m_desiredHits )
+ break;
+
+ DataRequest dr;
+
+ dr.url = KURL( QString( "http://" ) + m_citeSeerXServer + paperXpr.cap( 1 ) );
+
+ dr.parser = &WebQueryCiteSeerX::parsePaperPage;
+
+ m_queryQueue.push_back( dr );
+ }
+
+ // if we haven't reached the desired number of hits, schedule the next summary page
+ QRegExp nextSummaryXpr( "<a href=\"([^\"]+)\">Next 10" );
+
+ if ( m_receivedHits < m_desiredHits )
+ if ( nextSummaryXpr.search( data ) >= 0 )
+ {
+ DataRequest dr;
+ dr.url = KURL( QString( "http://" ) + m_citeSeerXServer + nextSummaryXpr.cap( 1 ).replace( "&amp;", "&" ) );
+ dr.parser = &WebQueryCiteSeerX::parseSummaryPage;
+ m_queryQueue.push_back( dr );
+ }
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // process the result of one single paper link
+
+ void WebQueryCiteSeerX::parsePaperPage( const QString& data )
+ {
+ // find type and id: @XXX{ YYY
+ QRegExp typeIdXpr( "@(.*)\\{(.*)," );
+ typeIdXpr.setMinimal( true );
+ typeIdXpr.search( data );
+ QString typeStr = typeIdXpr.cap( 1 );
+ QString id = typeIdXpr.cap( 2 );
+
+ // create entry
+ Entry *entry = new BibTeX::Entry( typeIdXpr.cap( 1 ), typeIdXpr.cap( 2 ) );
+
+ // find abstract: <..>Abstract:</..> <..> XXX </..>
+ parseForSingleExpression( "<[^<]+>Abstract:</[^<]+>\\s*<[^<]+>([^<]+)</[^<]+>", data, entry, BibTeX::EntryField::ftAbstract );
+
+ // find title: title = {XXX}
+ parseForSingleExpression( "title = \\{([^}]+)\\}", data, entry, BibTeX::EntryField::ftTitle );
+
+ // find author: author = {XXX}
+ parseForSingleExpression( "author = \\{([^}]+)\\}", data, entry, BibTeX::EntryField::ftAuthor );
+
+ // find year: year = {XXX}
+ parseForSingleExpression( "year = \\{([^}]+)\\}", data, entry, BibTeX::EntryField::ftYear );
+
+ // find journal: journal = {XXX}
+ parseForSingleExpression( "journal = \\{([^}]+)\\}", data, entry, BibTeX::EntryField::ftJournal );
+
+ // find pages: pages = {XXX}
+ parseForSingleExpression( "pages = \\{([^}]+)\\}", data, entry, BibTeX::EntryField::ftPages );
+
+ // publish what we've found
+ emit foundEntry( entry, false );
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // find single bibtex field in html page and add to entry
+
+ void WebQueryCiteSeerX::parseForSingleExpression( QString description, const QString &data, Entry *entry, BibTeX::EntryField::FieldType type )
+ {
+ // search, and add to entry if found
+ QRegExp xpr( description );
+
+ if ( xpr.search( data ) + 1 )
+ {
+ EntryField *field = new EntryField( type );
+ field->setValue( new Value( xpr.cap( 1 ), false ) );
+ entry->addField( field );
+ }
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // read data from the job and start the current parser
+
+ void WebQueryCiteSeerX::getData( KIO::Job *job )
+ {
+ // advance GUI progress bar
+ enterNextStage();
+
+ if ( job && !job->error() && !m_aborted )
+ {
+
+ // read data
+ QBuffer data;
+ data.open( IO_WriteOnly );
+ data.writeBlock( dynamic_cast<KIO::StoredTransferJob*>( job )->data() );
+ data.close();
+ data.open( IO_ReadOnly );
+ QTextStream ts( &data );
+ QString result = ts.read();
+ data.close();
+
+ // hand the read data over to the parser
+ ( this->*m_currentParser )( result );
+ }
+
+ // proceed
+ nextJob();
+ }
+
+
+ //_______________________________________________________________________________________________________________
+ // call the next job
+
+ void WebQueryCiteSeerX::nextJob()
+ {
+ // no more requests: finished
+ if ( !m_queryQueue.size() )
+ {
+ setEndSearch( WebQuery::statusSuccess );
+ m_receivedHits = 0;
+ }
+ // else: take the next request from queue and start it
+ else if ( !m_aborted )
+ {
+ m_currentParser = m_queryQueue.front().parser;
+ KIO::Job *job = KIO::storedGet( m_queryQueue.front().url, FALSE, FALSE );
+ m_queryQueue.pop_front();
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( getData( KIO::Job * ) ) );
+ }
+ }
+
+}
+
+#include "webqueryciteseerx.moc"
diff --git a/src/webqueryciteseerx.h b/src/webqueryciteseerx.h
new file mode 100644
index 0000000..458e188
--- /dev/null
+++ b/src/webqueryciteseerx.h
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Jacob Kanev <[email protected]>, *
+ * Thomas Fischer <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYCITESEERX_H
+#define KBIBTEXWEBQUERYCITESEERX_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <kio/job.h>
+
+#include <fileimporterbibtex.h>
+#include <webquery.h>
+
+#include <deque>
+
+class QBuffer;
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+
+ class WebQueryCiteSeerXWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+
+ public:
+ WebQueryCiteSeerXWidget( QWidget *parent, const char *name = 0 );
+ };
+
+
+ /// Convinience typedef for member pointer to parsing function
+
+ class WebQueryCiteSeerX;
+ typedef void ( WebQueryCiteSeerX::* DataParser )( const QString & );
+
+ /// Query the citeseer database.
+ /** This class is used for querying the citeseer data base. CiteSeerX is still beta, so this class has to be adapted as soon as the CiteSeer people change their web interface. After entering the search term, citeseer returns a page with 10 links (one for each paper), and one link for the next 10 hits. This class uses a queue to schedule each reading job, and two parsing functions, one for the summary page and one for each paper result. BibTeX fields abstract, title, author, year, journal, and pages are found.
+ @author Jacob Kanev <[email protected]> */
+
+ class WebQueryCiteSeerX : public WebQuery
+ {
+ Q_OBJECT
+
+ public:
+
+ struct DataRequest
+ {
+ KURL url;
+ DataParser parser;
+ };
+
+ /// Construct.
+ WebQueryCiteSeerX( QWidget* parent );
+
+ /// Destroy.
+ virtual ~WebQueryCiteSeerX();
+
+ /// Main function: start query.
+ void query();
+
+ /// Return title.
+ QString title();
+
+ /// Return disclaimer.
+ QString disclaimer();
+
+ /// Return disclaimer URL.
+ QString disclaimerURL();
+
+ /// Return GUI element.
+ WebQueryWidget *widget();
+
+ protected:
+ /// Callback for cancelling.
+ void cancelQuery();
+
+ private slots:
+
+ /// Callback when the job is finished.
+ /**Reads the data from the job, and hands it over to the currently set parser. */
+ void getData( KIO::Job *job );
+
+ private:
+
+ /// Parses the main page and schedules single-paper reading jobs.
+ /** Function parses the summary page, and schedules one job for each paper link, and one job for the "Next 10" summary page. */
+ void parseSummaryPage( const QString &data );
+
+ /// Parses single-paper pages.
+ /** Function reads the "Abstract:" and the "@entrytype{" strings found in the html page. */
+ void parsePaperPage( const QString &data );
+
+ /// Execute next waiting job.
+ /** Takes the next query out of the queue, sets the appropriate parser, and schedules getData with the URL. */
+ void nextJob();
+
+ /// Find single bibtex field in html page and add to entry.
+ /** Function uses the first collected text from the description (a regular expression), and adds it as type "type" to the "entry". */
+ void parseForSingleExpression( QString description, const QString &data, BibTeX::Entry *entry, BibTeX::EntryField::FieldType type );
+
+ /// The currently active parser.
+ DataParser m_currentParser;
+
+ /// The internet address of CiteSeerX.
+ QString m_citeSeerXServer;
+
+ /// Number of hits desired by user.
+ int m_desiredHits;
+
+ /// Number of hits read from summary pages.
+ int m_receivedHits;
+
+ /// List with waiting queries
+ std::deque<DataRequest> m_queryQueue;
+
+ /// Pointer to QT-dialog.
+ WebQueryCiteSeerXWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/webquerycsb.cpp b/src/webquerycsb.cpp
new file mode 100644
index 0000000..2a5ac54
--- /dev/null
+++ b/src/webquerycsb.cpp
@@ -0,0 +1,289 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qregexp.h>
+#include <qbuffer.h>
+#include <qcstring.h>
+#include <qiodevice.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qfile.h>
+#include <qdatetime.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+
+#include <settings.h>
+#include "webquerycsb.h"
+
+namespace KBibTeX
+{
+ WebQueryCSBWidget::WebQueryCSBWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "CSB_query" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ value = settings->getWebQueryDefault( "CSB_field" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxField->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "CSB_yearCheck" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ checkBoxYear->setChecked( value == "1" );
+ value = settings->getWebQueryDefault( "CSB_yearType" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxYear->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "CSB_yearValue" );
+ value = value == QString::null ? "2000" : value;
+ spinBoxYear->setValue( value.toInt() );
+ value = settings->getWebQueryDefault( "CSB_sortBy" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxSortBy->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "CSB_onlinePapersOnly" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ checkBoxOnlinePapersOnly->setChecked( value == "1" );
+ slotTextChanged( value, true );
+ }
+
+ void WebQueryCSBWidget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearSearchText );
+ QLabel *label = new QLabel( i18n( "Search &term:" ), this );
+ hLayout->addWidget( label );
+ lineEditQuery = new KLineEdit( this );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+ hLayout->addWidget( lineEditQuery );
+ label->setBuddy( lineEditQuery );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ label = new QLabel( i18n( "Here, \"Field\" refers to a parameter for the CSB search (author, title, any)", "&Field:" ), this );
+ hLayout->addWidget( label );
+ comboBoxField = new KComboBox( false, this );
+ hLayout->addWidget( comboBoxField );
+ label->setBuddy( comboBoxField );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ hLayout->setStretchFactor( lineEditQuery, 5 );
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+
+ hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+ label = new QLabel( i18n( "&Number of results:" ), this );
+ hLayout->addWidget( label );
+ spinBoxMaxHits = new QSpinBox( 1, 500, 1, this );
+ spinBoxMaxHits->setValue( 10 );
+ hLayout->setStretchFactor( spinBoxMaxHits, 3 );
+ hLayout->addWidget( spinBoxMaxHits );
+ label->setBuddy( spinBoxMaxHits );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ checkBoxYear = new QCheckBox( i18n( "&Year:" ), this );
+ hLayout->setStretchFactor( checkBoxYear, 1 );
+ checkBoxYear->setChecked( true );
+ hLayout->addWidget( checkBoxYear );
+ connect( checkBoxYear, SIGNAL( toggled( bool ) ), this, SLOT( slotYearCheckToggled() ) );
+ comboBoxYear = new KComboBox( false, this );
+ hLayout->setStretchFactor( comboBoxYear, 3 );
+ hLayout->addWidget( comboBoxYear );
+ spinBoxYear = new QSpinBox( 1800, 2100, 1, this );
+ spinBoxYear->setValue( QDate::currentDate().year() );
+ hLayout->setStretchFactor( spinBoxYear, 6 );
+ hLayout->addWidget( spinBoxYear );
+
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ label = new QLabel( i18n( "Sort &by:" ), this );
+ hLayout->addWidget( label );
+ comboBoxSortBy = new KComboBox( false, this );
+ hLayout->setStretchFactor( comboBoxSortBy, 8 );
+ hLayout->addWidget( comboBoxSortBy );
+ label->setBuddy( comboBoxSortBy );
+
+ hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+ checkBoxOnlinePapersOnly = new QCheckBox( i18n( "Online papers only" ), this );
+ hLayout->addWidget( checkBoxOnlinePapersOnly );
+
+ comboBoxField->insertItem( i18n( "any" ) );
+ comboBoxField->insertItem( i18n( "author" ) );
+ comboBoxField->insertItem( i18n( "title" ) );
+ comboBoxYear->insertItem( i18n( "exact" ) );
+ comboBoxYear->insertItem( i18n( "until" ) );
+ comboBoxYear->insertItem( i18n( "from" ) );
+ comboBoxYear->setCurrentItem( 1 );
+ comboBoxSortBy->insertItem( i18n( "none" ) );
+ comboBoxSortBy->insertItem( i18n( "score" ) );
+ comboBoxSortBy->insertItem( i18n( "year" ) );
+ }
+
+ void WebQueryCSBWidget::slotYearCheckToggled()
+ {
+ bool yearEnabled = checkBoxYear->isChecked();
+ comboBoxYear->setEnabled( yearEnabled );
+ spinBoxYear->setEnabled( yearEnabled );
+ }
+
+ WebQueryCSB::WebQueryCSB( QWidget* parent ): WebQuery( parent )
+ {
+ m_importer = new BibTeX::FileImporterBibTeX( FALSE );
+ m_importer->setIgnoreComments( TRUE );
+ m_widget = new WebQueryCSBWidget( parent );
+ }
+
+ WebQueryCSB::~WebQueryCSB()
+ {
+ delete m_widget;
+ delete m_importer;
+ }
+
+ QString WebQueryCSB::title()
+ {
+ return i18n( "Computer Science Bibliographies" );
+ }
+
+ QString WebQueryCSB::disclaimer()
+ {
+ return i18n( "Copyright for the Bibliography Collection" );
+ }
+
+ QString WebQueryCSB::disclaimerURL()
+ {
+ return "http://liinwww.ira.uka.de/bibliography/Copyright.html";
+ }
+
+ WebQueryWidget *WebQueryCSB::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryCSB::query()
+ {
+ WebQuery::query();
+
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "CSB_query", m_widget->lineEditQuery->text() );
+ settings->setWebQueryDefault( "CSB_field", QString::number( m_widget->comboBoxField->currentItem() ) );
+ settings->setWebQueryDefault( "CSB_yearCheck", m_widget->checkBoxYear->isChecked() ? "1" : "0" );
+ settings->setWebQueryDefault( "CSB_yearType", QString::number( m_widget->comboBoxYear->currentItem() ) );
+ settings->setWebQueryDefault( "CSB_yearValue", QString::number( m_widget->spinBoxYear->value() ) );
+ settings->setWebQueryDefault( "CSB_sortBy", QString::number( m_widget->comboBoxSortBy->currentItem() ) );
+ settings->setWebQueryDefault( "CSB_onlinePapersOnly", m_widget->checkBoxOnlinePapersOnly->isChecked() ? "1" : "0" );
+
+ setNumStages( 1 );
+
+ int numberOfResults = m_widget->spinBoxMaxHits->value();
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+
+ QString year;
+ if ( m_widget->checkBoxYear->isChecked() )
+ {
+ switch ( m_widget->comboBoxYear->currentItem() )
+ {
+ case 1: year = QString( "before=%1" ).arg( m_widget->spinBoxYear->value() ); break;
+ case 2: year = QString( "since=%1" ).arg( m_widget->spinBoxYear->value() ); break;
+ default: year = QString( "year=%1" ).arg( m_widget->spinBoxYear->value() ); break;
+ }
+ }
+
+ QString field;
+ switch ( m_widget->comboBoxField->currentItem() )
+ {
+ case 1: field = "au"; break;
+ case 2: field = "ti"; break;
+ default: field = ""; break;
+ }
+
+ QString sortBy;
+ switch ( m_widget->comboBoxSortBy->currentItem() )
+ {
+ case 1: sortBy = "&sort=score"; break;
+ case 2: sortBy = "&sort=year"; break;
+ default: sortBy = ""; break;
+ }
+
+ QString onlinePapersOnly = m_widget->checkBoxOnlinePapersOnly->isChecked() ? "&online=on" : "";
+
+ KURL url = KURL( QString( "http://liinwww.ira.uka.de/csbib?query=%4&results=bibtex&maxnum=%1&%2&field=%3" ).arg( numberOfResults ).arg( year ).arg( field ).arg( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ).append( onlinePapersOnly ).append( sortBy ) );
+
+ QString rawText = download( url );
+ if ( rawText != NULL && !m_aborted )
+ {
+ QRegExp removeXML( "<[^>]+>" );
+ rawText.replace( removeXML, "" );
+
+ BibTeX::FileImporterBibTeX importer( FALSE );
+ importer.setIgnoreComments( TRUE );
+ QBuffer buffer;
+
+ buffer.open( IO_WriteOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << rawText << endl;
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ BibTeX::File *tmpBibFile = importer.load( &buffer );
+ buffer.close();
+
+ if ( tmpBibFile != NULL && tmpBibFile->count() > 0 )
+ {
+ for ( BibTeX::File::ElementList::iterator it = tmpBibFile->begin(); !m_aborted && it != tmpBibFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ }
+
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else
+ setEndSearch( WebQuery::statusError );
+
+ if ( tmpBibFile != NULL )
+ delete tmpBibFile;
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+ }
+
+}
+#include "webquerycsb.moc"
diff --git a/src/webquerycsb.h b/src/webquerycsb.h
new file mode 100644
index 0000000..bedc3cc
--- /dev/null
+++ b/src/webquerycsb.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYCSB_H
+#define KBIBTEXWEBQUERYCSB_H
+
+#include <kio/job.h>
+
+#include <fileimporterbibtex.h>
+#include <webquery.h>
+
+class QSpinBox;
+class QCheckBox;
+
+class KLineEdit;
+class KComboBox;
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryCSBWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryCSBWidget( QWidget *parent, const char *name = 0 );
+
+ KComboBox *comboBoxField;
+ QCheckBox *checkBoxYear;
+ KComboBox *comboBoxYear;
+ QSpinBox *spinBoxYear;
+ KComboBox *comboBoxSortBy;
+ QCheckBox *checkBoxOnlinePapersOnly;
+
+ protected:
+ virtual void init();
+
+ private slots:
+ void slotYearCheckToggled();
+ };
+
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryCSB : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryCSB( QWidget* parent );
+ virtual ~WebQueryCSB();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ BibTeX::FileImporterBibTeX *m_importer;
+ WebQueryCSBWidget *m_widget;
+
+ };
+
+}
+
+#endif
diff --git a/src/webquerydblp.cpp b/src/webquerydblp.cpp
new file mode 100644
index 0000000..38d6492
--- /dev/null
+++ b/src/webquerydblp.cpp
@@ -0,0 +1,213 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qapplication.h>
+#include <qspinbox.h>
+#include <qregexp.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <kurl.h>
+
+#include <settings.h>
+#include <fileimporterbibtex.h>
+#include "webquerydblp.h"
+
+namespace KBibTeX
+{
+ WebQueryDBLPWidget::WebQueryDBLPWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "DBLP_query" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ value = settings->getWebQueryDefault( "DBLP_keepSeparate" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ checkBoxKeepEntriesSeparate->setChecked( value == "1" );
+ }
+
+ void WebQueryDBLPWidget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearSearchText );
+ QLabel *label = new QLabel( i18n( "Search &term:" ), this );
+ hLayout->addWidget( label );
+ lineEditQuery = new KLineEdit( this );
+ hLayout->addWidget( lineEditQuery );
+ label->setBuddy( lineEditQuery );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ hLayout->setStretchFactor( lineEditQuery, 4 );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+
+ label = new QLabel( i18n( "&Number of results:" ), this );
+ hLayout->addWidget( label );
+ spinBoxMaxHits = new QSpinBox( 1, 250, 1, this );
+ spinBoxMaxHits->setValue( 10 );
+ hLayout->addWidget( spinBoxMaxHits );
+ label->setBuddy( spinBoxMaxHits );
+
+ hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ checkBoxKeepEntriesSeparate = new QCheckBox( i18n( "Do not merge corresponding entries" ), this );
+ hLayout->addWidget( checkBoxKeepEntriesSeparate );
+
+ vLayout->addStretch( 0 );
+
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+ }
+
+ WebQueryDBLP::WebQueryDBLP( QWidget* parent ): WebQuery( parent )
+ {
+ m_widget = new WebQueryDBLPWidget( parent );
+ }
+
+ WebQueryDBLP::~WebQueryDBLP()
+ {
+ delete m_widget;
+ }
+
+ QString WebQueryDBLP::title()
+ {
+ return i18n( "DBLP" );
+ }
+
+ QString WebQueryDBLP::disclaimer()
+ {
+ return i18n( "DBLP - Copyright" );
+ }
+
+ QString WebQueryDBLP::disclaimerURL()
+ {
+ return "http://www.informatik.uni-trier.de/~ley/db/copyright.html";
+ }
+
+ WebQueryWidget *WebQueryDBLP::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryDBLP::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "DBLP_query", m_widget->lineEditQuery->text() );
+ settings->setWebQueryDefault( "DBLP_keepSeparate", m_widget->checkBoxKeepEntriesSeparate->isChecked() ? "1" : "0" );
+
+ int numberOfResults = m_widget->spinBoxMaxHits->value();
+ setNumStages( numberOfResults + 1 );
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ KURL url = KURL( QString( "http://dblp.l3s.de/?newsearch=1&q=%1&search_opt=all&synt_query_exp=full" ).arg( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ) );
+
+ QString completeText = download( url );
+ if ( completeText != QString::null && !m_aborted )
+ {
+ QRegExp findBibTeXurl( "<a href=\"(http://dblp.uni-trier.de/rec/bibtex/[^\"]+)\"" );
+ findBibTeXurl.search( completeText );
+ int pos = findBibTeXurl.pos( 1 );
+
+ int maxCount = numberOfResults;
+ while ( !m_aborted && pos > -1 && ( maxCount-- ) > 0 )
+ {
+ KURL keyUrl = KURL( findBibTeXurl.cap( 1 ) );
+ BibTeX::File *tmpBibFile = downloadBibTeXFile( keyUrl );
+ if ( tmpBibFile != NULL && !m_aborted )
+ {
+ if ( tmpBibFile->count() == 2 )
+ {
+ /** if the data returned from DBLP contains only two entry, check if they are InCollection and Book. In this case, one is the conference article and the other is the conference proceedings. */
+ BibTeX::Entry *firstEntry = dynamic_cast<BibTeX::Entry*>( *tmpBibFile->begin() );
+ BibTeX::Entry *secondEntry = dynamic_cast<BibTeX::Entry*>( *( ++tmpBibFile->begin() ) );
+
+ if ( !m_widget->checkBoxKeepEntriesSeparate->isChecked() && firstEntry != NULL && secondEntry != NULL && ( firstEntry->entryType() == BibTeX::Entry::etInProceedings || firstEntry->entryType() == BibTeX::Entry::etInCollection ) && ( secondEntry->entryType() == BibTeX::Entry::etBook || secondEntry->entryType() == BibTeX::Entry::etProceedings ) )
+ {
+ /** We merge both conference article and proceedings, as otherwise 2*n entries will be shown in the search result and it is no longer clear, which conference and with article match. */
+ BibTeX::Entry *myEntry = tmpBibFile->completeReferencedFieldsConst( firstEntry );
+ myEntry->merge( secondEntry, BibTeX::Entry::msAddNew );
+ myEntry->deleteField( BibTeX::EntryField::ftCrossRef );
+ emit foundEntry( myEntry, false );
+ }
+ else
+ {
+ emit foundEntry( new BibTeX::Entry( firstEntry ), false );
+ emit foundEntry( new BibTeX::Entry( secondEntry ), m_widget->checkBoxKeepEntriesSeparate->isChecked() );
+ }
+ }
+ else
+ for ( BibTeX::File::ElementList::iterator it = tmpBibFile->begin(); it != tmpBibFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ }
+ }
+
+ if ( tmpBibFile != NULL )
+ delete tmpBibFile;
+
+ findBibTeXurl.search( completeText, pos + 1 );
+ pos = findBibTeXurl.pos( 1 );
+ }
+
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+ }
+
+}
+#include "webquerydblp.moc"
diff --git a/src/webquerydblp.h b/src/webquerydblp.h
new file mode 100644
index 0000000..f52ef3d
--- /dev/null
+++ b/src/webquerydblp.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYDBLP_H
+#define KBIBTEXWEBQUERYDBLP_H
+
+#include <webquery.h>
+
+class QCheckBox;
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryDBLPWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryDBLPWidget( QWidget *parent, const char *name = 0 );
+ QCheckBox *checkBoxKeepEntriesSeparate;
+
+ protected:
+ virtual void init();
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryDBLP : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryDBLP( QWidget* parent );
+ virtual ~WebQueryDBLP();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQueryDBLPWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/webquerygooglescholar.cpp b/src/webquerygooglescholar.cpp
new file mode 100644
index 0000000..a1c2d52
--- /dev/null
+++ b/src/webquerygooglescholar.cpp
@@ -0,0 +1,469 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qapplication.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qmap.h>
+#include <qspinbox.h>
+#include <kconfig.h>
+
+#include <klineedit.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kio/job.h>
+
+#include <dcopref.h>
+
+#include <settings.h>
+#include "webquerygooglescholar.h"
+
+namespace KBibTeX
+{
+ WebQueryGoogleScholarWidget::WebQueryGoogleScholarWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "GoogleScholar" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+ WebQueryGoogleScholar::WebQueryGoogleScholar( QWidget* parent )
+ : WebQuery( parent ), m_transferJob( NULL ), m_transferJobBuffer( NULL )
+ {
+ m_importer = new BibTeX::FileImporterBibTeX( FALSE );
+ m_importer->setIgnoreComments( TRUE );
+ m_widget = new WebQueryGoogleScholarWidget( parent );
+ }
+
+ WebQueryGoogleScholar::~WebQueryGoogleScholar()
+ {
+ delete m_widget;
+ delete m_importer;
+ }
+
+ QString WebQueryGoogleScholar::title()
+ {
+ return i18n( "Google Scholar" );
+ }
+
+ QString WebQueryGoogleScholar::disclaimer()
+ {
+ return i18n( "About Google Scholar" );
+ }
+
+ QString WebQueryGoogleScholar::disclaimerURL()
+ {
+ return "http://scholar.google.com/intl/en/scholar/about.html";
+ }
+
+ WebQueryWidget *WebQueryGoogleScholar::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryGoogleScholar::query()
+ {
+ WebQuery::query();
+
+ /** save search term in settings */
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "GoogleScholar", m_widget->lineEditQuery->text() );
+
+ /** generate web-save search term */
+ m_searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ m_searchTerm = m_searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+ if ( m_searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ /** initialize variables */
+ m_abort = false;
+ m_numberOfResults = m_widget->spinBoxMaxHits->value();
+ setNumStages( m_numberOfResults + 5 );
+
+ /** reset KDE configuration for cookie handling */
+ readAndChangeConfig();
+
+ /** prepare HTTP request (buffer, signals, job) */
+ m_transferJobBuffer = new QBuffer();
+ m_transferJobBuffer->open( IO_WriteOnly );
+ KIO::TransferJob* m_transferJob = KIO::get( KURL( "http://scholar.google.com/scholar_ncr" ), false, false );
+ connect( m_transferJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ), this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+ connect( m_transferJob, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinishedStartpage( KIO::Job * ) ) );
+ }
+
+ void WebQueryGoogleScholar::cancelQuery()
+ {
+ /** user aborted search */
+ m_abort = true;
+ if ( m_transferJob != NULL ) m_transferJob->kill( false );
+ setEndSearch( WebQuery::statusError );
+ }
+
+ void WebQueryGoogleScholar::slotFinishedStartpage( KIO::Job *job )
+ {
+ /** close and delete buffer (content does not matter) */
+ m_transferJobBuffer->close();
+ delete m_transferJobBuffer;
+
+ /** if aborted in the mean time, clean up everything */
+ if ( m_abort )
+ {
+ restoreConfig();
+ return;
+ }
+
+ /** error occurred */
+ if ( job->error() != 0 )
+ {
+ restoreConfig();
+ kdDebug() << "Error in slotFinishedStartpage: " << job->error() << endl;
+ setEndSearch( statusError );
+ return;
+ }
+
+ /** update progress bar */
+ enterNextStage();
+
+ /** prepare next HTTP request for preferences page (buffer, signals, job) */
+ m_transferJobBuffer = new QBuffer();
+ m_transferJobBuffer->open( IO_WriteOnly );
+ KIO::TransferJob* m_transferJob = KIO::get( KURL( "http://scholar.google.com/scholar_preferences?hl=en" ), false, false );
+ connect( m_transferJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ), this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+ connect( m_transferJob, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinishedLoadingSettings( KIO::Job * ) ) );
+
+ }
+
+ void WebQueryGoogleScholar::slotFinishedLoadingSettings( KIO::Job *job )
+ {
+ /** close and delete buffer (content does not matter) */
+ m_transferJobBuffer->close();
+ QString htmlCode = textFromBuffer( m_transferJobBuffer );
+ delete m_transferJobBuffer;
+
+ /** if aborted in the mean time, clean up everything */
+ if ( m_abort )
+ {
+ restoreConfig();
+ return;
+ }
+
+ /** error occurred */
+ if ( job->error() != 0 )
+ {
+ restoreConfig();
+ kdDebug() << "Error in slotFinishedLoadingSettings: " << job->error() << endl;
+ setEndSearch( statusError );
+ return;
+ }
+
+ /** update progress bar */
+ enterNextStage();
+
+ /** parse html code to get form values */
+ QMap<QString, QString> keyValues = evalFormFields( htmlCode );
+ /** set form values for BibTeX search */
+ keyValues["scis"] = "yes";
+ keyValues["scisf"] = "4";
+ keyValues["submit"] = "Save+Preferences";
+ keyValues["num"] = QString::number( m_numberOfResults );
+
+ /** prepare next HTTP request to submit preferences (buffer, signals, job) */
+ KURL nextUrl( formFieldsToUrl( "http://scholar.google.com/scholar_setprefs", keyValues ) );
+ m_transferJobBuffer = new QBuffer();
+ m_transferJobBuffer->open( IO_WriteOnly );
+ KIO::TransferJob* m_transferJob = KIO::get( nextUrl, false, false );
+ connect( m_transferJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ), this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+ connect( m_transferJob, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinishedSavingSettings( KIO::Job * ) ) );
+ }
+
+ void WebQueryGoogleScholar::slotFinishedSavingSettings( KIO::Job *job )
+ {
+ /** close and delete buffer (content does not matter) */
+ m_transferJobBuffer->close();
+ QString htmlCode = textFromBuffer( m_transferJobBuffer );
+ delete m_transferJobBuffer;
+
+ /** if aborted in the mean time, clean up everything */
+ if ( m_abort )
+ {
+ restoreConfig();
+ return;
+ }
+
+ /** error occurred */
+ if ( job->error() != 0 )
+ {
+ restoreConfig();
+ kdDebug() << "Error in slotFinishedSavingSettings: " << job->error() << endl;
+ setEndSearch( statusError );
+ return;
+ }
+
+ /** update progress bar */
+ enterNextStage();
+
+ /** parse html code to get form values */
+ QMap<QString, QString> keyValues = evalFormFields( htmlCode );
+ /** set form values for search */
+ keyValues["q"] = m_searchTerm;
+ keyValues["num"] = QString::number( m_numberOfResults );
+
+ /** prepare next HTTP request for actual search (buffer, signals, job) */
+ KURL nextUrl( formFieldsToUrl( "http://scholar.google.com/scholar", keyValues ) );
+ m_transferJobBuffer = new QBuffer();
+ m_transferJobBuffer->open( IO_WriteOnly );
+ KIO::TransferJob* m_transferJob = KIO::get( nextUrl, false, false );
+ connect( m_transferJob, SIGNAL( data( KIO::Job *, const QByteArray & ) ), this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+ connect( m_transferJob, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinishedReceivingResultOverview( KIO::Job * ) ) );
+ }
+
+ void WebQueryGoogleScholar::slotFinishedReceivingResultOverview( KIO::Job *job )
+ {
+ /** close and delete buffer (content does not matter) */
+ m_transferJobBuffer->close();
+ QString htmlCode = textFromBuffer( m_transferJobBuffer );
+ delete m_transferJobBuffer;
+
+ /** if aborted in the mean time, clean up everything */
+ if ( m_abort )
+ {
+ restoreConfig();
+ return;
+ }
+
+ /** error occurred */
+ if ( job->error() != 0 )
+ {
+ restoreConfig();
+ kdDebug() << "Error in slotFinishedReceivingResultOverview: " << job->error() << endl;
+ setEndSearch( statusError );
+ return;
+ }
+
+ /** update progress bar */
+ enterNextStage();
+
+ /** find all links to BibTeX files in result page */
+ QRegExp reBibUrl( "/scholar.bib[^ \">]+" );
+ int pos = 0;
+ while ( !m_aborted && ( pos = htmlCode.find( reBibUrl, pos + 1 ) ) > 0 )
+ {
+ /** download individual BibTeX file for each search hit */
+ KURL bibUrl( "http://scholar.google.com" + reBibUrl.cap( 0 ).replace( "&amp;", "&" ) );
+ BibTeX::File *tmpBibFile = downloadBibTeXFile( bibUrl );
+
+ /** update progress bar */
+ enterNextStage();
+
+ /** parse, evaluate and store first BibTeX entry */
+ if ( tmpBibFile != NULL )
+ {
+ BibTeX::File::ElementList::iterator it = tmpBibFile->begin();
+ if ( it != tmpBibFile->end() )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ }
+ delete tmpBibFile;
+ }
+ }
+
+ /** restore old cookie configuration */
+ restoreConfig();
+
+ /** set result status */
+ if ( m_aborted )
+ setEndSearch( statusAborted );
+ else
+ setEndSearch( statusSuccess );
+ }
+
+ void WebQueryGoogleScholar::readAndChangeConfig()
+ {
+ KConfig cfg( "kcookiejarrc" );
+ cfg.setGroup( "Cookie Policy" );
+ m_originalEnableCookies = cfg.readBoolEntry( "Cookies", true );
+ m_originalSessionCookies = cfg.readBoolEntry( "AcceptSessionCookies", true );
+ QStringList cookieSettingsList = QStringList::split( ',', cfg.readEntry( "CookieDomainAdvice", "" ) );
+ m_originalCookieGlobalAdvice = cfg.readEntry( "CookieGlobalAdvice", "Accept" );
+
+ for ( QStringList::Iterator it = cookieSettingsList.begin(); it != cookieSettingsList.end(); ++it )
+ {
+ QStringList keyValue = QStringList::split( ':', *it );
+ if ( keyValue.size() == 2 )
+ {
+ m_originalCookieMap[keyValue[0]] = keyValue[1];
+ }
+ }
+
+ cfg.writeEntry( "Cookies", true );
+ cfg.writeEntry( "CookieGlobalAdvice", "Accept" );
+ cfg.writeEntry( "AcceptSessionCookies", true );
+ cookieSettingsList.clear();
+ for ( QMap<QString, QString>::Iterator it = m_originalCookieMap.begin(); it != m_originalCookieMap.end(); ++it )
+ {
+ QString value = it.key().contains( ".google." ) ? "Accept" : it.data();
+ cookieSettingsList << it.key() + ":" + value;
+ }
+ cfg.writeEntry( "CookieDomainAdvice", cookieSettingsList.join( "," ) );
+ cfg.sync();
+
+ ( void )DCOPRef( "kded", "kcookiejar" ).send( "reloadPolicy" );
+ }
+
+ void WebQueryGoogleScholar::restoreConfig()
+ {
+ KConfig cfg( "kcookiejarrc" );
+ cfg.setGroup( "Cookie Policy" );
+ cfg.writeEntry( "CookieGlobalAdvice", m_originalCookieGlobalAdvice );
+ cfg.writeEntry( "Cookies", m_originalEnableCookies );
+ cfg.writeEntry( "AcceptSessionCookies", m_originalSessionCookies );
+ QStringList cookieSettingsList;
+ for ( QMap<QString, QString>::Iterator it = m_originalCookieMap.begin(); it != m_originalCookieMap.end(); ++it )
+ cookieSettingsList << it.key() + ":" + it.data();
+ cfg.writeEntry( "CookieDomainAdvice", cookieSettingsList.join( "," ) );
+ cfg.sync();
+
+ if ( !m_originalEnableCookies )
+ ( void )DCOPRef( "kded", "kcookiejar" ).send( "shutdown" );
+ else
+ ( void )DCOPRef( "kded", "kcookiejar" ).send( "reloadPolicy" );
+ }
+
+ QString WebQueryGoogleScholar::textFromBuffer( QBuffer *buffer )
+ {
+ QString htmlCode = "";
+ buffer->open( IO_ReadOnly );
+ QTextStream ts( buffer );
+ while ( !ts.atEnd() )
+ htmlCode.append( ts.readLine() );
+ buffer->close();
+ return htmlCode;
+ }
+
+ QMap <QString, QString> WebQueryGoogleScholar::evalFormFields( const QString &htmlCode )
+ {
+ QMap<QString, QString> keyValues;
+
+ QRegExp reInput( "<input[^>]+>" );
+ QRegExp reSplit( "[<>=\" ]+" );
+ int pos = 0;
+ while (( pos = htmlCode.find( reInput, pos + 1 ) ) > 5 )
+ {
+ QStringList elements = QStringList::split( reSplit, reInput.cap( 0 ) );
+ bool checked = false;
+ bool isCheckable = false;
+ bool isSubmit = false;
+ QString key = QString::null;
+ QString value = QString::null;
+ for ( QStringList::Iterator it = elements.begin(); it != elements.end(); ++it )
+ {
+ if ( *it == "name" )
+ {
+ ++it; if ( it != elements.end() ) key = *it; else break;
+ }
+ if ( *it == "value" )
+ {
+ ++it; if ( it != elements.end() ) value = *it; else
+ {
+ value = ""; break;
+ }
+ }
+ if ( *it == "checked" )
+ checked = true;
+ if ( *it == "type" )
+ {
+ ++it;
+ if ( it == elements.end() ) break;
+ isCheckable = *it == "radio" || *it == "checkbox";
+ isSubmit = *it == "submit";
+ }
+ }
+ if (( !isCheckable || checked ) && ( !isSubmit || value == "submit" ) && value != QString::null && key != QString::null )
+ {
+ keyValues[key] = value;
+ }
+ }
+
+ QRegExp reSelect( "<select name=([^ >\"]+).*</select>" );
+ reSelect.setMinimal( true );
+ QRegExp reOption( "<option[^>]+>" );
+ int pos3 = 0;
+ while (( pos3 = htmlCode.find( reSelect, pos3 + 1 ) ) > 5 )
+ {
+ QString key = reSelect.cap( 1 );
+ QString sub = reSelect.cap( 0 );
+ int pos2 = 0;
+ while (( pos2 = sub.find( reOption, pos2 + 1 ) ) > 5 )
+ {
+ QStringList elements = QStringList::split( reSplit, reOption.cap( 0 ) );
+ bool selected = false;
+ QString value = QString::null;
+ for ( QStringList::Iterator it = elements.begin(); it != elements.end(); ++it )
+ {
+ if ( *it == "value" )
+ {
+ ++it; if ( it != elements.end() ) value = *it; else
+ {
+ value = ""; break;
+ }
+ }
+ if ( *it == "selected" )
+ selected = true;
+ }
+ if ( selected && value != QString::null && key != QString::null )
+ {
+ keyValues[key] = value;
+ }
+ }
+ }
+
+ return keyValues;
+ }
+
+ QString WebQueryGoogleScholar::formFieldsToUrl( const QString &prefix, const QMap<QString, QString> &keyValues )
+ {
+ bool first = true;
+ QString nextUrl = prefix;
+ for ( QMap<QString, QString>::ConstIterator it = keyValues.begin(); it != keyValues.end(); ++it )
+ {
+ if ( first )
+ nextUrl.append( "?" );
+ else
+ nextUrl.append( "&" );
+ first = false;
+ nextUrl.append( it.key() + "=" + it.data() );
+ }
+
+ return nextUrl;
+ }
+
+}
+#include "webquerygooglescholar.moc"
diff --git a/src/webquerygooglescholar.h b/src/webquerygooglescholar.h
new file mode 100644
index 0000000..6d9065a
--- /dev/null
+++ b/src/webquerygooglescholar.h
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYGOOGLESCHOLAR_H
+#define KBIBTEXWEBQUERYGOOGLESCHOLAR_H
+
+#include <qstringlist.h>
+#include <qbuffer.h>
+
+#include <kurl.h>
+
+#include <fileimporterbibtex.h>
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryGoogleScholarWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryGoogleScholarWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryGoogleScholar : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryGoogleScholar( QWidget* parent );
+ virtual ~WebQueryGoogleScholar();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery();
+
+ private slots:
+ void slotData( KIO::Job *, const QByteArray &data )
+ {
+ m_transferJobBuffer->writeBlock( data.data(), data.size() );
+ };
+
+ /** Google Scholar's start page has been loaded */
+ void slotFinishedStartpage( KIO::Job *job );
+ /** Settings page has been loaded */
+ void slotFinishedLoadingSettings( KIO::Job *job );
+ /** Settings page upload and search mask loaded */
+ void slotFinishedSavingSettings( KIO::Job *job );
+ /** page with results loaded */
+ void slotFinishedReceivingResultOverview( KIO::Job *job );
+
+ private:
+ WebQueryGoogleScholarWidget *m_widget;
+
+ bool m_abort;
+ QString m_searchTerm;
+ int m_numberOfResults;
+ BibTeX::FileImporterBibTeX *m_importer;
+ bool m_originalEnableCookies;
+ bool m_originalSessionCookies;
+ QMap <QString, QString> m_originalCookieMap;
+ QString m_originalCookieGlobalAdvice;
+
+ KIO::TransferJob *m_transferJob;
+ QBuffer *m_transferJobBuffer;
+
+ /** load KDE's cookie configuration, store values, and reset with Google-friendly values */
+ void readAndChangeConfig();
+ /** restore previous configuration values by saving old cookie configuration */
+ void restoreConfig();
+
+ /** extract text from a QBuffer object */
+ QString textFromBuffer( QBuffer *buffer );
+
+ /** parse HTML code and get all key-value pairs from <input..> and <select><option ...></select> */
+ QMap <QString, QString> evalFormFields( const QString &htmlCode );
+
+ /** glue together URL from key-value pairs in form */
+ QString formFieldsToUrl( const QString &prefix, const QMap<QString, QString> &keyValues );
+ };
+
+}
+
+#endif
diff --git a/src/webqueryieeexplore.cpp b/src/webqueryieeexplore.cpp
new file mode 100644
index 0000000..070f8ca
--- /dev/null
+++ b/src/webqueryieeexplore.cpp
@@ -0,0 +1,267 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qspinbox.h>
+#include <qfile.h>
+
+#include <kio/jobclasses.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <klineedit.h>
+#include <kurl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <settings.h>
+#include <entryfield.h>
+#include <file.h>
+#include <fileimporterbibtex.h>
+#include "webqueryieeexplore.h"
+
+#define min(a,b) ((a)>(b)?(b):(a))
+
+namespace KBibTeX
+{
+ WebQueryIEEExploreWidget::WebQueryIEEExploreWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "IEEE" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+ WebQueryIEEExplore::WebQueryIEEExplore( QWidget* parent ): WebQuery( parent ), m_numberOfMatches( "Your search matched <strong>(\\d+)</strong> of" ), m_findArNumber( "srchabstract.jsp\\?arnumber=(\\d+)" ), m_date( "(?:([A-Z][a-z]{2,3})(?:(?:/|-\\d+\\s+)([A-Z][a-z]{2,3}))?)?\\.?\\s*(\\d{4})$" ), m_risURL( "http://ieeexplore.ieee.org/xpls/citationAct" )
+ {
+ m_widget = new WebQueryIEEExploreWidget( parent );
+ m_bibtexImporter = new BibTeX::FileImporterBibTeX( false );
+ }
+
+ WebQueryIEEExplore::~WebQueryIEEExplore()
+ {
+ delete m_bibtexImporter;
+ delete m_widget;
+ }
+
+ QString WebQueryIEEExplore::title()
+ {
+ return i18n( "IEEExplore" );
+ }
+
+ QString WebQueryIEEExplore::disclaimer()
+ {
+ return i18n( "What is IEEE Xplore?" );
+ }
+
+ QString WebQueryIEEExplore::disclaimerURL()
+ {
+ return "http://ieeexplore.ieee.org/guide/g_oview_faq.jsp";
+ }
+
+ WebQueryWidget *WebQueryIEEExplore::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryIEEExplore::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "IEEE", m_widget->lineEditQuery->text() );
+
+ m_arnumList.clear();
+ m_numMaxHits = min( 50, m_widget->spinBoxMaxHits->value() );
+ setNumStages( m_numMaxHits + 1 );
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ QString category = "metadata";
+ KURL url = KURL( QString( "http://ieeexplore.ieee.org/search/freesearchresult.jsp?queryText=" ).append( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ).append( "+%3Cin%3E+" ).append( category ).append( "&ResultCount=" ).append( QString::number( m_numMaxHits ) ).append( "&ResultStart=0" ) );
+
+ QString completeText = downloadHTML( url );
+ if ( completeText != QString::null && !m_aborted )
+ {
+ if ( completeText.find( "You have entered an invalid search" ) > -1 )
+ {
+ KMessageBox::information( m_widget, i18n( "You have entered an invalid search." ), i18n( "Search Error" ) );
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+ else if ( completeText.find( "No results" ) > -1 )
+ {
+ setEndSearch( WebQuery::statusSuccess );
+ return;
+ }
+
+ m_numberOfMatches.search( completeText );
+ bool ok;
+ m_numMatches = m_numberOfMatches.cap( 1 ).toInt( &ok );
+ if ( !ok ) m_numMatches = 0;
+
+ if ( m_numMatches <= 0 )
+ {
+ setEndSearch( WebQuery::statusSuccess );
+ return;
+ }
+
+ m_findArNumber.search( completeText );
+ for ( int i = 0; i < m_numMatches; ++i )
+ {
+ if ( m_findArNumber.cap( 1 ).isEmpty() ) break;
+ int arnum = m_findArNumber.cap( 1 ).toInt( &ok );
+ if ( !ok || arnum <= 0 ) break;
+ m_arnumList.append( arnum );
+
+ m_findArNumber.search( completeText, m_findArNumber.pos( 1 ) + 1 );
+ }
+
+ if ( !m_arnumList.isEmpty() )
+ {
+ m_hitCounter = 1;
+ fetchNext();
+ }
+ else
+ {
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ {
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ }
+
+ void WebQueryIEEExplore::fetchNext()
+ {
+ if ( m_arnumList.isEmpty() ) return;
+
+ int arnum = m_arnumList.first();
+ m_arnumList.remove( m_arnumList.begin() );
+
+ m_incomingData = "";
+ QString data = "dlSelect=cite&fileFormate=BibTex&arnumber=%3Carnumber%3E" + QString::number( arnum ) + "%3C%2Farnumber%3E&Submit=Download";
+
+ KIO::TransferJob *job = KIO::http_post( m_risURL, data.utf8(), false );
+ job->addMetaData( "content-type", "Content-Type: application/x-www-form-urlencoded" );
+ connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotResult( KIO::Job * ) ) );
+ }
+
+ void WebQueryIEEExplore::slotData( KIO::Job *, const QByteArray &data )
+ {
+ if ( data.size() > 0 )
+ m_incomingData.append( QCString( data, data.size() + 1 ) );
+ }
+
+ void WebQueryIEEExplore::slotResult( KIO::Job *job )
+ {
+ QRegExp m_date( "^(((\\d{1,2}(-\\d{1,2}))\\s+)?(([A-Z][a-z]{2,3})(/([A-Z][a-z]{2,3}))?)\\.?\\s+)?(\\d{4})$" );
+ if ( job->error() )
+ {
+ job->showErrorDialog();
+ return;
+ }
+
+ enterNextStage();
+ m_incomingData.replace( "<br>", "" );
+
+ BibTeX::File *bibtexFile = m_bibtexImporter->load( m_incomingData );
+ if ( bibtexFile != NULL )
+ {
+ for ( BibTeX::File::ElementList::iterator it = bibtexFile->begin(); it != bibtexFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ {
+ fixDate( entry );
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ }
+ }
+ delete bibtexFile;
+ }
+
+ if ( !m_arnumList.isEmpty() )
+ fetchNext();
+ else
+ {
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ }
+
+ void WebQueryIEEExplore::fixDate( BibTeX::Entry *entry )
+ {
+ m_date.search( entry->getField( BibTeX::EntryField::ftYear )->value()->text() );
+
+ if ( !m_date.cap( 3 ).isNull() && !m_date.cap( 3 ).isEmpty() )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftYear );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftJournal );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( m_date.cap( 3 ), true ) );
+ }
+
+ QString newMonth = QString::null;
+ if ( !m_date.cap( 1 ).isNull() && !m_date.cap( 1 ).isEmpty() && ( newMonth = parseMonth( m_date.cap( 1 ) ) ) != QString::null )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftMonth );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftJournal );
+ entry->addField( field );
+ }
+
+ field->setValue( new BibTeX::Value( newMonth, true ) );
+
+ newMonth = QString::null;
+ if ( !m_date.cap( 2 ).isNull() && !m_date.cap( 2 ).isEmpty() && ( newMonth = parseMonth( m_date.cap( 2 ) ) ) != QString::null )
+ {
+ field->value()->items.append( new BibTeX::PlainText( "/" ) );
+ field->value()->items.append( new BibTeX::MacroKey( newMonth ) );
+ }
+ }
+ }
+
+ QString WebQueryIEEExplore::parseMonth( const QString &month )
+ {
+ for ( unsigned int i = 0; i < sizeof( BibTeX::MonthsTriple ) / sizeof( BibTeX::MonthsTriple[0] ); ++i )
+ if ( month.startsWith( BibTeX::MonthsTriple[i], false ) ) return BibTeX::MonthsTriple[i];
+ return QString::null;
+ }
+
+}
+#include "webqueryieeexplore.moc"
diff --git a/src/webqueryieeexplore.h b/src/webqueryieeexplore.h
new file mode 100644
index 0000000..d07f504
--- /dev/null
+++ b/src/webqueryieeexplore.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYIEEEXPLORE_H
+#define KBIBTEXWEBQUERYIEEEXPLORE_H
+
+#include <qregexp.h>
+
+#include <webquery.h>
+#include <fileimporter.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryIEEExploreWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryIEEExploreWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+
+ class WebQueryIEEExplore : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryIEEExplore( QWidget* parent );
+ virtual ~WebQueryIEEExplore();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ BibTeX::FileImporter *m_bibtexImporter;
+ WebQueryIEEExploreWidget *m_widget;
+ QRegExp m_numberOfMatches;
+ QRegExp m_findArNumber;
+ QRegExp m_date;
+ KURL m_risURL;
+ QValueList<int> m_arnumList;
+ QString m_incomingData;
+ int m_numMaxHits, m_numMatches, m_hitCounter;
+
+ void fetchNext();
+ void fixDate( BibTeX::Entry *entry );
+ QString parseMonth( const QString &month );
+
+ private slots:
+ void slotData( KIO::Job *job, const QByteArray &data );
+ void slotResult( KIO::Job *job );
+ };
+}
+
+#endif
diff --git a/src/webquerymathscinet.cpp b/src/webquerymathscinet.cpp
new file mode 100644
index 0000000..ef6349a
--- /dev/null
+++ b/src/webquerymathscinet.cpp
@@ -0,0 +1,188 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "webquerymathscinet.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <qspinbox.h>
+
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+
+#include <settings.h>
+
+namespace KBibTeX
+{
+ WebQueryMathSciNetWidget::WebQueryMathSciNetWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "MathSciNet" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+ void WebQueryMathSciNetWidget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearSearchText );
+ QLabel *label = new QLabel( i18n( "Search &term:" ), this );
+ hLayout->addWidget( label );
+ lineEditQuery = new KLineEdit( this );
+ hLayout->addWidget( lineEditQuery );
+ label->setBuddy( lineEditQuery );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ hLayout->setStretchFactor( lineEditQuery, 4 );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+
+/*
+ label = new QLabel( i18n( "&Number of results:" ), this );
+ hLayout->addWidget( label );
+ spinBoxMaxHits = new QSpinBox( 1, 250, 1, this );
+ spinBoxMaxHits->setValue( 10 );
+ hLayout->addWidget( spinBoxMaxHits );
+ label->setBuddy( spinBoxMaxHits );
+*/
+
+ label = new QLabel( i18n( "<qt>Use the same synatx as for <a href=\"http://www.math.tamu.edu/~comech/tools/bibget/\">BIBGET</a>. For spaces within a search element, use \"<tt>+</tt>\".<br/>Example: <tt>a=gilkey t=invariance book 1984</tt></qt>" ), this );
+ vLayout->addWidget( label );
+
+ vLayout->addStretch( 0 );
+
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+ }
+
+ WebQueryMathSciNet::WebQueryMathSciNet( QWidget* parent ): WebQuery( parent )
+ {
+ m_widget = new WebQueryMathSciNetWidget( parent );
+ }
+
+ WebQueryMathSciNet::~WebQueryMathSciNet()
+ {
+ delete m_widget;
+ }
+
+ QString WebQueryMathSciNet::title()
+ {
+ return i18n( "MathSciNet" );
+ }
+
+ QString WebQueryMathSciNet::disclaimer()
+ {
+ return i18n( "American Mathematical Society" );
+ }
+
+ QString WebQueryMathSciNet::disclaimerURL()
+ {
+ return "http://www.ams.org/ams/copyright.html";
+ }
+
+ WebQueryWidget *WebQueryMathSciNet::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryMathSciNet::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "MathSciNet", m_widget->lineEditQuery->text() );
+
+ setNumStages( 1 );
+
+ QStringList searchTerms = QStringList::split( QRegExp( "\\s+" ), m_widget->lineEditQuery->text().stripWhiteSpace() );
+ if ( searchTerms.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ QStringList queryTerms;
+ int count = 1;
+ for ( QStringList::ConstIterator it = searchTerms.constBegin(); it != searchTerms.constEnd(); ++it )
+ {
+ const QString term=*it;
+ if ( term.startsWith( "a=" ) )
+ queryTerms << QString( "pg%1=AUCN" ).arg( count ) << QString( "s%1=%2" ).arg( count ).arg( term.mid( 2 ) );
+ else if ( term.startsWith( "t=" ) )
+ queryTerms << QString( "pg%1=TI" ).arg( count ) << QString( "s%1=%2" ).arg( count ).arg( term.mid( 2 ) );
+ else if ( term.startsWith( "k=" ) )
+ queryTerms << QString( "pg%1=ALLF" ).arg( count ) << QString( "s%1=%2" ).arg( count ).arg( term.mid( 2 ) );
+ else if ( term.startsWith( "r=" ) )
+ queryTerms << QString( "pg%1=MR" ).arg( count ) << QString( "s%1=%2" ).arg( count ).arg( term.mid( 2 ) );
+ else if ( term.startsWith( "j=" ) )
+ queryTerms << QString( "pg%1=JOUR" ).arg( count ) << QString( "s%1=%2" ).arg( count ).arg( term.mid( 2 ) );
+ else
+ queryTerms << QString( "pg%1=ALLF" ).arg( count ) << QString( "s%1=%2" ).arg( count ).arg( term );
+ ++count;
+ }
+
+ KURL url( QString( "http://www.ams.org/msnmain?fn=130&fmt=bibtex&l=100&extend=1&" ).append( queryTerms.join( "&" ) ) );
+ kdDebug()<<"url="<<url.prettyURL()<<endl;
+
+ BibTeX::File *bibFile = downloadBibTeXFile( url );
+ enterNextStage();
+
+ if ( bibFile != NULL && !m_aborted )
+ {
+ for ( BibTeX::File::ElementList::iterator it = bibFile->begin(); it != bibFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ emit foundEntry( entry, false );
+ }
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+
+ if ( bibFile != NULL )
+ delete bibFile;
+ }
+
+}
+#include "webquerymathscinet.moc" \ No newline at end of file
diff --git a/src/webquerymathscinet.h b/src/webquerymathscinet.h
new file mode 100644
index 0000000..9b92f7c
--- /dev/null
+++ b/src/webquerymathscinet.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYMATHSCINET_H
+#define KBIBTEXWEBQUERYMATHSCINET_H
+
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryMathSciNetWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryMathSciNetWidget( QWidget *parent, const char *name = 0 );
+
+ protected:
+ virtual void init();
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryMathSciNet : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryMathSciNet( QWidget* parent );
+ virtual ~WebQueryMathSciNet();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQueryMathSciNetWidget *m_widget;
+ };
+
+}
+
+#endif // KBIBTEXWEBQUERYMATHSCINET_H
diff --git a/src/webquerypubmed.cpp b/src/webquerypubmed.cpp
new file mode 100644
index 0000000..f3dcb82
--- /dev/null
+++ b/src/webquerypubmed.cpp
@@ -0,0 +1,535 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qwidget.h>
+#include <qdom.h>
+#include <qapplication.h>
+#include <qstringlist.h>
+#include <qbuffer.h>
+#include <qcstring.h>
+#include <qregexp.h>
+#include <qspinbox.h>
+
+#include <klineedit.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+
+#include <entryfield.h>
+#include <value.h>
+#include <settings.h>
+#include "webquerypubmed.h"
+
+namespace KBibTeX
+{
+ WebQueryPubMedWidget::WebQueryPubMedWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "PubMed" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+ WebQueryPubMed::WebQueryPubMed( QWidget *parent ) : WebQuery( parent )
+ {
+ m_widget = new WebQueryPubMedWidget( parent );
+ }
+
+ WebQueryPubMed::~WebQueryPubMed()
+ {
+ delete m_widget;
+ }
+
+ QString WebQueryPubMed::title()
+ {
+ return i18n( "NCBI (PubMed)" );
+ }
+
+ QString WebQueryPubMed::disclaimer()
+ {
+ return i18n( "NCBI's Disclaimer and Copyright" );
+ }
+
+ QString WebQueryPubMed::disclaimerURL()
+ {
+ return "http://eutils.ncbi.nlm.nih.gov/About/disclaimer.html";
+ }
+
+ WebQueryWidget *WebQueryPubMed::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryPubMed::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "PubMed", m_widget->lineEditQuery->text() );
+
+ setNumStages( 2 );
+ int numberOfResults = m_widget->spinBoxMaxHits->value();
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ searchTerm = searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+ KURL url = KURL( QString( "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=%2&retmax=%1&tool=KBibTeX&[email protected]" ).arg( numberOfResults ).arg( searchTerm ) );
+
+ QString data = downloadHTML( url );
+ if ( data != QString::null && !m_aborted )
+ {
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << data << endl;
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ QValueList<int> intList;
+ QXmlInputSource inputSource( &buffer );
+ QXmlSimpleReader reader;
+ WebQueryPubMedStructureParserQuery handler( &intList );
+ reader.setContentHandler( &handler );
+ reader.parse( &inputSource );
+ buffer.close();
+
+ QString ids;
+ QValueList<int>::iterator it = intList.begin();
+ if ( it != intList.end() )
+ {
+ ids.append( QString::number( *it ) );
+ ++it;
+ for ( ; it != intList.end(); ++it )
+ {
+ ids.append( "," );
+ ids.append( QString::number( *it ) );
+ }
+ }
+
+ url = KURL( QString( "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&id=%1&tool=KBibTeX&[email protected]" ).arg( ids ) );
+ data = downloadHTML( url );
+ if ( data != QString::null && !m_aborted )
+ {
+ buffer.open( IO_WriteOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << data << endl;
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ QDomDocument doc( "efetch'ed" );
+ doc.setContent( &buffer );
+ QDomElement docElem = doc.documentElement();
+ WebQueryPubMedResultParser resultParser;
+ connect( &resultParser, SIGNAL( foundEntry( BibTeX::Entry*, bool ) ), this, SIGNAL( foundEntry( BibTeX::Entry*, bool ) ) );
+ resultParser.parse( docElem );
+ buffer.close();
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+ }
+
+ WebQueryPubMedStructureParserQuery::WebQueryPubMedStructureParserQuery( QValueList<int> *intList ) : QXmlDefaultHandler(), m_intList( intList )
+ {
+ m_intList->clear();
+ }
+
+ WebQueryPubMedStructureParserQuery::~WebQueryPubMedStructureParserQuery( )
+ {
+ // nothing
+ }
+
+ bool WebQueryPubMedStructureParserQuery::startElement( const QString & /*namespaceURI*/, const QString & /*localName*/, const QString & /*qName*/, const QXmlAttributes & /*atts*/ )
+ {
+ concatString = QString();
+ return TRUE;
+ }
+
+ bool WebQueryPubMedStructureParserQuery::endElement( const QString & /*namespaceURI*/, const QString & /*localName*/, const QString & qName )
+ {
+ if ( qName == "Id" )
+ {
+ bool ok;
+ int id = concatString.toInt( &ok );
+ if ( ok && id > 0 && m_intList != NULL )
+ m_intList->append( id );
+ }
+
+ return TRUE;
+ }
+
+ bool WebQueryPubMedStructureParserQuery::characters( const QString & ch )
+ {
+ concatString.append( ch );
+ return TRUE;
+ }
+
+ WebQueryPubMedResultParser::WebQueryPubMedResultParser( ) : QObject()
+ {
+ // nothing
+ }
+
+ void WebQueryPubMedResultParser::parse( const QDomElement& rootElement )
+ {
+ if ( rootElement.tagName() == "PubmedArticleSet" )
+ for ( QDomNode n = rootElement.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if ( !e.isNull() && e.tagName() == "PubmedArticle" )
+ {
+ BibTeX::Entry * entry = new BibTeX::Entry( BibTeX::Entry::etMisc, "PubMed" );
+ parsePubmedArticle( e, entry );
+ emit foundEntry( entry, false );
+ }
+ }
+ }
+
+ WebQueryPubMedResultParser::~WebQueryPubMedResultParser()
+ {
+ // nothing
+ }
+
+ void WebQueryPubMedResultParser::parsePubmedArticle( const QDomElement& element, BibTeX::Entry *entry )
+ {
+ for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if ( !e.isNull() && e.tagName() == "MedlineCitation" )
+ parseMedlineCitation( e, entry );
+ }
+ }
+
+ void WebQueryPubMedResultParser::parseMedlineCitation( const QDomElement& element, BibTeX::Entry *entry )
+ {
+ for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if ( !e.isNull() )
+ {
+ if ( e.tagName() == "PMID" )
+ {
+ entry->setId( QString( "PubMed_%1" ).arg( e.text() ) );
+
+ /** add url to pubmed website */
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftURL );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftURL );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( QString( "http://www.ncbi.nlm.nih.gov/pubmed/" ).append( e.text() ) ) );
+ }
+ else if ( e.tagName() == "Article" )
+ parseArticle( e, entry );
+ else if ( e.tagName() == "MedlineJournalInfo" )
+ {
+ for ( QDomNode n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
+ {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() == "MedlineTA" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftJournal );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftJournal );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e2.text() ) );
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ void WebQueryPubMedResultParser::parseArticle( const QDomElement& element, BibTeX::Entry *entry )
+ {
+ for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+
+ if ( e.tagName() == "Journal" )
+ {
+ parseJournal( e, entry );
+ entry->setEntryType( BibTeX::Entry::etArticle );
+ }
+ else if ( e.tagName() == "ArticleTitle" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftTitle );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftTitle );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e.text() ) );
+ }
+ else if ( e.tagName() == "Pagination" )
+ {
+ QDomElement medlinePgn = e.firstChild().toElement(); // may fail?
+ if ( !medlinePgn.text().isEmpty() )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftPages );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftPages );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( medlinePgn.text() ) );
+ }
+ }
+ else if ( e.tagName() == "Abstract" )
+ {
+ QDomElement abstractText = e.firstChild().toElement();
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftAbstract );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftAbstract );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( abstractText.text() ) );
+ }
+ else if ( e.tagName() == "Affiliation" )
+ {
+ BibTeX::EntryField * field = entry->getField( "affiliation" );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( "affiliation" );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e.text() ) );
+ }
+ else if ( e.tagName() == "AuthorList" )
+ parseAuthorList( e, entry );
+ }
+ }
+
+ void WebQueryPubMedResultParser::parseJournal( const QDomElement& element, BibTeX::Entry *entry )
+ {
+ for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+
+ if ( e.tagName() == "ISSN" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftISSN );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftISSN );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e.text() ) );
+ }
+ else if ( e.tagName() == "JournalIssue" )
+ parseJournalIssue( e, entry );
+ else if ( e.tagName() == "Title" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftJournal );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftJournal );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e.text() ) );
+ }
+ }
+ }
+
+ void WebQueryPubMedResultParser::parseJournalIssue( const QDomElement& element, BibTeX::Entry *entry )
+ {
+ for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+
+ if ( e.tagName() == "Volume" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftVolume );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftVolume );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e.text() ) );
+ }
+ else if ( e.tagName() == "Issue" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftNumber );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftNumber );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e.text() ) );
+ }
+ else if ( e.tagName() == "PubDate" )
+ parsePubDate( e, entry );
+ }
+ }
+
+ void WebQueryPubMedResultParser::parsePubDate( const QDomElement& element, BibTeX::Entry *entry )
+ {
+ for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+
+ if ( e.tagName() == "Year" )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftYear );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftYear );
+ entry->addField( field );
+ }
+ field->setValue( new BibTeX::Value( e.text() ) );
+ }
+ else if ( e.tagName() == "Month" )
+ {
+ QString month = e.text().lower();
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftMonth );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftMonth );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::MacroKey( month ) );
+ field->setValue( value );
+ }
+ else if ( e.tagName() == "MedlineDate" )
+ {
+ QStringList frags = QStringList::split( QRegExp( "\\s+" ), e.text() );
+ for ( QStringList::Iterator it = frags.begin(); it != frags.end(); ++it )
+ {
+ bool ok;
+ int num = ( *it ).toInt( &ok );
+ if ( ok && num > 1000 && num < 3000 )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftYear );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftYear );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::MacroKey( QString::number( num ) ) );
+ field->setValue( value );
+ }
+ else if ( !ok && ( *it ).length() == 3 )
+ {
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftMonth );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftMonth );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ value->items.append( new BibTeX::MacroKey(( *it ).lower() ) );
+ field->setValue( value );
+ }
+ }
+ }
+ }
+ }
+
+ void WebQueryPubMedResultParser::parseAuthorList( const QDomElement& element, BibTeX::Entry *entry )
+ {
+ if ( element.attribute( "CompleteYN", "Y" ) == "Y" )
+ {
+ QStringList authorList;
+ for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if ( e.tagName() == "Author" && e.attribute( "ValidYN", "Y" ) == "Y" )
+ {
+ QString lastName = QString::null, firstName = QString::null;
+ for ( QDomNode n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
+ {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() == "LastName" )
+ lastName = e2.text();
+ else if ( e2.tagName() == "CollectiveName" )
+ lastName = e2.text();
+ else if ( e2.tagName() == "FirstName" || e2.tagName() == "ForeName" )
+ firstName = e2.text();
+ }
+ QString name = lastName;
+ if ( !firstName.isNull() && !firstName.isEmpty() )
+ {
+ if ( name.isNull() ) name = "UNSET";
+ name.prepend( "|" ).prepend( firstName );
+ }
+ if ( !name.isNull() )
+ authorList.append( name );
+ }
+ }
+
+ BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftAuthor );
+ if ( field == NULL )
+ {
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftAuthor );
+ entry->addField( field );
+ }
+ BibTeX::Value *value = new BibTeX::Value();
+ Settings *settings = Settings::self();
+ BibTeX::PersonContainer *personContainer = new BibTeX::PersonContainer( settings->editing_FirstNameFirst );
+ value->items.append( personContainer );
+ for ( QStringList::Iterator sli = authorList.begin(); sli != authorList.end(); ++sli )
+ {
+ QStringList nameParts = QStringList::split( '|', *sli );
+ QString firstName = nameParts.count() > 1 ? nameParts[0] : "";
+ QString lastName = nameParts[nameParts.count() - 1];
+ personContainer->persons.append( new BibTeX::Person( firstName, lastName, settings->editing_FirstNameFirst ) );
+ }
+ field->setValue( value );
+ }
+ }
+
+}
+#include "webquerypubmed.moc"
diff --git a/src/webquerypubmed.h b/src/webquerypubmed.h
new file mode 100644
index 0000000..86d0326
--- /dev/null
+++ b/src/webquerypubmed.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef KBIBTEXWEBQUERYPUBMED_H
+#define KBIBTEXWEBQUERYPUBMED_H
+
+#include <qwidget.h>
+#include <qxml.h>
+#include <qvaluelist.h>
+
+#include <webquery.h>
+
+class QStringList;
+class QDomElement;
+class QDate;
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryPubMedWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryPubMedWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ class WebQueryPubMedStructureParserQuery : public QXmlDefaultHandler
+ {
+ public:
+ WebQueryPubMedStructureParserQuery( QValueList<int> *intList );
+ ~WebQueryPubMedStructureParserQuery( );
+
+ bool startElement( const QString&, const QString&, const QString&, const QXmlAttributes& );
+ bool endElement( const QString&, const QString&, const QString& );
+ bool characters( const QString & ch );
+
+ private:
+ QValueList<int> *m_intList;
+ QString concatString;
+ };
+
+ class WebQueryPubMedResultParser: public QObject
+ {
+ Q_OBJECT
+ public:
+ WebQueryPubMedResultParser();
+ ~WebQueryPubMedResultParser();
+
+ void parse( const QDomElement& rootElement );
+
+ signals:
+ void foundEntry( BibTeX::Entry*, bool );
+
+ private:
+ void parsePubmedArticle( const QDomElement& element, BibTeX::Entry *entry );
+ void parseMedlineCitation( const QDomElement& element, BibTeX::Entry *entry );
+ void parseArticle( const QDomElement& element, BibTeX::Entry *entry );
+ void parseJournal( const QDomElement& element, BibTeX::Entry *entry );
+ void parseJournalIssue( const QDomElement& element, BibTeX::Entry *entry );
+ void parsePubDate( const QDomElement& element, BibTeX::Entry *entry );
+ void parseAuthorList( const QDomElement& element, BibTeX::Entry *entry );
+ };
+
+ class WebQueryPubMed : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryPubMed( QWidget *parent );
+ virtual ~WebQueryPubMed();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQueryPubMedWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/webquerysciencedirect.cpp b/src/webquerysciencedirect.cpp
new file mode 100644
index 0000000..152d05b
--- /dev/null
+++ b/src/webquerysciencedirect.cpp
@@ -0,0 +1,425 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qbuffer.h>
+#include <qfile.h>
+
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <kiconloader.h>
+#include <kio/jobclasses.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+
+#include <settings.h>
+#include <fileimporterris.h>
+#include "webquerysciencedirect.h"
+
+namespace KBibTeX
+{
+ WebQueryScienceDirectWidget::WebQueryScienceDirectWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ QString allValues;
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "ScienceDirect_title" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ allValues += value;
+ value = settings->getWebQueryDefault( "ScienceDirect_author" );
+ value = value == QString::null ? "" : value;
+ lineEditAuthor->setText( value );
+ allValues += value;
+ value = settings->getWebQueryDefault( "ScienceDirect_journal" );
+ value = value == QString::null ? "" : value;
+ lineEditJournal->setText( value );
+ allValues += value;
+ value = settings->getWebQueryDefault( "ScienceDirect_volume" );
+ value = value == QString::null ? "" : value;
+ lineEditVolume->setText( value );
+ allValues += value;
+ value = settings->getWebQueryDefault( "ScienceDirect_issue" );
+ value = value == QString::null ? "" : value;
+ lineEditIssue->setText( value );
+ allValues += value;
+ value = settings->getWebQueryDefault( "ScienceDirect_page" );
+ value = value == QString::null ? "" : value;
+ lineEditPage->setText( value );
+ allValues += value;
+
+ slotTextChanged( allValues, true );
+ }
+
+ void WebQueryScienceDirectWidget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearSearchText );
+ QLabel *label = new QLabel( i18n( "Title, abstract, keywords:" ), this );
+ hLayout->addWidget( label );
+ lineEditQuery = new KLineEdit( this );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+ hLayout->addWidget( lineEditQuery );
+ label->setBuddy( lineEditQuery );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChangedSD( ) ) );
+ hLayout->setStretchFactor( lineEditQuery, 7 );
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+
+
+ hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ KPushButton *clearAuthor = new KPushButton( this );
+ clearAuthor->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearAuthor );
+ label = new QLabel( i18n( "Author:" ), this );
+ hLayout->addWidget( label );
+ lineEditAuthor = new KLineEdit( this );
+ completionQuery = lineEditAuthor->completionObject();
+ hLayout->addWidget( lineEditAuthor );
+ label->setBuddy( lineEditAuthor );
+ connect( clearAuthor, SIGNAL( clicked() ), lineEditAuthor, SLOT( clear() ) );
+ connect( lineEditAuthor, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChangedSD( ) ) );
+ hLayout->setStretchFactor( lineEditAuthor, 7 );
+ connect( lineEditAuthor, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditAuthor, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+
+ KPushButton *clearJournal = new KPushButton( this );
+ clearJournal->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearJournal );
+ label = new QLabel( i18n( "Journal/book title:" ), this );
+ hLayout->addWidget( label );
+ lineEditJournal = new KLineEdit( this );
+ completionQuery = lineEditJournal->completionObject();
+ hLayout->addWidget( lineEditJournal );
+ label->setBuddy( lineEditJournal );
+ connect( clearJournal, SIGNAL( clicked() ), lineEditJournal, SLOT( clear() ) );
+ connect( lineEditJournal, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChangedSD( ) ) );
+ hLayout->setStretchFactor( lineEditJournal, 4 );
+ connect( lineEditJournal, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditJournal, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+
+ hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ label = new QLabel( i18n( "Volume:" ), this );
+ hLayout->addWidget( label );
+ lineEditVolume = new KLineEdit( this );
+ hLayout->addWidget( lineEditVolume );
+ hLayout->setStretchFactor( lineEditVolume, 1 );
+ label->setBuddy( lineEditVolume );
+ connect( lineEditVolume, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+
+ label = new QLabel( i18n( "Issue:" ), this );
+ hLayout->addWidget( label );
+ lineEditIssue = new KLineEdit( this );
+ hLayout->addWidget( lineEditIssue );
+ label->setBuddy( lineEditIssue );
+ hLayout->setStretchFactor( lineEditIssue, 1 );
+ connect( lineEditIssue, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+
+ label = new QLabel( i18n( "Page:" ), this );
+ hLayout->addWidget( label );
+ lineEditPage = new KLineEdit( this );
+ hLayout->addWidget( lineEditPage );
+ hLayout->setStretchFactor( lineEditPage, 1 );
+ label->setBuddy( lineEditPage );
+ connect( lineEditPage, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+
+ label = new QLabel( i18n( "&Number of results:" ), this );
+ hLayout->addWidget( label );
+ spinBoxMaxHits = new QSpinBox( 1, 100, 1, this );
+ spinBoxMaxHits->setValue( 10 );
+ hLayout->addWidget( spinBoxMaxHits );
+ hLayout->setStretchFactor( spinBoxMaxHits, 1 );
+ label->setBuddy( spinBoxMaxHits );
+ hLayout->addStretch( 5 );
+ }
+
+ void WebQueryScienceDirectWidget::slotTextChangedSD()
+ {
+ QString text = lineEditQuery->text().stripWhiteSpace().append( lineEditAuthor->text().stripWhiteSpace() ).append( lineEditJournal->text().stripWhiteSpace() ).replace( '$', "" );
+ emit enableSearch( !text.isEmpty() );
+ }
+
+ WebQueryScienceDirect::WebQueryScienceDirect( QWidget* parent ): WebQuery( parent )
+ {
+ m_importer = new BibTeX::FileImporterBibTeX( FALSE );
+ m_importer->setIgnoreComments( TRUE );
+ m_widget = new WebQueryScienceDirectWidget( parent );
+ }
+
+ WebQueryScienceDirect::~WebQueryScienceDirect()
+ {
+ delete m_widget;
+ delete m_importer;
+ }
+
+ QString WebQueryScienceDirect::title()
+ {
+ return i18n( "ScienceDirect" );
+ }
+
+ QString WebQueryScienceDirect::disclaimer()
+ {
+ return i18n( "About ScienceDirect" );
+ }
+
+ QString WebQueryScienceDirect::disclaimerURL()
+ {
+ return "http://info.sciencedirect.com/";
+ }
+
+ WebQueryWidget *WebQueryScienceDirect::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryScienceDirect::query()
+ {
+ WebQuery::query();
+
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "ScienceDirect_author", m_widget->lineEditAuthor->text() );
+ settings->setWebQueryDefault( "ScienceDirect_journal", m_widget->lineEditJournal->text() );
+ settings->setWebQueryDefault( "ScienceDirect_volume", m_widget->lineEditVolume->text() );
+ settings->setWebQueryDefault( "ScienceDirect_issue", m_widget->lineEditIssue->text() );
+ settings->setWebQueryDefault( "ScienceDirect_page", m_widget->lineEditPage->text() );
+
+ QString tak = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" ).replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+ QString author = m_widget->lineEditAuthor->text().stripWhiteSpace().replace( '$', "" ).replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+ QString journal = m_widget->lineEditJournal->text().stripWhiteSpace().replace( '$', "" ).replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+ QString volume = m_widget->lineEditVolume->text().stripWhiteSpace().replace( '$', "" ).replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+ QString issue = m_widget->lineEditIssue->text().stripWhiteSpace().replace( '$', "" ).replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+ QString page = m_widget->lineEditPage->text().stripWhiteSpace().replace( '$', "" ).replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" );
+
+ if ( tak.isEmpty() && author.isEmpty() && journal.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ setNumStages( 4 );
+
+ if ( !getStartPage() ) return;
+
+ if ( !getResultPage( tak, author, journal, volume, issue, page ) ) return;
+
+ if ( !getArticleListPage() ) return;
+
+ if ( !getRISFile() ) return;
+ }
+
+ bool WebQueryScienceDirect::getStartPage()
+ {
+ QString startPage = downloadHTML( KURL( "http://www.sciencedirect.com/" ) );
+ if ( m_aborted )
+ {
+ setEndSearch( WebQuery::statusAborted );
+ return false;
+ }
+ else if ( startPage == QString::null )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+
+ int pos = startPage.find( "<input type=\"hidden\" name=\"_acct\" value=\"" );
+ if ( pos < 0 )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ m_account = startPage.mid( pos + 41, startPage.find( "\"", pos + 43 ) - pos - 41 );
+ pos = startPage.find( "<input type=\"hidden\" name=\"md5\" value=\"" );
+ if ( pos < 0 )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ m_md5 = startPage.mid( pos + 39, startPage.find( "\"", pos + 41 ) - pos - 39 );
+
+ return true;
+ }
+
+ bool WebQueryScienceDirect::getResultPage( const QString &tak, const QString &author, const QString &journal, const QString &volume, const QString &issue, const QString &page )
+ {
+ KURL url = KURL( QString( "http://www.sciencedirect.com/science?_ob=QuickSearchURL&_method=submitForm&qs_tak=" ).append( tak ).append( "&qs_author=" ).append( author ).append( "&qs_title=" ).append( journal ).append( "&qs_vol=" ).append( volume ).append( "&qs_issue=" ).append( issue ).append( "&qs_pages=" ).append( page ).append( "&_acct=" ).append( m_account ).append( "&md5=" ).append( m_md5 ).append( "&x=0&y=0&=Submit" ) );
+ QString resultPage = downloadHTML( url );
+ if ( m_aborted )
+ {
+ setEndSearch( WebQuery::statusAborted );
+ return false;
+ }
+ else if ( resultPage == QString::null )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+
+ int pos = resultPage.find( "<input type=\"hidden\" name=\"_ArticleListID\" value=" );
+ if ( pos < 0 )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ m_articleListID = resultPage.mid( pos + 49, resultPage.find( ">", pos + 50 ) - pos - 49 );
+ pos = resultPage.find( "<input type=\"hidden\" name=\"md5\" value=\"" );
+ pos = resultPage.find( "<input type=\"hidden\" name=\"md5\" value=\"" , pos + 2 );
+ if ( pos < 0 )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ m_md5 = resultPage.mid( pos + 39, 32 );
+ pos = resultPage.find( "_userid=" );
+ if ( pos < 0 )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ m_userid = resultPage.mid( pos + 8, resultPage.find( "&", pos + 9 ) - pos - 8 );
+
+ return true;
+ }
+
+ bool WebQueryScienceDirect::getArticleListPage()
+ {
+ KURL url = KURL( QString( "http://www.sciencedirect.com/science?_ob=ArticleListURL&_method=tag&refSource=search&_st=13&_chunk=0&NEXT_LIST=1&view=c&md5=%1&_ArticleListID=%2&sisr_search=&sisrterm=&export=Export+Citations&count=%3" ).arg( m_md5 ).arg( m_articleListID ).arg( m_widget->spinBoxMaxHits->value() ) );
+ QString articleListPage = downloadHTML( url );
+ if ( m_aborted )
+ {
+ setEndSearch( WebQuery::statusAborted );
+ return false;
+ }
+ else if ( articleListPage == QString::null )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ else if ( articleListPage.find( "subscription does not entitle" ) >= 0 )
+ {
+ qWarning( "Your subscription does not entitle you to access the download feature of ScienceDirect" );
+ setEndSearch( WebQuery::statusInsufficientPermissions );
+ return false;
+ }
+
+ int pos = articleListPage.find( "<input type=hidden name=md5 value=" );
+ if ( pos < 0 )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ m_md5 = articleListPage.mid( pos + 34, articleListPage.find( ">", pos + 36 ) - pos - 34 );
+ pos = articleListPage.find( "<input type=hidden name=_ArticleListID value=" );
+ if ( pos < 0 )
+ {
+ setEndSearch( WebQuery::statusError );
+ return false;
+ }
+ m_articleListID = articleListPage.mid( pos + 45, articleListPage.find( ">", pos + 46 ) - pos - 45 );
+
+ return true;
+ }
+
+ bool WebQueryScienceDirect::getRISFile()
+ {
+ m_incomingData = "";
+ QString data = QString( "_ob=DownloadURL&_method=finish&_acct=%1&_userid=%2&_ArticleListID=%3&count=10&md5=%4&JAVASCRIPT_ON=&format=cite&citation-type=RIS&RETURN_URL=http://www.sciencedirect.com/science/home" ).arg( m_account ).arg( m_userid ).arg( m_articleListID ).arg( m_md5 );
+ KURL url = KURL( "http://www.sciencedirect.com/science" );
+ KIO::TransferJob *job = KIO::http_post( url, data.utf8(), false );
+ job->addMetaData( "content-type", "Content-Type: application/x-www-form-urlencoded" );
+ connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotResult( KIO::Job * ) ) );
+
+ return true;
+ }
+
+ void WebQueryScienceDirect::slotData( KIO::Job *, const QByteArray &data )
+ {
+ if ( data.size() > 0 )
+ m_incomingData.append( QCString( data, data.size() + 1 ) );
+ }
+
+ void WebQueryScienceDirect::slotResult( KIO::Job *job )
+ {
+ if ( job->error() )
+ {
+ setEndSearch( WebQuery::statusError );
+ return;
+ }
+
+ BibTeX::FileImporterRIS importer;
+ QBuffer buffer;
+
+ buffer.open( IO_WriteOnly );
+ QTextStream ts( &buffer );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << m_incomingData << endl;
+ buffer.close();
+
+ buffer.open( IO_ReadOnly );
+ BibTeX::File *tmpBibFile = importer.load( &buffer );
+ buffer.close();
+
+ if ( tmpBibFile != NULL )
+ {
+ int count = m_widget->spinBoxMaxHits->value();
+ for ( BibTeX::File::ElementList::iterator it = tmpBibFile->begin(); count > 0 && it != tmpBibFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ {
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ --count;
+ }
+ }
+
+ delete tmpBibFile;
+ }
+ else
+ {
+ setEndSearch( WebQuery::statusError );
+ return;
+ }
+
+ setEndSearch( WebQuery::statusSuccess );
+ }
+}
+#include "webquerysciencedirect.moc"
diff --git a/src/webquerysciencedirect.h b/src/webquerysciencedirect.h
new file mode 100644
index 0000000..b43a221
--- /dev/null
+++ b/src/webquerysciencedirect.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYSCIENCEDIRECT_H
+#define KBIBTEXWEBQUERYSCIENCEDIRECT_H
+
+#include <fileimporterbibtex.h>
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryScienceDirectWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryScienceDirectWidget( QWidget *parent, const char *name = 0 );
+
+ KLineEdit *lineEditAuthor;
+ KLineEdit *lineEditJournal;
+ KLineEdit *lineEditVolume;
+ KLineEdit *lineEditIssue;
+ KLineEdit *lineEditPage;
+
+ protected:
+ virtual void init();
+
+ private slots:
+ void slotTextChangedSD();
+ };
+
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryScienceDirect : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryScienceDirect( QWidget* parent );
+ virtual ~WebQueryScienceDirect();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ BibTeX::FileImporterBibTeX *m_importer;
+ WebQueryScienceDirectWidget *m_widget;
+ QString m_incomingData;
+ QString m_md5, m_userid, m_articleListID, m_account;
+
+ bool getStartPage();
+ bool getResultPage( const QString &tak, const QString &author, const QString &journal, const QString &volume, const QString &issue, const QString &page );
+ bool getArticleListPage();
+ bool getRISFile();
+
+ private slots:
+ void slotData( KIO::Job *job, const QByteArray &data );
+ void slotResult( KIO::Job *job );
+ };
+
+}
+
+#endif
diff --git a/src/webqueryspireshep.cpp b/src/webqueryspireshep.cpp
new file mode 100644
index 0000000..61d9c48
--- /dev/null
+++ b/src/webqueryspireshep.cpp
@@ -0,0 +1,248 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+
+#include <kiconloader.h>
+#include <kcombobox.h>
+#include <kpushbutton.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <kio/netaccess.h>
+#include <kurl.h>
+
+#include <settings.h>
+#include <fileimporterbibtex.h>
+#include "webqueryspireshep.h"
+
+namespace KBibTeX
+{
+
+ const QString WebQuerySpiresHep::mirrorNames[] = {i18n( "DESY (Germany)" ), i18n( "FNAL (U.S.A.)" ), i18n( "IHEP (Russia)" ), i18n( "Durham U (U.K.)" ), i18n( "SLAC (U.S.A.)" ), i18n( "YITP (Japan)" ), i18n( "LIPI (Indonesia)" )};
+ const QString WebQuerySpiresHep::mirrorURLs[] = {"http://www-library.desy.de/cgi-bin/spiface", "http://www-spires.fnal.gov/spires", "http://usparc.ihep.su/spires", "http://www-spires.dur.ac.uk/spires", "http://www.slac.stanford.edu/spires", "http://www.yukawa.kyoto-u.ac.jp/spires", "http://www.spires.lipi.go.id/spires"};
+
+ WebQuerySpiresHepWidget::WebQuerySpiresHepWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "SpiresHep_query" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ value = settings->getWebQueryDefault( "SpiresHep_mirror" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxMirror->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "SpiresHep_type" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxType->setCurrentItem( value.toInt() );
+ }
+
+ void WebQuerySpiresHepWidget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ comboBoxMirror = new KComboBox( false, this );
+ hLayout->addWidget( comboBoxMirror );
+ hLayout->setStretchFactor( comboBoxMirror, 7 );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ for ( unsigned int i = 0; i < sizeof( WebQuerySpiresHep::mirrorNames ) / sizeof( WebQuerySpiresHep::mirrorNames[0] ); ++i )
+ comboBoxMirror->insertItem( WebQuerySpiresHep::mirrorNames[i] );
+ comboBoxMirror->setCurrentItem( 0 );
+
+ QLabel *label = new QLabel( i18n( "Type:" ), this );
+ hLayout->addWidget( label );
+ hLayout->setStretchFactor( label, 1 );
+ comboBoxType = new KComboBox( false, this );
+ label->setBuddy( comboBoxType );
+ hLayout->addWidget( comboBoxType );
+ hLayout->setStretchFactor( comboBoxType, 5 );
+ comboBoxType->insertItem( i18n( "raw query" ) );
+ comboBoxType->insertItem( i18n( "author" ) );
+ comboBoxType->insertItem( i18n( "title" ) );
+ comboBoxType->insertItem( i18n( "journal" ) );
+ comboBoxType->insertItem( i18n( "EPrint number" ) );
+ comboBoxType->insertItem( i18n( "report number" ) );
+ comboBoxType->insertItem( i18n( "keywords" ) );
+ comboBoxType->setCurrentItem( 0 );
+
+ hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ hLayout->addWidget( clearSearchText );
+ label = new QLabel( i18n( "Search &term:" ), this );
+ hLayout->addWidget( label );
+ lineEditQuery = new KLineEdit( this );
+ hLayout->addWidget( lineEditQuery );
+ label->setBuddy( lineEditQuery );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ hLayout->setStretchFactor( lineEditQuery, 4 );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+
+ m_checkBoxFetchAbstracts = new QCheckBox( i18n( "Include abstracts from arxiv.org if available" ), this );
+ vLayout->addWidget( m_checkBoxFetchAbstracts );
+
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+
+ vLayout->addStretch( 1 );
+ }
+
+ WebQuerySpiresHep::WebQuerySpiresHep( QWidget* parent ): WebQuery( parent )
+ {
+ m_widget = new WebQuerySpiresHepWidget( parent );
+ }
+
+ WebQuerySpiresHep::~WebQuerySpiresHep()
+ {
+ delete m_widget;
+ }
+
+ QString WebQuerySpiresHep::title()
+ {
+ return i18n( "SPIRES-HEP" );
+ }
+
+ QString WebQuerySpiresHep::disclaimer()
+ {
+ return i18n( "SPIRES-HEP Search" );
+ }
+
+ QString WebQuerySpiresHep::disclaimerURL()
+ {
+ return "http://www.slac.stanford.edu/spires/";
+ }
+
+ WebQueryWidget *WebQuerySpiresHep::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQuerySpiresHep::query()
+ {
+ const int maxEntries = 25;
+ bool doFetchAbstracts = m_widget->m_checkBoxFetchAbstracts->isChecked();
+ int mirrorIdx = m_widget->comboBoxMirror->currentItem();
+
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "SpiresHep_query", m_widget->lineEditQuery->text() );
+ settings->setWebQueryDefault( "SpiresHep_mirror", QString::number( m_widget->comboBoxMirror->currentItem() ) );
+ settings->setWebQueryDefault( "SpiresHep_type", QString::number( m_widget->comboBoxType->currentItem() ) );
+
+ setNumStages( 1 + doFetchAbstracts ? maxEntries : 0 );
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ switch ( m_widget->comboBoxType->currentItem() )
+ {
+ case 1: searchTerm = searchTerm.prepend( "fin a " ); break;
+ case 2: searchTerm = searchTerm.prepend( "fin t " ); break;
+ case 3: searchTerm = searchTerm.prepend( "fin j " ); break;
+ case 4: searchTerm = searchTerm.prepend( "fin eprint " ); break;
+ case 5: searchTerm = searchTerm.prepend( "fin r" ); break;
+ case 6: searchTerm = searchTerm.prepend( "fin k" ); break;
+ default: ;// nothing
+ }
+
+ KURL url = KURL( QString( "%1/find/hep/www?rawcmd=%2&FORMAT=WWWBRIEFBIBTEX&SEQUENCE=" ).arg( mirrorURLs[mirrorIdx] ).arg( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ) );
+ qDebug( "url=%s", url.prettyURL().latin1() );
+
+ BibTeX::File *tmpBibFile = downloadBibTeXFile( url );
+ if ( tmpBibFile != NULL && !m_aborted )
+ {
+ int count = 0;
+ for ( BibTeX::File::ElementList::iterator it = tmpBibFile->begin(); count < maxEntries && it != tmpBibFile->end(); ++it, ++count )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( doFetchAbstracts )
+ {
+ fetchArxivAbstract( entry );
+ enterNextStage();
+ }
+ if ( entry != NULL )
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ }
+
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+
+ if ( tmpBibFile != NULL )
+ delete tmpBibFile;
+ }
+
+ void WebQuerySpiresHep::fetchArxivAbstract( BibTeX::Entry *entry )
+ {
+ BibTeX::EntryField *field = NULL;
+ BibTeX::Value *value = NULL;
+ QString eprint = (( field = entry->getField( "eprint" ) ) ) && (( value = field->value() ) ) ? value->text() : QString::null;
+ QString archivePrefix = (( field = entry->getField( "archivePrefix" ) ) ) && (( value = field->value() ) ) ? value->text() : QString::null;
+
+ if ( archivePrefix == "arXiv" && !eprint.isNull() )
+ {
+ KURL absURL( QString( "http://arxiv.org/abs/" ).append( eprint ) );
+ QString abstract = download( absURL );
+ int p = abstract.find( "Abstract:</span>" );
+ if ( p > -1 )
+ {
+ int p2 = abstract.find( "</", p + 14 );
+ abstract = abstract.mid( p + 16, p2 - p - 16 ).simplifyWhiteSpace();
+ BibTeX::EntryField * field = new BibTeX::EntryField( BibTeX::EntryField::ftAbstract );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( abstract ) );
+
+ field = new BibTeX::EntryField( "pdf" );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( QString( "http://arxiv.org/pdf/" ).append( eprint ) ) );
+
+ field = new BibTeX::EntryField( BibTeX::EntryField::ftURL );
+ entry->addField( field );
+ field->setValue( new BibTeX::Value( QString( "http://arxiv.org/abs/" ).append( eprint ) ) );
+ }
+ }
+ }
+}
+#include "webqueryspireshep.moc"
diff --git a/src/webqueryspireshep.h b/src/webqueryspireshep.h
new file mode 100644
index 0000000..968a20e
--- /dev/null
+++ b/src/webqueryspireshep.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYSPIRESHEP_H
+#define KBIBTEXWEBQUERYSPIRESHEP_H
+
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQuerySpiresHepWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQuerySpiresHepWidget( QWidget *parent, const char *name = 0 );
+
+ KComboBox *comboBoxMirror;
+ KComboBox *comboBoxType;
+ QCheckBox *m_checkBoxFetchAbstracts;
+
+ protected:
+ virtual void init();
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQuerySpiresHep : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQuerySpiresHep( QWidget* parent );
+ virtual ~WebQuerySpiresHep();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ static const QString mirrorNames[];
+ static const QString mirrorURLs[];
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQuerySpiresHepWidget *m_widget;
+
+ void fetchArxivAbstract( BibTeX::Entry *entry );
+ };
+
+}
+
+#endif
diff --git a/src/webqueryz3950.cpp b/src/webqueryz3950.cpp
new file mode 100644
index 0000000..1b62129
--- /dev/null
+++ b/src/webqueryz3950.cpp
@@ -0,0 +1,397 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * based on code from or inspired by *
+ * - Tellico by Robby Stephenson *
+ * - kbib by Thach Nguyen *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ * *
+ * This code is based on code from Tellico 1.2.10 *
+ * by Robby Stephenson <[email protected]> *
+ * Tellico is released under the GNU GPL 2, too. *
+ * http://www.periapsis.org/tellico/ *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qfile.h>
+#include <qapplication.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kurl.h>
+
+#include <fileimporterbibutils.h>
+#include <settings.h>
+#include "webqueryz3950.h"
+
+namespace KBibTeX
+{
+ const QString WebQueryZ3950Widget::attributesI18N[] = { i18n( "any" ), i18n( "title" ), i18n( "author" ), i18n( "publisher" )};
+
+ WebQueryZ3950Widget::WebQueryZ3950Widget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name ), lineEditQuery2( NULL )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "Z3950_server" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxServers->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "Z3950_query1" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ value = settings->getWebQueryDefault( "Z3950_attr1" );
+ value = value == QString::null ? "1" : value;
+ comboBoxInAttribute->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "Z3950_query2" );
+ lineEditQuery2->setText( value == QString::null ? "" : value );
+ value = settings->getWebQueryDefault( "Z3950_attr2" );
+ value = value == QString::null ? "1" : value;
+ comboBoxInAttribute2->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "Z3950_booleanOp" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxBooleanOp->setCurrentItem( value.toInt() );
+ }
+
+ void WebQueryZ3950Widget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ QLabel *label = new QLabel( i18n( "Server:" ), this );
+ hLayout->setStretchFactor( label, 1 );
+ hLayout->addWidget( label );
+ comboBoxServers = new KComboBox( false, this );
+ hLayout->addWidget( comboBoxServers );
+ hLayout->setStretchFactor( comboBoxServers, 7 );
+ label->setBuddy( comboBoxServers );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ label = new QLabel( i18n( "&Number of results:" ), this );
+ hLayout->addWidget( label );
+ hLayout->setStretchFactor( label, 1 );
+ spinBoxMaxHits = new QSpinBox( 1, 50, 1, this );
+ spinBoxMaxHits->setValue( 10 );
+ hLayout->addWidget( spinBoxMaxHits );
+ hLayout->setStretchFactor( spinBoxMaxHits, 3 );
+ label->setBuddy( spinBoxMaxHits );
+
+ QGridLayout *layout = new QGridLayout( vLayout, 2, 6, KDialog::spacingHint() );
+
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ layout->addWidget( clearSearchText, 0, 1 );
+ label = new QLabel( i18n( "Search term 1:" ), this );
+ layout->addWidget( label, 0, 2 );
+ lineEditQuery = new KLineEdit( this );
+ layout->addWidget( lineEditQuery, 0, 3 );
+ label->setBuddy( lineEditQuery );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+ label = new QLabel( i18n( "Search in:" ), this );
+ layout->addWidget( label, 0, 4 );
+ comboBoxInAttribute = new KComboBox( false, this );
+ layout->addWidget( comboBoxInAttribute, 0, 5 );
+ label->setBuddy( comboBoxInAttribute );
+
+ comboBoxBooleanOp = new KComboBox( false, this );
+ layout->addWidget( comboBoxBooleanOp, 1, 0 );
+
+ clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ layout->addWidget( clearSearchText, 1, 1 );
+ label = new QLabel( i18n( "Search term 2:" ), this );
+ layout->addWidget( label, 1, 2 );
+ lineEditQuery2 = new KLineEdit( this );
+ layout->addWidget( lineEditQuery2, 1, 3 );
+ label->setBuddy( lineEditQuery2 );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery2, SLOT( clear() ) );
+ completionQuery = lineEditQuery->completionObject();
+ connect( lineEditQuery2, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery2, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+ label = new QLabel( i18n( "Search in:" ), this );
+ layout->addWidget( label, 1, 4 );
+ comboBoxInAttribute2 = new KComboBox( false, this );
+ layout->addWidget( comboBoxInAttribute2, 1, 5 );
+ label->setBuddy( comboBoxInAttribute2 );
+
+#ifdef HAVE_YAZ
+ Settings *settings = Settings::self();
+ for ( QMap<QString, Settings::Z3950Server>::Iterator it = settings->z3950_ServerList.begin(); it != settings->z3950_ServerList.end(); ++it )
+ comboBoxServers->insertItem( it.data().name );
+#endif // HAVE_YAZ
+ for ( unsigned int i = 0; i < sizeof( attributesI18N ) / sizeof( attributesI18N[0] ); ++i )
+ {
+ comboBoxInAttribute->insertItem( attributesI18N[i] );
+ comboBoxInAttribute2->insertItem( attributesI18N[i] );
+ }
+ comboBoxBooleanOp->insertItem( i18n( "and" ) );
+ comboBoxBooleanOp->insertItem( i18n( "or" ) );
+ }
+
+ WebQueryZ3950::WebQueryZ3950( QWidget* parent ) : WebQuery( parent )
+#ifdef HAVE_YAZ
+ , m_marc21transformer( NULL ), m_unimarctransformer( NULL ), m_modsImporter( NULL ), m_conn( NULL )
+#endif // HAVE_YAZ
+ {
+ m_widget = new WebQueryZ3950Widget( parent );
+ }
+
+ WebQueryZ3950::~WebQueryZ3950()
+ {
+#ifdef HAVE_YAZ
+ if ( m_modsImporter != NULL ) delete m_modsImporter;
+ if ( m_marc21transformer != NULL ) delete m_marc21transformer;
+ if ( m_unimarctransformer != NULL ) delete m_unimarctransformer;
+ if ( m_conn != NULL ) delete m_conn;
+#endif // HAVE_YAZ
+// delete m_widget; FIXME Why does delete fail here?
+ }
+
+ QString WebQueryZ3950::title()
+ {
+ return i18n( "Z39.50" );
+ }
+
+ QString WebQueryZ3950::disclaimer()
+ {
+ return i18n( "Z39.50" );
+ }
+
+ QString WebQueryZ3950::disclaimerURL()
+ {
+ return "http://[127.0.0.1]/";
+ }
+
+ WebQueryWidget *WebQueryZ3950::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryZ3950::query()
+ {
+ WebQuery::query();
+
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "Z3950_server", QString::number( m_widget->comboBoxServers->currentItem() ) );
+ settings->setWebQueryDefault( "Z3950_query1", m_widget->lineEditQuery->text() );
+ settings->setWebQueryDefault( "Z3950_attr1", QString::number( m_widget->comboBoxInAttribute->currentItem() ) );
+ settings->setWebQueryDefault( "Z3950_query2", m_widget->lineEditQuery2->text() );
+ settings->setWebQueryDefault( "Z3950_attr2", QString::number( m_widget->comboBoxInAttribute2->currentItem() ) );
+ settings->setWebQueryDefault( "Z3950_booleanOp", QString::number( m_widget->comboBoxBooleanOp->currentItem() ) );
+
+#ifdef HAVE_YAZ
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace();
+ if ( searchTerm.isEmpty() )
+ {
+ setNumStages( 1 );
+ setEndSearch( WebQuery::statusError );
+ return;
+ }
+
+ QString query = queryClause( searchTerm, m_widget->comboBoxInAttribute->currentItem() );
+
+ searchTerm = m_widget->lineEditQuery2->text().stripWhiteSpace();
+ if ( !searchTerm.isEmpty() )
+ {
+ if ( m_widget->comboBoxBooleanOp->currentItem() == 0 )
+ query = query.prepend( "@and " );
+ else
+ query = query.prepend( "@or " );
+ query = query.append( queryClause( searchTerm, m_widget->comboBoxInAttribute2->currentItem() ) );
+ }
+
+ kdDebug() << "query = " << query << endl;
+
+ m_conn = NULL;
+ settings = Settings::self();
+ for ( QMap<QString, Settings::Z3950Server>::Iterator it = settings->z3950_ServerList.begin(); m_conn == NULL && it != settings->z3950_ServerList.end(); ++it )
+ {
+ if ( it.data().name.compare( m_widget->comboBoxServers->currentText() ) == 0 )
+ {
+ m_syntax = it.data().syntax;
+ m_conn = new KBibTeX::Z3950Connection( this, it.data().host, it.data().port, it.data().database, it.data().charset, m_syntax, "f" );
+ m_conn->setUserPassword( it.data().user, it.data().password );
+ }
+ }
+
+ if ( m_conn != NULL )
+ {
+ setNumStages( m_widget->spinBoxMaxHits->value() );
+ m_started = true;
+
+ m_conn->setQuery( query, m_widget->spinBoxMaxHits->value() );
+ m_modsList.clear();
+ m_hitCounter = 0;
+ m_conn->start();
+ kdDebug() << "WebQueryZ3950::query: started" << endl;
+ }
+ else
+#else // HAVE_YAZ
+ kdDebug() << "HAVE_YAZ not defined" << endl;
+#endif // HAVE_YAZ
+ {
+ setNumStages( 1 );
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ }
+
+ void WebQueryZ3950::cancelQuery()
+ {
+#ifdef HAVE_YAZ
+ if ( m_started && m_conn != NULL )
+ {
+ m_started = false;
+ m_conn->abort();
+ m_conn->wait( 10000 );
+ setEndSearch( WebQuery::statusError );
+ }
+#endif // HAVE_YAZ
+ }
+
+#ifdef HAVE_YAZ
+ QString WebQueryZ3950::queryClause( const QString& text, int field )
+ {
+ QString result = "@attr 1=";
+ switch ( field )
+ {
+ case 1: result.append( "4" ); break;
+ case 2: result.append( "1003" ); break;
+ case 3: result.append( "1006" ); break;
+ case 4: result.append( "1016" ); break;
+ default: result.append( "1018" ); break;
+ }
+ result.append( " @attr 2=3 \"" ).append( text ).append( "\" " );
+
+ return result;
+ }
+#endif // HAVE_YAZ
+
+ void WebQueryZ3950::customEvent( QCustomEvent* event )
+ {
+ kdDebug() << "WebQueryZ3950::customEvent of type " << event->type() << endl;
+
+#ifdef HAVE_YAZ
+ if ( !m_conn )
+ {
+ return;
+ }
+
+ if ( event->type() == KBibTeX::Z3950ResultFound::uid() )
+ {
+ KBibTeX::Z3950ResultFound* e = static_cast<KBibTeX::Z3950ResultFound*>( event );
+ kdDebug() << "Z3950ResultFound: " << e->result().left( 24 ) << " [..] " << e->result().right( 24 ) << endl;
+ storeResult( e->result(), m_syntax );
+ m_hitCounter++;
+ enterNextStage();
+ }
+
+ else if ( event->type() == KBibTeX::Z3950ConnectionDone::uid() )
+ {
+ KBibTeX::Z3950ConnectionDone* e = static_cast<KBibTeX::Z3950ConnectionDone*>( event );
+ kdDebug() << "Z3950ConnectionDone: " << e->message() << " (" << e->messageType() << ")" << endl;
+ if ( e->messageType() > -1 )
+ KMessageBox::error( m_widget, QString( i18n( "The server returned the following message:\n\n%1" ) ).arg( e->message() ), i18n( "Error querying Z39.50 server" ) );
+
+ m_started = false;
+ if ( m_conn != NULL )
+ m_conn->wait();
+
+ if ( !m_aborted )
+ {
+ evalStoredResults();
+ setEndSearch( e->messageType() > -1 ? WebQuery::statusError : WebQuery::statusSuccess );
+ }
+ }
+
+ qApp->processEvents();
+#endif // HAVE_YAZ
+ }
+
+#ifdef HAVE_YAZ
+ void WebQueryZ3950::storeResult( const QString& resultText, const QString& syntax )
+ {
+ if ( resultText.isEmpty() ) return;
+ QString convertedResultText = QString::null;
+
+ if ( syntax == "mods" )
+ convertedResultText = resultText;
+ else if ( syntax == "usmarc" || syntax == "marc21" )
+ {
+ if ( m_marc21transformer == NULL ) m_marc21transformer = new BibTeX::XSLTransform( KGlobal::dirs()->findResource( "data", "kbibtexpart/xslt/MARC21slim2MODS3.xsl" ) );
+ convertedResultText = m_marc21transformer->transform( resultText );
+ }
+ else if ( syntax == "unimarc" )
+ {
+ if ( m_unimarctransformer == NULL ) m_unimarctransformer = new BibTeX::XSLTransform( KGlobal::dirs()->findResource( "data", "kbibtexpart/xslt/UNIMARC2MODS3.xsl" ) );
+ convertedResultText = m_unimarctransformer->transform( resultText );
+ }
+
+ m_modsList.append( convertedResultText );
+ }
+
+ void WebQueryZ3950::evalStoredResults()
+ {
+ if ( m_modsImporter == NULL )
+ m_modsImporter = new BibTeX::FileImporterBibUtils( BibTeX::File::formatMODS );
+
+ for ( QStringList::Iterator it = m_modsList.begin(); it != m_modsList.end();++it )
+ {
+ BibTeX::File *bibtexFile = m_modsImporter->load( *it );
+ if ( bibtexFile != NULL )
+ {
+ for ( BibTeX::File::ElementList::iterator it = bibtexFile->begin(); it != bibtexFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ {
+ BibTeX::Entry *newEntry = new BibTeX::Entry( entry );
+ kdDebug() << "entry= " << newEntry->text() << endl;
+ emit foundEntry( newEntry, false );
+ }
+ }
+
+ delete bibtexFile;
+ }
+ }
+ }
+#endif // HAVE_YAZ
+
+}
+#include "webqueryz3950.moc"
diff --git a/src/webqueryz3950.h b/src/webqueryz3950.h
new file mode 100644
index 0000000..93d8999
--- /dev/null
+++ b/src/webqueryz3950.h
@@ -0,0 +1,122 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * based on code from or inspired by *
+ * - Tellico by Robby Stephenson *
+ * - kbib by Thach Nguyen *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ * *
+ * This code is based on code from Tellico 1.2.10 *
+ * by Robby Stephenson <[email protected]> *
+ * Tellico is released under the GNU GPL 2, too. *
+ * http://www.periapsis.org/tellico/ *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef KBIBTEXWEBQUERYZ3950_H
+#define KBIBTEXWEBQUERYZ3950_H
+
+#include <qevent.h>
+#include <qdeepcopy.h>
+#include <qthread.h>
+
+#include <ksharedptr.h>
+
+#include <fileimporter.h>
+#include <webquery.h>
+#include <xsltransform.h>
+#include <z3950connection.h>
+
+class KComboBox;
+
+namespace KBibTeX
+{
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryZ3950Widget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryZ3950Widget( QWidget *parent, const char *name = 0 );
+
+ KComboBox *comboBoxServers;
+ KComboBox *comboBoxInAttribute;
+ KComboBox *comboBoxBooleanOp;
+ KLineEdit *lineEditQuery2;
+ KComboBox *comboBoxInAttribute2;
+
+ protected:
+ virtual void init();
+
+ private:
+ static const QString attributesI18N[];
+ };
+
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryZ3950 : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryZ3950( QWidget* parent );
+ virtual ~WebQueryZ3950();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ private:
+ WebQueryZ3950Widget *m_widget;
+
+ protected:
+ void cancelQuery();
+
+ protected:
+ virtual void customEvent( QCustomEvent* event );
+
+#ifdef HAVE_YAZ
+ private:
+ BibTeX::XSLTransform *m_marc21transformer;
+ BibTeX::XSLTransform *m_unimarctransformer;
+ BibTeX::FileImporter *m_modsImporter;
+ KBibTeX::Z3950Connection *m_conn;
+ bool m_started;
+ bool m_waitingRetrieveRange;
+ QString m_syntax;
+ QStringList m_modsList;
+ int m_hitCounter;
+
+ void storeResult( const QString& resultText, const QString& syntax );
+ void evalStoredResults();
+ QString queryClause( const QString& text, int field );
+#endif // HAVE_YAZ
+ };
+}
+
+#endif
diff --git a/src/webqueryzmath.cpp b/src/webqueryzmath.cpp
new file mode 100644
index 0000000..9e8a78e
--- /dev/null
+++ b/src/webqueryzmath.cpp
@@ -0,0 +1,124 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qfile.h>
+#include <qapplication.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+#include <kurl.h>
+
+#include <settings.h>
+#include <fileimporterbibtex.h>
+#include "webqueryzmath.h"
+
+namespace KBibTeX
+{
+ WebQueryZMATHWidget::WebQueryZMATHWidget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "ZMATH" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ }
+
+ WebQueryZMATH::WebQueryZMATH( QWidget* parent ): WebQuery( parent )
+ {
+ m_widget = new WebQueryZMATHWidget( parent );
+ }
+
+ WebQueryZMATH::~WebQueryZMATH()
+ {
+ delete m_widget;
+ }
+
+ QString WebQueryZMATH::title()
+ {
+ return i18n( "Zentralblatt MATH" );
+ }
+
+ QString WebQueryZMATH::disclaimer()
+ {
+ return i18n( "About Zentralblatt MATH" );
+ }
+
+ QString WebQueryZMATH::disclaimerURL()
+ {
+ return "http://www.zentralblatt-math.org/zmath/en/";
+ }
+
+ WebQueryWidget *WebQueryZMATH::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryZMATH::query()
+ {
+ WebQuery::query();
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "ZMATH", m_widget->lineEditQuery->text() );
+
+ int numberOfResults = m_widget->spinBoxMaxHits->value();
+ setNumStages( 1 );
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace().replace( '$', "" );
+ if ( searchTerm.isEmpty() )
+ {
+ setEndSearch( WebQuery::statusInvalidQuery );
+ return;
+ }
+
+ KURL url = KURL( QString( "http://www.zentralblatt-math.org/zmath/en/search/?q=%2&count=%1&type=bibtex&format=short&display=all" ).arg( numberOfResults ).arg( searchTerm.replace( "%", "%25" ).replace( "+", "%2B" ).replace( " ", "%20" ).replace( "#", "%23" ).replace( "&", "%26" ).replace( "?", "%3F" ) ) );
+ BibTeX::File *bibtexFile = downloadBibTeXFile( url );
+ if ( bibtexFile != NULL && !m_aborted )
+ {
+ for ( BibTeX::File::ElementList::iterator it = bibtexFile->begin(); it != bibtexFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ emit foundEntry( new BibTeX::Entry( entry ), false );
+ }
+
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ else if ( !m_aborted )
+ {
+ QString message = KIO::NetAccess::lastErrorString();
+ if ( message.isEmpty() )
+ message.prepend( '\n' );
+ message.prepend( QString( i18n( "Querying database '%1' failed." ) ).arg( title() ) );
+ KMessageBox::error( m_parent, message );
+ setEndSearch( WebQuery::statusError );
+ }
+ else
+ setEndSearch( WebQuery::statusAborted );
+
+ if ( bibtexFile != NULL ) delete bibtexFile;
+ }
+
+}
+#include "webqueryzmath.moc"
diff --git a/src/webqueryzmath.h b/src/webqueryzmath.h
new file mode 100644
index 0000000..e6e7625
--- /dev/null
+++ b/src/webqueryzmath.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef KBIBTEXWEBQUERYZMATH_H
+#define KBIBTEXWEBQUERYZMATH_H
+
+#include <webquery.h>
+
+namespace KBibTeX
+{
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryZMATHWidget : public WebQueryWidget
+ {
+ Q_OBJECT
+ public:
+ WebQueryZMATHWidget( QWidget *parent, const char *name = 0 );
+ };
+
+ /**
+ @author Thomas Fischer <[email protected]>
+ */
+ class WebQueryZMATH : public WebQuery
+ {
+ Q_OBJECT
+ public:
+ WebQueryZMATH( QWidget* parent );
+ virtual ~WebQueryZMATH();
+
+ void query();
+
+ QString title();
+ QString disclaimer();
+ QString disclaimerURL();
+
+ WebQueryWidget *widget();
+
+ protected:
+ void cancelQuery() { /* nothing */ };
+
+ private:
+ WebQueryZMATHWidget *m_widget;
+ };
+
+}
+
+#endif
diff --git a/src/xsltransform.cpp b/src/xsltransform.cpp
new file mode 100644
index 0000000..fbb4fce
--- /dev/null
+++ b/src/xsltransform.cpp
@@ -0,0 +1,81 @@
+/***************************************************************************
+* Copyright (C) 2004-2009 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlstring.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+#include <qfile.h>
+#include <qstring.h>
+
+#include "xsltransform.h"
+
+namespace BibTeX
+{
+
+ XSLTransform::XSLTransform( const QString& xsltFilename )
+ {
+ m_xlstStylesheet = xsltParseStylesheetFile(( const xmlChar* ) xsltFilename.latin1() );
+ if ( m_xlstStylesheet == NULL )
+ qDebug( "Could not load XSLT file '%s'.", xsltFilename.latin1() );
+ }
+
+ XSLTransform::~XSLTransform()
+ {
+ xsltFreeStylesheet( m_xlstStylesheet );
+ }
+
+ QString XSLTransform::transform( const QString& xmlText )
+ {
+ QString result = QString::null;
+ QCString xmlCText = xmlText.utf8();
+ xmlDocPtr document = xmlParseMemory( xmlCText, xmlCText.length() );
+ if ( document )
+ {
+ if ( m_xlstStylesheet )
+ {
+ xmlDocPtr resultDocument = xsltApplyStylesheet( m_xlstStylesheet, document, NULL );
+ if ( resultDocument )
+ {
+ // Save the result into the QString
+ xmlChar * mem;
+ int size;
+ xmlDocDumpMemoryEnc( resultDocument, &mem, &size, "UTF-8" );
+ result = QString::fromUtf8( QCString(( char * )( mem ), size + 1 ) );
+ xmlFree( mem );
+
+ xmlFreeDoc( resultDocument );
+ }
+ else
+ qDebug( "Applying XSLT stylesheet to XML document failed" );
+ }
+ else
+ qDebug( "XSLT stylesheet is not available or not valid" );
+
+ xmlFreeDoc( document );
+ }
+ else
+ qDebug( "XML document is not available or not valid" );
+
+ return result;
+ }
+
+}
diff --git a/src/xsltransform.h b/src/xsltransform.h
new file mode 100644
index 0000000..73dd4ec
--- /dev/null
+++ b/src/xsltransform.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+* Copyright (C) 2004-2006 by Thomas Fischer *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#ifndef BIBTEXXSLTRANSFORM_H
+#define BIBTEXXSLTRANSFORM_H
+
+#include <libxslt/xsltInternals.h>
+
+class QString;
+
+namespace BibTeX
+{
+
+ class XSLTransform
+ {
+
+ public:
+ XSLTransform( const QString& xsltFilename );
+ ~XSLTransform();
+
+ QString transform( const QString& xmlText );
+
+ private:
+ xsltStylesheetPtr m_xlstStylesheet;
+
+ };
+
+}
+
+#endif
diff --git a/src/z3950-servers.cfg b/src/z3950-servers.cfg
new file mode 100644
index 0000000..7d106f0
--- /dev/null
+++ b/src/z3950-servers.cfg
@@ -0,0 +1,263 @@
+[CalStateLib]
+Charset=iso-8859-1
+Database=Marion
+Host=vax.lib.state.ca.us
+Locale=
+Name=California State Library
+Password=
+Port=210
+Syntax=
+User=
+
+[KOBV]
+Charset=marc8
+Database=U-KBV90
+Host=z3950.kobv.de
+Locale=
+Name=kobv
+Password=[XX]
+Port=9991
+Syntax=usmarc
+User=[XX]
+
+[OCLC]
+Charset=iso-8859-1
+Database=insp
+Host=fsz3950.oclc.org
+Locale=
+Name=Inspec (OCLC)
+Password=
+Port=210
+Syntax=marc21
+User=
+
+[RMIT]
+Charset=iso-8859-1
+Database=VOYAGER
+Host=zcat.lib.rmit.edu.au
+Locale=
+Name=RMIT University
+Password=
+Port=7090
+Syntax=usmarc
+User=
+
+[SSGJUR]
+Charset=utf-8
+Database=SSGJUR
+Host=z3950.gbv.de
+Locale=
+Name=SSGJUR
+Password=abc
+Port=20012
+Syntax=usmarc
+User=999
+
+[University of Sydney]
+Charset=iso-8859-1
+Database=INNOPAC
+Host=129.78.72.7
+Locale=
+Name=University of Sydney
+Password=
+Port=210
+Syntax=marc21
+User=
+
+[York]
+Charset=
+Database=unicorn
+Host=theta.library.yorku.ca
+Locale=
+Name=York University
+Password=
+Port=2200
+Syntax=marc21
+User=
+
+[aberdeen]
+Charset=iso-8859-1
+Database=ABN01
+Host=aulib.abdn.ac.uk
+Locale=
+Name=Aberdeen University
+Password=
+Port=9991
+Syntax=marc21
+User=
+
+[amicus]
+Charset=iso-8859-1
+Database=NL
+Host=amicus.collectionscanada.ca
+Locale=ca
+Name=National Library of Canada
+Password=
+Port=210
+Syntax=marc21
+User=
+
+[bibsys]
+Charset=iso-8859-1
+Database=BIBSYS
+Host=z3950.bibsys.no
+Locale=no
+Name=BIBSYS (Norway)
+Password=
+Port=2100
+Syntax=usmarc
+User=
+
+[blzcat]
+Charset=marc-8
+Database=BLAC
+Host=3950cat.bl.uk
+Locale=en_GB
+Name=The British Library
+Password=
+Port=9909
+Syntax=
+User=
+
+[copac]
+Charset=utf-8
+Database=COPAC
+Host=z3950.copac.ac.uk
+Locale=uk,ie,en
+Name=Copac (UK and Ireland)
+Password=
+Port=210
+Syntax=mods
+User=
+
+[gvk]
+Charset=utf-8
+Database=gvk
+Host=z3950.gbv.de
+Locale=
+Name=gvk
+Password=abc
+Port=20012
+Syntax=usmarc
+User=999
+
+[hochschuledarmstadt]
+Charset=iso-8859-1
+Database=hebis
+Host=tolk.hebis.de
+Locale=
+Name=Hochschule Darmstadt
+Password=
+Port=210
+Syntax=usmarc
+User=
+
+[iul]
+Charset=utf-8
+Database=ULI02
+Host=libnet.ac.il
+Locale=il
+Name=Israel Union List
+Password=
+Port=9991
+Syntax=marc21
+User=
+
+[libis]
+Charset=utf-8
+Database=knygos
+Host=z3950.libis.lt
+Locale=lt
+Name=National Library of Lithuania
+Password=
+Port=210
+Syntax=unimarc
+User=
+
+[loc]
+Charset=utf-8
+Database=Voyager
+Host=z3950.loc.gov
+Locale=en
+Name=Library of Congress (US)
+Password=
+Port=7090
+Syntax=mods
+User=
+
+[mitlibrariescatalog]
+Charset=iso-8859-1
+Database=mit01pub
+Host=library.mit.edu
+Locale=
+Name=MIT Libraries' Catalog
+Password=
+Port=9909
+Syntax=usmarc
+User=
+
+[naul]
+Charset=utf-8
+Database=Voyager
+Host=catalogue.nla.gov.au
+Locale=au
+Name=National Library of Australia
+Password=
+Port=7090
+Syntax=marc21
+User=
+
+[nlp]
+Charset=iso6937
+Database=INNOPAC
+Host=alpha.bn.org.pl
+Locale=pl
+Name=National Library of Poland
+Password=
+Port=210
+Syntax=usmarc
+User=
+
+[porbase]
+Charset=iso-8859-1
+Database=bnd
+Host=z3950.bn.pt
+Locale=pt
+Name=Portuguese National Library
+Password=
+Port=210
+Syntax=unimarc
+User=
+
+[sbn]
+Charset=iso-8859-1
+Database=nopac
+Host=opac.sbn.it
+Locale=it
+Name=Italian National Library
+Password=
+Port=3950
+Syntax=unimarc
+User=
+
+[stabikat]
+Charset=iso-8859-1
+Database=STABIKAT
+Host=z3950.gbv.de
+Locale=
+Name=STABIKAT
+Password=abc
+Port=20010
+Syntax=usmarc
+User=999
+
+[sudoc]
+Charset=iso-5426
+Database=ABES-Z39-PUBLIC
+Host=carmin.sudoc.abes.fr
+Locale=fr
+Name=Sudoc (France)
+Password=
+Port=210
+Syntax=usmarc
+User=
diff --git a/src/z3950connection.cpp b/src/z3950connection.cpp
new file mode 100644
index 0000000..ada2a1d
--- /dev/null
+++ b/src/z3950connection.cpp
@@ -0,0 +1,589 @@
+/***************************************************************************
+ copyright : (C) 2005-2006 by Robby Stephenson
+ email : $EMAIL
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "z3950connection.h"
+// #include "z3950fetcher.h"
+#include "messagehandler.h"
+#include "latin1literal.h"
+#include <kdebug.h>
+#include "iso5426converter.h"
+#include "iso6937converter.h"
+
+#include <qapplication.h>
+
+#include <config.h>
+
+#ifdef HAVE_YAZ
+extern "C"
+{
+#include <yaz/zoom.h>
+#include <yaz/marcdisp.h>
+#include <yaz/yaz-version.h>
+}
+#endif
+
+#include <klocale.h>
+
+#include <qfile.h>
+
+namespace
+{
+ static const size_t Z3950_DEFAULT_MAX_RECORDS = 20;
+}
+
+using KBibTeX::Z3950ResultFound;
+using KBibTeX::Z3950Connection;
+
+Z3950ResultFound::Z3950ResultFound( const QString& s ) : QCustomEvent( uid() )
+ , m_result( QDeepCopy<QString>( s ) )
+{
+ ++Z3950Connection::resultsLeft;
+}
+
+Z3950ResultFound::~Z3950ResultFound()
+{
+ --Z3950Connection::resultsLeft;
+}
+
+class Z3950Connection::Private
+{
+public:
+ Private() {}
+#ifdef HAVE_YAZ
+ ~Private()
+ {
+ ZOOM_options_destroy( conn_opt );
+ ZOOM_connection_destroy( conn );
+ };
+
+ ZOOM_options conn_opt;
+ ZOOM_connection conn;
+#endif
+};
+
+int Z3950Connection::resultsLeft = 0;
+
+// since the character set goes into a yaz api call
+// I'm paranoid about user insertions, so just grab 64
+// characters at most
+Z3950Connection::Z3950Connection( QObject* fetcher,
+ const QString& host,
+ uint port,
+ const QString& dbname,
+ const QString& sourceCharSet,
+ const QString& syntax,
+ const QString& esn )
+ : QThread()
+ , d( new Private() )
+ , m_connected( false )
+ , m_aborted( false )
+ , m_fetcher( fetcher )
+ , m_host( QDeepCopy<QString>( host ) )
+ , m_port( port )
+ , m_dbname( QDeepCopy<QString>( dbname ) )
+ , m_sourceCharSet( QDeepCopy<QString>( sourceCharSet.left( 64 ) ) )
+ , m_syntax( QDeepCopy<QString>( syntax ) )
+ , m_esn( QDeepCopy<QString>( esn ) )
+ , m_start( 0 )
+ , m_limit( Z3950_DEFAULT_MAX_RECORDS )
+ , m_hasMore( false )
+{
+}
+
+Z3950Connection::~Z3950Connection()
+{
+ m_connected = false;
+ delete d;
+ d = 0;
+}
+
+void Z3950Connection::reset()
+{
+ m_start = 0;
+ m_limit = Z3950_DEFAULT_MAX_RECORDS;
+}
+
+void Z3950Connection::setQuery( const QString& query_, unsigned int numHits )
+{
+ m_pqn = QDeepCopy<QString>( query_ );
+ m_limit = Z3950_DEFAULT_MAX_RECORDS < numHits ? Z3950_DEFAULT_MAX_RECORDS : numHits;
+}
+
+void Z3950Connection::setUserPassword( const QString& user_, const QString& pword_ )
+{
+ m_user = QDeepCopy<QString>( user_ );
+ m_password = QDeepCopy<QString>( pword_ );
+}
+
+void Z3950Connection::run()
+{
+// kdDebug() << "Z3950Connection::run() - " << m_fetcher->source() << endl;
+ m_aborted = false;
+ m_hasMore = false;
+ resultsLeft = 0;
+#ifdef HAVE_YAZ
+
+ if ( !makeConnection() )
+ {
+ done();
+ return;
+ }
+
+ ZOOM_query query = ZOOM_query_create();
+ kdDebug() << "Z3950Connection::run() - pqn = " << toCString( m_pqn ) << endl;
+ int errcode = ZOOM_query_prefix( query, toCString( m_pqn ) );
+ if ( errcode != 0 )
+ {
+ kdDebug() << "Z3950Connection::run() - query error: " << m_pqn << endl;
+ ZOOM_query_destroy( query );
+ QString s = i18n( "Query error!" );
+ s += ' ' + m_pqn;
+ done( s, MessageHandler::Error );
+ return;
+ }
+
+ ZOOM_resultset resultSet = ZOOM_connection_search( d->conn, query );
+
+ // check abort status
+ if ( m_aborted )
+ {
+ done();
+ return;
+ }
+
+ // I know the LOC wants the syntax = "xml" and esn = "mods"
+ // to get MODS data, that seems a bit odd...
+ // esn only makes sense for marc and grs-1
+ // if syntax is mods, set esn to mods too
+ QCString type = "raw";
+ if ( m_syntax == Latin1Literal( "mods" ) )
+ {
+ m_syntax = QString::fromLatin1( "xml" );
+ ZOOM_resultset_option_set( resultSet, "elementSetName", "mods" );
+ type = "xml";
+ }
+ else
+ {
+ ZOOM_resultset_option_set( resultSet, "elementSetName", m_esn.latin1() );
+ }
+ ZOOM_resultset_option_set( resultSet, "start", QCString().setNum( m_start ) );
+ ZOOM_resultset_option_set( resultSet, "count", QCString().setNum( m_limit - m_start ) );
+ // search in default syntax, unless syntax is already set
+ if ( !m_syntax.isEmpty() )
+ {
+ ZOOM_resultset_option_set( resultSet, "preferredRecordSyntax", m_syntax.latin1() );
+ }
+
+ const char* errmsg;
+ const char* addinfo;
+ errcode = ZOOM_connection_error( d->conn, &errmsg, &addinfo );
+ if ( errcode != 0 )
+ {
+ ZOOM_resultset_destroy( resultSet );
+ ZOOM_query_destroy( query );
+ m_connected = false;
+
+ QString s = i18n( "Connection search error %1: %2" ).arg( errcode ).arg( toString( errmsg ) );
+ if ( !QCString( addinfo ).isEmpty() )
+ {
+ s += " (" + toString( addinfo ) + ")";
+ }
+ kdDebug() << "Z3950Connection::run() - " << s << endl;
+ done( s, MessageHandler::Error );
+ return;
+ }
+
+ const size_t numResults = ZOOM_resultset_size( resultSet );
+
+ QString newSyntax = m_syntax;
+ if ( numResults > 0 )
+ {
+ kdDebug() << "Z3950Connection::run() - current syntax is " << m_syntax << " (" << numResults << " results)" << endl;
+ // so now we know that results exist, might have to check syntax
+ int len;
+ ZOOM_record rec = ZOOM_resultset_record( resultSet, 0 );
+ // want raw unless it's mods
+ ZOOM_record_get( rec, type, &len );
+ if ( len > 0 && m_syntax.isEmpty() )
+ {
+ newSyntax = QString::fromLatin1( ZOOM_record_get( rec, "syntax", &len ) ).lower();
+ kdDebug() << "Z3950Connection::run() - syntax guess is " << newSyntax << endl;
+ if ( newSyntax == Latin1Literal( "mods" ) || newSyntax == Latin1Literal( "xml" ) )
+ {
+ m_syntax = QString::fromLatin1( "xml" );
+ ZOOM_resultset_option_set( resultSet, "elementSetName", "mods" );
+ }
+ else if ( newSyntax == Latin1Literal( "grs-1" ) )
+ {
+ // if it's defaulting to grs-1, go ahead and change it to try to get a marc
+ // record since grs-1 is a last resort for us
+ newSyntax.truncate( 0 );
+ }
+ }
+ // right now, we just understand mods, unimarc, marc21/usmarc, and grs-1
+ if ( newSyntax != Latin1Literal( "xml" ) &&
+ newSyntax != Latin1Literal( "usmarc" ) &&
+ newSyntax != Latin1Literal( "marc21" ) &&
+ newSyntax != Latin1Literal( "unimarc" ) &&
+ newSyntax != Latin1Literal( "grs-1" ) )
+ {
+ kdDebug() << "Z3950Connection::run() - changing z39.50 syntax to MODS" << endl;
+ newSyntax = QString::fromLatin1( "xml" );
+ ZOOM_resultset_option_set( resultSet, "elementSetName", "mods" );
+ ZOOM_resultset_option_set( resultSet, "preferredRecordSyntax", newSyntax.latin1() );
+ rec = ZOOM_resultset_record( resultSet, 0 );
+ ZOOM_record_get( rec, "xml", &len );
+ if ( len == 0 )
+ {
+ // change set name back
+ ZOOM_resultset_option_set( resultSet, "elementSetName", m_esn.latin1() );
+ newSyntax = QString::fromLatin1( "usmarc" ); // try usmarc
+ kdDebug() << "Z3950Connection::run() - changing z39.50 syntax to USMARC" << endl;
+ ZOOM_resultset_option_set( resultSet, "preferredRecordSyntax", newSyntax.latin1() );
+ rec = ZOOM_resultset_record( resultSet, 0 );
+ ZOOM_record_get( rec, "raw", &len );
+ }
+ if ( len == 0 )
+ {
+ newSyntax = QString::fromLatin1( "marc21" ); // try marc21
+ kdDebug() << "Z3950Connection::run() - changing z39.50 syntax to MARC21" << endl;
+ ZOOM_resultset_option_set( resultSet, "preferredRecordSyntax", newSyntax.latin1() );
+ rec = ZOOM_resultset_record( resultSet, 0 );
+ ZOOM_record_get( rec, "raw", &len );
+ }
+ if ( len == 0 )
+ {
+ newSyntax = QString::fromLatin1( "unimarc" ); // try unimarc
+ kdDebug() << "Z3950Connection::run() - changing z39.50 syntax to UNIMARC" << endl;
+ ZOOM_resultset_option_set( resultSet, "preferredRecordSyntax", newSyntax.latin1() );
+ rec = ZOOM_resultset_record( resultSet, 0 );
+ ZOOM_record_get( rec, "raw", &len );
+ }
+ if ( len == 0 )
+ {
+ newSyntax = QString::fromLatin1( "grs-1" ); // try grs-1
+ kdDebug() << "Z3950Connection::run() - changing z39.50 syntax to GRS-1" << endl;
+ ZOOM_resultset_option_set( resultSet, "preferredRecordSyntax", newSyntax.latin1() );
+ rec = ZOOM_resultset_record( resultSet, 0 );
+ ZOOM_record_get( rec, "raw", &len );
+ }
+ if ( len == 0 )
+ {
+ kdDebug() << "Z3950Connection::run() - giving up" << endl;
+ ZOOM_resultset_destroy( resultSet );
+ ZOOM_query_destroy( query );
+ done( i18n( "Record syntax error" ), MessageHandler::Error );
+ return;
+ }
+ kdDebug() << "Z3950Connection::run() - final syntax is " << newSyntax << endl;
+ }
+ }
+
+ // go back to fooling ourselves and calling it mods
+ if ( m_syntax == Latin1Literal( "xml" ) )
+ {
+ m_syntax = QString::fromLatin1( "mods" );
+ }
+ if ( newSyntax == Latin1Literal( "xml" ) )
+ {
+ newSyntax = QString::fromLatin1( "mods" );
+ }
+ // save syntax change for next time
+ if ( m_syntax != newSyntax )
+ {
+ qApp->postEvent( m_fetcher, new Z3950SyntaxChange( newSyntax ) );
+ m_syntax = newSyntax;
+ }
+
+ if ( m_sourceCharSet.isEmpty() )
+ {
+ m_sourceCharSet = QString::fromLatin1( "marc-8" );
+ }
+
+ const size_t realLimit = QMIN( numResults, m_limit );
+
+ for ( size_t i = m_start; i < realLimit && !m_aborted; ++i )
+ {
+ kdDebug() << "Z3950Connection::run() - grabbing index " << i << endl;
+ ZOOM_record rec = ZOOM_resultset_record( resultSet, i );
+ if ( !rec )
+ {
+ kdDebug() << "Z3950Connection::run() - no record returned for index " << i << endl;
+ continue;
+ }
+ int len;
+ QString data;
+ if ( m_syntax == Latin1Literal( "mods" ) )
+ {
+ data = toString( ZOOM_record_get( rec, "xml", &len ) );
+ }
+ else if ( m_syntax == Latin1Literal( "grs-1" ) ) // grs-1
+ {
+ // we're going to parse the rendered data, very ugly...
+ data = toString( ZOOM_record_get( rec, "render", &len ) );
+ }
+ else
+ {
+#if 0
+ kdWarning() << "Remove debug from z3950connection.cpp" << endl;
+ {
+ QFile f1( QString::fromLatin1( "/tmp/z3950.raw" ) );
+ if ( f1.open( IO_WriteOnly ) )
+ {
+ QDataStream t( &f1 );
+ t << ZOOM_record_get( rec, "raw", &len );
+ }
+ f1.close();
+ }
+#endif
+ data = toXML( ZOOM_record_get( rec, "raw", &len ), m_sourceCharSet );
+ }
+ Z3950ResultFound* ev = new Z3950ResultFound( data );
+ QApplication::postEvent( m_fetcher, ev );
+ }
+
+ ZOOM_resultset_destroy( resultSet );
+ ZOOM_query_destroy( query );
+
+ m_hasMore = m_limit < numResults;
+ if ( m_hasMore )
+ {
+ m_start = m_limit;
+ m_limit += Z3950_DEFAULT_MAX_RECORDS;
+ }
+#endif
+ done();
+}
+
+bool Z3950Connection::makeConnection()
+{
+ if ( m_connected )
+ {
+ return true;
+ }
+// kdDebug() << "Z3950Connection::makeConnection() - " << m_fetcher->source() << endl;
+// I don't know what to do except assume database, user, and password are in locale encoding
+#ifdef HAVE_YAZ
+ d->conn_opt = ZOOM_options_create();
+ ZOOM_options_set( d->conn_opt, "implementationName", "KBibTeX" );
+ ZOOM_options_set( d->conn_opt, "databaseName", toCString( m_dbname ) );
+ ZOOM_options_set( d->conn_opt, "user", toCString( m_user ) );
+ ZOOM_options_set( d->conn_opt, "password", toCString( m_password ) );
+
+ d->conn = ZOOM_connection_create( d->conn_opt );
+ ZOOM_connection_connect( d->conn, m_host.latin1(), m_port );
+
+ int errcode;
+ const char* errmsg; // unused: carries same info as 'errcode'
+ const char* addinfo;
+ errcode = ZOOM_connection_error( d->conn, &errmsg, &addinfo );
+ if ( errcode != 0 )
+ {
+ ZOOM_options_destroy( d->conn_opt );
+ ZOOM_connection_destroy( d->conn );
+ m_connected = false;
+
+ QString s = i18n( "Connection error %1: %2" ).arg( errcode ).arg( toString( errmsg ) );
+ if ( !QCString( addinfo ).isEmpty() )
+ {
+ s += " (" + toString( addinfo ) + ")";
+ }
+ kdDebug() << "Z3950Connection::makeConnection() - " << s << endl;
+ done( s, MessageHandler::Error );
+ return false;
+ }
+#endif
+ m_connected = true;
+ return true;
+}
+
+void Z3950Connection::done()
+{
+ checkPendingEvents();
+ qApp->postEvent( m_fetcher, new Z3950ConnectionDone( m_hasMore ) );
+}
+
+void Z3950Connection::done( const QString& msg_, int type_ )
+{
+ checkPendingEvents();
+ if ( m_aborted )
+ {
+ qApp->postEvent( m_fetcher, new Z3950ConnectionDone( m_hasMore ) );
+ }
+ else
+ {
+ qApp->postEvent( m_fetcher, new Z3950ConnectionDone( m_hasMore, msg_, type_ ) );
+ }
+}
+
+void Z3950Connection::checkPendingEvents()
+{
+ // if there's still some pending result events, go ahead and just wait 1 second
+ if ( resultsLeft > 0 )
+ {
+ sleep( 1 );
+ }
+}
+
+inline
+QCString Z3950Connection::toCString( const QString& text_ )
+{
+ return iconvRun( text_.utf8(), QString::fromLatin1( "utf-8" ), m_sourceCharSet );
+}
+
+inline
+QString Z3950Connection::toString( const QCString& text_ )
+{
+ return QString::fromUtf8( iconvRun( text_, m_sourceCharSet, QString::fromLatin1( "utf-8" ) ) );
+}
+
+// static
+QCString Z3950Connection::iconvRun( const QCString& text_, const QString& fromCharSet_, const QString& toCharSet_ )
+{
+#ifdef HAVE_YAZ
+ if ( text_.isEmpty() )
+ {
+ return text_;
+ }
+
+ if ( fromCharSet_ == toCharSet_ )
+ {
+ return text_;
+ }
+
+ yaz_iconv_t cd = yaz_iconv_open( toCharSet_.latin1(), fromCharSet_.latin1() );
+ if ( !cd )
+ {
+ // maybe it's iso 5426, which we sorta support
+ QString charSetLower = fromCharSet_.lower();
+ charSetLower.remove( '-' ).remove( ' ' );
+ if ( charSetLower == Latin1Literal( "iso5426" ) )
+ {
+ return iconvRun( Iso5426Converter::toUtf8( text_ ).utf8(), QString::fromLatin1( "utf-8" ), toCharSet_ );
+ }
+ else if ( charSetLower == Latin1Literal( "iso6937" ) )
+ {
+ return iconvRun( Iso6937Converter::toUtf8( text_ ).utf8(), QString::fromLatin1( "utf-8" ), toCharSet_ );
+ }
+ kdWarning() << "Z3950Connection::iconvRun() - conversion from " << fromCharSet_
+ << " to " << toCharSet_ << " is unsupported" << endl;
+ return text_;
+ }
+
+ const char* input = text_;
+ size_t inlen = text_.length();
+
+ size_t outlen = 2 * inlen; // this is enough, right?
+ QMemArray<char> result0( outlen );
+ char* result = result0.data();
+
+ int r = yaz_iconv( cd, const_cast<char**>( &input ), &inlen, &result, &outlen );
+ if ( r <= 0 )
+ {
+ kdDebug() << "Z3950Connection::iconvRun() - can't decode buffer" << endl;
+ return text_;
+ }
+ // bug in yaz, need to flush buffer to catch last character
+ yaz_iconv( cd, 0, 0, &result, &outlen );
+
+ // length is pointer difference
+ size_t len = result - result0;
+
+ QCString output = QCString( result0, len + 1 );
+// kdDebug() << "-------------------------------------------" << endl;
+// kdDebug() << output << endl;
+// kdDebug() << "-------------------------------------------" << endl;
+ yaz_iconv_close( cd );
+ return output;
+#endif
+ return text_;
+}
+
+QString Z3950Connection::toXML( const QCString& marc_, const QString& charSet_ )
+{
+#ifdef HAVE_YAZ
+ if ( marc_.isEmpty() )
+ {
+ kdDebug() << "Z3950Connection::toXML() - empty string" << endl;
+ return QString::null;
+ }
+
+ yaz_iconv_t cd = yaz_iconv_open( "utf-8", charSet_.latin1() );
+ if ( !cd )
+ {
+ // maybe it's iso 5426, which we sorta support
+ QString charSetLower = charSet_.lower();
+ charSetLower.remove( '-' ).remove( ' ' );
+ if ( charSetLower == Latin1Literal( "iso5426" ) )
+ {
+ return toXML( Iso5426Converter::toUtf8( marc_ ).utf8(), QString::fromLatin1( "utf-8" ) );
+ }
+ else if ( charSetLower == Latin1Literal( "iso6937" ) )
+ {
+ return toXML( Iso6937Converter::toUtf8( marc_ ).utf8(), QString::fromLatin1( "utf-8" ) );
+ }
+ kdWarning() << "Z3950Connection::toXML() - conversion from " << charSet_ << " is unsupported" << endl;
+ return QString::null;
+ }
+
+ yaz_marc_t mt = yaz_marc_create();
+ yaz_marc_iconv( mt, cd );
+ yaz_marc_xml( mt, YAZ_MARC_MARCXML );
+
+ // first 5 bytes are length
+ bool ok;
+#if YAZ_VERSIONL < 0x030000
+ int len = marc_.left( 5 ).toInt( &ok );
+#else
+ size_t len = marc_.left( 5 ).toInt( &ok );
+#endif
+ if ( ok && ( len < 25 || len > 100000 ) )
+ {
+ kdDebug() << "Z3950Connection::toXML() - bad length: " << ( ok ? len : -1 ) << endl;
+ return QString::null;
+ }
+
+#if YAZ_VERSIONL < 0x030000
+ char* result;
+#else
+ const char* result;
+#endif
+ int r = yaz_marc_decode_buf( mt, marc_, -1, &result, &len );
+ if ( r <= 0 )
+ {
+ kdDebug() << "Z3950Connection::toXML() - can't decode buffer" << endl;
+ return QString::null;
+ }
+
+ QString output = QString::fromLatin1( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
+ output += QString::fromUtf8( QCString( result, len + 1 ), len + 1 );
+// kdDebug() << QCString(result) << endl;
+// kdDebug() << "-------------------------------------------" << endl;
+// kdDebug() << output << endl;
+ yaz_iconv_close( cd );
+ yaz_marc_destroy( mt );
+
+ return output;
+#else // no yaz
+ return QString::null;
+#endif
+}
diff --git a/src/z3950connection.h b/src/z3950connection.h
new file mode 100644
index 0000000..8019f40
--- /dev/null
+++ b/src/z3950connection.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+ copyright : (C) 2005-2006 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file has been modified to match the requirements of KBibTeX. *
+ * In case of problems or bugs arising from this implementation, please *
+ * contact the KBibTeX team first. *
+ * Thomas Fischer <[email protected]> *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef KBIBTEX_Z3950CONNECTION_H
+#define KBIBTEX_Z3950CONNECTION_H
+
+#include <qthread.h>
+#include <qevent.h>
+#include <qdeepcopy.h>
+
+#include <ksharedptr.h>
+
+namespace KBibTeX {
+class Z3950ResultFound : public QCustomEvent {
+public:
+ Z3950ResultFound(const QString& s);
+ ~Z3950ResultFound();
+ const QString& result() const { return m_result; }
+
+ static int uid() { return User + 11111; }
+
+private:
+ QString m_result;
+};
+
+class Z3950ConnectionDone : public QCustomEvent {
+public:
+ Z3950ConnectionDone(bool more) : QCustomEvent(uid()), m_type(-1), m_hasMore(more) {}
+ Z3950ConnectionDone(bool more, const QString& s, int t) : QCustomEvent(uid()), m_msg(QDeepCopy<QString>(s)), m_type(t), m_hasMore(more) {}
+
+ const QString& message() const { return m_msg; }
+ int messageType() const { return m_type; }
+ bool hasMoreResults() const { return m_hasMore; }
+
+ static int uid() { return User + 22222; }
+
+private:
+ QString m_msg;
+ int m_type;
+ bool m_hasMore;
+};
+
+class Z3950SyntaxChange : public QCustomEvent {
+public:
+ Z3950SyntaxChange(const QString& s) : QCustomEvent(uid()), m_syntax(QDeepCopy<QString>(s)) {}
+ const QString& syntax() const { return m_syntax; }
+
+ static int uid() { return User + 33333; }
+
+private:
+ QString m_syntax;
+};
+
+/**
+ * @author Robby Stephenson
+ */
+class Z3950Connection : public QThread {
+public:
+ Z3950Connection(QObject* fetcher,
+ const QString& host,
+ uint port,
+ const QString& dbname,
+ const QString& sourceCharSet,
+ const QString& syntax,
+ const QString& esn);
+ ~Z3950Connection();
+
+ void reset();
+ void setQuery(const QString& query, unsigned int numHits);
+ void setUserPassword(const QString& user, const QString& pword);
+ void run();
+
+ void abort() { m_aborted = true; }
+
+private:
+ static QCString iconvRun(const QCString& text, const QString& fromCharSet, const QString& toCharSet);
+ static QString toXML(const QCString& marc, const QString& fromCharSet);
+
+ bool makeConnection();
+ void done();
+ void done(const QString& message, int type);
+ QCString toCString(const QString& text);
+ QString toString(const QCString& text);
+ void checkPendingEvents();
+
+ class Private;
+ Private* d;
+
+ bool m_connected;
+ bool m_aborted;
+
+ QObject* m_fetcher;
+ QString m_host;
+ uint m_port;
+ QString m_dbname;
+ QString m_user;
+ QString m_password;
+ QString m_sourceCharSet;
+ QString m_syntax;
+ QString m_pqn;
+ QString m_esn;
+ size_t m_start;
+ size_t m_limit;
+ bool m_hasMore;
+
+ friend class Z3950ResultFound;
+ static int resultsLeft;
+};
+
+} // end namespace
+
+#endif