summaryrefslogtreecommitdiffstats
path: root/src/webqueryz3950.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/webqueryz3950.cpp')
-rw-r--r--src/webqueryz3950.cpp397
1 files changed, 397 insertions, 0 deletions
diff --git a/src/webqueryz3950.cpp b/src/webqueryz3950.cpp
new file mode 100644
index 0000000..1b62129
--- /dev/null
+++ b/src/webqueryz3950.cpp
@@ -0,0 +1,397 @@
+/***************************************************************************
+ * Copyright (C) 2004-2009 by Thomas Fischer *
+ * fischer@unix-ag.uni-kl.de *
+ * *
+ * based on code from or inspired by *
+ * - Tellico by Robby Stephenson *
+ * - kbib by Thach Nguyen *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * *
+ * *
+ * This code is based on code from Tellico 1.2.10 *
+ * by Robby Stephenson <robby@periapsis.org> *
+ * Tellico is released under the GNU GPL 2, too. *
+ * http://www.periapsis.org/tellico/ *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qfile.h>
+#include <qapplication.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kurl.h>
+
+#include <fileimporterbibutils.h>
+#include <settings.h>
+#include "webqueryz3950.h"
+
+namespace KBibTeX
+{
+ const QString WebQueryZ3950Widget::attributesI18N[] = { i18n( "any" ), i18n( "title" ), i18n( "author" ), i18n( "publisher" )};
+
+ WebQueryZ3950Widget::WebQueryZ3950Widget( QWidget *parent, const char *name )
+ : WebQueryWidget( parent, name ), lineEditQuery2( NULL )
+ {
+ init();
+
+ Settings *settings = Settings::self();
+ QString value = settings->getWebQueryDefault( "Z3950_server" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxServers->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "Z3950_query1" );
+ value = value == QString::null ? "" : value;
+ lineEditQuery->setText( value );
+ slotTextChanged( value, true );
+ value = settings->getWebQueryDefault( "Z3950_attr1" );
+ value = value == QString::null ? "1" : value;
+ comboBoxInAttribute->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "Z3950_query2" );
+ lineEditQuery2->setText( value == QString::null ? "" : value );
+ value = settings->getWebQueryDefault( "Z3950_attr2" );
+ value = value == QString::null ? "1" : value;
+ comboBoxInAttribute2->setCurrentItem( value.toInt() );
+ value = settings->getWebQueryDefault( "Z3950_booleanOp" );
+ value = value == QString::null || value.isEmpty() ? "0" : value;
+ comboBoxBooleanOp->setCurrentItem( value.toInt() );
+ }
+
+ void WebQueryZ3950Widget::init()
+ {
+ QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QHBoxLayout *hLayout = new QHBoxLayout( );
+ vLayout->addLayout( hLayout );
+
+ QLabel *label = new QLabel( i18n( "Server:" ), this );
+ hLayout->setStretchFactor( label, 1 );
+ hLayout->addWidget( label );
+ comboBoxServers = new KComboBox( false, this );
+ hLayout->addWidget( comboBoxServers );
+ hLayout->setStretchFactor( comboBoxServers, 7 );
+ label->setBuddy( comboBoxServers );
+ hLayout->addSpacing( KDialog::spacingHint() * 2 );
+ label = new QLabel( i18n( "&Number of results:" ), this );
+ hLayout->addWidget( label );
+ hLayout->setStretchFactor( label, 1 );
+ spinBoxMaxHits = new QSpinBox( 1, 50, 1, this );
+ spinBoxMaxHits->setValue( 10 );
+ hLayout->addWidget( spinBoxMaxHits );
+ hLayout->setStretchFactor( spinBoxMaxHits, 3 );
+ label->setBuddy( spinBoxMaxHits );
+
+ QGridLayout *layout = new QGridLayout( vLayout, 2, 6, KDialog::spacingHint() );
+
+ KPushButton *clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ layout->addWidget( clearSearchText, 0, 1 );
+ label = new QLabel( i18n( "Search term 1:" ), this );
+ layout->addWidget( label, 0, 2 );
+ lineEditQuery = new KLineEdit( this );
+ layout->addWidget( lineEditQuery, 0, 3 );
+ label->setBuddy( lineEditQuery );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
+ connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
+ KCompletion *completionQuery = lineEditQuery->completionObject();
+ connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+ label = new QLabel( i18n( "Search in:" ), this );
+ layout->addWidget( label, 0, 4 );
+ comboBoxInAttribute = new KComboBox( false, this );
+ layout->addWidget( comboBoxInAttribute, 0, 5 );
+ label->setBuddy( comboBoxInAttribute );
+
+ comboBoxBooleanOp = new KComboBox( false, this );
+ layout->addWidget( comboBoxBooleanOp, 1, 0 );
+
+ clearSearchText = new KPushButton( this );
+ clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
+ layout->addWidget( clearSearchText, 1, 1 );
+ label = new QLabel( i18n( "Search term 2:" ), this );
+ layout->addWidget( label, 1, 2 );
+ lineEditQuery2 = new KLineEdit( this );
+ layout->addWidget( lineEditQuery2, 1, 3 );
+ label->setBuddy( lineEditQuery2 );
+ connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery2, SLOT( clear() ) );
+ completionQuery = lineEditQuery->completionObject();
+ connect( lineEditQuery2, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
+ connect( lineEditQuery2, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
+ label = new QLabel( i18n( "Search in:" ), this );
+ layout->addWidget( label, 1, 4 );
+ comboBoxInAttribute2 = new KComboBox( false, this );
+ layout->addWidget( comboBoxInAttribute2, 1, 5 );
+ label->setBuddy( comboBoxInAttribute2 );
+
+#ifdef HAVE_YAZ
+ Settings *settings = Settings::self();
+ for ( QMap<QString, Settings::Z3950Server>::Iterator it = settings->z3950_ServerList.begin(); it != settings->z3950_ServerList.end(); ++it )
+ comboBoxServers->insertItem( it.data().name );
+#endif // HAVE_YAZ
+ for ( unsigned int i = 0; i < sizeof( attributesI18N ) / sizeof( attributesI18N[0] ); ++i )
+ {
+ comboBoxInAttribute->insertItem( attributesI18N[i] );
+ comboBoxInAttribute2->insertItem( attributesI18N[i] );
+ }
+ comboBoxBooleanOp->insertItem( i18n( "and" ) );
+ comboBoxBooleanOp->insertItem( i18n( "or" ) );
+ }
+
+ WebQueryZ3950::WebQueryZ3950( QWidget* parent ) : WebQuery( parent )
+#ifdef HAVE_YAZ
+ , m_marc21transformer( NULL ), m_unimarctransformer( NULL ), m_modsImporter( NULL ), m_conn( NULL )
+#endif // HAVE_YAZ
+ {
+ m_widget = new WebQueryZ3950Widget( parent );
+ }
+
+ WebQueryZ3950::~WebQueryZ3950()
+ {
+#ifdef HAVE_YAZ
+ if ( m_modsImporter != NULL ) delete m_modsImporter;
+ if ( m_marc21transformer != NULL ) delete m_marc21transformer;
+ if ( m_unimarctransformer != NULL ) delete m_unimarctransformer;
+ if ( m_conn != NULL ) delete m_conn;
+#endif // HAVE_YAZ
+// delete m_widget; FIXME Why does delete fail here?
+ }
+
+ QString WebQueryZ3950::title()
+ {
+ return i18n( "Z39.50" );
+ }
+
+ QString WebQueryZ3950::disclaimer()
+ {
+ return i18n( "Z39.50" );
+ }
+
+ QString WebQueryZ3950::disclaimerURL()
+ {
+ return "http://[127.0.0.1]/";
+ }
+
+ WebQueryWidget *WebQueryZ3950::widget()
+ {
+ return m_widget;
+ }
+
+ void WebQueryZ3950::query()
+ {
+ WebQuery::query();
+
+ Settings *settings = Settings::self();
+ settings->setWebQueryDefault( "Z3950_server", QString::number( m_widget->comboBoxServers->currentItem() ) );
+ settings->setWebQueryDefault( "Z3950_query1", m_widget->lineEditQuery->text() );
+ settings->setWebQueryDefault( "Z3950_attr1", QString::number( m_widget->comboBoxInAttribute->currentItem() ) );
+ settings->setWebQueryDefault( "Z3950_query2", m_widget->lineEditQuery2->text() );
+ settings->setWebQueryDefault( "Z3950_attr2", QString::number( m_widget->comboBoxInAttribute2->currentItem() ) );
+ settings->setWebQueryDefault( "Z3950_booleanOp", QString::number( m_widget->comboBoxBooleanOp->currentItem() ) );
+
+#ifdef HAVE_YAZ
+
+ QString searchTerm = m_widget->lineEditQuery->text().stripWhiteSpace();
+ if ( searchTerm.isEmpty() )
+ {
+ setNumStages( 1 );
+ setEndSearch( WebQuery::statusError );
+ return;
+ }
+
+ QString query = queryClause( searchTerm, m_widget->comboBoxInAttribute->currentItem() );
+
+ searchTerm = m_widget->lineEditQuery2->text().stripWhiteSpace();
+ if ( !searchTerm.isEmpty() )
+ {
+ if ( m_widget->comboBoxBooleanOp->currentItem() == 0 )
+ query = query.prepend( "@and " );
+ else
+ query = query.prepend( "@or " );
+ query = query.append( queryClause( searchTerm, m_widget->comboBoxInAttribute2->currentItem() ) );
+ }
+
+ kdDebug() << "query = " << query << endl;
+
+ m_conn = NULL;
+ settings = Settings::self();
+ for ( QMap<QString, Settings::Z3950Server>::Iterator it = settings->z3950_ServerList.begin(); m_conn == NULL && it != settings->z3950_ServerList.end(); ++it )
+ {
+ if ( it.data().name.compare( m_widget->comboBoxServers->currentText() ) == 0 )
+ {
+ m_syntax = it.data().syntax;
+ m_conn = new KBibTeX::Z3950Connection( this, it.data().host, it.data().port, it.data().database, it.data().charset, m_syntax, "f" );
+ m_conn->setUserPassword( it.data().user, it.data().password );
+ }
+ }
+
+ if ( m_conn != NULL )
+ {
+ setNumStages( m_widget->spinBoxMaxHits->value() );
+ m_started = true;
+
+ m_conn->setQuery( query, m_widget->spinBoxMaxHits->value() );
+ m_modsList.clear();
+ m_hitCounter = 0;
+ m_conn->start();
+ kdDebug() << "WebQueryZ3950::query: started" << endl;
+ }
+ else
+#else // HAVE_YAZ
+ kdDebug() << "HAVE_YAZ not defined" << endl;
+#endif // HAVE_YAZ
+ {
+ setNumStages( 1 );
+ setEndSearch( WebQuery::statusSuccess );
+ }
+ }
+
+ void WebQueryZ3950::cancelQuery()
+ {
+#ifdef HAVE_YAZ
+ if ( m_started && m_conn != NULL )
+ {
+ m_started = false;
+ m_conn->abort();
+ m_conn->wait( 10000 );
+ setEndSearch( WebQuery::statusError );
+ }
+#endif // HAVE_YAZ
+ }
+
+#ifdef HAVE_YAZ
+ QString WebQueryZ3950::queryClause( const QString& text, int field )
+ {
+ QString result = "@attr 1=";
+ switch ( field )
+ {
+ case 1: result.append( "4" ); break;
+ case 2: result.append( "1003" ); break;
+ case 3: result.append( "1006" ); break;
+ case 4: result.append( "1016" ); break;
+ default: result.append( "1018" ); break;
+ }
+ result.append( " @attr 2=3 \"" ).append( text ).append( "\" " );
+
+ return result;
+ }
+#endif // HAVE_YAZ
+
+ void WebQueryZ3950::customEvent( QCustomEvent* event )
+ {
+ kdDebug() << "WebQueryZ3950::customEvent of type " << event->type() << endl;
+
+#ifdef HAVE_YAZ
+ if ( !m_conn )
+ {
+ return;
+ }
+
+ if ( event->type() == KBibTeX::Z3950ResultFound::uid() )
+ {
+ KBibTeX::Z3950ResultFound* e = static_cast<KBibTeX::Z3950ResultFound*>( event );
+ kdDebug() << "Z3950ResultFound: " << e->result().left( 24 ) << " [..] " << e->result().right( 24 ) << endl;
+ storeResult( e->result(), m_syntax );
+ m_hitCounter++;
+ enterNextStage();
+ }
+
+ else if ( event->type() == KBibTeX::Z3950ConnectionDone::uid() )
+ {
+ KBibTeX::Z3950ConnectionDone* e = static_cast<KBibTeX::Z3950ConnectionDone*>( event );
+ kdDebug() << "Z3950ConnectionDone: " << e->message() << " (" << e->messageType() << ")" << endl;
+ if ( e->messageType() > -1 )
+ KMessageBox::error( m_widget, QString( i18n( "The server returned the following message:\n\n%1" ) ).arg( e->message() ), i18n( "Error querying Z39.50 server" ) );
+
+ m_started = false;
+ if ( m_conn != NULL )
+ m_conn->wait();
+
+ if ( !m_aborted )
+ {
+ evalStoredResults();
+ setEndSearch( e->messageType() > -1 ? WebQuery::statusError : WebQuery::statusSuccess );
+ }
+ }
+
+ qApp->processEvents();
+#endif // HAVE_YAZ
+ }
+
+#ifdef HAVE_YAZ
+ void WebQueryZ3950::storeResult( const QString& resultText, const QString& syntax )
+ {
+ if ( resultText.isEmpty() ) return;
+ QString convertedResultText = QString::null;
+
+ if ( syntax == "mods" )
+ convertedResultText = resultText;
+ else if ( syntax == "usmarc" || syntax == "marc21" )
+ {
+ if ( m_marc21transformer == NULL ) m_marc21transformer = new BibTeX::XSLTransform( KGlobal::dirs()->findResource( "data", "kbibtexpart/xslt/MARC21slim2MODS3.xsl" ) );
+ convertedResultText = m_marc21transformer->transform( resultText );
+ }
+ else if ( syntax == "unimarc" )
+ {
+ if ( m_unimarctransformer == NULL ) m_unimarctransformer = new BibTeX::XSLTransform( KGlobal::dirs()->findResource( "data", "kbibtexpart/xslt/UNIMARC2MODS3.xsl" ) );
+ convertedResultText = m_unimarctransformer->transform( resultText );
+ }
+
+ m_modsList.append( convertedResultText );
+ }
+
+ void WebQueryZ3950::evalStoredResults()
+ {
+ if ( m_modsImporter == NULL )
+ m_modsImporter = new BibTeX::FileImporterBibUtils( BibTeX::File::formatMODS );
+
+ for ( QStringList::Iterator it = m_modsList.begin(); it != m_modsList.end();++it )
+ {
+ BibTeX::File *bibtexFile = m_modsImporter->load( *it );
+ if ( bibtexFile != NULL )
+ {
+ for ( BibTeX::File::ElementList::iterator it = bibtexFile->begin(); it != bibtexFile->end(); ++it )
+ {
+ BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
+ if ( entry != NULL )
+ {
+ BibTeX::Entry *newEntry = new BibTeX::Entry( entry );
+ kdDebug() << "entry= " << newEntry->text() << endl;
+ emit foundEntry( newEntry, false );
+ }
+ }
+
+ delete bibtexFile;
+ }
+ }
+ }
+#endif // HAVE_YAZ
+
+}
+#include "webqueryz3950.moc"