TDE graphics utilities
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mrml_part.cpp 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. /* This file is part of the KDE project
  2. Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public
  5. License as published by the Free Software Foundation, version 2.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9. General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; see the file COPYING. If not, write to
  12. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  13. Boston, MA 02110-1301, USA.
  14. */
  15. #include <tqcheckbox.h>
  16. #include <tqcursor.h>
  17. #include <tqdir.h>
  18. #include <tqfile.h>
  19. #include <tqgrid.h>
  20. #include <tqhgroupbox.h>
  21. #include <tqlabel.h>
  22. #include <tqpushbutton.h>
  23. #include <tqtooltip.h>
  24. #include <tqvbox.h>
  25. #include <kaboutdata.h>
  26. #include <kapplication.h>
  27. #include <kcombobox.h>
  28. #include <kconfig.h>
  29. #include <kdatastream.h>
  30. #include <kdebug.h>
  31. #include <kglobal.h>
  32. #include <klocale.h>
  33. #include <kiconloader.h>
  34. #include <kinstance.h>
  35. #include <kio/job.h>
  36. #include <kio/jobclasses.h>
  37. #include <kmessagebox.h>
  38. #include <knuminput.h>
  39. #include <kprotocolinfo.h>
  40. #include <kparts/genericfactory.h>
  41. #include <ktempfile.h>
  42. #include <mrml_utils.h>
  43. #include "algorithmdialog.h"
  44. #include "browser.h"
  45. #include "collectioncombo.h"
  46. #include "mrml_creator.h"
  47. #include "mrml_elements.h"
  48. #include "mrml_shared.h"
  49. #include "mrml_view.h"
  50. #include "mrml_part.h"
  51. #include "version.h"
  52. using namespace KMrml;
  53. extern "C"
  54. {
  55. void * init_libkmrmlpart() {
  56. return new KMrml::PartFactory();
  57. }
  58. }
  59. KInstance * PartFactory::s_instance = 0L;
  60. PartFactory::PartFactory()
  61. : KParts::Factory()
  62. {
  63. MrmlShared::ref();
  64. }
  65. PartFactory::~PartFactory()
  66. {
  67. MrmlShared::deref();
  68. delete s_instance;
  69. s_instance = 0L;
  70. }
  71. KInstance * PartFactory::instance()
  72. {
  73. if ( !s_instance ) {
  74. s_instance = new KInstance( "kmrml" );
  75. KGlobal::locale()->insertCatalogue( "kmrml" );
  76. }
  77. return s_instance;
  78. }
  79. KParts::Part * PartFactory::createPartObject( TQWidget *parentWidget,
  80. const char *widgetName,
  81. TQObject *parent,
  82. const char *name,
  83. const char *,
  84. const TQStringList& args )
  85. {
  86. return new MrmlPart( parentWidget, widgetName, parent, name, args );
  87. }
  88. // can't use this due to MrmlShared ref-counting
  89. // typedef KParts::GenericFactory<KMrml::MrmlPart> PartFactory;
  90. // K_EXPORT_COMPONENT_FACTORY( mrmlpart, PartFactory )
  91. ///////////////////////////////////////////////////////////////////
  92. ///////////////////////////////////////////////////////////////////
  93. uint MrmlPart::s_sessionId = 0;
  94. MrmlPart::MrmlPart( TQWidget *parentWidget, const char * /* widgetName */,
  95. TQObject *parent, const char *name,
  96. const TQStringList& /* args */ )
  97. : KParts::ReadOnlyPart( parent, name ),
  98. m_job( 0L ),
  99. m_status( NeedCollection )
  100. {
  101. m_sessionId = TQString::number( s_sessionId++ ).prepend("kmrml_");
  102. setName( "MRML Part" );
  103. m_browser = new Browser( this, "mrml browserextension");
  104. setInstance( PartFactory::instance(), true ); // do load plugins :)
  105. KConfig *config = PartFactory::instance()->config();
  106. config->setGroup("MRML Settings");
  107. TQVBox *box = new TQVBox( parentWidget, "main mrml box" );
  108. m_view = new MrmlView( box, "MrmlView" );
  109. connect( m_view, TQT_SIGNAL( activated( const KURL&, ButtonState )),
  110. this, TQT_SLOT( slotActivated( const KURL&, ButtonState )));
  111. connect( m_view, TQT_SIGNAL( onItem( const KURL& )),
  112. this, TQT_SLOT( slotSetStatusBar( const KURL& )));
  113. m_panel = new TQHGroupBox( box, "buttons box" );
  114. TQGrid *comboGrid = new TQGrid( 2, m_panel, "combo grid" );
  115. comboGrid->setSpacing( KDialog::spacingHint() );
  116. (void) new TQLabel( i18n("Server to query:"), comboGrid );
  117. m_hostCombo = new KComboBox( false, comboGrid, "host combo" );
  118. initHostCombo();
  119. connect( m_hostCombo, TQT_SIGNAL( activated( const TQString& ) ),
  120. TQT_SLOT( slotHostComboActivated( const TQString& )));
  121. (void) new TQLabel( i18n("Search in collection:"), comboGrid );
  122. m_collectionCombo = new CollectionCombo( comboGrid, "collection-combo" );
  123. // will be re-set in initCollections(), but we need to set it here to
  124. // prevent crashes when the connection to the server fails
  125. m_collectionCombo->setCollections( &m_collections );
  126. m_algoButton = new TQPushButton( TQString(), m_panel );
  127. m_algoButton->setPixmap( SmallIcon("configure") );
  128. m_algoButton->setFixedSize( m_algoButton->tqsizeHint() );
  129. connect( m_algoButton, TQT_SIGNAL( clicked() ),
  130. TQT_SLOT( slotConfigureAlgorithm() ));
  131. TQToolTip::add( m_algoButton, i18n("Configure algorithm") );
  132. TQWidget *spacer = new TQWidget( m_panel );
  133. spacer->tqsetSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding,
  134. TQSizePolicy::Minimum ) );
  135. int resultSize = config->readNumEntry( "Result-size", 20 );
  136. m_resultSizeInput = new KIntNumInput( resultSize, m_panel );
  137. m_resultSizeInput->setRange( 1, 100 );
  138. m_resultSizeInput->setLabel( i18n("Maximum result images:") );
  139. TQVBox *tmp = new TQVBox( m_panel );
  140. m_random = new TQCheckBox( i18n("Random search"), tmp );
  141. m_startButton = new TQPushButton( TQString(), tmp );
  142. connect( m_startButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotStartClicked() ));
  143. settqStatus( NeedCollection );
  144. setWidget( box );
  145. // setXMLFile( "mrml_part.rc" );
  146. slotSetStatusBar( TQString() );
  147. enableServerDependentWidgets( false );
  148. }
  149. MrmlPart::~MrmlPart()
  150. {
  151. closeURL();
  152. }
  153. void MrmlPart::enableServerDependentWidgets( bool enable )
  154. {
  155. m_collectionCombo->setEnabled( enable );
  156. m_algoButton->setEnabled( enable && false ); // ### re-enable!!!
  157. }
  158. void MrmlPart::initCollections( const TQDomElement& elem )
  159. {
  160. m_collections.initFromDOM( elem );
  161. m_collectionCombo->setCollections( &m_collections );
  162. enableServerDependentWidgets( m_collectionCombo->count() > 0 );
  163. if ( m_collectionCombo->count() == 0 )
  164. {
  165. KMessageBox::information( widget(),
  166. i18n("There is no image collection available\n"
  167. "at %1.\n"), i18n("No Image Collection"));
  168. settqStatus( NeedCollection );
  169. }
  170. else
  171. m_collectionCombo->updateGeometry(); // adjust the entire grid
  172. }
  173. void MrmlPart::initAlgorithms( const TQDomElement& elem )
  174. {
  175. m_algorithms.initFromDOM( elem );
  176. }
  177. // this is where we start!
  178. bool MrmlPart::openURL( const KURL& url )
  179. {
  180. closeURL();
  181. if ( url.protocol() != "mrml" || !url.isValid() ) {
  182. qWarning("MrmlPart::openURL: cannot handle url: %s", url.prettyURL().latin1());
  183. return false; // what to do with that?
  184. }
  185. m_url = url;
  186. TQString host = url.host().isEmpty() ?
  187. TQString::tqfromLatin1("localhost") : url.host();
  188. m_hostCombo->setCurrentItem( host );
  189. // urls we need to download before starting the query
  190. KURL::List downloadList;
  191. m_queryList.clear();
  192. TQString param = url.queryItem( "relevant" );
  193. TQStringList list = TQStringList::split( ';', param );
  194. // we can only search by example on localhost
  195. if ( host != "localhost" )
  196. {
  197. if ( !list.isEmpty() )
  198. KMessageBox::sorry( m_view,
  199. i18n("You can only search by example images "
  200. "on a local indexing server."),
  201. i18n("Only Local Servers Possible") );
  202. }
  203. else // localhost query
  204. {
  205. for( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
  206. {
  207. KURL u;
  208. if ( (*it).at(0) == '/' )
  209. u.setPath( *it );
  210. else
  211. u = *it;
  212. if ( u.isValid() )
  213. {
  214. if ( u.isLocalFile() )
  215. m_queryList.append( u );
  216. else
  217. downloadList.append( u );
  218. }
  219. }
  220. // ### we need a real solution for this!
  221. // gift refuses to start when no config file is available.
  222. if ( !TQFile::exists( m_config.mrmldDataDir() + "/gift-config.mrml" ) )
  223. {
  224. if ( KMessageBox::questionYesNo(0L,
  225. i18n("There are no indexable folders "
  226. "specified. Do you want to configure them "
  227. "now?"),
  228. i18n("Configuration Missing"),
  229. i18n("Configure"),
  230. i18n("Do Not Configure"),
  231. "kmrml_ask_configure_gift" )
  232. == KMessageBox::Yes )
  233. {
  234. KApplication::tdeinitExec( "kcmshell",
  235. TQString::tqfromLatin1("kcmkmrml"));
  236. settqStatus( NeedCollection );
  237. return false;
  238. }
  239. }
  240. }
  241. if ( !downloadList.isEmpty() )
  242. downloadReferenceFiles( downloadList );
  243. else
  244. contactServer( m_url );
  245. return true;
  246. }
  247. void MrmlPart::contactServer( const KURL& url )
  248. {
  249. m_job = transferJob( url );
  250. m_job->addMetaData( MrmlShared::kio_task(), MrmlShared::kio_initialize() );
  251. TQString host = url.host().isEmpty() ?
  252. TQString::tqfromLatin1("localhost") : url.host();
  253. slotSetStatusBar( i18n("Connecting to indexing server at %1...").tqarg( host ));
  254. }
  255. //
  256. // schedules a download all urls of downloadList (all remote and wellformed)
  257. // No other downloads are running (closeURL() has been called before)
  258. //
  259. void MrmlPart::downloadReferenceFiles( const KURL::List& downloadList )
  260. {
  261. assert( m_downloadJobs.isEmpty() );
  262. KURL::List::ConstIterator it = downloadList.begin();
  263. for ( ; it != downloadList.end(); it++ )
  264. {
  265. TQString extension;
  266. int index = (*it).fileName().findRev( '.' );
  267. if ( index != -1 )
  268. extension = (*it).fileName().mid( index );
  269. KTempFile tmpFile( TQString(), extension );
  270. if ( tmpFile.status() != 0 )
  271. {
  272. kdWarning() << "Can't create temporary file, skipping: " << *it << endl;
  273. continue;
  274. }
  275. m_tempFiles.append( tmpFile.name() );
  276. KURL destURL;
  277. destURL.setPath( tmpFile.name() );
  278. KIO::FileCopyJob *job = KIO::file_copy( *it, destURL, -1,
  279. true /* overwrite tmpfile */ );
  280. connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
  281. TQT_SLOT( slotDownloadResult( KIO::Job * ) ));
  282. m_downloadJobs.append( job );
  283. // ### should this be only called for one job?
  284. emit started( job );
  285. }
  286. if ( !m_downloadJobs.isEmpty() )
  287. slotSetStatusBar( i18n("Downloading reference files...") );
  288. else // probably never happens
  289. contactServer( m_url );
  290. }
  291. bool MrmlPart::closeURL()
  292. {
  293. m_view->stopDownloads();
  294. m_view->clear();
  295. TQPtrListIterator<KIO::FileCopyJob> it( m_downloadJobs );
  296. for ( ; it.current(); ++it )
  297. it.current()->kill();
  298. m_downloadJobs.clear();
  299. TQStringList::Iterator tit = m_tempFiles.begin();
  300. for ( ; tit != m_tempFiles.end(); ++tit )
  301. TQFile::remove( *tit );
  302. m_tempFiles.clear();
  303. if ( m_job ) {
  304. m_job->kill();
  305. m_job = 0L;
  306. }
  307. settqStatus( NeedCollection );
  308. return true;
  309. }
  310. KIO::TransferJob * MrmlPart::transferJob( const KURL& url )
  311. {
  312. KIO::TransferJob *job = KIO::get( url, true, false ); // reload, no gui
  313. job->setAutoErrorHandlingEnabled( true, m_view );
  314. connect( job, TQT_SIGNAL( result( KIO::Job * )),
  315. TQT_SLOT( slotResult( KIO::Job * )));
  316. connect( job, TQT_SIGNAL( data( KIO::Job *, const TQByteArray& )),
  317. TQT_SLOT( slotData( KIO::Job *, const TQByteArray& )));
  318. // ###
  319. // connect( job, TQT_SIGNAL( infoMessage( KIO::Job *, const TQString& )),
  320. // TQT_SLOT( slotResult( KIO::Job *, const TQString& )));
  321. job->setWindow( widget() );
  322. if ( !m_sessionId.isEmpty() )
  323. job->addMetaData( MrmlShared::sessionId(), m_sessionId );
  324. emit started( job );
  325. emit setWindowCaption( url.prettyURL() );
  326. settqStatus( InProgress );
  327. return job;
  328. }
  329. void MrmlPart::slotResult( KIO::Job *job )
  330. {
  331. if ( job == m_job )
  332. m_job = 0L;
  333. slotSetStatusBar( TQString() );
  334. if ( !job->error() )
  335. emit completed();
  336. else {
  337. emit canceled( job->errorString() );
  338. // qDebug("*** canceled: error: %s", job->errorString().latin1());
  339. }
  340. bool auto_random = m_view->isEmpty() && m_queryList.isEmpty();
  341. m_random->setChecked( auto_random );
  342. m_random->setEnabled( !auto_random );
  343. settqStatus( job->error() ? NeedCollection : CanSearch );
  344. if ( !job->error() && !m_queryList.isEmpty() ) {
  345. // we have a connection and we got a list of relevant URLs to query for
  346. // (via the URL)
  347. createQuery( &m_queryList );
  348. m_queryList.clear();
  349. }
  350. }
  351. // ### when user cancels download, we crash :(
  352. void MrmlPart::slotDownloadResult( KIO::Job *job )
  353. {
  354. assert( job->inherits( "KIO::FileCopyJob" ) );
  355. KIO::FileCopyJob *copyJob = static_cast<KIO::FileCopyJob*>( job );
  356. if ( !copyJob->error() )
  357. m_queryList.append( copyJob->destURL() );
  358. m_downloadJobs.removeRef( copyJob );
  359. if ( m_downloadJobs.isEmpty() ) // finally, we can start the query!
  360. {
  361. if ( m_queryList.isEmpty() ) // rather unlikely, but could happen ;)
  362. {
  363. kdWarning() << "Couldn't download the reference files. Will start a random search now" << endl;
  364. }
  365. contactServer( m_url );
  366. }
  367. }
  368. // mrml-document in the bytearray
  369. void MrmlPart::slotData( KIO::Job *, const TQByteArray& data )
  370. {
  371. if ( data.isEmpty() )
  372. return;
  373. TQDomDocument doc;
  374. doc.setContent( data );
  375. if ( !doc.isNull() )
  376. parseMrml( doc );
  377. }
  378. void MrmlPart::parseMrml( TQDomDocument& doc )
  379. {
  380. TQDomNode mrml = doc.documentElement(); // root element
  381. if ( !mrml.isNull() ) {
  382. TQDomNode child = mrml.firstChild();
  383. for ( ; !child.isNull(); child = child.nextSibling() ) {
  384. // qDebug("**** HERE %s", child.nodeName().latin1());
  385. if ( child.isElement() ) {
  386. TQDomElement elem = child.toElement();
  387. TQString tagName = elem.tagName();
  388. if ( tagName == "acknowledge-session-op" )
  389. m_sessionId = elem.attribute( MrmlShared::sessionId() );
  390. else if ( tagName == MrmlShared::algorithmList() ) {
  391. initAlgorithms( elem );
  392. }
  393. else if ( tagName == MrmlShared::collectionList() ) {
  394. initCollections( elem );
  395. }
  396. else if ( tagName == "error" ) {
  397. KMessageBox::information( widget(),
  398. i18n("Server returned error:\n%1\n")
  399. .tqarg( elem.attribute( "message" )),
  400. i18n("Server Error") );
  401. }
  402. else if ( tagName == "query-result" ) {
  403. m_view->clear();
  404. parseQueryResult( elem );
  405. }
  406. } // child.isElement()
  407. }
  408. } // !mrml.isNull()
  409. }
  410. void MrmlPart::parseQueryResult( TQDomElement& queryResult )
  411. {
  412. TQDomNode child = queryResult.firstChild();
  413. for ( ; !child.isNull(); child = child.nextSibling() ) {
  414. if ( child.isElement() ) {
  415. TQDomElement elem = child.toElement();
  416. TQString tagName = elem.tagName();
  417. if ( tagName == "query-result-element-list" ) {
  418. TQValueList<TQDomElement> list =
  419. KMrml::directChildElements( elem, "query-result-element" );
  420. TQValueListConstIterator<TQDomElement> it = list.begin();
  421. for ( ; it != list.end(); ++it )
  422. {
  423. TQDomNamedNodeMap a = (*it).attributes();
  424. m_view->addItem( KURL( (*it).attribute("image-location" ) ),
  425. KURL( (*it).attribute("thumbnail-location" ) ),
  426. (*it).attribute("calculated-similarity"));
  427. }
  428. }
  429. else if ( tagName == "query-result" )
  430. parseQueryResult( elem );
  431. }
  432. }
  433. }
  434. // creates/stops the query when the Start/Stop button was pressed
  435. void MrmlPart::slotStartClicked()
  436. {
  437. if ( m_status == InProgress )
  438. {
  439. closeURL();
  440. m_startButton->setText( i18n("&Search" ) );
  441. return;
  442. }
  443. // we need to reconnect, if the initial openURL() didn't work due to
  444. // the gift not being available.
  445. if ( m_status == NeedCollection )
  446. {
  447. openURL( m_url );
  448. return;
  449. }
  450. // cut off an eventual query and reference from the url, when the user
  451. // performs a real query (otherwise restoreState() would restore and
  452. // re-do the query from the URL
  453. m_url.setRef( TQString() );
  454. m_url.setQuery( TQString() );
  455. createQuery();
  456. m_browser->openURLNotify();
  457. }
  458. //
  459. // relevantItems is 0L when called from slotStartClicked() and set to a
  460. // non-empty list when called initially, from the commandline.
  461. //
  462. void MrmlPart::createQuery( const KURL::List * relevantItems )
  463. {
  464. if ( relevantItems && relevantItems->isEmpty() )
  465. return;
  466. TQDomDocument doc( "mrml" );
  467. TQDomElement mrml = MrmlCreator::createMrml( doc,
  468. sessionId(),
  469. transactionId() );
  470. Collection coll = currentCollection();
  471. // qDebug("** collection: name: %s, id: %s, valid: %i", coll.name().latin1(), coll.id().latin1(), coll.isValid());
  472. Algorithm algo = firstAlgorithmForCollection( coll );
  473. // qDebug("** algorithm: name: %s, id: %s, valid: %i, collection-id: %s", algo.name().latin1(), algo.id().latin1(), algo.isValid(), algo.collectionId().latin1());
  474. if ( algo.isValid() )
  475. {
  476. MrmlCreator::configureSession( mrml, algo, sessionId() );
  477. }
  478. TQDomElement query = MrmlCreator::addQuery( mrml,
  479. m_resultSizeInput->value() );
  480. if ( algo.isValid() )
  481. query.setAttribute( MrmlShared::algorithmId(), algo.id() );
  482. // ### result-cutoff, query-type?
  483. // start-up with/without urls on the commandline via mrmlsearch
  484. if ( relevantItems )
  485. {
  486. TQDomElement elem = MrmlCreator::addRelevanceList( query );
  487. KURL::List::ConstIterator it = relevantItems->begin();
  488. for ( ; it != relevantItems->end(); ++it )
  489. MrmlCreator::createRelevanceElement( doc, elem, (*it).url(),
  490. MrmlCreator::Relevant );
  491. }
  492. // get relevant items from the view? Only do this when relevantItems is 0L
  493. else if ( !m_random->isChecked() )
  494. {
  495. TQDomElement relevants = MrmlCreator::addRelevanceList( query );
  496. m_view->addRelevanceToQuery( doc, relevants );
  497. }
  498. performQuery( doc );
  499. }
  500. Collection MrmlPart::currentCollection() const
  501. {
  502. return m_collectionCombo->current();
  503. }
  504. Algorithm MrmlPart::firstAlgorithmForCollection( const Collection& coll ) const
  505. {
  506. if ( !m_algorithms.isEmpty() )
  507. {
  508. AlgorithmList::ConstIterator it = m_algorithms.begin();
  509. for ( ; it != m_algorithms.end(); ++it )
  510. {
  511. Algorithm algo = *it;
  512. if ( algo.paradigms().matches( coll.paradigms() ) )
  513. {
  514. algo.setCollectionId( coll.id() );
  515. return algo;
  516. }
  517. }
  518. }
  519. qDebug("#################### -> ADEFAULT!");
  520. Algorithm algo = Algorithm::defaultAlgorithm();
  521. algo.setCollectionId( coll.id() );
  522. return algo;
  523. }
  524. // emits the given TQDomDocument for eventual plugins, checks after that
  525. // if there are any relevance elements. If there are none, random search is
  526. // implied and performed.
  527. // finally, the search is actually started
  528. void MrmlPart::performQuery( TQDomDocument& doc )
  529. {
  530. TQDomElement mrml = doc.documentElement();
  531. emit aboutToStartQuery( doc ); // let plugins play with it :)
  532. // no items available? All "neutral"? -> random search
  533. TQDomElement queryStep = KMrml::firstChildElement( mrml, "query-step" );
  534. bool randomSearch = false;
  535. if ( !queryStep.isNull() )
  536. {
  537. TQDomElement relevanceList =
  538. KMrml::firstChildElement(queryStep, "user-relevance-element-list");
  539. TQValueList<TQDomElement> relevanceElements =
  540. KMrml::directChildElements( relevanceList,
  541. "user-relevance-element" );
  542. randomSearch = relevanceElements.isEmpty();
  543. if ( randomSearch )
  544. {
  545. m_random->setChecked( true );
  546. m_random->setEnabled( false );
  547. queryStep.setAttribute("query-type", "at-random");
  548. // remove user-relevance-element-list element for random search
  549. relevanceList.parentNode().removeChild( relevanceList );
  550. }
  551. }
  552. else
  553. {
  554. KMessageBox::error( m_view, i18n("Error formulating the query. The "
  555. "\"query-step\" element is missing."),
  556. i18n("Query Error") );
  557. }
  558. m_job = transferJob( url() );
  559. slotSetStatusBar( randomSearch ? i18n("Random search...") :
  560. i18n("Searching...") );
  561. m_job->addMetaData( MrmlShared::kio_task(), MrmlShared::kio_startQuery() );
  562. qDebug("\n\nSending XML:\n%s", doc.toString().latin1());
  563. m_job->addMetaData( MrmlShared::mrml_data(), doc.toString() );
  564. }
  565. void MrmlPart::slotSetStatusBar( const TQString& text )
  566. {
  567. if ( text.isEmpty() )
  568. emit setStatusBarText( i18n("Ready.") );
  569. else
  570. emit setStatusBarText( text );
  571. }
  572. void MrmlPart::slotActivated( const KURL& url, ButtonState button )
  573. {
  574. if ( button == Qt::LeftButton )
  575. emit m_browser->openURLRequest( url );
  576. else if ( button == Qt::MidButton )
  577. emit m_browser->createNewWindow( url );
  578. else if ( button == Qt::RightButton ) {
  579. // enableExtensionActions( url, true ); // for now
  580. emit m_browser->popupMenu( TQCursor::pos(), url, TQString() );
  581. // enableExtensionActions( url, false );
  582. }
  583. }
  584. void MrmlPart::enableExtensionActions( const KURL& url, bool enable )
  585. {
  586. bool del = KProtocolInfo::supportsDeleting( url );
  587. emit m_browser->enableAction( "copy", enable );
  588. emit m_browser->enableAction( "trash", del );
  589. emit m_browser->enableAction( "del", del );
  590. emit m_browser->enableAction( "shred", url.isLocalFile() );
  591. emit m_browser->enableAction( "properties", enable );
  592. // emit m_browser->enableAction( "print", enable ); // ### later
  593. }
  594. // only implemented because it's abstract in the baseclass
  595. bool MrmlPart::openFile()
  596. {
  597. return false;
  598. }
  599. void MrmlPart::slotConfigureAlgorithm()
  600. {
  601. m_algoButton->setEnabled( false );
  602. m_algoConfig = new AlgorithmDialog( m_algorithms, m_collections,
  603. currentCollection(),
  604. m_view, "algorithm configuration" );
  605. connect( m_algoConfig, TQT_SIGNAL( applyClicked() ),
  606. TQT_SLOT( slotApplyAlgoConfig() ));
  607. connect( m_algoConfig, TQT_SIGNAL( finished() ),
  608. TQT_SLOT( slotAlgoConfigFinished() ));
  609. m_algoConfig->show();
  610. }
  611. void MrmlPart::slotApplyAlgoConfig()
  612. {
  613. // ###
  614. }
  615. void MrmlPart::slotAlgoConfigFinished()
  616. {
  617. if ( m_algoConfig->result() == TQDialog::Accepted )
  618. slotApplyAlgoConfig();
  619. m_algoButton->setEnabled( true );
  620. m_algoConfig->deleteLater();
  621. m_algoConfig = 0L;
  622. }
  623. void MrmlPart::initHostCombo()
  624. {
  625. m_hostCombo->clear();
  626. m_hostCombo->insertStringList( m_config.hosts() );
  627. }
  628. void MrmlPart::slotHostComboActivated( const TQString& host )
  629. {
  630. ServerSettings settings = m_config.settingsForHost( host );
  631. openURL( settings.getUrl() );
  632. }
  633. void MrmlPart::settqStatus( tqStatus status )
  634. {
  635. switch ( status )
  636. {
  637. case NeedCollection:
  638. m_startButton->setText( i18n("&Connect") );
  639. break;
  640. case CanSearch:
  641. m_startButton->setText( i18n("&Search") );
  642. break;
  643. case InProgress:
  644. m_startButton->setText( i18n("Sto&p") );
  645. break;
  646. };
  647. m_status = status;
  648. }
  649. void MrmlPart::saveState( TQDataStream& stream )
  650. {
  651. stream << url();
  652. stream << m_sessionId;
  653. stream << m_queryList;
  654. // stream << m_algorithms;
  655. // stream << m_collections;
  656. stream << m_resultSizeInput->value();
  657. stream << *m_collectionCombo;
  658. m_view->saveState( stream );
  659. }
  660. void MrmlPart::restoreState( TQDataStream& stream )
  661. {
  662. KURL url;
  663. stream >> url;
  664. stream >> m_sessionId;
  665. stream >> m_queryList;
  666. // stream >> m_algorithms;
  667. // stream >> m_collections;
  668. int resultSize;
  669. stream >> resultSize;
  670. m_resultSizeInput->setValue( resultSize );
  671. stream >> *m_collectionCombo;
  672. m_view->restoreState( stream );
  673. // openURL( url );
  674. m_url = url;
  675. }
  676. KAboutData * MrmlPart::createAboutData()
  677. {
  678. KAboutData *data = new KAboutData(
  679. "kmrml",
  680. I18N_NOOP("MRML Client for KDE"),
  681. KMRML_VERSION,
  682. I18N_NOOP("A tool to search for images by their content"),
  683. KAboutData::License_GPL,
  684. I18N_NOOP("(c) 2001-2002, Carsten Pfeiffer"),
  685. 0,
  686. I18N_NOOP("http://devel-home.kde.org/~pfeiffer/kmrml/") );
  687. data->addAuthor( "Carsten Pfeiffer",
  688. I18N_NOOP("Developer, Maintainer"),
  689. "pfeiffer@kde.org" );
  690. data->addCredit( "Wolfgang Mller",
  691. I18N_NOOP("Developer of the GIFT, Helping Hand") );
  692. return data;
  693. }
  694. ///////////////////////////////////////////////////////////////////
  695. ///////////////////////////////////////////////////////////////////
  696. #include "mrml_part.moc"