/***************************************************************************
                          kbib.cpp  -  description
                             -------------------
    begin                : Sat May 24 16:37:30 EST 2003
    copyright            : (C) 2003 by Thach Nguyen
    email                : thach.nguyen@rmit.edu.au
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

// include files for KDE


#include <kstatusbar.h>
#include <kaboutdata.h>
#include <kiconloader.h>
#include <kfiledialog.h>
#include <klibloader.h>
#include <kstddirs.h>
#include <kmessagebox.h>
#include <kconfig.h>
#include <kspell.h>
#include <ksconfig.h>
#include <klocale.h>
#include <kglobalsettings.h>
#include <kprocess.h>
#include <krun.h>
#include <khtmlview.h>
#include <kkeydialog.h>
#include <kedittoolbar.h>
#include <kglobal.h>
#include <kprinter.h>
#include <kwin.h>
#include <kparts/browserextension.h>
#include <kaccel.h>
#include <kstdguiitem.h>
#include <kguiitem.h>
#include <kinputdialog.h>
#include <klineeditdlg.h>
#include <kprogress.h>
#include <ktempfile.h>
#include <kio/netaccess.h>
#include <kio/job.h>
#include <dcopclient.h>
#include <qinputdialog.h>


// include files for QT
#include <qtextcodec.h>
#include <qdir.h>
#include <qprinter.h>
#include <qpainter.h>
#include <qsplitter.h>
#include <qapplication.h>
#include <qclipboard.h>
#include <qfileinfo.h>
#include <qfile.h>
#include <qpaintdevicemetrics.h>
#include <qstringlist.h>
#include <qfile.h>
#include <qdir.h>
#include <qlayout.h>
#include <qdom.h>
#include <qregexp.h>

// application specific includes
#include "kbib.h"
#include "kbibdoc.h"
#include "kbibcheckkeydlg.h"
#include "kbibfinddlg.h"
#include "kbibstart.h"

#include "bibentrytable.h"
#include "bibentry.h"
#include "kbibselectentrytype.h"
#include "kbibconfigdlg.h"
#include "kbibcreatebiliographydlg.h"
#include "kbibsortdlg.h"
#include "kbibinsertfiledlg.h"
#include "kbibstringmacrodlg.h"
#include "kbibexporthtmldlg.h"
#include "kbibpreambledlg.h"
#include "kbibremotesearchdlg.h"
#include "newentryfromtextdialog.h"
#include "referencefieldsdialog.h"
#include "referencetypesdialog.h"
#include "setfielddlg.h"
#include "replacestringdlg.h"
#include "copyfieldcontent.h"

#if HAVE_POPPLER
	#include <poppler-qt.h>
#endif

#include <fstream>

#include "filters/bibprogs.h"

#define ID_STATUS_MSG 1
#define ID_STATUS_NOREF 2


KBibApp::KBibApp(QWidget* , const char* name):KMainWindow(0, name), DCOPObject("kbibapp"), m_findDlg(0), configDlg(0), m_id2Entry(0), m_queuedFilters(0)
{

    firstRun = TRUE;
    config=kapp->config();
	QTextCodec *codec = QTextCodec::codecForName("utf8");
	QTextCodec::setCodecForCStrings(codec);
	
	
	
	///////////////////////////////////////////////////////////////////
    // call inits to invoke all other construction parts
    initStatusBar();
    initActions();
    initDocument();
    initView();
	createEntryDefs();
	setGroupByList();
    doc->newDocument();

	group_view->addBibEntryTable ( doc->getEntryList() );

    ///////////////////////////////////////////////////////////////////
    // disable actions at startup
    fileSave->setEnabled(false);
    fileReload->setEnabled(false);
    createKeys->setEnabled(false);
    lockKeys->setEnabled(false);
    unLockKeys->setEnabled(false);
    refCheckKey->setEnabled(false);

    viewBibSource->setEnabled(false);

    editCopy->setEnabled(false);
    editCopyFormated->setEnabled(false);
    editCut->setEnabled(false);
    citeEntry->setEnabled(false);
    deleteEntry->setEnabled(false);
    sortReference->setEnabled(false);
    createBibliography->setEnabled(false);
    saveSelected->setEnabled(false);
	setFieldValue->setEnabled(false);
	copyFieldContent->setEnabled(false);
	replaceString->setEnabled(false);
    viewSelected->setEnabled(false);
    hideSelected->setEnabled(false);


    readOptions();
//	QTextCodec *codec = QTextCodec::codecForName((kbibConfigState.encoding).latin1());
//	QTextCodec::setCodecForCStrings(codec);
	
    



    setCaption((doc->getURL()).fileName(), false);
    connect(m_view, SIGNAL(signalListChange()), this, SLOT(slotDocChanged() ) );
    connect(m_view, SIGNAL(selectionChanged ()), this, SLOT(slotSelectionChanged()));
    connect(group_view, SIGNAL(selectionChanged ()), this, SLOT(slotSelectionChanged()));
    connect(previewBtn, SIGNAL(clicked()), this, SLOT(slotShowPreview()));

	bool found = false;
	QString uiFile = locateLocal( "data", "kbib/kbibui.rc" );

    if( ! QFile::exists(uiFile) )
    {
        uiFile = locate( "data", "kbib/kbibui.rc" );
        if( QFile::exists( uiFile ) )
            found = true;
        
    }
    else
        found = true;
		
	if (!found){
		KMessageBox::error( this,i18n("File kbibui.rc could not be found. Please check your KBib installation."));
	}
	
	
	createGUI("kbibui.rc");
	
    m_view->updateColumn();
    //  ms_findDlg = new KBibFindDlg(this);
    currentSelectedView = 0;
    m_view->setFont(kbibConfigState.font);
    group_view->setFont(kbibConfigState.font);
    p_preview->setFont(kbibConfigState.font);

    slotShowGroupView();
    slotShowPreview();
	
    
  m_attributes->insertItem(i18n("All Fields"));
  m_attributes->insertItem(i18n("Citation Key"));
  m_attributes->insertStringList(BibEntryDefTable::self()->getFieldNames());
		
//  m_attributes->adjustSize();
	
	
}

KBibApp::~KBibApp()
{
    if(m_findDlg)
        delete m_findDlg;
    if (configDlg)
        delete configDlg;
}

void KBibApp::initActions()
{


    fileNewWindow = new KAction(i18n("New &Window"), 0, 0, this, SLOT(slotFileNewWindow()), actionCollection(),"file_new_window");

    newEntry = new KAction(i18n("New Reference"), "edit_add", ALT+Key_N, this, SLOT(slotNewEntry()),actionCollection(), "newEntry");

	newEntryFromDOI = new KAction(i18n("Digital Object Identifier (DOI)"), 0, 0, this, SLOT(slotNewEntryFromDOI()),actionCollection(), "newEntryFromDOI");
	newEntryFromArXiv = new KAction(i18n("ArXiv ID"), 0, 0, this, SLOT(slotNewEntryFromArXiv()),actionCollection(), "newEntryFromArXiv");
	newEntryFromPMID = new KAction(i18n("PubMed ID"), 0, 0, this, SLOT(slotNewEntryFromPubmedID()),actionCollection(), "newEntryFromPMID");
#if HAVE_POPPLER	
	newEntryFromPDF = new KAction(i18n("New Reference from PDF file"), "pdf", ALT+Key_P, this, SLOT(slotNewEntryFromPDF()),actionCollection(), "newEntryFromPDF");
#endif
	newEntryFromText = new KAction(i18n("New Reference from Plain Text"), "txt", ALT+Key_T, this, SLOT(slotNewEntryFromText()),actionCollection(), "newEntryFromText");	
	
    insertExistingFile = new KAction(i18n("Import File"), "fileimport",  CTRL+Key_I, this, SLOT(slotInsertFile()),actionCollection(), "insertFile");

    deleteEntry = new KAction(i18n("Delete Selected References"), "edit_remove", Key_Delete, this, SLOT(slotDeleteEntry()),actionCollection(), "deleteEntry");
    citeEntry =  new KAction(i18n("Cite Selected References"), "cite", ALT+Key_C, this, SLOT(slotCiteEntry()),actionCollection(), "citeEntry");
    showPreview = new KAction(i18n("Hide Preview"), 0, 0, this, SLOT(slotShowPreview()),actionCollection(), "showPreview");
    showGroupView = new KAction(i18n("Hide Group View"), 0, 0, this, SLOT(slotShowGroupView()),actionCollection(), "showGroupView");
    previewModeSelect = new KSelectAction(i18n("Preview Mode"), 0, 0, this, SLOT(slotPreviewModeSelect() ),actionCollection(), "selectPreviewMode");
    //  previewModeSelect = new KSelectAction(i18n("Preview Mode"), 0, 0, actionCollection(), "selectPreviewMode");


    QStringList previewModeText;
    previewModeText.append(i18n("Detail Preview"));
    previewModeText.append(i18n("Short Preview"));

    previewModeSelect->setItems(previewModeText);
    previewModeSelect->setCurrentItem(1);
    previewMode = 1;
    //  connect(previewModeSelect, SIGNAL(activated (int index)), this, SLOT(slotPreviewModeSelect(int index) ) );

    preamble = new KAction(i18n("Preamble"), 0, 0, this, SLOT(slotPreamble()),actionCollection(), "preamble");
    stringMacro = new KAction(i18n("String Macros"), 0, 0, this, SLOT(slotStringMacro()),actionCollection(), "stringMacro");
	customiseFields = new KAction(i18n("Customise Reference Fields"), 0, 0, this, SLOT(slotCustomiseFields()),actionCollection(), "customiseFields");
	customiseTypes = new KAction(i18n("Customise Reference Types"), 0, 0, this, SLOT(slotCustomiseTypes()),actionCollection(), "customiseTypes");
    
	setFieldValue = new KAction(i18n("Set Field Content"), 0, 0, this, SLOT(slotSetFieldValue()),actionCollection(), "setFieldValue");
	replaceString = new KAction(i18n("Replace String"), 0, 0, this, SLOT(slotReplaceString()),actionCollection(), "replaceString");
	copyFieldContent = new KAction(i18n("Copy Field Content"), 0, 0, this, SLOT(slotCopyFieldContent()),actionCollection(), "copyFieldContent");
	
    createBibliography = new KAction(i18n("Create LateX Bibliography "), "bibtex", 0, this, SLOT(slotCreateBibliography()),actionCollection(), "createBibliography");

    saveSelected = new KAction(i18n("Save Selected References into A New File"), 0, 0, this, SLOT(slotSaveSelected()),actionCollection(), "saveSelected");

    viewBibSource = new KAction(i18n("View BibTeX File"), "view_text", CTRL+Key_B, this, SLOT(slotViewBibSource()),actionCollection(), "viewBibSource");
    createKeys = new KAction(i18n("Create Citation Keys"), 0, CTRL+Key_K, this, SLOT(slotCreateKeys()),actionCollection(), "createKeys");
    refCheckKey = new KAction(i18n("Check for Duplicated Citation Keys"), 0, 0, this, SLOT(slotCheckKeys()),actionCollection(), "checkKeys");
    lockKeys = new KAction(i18n("Lock All Citation Keys"), "lock", CTRL+Key_L, this, SLOT(slotLockKeys()),actionCollection(), "lockKeys");
    unLockKeys = new KAction(i18n("Unlock All Citation Keys"), "unlock", CTRL+Key_U, this, SLOT(slotunLockKeys()),actionCollection(), "unLockKeys");
    sortReference = new KAction(i18n("Sort References"), "sort", 0, this, SLOT(slotSortReference()),actionCollection(), "sortRef");

    removeDuplicated = new KAction(i18n("Remove Duplicated References"), 0, 0, this, SLOT(slotRemoveDuplicated()),actionCollection(), "removeDuplicated");

    showDuplicated = new KAction(i18n("Show Duplicated References"), 0, 0, this, SLOT(slotShowDuplicated()),actionCollection(), "showDuplicated");

	internetSearch = new KAction(i18n("Search Remote Databases"), "network", 0, this, SLOT(slotInternetSearch()),actionCollection(), "internetSearch");
	
    viewAll = new KAction(i18n("View All References"), 0, ALT+Key_A, this, SLOT(slotViewAll()),actionCollection(), "viewAll");

    viewSelected = new KAction(i18n("View Selected References"), 0, 0, this, SLOT(slotViewSelected()),actionCollection(), "viewSelected");
    hideSelected = new KAction(i18n("Hide Selected References"), 0, 0, this, SLOT(slotHideSelected()),actionCollection(), "hideSelected");

    viewByRefType = new KAction(i18n("View by Reference Type"), 0, 0, this, SLOT(slotViewByRefType()),actionCollection(), "viewByRefType");

    //  fileImport = new KAction(i18n("Import Endnote BibTex File"), 0, 0, this, SLOT(slotFileImport()),actionCollection(), "import");
    fileExportEndnote = new KAction(i18n("Export to Endnote File"), 0, 0, this, SLOT(slotFileExportEndnote()),actionCollection(), "exportEndnote");
    fileExportRIS = new KAction(i18n("Export to RIS File"), 0, 0, this, SLOT(slotFileExportRIS()),actionCollection(), "exportRIS");
    fileExportMODS = new KAction(i18n("Export to MODS XML File"), 0, 0, this, SLOT(slotFileExportMODSXML()),actionCollection(), "exportMODS");
    fileExportHTML = new KAction(i18n("Export to HTML File"), 0, 0, this, SLOT(slotFileExportHTML()),actionCollection(), "exportHTML");


    fileNew = KStdAction::openNew(this, SLOT(slotFileNew()), actionCollection());
    fileOpen = KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
    m_fileOpenRecent = KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)),
                       actionCollection());
    fileSave = KStdAction::save(this, SLOT(slotFileSave()), actionCollection());
    fileSaveAs = KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
    //  fileClose = KStdAction::close(this, SLOT(slotFileClose()), actionCollection());
    //filePrint = KStdAction::print(this, SLOT(slotFilePrint()), actionCollection());
    fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
    //  fileReload = new KAction(i18n("Reload"), 0, 0, this, SLOT(slotFileReload()),actionCollection(), "reload");
    fileReload =  KStdAction::revert(this, SLOT(slotFileReload()), actionCollection());
    editCopy = KStdAction::copy(this, SLOT(slotEditCopy()), actionCollection());
    editCopyFormated = new KAction(i18n("Copy as Formated References"), 0, CTRL+SHIFT+Key_C, this, SLOT(slotEditCopyFormated()),actionCollection(), "copyFormated");
    editPaste = KStdAction::paste(this, SLOT(slotEditPaste()), actionCollection());
    editCut = KStdAction::cut(this, SLOT(slotEditCut()), actionCollection());
    editSelecAll = KStdAction::selectAll(this, SLOT(slotEditSelectAll()), actionCollection());
    editDeSelectAll = KStdAction::deselect(this, SLOT(slotEditDeSelectAll()), actionCollection(), "editDeSelectAll");
    editInvertSelection = new KAction(i18n("Invert Selection"), 0, 0, this, SLOT(slotEditInvertSelection()),actionCollection(), "editInvertSelection");

    editFind = KStdAction::find(this, SLOT(slotEditFind()), actionCollection());
    editFindNext = KStdAction::findNext(this, SLOT(slotEditFindNext()), actionCollection());
    viewToolBar = KStdAction::showToolbar(this, SLOT(slotViewToolBar()), actionCollection());
    viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection());

    KStdAction::configureToolbars(this, SLOT(slotConfigToolbar()), actionCollection());
    KStdAction::keyBindings(this, SLOT(slotConfigKeys()), actionCollection());

    KStdAction::preferences(this, SLOT(slotConfig()), actionCollection());

    fileNewWindow->setStatusText(i18n("Opens a new application window"));
    fileNew->setStatusText(i18n("Creates a new document"));
    fileOpen->setStatusText(i18n("Opens an existing document"));
    //fileOpenRecent->setStatusText(i18n("Opens a recently used file"));
    fileSave->setStatusText(i18n("Saves the actual document"));
    fileSaveAs->setStatusText(i18n("Saves the actual document as..."));
    //filePrint ->setStatusText(i18n("Prints out the actual document"));
    fileQuit->setStatusText(i18n("Quits the application"));
    viewToolBar->setStatusText(i18n("Enables/disables the toolbar"));
    editSelecAll->setStatusText(i18n("Select all entries"));
    editDeSelectAll->setStatusText(i18n("Clear entry selection"));

    viewStatusBar->setStatusText(i18n("Enables/disables the statusbar"));
    newEntry->setStatusText(i18n("Insert new BibTeX References"));
    deleteEntry->setStatusText(i18n("Delete selected BibTeX References"));
    citeEntry->setStatusText(i18n("Cite selected BibTeX References"));
    viewBibSource->setStatusText(i18n("View BibTeX source file"));



    /*Filter*/
    (void) new KAction(i18n("Filter"), CTRL + Key_F, this, SLOT(slotFilterLabelActivated()),
                     actionCollection(), "quick_filter_accel");
  (void) new KAction(i18n("Clear Filter"), QString::fromLatin1("locationbar_erase"), 0,
                     this, SLOT(slotClearFilter()),
                     actionCollection(), "quick_filter_clear");

  m_quickFilter = new KLineEdit();
  m_quickFilter->setFixedWidth(m_quickFilter->fontMetrics().maxWidth()*10);
  // want to update every time the filter text changes
  connect(m_quickFilter, SIGNAL(textChanged(const QString&)),
          this, SLOT(slotQueueFilter()));
  KWidgetAction* wAction = new KWidgetAction(m_quickFilter, i18n("Filter"), 0, 0, 0,
                                             actionCollection(), "quick_filter");
  wAction->setToolTip(i18n("Filter the collection"));
  wAction->setShortcutConfigurable(false);
  wAction->setAutoSized(true);

  m_attributes = new KComboBox();
  connect(m_attributes, SIGNAL(activated(int) ), this, SLOT(slotFilterAttributeChanged() ));
  wAction = new KWidgetAction(m_attributes, i18n("Filter attribute"), 0, 0, 0,
                                             actionCollection(), "filter_attribute");
  wAction->setToolTip(i18n("Limit the filter to field"));
  wAction->setShortcutConfigurable(false);
  wAction->setAutoSized(false);


}


void KBibApp::initStatusBar()
{
    statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG);
    statusBar()->setItemAlignment( ID_STATUS_MSG, AlignLeft|AlignVCenter );
    statusBar()->insertItem(i18n("Total 0 reference"), ID_STATUS_NOREF, 1);
    statusBar()->setItemAlignment( ID_STATUS_NOREF, AlignRight|AlignVCenter );
}

void KBibApp::createEntryDefs()
{
    //entryDefTab = new BibEntryDefTable();
	
	
	bool found = false;
	QString entryDefFile = locateLocal( "data", "kbib/entryDefs.xml" );

    if( ! QFile::exists(entryDefFile) )
    {
        entryDefFile = locate( "data", "kbib/entryDefs.xml" );
        if( ! QFile::exists( entryDefFile ) )
            cerr<<"File: entryDefs.xml doesn't exist!\n";
        else
        {
            found = true;
        }
    }
    else
        found = true;
		
	if (found){
		cerr<<"entryDefs.xml file: " << entryDefFile.ascii() << "\n";
		BibEntryDefTable::self()->readEntryDefFile(	entryDefFile );
	}
	
	
	else{
		BibEntryDefTable::self()->newEntryDef(QString::fromLatin1("other"), QStringList(), QStringList(), true, true);	
		KMessageBox::error( this,i18n("The reference type definition file entryDefs.xml could not be found. Please check your KBib installation."));
		
		
	}

}

void KBibApp::initDocument()
{



    doc = new KBibDoc(this);

}

void KBibApp::initView()
{
    ////////////////////////////////////////////////////////////////////
    // create the main widget here that is managed by KTMainWindow's view-region and
    // connect the widget to your document to display document contents.

    setCaption((doc->getURL()).fileName(),false);

    QSplitter* mbox = new QSplitter(this);
    mbox->setOrientation(Horizontal);


    grpViewBox = new QGroupBox(mbox);
    groupViewSelect = new QComboBox(grpViewBox, "Groupviewselect");
	
	setGroupByList();
	
    group_view = new KBibGroupView(grpViewBox, "Groupview", groupViewSelect->currentText());
    QLabel *grplb = new QLabel(i18n("Group by "), grpViewBox);
    QVBoxLayout *grpLayout = new QVBoxLayout(grpViewBox);
    QHBoxLayout *grpLayoutTop = new QHBoxLayout(grpViewBox);
    grpLayoutTop->setMargin(10);
    grpLayoutTop->setSpacing(20);
    grpLayoutTop->addWidget(grplb);
    grpLayoutTop->addWidget(groupViewSelect);
    grpLayoutTop->setStretchFactor(grplb, 0);
    grpLayoutTop->setStretchFactor(groupViewSelect, 1);
    grpLayout->addLayout(grpLayoutTop);
    grpLayout->addWidget(group_view);


    QSplitter* vbox = new QSplitter(mbox);
    vbox->setOrientation(Vertical);
    
	m_view = new KBibListView( vbox, "m_view" );
	
    QHBox * l = new QHBox(vbox);
	vbox->setCollapsible(l, false);
    previewBtn = new KPushButton(i18n("Hide Preview"), l);
    l->setFixedHeight(l->sizeHint().height());
    l->setStretchFactor(previewBtn, 0);
    QWidget *dummy = new QWidget(l);
	l->setStretchFactor(dummy, 1);

    p_preview = new KBibPreview(vbox);


    setCentralWidget(mbox);
    doc->addListView(m_view);
    doc->addGroupView(group_view);
    m_view->addPreview(p_preview);
    slotStatusMsg(i18n("Ready"));

    group_view->addPreview( p_preview );
    connect( groupViewSelect, SIGNAL( activated (int) ), this, SLOT( slotGroupByChange() ) );
}

void KBibApp::setGroupByList(){
	groupViewSelect->clear();
    groupViewSelect->insertItem("Reference type");
	
	QStringList fieldNameTab = BibEntryDefTable::self()->getFieldNames();
	for (QStringList::Iterator it = fieldNameTab.begin(); it != fieldNameTab.end(); ++it){
		RefField *field = BibEntryDefTable::self()->getRefField(*it);
		if (field->allowGrouping){
			QString fn = field->name;
			QChar c = fn.at(0); 
			fn = fn.replace(0, 1, c.upper());
			groupViewSelect->insertItem(fn);
		}
	}
	
	
    groupViewSelect->setCurrentItem(0);
}

KBibDoc *KBibApp::getDocument() const
{
    return doc;
}

void KBibApp::saveOptions()
{
    config->setGroup( "Font" );
    config->writeEntry("Font",kbibConfigState.font);

    config->setGroup("General Options");
    config->writeEntry("Field Delimiter", kbibConfigState.fieldDelimiter);
    config->writeEntry("Ask Empty Required Field", kbibConfigState.askReqField);
    config->writeEntry("Auto Field Completion", kbibConfigState.autocompletion);

    config->writeEntry("Startup Action", kbibConfigState.startupAction);
    config->writeEntry("Cite Action", kbibConfigState.citeAction);
    config->writeEntry("Text Viewer", kbibConfigState.textViewer);
    config->writeEntry("Web Browser", kbibConfigState.browser);
    config->writeEntry("Compare references", kbibConfigState.compareRefSetting);
    config->writeEntry("Citation Key Connecting String", kbibConfigState.keyConnecting);
//	config->writeEntry("Encoding", kbibConfigState.encoding);
    config->writeEntry("Show Group View", !groupViewVisible);
    config->writeEntry("Show Preview", !previewVisible);

    config->writeEntry("First Run KBib 0.5.4", firstRun);
    config->writeEntry("Geometry", size());
    config->writeEntry("Show Toolbar", viewToolBar->isChecked());
    config->writeEntry("Show Statusbar",viewStatusBar->isChecked());
    //config->writeEntry("ToolBarPos", (int) toolBar("mainToolBar")->barPos());
    config->writeEntry("Preview Mode", previewMode);

    config->writeEntry("Display Fields", kbibConfigState.displayFields, ',');
    config->writeEntry("Display Authors", kbibConfigState.authorDisplaySetting);


    (kbibConfigState.displayFieldsSize).clear();
    for (int i = 0; i < m_view->columns(); i++)
    {
        kbibConfigState.displayFieldsSize += m_view->columnWidth(i);
    }
    config->writeEntry("Display Fields Size", kbibConfigState.displayFieldsSize, ',');
    config->setGroup( "Files" );
    m_fileOpenRecent->saveEntries(config, "Recent Files");
    if ((doc->getURL()).fileName() != QString(i18n("Untitled")))
    {
        config->writeEntry("Last File", (doc->getURL()).url());
    }


	//Global string macros
	config->setGroup( "Global String Macros" );
	int count = kbibConfigState.globalStringMacros.count();
	config->writeEntry("Global String Macros Count", count);
	count = 1;
	for(QMap<QString, QString>::ConstIterator it = kbibConfigState.globalStringMacros.begin(); it != kbibConfigState.globalStringMacros.end(); ++it){
		QString group = QString::fromLatin1("Global String Macros %1").arg(count);
		config->setGroup(group);
		config->writeEntry("Key", it.key());
		config->writeEntry("Value", it.data());	
		count++;
	}

    //  fileOpenRecent->saveEntries(config,"Recent Files");
}


void KBibApp::readOptions()
{

    config->setGroup( "Font" );

//    kbibConfigState.font = config->readFontEntry("Font",
//                           new QFont("sans",9,QFont::Normal));
	kbibConfigState.font = config->readFontEntry("Font",
                           &(this->font()));
	
    config->setGroup("General Options");
    kbibConfigState.fieldDelimiter = config->readNumEntry("Field Delimiter", 0);
    kbibConfigState.askReqField = config->readBoolEntry("Ask Empty Required Field", true);
    kbibConfigState.autocompletion = config->readBoolEntry("Auto Field Completion", true);
    kbibConfigState.startupAction=config->readNumEntry("Startup Action", 2);
    kbibConfigState.citeAction=config->readNumEntry("Cite Action", 1);
    kbibConfigState.textViewer = config->readEntry("Text Viewer","kwrite");
    kbibConfigState.browser = config->readEntry("Web Browser","konqueror");
    kbibConfigState.compareRefSetting = config->readNumEntry("Compare references",1);
    kbibConfigState.keyConnecting = config->readEntry("Citation Key Connecting String","");
//	kbibConfigState.encoding = config->readEntry("Encoding", QString::fromLatin1("utf8"));
    groupViewVisible = config->readBoolEntry("Show Group View", false);
    previewVisible = config->readBoolEntry("Show Preview", false);

    firstRun = config->readBoolEntry("First Run KBib 0.5.4", true);
    previewMode = config->readNumEntry("Preview Mode",1);
    previewModeSelect->setCurrentItem(previewMode);
    p_preview->updatePreview();
    // bar status settings
    kbibConfigState.displayFields = config->readListEntry("Display Fields");
    kbibConfigState.authorDisplaySetting = config->readNumEntry("Display Authors", 2);

    if((kbibConfigState.displayFields).isEmpty())
    {
        kbibConfigState.displayFields = defaultDisplayFields();
    }

    kbibConfigState.displayFieldsSize = config->readIntListEntry("Display Fields Size");

    if((kbibConfigState.displayFieldsSize).isEmpty())
    {
        kbibConfigState.displayFieldsSize = defaultDisplayFieldsSize();
    }

    kbibConfigState.displayFieldsChanged = FALSE;

    bool bViewToolbar = config->readBoolEntry("Show Toolbar", true);
    viewToolBar->setChecked(bViewToolbar);
    slotViewToolBar();

    bool bViewStatusbar = config->readBoolEntry("Show Statusbar", true);
    viewStatusBar->setChecked(bViewStatusbar);
    slotViewStatusBar();



    QSize size=config->readSizeEntry("Geometry");
    if(!size.isEmpty())
    {
        resize(size);
    }


    config->setGroup( "Files" );
    m_fileOpenRecent->loadEntries(config, "Recent Files");
    lastFile=config->readEntry("Last File","");
	
	//Global string macros
	kbibConfigState.globalStringMacros.clear();
	config->setGroup( "Global String Macros" );
	int count = config->readNumEntry("Global String Macros Count", 0);
	
	for (int i = 1; i <= count ; i++){
		QString group = QString::fromLatin1("Global String Macros %1").arg(i);
		config->setGroup(group);
		QString key = config->readEntry("Key");
		QString value = config->readEntry("Value");
		kbibConfigState.globalStringMacros.insert(key, value); 
		
	}
}

void KBibApp::startup()
{
    switch(kbibConfigState.startupAction)
    {
    case 0:
        break;
    case 1:
        openDocument(lastFile);
        break;
    default:
        startKbib();
        break;
    }
}

void KBibApp::saveProperties(KConfig *_cfg)
{
    if( (doc->getURL()).fileName()!=i18n("Untitled") && !doc->isModified())
    {
        // saving to tempfile not necessary

    }
    else
    {
        KURL url = doc->getURL();
        _cfg->writeEntry("filename", url.url());
        _cfg->writeEntry("modified", doc->isModified());
        QString tempname = kapp->tempSaveName(url.url());
        doc->saveDocument(url);
    }
}


void KBibApp::readProperties(KConfig* _cfg)
{
    QString filename = _cfg->readEntry("filename", "");
    KURL url(filename);
    bool modified = _cfg->readBoolEntry("modified", false);
    if(modified)
    {
        bool canRecover;
        QString tempname = kapp->checkRecoverFile(filename, canRecover);

        if(canRecover)
        {
            doc->openDocument(tempname);
            doc->setModified();
            setCaption((doc->getURL()).fileName(),true);
            QFile::remove
                (tempname);
        }
    }
    else
    {
        if(!filename.isEmpty())
        {
            doc->openDocument(url);
            setCaption((doc->getURL()).fileName(),false);
        }
    }
}

bool KBibApp::queryClose()
{
    return doc->saveModified();
}

bool KBibApp::queryExit()
{
    //  cout << "\nQuiting...\n";
    saveOptions();
    return true;
}

/////////////////////////////////////////////////////////////////////
// SLOT IMPLEMENTATION
/////////////////////////////////////////////////////////////////////

void KBibApp::slotFileNewWindow()
{
    slotStatusMsg(i18n("Opening a new application window..."));

    KBibApp *new_window= new KBibApp();
    new_window->show();

    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotFileNew()
{

    slotStatusMsg(i18n("Creating new document..."));

    if(!doc->saveModified())
    {
        // here saving wasn't successful

    }
    else
    {
        doc->newDocument();
        setCaption((doc->getURL()).fileName(),false);
        p_preview->setText("");
        p_preview->setBibEntry(0);
        fileSave->setEnabled(false);
        fileReload->setEnabled(false);

        createKeys->setEnabled(false);
        lockKeys->setEnabled(false);
        unLockKeys->setEnabled(false);
        refCheckKey->setEnabled(false);

        viewBibSource->setEnabled(false);
        sortReference->setEnabled(false);
        //createBibliography->setEnabled(false);
		setFieldValue->setEnabled(false);
		copyFieldContent->setEnabled(false);
		replaceString->setEnabled(false);
        slotNumRefMsg();
    }

    slotStatusMsg(i18n("Ready"));

}


void KBibApp::slotFileOpenRecent(const KURL& url_)
{
    slotStatusMsg(i18n("Opening file..."));

    if(doc->saveModified())
    {
        bool success = openDocument(url_);
        if(!success)
        {
            m_fileOpenRecent->removeURL(url_);
        }
    }

    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotFileOpen()
{
    slotStatusMsg(i18n("Opening file..."));

    if(!doc->saveModified())
    {
        // here saving wasn't successful

    }
    else
    {

        QString filter = i18n("*.bib|BibTeX files (*.bib)");
        filter += QString::fromLatin1("\n");
        filter += i18n("*|All files");


        KURL url = KFileDialog::getOpenURL(QString::fromLatin1(":open"), filter,
                                           this, i18n("Open File..."));
        if (!url.isEmpty())
        {
            //doc->openDocument(fn, false);
            if(openDocument(url))
            {
                m_fileOpenRecent->addURL(url);
                setCaption((doc->getURL()).fileName(), false);
                fileSave->setEnabled(false);
                p_preview->clear();
                p_preview->setBibEntry(0);
                slotNumRefMsg();
                if (doc->size() > 0)
                {
                    createKeys->setEnabled(true);
                    lockKeys->setEnabled(true);
                    unLockKeys->setEnabled(true);
                    refCheckKey->setEnabled(true);
					setFieldValue->setEnabled(true);
					copyFieldContent->setEnabled(true);
					replaceString->setEnabled(true);
                }
                viewBibSource->setEnabled(true);
                sortReference->setEnabled(true);
                //createBibliography->setEnabled(true);
            }
        }

    }


    slotStatusMsg(i18n("Ready"));
}


void KBibApp::slotFileSave()
{
    slotStatusMsg(i18n("Saving file..."));
    if ((doc->getURL()).fileName()!=i18n("Untitled"))
    {
        doc->saveDocument(doc->getURL());
        fileSave->setEnabled(false);
        fileReload->setEnabled(false);
    }
    else
        slotFileSaveAs();
    slotStatusMsg(i18n("Ready"));
    setCaption((doc->getURL()).fileName(),doc->isModified());
}

void KBibApp::slotFileSaveAs()
{
    slotStatusMsg(i18n("Saving file with a new filename..."));

    int query=KMessageBox::Yes;

    KURL url=KFileDialog::getSaveURL(QDir::currentDirPath(),
                                     i18n("*.bib|BibTeX Files (*.bib)\n*|All files"), this, i18n("Save as..."));
    if(!url.isEmpty())
    {
        if(KIO::NetAccess::exists(url, false, this))

            query = KMessageBox::warningYesNoCancel( this,i18n("A file named \"%1\" already exists. "
                    "Are you sure you want to overwrite it?").arg(url.fileName()) );
        if (query==KMessageBox::Yes)
        {
            doc->saveDocument(url);
            setCaption((doc->getURL()).fileName(),doc->isModified());
            fileSave->setEnabled(false);
            fileReload->setEnabled(false);
            viewBibSource->setEnabled(true);
        }
    }
    slotStatusMsg(i18n("Ready"));
}

/*
void KBibApp::slotFilePrint()
{
        slotStatusMsg(i18n("Printing..."));
 
        QPrinter printer;
        if (printer.setup(this)) {
                //    m_view->print(&printer);
        }
 
        slotStatusMsg(i18n("Ready"));
 
 
        
          slotStatusMsg(i18n("Printing..."));
          KPrinter printer;
          QString finame;
          finame=doc->getFileName();
          if (finame=="Untitled" || finame=="")
          {
              KMessageBox::error( this,i18n("Could not start the command."));
              return;
          }
        //Do we need to save the file first?
            QFileInfo fic(finame);
            if (fic.exists() && fic.isReadable() )
            {
              if ( printer.setup(this) )
              {
                 QSize margins = printer.margins();
                 int marginHeight = margins.height();
                 QPainter p;
                 if( !p.begin( &printer ) )  return;
                 int yPos        = 0;
         //        p.setFont( EditorFont );
                 QFontMetrics fm = p.fontMetrics();
                 QPaintDeviceMetrics metrics( &printer );
                 QFile f( finame );
                 if ( !f.open( IO_ReadOnly ) ) return;
                 QTextStream t(&f);
                 while ( !t.eof() )
                 {
                     QString s = t.readLine();
                     if ( marginHeight + yPos > metrics.height() - marginHeight )
                     {
                       printer.newPage();
                       yPos = 0;
                     }
                     p.drawText( marginHeight, marginHeight + yPos,metrics.width(), fm.lineSpacing(),ExpandTabs,s );
                     yPos = yPos + fm.lineSpacing();
                 }
                 f.close();
                 p.end();
               }
            }
         
          slotStatusMsg(i18n("Ready"));
        
}*/

void KBibApp::slotFileQuit()
{
    slotStatusMsg(i18n("Exiting..."));
    saveOptions();
	
    if (queryClose())
        qApp->quit();
}


void KBibApp::slotViewToolBar()
{
    slotStatusMsg(i18n("Toggling toolbar..."));
    ///////////////////////////////////////////////////////////////////
    // turn Toolbar on or off
    if(!viewToolBar->isChecked())
    {
        toolBar("mainToolBar")->hide();
    }
    else
    {
        toolBar("mainToolBar")->show();
    }

    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotViewStatusBar()
{
    slotStatusMsg(i18n("Toggle the statusbar..."));
    ///////////////////////////////////////////////////////////////////
    //turn Statusbar on or off
    if(!viewStatusBar->isChecked())
    {
        statusBar()->hide();
    }
    else
    {
        statusBar()->show();
    }

    slotStatusMsg(i18n("Ready"));
}


void KBibApp::slotStatusMsg(const QString &text)
{
    ///////////////////////////////////////////////////////////////////
    // change status message permanently
    statusBar()->clear();
    statusBar()->changeItem(text, ID_STATUS_MSG);
}


QString KBibApp::cite()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return 0;
    if (list)
    {
        bool first = true;
        QString citest;
        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );
            if (entry)
            {
                if(!first)
                {
                    citest.append(",");
                }
                citest.append(entry->getKey());
                first = false;
            }
        }

        if (!citest.isEmpty())
        {
            QString citeSt = QString("\\cite{")+citest+QString("}");
            return citeSt;
        }
        else
            return 0;
        delete list;
    }
    else
        return 0;
}


bool KBibApp::openDocument(KURL url)
{
    bool open = doc->openDocument(url, false);
    if (open)
    {
        setCaption((doc->getURL()).fileName(), doc->isModified());
        fileSave->setEnabled(false);
        fileReload->setEnabled(false);
        p_preview->clear();
        p_preview->setBibEntry(0);
        slotNumRefMsg();
        if (doc->size() > 0)
        {
            createKeys->setEnabled(true);
            lockKeys->setEnabled(true);
            unLockKeys->setEnabled(true);
            refCheckKey->setEnabled(true);
            sortReference->setEnabled(true);
			setFieldValue->setEnabled(true);
			copyFieldContent->setEnabled(true);
			replaceString->setEnabled(true);
            //createBibliography->setEnabled(true);
        }
        viewBibSource->setEnabled(true);

        return open;
    }
    else
    {
        KMessageBox::error(this, i18n("Could not open BibTeX file.") );
        return open;

    }

}



void KBibApp::slotNewEntry()
{
    slotStatusMsg(i18n("New reference..."));
    //  	m_view->slotNewItem();
    if (doc->newEntry())
    {
//      m_view->slotSelectionChanged();
        slotSelectionChanged();
        slotNumRefMsg();
    }
    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotInsertFile()
{
    int numInserted=0;
    slotStatusMsg(i18n("Importing file..."));

    KbibInsertFileDlg* insertDlg = new KbibInsertFileDlg(this);
    if (insertDlg->exec()==QDialog::Accepted)
    {
        QString fn = insertDlg->getFileName();
        int fileType = insertDlg->getFileType();
        bool notInsertExisting = insertDlg->getNotInsertExisting();
		bool importIntoNewDoc = insertDlg->importIntoNewDoc();
		 
		if (importIntoNewDoc){
			slotFileNew();
			numInserted = insertFile(fn, fileType, notInsertExisting);	
			
		}
		
		else{
		
	        numInserted = insertFile(fn, fileType, notInsertExisting);
		}    
		QString msg;
        msg.setNum(numInserted);
        if (numInserted > 1)
			msg = i18n("%1 references were imported").arg(numInserted);
        else
            msg = i18n("%1 reference was imported").arg(numInserted);
        KMessageBox::information(this, msg );
		

    }

    delete insertDlg;

    slotStatusMsg(i18n("Ready"));
}

int KBibApp::insertFile(QString url_, int fileType, bool notInsertExisting)
{
    KURL url = KURL(url_);
	KTempFile tmpfile;
    tmpfile.setAutoDelete(TRUE);
    QString fn = tmpfile.name();
    //	cerr << "File name " << (url.url()).ascii();
    if(!KIO::NetAccess::download(url, fn, this))
    {
        QString str;
        if(url.isLocalFile())
        {
            str = i18n("Kbib is unable to find the file - %1.").arg(url.fileName());
        }
        else
        {
            str = i18n("Kbib is unable to download the file - %1.").arg(url.url());
        }
        KMessageBox::sorry(this, str);

        return 0;

    }

    int numInserted = 0;
    QString cmd;
    switch(fileType)
    {
    case 1:
        numInserted = doc->importBibTexFile(fn.ascii(), true, notInsertExisting);
        break;

    case 2:
        end2xml(const_cast<char*>(fn.ascii()), "/tmp/kbib-tmp.xml");
        xml2bib("/tmp/kbib-tmp.xml", "/tmp/kbib-tmp.bib");
        numInserted = doc->importBibTexFile("/tmp/kbib-tmp.bib", false, notInsertExisting);
        system("rm /tmp/kbib-tmp.xml /tmp/kbib-tmp.bib");
        break;
		
    case 3:
        ris2xml(const_cast<char*>(fn.ascii()), "/tmp/kbib-tmp.xml");
        xml2bib("/tmp/kbib-tmp.xml", "/tmp/kbib-tmp.bib");
        numInserted = doc->importBibTexFile("/tmp/kbib-tmp.bib", false, notInsertExisting);
        system("rm /tmp/kbib-tmp.xml /tmp/kbib-tmp.bib");
        break;

    case 4:
        isi2xml(const_cast<char*>(fn.ascii()), "/tmp/kbib-tmp.xml");
        xml2bib("/tmp/kbib-tmp.xml", "/tmp/kbib-tmp.bib");
        numInserted = doc->importBibTexFile("/tmp/kbib-tmp.bib", false, notInsertExisting);
        system("rm /tmp/kbib-tmp.xml /tmp/kbib-tmp.bib");
        break;

    case 5:
        med2xml(const_cast<char*>(fn.ascii()), "/tmp/kbib-tmp.xml");
        xml2bib("/tmp/kbib-tmp.xml", "/tmp/kbib-tmp.bib");
        numInserted = doc->importBibTexFile("/tmp/kbib-tmp.bib", false, notInsertExisting);
        system("rm /tmp/kbib-tmp.xml /tmp/kbib-tmp.bib");
        break;

    case 6:
        copac2xml(const_cast<char*>(fn.ascii()), "/tmp/kbib-tmp.xml");
        xml2bib("/tmp/kbib-tmp.xml", "/tmp/kbib-tmp.bib");
        numInserted = doc->importBibTexFile("/tmp/kbib-tmp.bib", false, notInsertExisting);
        system("rm /tmp/kbib-tmp.xml /tmp/kbib-tmp.bib");
        break;

    case 7:
        xml2bib(const_cast<char*>(fn.ascii()), "/tmp/kbib-tmp.bib");
        numInserted = doc->importBibTexFile("/tmp/kbib-tmp.bib", false, notInsertExisting);
        system("rm /tmp/kbib-tmp.bib");
        break;

    default:
        numInserted = doc->importBibTexFile(fn.ascii(),false, notInsertExisting);
        break;
    }
    return numInserted;


}

void KBibApp::slotDeleteEntry()
{
    //m_view->slotHandleDelete();
    if (KMessageBox::warningYesNo(this, i18n("Are you sure to delete the selected entries?"),i18n("Warning")) == KMessageBox::Yes)
    {
        vector<int> *list=0;
        if (currentSelectedView == 2)
            list = m_view->deleteSelected();
        else if(currentSelectedView == 1)
        {
            QListViewItem *item_ = group_view->selectedItem();
            if (item_)
            {
                KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
                if (item)
                {
                    BibEntry *entry = item->getBibEntry();

                    list = new vector<int>;
                    int index = entry->getIndex();
                    m_view->deleteEntry(index);
                    list->push_back(index);


                }
            }
        }
        else
            return;
        if (list)
        {
            int numDeleted = doc->deleteEntry(list);
            delete list;
            if (numDeleted)
            {
                //if(currentSelectedView == 1)
                //	m_view->updateListView(doc->getEntryList( ));
                p_preview->setBibEntry(0);
                p_preview->clear();
                slotSelectionChanged();
            }
        }
    }
}

void KBibApp::slotCiteEntry()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        bool first = true;
        QString citest;
        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );
            if(!first)
            {
                citest.append(",");
            }
            citest.append(entry->getKey());
            first = false;
        }

        if (!citest.isEmpty())
        {
            int citeAction = kbibConfigState.citeAction;
			if (citeAction == 0){
				DCOPClient *client = kapp->dcopClient();
				client->send( "kile", "Kile", "insertText(QString)", "\\cite{"+citest+"}");	
				
			}
			
			
            else if (citeAction == 1)
            {
                QString home(getenv("HOME"));
                QString pipe_in_file = home+"/.lyxpipe.in";

                QString errorStr = i18n("<qt>Kbib is unable to write to the server pipe at <b>%1</b>.</qt>").arg(pipe_in_file );
                QCString pipe = QFile::encodeName(pipe_in_file);
                if(!QFile::exists(pipe_in_file))
                {
                    KMessageBox::sorry(this, errorStr);
                }
                else
                {
                    ofstream pipe_in(pipe_in_file.ascii());
                    if (pipe_in)
                    {
                        pipe_in << "LYXCMD:kbib:citation-insert:"<<citest.ascii()<<"\n";
                    }
                    pipe_in.close();
                }
            }

            else
            {
                QClipboard *cb = QApplication::clipboard();
                cb->setText("\\cite{"+citest+"}");
            }
        }

        delete list;
    }
}

void KBibApp::slotEditSelectAll()
{
    m_view->selectAll(true);

}

void KBibApp::slotEditDeSelectAll()
{
    group_view->clearSelection();
    m_view->clearSelection();
    currentSelectedView = 0;
}

void KBibApp::slotShowPreview()
{
    if(previewVisible)
    {
        p_preview->hide();
        previewVisible=false;
        showPreview->setText(i18n("Show Preview"));
        previewBtn->setText(i18n("Show Preview"));
    }
    else
    {
        p_preview->show();
        previewVisible=true;
        showPreview->setText(i18n("Hide Preview"));
        previewBtn->setText(i18n("Hide Preview"));
    }
}

void KBibApp::slotShowGroupView()
{
    if(groupViewVisible)
    {
        grpViewBox->hide();
        groupViewVisible=false;
        showGroupView->setText(i18n("Show Group View"));
    }
    else
    {
		group_view->createGroupView();
        grpViewBox->show();
        groupViewVisible=true;
        showGroupView->setText(i18n("Hide Group View"));
    }
}

void KBibApp::slotViewBibSource()
{
    KURL url = doc->getURL();
    QString fn;
    KTempFile tmpfile(QString::null, ".bib");
    //tmpfile.setAutoDelete(TRUE);
    if( url.fileName()!=i18n("Untitled"))
    {
        if(url.isLocalFile())
        {
            fn = url.path();
        }
        else
        {
            fn = tmpfile.name();
            if(!KIO::NetAccess::download(url, fn, this))
            {
                KMessageBox::error(this, i18n("Could not download BibTeX source file.") );
                return;
            }
        }


        QFileInfo fic(fn);

        KShellProcess* proc = new KShellProcess("/bin/sh");
        proc->clearArguments();

        QString docdir=fic.dirPath();
        KRun::shellQuote(docdir);
        (*proc) << "cd " << docdir << "&&";
        (*proc) << (kbibConfigState.textViewer).ascii();
        (*proc) << " " << fn;
        if(!proc->start())
        {
            KMessageBox::error(this, i18n("Could not open BibTeX source file.") );
        }
    }
}


void KBibApp::slotDocChanged()
{
    doc->setModified(TRUE);
    fileSave->setEnabled(true);
    setCaption((doc->getURL()).fileName(),true);
    if ((doc->getURL()).fileName() != QString(i18n("Untitled")) )
    {
        fileReload->setEnabled(true);
    }
    if (doc->size() > 0)
    {
        createKeys->setEnabled(true);
        lockKeys->setEnabled(true);
        unLockKeys->setEnabled(true);
        refCheckKey->setEnabled(true);
        sortReference->setEnabled(true);
		setFieldValue->setEnabled(true);
		copyFieldContent->setEnabled(true);
		replaceString->setEnabled(true);
        //createBibliography->setEnabled(true);
    }
    else
    {
        createKeys->setEnabled(false);
        lockKeys->setEnabled(false);
        unLockKeys->setEnabled(false);
        refCheckKey->setEnabled(false);
        sortReference->setEnabled(false);
		setFieldValue->setEnabled(false);
		copyFieldContent->setEnabled(false);
		replaceString->setEnabled(false);

        //createBibliography->setEnabled(false);

    }


}

void KBibApp::slotSelectionChanged(void)
{
    if ( (m_view->selectedItems()).isEmpty() && !group_view->selectedItem())
    {
        editCopy->setEnabled(false);
        editCopyFormated->setEnabled(false);
        editCut->setEnabled(false);
        citeEntry->setEnabled(false);
        deleteEntry->setEnabled(false);
        saveSelected->setEnabled(false);
        createBibliography->setEnabled(false);
        viewSelected->setEnabled(false);
        hideSelected->setEnabled(false);
        p_preview->setBibEntry(0);
        p_preview->updatePreview();
    }
    else
    {
        editCopy->setEnabled(true);
        editCopyFormated->setEnabled(true);
        editCut->setEnabled(true);
        citeEntry->setEnabled(true);
        deleteEntry->setEnabled(true);
        saveSelected->setEnabled(true);
        createBibliography->setEnabled(true);
        viewSelected->setEnabled(true);
        hideSelected->setEnabled(true);
    }

}


void KBibApp::slotCreateKeys()
{
    slotStatusMsg(i18n("Creating keys..."));
    if (KMessageBox::warningYesNo( this,i18n( "All current unlocked citation keys will be replaced by new keys.\nDo you want to continue?" ) )
            ==KMessageBox::Yes)
    {

        doc->createKeys((kbibConfigState.keyConnecting).ascii());

    }
    slotStatusMsg(i18n("Ready"));
}



int KBibApp::searchKey(const char *s, int start)
{
    return doc->searchKey(s, start);
}

void KBibApp::slotNumRefMsg()
{
	QString st = i18n("Showing %1 out of total %2 references").arg(m_view->getListSize()).arg(doc->size());
    statusBar()->changeItem(st, ID_STATUS_NOREF);
}

void KBibApp::slotCheckKeys()
{
    int errorCount = 0;
    int fixedCount = 0;
    bool repeat = false;

    slotStatusMsg(i18n("Validate keys..."));
    BibEntry *entry;
    QString fn;

    KGuiItem buttonYes = KGuiItem(i18n("Let KBib fix it") );
    buttonYes.setText(i18n("Let KBib fix it") );

    KGuiItem buttonNo = KGuiItem(i18n("You fix it") );
    KGuiItem buttonCancel = KGuiItem(i18n("Ignore") );

    KLineEditDlg* editKeyDlg;
    bool modified = doc->isModified();

    for (int i = 0; i< doc->size(); i++)
    {
        //    progressDlg->repaint();
        entry = doc->getEntry(i);
        QString key = entry->getKey() ;
        QString msg, msg2;
        int idx;
        bool keyError = false;

        if (key.isEmpty())
        {
            msg = QString("<p>There is no key for ");
            msg.append("<B>");
            msg.append(entry->getField("author"));
            msg.append(", <I>");
            msg.append(entry->getField("title"));
            msg.append("</I>, ");
            msg.append(entry->getField("year"));
            msg.append("</B></p>");
            msg.append("<p>What do you want to do?</p>");
            keyError = true;
        }
        else
        {
            idx = doc->searchKey(entry->getKey() );
            if (idx != i)
                keyError = true;
            else
            {
                while (idx < (doc->size()-1))
                {
                    idx = doc->searchKey(entry->getKey(), idx+1);
                    if (idx > 0)
                    {
                        BibEntry *m_entry = doc->getEntry(idx);
                        fn = m_entry->getField("lockkey");
                        if (fn == QString::fromLatin1("Y"))
                        {
                            idx = doc->size();
                            keyError = true;
                        }

                    }
                    else
                        idx = doc->size();
                }
            }

            if (keyError)
            {
                msg = QString("<p>Key <B>");
                msg.append(entry->getKey());
                msg.append("</B> for ");
                msg.append("<B>");
                msg.append(entry->getField("author"));
                msg.append(", <I>");
                msg.append(entry->getField("title"));
                msg.append("</I>, ");
                msg.append(entry->getField("year"));
                msg.append("</B>");
                msg.append(" has been used by another reference.</p>");
                msg.append("<p>What do you want to do?</p>");
                keyError = true;
            }
        }
        if (keyError)
        {

            if (!repeat)
                errorCount++;
            repeat = false;

            //      int userRsp = KMessageBox::warningYesNoCancel (this, msg, i18n("Conflict key"), buttonYes, buttonNo);
            m_view->clearSelection();
            m_view->highlightItem(i);

            KBibCheckKeyDlg * checkKeyDlg = new KBibCheckKeyDlg(msg, this);
            checkKeyDlg->exec();
            int userRsp = checkKeyDlg->getUserCode();
            fn = entry->getField("lockkey");
            switch(userRsp)
            {
            case 0:
                i = doc->size();
                //          progressDlg->hide();
                break;
            case 1:
                if (fn == QString::fromLatin1("Y"))
                {
                    KMessageBox::error(this, i18n("Sorry! The citation key is locked.") );

                }
                else
                {
                    (doc->getEntryList())->createKey(i, kbibConfigState.keyConnecting);
                    modified = true;
                    fixedCount++;
                }
                break;
            case 2:
                if (fn == QString::fromLatin1("Y"))
                {
                    KMessageBox::error(this, i18n("Sorry! The citation key is locked.") );

                }
                else
                {
                    editKeyDlg = new KLineEditDlg(i18n("Please enter the key"), QString(key), this);
                    if (editKeyDlg->exec()==QDialog::Accepted)
                    {
                        QString st = editKeyDlg->text();
                        entry->setKey(st );
                        i--;
                        repeat = true;
                        modified = true;
                    }
                }
                break;
            case 3:
                break;

            default:
                break;

            }

        }
        else
        {
            if (repeat)
            {
                repeat = false;
                fixedCount++;
            }


        }
        //    progress->setProgress(i+1);

    }

    //  progressDlg->hide();
    //m_view->updateListView(doc->getEntryList());
    m_view->updateCurrentListView();
    doc->setModified(modified);
    QString finishMsg = QString(i18n("Finish validating the citation keys.\n"));
    QString numString;
    numString = numString.setNum(errorCount);
    finishMsg.append(numString);
    if (errorCount>1)
        finishMsg.append(" errors were found, ");
    else
        finishMsg.append(" error was found, ");
    numString = numString.setNum(fixedCount);
    finishMsg.append(numString);
    if (fixedCount>1)
        finishMsg.append(" were fixed.");
    else
        finishMsg.append(" was fixed.");

    KMessageBox::information (this, finishMsg);
    setCaption((doc->getURL()).fileName(), modified);
    fileSave->setEnabled(modified);
    fileReload->setEnabled(modified);
    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotEditCopy()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        QClipboard *cb = QApplication::clipboard();
        QString st;

        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );
            st = st + entryToString(entry, kbibConfigState.fieldDelimiter);
        }
        cb->setText(st);
        delete list;
    }
}


void KBibApp::slotEditCopyFormated()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        QClipboard *cb = QApplication::clipboard();
        QString st;

        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );
            st = st + doc->getEntryList()->formatEntry(entry, false);
            st = st + "\n\n";
        }
        cb->setText(st);
        delete list;
    }
}

void KBibApp::slotEditPaste()
{
    //m_view->slotPaste();

    QClipboard *cb = QApplication::clipboard();


    QString str = cb->text(QClipboard::Clipboard);
    doc->paste(str);
    slotSelectionChanged();
    group_view->clearSelection();
//    m_view->slotSelectionChanged();
}

void KBibApp::slotEditCut()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->deleteSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                m_view->deleteEntry(index);
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        QClipboard *cb = QApplication::clipboard();
        QString st;

        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );
            st = st + entryToString(entry, kbibConfigState.fieldDelimiter);
        }
        cb->setText(st);

        int numDeleted = doc->deleteEntry(list);
        delete list;
        if (numDeleted)
        {
            //if(currentSelectedView == 1)
            //	m_view->updateListView(doc->getEntryList( ));
            p_preview->setBibEntry(0);
            p_preview->clear();
            slotSelectionChanged();
        }
    }

}


void KBibApp::slotViewURL()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        vector<int>::iterator p;
        int i;

        for (p=list->begin(); p!=list->end(); p++)
        {
            bool run = true;
            i = *p;
            BibEntry *entry = doc->getEntry( i );

            QString st = entry->getField(QString::fromLatin1("url"));

            QString fn = QString(st).simplifyWhiteSpace();
            if (fn.isEmpty())
            {
                st = entry->getField(QString::fromLatin1("doi") );
                fn = st.simplifyWhiteSpace();
                if (fn.isEmpty())
                {
                    run = false;
                    KMessageBox::error(this, i18n("Neither URL nor DOC field is available.") );
                }
                else
                    fn = QString("http://dx.doi.org/")+fn;
            }
            if (run)
            {
                KProcess* proc = new KProcess;
                proc->clearArguments();
                (*proc) << ((this->kbibConfigState).browser);
                (*proc) << (KURL(fn)).prettyURL();

                //(*proc) << "kfmclient openProfile webbrowsing " << fn;
                if(!proc->start())
                {
                    KMessageBox::error(this, i18n("Could not open URL or DOI.") );
                }
            }
        }
        delete list;

    }

}


void KBibApp::slotViewFile()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );

            QString fn = entry->getField(QString::fromLatin1("file") );

            if (fn.isEmpty())
            {
                KMessageBox::error(this, i18n("File field is empty.") );
            }
            else
            {
                KProcess* proc = new KProcess;
                proc->clearArguments();

                (*proc) << "kfmclient";
                (*proc) << "exec";
                (*proc) << (KURL(fn)).prettyURL();
                if(!proc->start())
                {
                    KMessageBox::error(this, i18n("Could not open file.") );
                }
            }
        }
        delete list;
    }
}

void KBibApp::slotFileReload()
{
    slotStatusMsg(i18n("Reload..."));
    int query=KMessageBox::Yes;
    if (doc->isModified())
        query = KMessageBox::warningYesNo(this,i18n( "Unsaved changes will be discarded.\nDo you want to continue" ));
    if (query == KMessageBox::Yes)
    {
        doc->openDocument(doc->getURL(), false);
        setCaption((doc->getURL()).fileName(), false);
        slotNumRefMsg();
        fileSave->setEnabled(false);
        fileReload->setEnabled(false);
    }
    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotEditFind()
{
    m_view->clearSelection();
    if(!m_findDlg)
    {
        m_findDlg = new KBibFindDlg(this);
        //    m_editFindNext->setEnabled(true);
    }
    else
    {
        m_findDlg->updateAttributeList();
    }

    m_findDlg->show();


}

void KBibApp::slotEditFindNext()
{

    if(doc->size() < 1 )
    {
        return;
    }

    if(m_findDlg)
    {
        m_findDlg->slotFindNext();
    }
}


void KBibApp::slotEditInvertSelection()
{
    m_view->invertSelection();
}

int KBibApp::getPreviewMode()
{
    return previewMode;

}


void KBibApp::slotPreviewModeSelect()
{
    previewMode = previewModeSelect->currentItem();
    p_preview->updatePreview();
}


/*!
    \fn KBibApp::startKbib()
 */
void KBibApp::startKbib()
{
    //KBibStart *startDlg = new KBibStart(this);
    //startDlg->show();
    QString fn;
    KBibStart *startDlg = new KBibStart(this);
    if (startDlg->exec()==QDialog::Accepted)
    {
        //startDlg->show();
        //startDlg->disableResize();


        int startAction = startDlg->getAction();
        switch(startAction)
        {
        case 1:
            slotFileNew();
            break;
        case 2:
            fn = startDlg->getFileName();

            if (!fn.isEmpty())
            {
                //doc->openDocument(fn, false);
                KURL url(fn);
                if(openDocument(url))
                {
                    m_fileOpenRecent->addURL(url);
                    setCaption(url.fileName(), false);
                    fileSave->setEnabled(false);
                    fileReload->setEnabled(false);
                    p_preview->clear();
                    p_preview->setBibEntry(0);
                    slotNumRefMsg();
                    if (doc->size() > 0)
                    {
                        createKeys->setEnabled(true);
                        lockKeys->setEnabled(true);
                        unLockKeys->setEnabled(true);
                        refCheckKey->setEnabled(true);
                        sortReference->setEnabled(true);
						setFieldValue->setEnabled(true);
						copyFieldContent->setEnabled(true);
						replaceString->setEnabled(true);
                        //createBibliography->setEnabled(true);
                    }
                    viewBibSource->setEnabled(true);
                }
            }

            break;

        default:
            break;

        }
    }
    delete startDlg;

}


/*!
    \fn KBibApp::closeEvent(QCloseEvent *e)
 */
void KBibApp::closeEvent(QCloseEvent *e)
{
    //	cout << "\nClosing ... \n";
    //	saveOptions();
    bool accept=true;
    accept = queryClose();
    if (accept)
    {
        e->accept();
        qApp->quit();
    }
}


/*!
    \fn KBibApp::getLastFile()
 */
QString KBibApp::getLastFile()
{
    return lastFile;
}


void KBibApp::slotConfig()
{
    if (configDlg==0)
    {
        configDlg = new KBibConfigDlg(this);
        configDlg->setState(kbibConfigState);
        connect( configDlg, SIGNAL( valueChanged(const configState &)),
                 this, SLOT(configurationChanged(const configState &)));
    }
    configDlg->show();

    //delete configDlg;

}


void KBibApp::slotConfigToolbar()
{
    saveMainWindowSettings(config, QString::fromLatin1("Main Window Options"));
    KEditToolbar dlg(actionCollection());
    connect(&dlg, SIGNAL(newToolbarConfig()), this, SLOT(slotNewToolbarConfig()));
    dlg.exec();
}

void KBibApp::slotNewToolbarConfig()
{
    applyMainWindowSettings(config, QString::fromLatin1("Main Window Options"));
    createGUI();
}

void KBibApp::slotConfigKeys()
{
    KKeyDialog::configure(actionCollection());
}


void KBibApp::configurationChanged(const configState &st)
{
    kbibConfigState = st;
    QFont font = kbibConfigState.font;
    //cerr << font.family();
    m_view->setFont(font);
   group_view->setFont(font);
    p_preview->setFont(font);

    if (kbibConfigState.displayFieldsChanged!=0)
    {
        kbibConfigState.displayFieldsSize = defaultDisplayFieldsSize();
        m_view->updateColumn();
        m_view->updateCurrentListView();
        m_view->repaint();
    }


}

void KBibApp::slotLockKeys()
{
    BibEntry *entry;
    bool change = false;
    if (KMessageBox::questionYesNo( this,i18n("Are you sure to lock all citation keys?")) == KMessageBox::Yes)
    {
        for (int i = 0; i< doc->size(); i++)
        {
            entry = doc->getEntry(i);
			QString lock = entry->getField(QString::fromLatin1("lockkey"));
			if (lock.isEmpty() || lock != QString::fromLatin1("Y") )
            {
                entry->setField("lockkey", "Y");
                change = true;
            }
        }
        if (change)
        {
            if ( ((kbibConfigState.displayFields).contains("citation key") ) || ((kbibConfigState.displayFields).contains("lockkey") ) )
                m_view->updateCurrentListView();
            p_preview->updatePreview();
            slotDocChanged();
        }
    }

}

void KBibApp::slotLockKeysSelected()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        bool change = false;
        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );

			QString lock = entry->getField(QString::fromLatin1("lockkey"));
			if (lock.isEmpty() || lock != QString::fromLatin1("Y") )
            {
                entry->setField("lockkey", "Y");
                change = true;
            }


        }
        if (change)
        {
            slotDocChanged();
            m_view->updateCurrentListView();
            p_preview->updatePreview();
        }

    }
}


void KBibApp::slotunLockKeys()
{
    BibEntry *entry;
    bool change=false;
    if (KMessageBox::questionYesNo( this,i18n("Are you sure to unlock all citation keys?")) == KMessageBox::Yes)
    {
        for (int i = 0; i< doc->size(); i++)
        {
            entry = doc->getEntry(i);
			
			QString lock = entry->getField(QString::fromLatin1("lockkey"));
			if (lock == QString::fromLatin1("Y") )
            {
                entry->setField("lockkey", "N");
                change = true;
            }

        }
        if(change)
        {
            if ( ((kbibConfigState.displayFields).contains("citation key") ) || ((kbibConfigState.displayFields).contains("lockkey") ) )
            {

                m_view->updateCurrentListView();
            }
            p_preview->updatePreview();
            slotDocChanged();
        }
    }

}

void KBibApp::slotunLockKeysSelected()
{
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
        return;
    if (list)
    {
        bool change = false;
        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );

			QString lock = entry->getField(QString::fromLatin1("lockkey"));
			if (lock == QString::fromLatin1("Y") )
            {
                entry->setField("lockkey", "N");
                change = true;
            }

        }
        if (change)
        {
            slotDocChanged();
            m_view->updateCurrentListView();
            p_preview->updatePreview();
        }

    }
}

void KBibApp::slotFileExportEndnote()
{
    slotStatusMsg(i18n("Export to Endnote..."));
    if (doc->isModified())
    {
        if (KMessageBox::questionYesNo( this,i18n("Current file has been changed. Do you want to save the change first?")) == KMessageBox::Yes)
        {
            slotFileSave();
        }

    }

    int query=KMessageBox::Yes;

    KURL url_end=KFileDialog::getSaveURL(QDir::currentDirPath(),
                                         i18n("*.end|Endnote Files (*.end)\n*|All files"), this, i18n("Exporting to..."));
    if(!url_end.isEmpty())
    {
        if(KIO::NetAccess::exists(url_end, false, this))
            query = KMessageBox::warningYesNoCancel( this,i18n("A file named \"%1\" already exists. "
                    "Are you sure you want to overwrite it?").arg(url_end.fileName()) );
        if (query==KMessageBox::Yes)
        {
            //QString bibfn = doc->getFileName();
            KURL url_bib = doc->getURL();
            KTempFile tmpfile;
            tmpfile.setAutoDelete(TRUE);
            QString bibfn = tmpfile.name();
            //	cerr << "File name " << (url.url()).ascii();
            if(KIO::NetAccess::download(url_bib, bibfn, this))
            {
                KTempFile tmpfile_xml;
                tmpfile_xml.setAutoDelete(TRUE);
                bib2xml(const_cast<char*>(bibfn.ascii()), const_cast<char*>((tmpfile_xml.name()).ascii() ));
                if(url_end.isLocalFile())
                {
                    xml2end(const_cast<char*>((tmpfile_xml.name()).ascii()), const_cast<char*>((url_end.path()).ascii()  ) );
                }
                else
                {
                    KTempFile tmpfile_end;
                    tmpfile_end.setAutoDelete(TRUE);
                    QString endfn = tmpfile_end.name();
                    xml2end(const_cast<char*>((tmpfile_xml.name()).ascii()), const_cast<char*>(endfn.ascii()) );
                    bool uploaded = KIO::NetAccess::upload(endfn, url_end, this);
                    if(!uploaded)
                    {
                        QString msg(i18n("Kbib is unable to upload the file - %1.").arg(url_end.url()));
                        KMessageBox::error(this, msg);
                    }
                }
            }
        }
    }
    slotStatusMsg(i18n("Ready"));
}





void KBibApp::slotFileExportRIS()
{
    slotStatusMsg(i18n("Export to RIS..."));
    if (doc->isModified())
    {
        if (KMessageBox::questionYesNo( this,i18n("Current file has been changed. Do you want to save the change first?")) == KMessageBox::Yes)
        {
            slotFileSave();
        }

    }

    int query=KMessageBox::Yes;

    KURL url_ris=KFileDialog::getSaveURL(QDir::currentDirPath(),
                                         i18n("*.ris|RIS Files (*.ris)\n*|All files"), this, i18n("Exporting to..."));
    if(!url_ris.isEmpty())
    {
        if(KIO::NetAccess::exists(url_ris, false, this))
            query = KMessageBox::warningYesNoCancel( this,i18n("A file named \"%1\" already exists. "
                    "Are you sure you want to overwrite it?").arg(url_ris.fileName()) );
        if (query==KMessageBox::Yes)
        {
            //QString bibfn = doc->getFileName();
            KURL url_bib = doc->getURL();
            KTempFile tmpfile;
            tmpfile.setAutoDelete(TRUE);
            QString bibfn = tmpfile.name();
            //	cerr << "File name " << (url.url()).ascii();
            if(KIO::NetAccess::download(url_bib, bibfn, this))
            {
                KTempFile tmpfile_xml;
                tmpfile_xml.setAutoDelete(TRUE);
                bib2xml(const_cast<char*>(bibfn.ascii()), const_cast<char*>((tmpfile_xml.name()).ascii() ));
                if(url_ris.isLocalFile())
                {
                    xml2ris(const_cast<char*>((tmpfile_xml.name()).ascii()), const_cast<char*>((url_ris.path()).ascii()  ) );
                }
                else
                {
                    KTempFile tmpfile_ris;
                    tmpfile_ris.setAutoDelete(TRUE);
                    QString risfn = tmpfile_ris.name();
                    xml2ris(const_cast<char*>((tmpfile_xml.name()).ascii()), const_cast<char*>(risfn.ascii()) );
                    bool uploaded = KIO::NetAccess::upload(risfn, url_ris, this);
                    if(!uploaded)
                    {
                        QString msg(i18n("Kbib is unable to upload the file - %1.").arg(url_ris.url()));
                        KMessageBox::error(this, msg);
                    }
                }
            }
        }
    }
    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotFileExportMODSXML()
{
    slotStatusMsg(i18n("Export to MODS XML..."));
    if (doc->isModified())
    {
        if (KMessageBox::questionYesNo( this,i18n("Current file has been changed. Do you want to save the change first?")) == KMessageBox::Yes)
        {
            slotFileSave();
        }

    }

    int query=KMessageBox::Yes;

    KURL url_xml=KFileDialog::getSaveURL(QDir::currentDirPath(),
                                         i18n("*.xml|XML Files (*.xml)\n*|All files"), this, i18n("Exporting to..."));
    if(!url_xml.isEmpty())
    {
        if(KIO::NetAccess::exists(url_xml, false, this))
            query = KMessageBox::warningYesNoCancel( this,i18n("A file named \"%1\" already exists. "
                    "Are you sure you want to overwrite it?").arg(url_xml.fileName()) );
        if (query==KMessageBox::Yes)
        {
            //QString bibfn = doc->getFileName();
            KURL url_bib = doc->getURL();
            KTempFile tmpfile;
            tmpfile.setAutoDelete(TRUE);
            QString bibfn = tmpfile.name();
            //	cerr << "File name " << (url.url()).ascii();
            if(KIO::NetAccess::download(url_bib, bibfn, this))
            {
                KTempFile tmpfile_xml;
                tmpfile_xml.setAutoDelete(TRUE);


                if(url_xml.isLocalFile())
                {
                    bib2xml(const_cast<char*>(bibfn.ascii()), const_cast<char*>((url_xml.path()).ascii()  ));


                }
                else
                {
                    KTempFile tmpfile_xml;
                    tmpfile_xml.setAutoDelete(TRUE);
                    QString xmlfn = tmpfile_xml.name();
                    bib2xml(const_cast<char*>(bibfn.ascii()),
                            const_cast<char*>(xmlfn.ascii()) );
                    bool uploaded = KIO::NetAccess::upload(xmlfn, url_xml, this);
                    if(!uploaded)
                    {
                        QString msg(i18n("Kbib is unable to upload the file - %1.").arg(url_xml.url()));
                        KMessageBox::error(this, msg);
                    }
                }
            }
        }
    }
    slotStatusMsg(i18n("Ready"));
}


void KBibApp::slotFileExportHTML()
{

    slotStatusMsg(i18n("Export to HTML..."));
    if (doc->isModified())
    {
        if (KMessageBox::questionYesNo( this,i18n("Current file has been changed. Do you want to save the change first?")) == KMessageBox::Yes)
        {
            slotFileSave();
        }

    }


    KBibExportHTMLDlg* exportHTMLDlg = new KBibExportHTMLDlg(this);
    if (exportHTMLDlg->exec()==QDialog::Accepted)
    {

        int query=KMessageBox::Yes;

        KURL url_html=KFileDialog::getSaveURL(QDir::currentDirPath(),
                                              i18n("*.html|HTML Files (*.html)\n*|All files"), this, i18n("Exporting to..."));
        if(!url_html.isEmpty())
        {
            if(KIO::NetAccess::exists(url_html, false, this))
                query = KMessageBox::warningYesNoCancel( this,i18n("A file named \"%1\" already exists. "
                        "Are you sure you want to overwrite it?").arg(url_html.fileName()) );
            if (query==KMessageBox::Yes)
            {
                KURL url_bib = doc->getURL();
                KTempFile tmpfile;
                tmpfile.setAutoDelete(TRUE);
                QString bibfn = tmpfile.name();
                if(KIO::NetAccess::download(url_bib, bibfn, this))
                {
                    KTempFile tmpfile_html;
                    tmpfile_html.setAutoDelete(TRUE);

                    QString htmlfn;
                    bool local = false;

                    if(url_html.isLocalFile())
                    {
                        htmlfn = url_html.path();
                        local = true;

                    }
                    else
                    {
                        htmlfn = tmpfile_html.name();
                        local = false;
                    }

                    KTempFile resulthtmlfile;
                    resulthtmlfile.setAutoDelete(TRUE);

                    QString cmd = "bibtex2html";
                    cmd = cmd +  " -noheader";
                    cmd = cmd +  " -rawurl";
                    cmd = cmd +  " -nobibsource";
                    cmd = cmd +  " -nofooter";
                    cmd = cmd +  " -nodoc";
                    cmd = cmd +  " -o ";
                    cmd = cmd +  resulthtmlfile.name();
                    cmd = cmd + " -fsuffix \"\" ";
                    QString style = (exportHTMLDlg->getBibStyle()).simplifyWhiteSpace();
                    if ( !style.isEmpty() )
                    {
                        cmd = cmd +  " -s ";
                        cmd = cmd +  style;
                    }
                    if (!exportHTMLDlg->isIncludeAbstract())
                    {
                        cmd = cmd +  " -noabstract";
                    }
                    if (!exportHTMLDlg->isIncludeKeywords())
                    {
                        cmd = cmd +  " -nokeywords ";
                    }

                    switch(exportHTMLDlg->getSortBy())
                    {
                    case 1:
                        cmd = cmd + " -d ";
                        break;
                    case 2:
                        cmd = cmd + " -a ";
                        break;
                    default:
                        cmd = cmd + " -u ";
                        break;
                    }

                    if (exportHTMLDlg->isRevertOrder() )
                    {
                        cmd = cmd + " -r ";
                    }

                    cmd = cmd +  " " + bibfn;
                    cerr << "CMD : " << cmd.ascii() <<"\n";
                    system(cmd.ascii());
                    QFile tmp_html_file(resulthtmlfile.name()  );// "/tmp/kbib-html.html");

                    if ( tmp_html_file.open( IO_ReadOnly ) )
                    {
                        tmp_html_file.reset();
                        QFile html_file(htmlfn );

                        if ( html_file.open( IO_WriteOnly ) )
                        {
                            html_file.reset();
                            QTextStream stream( &html_file );
                            stream.reset();
                            QTextStream ts;
                            ts.setDevice( &tmp_html_file );
                            ts.reset();
                            stream << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"> \n";
                            stream << "<html>\n	<head> \n ";
                            stream << "<title>\n";
                            stream << "Reference\n";
                            stream << "</title> \n</head> \n <body>\n";
                            stream << "<h1>Bibliography</h1>\n";


                            QString st = ts.read();
                            //                                cerr << st.ascii() << "\n";
                            stream << st;
                            stream << "\n";
                            stream << "</table><hr><em>Generated by <a href=\"http://user.digisurf.com.au/~thachly/kbib\">KBib</a> ";
                            stream << "with the help of <a href=\"http://www.lri.fr/~filliatr/bibtex2html/\">bibtex2html</a></em>\n";
                            stream << "</body> \n</html>";
                            ts.unsetDevice();
                            html_file.flush();
                            html_file.close();
                            if (!local)
                            {
                                bool uploaded = KIO::NetAccess::upload(htmlfn, url_html, this);
                                if(!uploaded)
                                {
                                    QString msg(i18n("Kbib is unable to upload the file - %1.").arg(url_html.url()));
                                    KMessageBox::error(this, msg);
                                }
                            }

                            KProcess* proc = new KProcess;
                            proc->clearArguments();
                            (*proc) << ((this->kbibConfigState).browser);
                            (*proc) << url_html.prettyURL();
                            proc->start();

                        }

                    }
                    tmp_html_file.close();

                }

            }
        }
    }
    delete exportHTMLDlg;
    slotStatusMsg(i18n("Ready"));
}

void KBibApp:: slotInternetSearch(){
	if (searchManager::self()->numSearcher() > 0){
		KBibRemoteSearchDlg *searchDlg = new KBibRemoteSearchDlg(this, "Internet Search" );
		if (searchDlg->exec() == QDialog::Rejected)
			searchDlg->stop();	
		delete searchDlg;
	}
	else{
		KMessageBox::sorry(this, i18n("No data source has been defined. You can add new data sources in \"Configure KBib\" dialog under \"Settings\" menu."));
 	}
}

void KBibApp::slotStringMacro()
{
    BibentryTable *entry_list = doc-> getEntryList();
	KbibStringMacroDlg *stringMacroDlg = new KbibStringMacroDlg(entry_list, kbibConfigState.globalStringMacros, this, "String Macro");
    stringMacroDlg->setCaption(i18n("String Macros") );
    if (stringMacroDlg->exec() == QDialog::Accepted)
    {
        entry_list->clearStringMacro();
		QMap<QString, QString> map = stringMacroDlg->getStringMacroList();
		for(QMap<QString, QString>::ConstIterator it = map.begin(); it != map.end(); ++it)
		{
			entry_list->new_stringMacro(it.key(), it.data());
			
		}
		
		slotDocChanged();

    }
    delete stringMacroDlg;
}


void KBibApp::slotPreamble()
{
    BibentryTable *entry_list = doc-> getEntryList();
    KBibPreambleDlg *preambleDlg = new KBibPreambleDlg(this, "Preamble");
    preambleDlg->setCaption(i18n("Preamble") );
    preambleDlg->setText(entry_list->getPreamble());
    if (preambleDlg->exec() == QDialog::Accepted)
    {
        entry_list->setPreamble( preambleDlg->getText());
        slotDocChanged();
    }
    delete preambleDlg;

}


void KBibApp::slotCustomiseFields(){
	ReferenceFieldsDialog *refFieldDlg = new ReferenceFieldsDialog(this, "Reference Fields");	
	if (refFieldDlg->exec() == QDialog::Accepted) {
		setGroupByList();
		//Write entry table file
		QString kbibDir = locateLocal( "data", "kbib" );

    	QDir dir(kbibDir);
    	if( ! dir.exists() )
    	{
        	cerr << "Directory kbib does not exist. Create it!\n";
        	dir.mkdir(kbibDir);
    	}

	    kbibDir = kbibDir+"/entryDefs.xml";
		BibEntryDefTable::self()->writeEntryDefFile(kbibDir);
	}
	delete refFieldDlg;
}


void KBibApp::slotCustomiseTypes(){
	ReferenceTypesDialog *refTypeDlg = new ReferenceTypesDialog(this, "Reference Types");	
	if (refTypeDlg->exec() == QDialog::Accepted) {
		KURL url = doc->getURL();
		//Save current list into a temp file
		KTempFile tmpfile;
    	tmpfile.setAutoDelete(TRUE);
    	QString fn = tmpfile.name();	
		doc->saveDocument(fn);
		//save entry defs
		refTypeDlg->saveTypes();
		//reload the tmp file
		doc->openDocument(fn, false);
		doc->setURL(url);
		//Write entry table file
		QString kbibDir = locateLocal( "data", "kbib" );

    	QDir dir(kbibDir);
    	if( ! dir.exists() )
    	{
        	cerr << "Directory kbib does not exist. Create it!\n";
        	dir.mkdir(kbibDir);
    	}

	    kbibDir = kbibDir+"/entryDefs.xml";
		BibEntryDefTable::self()->writeEntryDefFile(kbibDir);
	}
	delete refTypeDlg;
}


void KBibApp::slotSetFieldValue()
{
	bool selected;
	if ( ((m_view->selectedItems()).count() > 0) || ( (group_view->selectedItems()).count() > 0) )
		selected = true;
	else
		selected = false;
	SetFieldDlg *setFieldDlg = new SetFieldDlg(selected, this, "Set Field");	
	if (setFieldDlg->exec() == QDialog::Accepted) {	
		QString fn = setFieldDlg->fieldName();
		QString value = setFieldDlg->fieldValue();
		if (!fn.isEmpty()){
			if (setFieldDlg->isAllReferences()){
				for (int i = 0; i < doc->size(); i++){
					doc->getEntry(i)->setField(fn, value);		
				}
			}
			else{
				QPtrList< QListViewItem >  selectedItems;
				if (currentSelectedView == 2)
					selectedItems = m_view->selectedItems ();
				else
					selectedItems = group_view->selectedItems ();
				
				for ( QListViewItem *item_ = selectedItems.first(); item_; item_ = selectedItems.next() ){
					BibEntry *entry;
					if (currentSelectedView == 2){
						KBibListViewItem *item = dynamic_cast<KBibListViewItem*>(item_);
						entry = item->getBibEntry();	
					}
					else{
						KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);	
						entry = item->getBibEntry();
					}
					entry->setField(fn, value);
					
				}
			}
			if (kbibConfigState.displayFields.contains(fn) > 0){
				m_view->updateCurrentListView();
			}
			group_view->createGroupView();
			p_preview->updatePreview();
			slotDocChanged();
		}
	}
	delete setFieldDlg;
	
}


void KBibApp::slotReplaceString(){
	bool selected;
	if ( ((m_view->selectedItems()).count() > 0) || ( (group_view->selectedItems()).count() > 0) )
		selected = true;
	else
		selected = false;
	ReplaceStringDlg *replaceStringDlg = new ReplaceStringDlg(selected, this, "Replace String");	
	if (replaceStringDlg->exec() == QDialog::Accepted) {
		QString oldString = replaceStringDlg->oldString();
		QString newString = replaceStringDlg->newString();
		bool allField = replaceStringDlg->isAllField();
		QString fieldName = replaceStringDlg->fieldName();
		bool change = false;
		if (oldString!=newString ){
			if (replaceStringDlg->isAllReferences()){
				for (int i = 0; i < doc->size(); i++){
					if (doc->getEntry(i)->replaceString(allField, fieldName, oldString, newString) )
						change = true;		
				}
			}
			else{
				QPtrList< QListViewItem >  selectedItems;
				if (currentSelectedView == 2)
					selectedItems = m_view->selectedItems ();
				else
					selectedItems = group_view->selectedItems ();
				
				for ( QListViewItem *item_ = selectedItems.first(); item_; item_ = selectedItems.next() ){
					BibEntry *entry;
					if (currentSelectedView == 2){
						KBibListViewItem *item = dynamic_cast<KBibListViewItem*>(item_);
						entry = item->getBibEntry();	
					}
					else{
						KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);	
						entry = item->getBibEntry();
					}
					if (entry->replaceString(allField, fieldName, oldString, newString))
						change = true;	
					
				}
			}
			if (change){
				if (kbibConfigState.displayFields.contains(fieldName) > 0 || allField){
					m_view->updateCurrentListView();
				}
				group_view->createGroupView();
				p_preview->updatePreview();
				slotDocChanged();
			}
		}		
	}
	delete replaceStringDlg;
}


void KBibApp::slotCopyFieldContent(){
	bool selected;
	if ( ((m_view->selectedItems()).count() > 0) || ( (group_view->selectedItems()).count() > 0) )
		selected = true;
	else
		selected = false;
	CopyFieldContentDlg *copyFieldContentDlg = new CopyFieldContentDlg(selected, this, "Copy Field Content");	
	if (copyFieldContentDlg->exec() == QDialog::Accepted) {
		QString srcField = copyFieldContentDlg->sourceFieldName();
		QString dstField = copyFieldContentDlg->destinationFieldName();
		if (!srcField.isEmpty() && !dstField.isEmpty() && srcField != dstField) {
			bool change = false;
			BibEntry *entry;
			QString content;
			bool macro;
			if (copyFieldContentDlg->isAllReferences()){
				for (int i = 0; i < doc->size(); i++){
					entry = doc->getEntry(i);
					content = entry->getField(srcField);
					if (!content.isEmpty()){
						macro = entry->stringMacroIndicator(srcField);
						entry->setField(dstField, content);
						entry->setStringMacroIndicator(dstField, macro);
						if (copyFieldContentDlg->clearSourceContent()){
							entry->setField(srcField, 0);
							entry->setStringMacroIndicator(srcField, false);	
						}							
						change = true;
					}		
				}
			}
			else{
				QPtrList< QListViewItem >  selectedItems;
				if (currentSelectedView == 2)
					selectedItems = m_view->selectedItems ();
				else
					selectedItems = group_view->selectedItems ();
				
				for ( QListViewItem *item_ = selectedItems.first(); item_; item_ = selectedItems.next() ){
					BibEntry *entry;
					if (currentSelectedView == 2){
						KBibListViewItem *item = dynamic_cast<KBibListViewItem*>(item_);
						entry = item->getBibEntry();	
					}
					else{
						KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);	
						entry = item->getBibEntry();
					}
					content = entry->getField(srcField);
					if (!content.isEmpty()){
						macro = entry->stringMacroIndicator(srcField);
						entry->setField(dstField, content);
						entry->setStringMacroIndicator(dstField, macro);
						if (copyFieldContentDlg->clearSourceContent()){
							entry->setField(srcField, 0);
							entry->setStringMacroIndicator(srcField, false);	
						}							
						change = true;
					}					
					
				}
			}
			if (change){
				if (kbibConfigState.displayFields.contains(srcField) > 0 || kbibConfigState.displayFields.contains(dstField) > 0 ){
					m_view->updateCurrentListView();
				}
				group_view->createGroupView();
				p_preview->updatePreview();
				slotDocChanged();
			}	
		}
	}
	delete copyFieldContentDlg;
}


void KBibApp::slotCreateBibliography()
{

    slotStatusMsg(i18n("Create bibliography..."));
    vector<int> *list=0;
    if (currentSelectedView == 2)
        list = m_view->getSelected();
    else if(currentSelectedView == 1)
    {
        QListViewItem *item_ = group_view->selectedItem();
        if (item_)
        {
            KBibGroupViewItem *item = dynamic_cast<KBibGroupViewItem*>(item_);
            if (item)
            {
                BibEntry *entry = item->getBibEntry();
                list = new vector<int>;
                int index = entry->getIndex();
                list->push_back(index);


            }
        }
    }
    else
    {
        slotStatusMsg(i18n("Ready"));
        return;
    }
    if (list)
    {
        bool first = true;
        QString citest;
        vector<int>::iterator p;
        int i;
        for (p=list->begin(); p!=list->end(); p++)
        {
            i = *p;
            BibEntry *entry = doc->getEntry( i );
            if(!first)
            {
                citest.append(",");
            }
            citest.append(entry->getKey());
            first = false;
        }

        if (citest.isEmpty())
        {
            KMessageBox::information(this, i18n("No reference was selected") );
            return;
        }


        KBibCreateBiliographyDlg *createBibDlg = new KBibCreateBiliographyDlg(this);
        if (createBibDlg->exec()==QDialog::Accepted)
        {
            m_view->saveSelected("/tmp/kbib-bib.bib");
            QString bibStyle = createBibDlg->getBibStyle();
            QString addionalFile = createBibDlg->getAdditionalFile();
            ofstream aux_file("/tmp/kbib-bib.aux");
            aux_file << "\\citation{" << citest << "}\n";
            aux_file << "\\bibstyle{" << bibStyle.ascii() << "}\n";
            aux_file << "\\bibdata{";
            if (!addionalFile.isEmpty())
            {
                QString fn = addionalFile.section('.', -1024, -2);
                aux_file << fn.ascii() << ",";
            }

            aux_file << "/tmp/kbib-bib" << "}\n";

            aux_file.close();

            system("bibtex /tmp/kbib-bib");

            KBibBiliographyDlg *viewBib = new KBibBiliographyDlg(this);

            QFile file("/tmp/kbib-bib.bbl"); // Read the text from a file
            if ( file.open( IO_ReadOnly ) )
            {
                QTextStream stream( &file );
                viewBib->setText( stream.read() );
            }

            viewBib->exec();

            //delete refname;
            delete viewBib;

        }
        delete createBibDlg;
        delete list;
    }
    slotStatusMsg(i18n("Ready"));

}


void KBibApp::slotSaveSelected()
{
    int query=KMessageBox::Yes;
    slotStatusMsg(i18n("Save selected..."));
    KURL url = KFileDialog::getSaveURL(QDir::currentDirPath(),
                                       i18n("*.bib|BibTeX Files (*.bib)\n*|All files"), this, i18n("Save to file..."));
    if(!url.isEmpty())
    {

        if(KIO::NetAccess::exists(url, false, this))
            query = KMessageBox::warningYesNoCancel( this,i18n("A file named \"%1\" already exists. "
                    "Are you sure you want to overwrite it?").arg(url.fileName()) );
        if (query==KMessageBox::Yes)
        {
            m_view->saveSelected(url);
        }
    }
    slotStatusMsg(i18n("Ready"));


}


void KBibApp::slotSortReference()
{
    slotStatusMsg(i18n("Sort references..."));
    KBibSortDlg *sortDlg = new KBibSortDlg(this);
    if (sortDlg->exec()==QDialog::Accepted)
    {
        int sortOrder = sortDlg->sortOrder();
        QString fieldToSort = sortDlg->getFieldToSort();

        doc->sort(sortOrder, fieldToSort);

    }
	delete sortDlg;
    slotStatusMsg(i18n("Ready"));

}


void KBibApp::slotRemoveDuplicated()
{
    slotStatusMsg(i18n("Remove duplicated references..."));
    if (KMessageBox::questionYesNo( this,i18n("Are you sure to remove duplicated references?")) == KMessageBox::Yes)
    {
        int numRemoved = doc->removeDuplicated();
        QString msg;
        msg.setNum(numRemoved);
        msg = msg+QString(" duplicated references were removed.");
        KMessageBox::information(this, i18n(msg) );

    }
    slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotShowDuplicated()
{
    slotStatusMsg(i18n("Show duplicated references..."));
    m_view->updateListView(doc->getEntryList());
    int numDuplicated = m_view->showDuplicated();
    slotNumRefMsg();
    QString msg;
    msg.setNum(numDuplicated);
    msg = msg+QString(" duplicated references were found.");
    KMessageBox::information(this, i18n(msg) );
    slotStatusMsg(i18n("Ready"));
}

bool KBibApp::editEntry(int index)
{
    slotStatusMsg(i18n("Edit references..."));
    bool edit = doc->modifyEntry(index);
    slotStatusMsg(i18n("Ready"));
    return edit;
}


void KBibApp::slotViewAll()
{
    m_view->updateListView(doc->getEntryList());
    slotSelectionChanged();
    m_view->slotSelectionChanged();
    slotNumRefMsg();
}

void KBibApp::slotViewSelected()
{
    m_view->viewSelected();
    slotNumRefMsg();
}


void KBibApp::slotHideSelected()
{
    m_view->hideSelected();
    slotSelectionChanged();
    m_view->slotSelectionChanged();
    slotNumRefMsg();

}

void KBibApp::slotNewEntryFromText(){
	slotStatusMsg(i18n("New reference from plain text..."));
	NewEntryFromTextDialog *dlg = new NewEntryFromTextDialog(this);
	if (dlg->exec()==QDialog::Accepted)
	{
		BibEntry *e = dlg->getBibEntry();
		doc->addEntry(new BibEntry(*e));

	}
	delete dlg;
	slotStatusMsg(i18n("Ready"));	
}

void KBibApp::slotViewByRefType()
{
    slotStatusMsg(i18n("View by reference type..."));
    KbibSelectEntryType *entrySelectDlg = new KbibSelectEntryType(this, "Select Reference Type");


    if (entrySelectDlg->exec()==QDialog::Accepted)
    {
        m_view->updateListView(doc->getEntryList());
        QString entryTypeName = entrySelectDlg->get_entryType();
        m_view->showByRefType(entryTypeName);
        slotSelectionChanged();
        slotNumRefMsg();
        m_view->slotSelectionChanged();
    }
    slotStatusMsg(i18n("Ready"));
}


QStringList KBibApp::defaultDisplayFields()
{
    QStringList names;
    names.clear();
    names += QString::fromLatin1("author");
    names += QString::fromLatin1("citation key");
    names += QString::fromLatin1("year");
    names += QString::fromLatin1("title");
    return names;

}

QValueList<int> KBibApp::defaultDisplayFieldsSize()
{
    QValueList<int> sizes;
    sizes.clear();
    int columns = (kbibConfigState.displayFields).count();
    int col_size = (this->width() )/columns;

    for (int i = 0; i < columns-1; i++)
        sizes += col_size;
    sizes += (this->width() ) - col_size*(columns-1);


    return sizes;
}

void KBibApp::slotGroupByChange()
{
    QString groupBy = groupViewSelect->currentText();
    if (groupBy != group_view->currentGroupBy())
    {
        group_view->setGroupBy(groupBy);
        group_view->createGroupView();
    }
}

void KBibApp::setCurrentSelectedView(int view)
{
    switch(view)
    {
    case 0:
        group_view->clearSelection();
        m_view->clearSelection();
        currentSelectedView = view;
        break;
    case 1:
        m_view->clearSelection();
        currentSelectedView = view;
        break;
    case 2:
        group_view->clearSelection();
        currentSelectedView = view;
        break;
    default:
        break;
    }
}

void KBibApp::setActive()
{
	kapp->mainWidget()->raise();
	kapp->mainWidget()->setActiveWindow();
}

void KBibApp::slotNewEntryFromDOI()
{
	slotStatusMsg(i18n("Create new reference from DOI..."));
	
	bool ok;
    QString doi = KInputDialog::getText(
            i18n("New reference from DOI"), QString::fromLatin1("DOI:"), QString::null, &ok, this ).stripWhiteSpace();
    if ( ok && !doi.isEmpty() ) {
		newRefFromID(DOI, doi);
	}
	else
		slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotNewEntryFromArXiv()
{	
	slotStatusMsg(i18n("Create new reference from arXiv ID..."));
	
	bool ok;
    QString id = KInputDialog::getText(
            i18n("New reference from arXiv ID"), QString::fromLatin1("arXiv ID:"), QString::null, &ok, this ).stripWhiteSpace();
    if ( ok && !id.isEmpty() ) {
		newRefFromID(arXiv, id);
	}
	else
		slotStatusMsg(i18n("Ready"));
}

void KBibApp::slotNewEntryFromPubmedID()
{
	slotStatusMsg(i18n("Create new reference from PubMed ID..."));
	
	bool ok;
    QString id = KInputDialog::getText(
            i18n("New reference from PubMed ID"), QString::fromLatin1("PubMed ID:"), QString::null, &ok, this ).stripWhiteSpace();
    if ( ok && !id.isEmpty() ) {
		newRefFromID(PMID, id);
	}
	else
		slotStatusMsg(i18n("Ready"));	
}



void KBibApp::newRefFromID(IDType type, QString id, BibEntry* entry)
{
	if (!m_id2Entry){
			m_id2Entry = new ID2Entry(this);
			connect(m_id2Entry, SIGNAL(signalResultFound(BibEntry*)), this, SLOT(slotNewEntryFromIDResult(BibEntry*) ) );		
	}
	m_id2Entry->setEntry(entry);

	m_id2Entry->setIDType(type);
	m_id2Entry->setID(id);
	m_id2Entry->search();
	
}

void KBibApp::slotNewEntryFromIDResult(BibEntry *entry){
	if (entry){
		entry->createKey(kbibConfigState.keyConnecting);
		doc->addEntry(entry, false, true);	
	}
	slotStatusMsg(i18n("Ready"));
}


void KBibApp::slotNewEntryFromPDF(){
#if HAVE_POPPLER	
	slotStatusMsg(i18n("New reference from a PDF file..."));
	
	QString filter = i18n("*.pdf|PDF files (*.pdf)");
        filter += QString::fromLatin1("\n");
        filter += i18n("*|All files");
	QString fn = KFileDialog::getOpenFileName(QString::fromLatin1(":open"), filter,
                                           this, i18n("Open File..."));
	if (fn.isEmpty())
		return;
	
	Poppler::Document *pdfDoc = Poppler::Document::load(fn);
	if (!pdfDoc){
		KMessageBox::error( this,i18n("The file cannot be openned."));
		return;	
	}
	int numPages = pdfDoc->getNumPages();
	QString st = QString::null;
	for (int i = 0; i < 1; i++){
		Poppler::Page *page = pdfDoc->getPage(i);
		st = st + page->getText(0);	
	}
	
	BibEntry *entry = new BibEntry(QString::fromLatin1("article"), QString::null);
	entry->setField(QString::fromLatin1("file"), fn);
	
	QRegExp rx1(QString::fromLatin1(".*(10\\.[\\d.]+/[^\\s]+).*"));
	QRegExp rx2(QString::fromLatin1(".*arXiv:? *([^\\.\\/\\s:]+[\\/\\.][\\d]+).*"));
	
	if (rx1.exactMatch(st))
    {
		QString doi = rx1.cap(1);
		newRefFromID(DOI, doi, entry);

	}
	else if(rx2.exactMatch(st)){
		QString id = rx2.cap(1);
		newRefFromID(arXiv, id, entry);	
	}
	else{
		if (KMessageBox::warningYesNo(this, i18n("No DOI or arXiv ID was found in the file.\nDo you want to manually create a reference from text content of the PDF file?")) == KMessageBox::Yes){
			slotStatusMsg(i18n("New reference from plain text..."));
			NewEntryFromTextDialog *dlg = new NewEntryFromTextDialog(this, 0, st);
			dlg->getBibEntry()->setField(QString::fromLatin1("file"), fn);
			if (dlg->exec()==QDialog::Accepted)
			{
				BibEntry *e = dlg->getBibEntry();
				doc->addEntry(new BibEntry(*e));
			}
			delete dlg;
			slotStatusMsg(i18n("Ready"));
		}
	
		else
			slotStatusMsg(i18n("Ready"));
	}
#endif
}

void KBibApp::slotFilterLabelActivated(){ 
  m_quickFilter->setFocus();
  m_quickFilter->selectAll();

}
void KBibApp::slotClearFilter(){
  m_quickFilter->clear();
  slotQueueFilter();
}
void KBibApp::slotQueueFilter(){
  m_queuedFilters++;
  QTimer::singleShot(300, this, SLOT(slotUpdateFilter()));
}

void KBibApp::slotUpdateFilter() {
  m_queuedFilters--;
  if(m_queuedFilters > 0) {
    return;
  }
  QString text = m_quickFilter->text().stripWhiteSpace();
  if(!text.isEmpty()) {
	m_view->updateListView(doc->getEntryList());
	int att = (m_attributes->currentItem())-1;
	int options = 0;
	int found = 0;
	int startIndex = 0;
	while(found < doc->size() - 1 && found >= 0){
		found = doc->search_string(const_cast<char* >(text.ascii()), startIndex, att, options);
  		startIndex = found+1;
	}
	slotViewSelected();
	m_view->clearSelection();
   }
   else{
	slotViewAll();
   }
}

void KBibApp::slotFilterAttributeChanged(){
	slotQueueFilter();
}


