diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 47d455dd55be855e4cc691c32f687f723d9247ee (patch) | |
tree | 52e236aaa2576bdb3840ebede26619692fed6d7d /kmrml | |
download | tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kmrml')
66 files changed, 8237 insertions, 0 deletions
diff --git a/kmrml/AUTHORS b/kmrml/AUTHORS new file mode 100644 index 00000000..9e0745fb --- /dev/null +++ b/kmrml/AUTHORS @@ -0,0 +1 @@ +Carsten Pfeiffer <pfeiffer@kde.org> diff --git a/kmrml/ChangeLog b/kmrml/ChangeLog new file mode 100644 index 00000000..9dbd3ea3 --- /dev/null +++ b/kmrml/ChangeLog @@ -0,0 +1,28 @@ +Uh er, looks like I didn't add all the other changes lately :} Sorry... + +Sun May 6 04:40:52 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + * UI is a bit nicer now (arrangement of thumbnail items) + + * it's possible to search by example, i.e. by right-clicking + on one or more images and selecting "search for similar images" + + * tiny bit of code cleanup + +Sat May 5 02:30:21 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + * argh, fixed the bug that files couldn't get downloaded by + clicking on them and that the statusbar isn't updated. + casts suck :} That took me a lot of time to find out :( + + * added middle-button -> create new window + + * scroll to top when loading a new page + + * show standard popupmenu on right-click on image + + * schedule the slaves instead of creating all at once + +Sam Apr 28 00:09:17 CEST 2001 - Carsten Pfeiffer <pfeiffer@kde.org> + o Initial Creation + didn't do any entries until something is actually working :) diff --git a/kmrml/Makefile.am b/kmrml/Makefile.am new file mode 100644 index 00000000..c48d9eb6 --- /dev/null +++ b/kmrml/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = kmrml diff --git a/kmrml/README b/kmrml/README new file mode 100644 index 00000000..59f2dd9b --- /dev/null +++ b/kmrml/README @@ -0,0 +1,95 @@ +kio_mrml and mrml_part + +Carsten Pfeiffer <pfeiffer@kde.org> 2001/05/03 +---------------------------------------------------------------------- +These are the sources for an mrml kioslave and an accompanying KPart. + + +How does it work in Konqueror? +============================== +For now, the MrmlPart is rather a proof of concept, than a full blown +MRML client. + +You can start the MrmlPart by entering an appropriate URL into Konqueror, +e.g. mrml://user:pass@host.domain:port +user, pass and domain are optional, so if you're running a server locally +yourself, you can enter mrml://localhost to make Konqueror show the +MrmlPart. If you don't have a running GIFT-server, you can try out +mrml://viper.unige.ch:12790 as an example. Then, Konqueror will try to +connect the server at the given URL and show you a list of +image-collections the server has available. You can specify the number +of images a query should return and you can hit the Search-button +to actually start the query. If you don't give an image as example for +the query, it will return random images from the collection. + +Shortly after hitting the Search-button, you will see a list of images +as thumbnails. Below every image is a small rectangle showing the +similarity of the image with the example image(s). The longer the +rectangle, the better the match. + +Even easier than entering the mrml URL is right-clicking on an image +in Konqueror and selecting "Search for similar images..." in the context +menu. This will open up a new Konqueror window where the query will start +automatically. By default, this will try to contact a local server, i.e +mrml://localhost. You can configure different servers in the KControl +Module (System -> Advanced Search). The last chosen server will be used +for those queries. + +Note that a remote server surely can't access an image from your home +direcory though. I have to think a little bit about the usability of +this :) The greatest use of this is when you've indexed your files +and running an own GIFT server anyway. Ideally, the server could be +started on demand, when a query comes up. + + +MrmlPart: +========= + This KPart makes use of the mrml ioslave to provide a full MRML +client. MRML, Multimedia Retrieval Markup Language (see +http://www.mrml.net) is a means to query CBIR (Content Based Image +Retrieval) servers. An OpenSource server is the GIFT (GNU Image +Finding Tool), see www.mrml.net for downloading the GIFT. + +You can query for images by choosing one or more "example" images. +The server will search for images that have similarities to the +example(s) you gave. Queries can be refined by specifying relevance, +i.e. by including and excluding parts of the previous search result. + + +mrml ioslave: +============= + Basically this is not much more than a slave for asynchronous +transport of "data". With the URL, you can specify the user, password +and port, as well as the url of the server to connect to. + +The data exchange of client <-> slave is done via metaData, with an +"mrml_data" key. The data that the slave sends to the client is sent +in one big chunk, after all the data has arrived at the slave. This +could be made configurable later. + +With a little tuning, one could turn this into a generic slave +which can transport any kind of data. + +[mrmlsearch] +This little baby is called from Konqueror's popupmenu, when you hit +"Search for similar images...". This program simply gets the URLs +from Konqueror and creates a query of the form +mrml://host.com/?relevant=url1;url2;url3;url4.... +It will use the currently selected host in the KControl module +System -> Advanced Search to perform the query. + +mrmlsearch will then invoke "kfmclient openURL query" to start open +a new Konqueror window and perform the query. + + +Thanks go to Wolfgang Mller <Wolfgang.Mueller@cui.unige.ch> for his +work on the GIFT and for making me write this frontend :) I really +had a WOW-effect about the GIFT, when MrmlPart returned the first +query results. + +New versions of this package can be found at +http://devel-home.kde.org/~pfeiffer/kmrml/ +See http://www.mrml.net for downloading the GIFT and more information. + +Have fun, + Carsten Pfeiffer diff --git a/kmrml/README.DEVELOPMENT b/kmrml/README.DEVELOPMENT new file mode 100644 index 00000000..6fbe600d --- /dev/null +++ b/kmrml/README.DEVELOPMENT @@ -0,0 +1,41 @@ +This file gives an overview of the structure of the kmrml package. + +kmrml consists of the following: + +- kio_mrml: an ioslave that is able to contact an mrml daemon (i.e. the GIFT) + and transports the data from the daemon to its master (i.e. the + MrmlPart) as XML (MRML, Multimedia Retrieval Markup Language) + +- MrmlPart: the konqueror-embeddable controller and view + +- mrmlsearch: a small tool that is e.g. called from Konqueror's ContextMenu + "Search for similar images" to start an image query. + +- kcontrol/: a KDE Control Center module for configuring parts of the GIFT, + i.e. indexing directories, specifying GIFT hosts, etc. + +- server/: a kded module, i.e. a tiny little daemon, that can be told via + DCOP to start, restart upon failure and automatically/manually + stop services. It is completely independent of GIFT/kmrml. + It is used to have one centralized place where the gift server + is started (ensuring this happens only once, restarting it upon + failure and stopping the gift after all kio_mrml instances + have been killed. + +lib/: common stuff used by more than one module + + +Useful URLs: + +The MRML DTD: +http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/gift/gift/dtd/mrml.dtd?rev=HEAD&content-type=text/plain + +The GIFT Homepage: +http://www.gnu.org/software/gift + +The fer-de-lance project homepage, under which the GIFT and kmrml are living +http://www.fer-de-lance.org + + +2002/08/08 +Carsten Pfeiffer <pfeiffer@kde.org> diff --git a/kmrml/TODO b/kmrml/TODO new file mode 100644 index 00000000..85a9aa7f --- /dev/null +++ b/kmrml/TODO @@ -0,0 +1,15 @@ +- Konqueror Properties dialog for indexing directory? Or just a context menu entry? +- make use of BrowserExtension, provide the actions +- contextmenu +- better layouting? +- better keyboard support +- progress report from slave +- transfer mrml in chunks as data arrives? +- finish algorithm configuration +- integrate with KPaint so you can paint an example image +- integrate with kamera, so that images from your digicam will be indexed automatically +- create Konq ContextMenu plugin instead of the ServiceMenu thing (mrmlsearch binary) +- proper browserextension (restorestate/savestate, history, implement actions) +- a panel applet or tray app KDirWatching indexable dirs and re-indexing on demand + +lots more probably diff --git a/kmrml/example-session.mrml b/kmrml/example-session.mrml new file mode 100644 index 00000000..27b5c009 --- /dev/null +++ b/kmrml/example-session.mrml @@ -0,0 +1,142 @@ + <algorithm-list> + <algorithm + algorithm-name="Classical IDF" + algorithm-id="a-cidf" + algorithm-type="a-cidf" > + cui-block-texture-histogram="no" + collection-id="c-0-40-20-27-3-101-5-116-0" + cui-pr-percentage-of-features="70" + cui-block-texture-blocks="no" + cui-weighting-function="ClassicalIDF" + cui-base-type="inverted_file" + cui-block-color-histogram="no" + cui-block-color-blocks="no" + <query-paradigm-list> + <query-paradigm/> + </query-paradigm-list> + + + <property-sheet + send-type="none" + maxsubsetsize="1" + property-sheet-id="cui-p-1" + minsubsetsize="0" + property-sheet-type="subset" > + <property-sheet + caption="Modify default configuration" + send-type="none" + property-sheet-id="cui-p0" + property-sheet-type="set-element" > + + <property-sheet + send-name="cui-pr-percentage-of-features" + send-value="70" + caption="Prune at % of features" + send-type="attribute" + from="20" + to="100" + step="5" + property-sheet-id="cui-p15" + property-sheet-type="numeric" /> + + <property-sheet + send-type="none" + maxsubsetsize="4" + property-sheet-id="cui-p1" + minsubsetsize="1" + property-sheet-type="subset" > + <property-sheet + send-name="cui-block-color-blocks" + send-value="yes" + caption="Colour blocks" + send-type="attribute" + property-sheet-id="cui-p12" + send-boolean-inverted="yes" + property-sheet-type="set-element" /> + <property-sheet + send-name="cui-block-texture-blocks" + send-value="yes" + caption="Gabor blocks" + send-type="attribute" + property-sheet-id="cui-p14" + send-boolean-inverted="yes" + property-sheet-type="set-element" /> + <property-sheet + send-name="cui-block-texture-histogram" + send-value="yes" + caption="Gabor histogram" + send-type="attribute" + property-sheet-id="cui-p13" + send-boolean-inverted="yes" + property-sheet-type="set-element" /> + <property-sheet + send-name="cui-block-color-histogram" + send-value="yes" + caption="Colour histogram" + send-type="attribute" + property-sheet-id="cui-p11" + send-boolean-inverted="yes" + property-sheet-type="set-element" /> + </property-sheet> + </property-sheet> + </property-sheet> + + + </algorithm> + + + <!-- --> + + + <algorithm cui-perl-query-function="processGIFTQueryCall" algorithm-id="a-perl" cui-perl-script-file="/home/gis/gift-embed-perl-modules.pl" cui-perl-package="CGIFTLink" collection-id="c-0-40-20-27-3-101-5-116-0" cui-perl-random-function="processGIFTRandomQueryCall" cui-weighting-function="ClassicalIDF" algorithm-name="Perl link" cui-base-type="perl" algorithm-type="a-perl" > + <query-paradigm-list> + <query-paradigm type="inverted-file" /> + <query-paradigm type="perl-demo" /> + </query-paradigm-list> + + + <property-sheet send-type="none" maxsubsetsize="1" property-sheet-id="cui-p-1" minsubsetsize="0" property-sheet-type="subset" > + <property-sheet caption="Modify default configuration" send-type="none" property-sheet-id="cui-p0" property-sheet-type="set-element" /> + </property-sheet> + </algorithm> + <algorithm cui-block-texture-histogram="no" algorithm-id="adefault" collection-id="c-0-40-20-27-3-101-5-116-0" cui-pr-percentage-of-features="70" cui-block-texture-blocks="no" cui-weighting-function="ClassicalIDF" algorithm-name="Separate Normalisation" cui-base-type="multiple" cui-block-color-histogram="no" cui-block-color-blocks="no" algorithm-type="adefault" > + <algorithm cui-block-texture-histogram="yes" algorithm-id="sub1" cui-pr-percentage-of-features="100" cui-block-texture-blocks="yes" algorithm-name="sub1" cui-base-type="inverted_file" cui-block-color-blocks="yes" algorithm-type="sub1" /> + <algorithm cui-block-texture-histogram="yes" algorithm-id="sub2" cui-block-texture-blocks="yes" algorithm-name="sub2" cui-base-type="inverted_file" cui-block-color-histogram="yes" algorithm-type="sub2" /> + <algorithm algorithm-id="sub3" cui-pr-percentage-of-features="100" cui-block-texture-blocks="yes" algorithm-name="sub3" cui-base-type="inverted_file" cui-block-color-histogram="yes" cui-block-color-blocks="yes" algorithm-type="sub3" /> + <algorithm cui-block-texture-histogram="yes" algorithm-id="sub4" algorithm-name="sub4" cui-base-type="inverted_file" cui-block-color-histogram="yes" cui-block-color-blocks="yes" algorithm-type="sub4" /> + <query-paradigm-list> + <query-paradigm/> + </query-paradigm-list> + <property-sheet send-type="none" maxsubsetsize="1" property-sheet-id="cui-p-1" minsubsetsize="0" property-sheet-type="subset" > + <property-sheet caption="Modify default configuration" send-type="none" property-sheet-id="cui-p0" property-sheet-type="set-element" > + <property-sheet send-name="cui-pr-percentage-of-features" send-value="70" caption="Prune at % of features" send-type="attribute" from="20" to="100" step="5" property-sheet-id="cui-p15" property-sheet-type="numeric" /> + <property-sheet send-type="none" maxsubsetsize="4" property-sheet-id="cui-p1" minsubsetsize="1" property-sheet-type="subset" > + <property-sheet send-name="cui-block-color-blocks" send-value="yes" caption="Colour blocks" send-type="attribute" property-sheet-id="cui-p12" send-boolean-inverted="yes" property-sheet-type="set-element" /> + <property-sheet send-name="cui-block-texture-blocks" send-value="yes" caption="Gabor blocks" send-type="attribute" property-sheet-id="cui-p14" send-boolean-inverted="yes" property-sheet-type="set-element" /> + <property-sheet send-name="cui-block-texture-histogram" send-value="yes" caption="Gabor histogram" send-type="attribute" property-sheet-id="cui-p13" send-boolean-inverted="yes" property-sheet-type="set-element" /> + <property-sheet send-name="cui-block-color-histogram" send-value="yes" caption="Colour histogram" send-type="attribute" property-sheet-id="cui-p11" send-boolean-inverted="yes" property-sheet-type="set-element" /> + </property-sheet> + </property-sheet> + </property-sheet> + </algorithm> + </algorithm-list> + + + + <collection-list> + <collection + collection-name="images" + collection-id="c-0-40-20-27-3-101-5-116-0" + cui-inverted-file-location="InvertedFile.db" + cui-offset-file-location="InvertedFileOffset.db" + cui-algorithm-id-list-id="ail-inverted-file" + cui-feature-file-location="url2fts.xml" + cui-feature-description-location="InvertedFileFeatureDescription.db" + cui-base-dir="/home/gis/gift-indexing-data/images//" + cui-number-of-images="372" > + <query-paradigm-list> + <query-paradigm type="inverted-file" /> + <query-paradigm type="perl-demo" /> + </query-paradigm-list> + </collection> + </collection-list> diff --git a/kmrml/kmrml.lsm b/kmrml/kmrml.lsm new file mode 100644 index 00000000..4b2dfeb6 --- /dev/null +++ b/kmrml/kmrml.lsm @@ -0,0 +1,27 @@ +Begin3 +Title: MRML for KDE -- Content based image retrieval +Version: 0.3.2 +Entered-date: 2001/06/05 +Description: MRML is short for Multimedia Retrieval Markup Language, + which defines a protocol for querying a server for images + based on their content. See http://www.mrml.net about MRML + and the GNU Image Finding Tool (GIFT), an MRML server. + + This package consists of an mrml kio-slave that handles + the communication with the MRML server and a KPart to + be embedded e.g. into Konqueror. + + With those, you can search for images by giving an example + image and let the server look up similar images. The query + result can be refined by giving positive/negative feedback. +Keywords: Image retrieval, GIFT, MRML, Konqueror, KDE, Qt +Author: Carsten Pfeiffer <pfeiffer@kde.org> +Maintained-by: Carsten Pfeiffer <pfeiffer@kde.org> +Home-page: http://devel-home.kde.org/~pfeiffer/kmrml/ +Alternate-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils +Primary-site: http://devel-home.kde.org/~pfeiffer/kmrml/ + xxxxxx kmrml-0.3.2.tgz + xxx kmrml-0.3.2.lsm +Platform: Unix. Needs KDE 3.x +Copying-policy: GPL +End diff --git a/kmrml/kmrml.spec b/kmrml/kmrml.spec new file mode 100644 index 00000000..79dbab29 --- /dev/null +++ b/kmrml/kmrml.spec @@ -0,0 +1,62 @@ +%define version 0.3 +%define release 1 +%define serial 1 +%define prefix /opt/kde3 + +Name: kmrml +Summary: MRML for KDE -- Content based image retrieval +Version: %{version} +Release: %{release} +Serial: %{serial} +Source: http://devel-home.kde.org/~pfeiffer/kmrml/kmrml-%{version}.tgz +URL: http://devel-home.kde.org/~pfeiffer/kmrml/ +Copyright: GPL +Packager: Carsten Pfeiffer <pfeiffer@kde.org> +Group: X11/KDE/Utilities +BuildRoot: /tmp/kmrml-%{version}-root +Prefix: %{prefix} + +%description +MRML is short for Multimedia Retrieval Markup Language, +which defines a protocol for querying a server for images +based on their content. See http://www.mrml.net about MRML +and the GNU Image Finding Tool (GIFT), an MRML server. + +This package consists of an mrml kio-slave that handles +the communication with the MRML server and a KPart to +be embedded e.g. into Konqueror. + +With those, you can search for images by giving an example +image and let the server look up similar images. The query +result can be refined by giving positive/negative feedback. + +Install with '--prefix $KDEDIR' unless you have KDE in /opt/kde3 + +%prep +rm -rf $RPM_BUILD_ROOT + +%setup -n kmrml-%{version} + +%build +export KDEDIR=%{prefix} +CXXFLAGS="$RPM_OPT_FLAGS -fno-exceptions -malign-functions=2 -malign-jumps=2 -malign-loops=2 -pipe" LDFLAGS=-s ./configure --prefix=%{prefix} --enable-final --disable-debug +mkdir -p $RPM_BUILD_ROOT +make + +%install +make install DESTDIR=$RPM_BUILD_ROOT + +cd $RPM_BUILD_ROOT + +find . -type d | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' > $RPM_BUILD_DIR/file.list.%{name} + +find . -type f | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.%{name} + +find . -type l | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.%{name} + +%clean +rm -rf $RPM_BUILD_ROOT +rm -f $RPM_BUILD_DIR/file.list.%{name} + +%files -f ../file.list.%{name} + diff --git a/kmrml/kmrml/Makefile.am b/kmrml/kmrml/Makefile.am new file mode 100644 index 00000000..440e1123 --- /dev/null +++ b/kmrml/kmrml/Makefile.am @@ -0,0 +1,41 @@ +SUBDIRS = server lib kcontrol +INCLUDES= -I$(top_srcdir)/kmrml/kmrml/lib $(all_includes) +METASOURCES = AUTO + +LIB_KMRMLSTUFF = $(top_builddir)/kmrml/kmrml/lib/libkmrmlstuff.la + +####### Files + +kde_module_LTLIBRARIES = kio_mrml.la libkmrmlpart.la + +kio_mrml_la_SOURCES = mrml.cpp +kio_mrml_la_LIBADD = $(LIB_KMRMLSTUFF) $(LIB_KIO) +kio_mrml_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module + +libkmrmlpart_la_SOURCES = mrml_part.cpp mrml_view.cpp loader.cpp \ + mrml_elements.cpp mrml_creator.cpp browser.cpp algorithmdialog.cpp \ + collectioncombo.cpp algorithmcombo.cpp propertysheet.cpp +libkmrmlpart_la_LIBADD = $(LIB_KMRMLSTUFF) $(LIB_KPARTS) +libkmrmlpart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) + +services_DATA = mrml.protocol mrml_part.desktop +servicesdir = $(kde_servicesdir) + +mimetypes_DATA = mrml.desktop +mimetypesdir = $(kde_mimedir)/text + +servicemenu_DATA = mrml-servicemenu.desktop +servicemenudir = $(kde_datadir)/konqueror/servicemenus + +############################################# +bin_PROGRAMS = +lib_LTLIBRARIES = +kdeinit_LTLIBRARIES = mrmlsearch.la + +mrmlsearch_la_LIBADD = $(LIB_KMRMLSTUFF) $(LIB_KDECORE) +mrmlsearch_la_LDFLAGS = $(all_libraries) -module -avoid-version +mrmlsearch_la_SOURCES = mrmlsearch.cpp + +messages: + $(EXTRACTRC) */*.ui > rc.cpp + $(XGETTEXT) *.h *.cpp */*.cpp */*.h -o $(podir)/kmrml.pot diff --git a/kmrml/kmrml/algorithmcombo.cpp b/kmrml/kmrml/algorithmcombo.cpp new file mode 100644 index 00000000..b22556df --- /dev/null +++ b/kmrml/kmrml/algorithmcombo.cpp @@ -0,0 +1,66 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "algorithmcombo.h" + +#include <kdatastream.h> + +using namespace KMrml; + +// ### copycat of CollectionCombo... moc can't handle templates unfortunately.. +// could use base-class MrmlElement.... + +AlgorithmCombo::AlgorithmCombo( QWidget *parent, const char *name ) + : KComboBox( false, parent, name ), + m_algorithms( 0L ) +{ + connect( this, SIGNAL( activated( const QString& ) ), + SLOT( slotActivated( const QString& ) )); +} + +AlgorithmCombo::~AlgorithmCombo() +{ +} + +void AlgorithmCombo::setAlgorithms( const AlgorithmList *algorithms ) +{ + assert( algorithms != 0L ); + + clear(); + m_algorithms = algorithms; + insertStringList( algorithms->itemNames() ); + // #### block signals here? +} + +void AlgorithmCombo::setCurrent( const Algorithm& coll ) +{ + setCurrentItem( coll.name() ); +} + +Algorithm AlgorithmCombo::current() const +{ + return m_algorithms->findByName( currentText() ); +} + +void AlgorithmCombo::slotActivated( const QString& name ) +{ + Algorithm coll = m_algorithms->findByName( name ); + emit selected( coll ); +} + +#include "algorithmcombo.moc" diff --git a/kmrml/kmrml/algorithmcombo.h b/kmrml/kmrml/algorithmcombo.h new file mode 100644 index 00000000..3e151933 --- /dev/null +++ b/kmrml/kmrml/algorithmcombo.h @@ -0,0 +1,54 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef ALGORITHMCOMBO_H +#define ALGORITHMCOMBO_H + +#include <kcombobox.h> + +#include "mrml_elements.h" + +namespace KMrml +{ + + class AlgorithmCombo : public KComboBox + { + Q_OBJECT + + public: + AlgorithmCombo( QWidget *parent, const char *name = 0 ); + ~AlgorithmCombo(); + + void setAlgorithms( const AlgorithmList * algorithms ); + void setCurrent( const Algorithm& coll ); + + Algorithm current() const; + + signals: + void selected( const Algorithm& ); + + private slots: + void slotActivated( const QString& ); + + private: + const AlgorithmList *m_algorithms; + }; + +} + +#endif // ALGORITHMCOMBO_H diff --git a/kmrml/kmrml/algorithmdialog.cpp b/kmrml/kmrml/algorithmdialog.cpp new file mode 100644 index 00000000..cb62fd84 --- /dev/null +++ b/kmrml/kmrml/algorithmdialog.cpp @@ -0,0 +1,132 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "algorithmdialog.h" +#include "algorithmcombo.h" +#include "collectioncombo.h" + +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qscrollview.h> +#include <qvbox.h> +#include <qvgroupbox.h> + +#include <klocale.h> + +using namespace KMrml; + +class ScrollView : public QScrollView +{ +public: + ScrollView(QWidget* parent = 0, const char* name = 0) + : QScrollView(parent, name) + { + setFrameStyle(QFrame::NoFrame); + m_frame = new QFrame(viewport(), "ScrollView::m_frame"); + m_frame->setFrameStyle(QFrame::NoFrame); + addChild(m_frame, 0, 0); + }; + + QFrame* frame() {return m_frame;}; + +protected: + virtual void viewportResizeEvent(QResizeEvent* ev) + { + QScrollView::viewportResizeEvent(ev); + m_frame->resize( kMax(m_frame->sizeHint().width(), ev->size().width()), + kMax(m_frame->sizeHint().height(), ev->size().height())); + }; + +private: + QFrame* m_frame; +}; + +AlgorithmDialog::AlgorithmDialog( const AlgorithmList& algorithms, + const CollectionList& collections, + const Collection& currentColl, + QWidget *parent, const char *name ) + : KDialogBase( parent, name, false, i18n("Configure Query Algorithms"), + Ok | Cancel, Ok, false ), + m_allAlgorithms( algorithms ), + m_collections( collections ) +{ + QWidget *box = makeMainWidget(); + + QVBoxLayout *mainLayout = new QVBoxLayout( box, 0, KDialog::spacingHint(), + "mainLayout"); + + QHBoxLayout *collectionLayout = new QHBoxLayout( 0L, 0, 0, "coll layout"); + collectionLayout->addWidget( new QLabel( i18n("Collection: "), box )); + + m_collectionCombo = new CollectionCombo( box, "collection combo" ); + m_collectionCombo->setCollections( &m_collections ); + collectionLayout->addWidget( m_collectionCombo ); + + mainLayout->addLayout( collectionLayout ); + mainLayout->addSpacing( 14 ); + + QHBox *algoHLayout = new QHBox( box ); + (void) new QLabel( i18n("Algorithm: "), algoHLayout); + m_algoCombo = new AlgorithmCombo( algoHLayout, "algo combo" ); + + QVGroupBox *groupBox = new QVGroupBox( box, "groupBox" ); + mainLayout->addWidget( groupBox ); + algoHLayout->raise(); + + ScrollView *scrollView = new ScrollView( groupBox, "scroll view" ); + m_view = scrollView->frame(); + QVBoxLayout *viewLayout = new QVBoxLayout( scrollView ); + viewLayout->setSpacing( KDialog::spacingHint() ); + + + collectionChanged( currentColl ); + + connect( m_algoCombo, SIGNAL( selected( const Algorithm& ) ), + SLOT( initGUI( const Algorithm& ) )); + connect( m_collectionCombo, SIGNAL( selected( const Collection& ) ), + SLOT( collectionChanged( const Collection& ) )); + + algoHLayout->adjustSize(); + mainLayout->activate(); + algoHLayout->move( groupBox->x() + 10, groupBox->y() - 12 ); + + box->setMinimumWidth( algoHLayout->sizeHint().width() + + 4 * KDialog::spacingHint() ); +} + +AlgorithmDialog::~AlgorithmDialog() +{ +} + +void AlgorithmDialog::collectionChanged( const Collection& coll ) +{ + m_algosForCollection = m_allAlgorithms.algorithmsForCollection( coll ); + m_algoCombo->setAlgorithms( &m_algosForCollection ); + + initGUI( m_algoCombo->current() ); +} + +void AlgorithmDialog::initGUI( const Algorithm& algo ) +{ + m_algo = algo; + + +} + +#include "algorithmdialog.moc" diff --git a/kmrml/kmrml/algorithmdialog.h b/kmrml/kmrml/algorithmdialog.h new file mode 100644 index 00000000..740a95bf --- /dev/null +++ b/kmrml/kmrml/algorithmdialog.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef ALGORITHMDIALOG_H +#define ALGORITHMDIALOG_H + +#include <kdialogbase.h> + +#include "mrml_elements.h" + +namespace KMrml +{ + class AlgorithmCombo; + class CollectionCombo; + + class AlgorithmDialog : public KDialogBase + { + Q_OBJECT + + public: + AlgorithmDialog( const AlgorithmList&, const CollectionList&, + const Collection& currentColl, + QWidget *parent = 0, const char *name = 0 ); + ~AlgorithmDialog(); + + private slots: + void collectionChanged( const Collection& ); + void initGUI( const Algorithm& algo ); + + private: + Algorithm m_algo; + AlgorithmList m_allAlgorithms; + AlgorithmList m_algosForCollection; + CollectionList m_collections; + + CollectionCombo *m_collectionCombo; + AlgorithmCombo *m_algoCombo; + + QFrame *m_view; + }; + +} + +#endif // ALGORITHMDIALOG_H diff --git a/kmrml/kmrml/browser.cpp b/kmrml/kmrml/browser.cpp new file mode 100644 index 00000000..f2453243 --- /dev/null +++ b/kmrml/kmrml/browser.cpp @@ -0,0 +1,63 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "browser.h" +#include "mrml_part.h" + +#include <qscrollview.h> + +using namespace KMrml; + +Browser::Browser( MrmlPart *parent, const char *name ) + : KParts::BrowserExtension( parent, name ), + m_part( parent ) +{ + +} + +Browser::~Browser() +{ + +} + +void Browser::saveState( QDataStream& stream ) +{ +// BrowserExtension::saveState( stream ); + + m_part->saveState( stream ); +} + +void Browser::restoreState( QDataStream& stream ) +{ +// BrowserExtension::restoreState( stream ); + // ### BrowserExtension::restoreState() calls openURL() at the end (arghh). + + m_part->restoreState( stream ); +} + +int Browser::xOffset() +{ + return static_cast<QScrollView*>( m_part->widget())->contentsX(); +} + +int Browser::yOffset() +{ + return static_cast<QScrollView*>( m_part->widget())->contentsY(); +} + +#include "browser.moc" diff --git a/kmrml/kmrml/browser.h b/kmrml/kmrml/browser.h new file mode 100644 index 00000000..11661ed5 --- /dev/null +++ b/kmrml/kmrml/browser.h @@ -0,0 +1,48 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef BROWSER_H +#define BROWSER_H + +#include <kparts/browserextension.h> + +namespace KMrml +{ + class MrmlPart; + + class Browser : public KParts::BrowserExtension + { + Q_OBJECT + + public: + Browser( MrmlPart *parent, const char *name ); + ~Browser(); + + virtual void saveState( QDataStream& stream ); + virtual void restoreState( QDataStream& stream ); + + virtual int xOffset(); + virtual int yOffset(); + + private: + MrmlPart *m_part; + }; + +} + +#endif // BROWSER_H diff --git a/kmrml/kmrml/collectioncombo.cpp b/kmrml/kmrml/collectioncombo.cpp new file mode 100644 index 00000000..b45d7ebf --- /dev/null +++ b/kmrml/kmrml/collectioncombo.cpp @@ -0,0 +1,95 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "collectioncombo.h" + +#include <kdatastream.h> + +using namespace KMrml; + +CollectionCombo::CollectionCombo( QWidget *parent, const char *name ) + : KComboBox( false, parent, name ), + m_collections( 0L ) +{ + connect( this, SIGNAL( activated( const QString& ) ), + SLOT( slotActivated( const QString& ) )); +} + +CollectionCombo::~CollectionCombo() +{ +} + +void CollectionCombo::setCollections( const CollectionList *collections ) +{ + assert( collections != 0L ); + + clear(); + m_collections = collections; + insertStringList( collections->itemNames() ); + // #### block signals here? +} + +void CollectionCombo::setCurrent( const Collection& coll ) +{ + setCurrentItem( coll.name() ); +} + +Collection CollectionCombo::current() const +{ + return m_collections->findByName( currentText() ); +} + +void CollectionCombo::slotActivated( const QString& name ) +{ + Collection coll = m_collections->findByName( name ); + emit selected( coll ); +} + +QDataStream& KMrml::operator<<( QDataStream& stream, + const CollectionCombo& combo ) +{ + int count = combo.count(); + stream << count; + for ( int i = 0; i < count; i++ ) + stream << combo.text( i ); + + stream << combo.currentItem(); + return stream; +} + +QDataStream& KMrml::operator>>( QDataStream& stream, CollectionCombo& combo ) +{ + combo.clear(); + + int count; + stream >> count; + QString text; + for ( int i = 0; i < count; i++ ) + { + stream >> text; + combo.insertItem( text ); + } + + int current; + stream >> current; + combo.setCurrentItem( current ); + + return stream; +} + +#include "collectioncombo.moc" diff --git a/kmrml/kmrml/collectioncombo.h b/kmrml/kmrml/collectioncombo.h new file mode 100644 index 00000000..3ca67a64 --- /dev/null +++ b/kmrml/kmrml/collectioncombo.h @@ -0,0 +1,57 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef COLLECTIONCOMBO_H +#define COLLECTIONCOMBO_H + +#include <kcombobox.h> + +#include "mrml_elements.h" + +namespace KMrml +{ + + class CollectionCombo : public KComboBox + { + Q_OBJECT + + public: + CollectionCombo( QWidget *parent, const char *name = 0 ); + ~CollectionCombo(); + + void setCollections( const CollectionList * collections ); + void setCurrent( const Collection& coll ); + + Collection current() const; + + signals: + void selected( const Collection& ); + + private slots: + void slotActivated( const QString& ); + + private: + const CollectionList *m_collections; + }; + + QDataStream& operator<<( QDataStream& stream, const CollectionCombo& ); + QDataStream& operator>>( QDataStream& stream, CollectionCombo& ); + +} + +#endif // COLLECTIONCOMBO_H diff --git a/kmrml/kmrml/kcontrol/Makefile.am b/kmrml/kmrml/kcontrol/Makefile.am new file mode 100644 index 00000000..c1330cfd --- /dev/null +++ b/kmrml/kmrml/kcontrol/Makefile.am @@ -0,0 +1,25 @@ +LIB_KMRMLSTUFF = $(top_builddir)/kmrml/kmrml/lib/libkmrmlstuff.la + +kde_module_LTLIBRARIES = kcm_kmrml.la + +kcm_kmrml_la_SOURCES = kcmkmrml.cpp mainpage.cpp indexer.cpp serverconfigwidget.ui indexcleaner.cpp +kcm_kmrml_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +kcm_kmrml_la_LIBADD = $(LIB_KMRMLSTUFF) $(LIB_KIO) +INCLUDES= -I$(top_srcdir)/kmrml/kmrml/lib $(all_includes) + +kcm_kmrml_la_METASOURCES = AUTO + +noinst_HEADERS = kcmkmrml.h mainpage.h serverconfigwidget.h indexer.h indexcleaner.h + +xdg_apps_DATA = kcmkmrml.desktop + +#check_PROGRAMS = indextest +#indextest_SOURCES = indextest.cpp indexer.cpp +#indextest_LDADD = $(LIB_KMRMLSTUFF) $(LIB_KDECORE) +#indextest_LDFLAGS = $(all_libraries) + + + +#pics_DATA = play.png +#picsdir = $(kde_datadir)/kcontrol/pics + diff --git a/kmrml/kmrml/kcontrol/indexcleaner.cpp b/kmrml/kmrml/kcontrol/indexcleaner.cpp new file mode 100644 index 00000000..5f5eea93 --- /dev/null +++ b/kmrml/kmrml/kcontrol/indexcleaner.cpp @@ -0,0 +1,96 @@ +#include <kdebug.h> +#include <kprocess.h> + +#include <kmrml_config.h> +#include "indexcleaner.h" + +#include <kdeversion.h> +#if KDE_VERSION < 306 + #define QUOTE( x ) x +#else + #define QUOTE( x ) KProcess::quote( x ) +#endif + +using namespace KMrmlConfig; + +IndexCleaner::IndexCleaner( const QStringList& dirs, + const KMrml::Config *config, + QObject *parent, const char *name ) + : QObject( parent, name ), + m_dirs( dirs ), + m_config( config ), + m_process( 0L ) +{ + m_stepSize = 100 / dirs.count(); +} + +IndexCleaner::~IndexCleaner() +{ + if ( m_process ) + { + m_process->kill(); + delete m_process; + m_process = 0L; + } +} + +void IndexCleaner::start() +{ + startNext(); +} + +void IndexCleaner::slotExited( KProcess *proc ) +{ + emit advance( m_stepSize ); + + if ( !proc->normalExit() ) + kdWarning() << "Error removing old indexed directory" << endl; + + m_process = 0L; + + startNext(); +} + +void IndexCleaner::startNext() +{ + if ( m_dirs.isEmpty() ) + { + emit advance( 100 ); + emit finished(); + return; + } + +#if KDE_VERSION < 306 + m_process = new KShellProcess(); +#else + m_process = new KProcess(); + m_process->setUseShell( true ); +#endif + connect( m_process, SIGNAL( processExited( KProcess * )), + SLOT( slotExited( KProcess * ) )); + + QString cmd = m_config->removeCollectionCommandLine(); + + QString dir = m_dirs.first(); + m_dirs.pop_front(); + + int index = cmd.find( "%d" ); + if ( index != -1 ) + cmd.replace( index, 2, QUOTE( dir ) ); + else // no %d? What else can we do? + cmd.append( QString::fromLatin1(" ") + QUOTE( dir ) ); + + *m_process << cmd; + + if ( !m_process->start() ) + { + kdWarning() << "Error starting: " << cmd << endl; + + delete m_process; + m_process = 0L; + + startNext(); + } +} + +#include "indexcleaner.moc" diff --git a/kmrml/kmrml/kcontrol/indexcleaner.h b/kmrml/kmrml/kcontrol/indexcleaner.h new file mode 100644 index 00000000..0ddcaac4 --- /dev/null +++ b/kmrml/kmrml/kcontrol/indexcleaner.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** $Id$ +** +** Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> +** +****************************************************************************/ + +#ifndef INDEXCLEANER_H +#define INDEXCLEANER_H + +#include <qobject.h> +#include <qstringlist.h> + +class KProcess; + +namespace KMrml +{ + class Config; +} + +namespace KMrmlConfig +{ + class IndexCleaner : public QObject + { + Q_OBJECT + + public: + IndexCleaner( const QStringList& dirs, const KMrml::Config *config, + QObject *parent = 0, const char *name = 0 ); + ~IndexCleaner(); + + void start(); + + signals: + void advance( int value ); + void finished(); + + private slots: + void slotExited( KProcess * ); + + private: + int m_stepSize; + void startNext(); + + QStringList m_dirs; + const KMrml::Config *m_config; + KProcess *m_process; + }; + +} + + +#endif // INDEXCLEANER_H diff --git a/kmrml/kmrml/kcontrol/indexer.cpp b/kmrml/kmrml/kcontrol/indexer.cpp new file mode 100644 index 00000000..a3bb6b7d --- /dev/null +++ b/kmrml/kmrml/kcontrol/indexer.cpp @@ -0,0 +1,190 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qfile.h> +#include <qregexp.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> +#include <kprocio.h> + +#include "indexer.h" + +#include <kdeversion.h> +#if KDE_VERSION < 306 + #define QUOTE( x ) x +#else + #define QUOTE( x ) KProcess::quote( x ) +#endif + +using namespace KMrmlConfig; + +Indexer::Indexer( const KMrml::Config* config, + QObject *parent, const char *name ) + : QObject( parent, name ), + m_config( config ), + m_dirCount( 0 ) +{ + m_process = new KProcIO(); +#if KDE_VERSION >= 306 + m_process->setUseShell( true ); +#endif + m_process->setEnvironment( "LC_ALL", "C" ); + connect( m_process, SIGNAL( processExited( KProcess * )), + SLOT( processFinished( KProcess * ))); + connect( m_process, SIGNAL( readReady( KProcIO * )), + SLOT( slotCanRead( KProcIO * )) ); +} + +Indexer::~Indexer() +{ + delete m_process; +} + +void Indexer::startIndexing( const QStringList& dirs ) +{ + if ( m_process->isRunning() ) + return; + + m_dirs = dirs; + m_dirCount = dirs.count(); + processNext(); +} + +void Indexer::processFinished( KProcess *proc ) +{ + // still more directories to index? + if ( !m_dirs.isEmpty() ) + processNext(); + else + { + if ( proc->normalExit() ) + emit finished( proc->exitStatus() ); + else + emit finished( -1000 ); + } +} + + +void Indexer::processNext() +{ + m_currentDir = m_dirs.first(); + m_dirs.pop_front(); + while ( m_currentDir.endsWith( "/" ) ) + m_currentDir.remove( m_currentDir.length() -1, 1 ); + + m_process->resetAll(); + + QString cmd = m_config->addCollectionCommandLine().simplifyWhiteSpace().stripWhiteSpace(); + + // in the commandline, replace %d with the directory to process and + // %t with the thumbnail dir + int index = cmd.find( "%d" ); // ### QFile::encodeName()? + if ( index != -1 ) + cmd.replace( index, 2, QUOTE( m_currentDir ) ); + index = cmd.find( "%t" ); + if ( index != -1 ) + cmd.replace( index, 2, QUOTE(m_currentDir + "_thumbnails") ); + +// qDebug("****** command: %s", cmd.latin1()); +#if KDE_VERSION >= 306 + *m_process << cmd; +#else + QStringList params = QStringList::split( ' ', cmd ); + QStringList::Iterator it = params.begin(); + for ( ; it != params.end(); ++it ) + *m_process << *it; +#endif + + emit progress( 0, i18n("<qt>Next Folder: <br><b>%1</b>").arg( m_currentDir )); + m_process->start(); +} + +void Indexer::slotCanRead( KProcIO *proc ) +{ + static const QString& sprogress = KGlobal::staticQString("PROGRESS: "); + static const QString& r1 = /* PROGRESS: 1 of 6 done (15%) */ + KGlobal::staticQString( "(\\d+) of (\\d+) done \\((\\d+)%\\)" ); + + QString line; + int bytes = -1; + while ( (bytes = proc->readln( line )) != -1 ) + { + // examine the output. + // We're looking for lines like: + // PROGRESS: 1 of 6 done (15%) + // PROGRESS: 99% + // PROGRESS: 100% + + if ( !line.startsWith( sprogress ) ) // uninteresting debug output + continue; + else // parse output + { + // cut off "PROGRESS: " + line = line.mid( sprogress.length() ); + line = line.simplifyWhiteSpace().stripWhiteSpace(); +// qDebug("*** START LINE ***"); +// qDebug("%s", line.latin1()); +// qDebug("*** END LINE ***"); + + // case 1: image processing, below 99% + if ( line.at( line.length() -1 ) == ')' ) + { + QRegExp regxp( r1 ); + int pos = regxp.search( line ); + if ( pos > -1 ) + { + QString currentFile = regxp.cap( 1 ); + QString numFiles = regxp.cap( 2 ); + QString percent = regxp.cap( 3 ); + +// qDebug( "current: %s, number: %s, percent: %s", currentFile.latin1(), numFiles.latin1(), percent.latin1()); + bool ok = false; + int perc = percent.toInt( &ok ); + if ( ok ) + { + uint dirsLeft = m_dirs.count(); + QString message = i18n( "<qt>Processing folder %1 of %2: <br><b>%3</b><br>File %4 of %5.</qt>").arg( m_dirCount - dirsLeft ).arg( m_dirCount).arg( m_currentDir ).arg( currentFile ).arg( numFiles ); + emit progress( perc, message ); + } + } + } + + + // case 2: file writing, 99% or done, 100% + else + { + QString percent = line.left( line.length() - 1 ); + + bool ok = false; + int number = percent.toInt( &ok ); + if ( ok ) + { + QString message = (number == 100) ? + i18n("Finished.") : i18n("Writing data..."); + emit progress( number, message ); + } + else + kdDebug() << "Error while parsing gift-add-collection.pl output" << endl; + } + } + } +} + +#include "indexer.moc" diff --git a/kmrml/kmrml/kcontrol/indexer.h b/kmrml/kmrml/kcontrol/indexer.h new file mode 100644 index 00000000..97335a70 --- /dev/null +++ b/kmrml/kmrml/kcontrol/indexer.h @@ -0,0 +1,68 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INDEXER_H +#define INDEXER_H + +#include <qobject.h> + +#include <kmrml_config.h> + +class KProcess; +class KProcIO; + +namespace KMrmlConfig +{ + class Indexer : public QObject + { + Q_OBJECT + + public: + Indexer( const KMrml::Config *config, + QObject *parent = 0L, const char *name = 0 ); + ~Indexer(); + + void startIndexing( const QStringList& dirs ); + void stop(); + + signals: + void progress( int percent, const QString& text ); + void finished( int returnCode ); + + + private slots: + void slotCanRead( KProcIO * ); + void processFinished( KProcess * ); + + private: + void processNext(); + + KProcIO *m_process; + const KMrml::Config *m_config; + + uint m_dirCount; + QStringList m_dirs; + QString m_currentDir; + + }; + + +} + + +#endif // INDEXER_H diff --git a/kmrml/kmrml/kcontrol/indextest.cpp b/kmrml/kmrml/kcontrol/indextest.cpp new file mode 100644 index 00000000..161ca798 --- /dev/null +++ b/kmrml/kmrml/kcontrol/indextest.cpp @@ -0,0 +1,43 @@ +#include "indexer.h" +#include <kmrml_config.h> +#include "indextest.moc" + +#include <kapplication.h> +#include <kconfig.h> +#include <kglobal.h> + +using namespace KMrmlConfig; + +IndexTest::IndexTest() +{ + KMrml::Config *config = new KMrml::Config( KGlobal::config() ); + Indexer *indexer = new Indexer( *config, this ); + connect( indexer, SIGNAL( finished( bool )), SLOT( slotFinished( bool ))); + connect( indexer, SIGNAL( progress( int, const QString& )), + SLOT( slotProgress( int, const QString& ))); + + indexer->startIndexing( "/home/gis/testcoll" ); +} + +IndexTest::~IndexTest() +{ + +} + +void IndexTest::slotFinished( bool success ) +{ + qDebug("##### FINISHED: %i", success ); +} + +void IndexTest::slotProgress( int percent, const QString& message ) +{ + qDebug("--- progress: %i: %s", percent, message.latin1()); +} + +int main( int argc, char **argv ) +{ + KApplication app( argc, argv, "indextest" ); + IndexTest *test = new IndexTest(); + + return app.exec(); +} diff --git a/kmrml/kmrml/kcontrol/indextest.h b/kmrml/kmrml/kcontrol/indextest.h new file mode 100644 index 00000000..5f85f5f1 --- /dev/null +++ b/kmrml/kmrml/kcontrol/indextest.h @@ -0,0 +1,26 @@ +/**************************************************************************** +** $Id$ +** +** Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> +** +****************************************************************************/ + +#ifndef INDEXTEST_H +#define INDEXTEST_H + +class IndexTest : public QObject +{ + Q_OBJECT + +public: + IndexTest(); + ~IndexTest(); + +private slots: + void slotFinished( bool success ); + void slotProgress( int percent, const QString& message ); + +}; + + +#endif // INDEXTEST_H diff --git a/kmrml/kmrml/kcontrol/kcmkmrml.cpp b/kmrml/kmrml/kcontrol/kcmkmrml.cpp new file mode 100644 index 00000000..43e46b03 --- /dev/null +++ b/kmrml/kmrml/kcontrol/kcmkmrml.cpp @@ -0,0 +1,146 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qlabel.h> +#include <qlayout.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kglobal.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kgenericfactory.h> +#include <kstandarddirs.h> +#include <kurllabel.h> + +#include "kcmkmrml.h" +#include <dcopclient.h> + +#include "mainpage.h" +#include <version.h> + +using namespace KMrmlConfig; + +static const int COL_FILENAME = 1; + +typedef KGenericFactory<KCMKMrml, QWidget> MrmlFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_kmrml, MrmlFactory("kmrml") ) + +KCMKMrml::KCMKMrml(QWidget *parent, const char *name, const QStringList & ): + KCModule(MrmlFactory::instance(), parent, name) +{ + KAboutData* ab = new KAboutData( + "kcmkmrml", + I18N_NOOP("KCMKMrml"), + KMRML_VERSION, + I18N_NOOP("Advanced Search Control Module"), + KAboutData::License_GPL, + I18N_NOOP( "Copyright 2002, Carsten Pfeiffer" ), + 0, + "http://devel-home.kde.org/~pfeiffer/kmrml/" ); + ab->addAuthor( "Carsten Pfeiffer", 0, "pfeiffer@kde.org" ); + setAboutData( ab ); + + QVBoxLayout *layout = new QVBoxLayout( this ); + layout->setSpacing( KDialog::spacingHint() ); + m_mainPage = new MainPage( this, "main page" ); + + layout->addWidget( m_mainPage ); + + connect( m_mainPage, SIGNAL( changed( bool ) ), SIGNAL( changed( bool ))); + + checkGiftInstallation(); +} + +KCMKMrml::~KCMKMrml() +{ +} + +void KCMKMrml::checkGiftInstallation() +{ + QString giftExe = KGlobal::dirs()->findExe( "gift" ); + QString giftAddCollectionExe = KGlobal::dirs()->findExe( "gift-add-collection.pl" ); + + if ( giftExe.isEmpty() || giftAddCollectionExe.isEmpty() ) + { + QString errorMessage = + i18n("Cannot find executables \"gift\" and/or \"gift-add-collection.pl\" in the PATH.\n" + "Please install the \"GNU Image Finding Tool\"."); + KMessageBox::error( this, errorMessage ); + m_mainPage->hide(); + QLabel *errorLabel = new QLabel( errorMessage, this ); + errorLabel->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) ); + KURLLabel *urlLabel = new KURLLabel( "http://www.gnu.org/software/gift", QString::null, this ); + urlLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); + connect( urlLabel, SIGNAL( leftClickedURL( const QString& )), kapp, SLOT( invokeBrowser( const QString& )) ); + QLayout *l = layout(); + l->addItem( new QSpacerItem( 0, 10, QSizePolicy::Minimum, QSizePolicy::Expanding ) ); + l->add( errorLabel ); + l->add( urlLabel ); + l->addItem( new QSpacerItem( 0, 10, QSizePolicy::Minimum, QSizePolicy::Expanding ) ); + errorLabel->show(); + } + else + load(); +} + +void KCMKMrml::defaults() +{ + if (KMessageBox::warningContinueCancel(this, + i18n("Do you really want the configuration to be reset " + "to the defaults?"), i18n("Reset Configuration"), KStdGuiItem::cont()) + != KMessageBox::Continue) + return; + + m_mainPage->resetDefaults(); + + emit changed( true ); +} + +void KCMKMrml::load() +{ + m_mainPage->load(); + + emit changed( true ); +} + +void KCMKMrml::save() +{ + m_mainPage->save(); + + emit changed( false ); +} + +QString KCMKMrml::quickHelp() const +{ + return i18n("<h1>Image Index</h1>" + "KDE can make use of the GNU Image Finding Tool (GIFT) to " + "perform queries based not just on filenames, but on " + "file content." + "<p>For example, you can search for an image by giving an example " + "image that looks similar to the one you are looking for.</p>" + "<p>For this to work, your image directories need to be " + "indexed by, for example, the GIFT server.</p>" + "<p>Here you can configure the servers (you can also query " + "remote servers) and the directories to index.</p>" + ); +} + +#include "kcmkmrml.moc" diff --git a/kmrml/kmrml/kcontrol/kcmkmrml.desktop b/kmrml/kmrml/kcontrol/kcmkmrml.desktop new file mode 100644 index 00000000..d9dd1f02 --- /dev/null +++ b/kmrml/kmrml/kcontrol/kcmkmrml.desktop @@ -0,0 +1,176 @@ +[Desktop Entry] +Exec=kcmshell kcmkmrml +Icon=folder_image +Type=Application + +X-KDE-ModuleType=Library +X-KDE-Library=kmrml + +Name=Image Index +Name[ar]=فهرس الصور +Name[bg]=Графичен индекс +Name[br]=Meneger ar skeudenn +Name[bs]=Indeks slika +Name[ca]=Índex d'imatge +Name[cs]=Rejstřík obrázků +Name[cy]=Mynegai Delweddau +Name[da]=Billedindeks +Name[de]=Bildindex +Name[el]=Ευρετήριο εικόνων +Name[eo]=Bildindekso +Name[es]=Índice de imágenes +Name[et]=Pildiindeks +Name[eu]=Irudiaren indizea +Name[fa]=نمایۀ تصویر +Name[fi]=Kuvahakemisto +Name[fr]=Indexation des images +Name[gl]=Índice imaxe +Name[he]=אינדקס תמונות +Name[hi]=छवि सूची +Name[hu]=Képkereső +Name[is]=Myndayfirlit +Name[it]=Indice di immagini +Name[ja]=画像インデックス +Name[kk]=Кескіндер индексі +Name[km]=លិបិក្រមរូបភាព +Name[lt]=Paveikslėlių rodyklė +Name[ms]=Indeks Imej +Name[nb]=Bildeindeks +Name[nds]=Bildindex +Name[ne]=छवि अनुक्रमणिका +Name[nl]=Afbeeldingenindex +Name[nn]=Biletindeks +Name[nso]=Palo ya Ponagalo +Name[pl]=Spis obrazków +Name[pt]=Índice de Imagens +Name[pt_BR]=Índice de Imagens +Name[ro]=Index imagini +Name[ru]=Индексирование изображений +Name[se]=Govvaindeaksa +Name[sk]=Katalóg obrázkov +Name[sl]=Seznam slik +Name[sr]=Индекс слика +Name[sr@Latn]=Indeks slika +Name[sv]=Bildindex +Name[ta]=பிம்ப அட்டவணை +Name[tg]=Индексатсия кардани тасвирот +Name[th]=ดัชนีรูปภาพ +Name[tr]=Resim İndeksi +Name[uk]=Індекс зображень +Name[uz]=Rasm indeksi +Name[uz@cyrillic]=Расм индекси +Name[ven]=Index ya tshifanyiso +Name[wa]=Indecse des imådjes +Name[xh]=Isalathisi Somfanekiso +Name[zh_CN]=图像索引 +Name[zh_HK]=圖像索引 +Name[zh_TW]=影像索引 +Name[zu]=Isiqalo Sesithombe + +Comment=Configuration for using the GNU Image Finding Tool +Comment[ar]=اعدادات لاستخدام أداة GNU للبحث عن الصور +Comment[bg]=Настройване на програмата за индексиране и търсене на изображения +Comment[bs]=Podešavanje za upotrebu GNU Alata za pronalaženje slika +Comment[ca]=Configuració per a l'ús de l'eina de cerca d'imatges GNU +Comment[cs]=Konfigurace používání nástroje GNU Image Finding Tool +Comment[cy]=Ffurfweddiad am ddefnyddio'r Erfyn Canfod Delweddau GNU +Comment[da]=Indstilling for brug af GNU Image Finding Tool +Comment[de]=Einrichtung für die Benutzung des GNU Bildersuchwerkzeugs (GNU Image Finding Tool) +Comment[el]=Ρύθμιση για τη χρήση του εργαλείου αναζήτησης εικόνων GIFT +Comment[es]=Configuración para utilizar la herramienta de búsqueda de imágenes de GNU +Comment[et]=Seadistused GNU pildileidmisrakenduse kasutamiseks +Comment[eu]=GNU irudi aurkitzailea erabiltzeko konfigurazioa +Comment[fa]=پیکربندی برای استفاده از ابزار یافتن تصویر GNU +Comment[fi]=Asetukset GNU Image Finding Tool -ohjelman käyttöä varten +Comment[fr]=Configuration pour l'utilisation du GNU Image Finding Tool +Comment[gl]=Configuración para empregar a «GNU Image Finding Tool» +Comment[he]=שינוי הגדרות כלי חיפוש התמונות של GNU +Comment[hi]=ग्नू छवि खोज औज़ार को उपयोग करने के लिए कॉन्फ़िगरेशन +Comment[hu]=A GIFT képkereső szolgáltatás beállításai +Comment[is]=Stillingar til þess að nota GNU myndleitartólið +Comment[it]=Configurazione della ricerca delle immagini +Comment[ja]=GIFT (GNU Image Finding Tool) を使用するための設定 +Comment[kk]=GNU Image Finding Tool кескінді табу құралын пайдалану баптаулары +Comment[km]=ការកំណត់រចនាសម្ព័ន្ធដើម្បីប្រើឧបករណ៍ស្វែងរករូបភាពរបស់ GNU +Comment[lt]=GNU paveikslėlių paieškos įrankio konfigūracija +Comment[ms]=Konfigurasi untuk mengguna Alat Carian Imej GNU +Comment[nb]=Tilpass GNU bildesøkingsverktøy +Comment[nds]=Inrichten för dat GNU-Bildsöökwarktüüch +Comment[ne]=GNU छवि फेला पार्ने उपकरण प्रयोगका लागि कन्फिगरेसन +Comment[nl]=Configuratie voor het gebruik van de GNU Image Finding Tool +Comment[nn]=Oppsett av GNU Image Finding Tool +Comment[pl]=Konfiguracja Gifta (narzędzia do szukania obrazków GNU) +Comment[pt]=Configuração da Ferramenta de Procura de Imagens da GNU +Comment[pt_BR]=Configuração para o uso da Ferramenta de Procura de Imagens GNU +Comment[ro]=Configurare pentru GNU Image Finding Tool +Comment[ru]=Настройка использования программы поиска изображений GNU Image Finding Tool +Comment[se]=Heivet GNU Image Finding Tool +Comment[sk]=Konfigurácia pre GNU Image Finding Tool +Comment[sl]=Nastavitve za uporabo orodja GNU za iskanje slik +Comment[sr]=Подешавање коришћења GNU-овог алата за тражење слика +Comment[sr@Latn]=Podešavanje korišćenja GNU-ovog alata za traženje slika +Comment[sv]=Inställning för att använda GNU:s bildsökverktyg +Comment[ta]=GNU பிம்ப தேடுதல் கருவியை பயன்படுத்துவதற்கான அமைப்பு +Comment[tg]=Танзимоти истифодабарии барномаиҷустуҷӯи тасвироти GNU Image Finding Tool +Comment[tr]=GNU Resim Bulma Aracı yapılandırması +Comment[uk]=Налаштування засобу пошуку зображень GNU +Comment[ven]=Nzudzanyo yau shumisa tshishumiswa tshau toda tshifanyiso tsha GNU +Comment[wa]=Apontiaedje po-z eployî l' usteye di cweraedje d' imådjes di GNU +Comment[xh]=Uqwalaselo lokusebenzisa Isixhobo Sokufumana Umfanekiso we GNU +Comment[zh_CN]=使用 GNU 图像查找工具的配置 +Comment[zh_HK]=GNU 圖像搜尋工具的設定 +Comment[zh_TW]= GNU 影像搜尋工具組態 +Comment[zu]=Inhlanganiselo yokusebenzisa Ithuluzi Lokuthola Isithombe se-GNU + +Keywords=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR +Keywords[ar]=صور,بحث,استعلام,Find,Gift,kmrml,mrml,CBIR +Keywords[bg]=изображения, търсене, заявка, картинка, картинки, снимки, Images, Search, Query, Find, Gift, kmrml, mrml, CBIR +Keywords[bs]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR,slike,pretraga,upit,nađi +Keywords[ca]=Imatges,Cerca,Consulta,Busca,Gift,kmrml,mrml,CBIR +Keywords[cs]=Obrázky,Hledat,Dotaz,Najít,Gift,kmrml,mrml,CBIR +Keywords[cy]=Delweddau,Chwilio,Canfod,Gift,kmrml,mrml,CBIR +Keywords[da]=Billeder,Søgning,Forespørgsel,Find,Gave,kmrml,mrml,CBIR +Keywords[de]=Bilder,Suche,Anfrage,finden,Geschenk,kmrml,mrml,CBIR +Keywords[el]=Εικόνες,Αναζήτηση,Ερώτηση,Αναζήτηση,Gift,kmrml,mrml,CBIR +Keywords[es]=Imágenes,Búsqueda,Consulta,Buscar,Gift,kmrml,mrml,CBIR +Keywords[et]=pildid,otsing,päring,leia,Gift,kmrml,mrml,CBIR +Keywords[eu]=Irudiak,Bilaketa,Bilatu,Galdetu,Gift,kmrml,mrml,CBIR +Keywords[fa]=تصاویر، جستجو، پرسوجو، یافتن، Gift،kmrml،mrml،CBIR +Keywords[fi]=Kuvat,Haku,Etsi,Lahja,kmrml,mrml,CBIR +Keywords[fr]=Images,Recherche,Requête,Chercher,Gift,kmrml,mrml,CBIR +Keywords[gl]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR, imaxes, procura +Keywords[he]=תמונות,חיפוש,שאילתה,Gift,kmrml,mrml,CBIR, Images,Search,Query,Find +Keywords[hi]=छवि, खोज,ढूंढ,तलाश,उपहार,केएमआरएमएल,एमआरएमएल,सीबीआईआर +Keywords[hu]=képek,keresés,lekérdezés,találat,Gift,kmrml,mrml,CBIR +Keywords[it]=immagini,ricerca,trovare,Gift,kmrml,mrml,CBIR +Keywords[ja]=画像,検索,クエリ,検索,Gift,kmrml,mrml,CBIR +Keywords[km]=រូបភាព,ស្វែងរក,សួរ,រក,Gift,kmrml,mrml,CBIR +Keywords[lt]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR, paveikslėliai,paieška,paklausimas +Keywords[nb]=Bilder,Søk,Spørringer,Finn,Gift,kmrml,mrml,CBIR +Keywords[nds]=Biller,Söök,Anfraag,söken,Gaav,kmrml,mrml,CBIR +Keywords[nl]=illustraties,figuren,figuur,afbeeldingen,plaatjes,zoeken,find,gift,kmrml,mrml,CBIR,images +Keywords[nn]=bilete,søk,spørjing,finn,gåve,kmrml,mrml,CBIR +Keywords[nso]=Diponagalo,Nyaka,Kgokgonego,Hwetsa,Mpho,kmrml,mrml,CBIR +Keywords[pl]=Obrazki,Szukanie,Zapytanie,Szukaj,Gift,kmrml,mrml,CBIR +Keywords[pt]=Imagens,Procurar,Pesquisar,Encontrar,Prenda,kmrml,mrml,CBIR +Keywords[pt_BR]=Imagens,Busca,Consulta,Procurar,Presente,kmrml,mrml,CBIR +Keywords[ro]=imagini,căutare,caută,interogare,găseşte,dar,kmrml,mrml,CBIR +Keywords[ru]=изображения,поиск,запрос,kmrml,mrml,CBIR +Keywords[sk]=Obrázky,Hľadanie,Dotazy,Nájsť,kmrml,mrml,CBIR +Keywords[sl]=slike,iskanje,povpraševanje,išči,najdi,gift,kmrml,mrml,CBIR +Keywords[sr]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR,слике,тражи,упит,нађи,поклон +Keywords[sr@Latn]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR,slike,traži,upit,nađi,poklon +Keywords[sv]=Bilder,Sök,Förfrågan,Hitta,Gift,kmrml,mrml,CBIR +Keywords[ta]=பிம்பங்கள், தேடு, கேள்வி, கண்டுபிடி,பரிசு,kmrml,mrml,CBIR +Keywords[tg]=тасвирот,ҷустуҷӯӣ,дархост,kmrml,mrml,CBIR +Keywords[tr]=Resimler,Ara,Arama,kmrml,mrml,CBIR +Keywords[uk]=зображення,пошук,запит,знайти,подарунок,kmrml,mrml,CBIR +Keywords[ven]=Zwifanyiso,Toda,Mbudziso,Wana,Mpho,kmrml,mrml,CBIR +Keywords[wa]=Imådjes,Cweri,Cweraedje,Trover,Gift,kmrml,mrml,CBIR +Keywords[xh]=Imifanekiso,Uphendlo,Ubuzo,fumana,Isiphiwo,kmrml,mrml,CBIR +Keywords[zh_CN]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR,图像,搜索,查询,查找,礼物 +Keywords[zh_HK]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR,圖像,搜尋,查詢,尋找 +Keywords[zh_TW]=Images,Search,Query,Find,Gift,kmrml,mrml,CBIR,影像,搜尋,查詢,尋找 +Keywords[zu]=Izithombe,Funa,Buza,Thola,Isipho,kmrml,mrml,CBIR + +Categories=Qt;KDE;Settings;X-KDE-settings-system; diff --git a/kmrml/kmrml/kcontrol/kcmkmrml.h b/kmrml/kmrml/kcontrol/kcmkmrml.h new file mode 100644 index 00000000..b0bb2443 --- /dev/null +++ b/kmrml/kmrml/kcontrol/kcmkmrml.h @@ -0,0 +1,52 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KCMKMRML_H +#define KCMKMRML_H + +#include <kcmodule.h> + +class KAboutData; +class KURLRequester; + +namespace KMrmlConfig +{ + class MainPage; + + class KCMKMrml : public KCModule + { + Q_OBJECT + + public: + KCMKMrml(QWidget *parent, const char *name, const QStringList &); + virtual ~KCMKMrml(); + + virtual void defaults(); + virtual void load(); + virtual void save(); + virtual QString quickHelp() const; + + private: + void checkGiftInstallation(); + + MainPage *m_mainPage; + }; + +} + +#endif diff --git a/kmrml/kmrml/kcontrol/mainpage.cpp b/kmrml/kmrml/kcontrol/mainpage.cpp new file mode 100644 index 00000000..514b9cf6 --- /dev/null +++ b/kmrml/kmrml/kcontrol/mainpage.cpp @@ -0,0 +1,501 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qcheckbox.h> +#include <qlabel.h> +#include <qsizepolicy.h> +#include <qtooltip.h> +#include <qwidget.h> +#include <qvgroupbox.h> + +#include <kcombobox.h> +#include <kdialog.h> +#include <keditlistbox.h> +#include <kglobalsettings.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprogress.h> +#include <kurlrequester.h> + +#include <kdeversion.h> +#include <kdebug.h> +#include <kio/slaveconfig.h> +#include <kio/ioslave_defaults.h> // MAX_PORT_VALUE + +#include "serverconfigwidget.h" +#include "mainpage.h" +#include "indexer.h" +#include "indexcleaner.h" + +#include <limits.h> +#include <string.h> + +using namespace KMrmlConfig; + + +MainPage::MainPage( QWidget *parent, const char *name ) + : QVBox( parent, name ), + m_indexer( 0L ), + m_indexCleaner( 0L ), + m_progressDialog( 0L ), + m_performIndexing( false ), + m_locked( false ) +{ + m_config = new KMrml::Config(); + setSpacing( KDialog::spacingHint() ); + + QVGroupBox *gBox = new QVGroupBox( i18n("Indexing Server Configuration"), + this ); + m_serverWidget = new ServerConfigWidget( gBox, "server config widget" ); + QString tip = i18n("Hostname of the Indexing Server"); + QToolTip::add( m_serverWidget->m_hostLabel, tip ); + QToolTip::add( m_serverWidget->m_hostCombo, tip ); + + m_serverWidget->m_portInput->setRange( 0, MAX_PORT_VALUE ); + +#if KDE_VERSION >= 306 + KURLRequester *requester = new KURLRequester( this, "dir requester" ); + requester->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly ); + requester->setURL( KGlobalSettings::documentPath() ); + connect( requester, SIGNAL( openFileDialog( KURLRequester * )), + SLOT( slotRequesterClicked( KURLRequester * ))); + + m_listBox = new KEditListBox( i18n("Folders to Be Indexed" ), + requester->customEditor(), this, "listbox", + false, + KEditListBox::Add | KEditListBox::Remove ); +#else + m_listBox = new KEditListBox( i18n("Folders to Be Indexed" ), + this, "listbox", false, + KEditListBox::Add | KEditListBox::Remove ); +#endif + + connect( m_listBox, SIGNAL( changed() ), SLOT( slotDirectoriesChanged() )); + connect( m_serverWidget->m_hostCombo, SIGNAL( textChanged(const QString&)), + SLOT( slotHostChanged() )); + connect( m_serverWidget->m_portInput, SIGNAL( valueChanged( int )), + SLOT( slotPortChanged( int ) )); + connect ( m_serverWidget->m_useAuth, SIGNAL( toggled(bool) ), + SLOT( slotUseAuthChanged( bool ) )); + connect( m_serverWidget->m_userEdit, SIGNAL( textChanged( const QString&)), + SLOT( slotUserChanged( const QString& ) )); + connect( m_serverWidget->m_passEdit, SIGNAL( textChanged( const QString&)), + SLOT( slotPassChanged( const QString& ) )); + + connect( m_serverWidget->m_addButton, SIGNAL( clicked() ), + SLOT( slotAddClicked() )); + connect( m_serverWidget->m_removeButton, SIGNAL( clicked() ), + SLOT( slotRemoveClicked() )); + + connect( m_serverWidget->m_hostCombo, SIGNAL( activated( const QString& )), + SLOT( slotHostActivated( const QString& ))); + connect( m_serverWidget->m_hostCombo, SIGNAL( returnPressed() ), + SLOT( slotAddClicked() )); + + connect( m_serverWidget->m_autoPort, SIGNAL( toggled( bool ) ), + SLOT( slotAutoPortChanged( bool ) )); + + m_serverWidget->m_hostCombo->setTrapReturnKey( true ); + m_serverWidget->m_hostCombo->setFocus(); +} + +MainPage::~MainPage() +{ + delete m_config; +} + +void MainPage::resetDefaults() +{ + blockSignals( true ); + + initFromSettings( KMrml::ServerSettings::defaults() ); + + m_serverWidget->m_hostCombo->clear(); + m_serverWidget->m_hostCombo->insertItem( m_settings.host ); + + m_listBox->clear(); + + // slotHostChanged(); not necessary, will be called by Qt signals + slotUseAuthChanged( m_serverWidget->m_useAuth->isChecked() ); + + blockSignals( false ); +} + +void MainPage::load() +{ + blockSignals( true ); + + initFromSettings( m_config->defaultSettings() ); + + m_serverWidget->m_hostCombo->clear(); + m_serverWidget->m_hostCombo->insertStringList( m_config->hosts() ); + m_serverWidget->m_hostCombo->setCurrentItem( m_settings.host ); + + m_listBox->clear(); + m_listBox->insertStringList( m_config->indexableDirectories() ); + + // slotHostChanged(); not necessary, will be called by Qt signals + slotUseAuthChanged( m_serverWidget->m_useAuth->isChecked() ); + + blockSignals( false ); +} + +void MainPage::save() +{ + m_config->addSettings( m_settings ); + m_config->setDefaultHost( m_settings.host ); + + QStringList indexDirs = m_listBox->items(); + QStringList oldIndexDirs = m_config->indexableDirectories(); + QStringList removedDirs = difference( oldIndexDirs, indexDirs ); + + m_config->setIndexableDirectories( indexDirs ); + if ( indexDirs.isEmpty() ) + KMessageBox::information( this, + i18n("You did not specify any folders to " + "be indexed. This means you will be " + "unable to perform queries on your " + "computer."), + "kcmkmrml_no_directories_specified" ); + + if ( m_config->sync() ) + KIO::SlaveConfig::self()->reset(); + + processIndexDirs( removedDirs ); +} + +QStringList MainPage::difference( const QStringList& oldIndexDirs, + const QStringList& newIndexDirs ) const +{ + QStringList result; + + QString slash = QString::fromLatin1("/"); + QStringList::ConstIterator oldIt = oldIndexDirs.begin(); + QString oldDir, newDir; + + for ( ; oldIt != oldIndexDirs.end(); oldIt++ ) + { + bool removed = true; + oldDir = *oldIt; + + while ( oldDir.endsWith( slash ) ) // remove slashes + oldDir.remove( oldDir.length() - 1, 1 ); + + QStringList::ConstIterator newIt = newIndexDirs.begin(); + for ( ; newIt != newIndexDirs.end(); newIt++ ) + { + newDir = *newIt; + while ( newDir.endsWith( slash ) ) // remove slashes + newDir.remove( newDir.length() - 1, 1 ); + + if ( oldDir == newDir ) + { + removed = false; + break; + } + } + + if ( removed ) + result.append( *oldIt ); // not oldDir -- maybe gift needs slashes + } + + return result; +} + +void MainPage::initFromSettings( const KMrml::ServerSettings& settings ) +{ + m_settings = settings; + + m_locked = true; + + m_serverWidget->m_portInput->setValue( settings.configuredPort ); + m_serverWidget->m_autoPort->setChecked( settings.autoPort ); + m_serverWidget->m_useAuth->setChecked( settings.useAuth ); + m_serverWidget->m_userEdit->setText( settings.user ); + m_serverWidget->m_passEdit->setText( settings.pass ); + + m_locked = false; +} + +void MainPage::slotHostActivated( const QString& host ) +{ + // implicitly save the current settings when another host was chosen + m_config->addSettings( m_settings ); + + initFromSettings( m_config->settingsForHost( host ) ); +} + +void MainPage::slotHostChanged() +{ + QString host = m_serverWidget->m_hostCombo->currentText(); + m_listBox->setEnabled( (host == "localhost") ); + + KMrml::ServerSettings settings = m_config->settingsForHost( host ); + enableWidgetsFor( settings ); +} + +void MainPage::slotUseAuthChanged( bool enable ) +{ + m_settings.useAuth = enable; + m_serverWidget->m_userEdit->setEnabled( enable ); + m_serverWidget->m_passEdit->setEnabled( enable ); + + if ( enable ) + m_serverWidget->m_userEdit->setFocus(); + + if ( !m_locked ) + changed(); +} + +void MainPage::slotUserChanged( const QString& user ) +{ + if ( m_locked ) + return; + + m_settings.user = user; + changed(); +} + +void MainPage::slotPassChanged( const QString& pass ) +{ + if ( m_locked ) + return; + + m_settings.pass = pass; + changed(); +} + +void MainPage::slotPortChanged( int port ) +{ + if ( m_locked ) + return; + + m_settings.configuredPort = (unsigned short int) port; + changed(); +} + +void MainPage::slotAutoPortChanged( bool on ) +{ + if ( m_locked ) + return; + + m_settings.autoPort = on; + m_serverWidget->m_portInput->setEnabled( !on ); + changed(); +} + +void MainPage::slotRequesterClicked( KURLRequester *requester ) +{ + static bool init = true; + if ( !init ) + return; + + init = false; + + requester->setCaption(i18n("Select Folder You Want to Index")); +} + +void MainPage::slotAddClicked() +{ + QString host = m_serverWidget->m_hostCombo->currentText(); + m_settings.host = host; + + m_config->addSettings( m_settings ); + m_serverWidget->m_hostCombo->insertItem( host ); + m_serverWidget->m_hostCombo->setCurrentItem( host ); + + enableWidgetsFor( m_settings ); +} + +void MainPage::slotRemoveClicked() +{ + QString host = m_serverWidget->m_hostCombo->currentText(); + if ( host.isEmpty() ) // should never happen + return; + + m_config->removeSettings( host ); + m_serverWidget->m_hostCombo->removeItem( m_serverWidget->m_hostCombo->currentItem() ); + m_serverWidget->m_hostCombo->setCurrentItem( 0 ); + + host = m_serverWidget->m_hostCombo->currentText(); + initFromSettings( m_config->settingsForHost( host ) ); +} + +void MainPage::enableWidgetsFor( const KMrml::ServerSettings& settings ) +{ + QString host = settings.host; + bool enableWidgets = (m_config->hosts().findIndex( host ) > -1); + m_serverWidget->m_addButton->setEnabled(!enableWidgets && !host.isEmpty()); + m_serverWidget->m_removeButton->setEnabled( enableWidgets && + !host.isEmpty() && + host != "localhost" ); + + m_serverWidget->m_autoPort->setEnabled( host == "localhost" ); + bool portEnable = enableWidgets && (settings.autoPort || + !m_serverWidget->m_autoPort->isEnabled()); + m_serverWidget->m_portLabel->setEnabled( portEnable && !m_serverWidget->m_autoPort->isChecked()); + m_serverWidget->m_portInput->setEnabled( portEnable && !m_serverWidget->m_autoPort->isChecked()); + + m_serverWidget->m_useAuth->setEnabled( enableWidgets ); + m_serverWidget->m_userLabel->setEnabled( enableWidgets ); + m_serverWidget->m_passLabel->setEnabled( enableWidgets ); + m_serverWidget->m_userEdit->setEnabled( enableWidgets ); + m_serverWidget->m_passEdit->setEnabled( enableWidgets ); + + bool useAuth = m_serverWidget->m_useAuth->isChecked(); + m_serverWidget->m_userEdit->setEnabled( useAuth ); + m_serverWidget->m_passEdit->setEnabled( useAuth ); +} + +void MainPage::slotDirectoriesChanged() +{ + m_performIndexing = true; + changed(); +} + +void MainPage::processIndexDirs( const QStringList& removeDirs ) +{ + // ### how to remove indexed directories? + if ( !m_performIndexing || + (removeDirs.isEmpty() && m_config->indexableDirectories().isEmpty()) ) + return; + + delete m_progressDialog; + delete m_indexCleaner; + m_indexCleaner = 0L; + delete m_indexer; + m_indexer = 0L; + + m_progressDialog = new KProgressDialog( this, "indexing dialog", + i18n("Removing old Index Files"), + i18n("Processing..."), + true ); + m_progressDialog->setAutoClose( false ); + m_progressDialog->setMinimumWidth( 300 ); + connect( m_progressDialog, SIGNAL( cancelClicked() ), + SLOT( slotCancelIndexing() )); + + // argh -- don't automatically show the dialog + m_progressDialog->setMinimumDuration( INT_MAX ); + + if ( !removeDirs.isEmpty() ) + { + m_indexCleaner = new IndexCleaner( removeDirs, m_config, this ); + connect( m_indexCleaner, SIGNAL( advance( int ) ), + m_progressDialog->progressBar(), SLOT( advance( int ) )); + connect( m_indexCleaner, SIGNAL( finished() ), + SLOT( slotMaybeIndex() ) ); + m_indexCleaner->start(); + } + else + { + slotMaybeIndex(); + } + if ( m_progressDialog ) + m_progressDialog->exec(); +} + +void MainPage::slotMaybeIndex() +{ + delete m_indexCleaner; // Stop in the name of the law! + m_indexCleaner = 0L; + + m_progressDialog->setLabel( i18n("Finished.") ); + + if ( m_config->indexableDirectories().isEmpty() ) + return; + + if ( KMessageBox::questionYesNo( this, + i18n("The settings have been saved. Now, " + "the configured directories need to " + "be indexed. This may take a while. " + "Do you want to do this now?"), + i18n("Start Indexing Now?"), + i18n("Index"), i18n("Do Not Index"), + "ask_startIndexing" + ) != KMessageBox::Yes ) + return; + m_progressDialog->setCaption( i18n("Indexing Folders") ); + m_progressDialog->setLabel( i18n("Processing...") ); + m_progressDialog->progressBar()->setProgress( 0 ); + + // do the indexing + m_indexer = new Indexer( m_config, this, "Indexer" ); + connect( m_indexer, SIGNAL( progress( int, const QString& )), + SLOT( slotIndexingProgress( int, const QString& ) )); + connect( m_indexer, SIGNAL( finished( int )), + SLOT( slotIndexingFinished( int ) )); + m_indexer->startIndexing( m_config->indexableDirectories() ); +} + + +void MainPage::slotIndexingProgress( int percent, const QString& message ) +{ + m_progressDialog->progressBar()->setValue( percent ); + m_progressDialog->setLabel( message ); +} + +void MainPage::slotIndexingFinished( int returnCode ) +{ + if ( returnCode != 0 ) + { + QString syserr; + if ( returnCode == 127 ) + syserr = i18n("Is the \"GNU Image Finding Tool\" properly installed?"); + else + { + char *err = strerror( returnCode ); + if ( err ) + syserr = QString::fromLocal8Bit( err ); + else + syserr = i18n("Unknown error: %1").arg( returnCode ); + } + + KMessageBox::detailedError( this, i18n("An error occurred during indexing. The index might be invalid."), + syserr, i18n("Indexing Aborted") ); + } + else + m_performIndexing = false; + + delete m_indexer; + m_indexer = 0L; + if ( m_progressDialog ) + { + m_progressDialog->deleteLater(); + m_progressDialog = 0L; + } +} + +void MainPage::slotCancelIndexing() +{ + delete m_indexCleaner; + m_indexCleaner = 0L; + + delete m_indexer; + m_indexer = 0L; + if ( m_progressDialog ) + { + m_progressDialog->deleteLater(); + m_progressDialog = 0L; + } +} + + +#include "mainpage.moc" diff --git a/kmrml/kmrml/kcontrol/mainpage.h b/kmrml/kmrml/kcontrol/mainpage.h new file mode 100644 index 00000000..e91b4168 --- /dev/null +++ b/kmrml/kmrml/kcontrol/mainpage.h @@ -0,0 +1,109 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MAINPAGE_H +#define MAINPAGE_H + +#include <qvbox.h> + +#include <kmrml_config.h> + +class QCheckBox; +class KComboBox; +class KEditListBox; +class KIntNumInput; +class KLineEdit; +class KProgressDialog; +class KURLRequester; + +namespace KMrml +{ + class Config; +} + +class ServerConfigWidget; + +namespace KMrmlConfig +{ + class Indexer; + class IndexCleaner; + + class MainPage : public QVBox + { + Q_OBJECT + + public: + MainPage( QWidget *parent, const char *name ); + ~MainPage(); + + void resetDefaults(); + void load(); + void save(); + + signals: + void changed( bool ); + + private slots: + void changed() { emit changed( true ); } + void slotRequesterClicked( KURLRequester * ); + void slotHostChanged(); + void slotUseAuthChanged( bool ); + void slotUserChanged( const QString& ); + void slotPassChanged( const QString& ); + void slotPortChanged( int ); + void slotAutoPortChanged( bool ); + + void slotAddClicked(); + void slotRemoveClicked(); + + void slotHostActivated( const QString& ); + + void slotDirectoriesChanged(); + + void slotMaybeIndex(); + void slotIndexingProgress( int percent, const QString& message ); + void slotIndexingFinished( int returnCode ); + void slotCancelIndexing(); + + + private: + void enableWidgetsFor( const KMrml::ServerSettings& settings ); + void initFromSettings( const KMrml::ServerSettings& settings ); + + void processIndexDirs( const QStringList& removedDirs ); + + QStringList difference( const QStringList& oldIndexDirs, + const QStringList& newIndexDirs ) const; + + ServerConfigWidget *m_serverWidget; + KEditListBox *m_listBox; + KMrml::Config *m_config; + KMrmlConfig::Indexer *m_indexer; + KMrmlConfig::IndexCleaner *m_indexCleaner; + KProgressDialog *m_progressDialog; + + KMrml::ServerSettings m_settings; + bool m_performIndexing; + bool m_locked; + }; + +} + + + +#endif // MAINPAGE_H diff --git a/kmrml/kmrml/kcontrol/serverconfigwidget.ui b/kmrml/kmrml/kcontrol/serverconfigwidget.ui new file mode 100644 index 00000000..e0a08007 --- /dev/null +++ b/kmrml/kmrml/kcontrol/serverconfigwidget.ui @@ -0,0 +1,272 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>ServerConfigWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ServerConfigWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>455</width> + <height>321</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout7</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="KComboBox"> + <property name="name"> + <cstring>m_hostCombo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_addButton</cstring> + </property> + <property name="text"> + <string>&Add</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_removeButton</cstring> + </property> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="1" column="1"> + <property name="name"> + <cstring>Layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>m_portInput</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" stdset="0"> + <string>TCP/IP Port Number of the Indexing Server</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_autoPort</cstring> + </property> + <property name="text"> + <string>Au&to</string> + </property> + <property name="toolTip" stdset="0"> + <string>Tries to automatically determine the port. This works only for local servers.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>200</width> + <height>0</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_hostLabel</cstring> + </property> + <property name="text"> + <string>Ho&stname:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_hostCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_portLabel</cstring> + </property> + <property name="text"> + <string>P&ort:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_portInput</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_useAuth</cstring> + </property> + <property name="text"> + <string>Per&form authentication</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout12</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_userLabel</cstring> + </property> + <property name="text"> + <string>&Username:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_userEdit</cstring> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1"> + <property name="name"> + <cstring>m_passEdit</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_passLabel</cstring> + </property> + <property name="text"> + <string>&Password:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_passEdit</cstring> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>m_userEdit</cstring> + </property> + </widget> + </grid> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<tabstops> + <tabstop>m_hostCombo</tabstop> + <tabstop>m_addButton</tabstop> + <tabstop>m_removeButton</tabstop> + <tabstop>m_portInput</tabstop> + <tabstop>m_useAuth</tabstop> + <tabstop>m_userEdit</tabstop> + <tabstop>m_passEdit</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kmrml/kmrml/lib/Makefile.am b/kmrml/kmrml/lib/Makefile.am new file mode 100644 index 00000000..4201f04f --- /dev/null +++ b/kmrml/kmrml/lib/Makefile.am @@ -0,0 +1,11 @@ +noinst_LTLIBRARIES = libkmrmlstuff.la +libkmrmlstuff_la_SOURCES = kmrml_config.cpp mrml_shared.cpp mrml_utils.cpp\ +watcher_stub.cpp +noinst_HEADERS = kmrml_config.h mrml_shared.h mrml_utils.h watcher_stub.h + +METASOURCES = AUTO + +libkmrmlstuff_la_LDFLAGS = $(all_libraries) -no-undefined +libkmrmlstuff_la_LIBADD = $(LIB_KDECORE) + +INCLUDES = -I$(top_srcdir) $(all_includes) diff --git a/kmrml/kmrml/lib/kmrml_config.cpp b/kmrml/kmrml/lib/kmrml_config.cpp new file mode 100644 index 00000000..a88e8404 --- /dev/null +++ b/kmrml/kmrml/lib/kmrml_config.cpp @@ -0,0 +1,339 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qdir.h> +#include <qfile.h> +#include <qtextcodec.h> + +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kprocess.h> +#include <kstandarddirs.h> + +#include "kmrml_config.h" + +#include <kdeversion.h> +#if KDE_VERSION < 307 + #define QUOTE( x ) x +#else + #define QUOTE( x ) KProcess::quote( x ) +#endif + +using namespace KMrml; + +// #define DEFAULT_ADDCOLLECTION_CMD "gift-add-collection.pl --thumbnail-dir=%t --local-encoding %d" +#define DEFAULT_ADDCOLLECTION_CMD "gift-add-collection.pl --gift-home=%h --thumbnail-dir=%t --local-encoding=%e %d" +#define DEFAULT_REMOVECOLLECTION_CMD "gift-add-collection.pl --gift-home=%h --local-encoding=%e --remove-collection %d" + +#define DEFAULT_MRMLD_CMD "gift --port %p --datadir %d" +#define DEFAULT_MRMLD_CMD_AUTOPORT "gift --datadir %d" + +#define CONFIG_GROUP "MRML Settings" +#define DEFAULT_HOST "localhost" +#define DEFAULT_USER "kmrml" +#define DEFAULT_PASS "none" +#define DEFAULT_AUTH false +#define DEFAULT_AUTOPORT true +const int DEFAULT_PORT = 12789; + +Config::Config() +{ + m_ownConfig = new KConfig( "kio_mrmlrc", false, false ); + m_config = m_ownConfig; + + init(); +} + +Config::Config( KConfig *config ) + : m_config( config ), + m_ownConfig( 0L ) +{ + init(); +} + +Config::~Config() +{ + delete m_ownConfig; +} + +void Config::init() +{ + m_config->setGroup( CONFIG_GROUP ); + m_defaultHost = m_config->readEntry( "Default Host" ); + if ( m_defaultHost.isEmpty() ) + m_defaultHost = DEFAULT_HOST; + + m_hostList = m_config->readListEntry( "Host List" ); + if ( m_hostList.isEmpty() ) + m_hostList.append( DEFAULT_HOST ); + + m_serverStartedIndividually = + m_config->readBoolEntry( "ServerStartedIndividually", false ); +} + +bool Config::sync() +{ + bool notifySlaves = m_config->isDirty(); + m_config->sync(); + return notifySlaves; + + // This moved to kcontrol/MainPage::save() so we don't have to link against + // KIO and need a full KApplication instance to work (so that the tiny + // mrmlsearch binary can also use this class) + // tell the ioslaves about the new configuration +// if ( notifySlaves ) +// KIO::SlaveConfig::self()->reset(); +} + +void Config::setDefaultHost( const QString& host ) +{ + m_defaultHost = host.isEmpty() ? + QString::fromLatin1(DEFAULT_HOST) : host; + + m_config->setGroup( CONFIG_GROUP ); + m_config->writeEntry( "Default Host", m_defaultHost ); +} + +ServerSettings Config::settingsForLocalHost() const +{ + return settingsForHost( "localhost" ); +} + +ServerSettings Config::settingsForHost( const QString& host ) const +{ + KConfigGroup config( m_config, settingsGroup( host ) ); + ServerSettings settings; + + settings.host = host; + settings.configuredPort = config.readUnsignedNumEntry( "Port", + DEFAULT_PORT ); + settings.autoPort = (host == "localhost") && + config.readBoolEntry("Automatically determine Port", + DEFAULT_AUTOPORT ); + settings.user = config.readEntry( "Username", DEFAULT_USER ); + settings.pass = config.readEntry( "Password", DEFAULT_PASS ); + settings.useAuth = config.readBoolEntry( "Perform Authentication", + DEFAULT_AUTH ); + + return settings; +} + +void Config::addSettings( const ServerSettings& settings ) +{ + QString host = settings.host; + if ( m_hostList.find( host ) == m_hostList.end() ) + m_hostList.append( host ); + + m_config->setGroup( CONFIG_GROUP ); + m_config->writeEntry( "Host List", m_hostList ); + + m_config->setGroup( settingsGroup( host ) ); + m_config->writeEntry( "Host", host ); + m_config->writeEntry( "Port", settings.configuredPort ); + m_config->writeEntry( "Automatically determine Port", settings.autoPort ); + m_config->writeEntry( "Username", settings.user ); + m_config->writeEntry( "Password", settings.pass ); + m_config->writeEntry( "Perform Authentication", settings.useAuth ); +} + +bool Config::removeSettings( const QString& host ) +{ + bool success = m_config->deleteGroup( settingsGroup( host ) ); + if ( success ) + { + m_hostList.remove( host ); + m_config->setGroup( CONFIG_GROUP ); + } + + return success; +} + +QStringList Config::indexableDirectories() const +{ + m_config->setGroup( CONFIG_GROUP ); + return m_config->readListEntry( "Indexable Directories" ); +} + +void Config::setIndexableDirectories( const QStringList& dirs ) +{ + m_config->setGroup( CONFIG_GROUP ); + m_config->writeEntry( "Indexable Directories", dirs ); +} + +QString Config::addCollectionCommandLine() const +{ + m_config->setGroup( CONFIG_GROUP ); + QString cmd = m_config->readEntry( "AddCollection Commandline", + DEFAULT_ADDCOLLECTION_CMD ); + int index = cmd.find( "%h" ); + if ( index != -1 ) + cmd.replace( index, 2, QUOTE( mrmldDataDir() ) ); + + index = cmd.find( "%e" ); + if ( index != -1 ) + cmd.replace( index, 2, QTextCodec::codecForLocale()->mimeName() ); + + return cmd; +} + +void Config::setAddCollectionCommandLine( const QString& cmd ) +{ + m_config->setGroup( CONFIG_GROUP ); + m_config->writeEntry( "AddCollection Commandline", cmd ); +} + +QString Config::removeCollectionCommandLine() const +{ + m_config->setGroup( CONFIG_GROUP ); + QString cmd = m_config->readEntry( "RemoveCollection Commandline", + DEFAULT_REMOVECOLLECTION_CMD ); + int index = cmd.find( "%h" ); + if ( index != -1 ) + cmd.replace( index, 2, QUOTE( mrmldDataDir() ) ); + + index = cmd.find( "%e" ); + if ( index != -1 ) + cmd.replace( index, 2, QTextCodec::codecForLocale()->mimeName() ); + + return cmd; +} + +void Config::setRemoveCollectionCommandLine( const QString& cmd ) +{ + m_config->setGroup( CONFIG_GROUP ); + m_config->writeEntry( "RemoveCollection Commandline", cmd ); +} + +QString Config::mrmldCommandline() const +{ + ServerSettings settings = settingsForLocalHost(); + + m_config->setGroup( CONFIG_GROUP ); + QString cmd = m_config->readEntry( "MrmmlDaemon Commandline", + settings.autoPort ? + DEFAULT_MRMLD_CMD_AUTOPORT : + DEFAULT_MRMLD_CMD ); + + // add data directory and port to the commandline + int index = cmd.find( "%p" ); + if ( index != -1 ) + { + QString port = settings.autoPort ? + QString::null : QString::number( settings.configuredPort ); + cmd.replace( index, 2, port ); + } + index = cmd.find( "%d" ); + if ( index != -1 ) + { + cmd.replace( index, 2, QUOTE( mrmldDataDir() ) ); + } + + qDebug("***** commandline: %s", cmd.latin1()); + + return cmd; +} + +QString Config::mrmldDataDir() +{ + QString dir = KGlobal::dirs()->saveLocation( "data", + "kmrml/mrmld-data/" ); + if ( dir.isEmpty() ) // fallback + dir = QDir::homeDirPath() + "/"; + + return dir; +} + +void Config::setMrmldCommandLine( const QString& cmd ) +{ + m_config->setGroup( CONFIG_GROUP ); + m_config->writeEntry( "MrmmlDaemon Commandline", cmd ); +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +ServerSettings::ServerSettings() + : configuredPort( 0 ), + autoPort( true ), + useAuth( false ) +{ +} + +ServerSettings::ServerSettings( const QString& host, unsigned short int port, + bool autoPort, bool useAuth, + const QString& user, const QString& pass ) +{ + this->host = host; + this->configuredPort = port; + this->autoPort = autoPort; + this->useAuth = useAuth; + this->user = user; + this->pass = pass; +} + +// static +ServerSettings ServerSettings::defaults() +{ + return ServerSettings( DEFAULT_HOST, DEFAULT_PORT, + (!strcmp(DEFAULT_HOST, "localhost") && DEFAULT_PORT), + DEFAULT_AUTH, DEFAULT_USER, DEFAULT_PASS ); +} + +KURL ServerSettings::getUrl() const +{ + KURL url; + url.setProtocol( "mrml" ); + url.setHost( host ); + if ( !autoPort ) + url.setPort( configuredPort ); + + if ( useAuth && user.isEmpty() ) + { + url.setUser( user ); + url.setPass( pass ); + } + + return url; +} + +unsigned short int ServerSettings::port() const +{ + if ( autoPort ) + { + QString portsFile = Config::mrmldDataDir() + "gift-port.txt"; + QFile file( portsFile ); + if ( file.open( IO_ReadOnly ) ) + { + QString line; + (void) file.readLine( line, 6 ); +// qDebug("**** read: %s", line.latin1()); + + file.close(); + + bool ok; + unsigned short int p = line.toUShort( &ok ); + if ( ok ) + return p; + } + else + kdWarning() << "Can't open \"" << portsFile << "\" to automatically determine the gift port" << endl; + } + + return configuredPort; +} diff --git a/kmrml/kmrml/lib/kmrml_config.h b/kmrml/kmrml/lib/kmrml_config.h new file mode 100644 index 00000000..3b6baa40 --- /dev/null +++ b/kmrml/kmrml/lib/kmrml_config.h @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KMRML_CONFIG_H +#define KMRML_CONFIG_H + +class KConfig; + +#include <qstringlist.h> +#include <kurl.h> + +namespace KMrml +{ + class ServerSettings + { + public: + ServerSettings(); + ServerSettings(const QString& host, unsigned short int port, + bool autoPort, bool useAuth, const + QString& user, const QString& pass); + + // does NOT set the port in the KURL object, if autoPort is selected + // kio_mrml is going to determine itself (via ServerSettings::port()). + // This deuglifies the mrml:/ url a bit (no port is shown) + KURL getUrl() const; + + QString host; + QString user; + QString pass; + unsigned short int configuredPort; + bool autoPort :1; // only possible with host == localhost + bool useAuth :1; + + static ServerSettings defaults(); + + // returns configuredPort or the automatically determined port, + // depending on the value of autoPort + unsigned short int port() const; + }; + + class Config + { + public: + Config(); + Config( KConfig *config ); // does not take ownership of KConfig + ~Config(); + + bool sync(); + + ServerSettings defaultSettings() const + { + return settingsForHost( m_defaultHost ); + } + + ServerSettings settingsForLocalHost() const; + ServerSettings settingsForHost( const QString& host ) const; + + void setDefaultHost( const QString& host ); + + /** + * Indexed by the hostname -- ensures there are no dupes + */ + void addSettings( const ServerSettings& settings ); + + bool removeSettings( const QString& host ); + + QStringList hosts() const { return m_hostList; } + + /** + * The list of indexable directories -- only applicable to "localhost" + */ + QStringList indexableDirectories() const; + void setIndexableDirectories( const QStringList& dirs ); + + QString addCollectionCommandLine() const; + void setAddCollectionCommandLine( const QString& cmd ); + + QString removeCollectionCommandLine() const; + void setRemoveCollectionCommandLine( const QString& cmd ); + + void setMrmldCommandLine( const QString& cmd ); + QString mrmldCommandline() const; + + // e.g. Wolfgang needs this :) + bool serverStartedIndividually() const { + return m_serverStartedIndividually; + } + + static QString mrmldDataDir(); + + private: + void init(); + + QString settingsGroup( const QString& host ) const + { + return QString::fromLatin1( "SettingsFor: " ).append( host ); + } + + bool m_serverStartedIndividually; + QString m_defaultHost; + QStringList m_hostList; + + KConfig *m_config; + KConfig *m_ownConfig; + }; +} + +#endif // KMRML_CONFIG_H diff --git a/kmrml/kmrml/lib/mrml_shared.cpp b/kmrml/kmrml/lib/mrml_shared.cpp new file mode 100644 index 00000000..0c5b692b --- /dev/null +++ b/kmrml/kmrml/lib/mrml_shared.cpp @@ -0,0 +1,235 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "mrml_shared.h" + +// mrml stuff +const QString * MrmlShared::m_sessionId = 0L; +const QString * MrmlShared::m_transactionId = 0L; +const QString * MrmlShared::m_algorithm = 0L; +const QString * MrmlShared::m_algorithmId = 0L; +const QString * MrmlShared::m_algorithmName = 0L; +const QString * MrmlShared::m_algorithmList = 0L; +const QString * MrmlShared::m_algorithmType = 0L; +const QString * MrmlShared::m_collectionId = 0L; +const QString * MrmlShared::m_collectionList = 0L; +const QString * MrmlShared::m_collection = 0L; +const QString * MrmlShared::m_collectionName = 0L; +const QString * MrmlShared::m_queryParadigm = 0L; +const QString * MrmlShared::m_queryParadigmList = 0L; +const QString * MrmlShared::m_configureSession = 0L; + +const QString * MrmlShared::m_propertySheet = 0L; +const QString * MrmlShared::m_propertySheetId = 0L; +const QString * MrmlShared::m_propertySheetType = 0L; +const QString * MrmlShared::m_sendName = 0L; +const QString * MrmlShared::m_sendType = 0L; +const QString * MrmlShared::m_sendValue = 0L; +const QString * MrmlShared::m_maxSubsetSize = 0L; +const QString * MrmlShared::m_minSubsetSize = 0L; +const QString * MrmlShared::m_caption = 0L; +const QString * MrmlShared::m_from = 0L; +const QString * MrmlShared::m_to = 0L; +const QString * MrmlShared::m_step = 0L; +const QString * MrmlShared::m_sendBooleanInverted = 0L; + +const QString * MrmlShared::m_element = 0L; +const QString * MrmlShared::m_attribute = 0L; +const QString * MrmlShared::m_attributeName = 0L; +const QString * MrmlShared::m_attributeValue = 0L; +const QString * MrmlShared::m_children = 0L; +const QString * MrmlShared::m_none = 0L; + +const QString * MrmlShared::m_multiSet = 0L; +const QString * MrmlShared::m_subset = 0L; +const QString * MrmlShared::m_setElement = 0L; +const QString * MrmlShared::m_boolean = 0L; +const QString * MrmlShared::m_numeric = 0L; +const QString * MrmlShared::m_textual = 0L; +const QString * MrmlShared::m_panel = 0L; +const QString * MrmlShared::m_clone = 0L; +const QString * MrmlShared::m_reference = 0L; + +const QString * MrmlShared::m_visibility = 0L; +const QString * MrmlShared::m_visible = 0L; +const QString * MrmlShared::m_invisible = 0L; +const QString * MrmlShared::m_popup = 0L; +// const QString * MrmlShared::m_ = 0L; + +// meta-data +const QString * MrmlShared::m_mrml_data = 0L; + +// kio_mrml tasks +const QString * MrmlShared::m_kio_task = 0L; +const QString * MrmlShared::m_kio_initialize = 0L; +const QString * MrmlShared::m_kio_startQuery = 0L; + + +int MrmlShared::s_references = 0; + +void MrmlShared::ref() +{ + if ( s_references == 0 ) + init(); + + s_references++; +} + +bool MrmlShared::deref() +{ + if ( s_references > 0 ) + s_references--; + + if ( s_references == 0 ) + { + // ### delete all strings here... + + return true; + } + + return false; +} + +void MrmlShared::init() +{ + m_sessionId = new QString ( "session-id" ) ; + m_transactionId = new QString ( "transaction-id" ) ; + m_algorithm = new QString ( "algorithm" ) ; + m_algorithmId = new QString ( "algorithm-id" ) ; + m_algorithmName = new QString ( "algorithm-name" ) ; + m_algorithmList = new QString ( "algorithm-list" ) ; + m_algorithmType = new QString ( "algorithm-type" ) ; + m_collectionId = new QString ( "collection-id" ) ; + m_collectionList = new QString ( "collection-list" ) ; + m_collection = new QString ( "collection" ) ; + m_collectionName = new QString ( "collection-name" ) ; + m_queryParadigm = new QString ( "query-paradigm" ) ; + m_queryParadigmList = new QString ( "query-paradigm-list" ) ; + m_configureSession = new QString ( "configure-session" ) ; + + m_propertySheet = new QString ( "property-sheet" ) ; + m_propertySheetId = new QString ( "property-sheet-id" ) ; + m_propertySheetType = new QString ( "property-sheet-type" ) ; + m_sendName = new QString ( "send-name" ) ; + m_sendType = new QString ( "send-type" ) ; + m_sendValue = new QString ( "send-value" ) ; + m_maxSubsetSize = new QString ( "maxsubsetsize" ) ; + m_minSubsetSize = new QString ( "minsubsetsize" ) ; + m_caption = new QString ( "caption" ) ; + m_from = new QString ( "from" ) ; + m_to = new QString ( "to" ) ; + m_step = new QString ( "step" ) ; + m_sendBooleanInverted = new QString ( "send-boolean-inverted" ) ; + + m_element = new QString ( "element" ) ; + m_attribute = new QString ( "attribute" ) ; + m_attributeName = new QString ( "attribute-name" ) ; + m_attributeValue = new QString ( "attribute-value" ) ; + m_children = new QString ( "children" ) ; + m_none = new QString ( "none" ) ; + + m_multiSet = new QString ( "multi-set" ) ; + m_subset = new QString ( "subset" ) ; + m_setElement = new QString ( "set-element" ) ; + m_boolean = new QString ( "boolean" ) ; + m_numeric = new QString ( "numeric" ) ; + m_textual = new QString ( "textual" ) ; + m_panel = new QString ( "panel" ) ; + m_clone = new QString ( "clone" ) ; + m_reference = new QString ( "reference" ) ; + + m_visibility = new QString ( "visibility" ) ; + m_visible = new QString ( "visible" ) ; + m_invisible = new QString ( "invisible" ) ; + m_popup = new QString ( "popup" ) ; +// m_ = new QString ( "" ) ; + +// meta-data + m_mrml_data = new QString ( "mrml_data" ) ; + +// kio_mrml tasks + m_kio_task = new QString ( "kio_task" ) ; + m_kio_initialize = new QString ( "kio_initialize" ) ; + m_kio_startQuery = new QString ( "kio_startQuery" ) ; +} + +void MrmlShared::cleanup() +{ + delete m_sessionId; + delete m_transactionId; + delete m_algorithm; + delete m_algorithmId; + delete m_algorithmName; + delete m_algorithmList; + delete m_algorithmType; + delete m_collectionId; + delete m_collectionList; + delete m_collection; + delete m_collectionName; + delete m_queryParadigm; + delete m_queryParadigmList; + delete m_configureSession; + + // property sheet stuff + delete m_propertySheet; + delete m_propertySheetId; + delete m_propertySheetType; + delete m_sendName; + delete m_sendType; + delete m_sendValue; + delete m_maxSubsetSize; + delete m_minSubsetSize; + delete m_caption; + delete m_from; + delete m_to; + delete m_step; + delete m_sendBooleanInverted; + + delete m_multiSet; + delete m_subset; + delete m_setElement; + delete m_boolean; + delete m_numeric; + delete m_textual; + delete m_panel; + delete m_clone; + delete m_reference; + + delete m_element; + delete m_attribute; + delete m_attributeName; + delete m_attributeValue; + delete m_children; + delete m_none; + + delete m_visibility; + delete m_visible; + delete m_invisible; + delete m_popup; +// delete m_; + + // meta-data + delete m_mrml_data; + + // kio_mrml tasks + delete m_kio_task; + delete m_kio_initialize; + delete m_kio_startQuery; + +} diff --git a/kmrml/kmrml/lib/mrml_shared.h b/kmrml/kmrml/lib/mrml_shared.h new file mode 100644 index 00000000..aff2a98d --- /dev/null +++ b/kmrml/kmrml/lib/mrml_shared.h @@ -0,0 +1,166 @@ +/* This file is part of the KDE project + Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SHARED_H +#define SHARED_H + +// maybe use mrml_const.h from libMRML, unfortunately not installed +// by gift 0.1.6pre2 + +#include <qshared.h> +#include <qstring.h> + +class MrmlShared +{ +public: +// attribute/element names for mrml + static void ref(); + static bool deref(); + + static const QString& sessionId() { return *m_sessionId; } + static const QString& transactionId() { return *m_transactionId; } + static const QString& algorithm() { return *m_algorithm; } + static const QString& algorithmId() { return *m_algorithmId; } + static const QString& algorithmName() { return *m_algorithmName; } + static const QString& algorithmList() { return *m_algorithmList; } + static const QString& algorithmType() { return *m_algorithmType; } + static const QString& collectionId() { return *m_collectionId; } + static const QString& collectionList() { return *m_collectionList; } + static const QString& collection() { return *m_collection; } + static const QString& collectionName() { return *m_collectionName; } + static const QString& queryParadigm() { return *m_queryParadigm; } + static const QString& queryParadigmList() { return *m_queryParadigmList; } + static const QString& configureSession() { return *m_configureSession; } + + // property sheet stuff + static const QString& propertySheet() { return *m_propertySheet; } + static const QString& propertySheetId() { return *m_propertySheetId; } + static const QString& propertySheetType() { return *m_propertySheetType; } + static const QString& sendName() { return *m_sendName; } + static const QString& sendType() { return *m_sendType; } + static const QString& sendValue() { return *m_sendValue; } + static const QString& maxSubsetSize() { return *m_maxSubsetSize; } + static const QString& minSubsetSize() { return *m_minSubsetSize; } + static const QString& caption() { return *m_caption; } + static const QString& from() { return *m_from; } + static const QString& to() { return *m_to; } + static const QString& step() { return *m_step; } + static const QString& sendBooleanInverted() { return *m_sendBooleanInverted; } + + static const QString& multiSet() { return *m_multiSet; } + static const QString& subset() { return *m_subset; } + static const QString& setElement() { return *m_setElement; } + static const QString& boolean() { return *m_boolean; } + static const QString& numeric() { return *m_numeric; } + static const QString& textual() { return *m_textual; } + static const QString& panel() { return *m_panel; } + static const QString& clone() { return *m_clone; } + static const QString& reference() { return *m_reference; } + + static const QString& element() { return *m_element; } + static const QString& attribute() { return *m_attribute; } + static const QString& attributeName() { return *m_attributeName; } + static const QString& attributeValue() { return *m_attributeValue; } + static const QString& children() { return *m_children; } + static const QString& none() { return *m_none; } + + static const QString& visibility() { return *m_visibility; } + static const QString& visible() { return *m_visible; } + static const QString& invisible() { return *m_invisible; } + static const QString& popup() { return *m_popup; } +// static const QString& () { return *m_; } + + // meta-data + static const QString& mrml_data() { return *m_mrml_data; } + + // kio_mrml tasks + static const QString& kio_task() { return *m_kio_task; } + static const QString& kio_initialize() { return *m_kio_initialize; } + static const QString& kio_startQuery() { return *m_kio_startQuery; } + + +private: + static const QString * m_sessionId; + static const QString * m_transactionId; + static const QString * m_algorithm; + static const QString * m_algorithmId; + static const QString * m_algorithmName; + static const QString * m_algorithmList; + static const QString * m_algorithmType; + static const QString * m_collectionId; + static const QString * m_collectionList; + static const QString * m_collection; + static const QString * m_collectionName; + static const QString * m_queryParadigm; + static const QString * m_queryParadigmList; + static const QString * m_configureSession; + + // property sheet stuff + static const QString * m_propertySheet; + static const QString * m_propertySheetId; + static const QString * m_propertySheetType; + static const QString * m_sendName; + static const QString * m_sendType; + static const QString * m_sendValue; + static const QString * m_maxSubsetSize; + static const QString * m_minSubsetSize; + static const QString * m_caption; + static const QString * m_from; + static const QString * m_to; + static const QString * m_step; + static const QString * m_sendBooleanInverted; + + static const QString * m_multiSet; + static const QString * m_subset; + static const QString * m_setElement; + static const QString * m_boolean; + static const QString * m_numeric; + static const QString * m_textual; + static const QString * m_panel; + static const QString * m_clone; + static const QString * m_reference; + + static const QString * m_element; + static const QString * m_attribute; + static const QString * m_attributeName; + static const QString * m_attributeValue; + static const QString * m_children; + static const QString * m_none; + + static const QString * m_visibility; + static const QString * m_visible; + static const QString * m_invisible; + static const QString * m_popup; +// static const QString * m_; + + // meta-data + static const QString * m_mrml_data; + + // kio_mrml tasks + static const QString * m_kio_task; + static const QString * m_kio_initialize; + static const QString * m_kio_startQuery; + +private: + static void cleanup(); + static void init(); + + static int s_references; +}; + +#endif // SHARED_H diff --git a/kmrml/kmrml/lib/mrml_utils.cpp b/kmrml/kmrml/lib/mrml_utils.cpp new file mode 100644 index 00000000..f20dad6a --- /dev/null +++ b/kmrml/kmrml/lib/mrml_utils.cpp @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <dcopclient.h> +#include <kapplication.h> +#include <kprocess.h> +#include <kstaticdeleter.h> + +#include "watcher_stub.h" + +#include "mrml_utils.h" + +// after 100 of no use, terminate the mrmld +#define TIMEOUT 100 +// how often to restart the mrmld in case of failure +#define NUM_RESTARTS 5 + +using namespace KMrml; + +KStaticDeleter<Util> utils_sd; + +Util *Util::s_self = 0L; + +Util::Util() +{ + // we need our own dcopclient, when used in kio_mrml + if ( !DCOPClient::mainClient() ) + { + DCOPClient::setMainClient( new DCOPClient() ); + if ( !DCOPClient::mainClient()->attach() ) + qWarning( "kio_mrml: Can't attach to DCOP Server."); + } +} + +Util::~Util() +{ + if ( this == s_self ) + s_self = 0L; +} + +Util *Util::self() +{ + if ( !s_self ) + s_self = utils_sd.setObject( new Util() ); + return s_self; +} + +bool Util::requiresLocalServerFor( const KURL& url ) +{ + return url.host().isEmpty() || url.host() == "localhost"; +} + +bool Util::startLocalServer( const Config& config ) +{ + if ( config.serverStartedIndividually() ) + return true; + + DCOPClient *client = DCOPClient::mainClient(); + + // ### check if it's already running (add dcop method to Watcher) + Watcher_stub watcher( client, "kded", "daemonwatcher"); + return ( watcher.requireDaemon( client->appId(), + "mrmld", config.mrmldCommandline(), + TIMEOUT, NUM_RESTARTS ) + && watcher.ok() ); +} + +void Util::unrequireLocalServer() +{ + DCOPClient *client = DCOPClient::mainClient(); + + Watcher_stub watcher( client, "kded", "daemonwatcher"); + watcher.unrequireDaemon( client->appId(), "mrmld" ); +} diff --git a/kmrml/kmrml/lib/mrml_utils.h b/kmrml/kmrml/lib/mrml_utils.h new file mode 100644 index 00000000..25f39d98 --- /dev/null +++ b/kmrml/kmrml/lib/mrml_utils.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#ifndef MRML_UTILS_H +#define MRML_UTILS_H + +#include <qobject.h> + +#include <kurl.h> + +#include "kmrml_config.h" + +namespace KMrml +{ + class Util : public QObject + { + public: + static Util * self(); + ~Util(); + + bool requiresLocalServerFor( const KURL& url ); + bool startLocalServer( const Config& config ); + void unrequireLocalServer(); +// bool isLocalServerRunning(); + + private: + static Util *s_self; + Util(); + }; + + +} + +#endif // MRML_UTILS_H diff --git a/kmrml/kmrml/lib/version.h b/kmrml/kmrml/lib/version.h new file mode 100644 index 00000000..5cf8e270 --- /dev/null +++ b/kmrml/kmrml/lib/version.h @@ -0,0 +1,6 @@ +#ifndef VERSION_H +#define VERSION_H + +#define KMRML_VERSION "0.3.2" + +#endif // VERSION_H diff --git a/kmrml/kmrml/lib/watcher_stub.cpp b/kmrml/kmrml/lib/watcher_stub.cpp new file mode 100644 index 00000000..cf84818b --- /dev/null +++ b/kmrml/kmrml/lib/watcher_stub.cpp @@ -0,0 +1,95 @@ +// +// Generated in ../server/ via dcopidl -- needs to be in the lib tho. +// Regenerate when necessary by uncommenting the watcher.stub in +// ../server/Makefile.am +// + +#include "watcher_stub.h" +#include <dcopclient.h> + +#include <kdatastream.h> + +namespace KMrml { + +Watcher_stub::Watcher_stub( const QCString& app, const QCString& obj ) + : DCOPStub( app, obj ) +{ +} + +Watcher_stub::Watcher_stub( DCOPClient* client, const QCString& app, const QCString& obj ) + : DCOPStub( client, app, obj ) +{ +} + +bool Watcher_stub::requireDaemon( const QCString& arg0, const QString& arg1, const QString& arg2, uint arg3, int arg4 ) +{ + bool result; + if ( !dcopClient() ) { + setStatus( CallFailed ); + return false; + } + QByteArray data, replyData; + QCString replyType; + QDataStream arg( data, IO_WriteOnly ); + arg << arg0; + arg << arg1; + arg << arg2; + arg << arg3; + arg << arg4; + if ( dcopClient()->call( app(), obj(), "requireDaemon(QCString,QString,QString,uint,int)", data, replyType, replyData ) ) { + if ( replyType == "bool" ) { + QDataStream _reply_stream( replyData, IO_ReadOnly ); + _reply_stream >> result; + setStatus( CallSucceeded ); + } else { + callFailed(); + } + } else { + callFailed(); + } + return result; +} + +void Watcher_stub::unrequireDaemon( const QCString& arg0, const QString& arg1 ) +{ + if ( !dcopClient() ) { + setStatus( CallFailed ); + return; + } + QByteArray data, replyData; + QCString replyType; + QDataStream arg( data, IO_WriteOnly ); + arg << arg0; + arg << arg1; + if ( dcopClient()->call( app(), obj(), "unrequireDaemon(QCString,QString)", data, replyType, replyData ) ) { + setStatus( CallSucceeded ); + } else { + callFailed(); + } +} + +QStringList Watcher_stub::runningDaemons() +{ + QStringList result; + if ( !dcopClient() ) { + setStatus( CallFailed ); + return result; + } + QByteArray data, replyData; + QCString replyType; + if ( dcopClient()->call( app(), obj(), "runningDaemons()", data, replyType, replyData ) ) { + if ( replyType == "QStringList" ) { + QDataStream _reply_stream( replyData, IO_ReadOnly ); + _reply_stream >> result; + setStatus( CallSucceeded ); + } else { + callFailed(); + } + } else { + callFailed(); + } + return result; +} + +} // namespace + diff --git a/kmrml/kmrml/lib/watcher_stub.h b/kmrml/kmrml/lib/watcher_stub.h new file mode 100644 index 00000000..04b1292e --- /dev/null +++ b/kmrml/kmrml/lib/watcher_stub.h @@ -0,0 +1,36 @@ +// +// Generated in ../server/ via dcopidl -- needs to be in the lib tho. +// Regenerate when necessary by uncommenting the watcher.stub in +// ../server/Makefile.am +// + +#ifndef __WATCHER_STUB__ +#define __WATCHER_STUB__ + +#include <dcopstub.h> +#include <qdict.h> +#include <qptrlist.h> +#include <qmap.h> +#include <qstrlist.h> +#include <qstringlist.h> +#include <qtimer.h> +#include <kdedmodule.h> +#include <kprocess.h> + +namespace KMrml { + +class Watcher_stub : public DCOPStub +{ +public: + Watcher_stub( const QCString& app, const QCString& id ); + Watcher_stub( DCOPClient* client, const QCString& app, const QCString& id ); + virtual bool requireDaemon( const QCString& clientAppId, const QString& daemonKey, const QString& commandline, uint timeout, int numRestarts ); + virtual void unrequireDaemon( const QCString& clientAppId, const QString& daemonKey ); + virtual QStringList runningDaemons(); +protected: + Watcher_stub() : DCOPStub( never_use ) {}; +}; + +} // namespace + +#endif diff --git a/kmrml/kmrml/loader.cpp b/kmrml/kmrml/loader.cpp new file mode 100644 index 00000000..cc59c172 --- /dev/null +++ b/kmrml/kmrml/loader.cpp @@ -0,0 +1,121 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kstaticdeleter.h> +#include <kio/scheduler.h> + +#include "loader.h" + +Loader *Loader::s_self = 0L; + +KStaticDeleter<Loader> sd; + +Loader * Loader::self() +{ + if ( !s_self ) + s_self = sd.setObject( new Loader() ); + + return s_self; +} + +Loader::Loader() : QObject() +{ +} + +Loader::~Loader() +{ + disconnect( this, SIGNAL( finished( const KURL&, const QByteArray& ))); + + DownloadIterator it = m_downloads.begin(); + for ( ; it != m_downloads.end(); ++it ) { + it.key()->kill(); + delete it.data(); + } + + s_self = 0L; +} + +void Loader::requestDownload( const KURL& url ) +{ + DownloadIterator it = m_downloads.begin(); + for ( ; it != m_downloads.end(); ++it ) { + if ( it.key()->url() == url ) + return; + } + + KIO::TransferJob *job = KIO::get( url, false, false ); + KIO::Scheduler::scheduleJob(job); + + connect( job , SIGNAL( data( KIO::Job *, const QByteArray& )), + SLOT( slotData( KIO::Job *, const QByteArray& ))); + connect( job , SIGNAL( result( KIO::Job * )), + SLOT( slotResult( KIO::Job * ))); + + Download *d = new Download(); + m_downloads.insert( job, d ); +} + +void Loader::slotData( KIO::Job *job, const QByteArray& data ) +{ + DownloadIterator it = m_downloads.find( static_cast<KIO::TransferJob*>(job) ); + if ( it != m_downloads.end() ) { + QBuffer& buffer = it.data()->m_buffer; + if ( !buffer.isOpen() ) + buffer.open( IO_ReadWrite ); + if ( !buffer.isOpen() ) { + qDebug("********* EEK, can't open buffer for thumbnail download!"); + return; + } + + buffer.writeBlock( data.data(), data.size() ); + } +} + +void Loader::slotResult( KIO::Job *job ) +{ + KIO::TransferJob *tjob = static_cast<KIO::TransferJob*>( job ); + + DownloadIterator it = m_downloads.find( tjob ); + if ( it != m_downloads.end() ) { + Download *d = it.data(); + + if ( job->error() != 0 ) + emit finished( tjob->url(), QByteArray() ); + else + emit finished( tjob->url(), d->m_buffer.buffer() ); + + delete d; + m_downloads.remove( it ); + } +} + + +// ### simultaneous downloads with multiple views? reference count downloads! +void Loader::removeDownload( const KURL& url ) +{ + DownloadIterator it = m_downloads.begin(); + for ( ; it != m_downloads.end(); ++it ) { + if ( it.key()->url() == url ) { + it.key()->kill(); + delete it.data(); + return; + } + } +} + +#include "loader.moc" diff --git a/kmrml/kmrml/loader.h b/kmrml/kmrml/loader.h new file mode 100644 index 00000000..5e81a2e4 --- /dev/null +++ b/kmrml/kmrml/loader.h @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef LOADER_H +#define LOADER_H + +#include <qbuffer.h> +#include <qcstring.h> +#include <qmap.h> +#include <qobject.h> + +#include <kio/job.h> +#include <kurl.h> + +class Download +{ +public: + ~Download() { + if ( m_buffer.isOpen() ) + m_buffer.close(); + } + QBuffer m_buffer; + // add context of MrmlPart for progress? +}; + + +class Loader : public QObject +{ + friend class gcc_sucks; + Q_OBJECT + +public: + static Loader *self(); + ~Loader(); + + void requestDownload( const KURL& url ); + + void removeDownload( const KURL& url ); + +signals: + void finished( const KURL& url, const QByteArray& ); + +private slots: + void slotData( KIO::Job *, const QByteArray& ); + void slotResult( KIO::Job * ); + +private: + Loader(); + + QMap<KIO::TransferJob*,Download*> m_downloads; + typedef QMapIterator<KIO::TransferJob*,Download*> DownloadIterator; + + static Loader *s_self; + +}; + +#endif // LOADER_H diff --git a/kmrml/kmrml/mrml-servicemenu.desktop b/kmrml/kmrml/mrml-servicemenu.desktop new file mode 100644 index 00000000..2d9a938c --- /dev/null +++ b/kmrml/kmrml/mrml-servicemenu.desktop @@ -0,0 +1,67 @@ +[Desktop Entry] +ServiceTypes=image/png,image/jpeg,image/gif,image/tiff,image/bmp,image/x-xpm,image/x-xbm,image/x-png +Actions=search; + +[Desktop Action search] +Name=Search for Similar Images... +Name[af]=Soektog vir Soortgelyk Beelde... +Name[ar]=بحث عن الصور المتشابهه... +Name[bg]=Търсене на подобни изображения... +Name[bs]=Traženje sličnih slika... +Name[ca]=Cerca imatges similars... +Name[cs]=Hledat podobný obrázek... +Name[cy]=Chwilio am Ddelweddau Tebyg... +Name[da]=Søg efter lignende filer... +Name[de]=Nach ähnlichen Bildern suchen ... +Name[el]=Αναζήτηση για παρόμοιες εικόνες... +Name[eo]=Serĉi Similajn Bildojn... +Name[es]=Búsqueda de imágenes similares... +Name[et]=Otsi sarnaseid pilte... +Name[eu]=Bilatu antzeko irudiak... +Name[fa]=جستجو برای تصاویر مشابه... +Name[fi]=Etsi samankaltaisia kuvia... +Name[fr]=Recherche d'images semblables... +Name[gl]=Procurar imaxes semellantes... +Name[he]=חיפוש תמונות דומות... +Name[hi]=एक जैसे छवियों के लिए ढूंढें... +Name[hu]=Ehhez hasonló képek keresése... +Name[is]=Leita að svipuðum myndum... +Name[it]=Cerca immagini simili... +Name[ja]=同じような画像を検索... +Name[kk]=Ұқсас кескіндерді іздеу... +Name[km]=ស្វែងរករូបភាពស្រដៀងគ្នា... +Name[lt]=Panašių paveikslėlių paieška... +Name[ms]=Cari Imej Serupa... +Name[nb]=Søk etter liknende bilder … +Name[nds]=Na lieke Biller söken... +Name[ne]=उस्तै छविका लागि खोजी गर्नुहोस्... +Name[nl]=Zoeken naar vergelijkbare afbeeldingen... +Name[nn]=Søk etter liknande bilete … +Name[nso]=Nyako ya Diponagalo tseo di Swanago... +Name[pl]=Szukaj podobnych obrazków +Name[pt]=Procurar por Imagens Semelhantes... +Name[pt_BR]=Procurar por Imagens Parecidas... +Name[ro]=Caută imagini similare... +Name[ru]=Поиск похожих изображений... +Name[se]=Oza seammalágana govaid … +Name[sk]=Hľadať podobné obrázky... +Name[sl]=Išči podobne slike ... +Name[sr]=Потражи сличне слике... +Name[sr@Latn]=Potraži slične slike... +Name[sv]=Sök efter liknande bilder... +Name[ta]=இதே போன்ற பிம்பங்களை தேடுக... +Name[tg]=Ҷустуҷӯи тасвироти якхела... +Name[th]=ค้นหาภาพที่เหมือนกัน... +Name[tr]=Benzer Resimleri Ara... +Name[uk]=Пошук схожих зображень... +Name[uz]=Oʻxshash rasmlarni qidirish +Name[uz@cyrillic]=Ўхшаш расмларни қидириш +Name[ven]=Todani zwifanyiso zwielanaho... +Name[wa]=Cweri après des rshonnantès imådjes... +Name[xh]=Phendla Imifanekiso Efanayo... +Name[zh_CN]=搜索类似图像... +Name[zh_HK]=尋找類似的圖像... +Name[zh_TW]=尋找類似的影像... +Name[zu]=Sesha ukuthola Izithombe Ezifanayo.... +Icon=image +Exec=mrmlsearch %U diff --git a/kmrml/kmrml/mrml.cpp b/kmrml/kmrml/mrml.cpp new file mode 100644 index 00000000..082d037b --- /dev/null +++ b/kmrml/kmrml/mrml.cpp @@ -0,0 +1,267 @@ +/* This file is part of the KDE project + Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kinstance.h> +#include <klocale.h> + +#include <mrml_utils.h> + +#include "mrml.h" + +extern "C" { + KDE_EXPORT int kdemain( int argc, char **argv ) + { + KLocale::setMainCatalogue("kdelibs"); + KInstance instance( "kio_mrml" ); + KGlobal::locale()->insertCatalogue( "kmrml" ); + + kdDebug() << "Starting MRML " << getpid() << endl; + + if (argc != 4) + { + fprintf(stderr, "Usage: kio_mrml protocol domain-socket1 domain-socket2\n"); + exit(-1); + } + + Mrml slave(argv[2], argv[3]); + slave.dispatchLoop(); + + kdDebug() << "Done" << endl; + return 0; + } +} + +const int Mrml::bufsize = 8192; + +Mrml::Mrml( const QCString& pool_socket, const QCString& app_socket ) + : TCPSlaveBase( 12789, "mrml", pool_socket, app_socket ), + m_config( KGlobal::config() ) +{ + MrmlShared::ref(); +} + +Mrml::~Mrml() +{ + KMrml::Util::self()->unrequireLocalServer(); + + closeDescriptor(); + MrmlShared::deref(); +} + +bool Mrml::checkLocalServer( const KURL& url ) +{ + if ( KMrml::Util::self()->requiresLocalServerFor( url ) ) + { + if ( !KMrml::Util::self()->startLocalServer( m_config ) ) + return false; + } + + return true; +} + +void Mrml::get( const KURL& url ) +{ +// qDebug("******* getting: %s (user: %s)", url.url().latin1(), url.user().latin1()); + + if ( !checkLocalServer( url ) ) + { + error( KIO::ERR_SLAVE_DEFINED, i18n("Unable to start the Indexing Server. " + "Aborting the query.") ); + return; + } + + int retriesLeft = 5; +tryConnect: + + QCString utf8; + bool sendError = (retriesLeft <= 0); + + if ( connectToHost( url.host(), port(url), sendError ) ) + { +// qDebug(" connected!"); + + QString task = metaData( MrmlShared::kio_task() ); + + if ( task == MrmlShared::kio_initialize() ) { + startSession( url ); + } + + else if ( task == MrmlShared::kio_startQuery() ) { + QString meta = metaData( MrmlShared::mrml_data() ); + if ( meta.isEmpty() ) { + closeDescriptor(); + error( KIO::ERR_SLAVE_DEFINED, i18n("No MRML data is available.") ); + return; + } + + utf8 = meta.utf8(); + write( utf8, utf8.length() ); + + emitData( readAll() ); + } + + // no task metadata available, we're called from KonqRun or something + // like that. Emitting the mimetype seems to suffice for now. After + // that, MrmlPart is going to start and start the get() again. + else + { + mimeType( "text/mrml" ); + finished(); + } + + } + else + { + if ( retriesLeft-- >= 0 ) + { +#ifdef HAVE_USLEEP + usleep( 500 ); // wait a while for gift to start up +#endif + goto tryConnect; + return; + } + + error( KIO::ERR_COULD_NOT_CONNECT, + i18n("Could not connect to GIFT server.") ); + return; + } + + closeDescriptor(); + //data( QByteArray() ); // send an empty QByteArray to signal end of data. + finished(); +} + +// make sure we're connected when you call this! +QCString Mrml::readAll() +{ + QCString data; + + char buf[bufsize]; + ssize_t bytes = 0; + + while ( (bytes = read( buf, bufsize-1 )) > 0 ) { + buf[bytes] = '\0'; + data.append( buf ); + } + +// qDebug("*** readAll()::: %i, %s", data.length(), data.data()); + return data; +} + +QCString Mrml::loginString() +{ + return "<mrml><get-server-properties/></mrml>"; +} + +QCString Mrml::getConfigurationString() +{ + return "<mrml><get-configuration/></mrml>"; +} + +// ### needed? +QCString Mrml::getSessionsString( const QString& username, + const QString& password ) +{ + QCString data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><mrml><get-sessions "; + if ( !username.isEmpty() ) { // ### pop up auth-dialog??? + data.append( "user-name=\""); + data.append( username.utf8() ); + data.append( "\""); + + if ( !password.isEmpty() ) { + data.append( " password=\""); + data.append( password.utf8() ); + data.append( "\"" ); + } + + } + data.append( "/></mrml>" ); + + return data; +} + + +bool Mrml::startSession( const KURL& url ) +{ + // might first ask for collections, and then for algorithms for the + // desired collection-id + + // Wolfgang says, we shouldn't create an own session-id here, as gcc 2.95 + // apparently makes problems in exception handling somehow. So we simply + // accept the server's session-id. + QString msg = mrmlString( QString::null ).arg( + "<open-session user-name=\"%1\" session-name=\"kio_mrml session\" /> \ + <get-algorithms /> \ + <get-collections /> \ + </mrml>" ).arg( user( url )); + + QCString utf8 = msg.utf8(); +// qDebug(":::Writing: %s", utf8.data()); + write( utf8, utf8.length() ); + + emitData( readAll() ); + + return true; +} + +QString Mrml::mrmlString( const QString& sessionId, const QString& transactionId ) +{ + QString msg = + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?> \ + <!DOCTYPE mrml SYSTEM \"http://isrpc85.epfl.ch/Charmer/code/mrml.dtd\"> \ + %1 \ + </mrml>"; + + if ( sessionId.isEmpty() ) // when we don't have one yet + return msg.arg( "<mrml>%1" ); + + if ( transactionId.isNull() ) + return msg.arg( "<mrml session-id=\"%1\">%1" ).arg( sessionId ); + else + return msg.arg( "<mrml session-id=\"%1\" transaction-id=\"%1\">%1") + .arg( sessionId ).arg( transactionId ); +} + +void Mrml::emitData( const QCString& msg ) +{ + mimeType( "text/mrml" ); + data( msg ); + processedSize( msg.count() ); +} + +void Mrml::mimetype( const KURL& url ) +{ + if ( url.protocol() == "mrml" ) { + mimeType( "text/mrml" ); + finished(); + } + else + KIO::TCPSlaveBase::mimetype( url ); +} diff --git a/kmrml/kmrml/mrml.desktop b/kmrml/kmrml/mrml.desktop new file mode 100644 index 00000000..73abf1e0 --- /dev/null +++ b/kmrml/kmrml/mrml.desktop @@ -0,0 +1,60 @@ +[Desktop Entry] +Comment=Multimedia Retrieval Markup Language Document +Comment[af]=Multimedia Onttrekking Opmerk Taal Dokument +Comment[ar]=مستند لغة ترميز استرجاع الوسائط المتعددة +Comment[bs]=Multimedia Retrieval Markup Language dokument +Comment[ca]=Document de llenguatge de marcatge de recuperació multimèdia +Comment[cs]=Multimedia Retrieval Markup Language dokument +Comment[cy]=Dogfen Multimedia Retrieval Markup Language +Comment[da]=Multimedia Retrieval Markup Language-dokument +Comment[de]=Multimedia Suche- und Beschreibungssprache-Dokument (MRML-Dokument) +Comment[el]=Έγγραφο Multimedia Retrieval Markup Language +Comment[es]=Documento de lenguaje de descripción de descargas multimedia +Comment[et]=Multimeedia otsingu märgistuskeele (MRML) dokument +Comment[eu]=Multimedia Retrieval Markup Language dokumentua +Comment[fa]=سند زبان نشانگذاری بازیابی چند رسانهای +Comment[fi]=Multimedianhakuasiakirja +Comment[fr]=Document en langage Multimedia Retrieval Markup (MRML) +Comment[he]=מסמך שפת סימון לאחזור מולטימדיה +Comment[hi]=मल्टीमीडिया रिट्राइवल मार्कअप लैंग्वेज दस्तावेज़ +Comment[hu]=MRML-fájl +Comment[is]=Multimedia Retrieval Markup Language skjal +Comment[it]=Documento MRML +Comment[ja]=Multimedia Retrieval Markup Language ドキュメント +Comment[kk]=MRML (Multimedia Retrieval Markup Language) құжаты +Comment[km]=ឯកសារ Multimedia Retrieval Markup Language +Comment[lt]=Multimedia Retrieval Markup kalbos dokumentas +Comment[ms]=Dokumen Bahasa Capaian Tandatas Multimedia +Comment[nb]=«Multimedia Retrieval Markup Language»-dokument +Comment[nds]=Dokment in de Affraag-Utteekspraak för Multimedia-Dokmenten +Comment[ne]=मल्टिमिडिया पुन: प्राप्ति मार्कअप भाषा कागजात +Comment[nl]=Multimedia Retrieval Markup Language-document +Comment[nn]=«Multimedia Retrieval Markup Language»-dokument +Comment[nso]=Tokomane ya Leleme la Peakanyo ya Kutullo ya Multimedia +Comment[pl]=Dokument MRML (Język Znacznikowy Pozyskiwania Multimediów) +Comment[pt]=Documento de Multimedia Retrieval Markup Language +Comment[pt_BR]=Documento da Linguagem de Marcação de Recuperação Multimídia +Comment[ro]=Document MRML (limbaj de marcare pentru căutări multimedia) +Comment[ru]=Документ MRML (Multimedia Retrieval Markup Language) +Comment[se]=«Multimedia Retrieval Markup Language»-dokumeanta +Comment[sk]=Dokument Multimedia Retrieval Markup Language +Comment[sl]=Dokument Multimedia Retrieval Markup Language +Comment[sr]=Документ у обележивачком језику за добављање мултимедије (MRML) +Comment[sr@Latn]=Dokument u obeleživačkom jeziku za dobavljanje multimedije (MRML) +Comment[sv]=Multimedia Retrieval Markup Language-dokument +Comment[ta]=பல் ஊடக திரும்பப்பெறு அடையாள மொழி ஆவணம் +Comment[tg]=Санади MRML (Multimedia Retrieval Markup Language) +Comment[th]=เอกสาร Multimedia Retrieval Markup Language +Comment[tr]=Multimedia Retrieval Markup Language Belgesi +Comment[uk]=Документ формату зберігання мультимедіа +Comment[ven]=Manwalwa a luambo lwau humbula zwa khasho nnzhi +Comment[xh]=Uxwebhu Lolwimi Lophawulo phezulu Lokufumana i Multimedia +Comment[zh_CN]=多媒体检索标记语言文档 +Comment[zh_HK]=多媒體取得標記語言文件 +Comment[zh_TW]=多媒體補償標記語言文件 +Comment[zu]=Ushicilelo Lwe-Multimedia Retrieval Markup Language +Icon=html +Type=MimeType +MimeType=text/mrml +Patterns=*.mrml;*.MRML; +X-KDE-AutoEmbed=true diff --git a/kmrml/kmrml/mrml.h b/kmrml/kmrml/mrml.h new file mode 100644 index 00000000..f8088ef6 --- /dev/null +++ b/kmrml/kmrml/mrml.h @@ -0,0 +1,84 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MRML_H +#define MRML_H + + +#include <kio/tcpslavebase.h> +#include <kurl.h> + +#include <kmrml_config.h> +#include "mrml_shared.h" + +class Mrml : public KIO::TCPSlaveBase +{ +public: + Mrml( const QCString&, const QCString& ); + ~Mrml(); + + virtual void get( const KURL& url ); + + virtual void mimetype( const KURL& url ); + +private: + QCString readAll(); + void emitData( const QCString& ); + + bool startSession( const KURL& url ); + + // helpers + inline QString sessionId() { + return metaData( MrmlShared::sessionId() ); + } + + // misc + short int port( const KURL& url ) + { + return (url.port() != 0) ? + url.port() : + m_config.settingsForHost( url.host() ).port(); + } + + static QString mrmlString( const QString& sessionId, + const QString& transactionId = QString::null ); + + static QCString loginString(); + static QCString getConfigurationString(); + static QCString getSessionsString( const QString& username, + const QString& password ); + QString user( const KURL& url ) { + return url.hasUser() ? + url.user() : m_config.defaultSettings().user; + } + QString pass( const KURL& url ) { + return url.hasPass() ? + url.pass() : m_config.defaultSettings().pass; + } + + bool checkLocalServer( const KURL& url ); + + static const int bufsize; + QString defaultUser; + QString defaultPass; + + KMrml::Config m_config; + +}; + +#endif // MRML_H diff --git a/kmrml/kmrml/mrml.protocol b/kmrml/kmrml/mrml.protocol new file mode 100644 index 00000000..c3a732eb --- /dev/null +++ b/kmrml/kmrml/mrml.protocol @@ -0,0 +1,10 @@ +[Protocol] +exec=kio_mrml +protocol=mrml +input=none +output=filesystem +reading=true +defaultMimetype=text/mrml +determineMimetypeFromExtension=false +Icon=image +DocPath=kioslave/mrml.html diff --git a/kmrml/kmrml/mrml_creator.cpp b/kmrml/kmrml/mrml_creator.cpp new file mode 100644 index 00000000..fce84e36 --- /dev/null +++ b/kmrml/kmrml/mrml_creator.cpp @@ -0,0 +1,76 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "mrml_creator.h" + +QDomElement MrmlCreator::createMrml( QDomDocument& doc, + const QString& sessionId, + const QString& transactionId ) +{ + QDomElement mrml = doc.createElement( "mrml" ); + doc.appendChild( mrml ); + mrml.setAttribute( MrmlShared::sessionId(), sessionId ); + if ( !transactionId.isNull() ) + mrml.setAttribute( MrmlShared::transactionId(), transactionId ); + + return mrml; +} + +QDomElement MrmlCreator::configureSession( QDomElement& mrml, + const KMrml::Algorithm& algo, + const QString& sessionId ) +{ + QDomDocument doc = mrml.ownerDocument(); + QDomElement config = doc.createElement( MrmlShared::configureSession() ); + mrml.appendChild( config ); + config.setAttribute( MrmlShared::sessionId(), sessionId ); + algo.toElement( config ); + + return config; +} + +QDomElement MrmlCreator::addQuery( QDomElement& mrml, int resultSize ) +{ + QDomElement query = mrml.ownerDocument().createElement("query-step"); + mrml.appendChild( query ); + // query.setAttribute( "query-step-id", "5" ); // ### + query.setAttribute( "result-size", QString::number( resultSize )); + return query; +} + +QDomElement MrmlCreator::addRelevanceList( QDomElement& query ) +{ + QDomElement elem = + query.ownerDocument().createElement("user-relevance-element-list"); + query.appendChild( elem ); + return elem; +} + +/** + * Creates a <user-relevance-element> with the given attributes set. + */ +void MrmlCreator::createRelevanceElement( QDomDocument& doc, + QDomElement& parent, + const QString& url, + Relevance relevance ) +{ + QDomElement element = doc.createElement( "user-relevance-element" ); + element.setAttribute( "image-location", url ); + element.setAttribute( "user-relevance", QString::number( relevance ) ); + parent.appendChild( element ); +} diff --git a/kmrml/kmrml/mrml_creator.h b/kmrml/kmrml/mrml_creator.h new file mode 100644 index 00000000..2cc59e7a --- /dev/null +++ b/kmrml/kmrml/mrml_creator.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MRML_CREATOR_H +#define MRML_CREATOR_H + +#include <qdom.h> + +#include <kurl.h> + +#include "mrml_elements.h" +#include "mrml_shared.h" + +namespace MrmlCreator +{ + enum Relevance { Relevant = 1, Irrelevant = -1 }; + + QDomElement createMrml( QDomDocument& doc, + const QString& sessionId, + const QString& transactionId = QString::null ); + QDomElement configureSession( QDomElement& mrml, + const KMrml::Algorithm& algo, + const QString& sessionId ); + QDomElement addQuery( QDomElement& mrml, int resultSize ); + QDomElement addRelevanceList( QDomElement& query ); + /** + * Creates a <user-relevance-element> with the given attributes set. + */ + void createRelevanceElement( QDomDocument& doc, QDomElement& parent, + const QString& url, Relevance relevance ); + +} + +#endif // MRML_CREATOR_H diff --git a/kmrml/kmrml/mrml_elements.cpp b/kmrml/kmrml/mrml_elements.cpp new file mode 100644 index 00000000..20f3d04e --- /dev/null +++ b/kmrml/kmrml/mrml_elements.cpp @@ -0,0 +1,358 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "mrml_elements.h" +#include "mrml_shared.h" + +#include <kdatastream.h> + +#include <qdom.h> + +using namespace KMrml; + +// +// MrmlElement is currently the baseclass for Algorithm and Collection. Both +// may have a single child-element <query-paradigm-list>, with a number of +// <query-paradigm> elements as children. +// + +MrmlElement::MrmlElement( const QDomElement& elem ) +{ + QValueList<QDomElement> list = + KMrml::directChildElements( elem, MrmlShared::queryParadigmList() ); + + Q_ASSERT( list.count() < 2 ); // There can be only one. + + if ( list.count() ) + m_paradigms.initFromDOM( list.first() ); +} + + +void MrmlElement::setOtherAttributes( QDomElement& elem ) const +{ + QMapConstIterator<QString,QString> it = m_attributes.begin(); + for ( ; it != m_attributes.end(); ++it ) + { + elem.setAttribute( it.key(), it.data() ); + } +} + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +AlgorithmList AlgorithmList::algorithmsForCollection( const Collection& coll ) const +{ + AlgorithmList list; + + AlgorithmList::ConstIterator it = begin(); + for ( ; it != end(); ++it ) + { + Algorithm algo = *it; + if ( algo.paradigms().matches( coll.paradigms() ) ) + { + algo.setCollectionId( coll.id() ); + list.append( algo ); + } + } + + return list; +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +Collection::Collection( const QDomElement& elem ) + : MrmlElement( elem ) +{ + QDomNamedNodeMap attrs = elem.attributes(); + for ( uint i = 0; i < attrs.length(); i++ ) + { + QDomAttr attribute = attrs.item( i ).toAttr(); + QString name = attribute.name(); + + if ( name == MrmlShared::collectionName() ) + m_name = attribute.value(); + else if ( name == MrmlShared::collectionId() ) + m_id = attribute.value(); + + else // custom attributes + m_attributes.insert( name, attribute.value() ); + } +} + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +Algorithm::Algorithm( const QDomElement& elem ) + : MrmlElement( elem ) +{ + QDomNamedNodeMap attrs = elem.attributes(); + + for ( uint i = 0; i < attrs.length(); i++ ) + { + QDomAttr attribute = attrs.item( i ).toAttr(); + QString name = attribute.name(); + + if ( name == MrmlShared::algorithmName() ) + m_name = attribute.value(); + else if ( name == MrmlShared::algorithmId() ) + m_id = attribute.value(); + else if ( name == MrmlShared::algorithmType() ) + m_type = attribute.value(); + + // not really necessary + else if ( name == MrmlShared::collectionId() ) + m_collectionId = attribute.value(); + + else // custom attributes + m_attributes.insert( name, attribute.value() ); + } + + QDomElement propsElem = firstChildElement(elem, MrmlShared::propertySheet()); + m_propertySheet.initFromDOM( propsElem ); + + qDebug("############# new algorithm: name: %s, id: %s, type: %s", m_name.latin1(), m_id.latin1(), m_type.latin1()); +} + +Algorithm Algorithm::defaultAlgorithm() +{ + Algorithm algo; + algo.m_id = "adefault"; + algo.m_type = "adefault"; // ### not in the DTD + algo.m_name = "dummy"; + + return algo; +} + +QDomElement Algorithm::toElement( QDomElement& parent ) const +{ + QDomDocument doc = parent.ownerDocument(); + QDomElement algorithm = doc.createElement( MrmlShared::algorithm() ); + parent.appendChild( algorithm ); + setOtherAttributes( algorithm ); + + if ( !m_name.isEmpty() ) + algorithm.setAttribute( MrmlShared::algorithmName(), m_name ); + if ( !m_id.isEmpty() ) + algorithm.setAttribute( MrmlShared::algorithmId(), m_id ); + if ( !m_type.isEmpty() ) + algorithm.setAttribute( MrmlShared::algorithmType(), m_type ); + + if ( !m_collectionId.isEmpty() ) + algorithm.setAttribute( MrmlShared::collectionId(), m_collectionId ); + return algorithm; +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +QueryParadigm::QueryParadigm( const QDomElement& elem ) +{ + QDomNamedNodeMap attrs = elem.attributes(); + for ( uint i = 0; i < attrs.count(); i++ ) + { + QDomAttr attr = attrs.item( i ).toAttr(); + m_attributes.insert( attr.name(), attr.value() ); + if ( attr.name() == "type" ) + m_type = attr.value(); + } +} + +bool QueryParadigm::matches( const QueryParadigm& other ) const +{ + return m_attributes.isEmpty() || other.m_attributes.isEmpty() || + equalMaps( m_attributes, other.m_attributes ); +} + +bool QueryParadigm::equalMaps( const QMap<QString,QString> m1, + const QMap<QString,QString> m2 ) +{ + if ( m1.count() != m2.count() ) + return false; + + QMapConstIterator<QString,QString> it = m1.begin(); + for ( ; it != m1.end(); ++it ) + { + QMapConstIterator<QString,QString> it2 = m2.find( it.key() ); + if ( it2 == m2.end() || it.data() != it2.data() ) + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +void QueryParadigmList::initFromDOM( const QDomElement& elem ) +{ + clear(); + + QValueList<QDomElement> list = + KMrml::directChildElements( elem, MrmlShared::queryParadigm() ); + + QValueListConstIterator<QDomElement> it = list.begin(); + for ( ; it != list.end(); ++it ) + { + append( QueryParadigm( *it )); + } +} + +// two QueryParadigmLists match, when there is at least one pair of +// QueryParadigms that match (all attribute-value pairs are equal, or there +// are no attributes at all). +bool QueryParadigmList::matches( const QueryParadigmList& other ) const +{ + ConstIterator it = begin(); + + for ( ; it != end(); ++it ) + { + ConstIterator oit = other.begin(); + for ( ; oit != other.end(); ++oit ) + if ( (*it).matches( *oit ) ) + return true; + } + + return false; +} + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +QValueList<QDomElement> KMrml::directChildElements( const QDomElement& parent, + const QString& tagName ) +{ + QValueList<QDomElement> list; + + QDomNode node = parent.firstChild(); + while ( !node.isNull() ) + { + if ( node.isElement() && node.nodeName() == tagName ) + list.append( node.toElement() ); + + node = node.nextSibling(); + } + + return list; +} + +QDomElement KMrml::firstChildElement( const QDomElement& parent, + const QString& tagName ) +{ + QDomNode node = parent.firstChild(); + while ( !node.isNull() ) + { + if ( node.isElement() && node.nodeName() == tagName ) + return node.toElement(); + + node = node.nextSibling(); + } + + return QDomElement(); +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +QDataStream& KMrml::operator<<( QDataStream& stream, const QueryParadigm& ) +{ + + return stream; +} +QDataStream& KMrml::operator>>( QDataStream& stream, QueryParadigm& ) +{ + + return stream; +} + +QDataStream& KMrml::operator<<( QDataStream& stream, const QueryParadigmList& ) +{ + + return stream; +} +QDataStream& KMrml::operator>>( QDataStream& stream, QueryParadigmList& ) +{ + + return stream; +} + +QDataStream& KMrml::operator<<( QDataStream& stream, const MrmlElement& ) +{ + + return stream; +} +QDataStream& KMrml::operator>>( QDataStream& stream, MrmlElement& ) +{ + + return stream; +} + +QDataStream& KMrml::operator<<( QDataStream& stream, const Algorithm& ) +{ + + return stream; +} +QDataStream& KMrml::operator>>( QDataStream& stream, Algorithm& ) +{ + + return stream; +} + +QDataStream& KMrml::operator<<( QDataStream& stream, const Collection& ) +{ + + return stream; +} +QDataStream& KMrml::operator>>( QDataStream& stream, Collection& ) +{ + return stream; +} + +template <class t> QDataStream& KMrml::operator<<( QDataStream& stream, + const MrmlElementList<t>& ) +{ + + return stream; +} +template <class t> QDataStream& KMrml::operator>>( QDataStream& stream, + MrmlElementList<t>& ) +{ + + return stream; +} + +QDataStream& KMrml::operator<<( QDataStream& stream, const AlgorithmList& ) +{ + + return stream; +} +QDataStream& KMrml::operator>>( QDataStream& stream, AlgorithmList& ) +{ + + return stream; +} + diff --git a/kmrml/kmrml/mrml_elements.h b/kmrml/kmrml/mrml_elements.h new file mode 100644 index 00000000..09d2a4a8 --- /dev/null +++ b/kmrml/kmrml/mrml_elements.h @@ -0,0 +1,255 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MRML_ELEMENTS_H +#define MRML_ELEMENTS_H + +#include <qdom.h> +#include <qmap.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include "mrml_shared.h" +#include "propertysheet.h" + +#include <assert.h> + +namespace KMrml +{ + class PropertySheet; + + class QueryParadigm + { + public: + QueryParadigm() {} + QueryParadigm( const QDomElement& elem ); + bool matches( const QueryParadigm& other ) const; + QString type() const { return m_type; } + +// bool operator== ( const QueryParadigm& p1, const QueryParadigm& p2 ) + + private: + QString m_type; + QMap<QString,QString> m_attributes; + + static bool equalMaps( const QMap<QString,QString>, + const QMap<QString,QString> ); + }; + + class QueryParadigmList : protected QValueList<QueryParadigm> + { + public: + typedef QValueListIterator<QueryParadigm> Iterator; + typedef QValueListConstIterator<QueryParadigm> ConstIterator; + + void initFromDOM( const QDomElement& elem ); + bool matches( const QueryParadigmList& other ) const; + }; + + class MrmlElement + { + public: + MrmlElement() {} + MrmlElement( const QDomElement& elem ); + virtual ~MrmlElement() {} + + QString id() const { return m_id; } + QString name() const { return m_name; } + QString attribute( const QString& name ) const { return m_attributes[ name ]; } + QueryParadigmList paradigms() const { return m_paradigms; } + + + QMapConstIterator<QString,QString> attributeIterator() const { + return m_attributes.begin(); + } + QMapConstIterator<QString,QString> end() const { return m_attributes.end(); } + + bool isValid() const { return !m_name.isNull() && !m_id.isNull(); } + + protected: + QString m_id; + QString m_name; + QueryParadigmList m_paradigms; + QMap<QString,QString> m_attributes; + + void setOtherAttributes( QDomElement& elem ) const; + }; + + class Algorithm : public MrmlElement + { + public: + Algorithm() { m_collectionId = "adefault"; } + Algorithm( const QDomElement& elem ); + QString type() const { return m_type; } + + QString collectionId() const + { + return m_collectionId; + } + void setCollectionId( const QString& id ) + { + m_collectionId = id; + } + + QDomElement toElement( QDomElement& parent ) const; + const PropertySheet& propertySheet() const; + + static Algorithm defaultAlgorithm(); + + private: + QString m_type; + PropertySheet m_propertySheet; + + QString m_collectionId; + }; + + class Collection : public MrmlElement + { + public: + Collection() {} + Collection( const QDomElement& elem ); + }; + + template <class t> class MrmlElementList : public QValueList<t> + { + public: + typedef QValueListIterator<t> Iterator; + typedef QValueListConstIterator<t> ConstIterator; + + /** + * Creates an invalid element. + */ + MrmlElementList( const QString& tagName ) : + QValueList<t>(), + m_tagName( tagName ) {} + MrmlElementList( const QDomElement& elem, const QString& tagName ) : + QValueList<t>(), + m_tagName( tagName ) + { + initFromDOM( elem ); + } + virtual ~MrmlElementList() {}; + + void initFromDOM( const QDomElement& elem ) + { + assert( !m_tagName.isEmpty() ); + + QValueList<t>::clear(); + + QDomNodeList list = elem.elementsByTagName( m_tagName ); + for ( uint i = 0; i < list.length(); i++ ) + { + QDomElement elem = list.item( i ).toElement(); + t item( elem ); + if ( item.isValid() ) + append( item ); + } + } + + t findByName( const QString& name ) const + { + QValueListConstIterator<t> it = QValueList<t>::begin(); + for ( ; it != QValueList<t>::end(); ++it ) + { + if ( (*it).name() == name ) + return *it; + } + + return t(); + } + + t findById( const QString& id ) const + { + QValueListConstIterator<t> it = QValueList<t>::begin(); + for ( ; it != QValueList<t>::end(); ++it ) + { + if ( (*it).id() == id ) + return *it; + } + + return MrmlElement(); + } + + QStringList itemNames() const { + QStringList list; + QValueListConstIterator<t> it = QValueList<t>::begin(); + for ( ; it != QValueList<t>::end(); ++it ) + list.append( (*it).name() ); + + return list; + } + + void setItemName( const QString& tagName ) { m_tagName = tagName; } + QString tagName() const { return m_tagName; } + + private: + QString m_tagName; + MrmlElementList(); + }; + + class AlgorithmList : public MrmlElementList<Algorithm> + { + public: + AlgorithmList() : + MrmlElementList<Algorithm>( MrmlShared::algorithm() ) + {} + + AlgorithmList algorithmsForCollection( const Collection& coll ) const; + }; + + class CollectionList : public MrmlElementList<Collection> + { + public: + CollectionList() : + MrmlElementList<Collection>( MrmlShared::collection() ) + {} + }; + + + QValueList<QDomElement> directChildElements( const QDomElement& parent, + const QString& tagName); + QDomElement firstChildElement( const QDomElement& parent, + const QString& tagName ); + + + QDataStream& operator<<( QDataStream& stream, const QueryParadigm& ); + QDataStream& operator>>( QDataStream& stream, QueryParadigm& ); + + QDataStream& operator<<( QDataStream& stream, const QueryParadigmList& ); + QDataStream& operator>>( QDataStream& stream, QueryParadigmList& ); + + QDataStream& operator<<( QDataStream& stream, const MrmlElement& ); + QDataStream& operator>>( QDataStream& stream, MrmlElement& ); + + QDataStream& operator<<( QDataStream& stream, const Algorithm& ); + QDataStream& operator>>( QDataStream& stream, Algorithm& ); + + QDataStream& operator<<( QDataStream& stream, const Collection& ); + QDataStream& operator>>( QDataStream& stream, Collection& ); + + template <class t> QDataStream& operator<<( QDataStream&, + const MrmlElementList<t>& ); + template <class t> QDataStream& operator>>( QDataStream&, + MrmlElementList<t>& ); + + QDataStream& operator<<( QDataStream&, const AlgorithmList& ); + QDataStream& operator>>( QDataStream&, AlgorithmList& ); + +} + +#endif // MRML_ELEMENTS_H diff --git a/kmrml/kmrml/mrml_part.cpp b/kmrml/kmrml/mrml_part.cpp new file mode 100644 index 00000000..4d3f65e6 --- /dev/null +++ b/kmrml/kmrml/mrml_part.cpp @@ -0,0 +1,857 @@ +/* This file is part of the KDE project + Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qcheckbox.h> +#include <qcursor.h> +#include <qdir.h> +#include <qfile.h> +#include <qgrid.h> +#include <qhgroupbox.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qtooltip.h> +#include <qvbox.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kdatastream.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kio/job.h> +#include <kio/jobclasses.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprotocolinfo.h> +#include <kparts/genericfactory.h> +#include <ktempfile.h> + +#include <mrml_utils.h> + +#include "algorithmdialog.h" +#include "browser.h" +#include "collectioncombo.h" +#include "mrml_creator.h" +#include "mrml_elements.h" +#include "mrml_shared.h" +#include "mrml_view.h" +#include "mrml_part.h" +#include "version.h" + +using namespace KMrml; + +extern "C" +{ + void * init_libkmrmlpart() { + return new KMrml::PartFactory(); + } +} + +KInstance * PartFactory::s_instance = 0L; + +PartFactory::PartFactory() + : KParts::Factory() +{ + MrmlShared::ref(); +} + +PartFactory::~PartFactory() +{ + MrmlShared::deref(); + delete s_instance; + s_instance = 0L; +} + +KInstance * PartFactory::instance() +{ + if ( !s_instance ) { + s_instance = new KInstance( "kmrml" ); + KGlobal::locale()->insertCatalogue( "kmrml" ); + } + return s_instance; +} + +KParts::Part * PartFactory::createPartObject( QWidget *parentWidget, + const char *widgetName, + QObject *parent, + const char *name, + const char *, + const QStringList& args ) +{ + return new MrmlPart( parentWidget, widgetName, parent, name, args ); +} + + +// can't use this due to MrmlShared ref-counting +// typedef KParts::GenericFactory<KMrml::MrmlPart> PartFactory; +// K_EXPORT_COMPONENT_FACTORY( mrmlpart, PartFactory ) + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +uint MrmlPart::s_sessionId = 0; + +MrmlPart::MrmlPart( QWidget *parentWidget, const char * /* widgetName */, + QObject *parent, const char *name, + const QStringList& /* args */ ) + : KParts::ReadOnlyPart( parent, name ), + m_job( 0L ), + m_status( NeedCollection ) +{ + m_sessionId = QString::number( s_sessionId++ ).prepend("kmrml_"); + + setName( "MRML Part" ); + m_browser = new Browser( this, "mrml browserextension"); + setInstance( PartFactory::instance(), true ); // do load plugins :) + KConfig *config = PartFactory::instance()->config(); + config->setGroup("MRML Settings"); + + QVBox *box = new QVBox( parentWidget, "main mrml box" ); + m_view = new MrmlView( box, "MrmlView" ); + connect( m_view, SIGNAL( activated( const KURL&, ButtonState )), + this, SLOT( slotActivated( const KURL&, ButtonState ))); + connect( m_view, SIGNAL( onItem( const KURL& )), + this, SLOT( slotSetStatusBar( const KURL& ))); + + m_panel = new QHGroupBox( box, "buttons box" ); + + QGrid *comboGrid = new QGrid( 2, m_panel, "combo grid" ); + comboGrid->setSpacing( KDialog::spacingHint() ); + + (void) new QLabel( i18n("Server to query:"), comboGrid ); + + m_hostCombo = new KComboBox( false, comboGrid, "host combo" ); + initHostCombo(); + connect( m_hostCombo, SIGNAL( activated( const QString& ) ), + SLOT( slotHostComboActivated( const QString& ))); + + (void) new QLabel( i18n("Search in collection:"), comboGrid ); + m_collectionCombo = new CollectionCombo( comboGrid, "collection-combo" ); + // will be re-set in initCollections(), but we need to set it here to + // prevent crashes when the connection to the server fails + m_collectionCombo->setCollections( &m_collections ); + + m_algoButton = new QPushButton( QString::null, m_panel ); + m_algoButton->setPixmap( SmallIcon("configure") ); + m_algoButton->setFixedSize( m_algoButton->sizeHint() ); + connect( m_algoButton, SIGNAL( clicked() ), + SLOT( slotConfigureAlgorithm() )); + QToolTip::add( m_algoButton, i18n("Configure algorithm") ); + + QWidget *spacer = new QWidget( m_panel ); + spacer->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::Minimum ) ); + + int resultSize = config->readNumEntry( "Result-size", 20 ); + m_resultSizeInput = new KIntNumInput( resultSize, m_panel ); + m_resultSizeInput->setRange( 1, 100 ); + m_resultSizeInput->setLabel( i18n("Maximum result images:") ); + + QVBox *tmp = new QVBox( m_panel ); + m_random = new QCheckBox( i18n("Random search"), tmp ); + + m_startButton = new QPushButton( QString::null, tmp ); + connect( m_startButton, SIGNAL( clicked() ), SLOT( slotStartClicked() )); + setStatus( NeedCollection ); + + setWidget( box ); + + // setXMLFile( "mrml_part.rc" ); + + slotSetStatusBar( QString::null ); + + enableServerDependentWidgets( false ); +} + +MrmlPart::~MrmlPart() +{ + closeURL(); +} + +void MrmlPart::enableServerDependentWidgets( bool enable ) +{ + m_collectionCombo->setEnabled( enable ); + m_algoButton->setEnabled( enable && false ); // ### re-enable!!! +} + +void MrmlPart::initCollections( const QDomElement& elem ) +{ + m_collections.initFromDOM( elem ); + + m_collectionCombo->setCollections( &m_collections ); + enableServerDependentWidgets( m_collectionCombo->count() > 0 ); + + if ( m_collectionCombo->count() == 0 ) + { + KMessageBox::information( widget(), + i18n("There is no image collection available\n" + "at %1.\n"), i18n("No Image Collection")); + setStatus( NeedCollection ); + } + else + m_collectionCombo->updateGeometry(); // adjust the entire grid +} + +void MrmlPart::initAlgorithms( const QDomElement& elem ) +{ + m_algorithms.initFromDOM( elem ); +} + +// this is where we start! +bool MrmlPart::openURL( const KURL& url ) +{ + closeURL(); + + if ( url.protocol() != "mrml" || !url.isValid() ) { + qWarning("MrmlPart::openURL: cannot handle url: %s", url.prettyURL().latin1()); + return false; // what to do with that? + } + + m_url = url; + QString host = url.host().isEmpty() ? + QString::fromLatin1("localhost") : url.host(); + + m_hostCombo->setCurrentItem( host ); + + // urls we need to download before starting the query + KURL::List downloadList; + + m_queryList.clear(); + QString param = url.queryItem( "relevant" ); + QStringList list = QStringList::split( ';', param ); + + // we can only search by example on localhost + if ( host != "localhost" ) + { + if ( !list.isEmpty() ) + KMessageBox::sorry( m_view, + i18n("You can only search by example images " + "on a local indexing server."), + i18n("Only Local Servers Possible") ); + } + + else // localhost query + { + for( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + { + KURL u; + if ( (*it).at(0) == '/' ) + u.setPath( *it ); + else + u = *it; + + if ( u.isValid() ) + { + if ( u.isLocalFile() ) + m_queryList.append( u ); + else + downloadList.append( u ); + } + } + + + // ### we need a real solution for this! + // gift refuses to start when no config file is available. + if ( !QFile::exists( m_config.mrmldDataDir() + "/gift-config.mrml" ) ) + { + if ( KMessageBox::questionYesNo(0L, + i18n("There are no indexable folders " + "specified. Do you want to configure them " + "now?"), + i18n("Configuration Missing"), + i18n("Configure"), + i18n("Do Not Configure"), + "kmrml_ask_configure_gift" ) + == KMessageBox::Yes ) + { + KApplication::kdeinitExec( "kcmshell", + QString::fromLatin1("kcmkmrml")); + setStatus( NeedCollection ); + return false; + } + } + } + + + if ( !downloadList.isEmpty() ) + downloadReferenceFiles( downloadList ); + else + contactServer( m_url ); + + return true; +} + +void MrmlPart::contactServer( const KURL& url ) +{ + m_job = transferJob( url ); + + m_job->addMetaData( MrmlShared::kio_task(), MrmlShared::kio_initialize() ); + + QString host = url.host().isEmpty() ? + QString::fromLatin1("localhost") : url.host(); + + slotSetStatusBar( i18n("Connecting to indexing server at %1...").arg( host )); +} + +// +// schedules a download all urls of downloadList (all remote and wellformed) +// No other downloads are running (closeURL() has been called before) +// +void MrmlPart::downloadReferenceFiles( const KURL::List& downloadList ) +{ + assert( m_downloadJobs.isEmpty() ); + + KURL::List::ConstIterator it = downloadList.begin(); + for ( ; it != downloadList.end(); it++ ) + { + QString extension; + int index = (*it).fileName().findRev( '.' ); + if ( index != -1 ) + extension = (*it).fileName().mid( index ); + + KTempFile tmpFile( QString::null, extension ); + if ( tmpFile.status() != 0 ) + { + kdWarning() << "Can't create temporary file, skipping: " << *it << endl; + + continue; + } + + m_tempFiles.append( tmpFile.name() ); + KURL destURL; + destURL.setPath( tmpFile.name() ); + + KIO::FileCopyJob *job = KIO::file_copy( *it, destURL, -1, + true /* overwrite tmpfile */ ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotDownloadResult( KIO::Job * ) )); + m_downloadJobs.append( job ); + // ### should this be only called for one job? + emit started( job ); + } + + if ( !m_downloadJobs.isEmpty() ) + slotSetStatusBar( i18n("Downloading reference files...") ); + else // probably never happens + contactServer( m_url ); +} + +bool MrmlPart::closeURL() +{ + m_view->stopDownloads(); + m_view->clear(); + + QPtrListIterator<KIO::FileCopyJob> it( m_downloadJobs ); + for ( ; it.current(); ++it ) + it.current()->kill(); + m_downloadJobs.clear(); + + QStringList::Iterator tit = m_tempFiles.begin(); + for ( ; tit != m_tempFiles.end(); ++tit ) + QFile::remove( *tit ); + m_tempFiles.clear(); + + if ( m_job ) { + m_job->kill(); + m_job = 0L; + } + + setStatus( NeedCollection ); + + return true; +} + +KIO::TransferJob * MrmlPart::transferJob( const KURL& url ) +{ + KIO::TransferJob *job = KIO::get( url, true, false ); // reload, no gui + job->setAutoErrorHandlingEnabled( true, m_view ); + connect( job, SIGNAL( result( KIO::Job * )), + SLOT( slotResult( KIO::Job * ))); + connect( job, SIGNAL( data( KIO::Job *, const QByteArray& )), + SLOT( slotData( KIO::Job *, const QByteArray& ))); + +// ### +// connect( job, SIGNAL( infoMessage( KIO::Job *, const QString& )), +// SLOT( slotResult( KIO::Job *, const QString& ))); + + job->setWindow( widget() ); + if ( !m_sessionId.isEmpty() ) + job->addMetaData( MrmlShared::sessionId(), m_sessionId ); + + emit started( job ); + emit setWindowCaption( url.prettyURL() ); + setStatus( InProgress ); + + return job; +} + +void MrmlPart::slotResult( KIO::Job *job ) +{ + if ( job == m_job ) + m_job = 0L; + + slotSetStatusBar( QString::null ); + + if ( !job->error() ) + emit completed(); + else { + emit canceled( job->errorString() ); +// qDebug("*** canceled: error: %s", job->errorString().latin1()); + } + + + bool auto_random = m_view->isEmpty() && m_queryList.isEmpty(); + m_random->setChecked( auto_random ); + m_random->setEnabled( !auto_random ); + setStatus( job->error() ? NeedCollection : CanSearch ); + + if ( !job->error() && !m_queryList.isEmpty() ) { + // we have a connection and we got a list of relevant URLs to query for + // (via the URL) + + createQuery( &m_queryList ); + m_queryList.clear(); + } +} + +// ### when user cancels download, we crash :( +void MrmlPart::slotDownloadResult( KIO::Job *job ) +{ + assert( job->inherits( "KIO::FileCopyJob" ) ); + KIO::FileCopyJob *copyJob = static_cast<KIO::FileCopyJob*>( job ); + + if ( !copyJob->error() ) + m_queryList.append( copyJob->destURL() ); + + m_downloadJobs.removeRef( copyJob ); + + if ( m_downloadJobs.isEmpty() ) // finally, we can start the query! + { + if ( m_queryList.isEmpty() ) // rather unlikely, but could happen ;) + { + kdWarning() << "Couldn't download the reference files. Will start a random search now" << endl; + } + + contactServer( m_url ); + } +} + +// mrml-document in the bytearray +void MrmlPart::slotData( KIO::Job *, const QByteArray& data ) +{ + if ( data.isEmpty() ) + return; + + QDomDocument doc; + doc.setContent( data ); + + if ( !doc.isNull() ) + parseMrml( doc ); +} + +void MrmlPart::parseMrml( QDomDocument& doc ) +{ + QDomNode mrml = doc.documentElement(); // root element + if ( !mrml.isNull() ) { + QDomNode child = mrml.firstChild(); + for ( ; !child.isNull(); child = child.nextSibling() ) { +// qDebug("**** HERE %s", child.nodeName().latin1()); + if ( child.isElement() ) { + QDomElement elem = child.toElement(); + + QString tagName = elem.tagName(); + + if ( tagName == "acknowledge-session-op" ) + m_sessionId = elem.attribute( MrmlShared::sessionId() ); + + else if ( tagName == MrmlShared::algorithmList() ) { + initAlgorithms( elem ); + } + + else if ( tagName == MrmlShared::collectionList() ) { + initCollections( elem ); + } + + else if ( tagName == "error" ) { + KMessageBox::information( widget(), + i18n("Server returned error:\n%1\n") + .arg( elem.attribute( "message" )), + i18n("Server Error") ); + } + + else if ( tagName == "query-result" ) { + m_view->clear(); + parseQueryResult( elem ); + } + + + } // child.isElement() + } + } // !mrml.isNull() +} + +void MrmlPart::parseQueryResult( QDomElement& queryResult ) +{ + QDomNode child = queryResult.firstChild(); + for ( ; !child.isNull(); child = child.nextSibling() ) { + if ( child.isElement() ) { + QDomElement elem = child.toElement(); + QString tagName = elem.tagName(); + + if ( tagName == "query-result-element-list" ) { + QValueList<QDomElement> list = + KMrml::directChildElements( elem, "query-result-element" ); + + QValueListConstIterator<QDomElement> it = list.begin(); + for ( ; it != list.end(); ++it ) + { + QDomNamedNodeMap a = (*it).attributes(); + m_view->addItem( KURL( (*it).attribute("image-location" ) ), + KURL( (*it).attribute("thumbnail-location" ) ), + (*it).attribute("calculated-similarity")); + + } + } + + else if ( tagName == "query-result" ) + parseQueryResult( elem ); + } + } +} + +// creates/stops the query when the Start/Stop button was pressed +void MrmlPart::slotStartClicked() +{ + if ( m_status == InProgress ) + { + closeURL(); + m_startButton->setText( i18n("&Search" ) ); + return; + } + + // we need to reconnect, if the initial openURL() didn't work due to + // the gift not being available. + if ( m_status == NeedCollection ) + { + openURL( m_url ); + return; + } + + // cut off an eventual query and reference from the url, when the user + // performs a real query (otherwise restoreState() would restore and + // re-do the query from the URL + m_url.setRef( QString::null ); + m_url.setQuery( QString::null ); + + createQuery(); + m_browser->openURLNotify(); +} + +// +// relevantItems is 0L when called from slotStartClicked() and set to a +// non-empty list when called initially, from the commandline. +// +void MrmlPart::createQuery( const KURL::List * relevantItems ) +{ + if ( relevantItems && relevantItems->isEmpty() ) + return; + + QDomDocument doc( "mrml" ); + QDomElement mrml = MrmlCreator::createMrml( doc, + sessionId(), + transactionId() ); + + Collection coll = currentCollection(); +// qDebug("** collection: name: %s, id: %s, valid: %i", coll.name().latin1(), coll.id().latin1(), coll.isValid()); + Algorithm algo = firstAlgorithmForCollection( coll ); +// qDebug("** algorithm: name: %s, id: %s, valid: %i, collection-id: %s", algo.name().latin1(), algo.id().latin1(), algo.isValid(), algo.collectionId().latin1()); + + if ( algo.isValid() ) + { + MrmlCreator::configureSession( mrml, algo, sessionId() ); + } + + QDomElement query = MrmlCreator::addQuery( mrml, + m_resultSizeInput->value() ); + if ( algo.isValid() ) + query.setAttribute( MrmlShared::algorithmId(), algo.id() ); + + // ### result-cutoff, query-type? + + // start-up with/without urls on the commandline via mrmlsearch + if ( relevantItems ) + { + QDomElement elem = MrmlCreator::addRelevanceList( query ); + KURL::List::ConstIterator it = relevantItems->begin(); + for ( ; it != relevantItems->end(); ++it ) + MrmlCreator::createRelevanceElement( doc, elem, (*it).url(), + MrmlCreator::Relevant ); + } + + // get relevant items from the view? Only do this when relevantItems is 0L + else if ( !m_random->isChecked() ) + { + QDomElement relevants = MrmlCreator::addRelevanceList( query ); + m_view->addRelevanceToQuery( doc, relevants ); + } + + performQuery( doc ); +} + +Collection MrmlPart::currentCollection() const +{ + return m_collectionCombo->current(); +} + +Algorithm MrmlPart::firstAlgorithmForCollection( const Collection& coll ) const +{ + if ( !m_algorithms.isEmpty() ) + { + AlgorithmList::ConstIterator it = m_algorithms.begin(); + for ( ; it != m_algorithms.end(); ++it ) + { + Algorithm algo = *it; + if ( algo.paradigms().matches( coll.paradigms() ) ) + { + algo.setCollectionId( coll.id() ); + return algo; + } + } + } + + qDebug("#################### -> ADEFAULT!"); + Algorithm algo = Algorithm::defaultAlgorithm(); + algo.setCollectionId( coll.id() ); + return algo; +} + +// emits the given QDomDocument for eventual plugins, checks after that +// if there are any relevance elements. If there are none, random search is +// implied and performed. +// finally, the search is actually started +void MrmlPart::performQuery( QDomDocument& doc ) +{ + QDomElement mrml = doc.documentElement(); + + emit aboutToStartQuery( doc ); // let plugins play with it :) + + // no items available? All "neutral"? -> random search + + QDomElement queryStep = KMrml::firstChildElement( mrml, "query-step" ); + bool randomSearch = false; + + if ( !queryStep.isNull() ) + { + QDomElement relevanceList = + KMrml::firstChildElement(queryStep, "user-relevance-element-list"); + QValueList<QDomElement> relevanceElements = + KMrml::directChildElements( relevanceList, + "user-relevance-element" ); + + randomSearch = relevanceElements.isEmpty(); + + if ( randomSearch ) + { + m_random->setChecked( true ); + m_random->setEnabled( false ); + queryStep.setAttribute("query-type", "at-random"); + + // remove user-relevance-element-list element for random search + relevanceList.parentNode().removeChild( relevanceList ); + } + } + else + { + KMessageBox::error( m_view, i18n("Error formulating the query. The " + "\"query-step\" element is missing."), + i18n("Query Error") ); + } + + m_job = transferJob( url() ); + slotSetStatusBar( randomSearch ? i18n("Random search...") : + i18n("Searching...") ); + m_job->addMetaData( MrmlShared::kio_task(), MrmlShared::kio_startQuery() ); + qDebug("\n\nSending XML:\n%s", doc.toString().latin1()); + m_job->addMetaData( MrmlShared::mrml_data(), doc.toString() ); +} + +void MrmlPart::slotSetStatusBar( const QString& text ) +{ + if ( text.isEmpty() ) + emit setStatusBarText( i18n("Ready.") ); + else + emit setStatusBarText( text ); +} + +void MrmlPart::slotActivated( const KURL& url, ButtonState button ) +{ + if ( button == LeftButton ) + emit m_browser->openURLRequest( url ); + else if ( button == MidButton ) + emit m_browser->createNewWindow( url ); + else if ( button == RightButton ) { + // enableExtensionActions( url, true ); // for now + emit m_browser->popupMenu( QCursor::pos(), url, QString::null ); + // enableExtensionActions( url, false ); + } +} + +void MrmlPart::enableExtensionActions( const KURL& url, bool enable ) +{ + bool del = KProtocolInfo::supportsDeleting( url ); + emit m_browser->enableAction( "copy", enable ); + emit m_browser->enableAction( "trash", del ); + emit m_browser->enableAction( "del", del ); + emit m_browser->enableAction( "shred", url.isLocalFile() ); + emit m_browser->enableAction( "properties", enable ); + // emit m_browser->enableAction( "print", enable ); // ### later +} + + +// only implemented because it's abstract in the baseclass +bool MrmlPart::openFile() +{ + return false; +} + +void MrmlPart::slotConfigureAlgorithm() +{ + m_algoButton->setEnabled( false ); + + m_algoConfig = new AlgorithmDialog( m_algorithms, m_collections, + currentCollection(), + m_view, "algorithm configuration" ); + connect( m_algoConfig, SIGNAL( applyClicked() ), + SLOT( slotApplyAlgoConfig() )); + connect( m_algoConfig, SIGNAL( finished() ), + SLOT( slotAlgoConfigFinished() )); + + m_algoConfig->show(); +} + +void MrmlPart::slotApplyAlgoConfig() +{ + // ### +} + +void MrmlPart::slotAlgoConfigFinished() +{ + if ( m_algoConfig->result() == QDialog::Accepted ) + slotApplyAlgoConfig(); + + m_algoButton->setEnabled( true ); + m_algoConfig->deleteLater(); + m_algoConfig = 0L; +} + +void MrmlPart::initHostCombo() +{ + m_hostCombo->clear(); + m_hostCombo->insertStringList( m_config.hosts() ); +} + +void MrmlPart::slotHostComboActivated( const QString& host ) +{ + ServerSettings settings = m_config.settingsForHost( host ); + openURL( settings.getUrl() ); +} + +void MrmlPart::setStatus( Status status ) +{ + switch ( status ) + { + case NeedCollection: + m_startButton->setText( i18n("&Connect") ); + break; + case CanSearch: + m_startButton->setText( i18n("&Search") ); + break; + case InProgress: + m_startButton->setText( i18n("Sto&p") ); + break; + }; + + m_status = status; +} + + +void MrmlPart::saveState( QDataStream& stream ) +{ + stream << url(); + stream << m_sessionId; + stream << m_queryList; +// stream << m_algorithms; +// stream << m_collections; + + stream << m_resultSizeInput->value(); + stream << *m_collectionCombo; + + m_view->saveState( stream ); +} + +void MrmlPart::restoreState( QDataStream& stream ) +{ + KURL url; + stream >> url; + + stream >> m_sessionId; + stream >> m_queryList; +// stream >> m_algorithms; +// stream >> m_collections; + + int resultSize; + stream >> resultSize; + m_resultSizeInput->setValue( resultSize ); + stream >> *m_collectionCombo; + + m_view->restoreState( stream ); + +// openURL( url ); + m_url = url; +} + +KAboutData * MrmlPart::createAboutData() +{ + KAboutData *data = new KAboutData( + "kmrml", + I18N_NOOP("MRML Client for KDE"), + KMRML_VERSION, + I18N_NOOP("A tool to search for images by their content"), + KAboutData::License_GPL, + I18N_NOOP("(c) 2001-2002, Carsten Pfeiffer"), + 0, + I18N_NOOP("http://devel-home.kde.org/~pfeiffer/kmrml/") ); + + data->addAuthor( "Carsten Pfeiffer", + I18N_NOOP("Developer, Maintainer"), + "pfeiffer@kde.org" ); + data->addCredit( "Wolfgang Mller", + I18N_NOOP("Developer of the GIFT, Helping Hand") ); + + return data; +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +#include "mrml_part.moc" diff --git a/kmrml/kmrml/mrml_part.desktop b/kmrml/kmrml/mrml_part.desktop new file mode 100644 index 00000000..90017794 --- /dev/null +++ b/kmrml/kmrml/mrml_part.desktop @@ -0,0 +1,67 @@ +[Desktop Entry] +Type=Service +Exec=blahfoo +Name=MRML View +Name[ar]=برنامج MRML View +Name[br]=Gwel MRML +Name[ca]=Vista MRML +Name[cs]=MRML pohled +Name[cy]=Gwelydd MRML +Name[da]=MRML-visning +Name[de]=MRML-Ansicht +Name[el]=Προβολή MRML +Name[eo]=MRML-Rigardo +Name[es]=Vista de MRML +Name[et]=MRML vaade +Name[eu]=MRML ikuspegia +Name[fa]=نمای MRML +Name[fi]=MRML-näkymä +Name[fr]=Affichage MRML +Name[ga]=Amharc MRML +Name[gl]=Visor MRML +Name[he]=תצוגת MRML +Name[hi]=MRML दृश्य +Name[hu]=MRML-nézet +Name[is]=MRML sýn +Name[it]=Visione MRML +Name[ja]=MRML ビュー +Name[kk]=MRML файлдарды қарау +Name[km]=ទិដ្ឋភាព MRML +Name[lt]=MRML peržiūra +Name[ms]=Paparan MRML +Name[nds]=MRML-Ansicht +Name[ne]=MRML दृश्य +Name[nl]=MRML-weergave +Name[nso]=Pono ya MRML +Name[pa]=MRML ਝਲਕ +Name[pl]=Widok MRML +Name[pt]=Janela de MRML +Name[pt_BR]=Visualização de MRML +Name[ro]=Vizualizare MRML +Name[ru]=Просмотр MRML +Name[se]=MRML-čájeheapmi +Name[sk]=Prehliadač MRML +Name[sl]=Pregledovalnik MRML +Name[sr]=MRML приказивач +Name[sr@Latn]=MRML prikazivač +Name[ta]=MRML காட்சி +Name[tg]=Намоиши MRML +Name[th]=ดู MRML +Name[tr]=MRML Görünümü +Name[uk]=Перегляд MRML +Name[ven]=Mbonalelo ya MRML +Name[xh]=MRML Imbono +Name[zh_CN]=MRML 查看器 +Name[zh_HK]=MRML 檢視 +Name[zh_TW]=MRML 檢視器 +Name[zu]=Umbukiso we-MRML +MimeType=text/mrml +ServiceTypes=KParts/ReadOnlyPart +X-KDE-Library=libkmrmlpart +#X-KDE-BrowserView-AllowAsDefault=true +#X-KDE-BrowserView-HideFromMenus=true +#X-KDE-BrowserView-Args=IconView +#X-KDE-BrowserView-ModeProperty=viewMode +#X-KDE-BrowserView-ModePropertyValue=IconView +Icon=view_icon +InitialPreference=10 diff --git a/kmrml/kmrml/mrml_part.h b/kmrml/kmrml/mrml_part.h new file mode 100644 index 00000000..110d290a --- /dev/null +++ b/kmrml/kmrml/mrml_part.h @@ -0,0 +1,175 @@ +/* This file is part of the KDE project + Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MRMLPART_H +#define MRMLPART_H + +#include <qcstring.h> +#include <qstringlist.h> + +#include <kurl.h> +#include <kparts/factory.h> +#include <kparts/part.h> + +#include <kmrml_config.h> + +#include "mrml_elements.h" + +class QCheckBox; +class QHGroupBox; +class QPushButton; + +class KAboutData; +class KComboBox; +class KIntNumInput; + +namespace KIO { + class FileCopyJob; + class TransferJob; +} + +namespace KMrml +{ + +class AlgorithmDialog; +class Browser; +class CollectionCombo; +class MrmlView; + +class MrmlPart : public KParts::ReadOnlyPart +{ + Q_OBJECT + +public: + enum Status { NeedCollection, CanSearch, InProgress }; + + MrmlPart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, const QStringList& args ); + ~MrmlPart(); + + QString sessionId() const { return m_sessionId; } + QString transactionId() const { return QString::null; } // ### + + void saveState( QDataStream& stream ); + void restoreState( QDataStream& stream ); + + static KAboutData *createAboutData(); + +public slots: + virtual bool openURL( const KURL& ); + virtual bool closeURL(); + + void slotActivated( const KURL& url, ButtonState ); + +protected: + virtual bool openFile(); + Algorithm firstAlgorithmForCollection( const Collection& coll ) const; + Collection currentCollection() const; + +signals: + /** + * allow plugins to extend the query + */ + void aboutToStartQuery( QDomDocument& ); + +private slots: + void slotStartClicked(); + void slotSetStatusBar( const QString& ); + void slotSetStatusBar( const KURL& url ) { slotSetStatusBar( url.prettyURL() ); } + void slotHostComboActivated( const QString& ); + + void slotResult( KIO::Job * ); + void slotData( KIO::Job *, const QByteArray& ); + + void slotDownloadResult( KIO::Job * ); + + void slotConfigureAlgorithm(); + void slotApplyAlgoConfig(); + void slotAlgoConfigFinished(); + +private: + void createQuery( const KURL::List * relevantItems = 0L ); + void initCollections( const QDomElement& ); + void initAlgorithms( const QDomElement& ); + void performQuery( QDomDocument& doc ); + void parseMrml( QDomDocument& doc ); + void parseQueryResult( QDomElement& ); + void enableExtensionActions( const KURL& url, bool enable ); + KIO::TransferJob * transferJob( const KURL& url ); + + void initHostCombo(); + void enableServerDependentWidgets( bool enable ); + + void setStatus( Status status ); + + void contactServer( const KURL& url ); + void downloadReferenceFiles( const KURL::List& downloadList ); + + KIO::TransferJob *m_job; + MrmlView *m_view; + Config m_config; + KIntNumInput * m_resultSizeInput; + CollectionCombo * m_collectionCombo; + QPushButton *m_algoButton; + QHGroupBox *m_panel; + QPushButton *m_startButton; + QCheckBox *m_random; + Browser *m_browser; + AlgorithmDialog *m_algoConfig; + KComboBox *m_hostCombo; + + QPtrList<KIO::FileCopyJob> m_downloadJobs; + QStringList m_tempFiles; + + QString m_sessionId; + KURL::List m_queryList; // a list of valid LOCAL (!) urls to query for + + CollectionList m_collections; + AlgorithmList m_algorithms; + + Status m_status; + static uint s_sessionId; + +}; + +class PartFactory : public KParts::Factory +{ + Q_OBJECT + +public: + PartFactory(); + ~PartFactory(); + + static KInstance * instance(); + +protected: + virtual KParts::Part * createPartObject( QWidget *parentWidget = 0, + const char *widgetName = 0, + QObject *parent = 0, + const char *name = 0, + const char *classname = "KParts::Part", + const QStringList& args = QStringList() ); + +private: + static KInstance * s_instance; + +}; + +} + +#endif // MRMLPART_H diff --git a/kmrml/kmrml/mrml_view.cpp b/kmrml/kmrml/mrml_view.cpp new file mode 100644 index 00000000..71f3c741 --- /dev/null +++ b/kmrml/kmrml/mrml_view.cpp @@ -0,0 +1,480 @@ +/* This file is part of the KDE project + Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qdom.h> +#include <qlabel.h> +#include <qpainter.h> +#include <qtimer.h> +#include <qtooltip.h> + +#include <kcursor.h> +#include <kdatastream.h> +#include <klocale.h> +#include <kcombobox.h> +#include <kmimetype.h> +#include <kurl.h> +#include <kurldrag.h> + +#include "loader.h" +#include "mrml_creator.h" +#include "mrml_view.h" + +using namespace KMrml; + +MrmlView::MrmlView( QWidget *parent, const char *name ) + : QScrollView( parent, name ) +{ + setStaticBackground( true ); + setResizePolicy( Manual ); + setHScrollBarMode( AlwaysOff ); + enableClipper( true ); // ### test this + + m_items.setAutoDelete( true ); + + connect( Loader::self(), SIGNAL( finished(const KURL&, const QByteArray&)), + SLOT( slotDownloadFinished( const KURL&, const QByteArray& ))); + + m_timer = new QTimer( this ); + connect( m_timer, SIGNAL( timeout() ), SLOT( slotLayout() )); + + // we need a pixmap to be shown when no thumbnail is available for a + // query result image + QLabel l( i18n( "No thumbnail available" ), 0L ); + l.setFixedSize( 80, 80 ); + l.setAlignment( WordBreak | AlignCenter ); +// l.setFrameStyle( QLabel::Box | QLabel::Plain ); +// l.setLineWidth( 1 ); + l.setPaletteBackgroundColor( Qt::white ); + l.setPaletteForegroundColor( Qt::black ); + m_unavailablePixmap = QPixmap::grabWidget( &l ); +} + +MrmlView::~MrmlView() +{ +} + +MrmlViewItem * MrmlView::addItem( const KURL& url, const KURL& thumbURL, + const QString& similarity ) +{ + bool ok; + double value = similarity.toDouble( &ok ); + if ( !ok || value < 0.05 ) + return 0L; + + return addItem( url, thumbURL, value ); +} + +MrmlViewItem * MrmlView::addItem( const KURL& url, const KURL& thumbURL, + double similarity ) +{ + if ( !url.isValid() ) { + qWarning( "MrmlPart: received malformed URL from query: %s", + url.prettyURL().isNull() ? "(null)" : url.prettyURL().latin1() ); + return 0L; + } + +// qDebug("** url: %s", thumbURL.url().latin1()); + + MrmlViewItem *item = new MrmlViewItem( url, thumbURL, similarity, this ); + QPixmap *pixmap = getPixmap( thumbURL ); + if ( pixmap ) + item->setPixmap( *pixmap ); + + m_items.append( item ); + + m_timer->start( 0, true ); + return item; +} + +void MrmlView::addRelevanceToQuery( QDomDocument& document, + QDomElement& parent ) +{ + QPtrListIterator<MrmlViewItem> it( m_items ); + for( ; it.current(); ++it ) { + it.current()->createRelevanceElement( document, parent ); + } +} + +void MrmlView::clear() +{ + m_items.clear(); // items are deleted and removed from scrollview + setContentsPos( 0, 0 ); +} + +QPixmap * MrmlView::getPixmap( const KURL& url ) +{ + QString u = url.url(); + QPixmap *pix = m_pixmapCache.find( u ); + if ( pix ) + return pix; + + if ( url.isLocalFile() ) { + QPixmap p; + if ( !p.load( url.path() ) ) + p = m_unavailablePixmap; + + m_pixmapCache.insert( u, p ); + return m_pixmapCache.find( u ); + } + else { // remote url, download with KIO + Loader::self()->requestDownload( url ); + } + + return 0L; +} + +void MrmlView::slotDownloadFinished( const KURL& url, const QByteArray& data ) +{ + QPtrListIterator<MrmlViewItem> it( m_items ); + for( ; it.current(); ++it ) { + MrmlViewItem *item = it.current(); + if ( item->thumbURL() == url ) + { + QPixmap p; + if ( data.isEmpty() || !p.loadFromData( data ) ) + p = m_unavailablePixmap; + + m_pixmapCache.insert( url.url(), p ); + item->setPixmap( p ); + + slotLayout(); + return; + } + } +} + +void MrmlView::stopDownloads() +{ + Loader *loader = Loader::self(); + QPtrListIterator<MrmlViewItem> it( m_items ); + for( ; it.current(); ++it ) { + MrmlViewItem *item = it.current(); + if ( !item->hasRemotePixmap() ) + loader->removeDownload( item->url() ); + } +} + +void MrmlView::slotLayout() +{ + int itemWidth = 0; + QPtrListIterator<MrmlViewItem> it( m_items ); + + for ( ; it.current(); ++it ) { + itemWidth = QMAX( itemWidth, it.current()->sizeHint().width() ); + } + + if ( itemWidth == 0 ) + return; + + + uint itemsPerRow = visibleWidth() / itemWidth; + int margin = (visibleWidth() - (itemsPerRow * itemWidth)) / 2; + int rowHeight = 0; + uint item = 0; + uint y = 5; + + // pointing to the first item of a row + QPtrListIterator<MrmlViewItem> rowIt( m_items ); + + for ( it.toFirst(); it.current(); ++it ) { + if ( item >= itemsPerRow ) { + item = 0; + y += rowHeight; + rowHeight = 0; + } + + if ( item == 0 ) + rowIt = it; + + rowHeight = QMAX( rowHeight, it.current()->sizeHint().height() ); + addChild( it.current(), margin + item * itemWidth, y ); + it.current()->show(); + + item++; + + // resize all items of the current row so they all have the same size + if ( item >= itemsPerRow || it.atLast() ) + { + for ( uint i = 0; (i < itemsPerRow && rowIt.current()); i++ ) + { + rowIt.current()->resize( itemWidth, rowHeight ); + ++rowIt; + } + } + } + + resizeContents( visibleWidth(), y + rowHeight ); +} + +void MrmlView::resizeEvent( QResizeEvent *e ) +{ + int oldW = visibleWidth(); + QScrollView::resizeEvent( e ); + + if ( visibleWidth() != oldW ) + slotLayout(); +} + +void MrmlView::saveState( QDataStream& stream ) +{ + stream << m_items.count(); + QPtrListIterator<MrmlViewItem> it( m_items ); + for( ; it.current(); ++it ) { + stream << *it.current(); + } + +} + +void MrmlView::restoreState( QDataStream& stream ) +{ + stopDownloads(); + clear(); + + int count; + stream >> count; + + KURL url, thumbURL; + double similarity; + Q_UINT32 relevance; + MrmlViewItem *item; + + + for ( int i = 0; i < count; i++ ) + { + stream >> url; + stream >> thumbURL; + stream >> similarity; + stream >> relevance; + + item = addItem( url, thumbURL, similarity ); + if ( item ) + item->setRelevance( (MrmlViewItem::Relevance) relevance ); + } +} + +QDataStream& KMrml::operator<<( QDataStream& stream, + const KMrml::MrmlViewItem& item ) +{ + return stream << item.url() + << item.thumbURL() + << item.similarity() + << static_cast<Q_UINT32>( item.relevance() ); +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +MrmlViewItem::MrmlViewItem( const KURL& url, const KURL& thumbURL, + double similarity, MrmlView *view, + const char *name ) + : QFrame( view->viewport() , name ), + m_view( view ), + m_url( url ), + m_thumbURL( thumbURL ), + similarityFullWidth( 120 ), // ### + m_hasRemotePixmap( false ) +{ + if ( m_similarity != -1 ) + m_similarity = QMAX( 0.0, QMIN( 1.0, similarity )); + setFrameStyle( Panel | Sunken ); + setMouseTracking( true ); + + m_combo = new KComboBox( this ); + QToolTip::add( m_combo, i18n("You can refine queries by giving feedback about the current result and pressing the Search button again.") ); + m_combo->insertItem( i18n("Relevant"), Relevant ); + m_combo->insertItem( i18n("Neutral"), Neutral ); + m_combo->insertItem( i18n("Irrelevant"), Irrelevant ); + m_combo->adjustSize(); + m_combo->setCurrentItem( Neutral ); + + /* + if ( similarity > -1 ) + QToolTip::add( this, QString::fromLatin1("<qt>%1<br>%1</qt>") + .arg( url ) + .arg(i18n("Similarity: %1").arg( QString::number(similarity)))); + else + QToolTip::add( this, QString::fromLatin1("<qt>%1</qt>").arg( url ) ); + */ + + setMinimumSize( 130, 130 ); // ### +} + +MrmlViewItem::~MrmlViewItem() +{ +} + +void MrmlViewItem::setPixmap( const QPixmap& pix ) +{ + if ( !m_url.isLocalFile() ) + m_hasRemotePixmap = true; + + m_pixmap = pix; + adjustSize(); + update(); +} + +void MrmlViewItem::paintEvent( QPaintEvent *e ) +{ + QFrame::paintEvent( e ); + + if ( !m_pixmap.isNull() ) { + bitBlt( this, pixmapX(), pixmapY(), + &m_pixmap, 0, 0, m_pixmap.width(), m_pixmap.height(), + CopyROP ); + } + + if ( m_similarity >= 0 ) { + QPainter p( this ); + QPen pen( colorGroup().highlight(), 1, QPen::SolidLine ); + p.setPen( pen ); + int x = margin; + int y = m_combo->y() - similarityHeight - 2; + int w = (int) (similarityFullWidth * m_similarity); + int h = similarityHeight; + p.drawRect( x, y, similarityFullWidth, h ); + p.fillRect( x, y, w, h, colorGroup().highlight() ); + } +} + +void MrmlViewItem::resizeEvent( QResizeEvent *e ) +{ + QFrame::resizeEvent( e ); + + int y = height() - m_combo->height() - margin; + m_combo->move( width()/2 - m_combo->width()/2, y ); +} + +QSize MrmlViewItem::sizeHint() const +{ + int w = QMAX( QMAX(minimumHeight(), m_combo->width()), m_pixmap.width() ); + w += 2 * margin; + + int h = m_pixmap.isNull() ? margin : margin + spacing + m_pixmap.height(); + h += (m_similarity > -1) ? similarityHeight + spacing : 0; + h += m_combo->height() + margin; + + return QSize( w, h ); +} + +void MrmlViewItem::mousePressEvent( QMouseEvent *e ) +{ + QFrame::mousePressEvent( e ); + pressedPos.setX( 0 ); + pressedPos.setY( 0 ); + + + if ( e->button() == LeftButton || e->button() == MidButton ) { + if ( hitsPixmap( e->pos() ) ) + pressedPos = e->pos(); + } + else if ( e->button() == RightButton && hitsPixmap( e->pos() ) ) + emit view()->activated( m_url, e->button() ); +} + +void MrmlViewItem::mouseMoveEvent( QMouseEvent *e ) +{ + if ( hitsPixmap( e->pos() ) ) { + if ( !ownCursor() ) { // nice hacklet :) + setCursor( KCursor::handCursor() ); + emit view()->onItem( m_url ); + } + } + else { + if ( ownCursor() ) { + unsetCursor(); + emit view()->onItem( KURL() ); + } + } + + if ( (e->state() & LeftButton) && !pressedPos.isNull() ) { + QPoint dist = e->pos() - pressedPos; + if ( dist.manhattanLength() > KGlobalSettings::dndEventDelay() ) { + // start drag here + KURL::List urls; + // ### support multiple files? + urls.append( m_url ); + KURLDrag *drag = new KURLDrag( urls, this ); + drag->setPixmap( KMimeType::pixmapForURL( m_url ) ); + drag->drag(); + } + } +} + +void MrmlViewItem::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( hitsPixmap( e->pos() )) { + QPoint dist = e->pos() - pressedPos; + if ( dist.manhattanLength() < KGlobalSettings::dndEventDelay() ) { + emit view()->activated( m_url, e->button() ); + } + } +} + +bool MrmlViewItem::hitsPixmap( const QPoint& pos ) const +{ + if ( m_pixmap.isNull() ) + return false; + + if ( pos.x() > pixmapX() && pos.x() < pixmapX() + m_pixmap.width() && + pos.y() > pixmapY() && pos.y() < pixmapY() + m_pixmap.height() ) + return true; + return false; +} + +void MrmlViewItem::createRelevanceElement( QDomDocument& document, + QDomElement& parent ) +{ + int rel = m_combo->currentItem(); + if ( rel == Neutral ) + return; + + MrmlCreator::createRelevanceElement( document, parent, m_url.url(), + (rel == Relevant) ? MrmlCreator::Relevant : MrmlCreator::Irrelevant ); +} + +MrmlViewItem::Relevance MrmlViewItem::relevance() const +{ + return (Relevance) m_combo->currentItem(); +} + +void MrmlViewItem::setRelevance( Relevance relevance ) +{ + m_combo->setCurrentItem( relevance ); +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + + +int MrmlViewItemList::compareItems( QPtrCollection::Item item1, + QPtrCollection::Item item2 ) +{ + double s1 = (static_cast<MrmlViewItem*>( item1 ))->similarity(); + double s2 = (static_cast<MrmlViewItem*>( item2 ))->similarity(); + + if ( s1 < s2 ) + return 1; + else if ( s1 > s2 ) + return -1; + else + return 0; +} + +#include "mrml_view.moc" diff --git a/kmrml/kmrml/mrml_view.h b/kmrml/kmrml/mrml_view.h new file mode 100644 index 00000000..f6c9f58c --- /dev/null +++ b/kmrml/kmrml/mrml_view.h @@ -0,0 +1,180 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MRML_VIEW_H +#define MRML_VIEW_H + +#include <qevent.h> +#include <qframe.h> +#include <qptrlist.h> +#include <qpixmap.h> +#include <qpixmapcache.h> +#include <qscrollview.h> + +class QDomDocument; +class QDomElement; +class QTimer; + +class KComboBox; + +namespace KMrml +{ + +class MrmlViewItem; + + +class MrmlViewItemList : public QPtrList<MrmlViewItem> +{ +protected: + // sort by similarity + virtual int compareItems( QPtrCollection::Item, QPtrCollection::Item ); + +}; + + +class MrmlView : public QScrollView +{ + friend class MrmlViewItem; + + Q_OBJECT + +public: + MrmlView( QWidget *parent = 0L, const char *name = 0L ); + ~MrmlView(); + + MrmlViewItem * addItem( const KURL& url, const KURL& thumbURL, + const QString& similarity ); + MrmlViewItem * addItem( const KURL& url, const KURL& thumbURL, + double similarity ); + + + void addRelevanceToQuery( QDomDocument&, QDomElement& parent ); + + void clear(); + + bool isEmpty() const { return m_items.isEmpty(); } + + void stopDownloads(); + + void saveState( QDataStream& stream ); + void restoreState( QDataStream& stream ); + +signals: + void activated( const KURL& url, ButtonState button ); + void onItem( const KURL& url ); + +protected: + virtual void resizeEvent( QResizeEvent * ); + +private slots: + void slotLayout(); + void slotDownloadFinished( const KURL&, const QByteArray& ); + +private: + /** + * @returns a _temporary_ pointer to a pixmap. Copy it! + */ + QPixmap * getPixmap( const KURL& url ); + + MrmlViewItemList m_items; + QTimer *m_timer; + QPixmapCache m_pixmapCache; + QPixmap m_unavailablePixmap; + + +}; + + +class MrmlViewItem : public QFrame +{ + Q_OBJECT + +public: + enum Relevance + { + Relevant = 0, + Neutral = 1, + Irrelevant = 2 + }; + + MrmlViewItem( const KURL& url, const KURL& thumbURL, double similarity, + MrmlView *view, const char *name=0L ); + virtual ~MrmlViewItem(); + + void setPixmap( const QPixmap& pixmap ); + + void createRelevanceElement( QDomDocument& document, QDomElement& parent ); + + double similarity() const { return m_similarity; } + + void setSimilarity( double value ); + + virtual QSize sizeHint() const; + + const KURL& url() const { return m_url; } + const KURL& thumbURL() const { return m_thumbURL; } + + bool hasRemotePixmap() const { return !m_thumbURL.isLocalFile() && m_hasRemotePixmap; } + + Relevance relevance() const; + void setRelevance( Relevance relevance ); + +protected: + virtual void paintEvent( QPaintEvent * ); + virtual void resizeEvent( QResizeEvent * ); + + virtual void mousePressEvent( QMouseEvent * ); + virtual void mouseMoveEvent( QMouseEvent * ); + virtual void mouseReleaseEvent( QMouseEvent * ); + +private: + bool hitsPixmap( const QPoint& ) const; + MrmlView * view() const { return m_view; } + + inline int pixmapX() const { + return QMAX( margin, (width() - m_pixmap.width()) / 2); + } + inline int pixmapY() const { + return m_combo->y() - similarityHeight - m_pixmap.height() - margin; + } + + KComboBox *m_combo; // for relevance + MrmlView *m_view; + + KURL m_url; + KURL m_thumbURL; + + QPixmap m_pixmap; + + double m_similarity; + const int similarityFullWidth; + bool m_hasRemotePixmap; + + QPoint pressedPos; + + static const int spacing = 3; + static const int margin = 5; + static const int similarityHeight = 4; + +}; + +QDataStream& operator <<( QDataStream& stream, const KMrml::MrmlViewItem& ); + +} + +#endif // MRML_VIEW_H diff --git a/kmrml/kmrml/mrmlsearch.cpp b/kmrml/kmrml/mrmlsearch.cpp new file mode 100644 index 00000000..6f411313 --- /dev/null +++ b/kmrml/kmrml/mrmlsearch.cpp @@ -0,0 +1,74 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// This little baby is called from Konqueror's popupmenu, when you hit +// "Search for similar images...". This program simply gets the URLs +// from Konqueror and creates a query of the form +// mrml://host.com/?relevant=url1;url2;url3;url4.... +// By default, the mrml URL is mrml://localhost", but you can override that +// by editing ~/.kde/share/config/kio_mrmlrc and adding +// [MRML Settings] +// Default URL=mrml://url.to.your.giftserver.com +// +// mrmlsearch will then invoke "kfmclient openURL query" to start open +// a new Konqueror window and perform the query. + +#include <unistd.h> + +#include <qfile.h> +#include <qstring.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kinstance.h> +#include <kurl.h> + +#include <kmrml_config.h> + +extern "C" KDE_EXPORT int kdemain( int argc, char **argv ) +{ + QString query; + + for ( int i = 1; i < argc; i++ ) { + if ( i > 1 ) + query += ';'; + QString path = QFile::decodeName( argv[i] ); + if ( path.at( 0 ) == '/' ) { + KURL u; + u.setPath( path ); + path = u.url(); + } + query.append( path ); + } + + KInstance instance( "kio_mrml" ); + + KMrml::Config config( instance.config() ); + KMrml::ServerSettings settings = config.defaultSettings(); + KURL url; + url.setProtocol( "mrml" ); + url.setHost( settings.host ); + + query = KURL::encode_string_no_slash( query ); + query.prepend( "?relevant=" ); // this is not encoded! + url.setQuery( query ); + qDebug("***** Query: %s ** URL: %s", query.latin1(), url.url().latin1()); + + return execlp( "kfmclient", + "kfmclient", "openURL", QFile::encodeName(url.url()).data(), + "text/mrml", (void *)0 ); +} diff --git a/kmrml/kmrml/propertysheet.cpp b/kmrml/kmrml/propertysheet.cpp new file mode 100644 index 00000000..ec46aac0 --- /dev/null +++ b/kmrml/kmrml/propertysheet.cpp @@ -0,0 +1,206 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "propertysheet.h" + +#include "mrml_elements.h" +#include "mrml_shared.h" + +#include <knuminput.h> +#include <qwidget.h> + +using namespace KMrml; + +template class QValueList<QDomElement>; + +PropertySheet::PropertySheet() +{ + init(); +} + +PropertySheet::PropertySheet( const QDomElement& elem ) +{ + init(); + + initFromDOM( elem ); +} + +PropertySheet::PropertySheet( const PropertySheet& ps ) +{ + *this = ps; +} + +PropertySheet& PropertySheet::operator= ( const PropertySheet& ps ) +{ + if ( &ps == this ) + return *this; + + m_visibility = ps.m_visibility; + m_type = ps.m_type; + m_caption = ps.m_caption; + m_id = ps.m_id; + + m_sendType = ps.m_sendType; + m_sendName = ps.m_sendName; + m_sendValue = ps.m_sendValue; + + m_minRange = ps.m_minRange; + m_maxRange = ps.m_maxRange; + m_stepSize = ps.m_stepSize; + + m_minSubsetSize = ps.m_minSubsetSize; + m_maxSubsetSize = ps.m_maxSubsetSize; + + // deep copy of m_subSheets + QPtrListIterator<PropertySheet> it( ps.m_subSheets ); + for ( ; it.current(); ++it ) + m_subSheets.append( new PropertySheet( *it.current() ) ); + + return *this; +} + +void PropertySheet::init() +{ + m_subSheets.setAutoDelete( true ); + m_visibility = Visible; +} + +void PropertySheet::initFromDOM( const QDomElement& elem ) +{ + m_subSheets.clear(); + + m_visibility = getVisibility( elem.attribute( MrmlShared::visibility() )); + m_type = getType( elem.attribute( MrmlShared::propertySheetType() ) ); + m_caption = elem.attribute( MrmlShared::caption() ); + m_id = elem.attribute( MrmlShared::propertySheetId() ); + m_sendType = getSendType( elem.attribute( MrmlShared::sendType() )); + m_sendName = elem.attribute( MrmlShared::sendName() ); + m_sendValue = elem.attribute( MrmlShared::sendValue() ); + m_minRange = toInt( elem.attribute( MrmlShared::from() )); + m_maxRange = toInt( elem.attribute( MrmlShared::to() )); + m_stepSize = toInt( elem.attribute( MrmlShared::step() )); + + m_minSubsetSize = toInt( elem.attribute( MrmlShared::minSubsetSize() )); + m_maxSubsetSize = toInt( elem.attribute( MrmlShared::maxSubsetSize() )); + + QValueList<QDomElement> children = + KMrml::directChildElements( elem, MrmlShared::propertySheet() ); + QValueListConstIterator<QDomElement> it = children.begin(); + for ( ; it != children.end(); ++it ) + m_subSheets.append( new PropertySheet( *it ) ); +} + +QWidget * PropertySheet::createWidget( QWidget */*parent*/, const char */*name*/ ) +{ + QWidget *w = 0L; + + switch ( m_type ) + { + case Numeric: + { +// KIntNumInput *input = new KIntNumInput(); + break; + } + + case Subset: + { + if ( m_minSubsetSize == 1 && m_maxSubsetSize == 1 ) + { + + } + + break; + } + + default: + qDebug("** can't create widget for type: %i", m_type); + } + + return w; +} + + +// +// static methods +// +PropertySheet::Visibility PropertySheet::getVisibility( const QString& value ) +{ + Visibility vis; + + if ( value == MrmlShared::invisible() ) + vis = Invisible; + else if ( value == MrmlShared::popup() ) + vis = Popup; + else + vis = Visible; // default value + + return vis; +} + +PropertySheet::Type PropertySheet::getType( const QString& value ) +{ + Type type = (Type) 0; + + if ( value == MrmlShared::multiSet() ) + type = MultiSet; + else if ( value == MrmlShared::subset() ) + type = Subset; + else if ( value == MrmlShared::setElement() ) + type = SetElement; + else if ( value == MrmlShared::boolean() ) + type = Boolean; + else if ( value == MrmlShared::numeric() ) + type = Numeric; + else if ( value == MrmlShared::textual() ) + type = Textual; + else if ( value == MrmlShared::panel() ) + type = Panel; + else if ( value == MrmlShared::clone() ) + type = Clone; + else if ( value == MrmlShared::reference() ) + type = Reference; + + return type; +} + +PropertySheet::SendType PropertySheet::getSendType( const QString& value ) +{ + SendType type = (SendType) 0; + + if ( value == MrmlShared::element() ) + type = Element; + else if ( value == MrmlShared::attribute() ) + type = Attribute; + else if ( value == MrmlShared::attributeName() ) + type = AttributeName; + else if ( value == MrmlShared::attributeValue() ) + type = AttributeValue; + else if ( value == MrmlShared::children() ) + type = Children; + else if ( value == MrmlShared::none() ) + type = None; + + return type; +} + +int PropertySheet::toInt( const QString& value, int defaultValue ) +{ + bool ok = false; + int res = value.toInt( &ok ); + return ok ? res : defaultValue; +} diff --git a/kmrml/kmrml/propertysheet.h b/kmrml/kmrml/propertysheet.h new file mode 100644 index 00000000..029d0242 --- /dev/null +++ b/kmrml/kmrml/propertysheet.h @@ -0,0 +1,113 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PROPERTYSHEET_H +#define PROPERTYSHEET_H + +#include <qdom.h> +#include <qstring.h> +#include <qptrlist.h> + +class QWidget; + +namespace KMrml +{ + class PropertySheet + { + public: + enum Type + { + MultiSet = 1, // ?? + Subset, // radio-button/combobox or listbox + SetElement, // CheckBox -> disables/enables children? + Boolean, // CheckBox + Numeric, // Slider/Spinbox + Textual, // lineedit + Panel, // groupbox? + Clone, + Reference + }; + enum Visibility + { + Visible, + Invisible, + Popup + }; + enum SendType + { + Element = 1, + Attribute, + AttributeName, + AttributeValue, + Children, + None + }; + + PropertySheet(); + PropertySheet( const QDomElement& elem ); + PropertySheet( const PropertySheet& ps ); + ~PropertySheet() {}; + + PropertySheet& operator=( const PropertySheet& ps ); + + bool isValid() const { + // required mrml attributes + return !m_id.isNull() && m_type != 0 && m_sendType != 0; + } + void initFromDOM( const QDomElement& elem ); + + void toElement( QDomElement& parent ); + + QWidget * createWidget( QWidget *parent, const char *name = 0 ); + + private: + static Visibility getVisibility( const QString& value ); + static Type getType( const QString& value ); + static SendType getSendType( const QString& value ); + static int toInt( const QString& value, int defaultValue = 0 ); + + void init(); + + + // update operator=() when adding data members! + + QPtrList<PropertySheet> m_subSheets; + Visibility m_visibility; + Type m_type; + QString m_caption; + QString m_id; + + SendType m_sendType; + QString m_sendName; + QString m_sendValue; + + int m_minRange; + int m_maxRange; + int m_stepSize; + + // Type = Subset && m_minSubsetSize == m_maxSubsetSize == 1 -> Combobox + // or radio buttons. + // > max > 1 -> Listbox with multiselection + int m_minSubsetSize; + int m_maxSubsetSize; + + }; + +} + +#endif // PROPERTYSHEET_H diff --git a/kmrml/kmrml/propertywidgets.cpp b/kmrml/kmrml/propertywidgets.cpp new file mode 100644 index 00000000..ef00b18f --- /dev/null +++ b/kmrml/kmrml/propertywidgets.cpp @@ -0,0 +1,121 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "propertywidgets.h" + +IntegerWidget::IntegerWidget( const PropertySheet& sheet, + QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + +} + +IntegerWidget::~IntegerWidget() +{ + +} + +int IntegerWidget::value() const +{ + +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +ComboWidget::ComboWidget( const PropertySheet& sheet, + QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + +} + +ComboWidget::~ComboWidget() +{ + +} + +QString ComboWidget::value() const +{ + +} + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +CheckBoxWidget::CheckBoxWidget( const PropertySheet& sheet, + QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + +} + +CheckBoxWidget::~CheckBoxWidget() +{ + +} + +bool CheckBoxWidget::value() const +{ + +} + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +LineEditWidget::LineEditWidget( const PropertySheet& sheet, + QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + +} + +LineEditWidget::~LineEditWidget() +{ + +} + +QString LineEditWidget::value() const +{ + +} + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +ListBoxWidget::ListBoxWidget( const PropertySheet& sheet, + QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + +} + +ListBoxWidget::~ListBoxWidget() +{ + +} + +QStringList ListBoxWidget::value() const +{ + +} + +#include "propertywidgets.moc" diff --git a/kmrml/kmrml/propertywidgets.h b/kmrml/kmrml/propertywidgets.h new file mode 100644 index 00000000..c738d03d --- /dev/null +++ b/kmrml/kmrml/propertywidgets.h @@ -0,0 +1,108 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PROPERTYWIDGETS_H +#define PROPERTYWIDGETS_H + +#include <qhbox.h> + +#include "propertysheet.h" + +namespace KMrml +{ + class IntegerWidget : public QHBox + { + Q_OBJECT + + public: + IntegerWidget( const PropertySheet& sheet, + QWidget *parent = parent, const char *name = 0L ); + ~IntegerWidget(); + + int value() const; + + private: + + }; + + class ComboWidget : public QHBox + { + Q_OBJECT + + public: + ComboWidget( const PropertySheet& sheet, + QWidget *parent = parent, const char *name = 0L ); + ~ComboWidget(); + + QString value() const; + + private: + + }; + + class CheckBoxWidget : public QHBox + { + Q_OBJECT + + public: + CheckBoxWidget( const PropertySheet& sheet, + QWidget *parent = parent, const char *name = 0L ); + ~CheckBoxWidget(); + + bool value(); + + private: + + + }; + + + class LineEditWidget : public QHBox + { + Q_OBJECT + + public: + LineEditWidget( const PropertySheet& sheet, + QWidget *parent = parent, const char *name = 0L ); + ~LineEditWidget(); + + QString value(); + + private: + + }; + + class ListBoxWidget : public QHBox + { + Q_OBJECT + + public: + ListBoxWidget( const PropertySheet& sheet, + QWidget *parent = parent, const char *name = 0L ); + ~ListBoxWidget(); + + QStringList values(); + + private: + + }; + +}; + + +#endif // PROPERTYWIDGETS_H diff --git a/kmrml/kmrml/server/Makefile.am b/kmrml/kmrml/server/Makefile.am new file mode 100644 index 00000000..875684b0 --- /dev/null +++ b/kmrml/kmrml/server/Makefile.am @@ -0,0 +1,12 @@ +kde_module_LTLIBRARIES = kded_daemonwatcher.la + +INCLUDES = $(all_includes) +kded_daemonwatcher_la_SOURCES = watcher.cpp watcher.skel +# watcher.stub +kded_daemonwatcher_la_LDFLAGS = $(all_libraries) -module -avoid-version +kded_daemonwatcher_la_LIBADD = $(LIB_KSYCOCA) $(LIB_KDEUI) + +METASOURCES = AUTO + +servicesdir = $(kde_servicesdir)/kded +services_DATA = daemonwatcher.desktop diff --git a/kmrml/kmrml/server/daemonwatcher.desktop b/kmrml/kmrml/server/daemonwatcher.desktop new file mode 100644 index 00000000..c29495b4 --- /dev/null +++ b/kmrml/kmrml/server/daemonwatcher.desktop @@ -0,0 +1,103 @@ +[Desktop Entry] +Type=Service +Name=KDED KMRML Daemon Watcher +Name[ar]=مراقب KDED KMRML Daemon +Name[bs]=KDED KMRML nadzor demona +Name[ca]=Dimoni vigilant KDED KMRL +Name[cs]=Sledovač KMRML démonů +Name[cy]=Gwyliwr Ellyll KMRML KDED +Name[da]=KDED KMRML-dæmon-overvåger +Name[de]=Überwachung der KDE-Bildersuche +Name[el]=Επόπτης δαίμονα KMRML KDED +Name[es]=Guardián del demonio KDED KMRML +Name[et]=KDED KMRML deemoni jälgija +Name[eu]=KDED KMRML deabru behatzailea +Name[fa]=پایشگر شبح KDED KMRML +Name[fi]=KDED KMRML-palvelimen tarkkailija +Name[fr]=Observateur KDE du démon KMRML +Name[gl]=Vixiante do daemon de KDED KMRML +Name[he]=צופה תהליכי הרקע של KDED KMRML +Name[hi]=KDED KMRML डेमन वाचर +Name[hu]=KDED KMRML szolgáltatásfigyelő +Name[is]=Eftirlit með KDED KMRML þjóninum +Name[it]=Controllo del demone KDED KMRML +Name[ja]=KDED KMRML デーモンウォッチャー +Name[kk]=KDED KMRML қызметі +Name[km]=កម្មវិធីឃ្លាំមើលដេមិន KDED KMRML +Name[lt]=KDED KMRML tarnybos stebėtojas +Name[ms]=Pemerhati Daemon KDED KMRML +Name[nb]=KDED KMRML nisseovervåker +Name[nds]=KMRML-Luerdämoon för KDED +Name[ne]=KDED KMRML डेइमन दर्शक +Name[nl]=KDED KMRML-daemonbeheer +Name[nn]=KDED KMRML-nisseovervaking +Name[pl]=Monitor usług KMRML +Name[pt]=Monitor KMRML de Servidores KDED +Name[pt_BR]=Sentinela de Serviços KDED +Name[ro]=Demon KDED pentru MRML +Name[ru]=Служба MRML +Name[se]=KDED KMRML-duogášprográmmagoziheaddji +Name[sk]=Sledovanie démona KDED KMRML +Name[sl]=Opazovalnik demona KMRML za KDED +Name[sr]=KDED KMRML демон за праћење +Name[sr@Latn]=KDED KMRML demon za praćenje +Name[sv]=KDED KMRML-demonbevakare +Name[ta]=KDED டிமென் வாட்சர் +Name[tg]=Мудири демони KDED KMRML +Name[th]=ตัวเฝ้าดูแดมอน KDED KMRML +Name[tr]=KDED KMRML Aracı İzleyici +Name[uk]=Спостерігач демону KDED KMRML +Name[zh_CN]=KDED KMRML 守护程序监视器 +Name[zh_HK]=KDED KMRML 系統程式監察器 +Name[zh_TW]=KDED KMRML 伺服程式監看器 +Comment=Starts daemons on demand and restarts them on failure +Comment[bg]=Стартиране на демоните при заявка и рестартиране на демони при грешка +Comment[bs]=Pokreće demone po potrebi i restartuje ih ako se sruše +Comment[ca]=Engega els dimonis sota petició i els torna a engegar si fallen +Comment[cs]=Spouští démony na požádání a restartuje je při selhání +Comment[da]=Starter dæmoner ved forespørgsel og genstarter dem ved fejl +Comment[de]=Startet KMRML-Dienste bei Bedarf und im Fehlerfall neu +Comment[el]=Εκκινεί δαίμονες όταν ζητηθεί και τους επανεκκινεί κατά την αποτυχία +Comment[es]=Inicia los demonios bajo demanda y los reinicia si fallan +Comment[et]=Käivitab nõudmisel deemoneid ja taaskäivitab neid ebaõnnestumise korral +Comment[eu]=Demonioak hasi eta bukau egiten ditu eskatzen zaionean +Comment[fa]=شبحها را بر اساس نیاز آغاز میکند و هنگام خرابی آنها را بازآغازی میکند +Comment[fi]=Käynnistää palvelimia tarpeen mukaan ja uudelleenkäynnistää ne virheen yhteydessä +Comment[fr]=Lance les démons à la demande et les redémarre en cas d'échec +Comment[gl]=Iniciar daemons cando sexa preciso e reinicialos se fallan. +Comment[he]=מפעיל תהליכי רקע לפי דרישה ומפעיל אותם מחדש במקרה של כשל +Comment[hu]=Szükség esetén elindítja, hiba esetén újraindítja a szolgáltatásokat +Comment[is]=Ræsir þjóna þegar þarf og endurræsir þá ef þeir bregðast +Comment[it]=Avvia i demoni su richiesta e li riavvia in caso di problemi +Comment[ja]=デーモンをオンデマンドで起動し、失敗したときは再起動します。 +Comment[kk]=Талап бойынша қызметті жегу, жаңылса қайта жегу +Comment[km]=ចាប់ផ្ដើមដេមិននៅពេលត្រូវការ ហើយចាប់ផ្ដើមពួកវាឡើងវិញនៅពេលបរាជ័យ +Comment[lt]=Paleidžia tarnybas pagal pareikalavimą ir paleidžia iš naujo nesėkmės atveju +Comment[ms]=Mulakan daemons atas permintaan dan mula semula atas kegagalan +Comment[nb]=Starter nisser på forespørsler og starter dem igjen ved feil. +Comment[nds]=Start Achtergrundperzessen op Nafraag un bi Fehlers nieg +Comment[ne]=माग गरेको बेलामा डेइमन सुरु गर्दछ र अफफल भएमा फेरि सुरु गर्दछ +Comment[nl]=Start achtergrondprogramma's op en herstart deze indien nodig +Comment[nn]=Startar nissar når dei trengst og startar dei om att ved feil +Comment[pl]=Uruchamia usługi na żądanie i wznawia je po awarii +Comment[pt]=Inicia os servidores a pedido e reinicia-os em caso de falha +Comment[pt_BR]=Inicia serviços sob demanda e reinicia-os em caso de falha +Comment[ro]=Porneşte demonii la cerere şi îi reporneşte în caz de eroare +Comment[ru]=Поддержка протокола MRML +Comment[sk]=Spustí démonov podľa požiadaviek a pri zlyhaní ich reštartuje +Comment[sl]=Na zahtevo zažene demone in jih ob napaki znova zažene +Comment[sr]=На захтев покреће демоне и поново их покреће ако се сруше +Comment[sr@Latn]=Na zahtev pokreće demone i ponovo ih pokreće ako se sruše +Comment[sv]=Starta demoner vid behov och starta om dem vid fel +Comment[ta]=அவசிய நேரத்தில் டிமென்னை துவக்குகிறது. இயலாதபோது திரும்ப துவக்குகிறது +Comment[tg]=Оғози демон аз рӯи дархост ва ҳангоми нуқсони он аз сари нав оғоз намудан. +Comment[tr]=İstek halinde programı başlatır ve hata durumunda yeniden başlatır. +Comment[uk]=Запускає демони при потребі та перезапускає їх при аварії +Comment[zh_CN]=按需启动守护程序并在失败时重新启动 +Comment[zh_HK]=依要求啟動系統程式並在失敗時重新啟動它們。 +Comment[zh_TW]=需要時啟動守護程式,失敗的話重新啟動 +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=daemonwatcher +X-KDE-FactoryName=daemonwatcher +X-KDE-Kded-load-on-demand=true diff --git a/kmrml/kmrml/server/watcher.cpp b/kmrml/kmrml/server/watcher.cpp new file mode 100644 index 00000000..e6137cc5 --- /dev/null +++ b/kmrml/kmrml/server/watcher.cpp @@ -0,0 +1,280 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <dcopclient.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "watcher.h" + +using namespace KMrml; + +Watcher::Watcher( const QCString& name ) + : KDEDModule( name ) +{ + m_daemons.setAutoDelete( true ); + + // safety, for clients that die without unregistering + KApplication::dcopClient()->setNotifications( true ); + connect( KApplication::dcopClient(), + SIGNAL( applicationRemoved( const QCString& )), + SLOT( slotAppUnregistered( const QCString& ))); +} + +Watcher::~Watcher() +{ + KApplication::dcopClient()->setNotifications( false ); +} + +bool Watcher::requireDaemon( const QCString& clientAppId, + const QString& daemonKey, + const QString& commandline, + uint timeout /* seconds */, + int restartOnFailure ) +{ + if ( !KApplication::dcopClient()->isApplicationRegistered( clientAppId ) ) + kdWarning() << "Watcher::requireDaemon: " << daemonKey + << ": Client AppID is not registered with DCOP: " + << clientAppId << endl; + + DaemonData *daemon = m_daemons.find( daemonKey ); + + if ( daemon ) + { + if ( !daemon->apps.find( clientAppId ) ) + daemon->apps.append( clientAppId ); + + // timeout, commandline and restart values are: first come, first serve + return true; // process already running, all fine + } + + else // start daemon + { + daemon = new DaemonData( daemonKey, commandline, + timeout, restartOnFailure ); + m_daemons.insert( daemonKey, daemon ); + daemon->apps.append( clientAppId ); + +#if KDE_VERSION >= 306 + daemon->process = new KProcess(); + daemon->process->setUseShell( true ); +#else + daemon->process = new KShellProcess(); +#endif + daemon->process->setEnvironment( "LC_ALL", "C" ); + daemon->process->setEnvironment( "LANG", "C" ); + daemon->process->setEnvironment( "LANGUAGE", "C" ); + *daemon->process << commandline; + connect( daemon->process, SIGNAL( processExited( KProcess * ) ), + SLOT( slotProcExited( KProcess * ))); + return startDaemon( daemon ); + } +} + +void Watcher::unrequireDaemon( const QCString& clientAppId, + const QString& daemonKey ) +{ + unrequireDaemon( m_daemons.find( daemonKey ), clientAppId ); +} + +void Watcher::unrequireDaemon( DaemonData *daemon, + const QCString& clientAppId ) +{ + if ( daemon ) + { + daemon->apps.remove( clientAppId ); + if ( daemon->apps.isEmpty() ) + { + if ( !daemon->timer ) + { + daemon->timer = new QTimer(); + connect( daemon->timer, SIGNAL( timeout() ), + SLOT( slotTimeout() )); + } + daemon->timer->start( daemon->timeout * 1000, true ); + } + } + else + kdWarning() << "Watcher::unrequireDaemon: daemon unknown. client: " + << clientAppId << endl; +} + +QStringList Watcher::runningDaemons() const +{ + QStringList result; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; it.current(); ++it ) + result.append( it.current()->commandline ); + + return result; +} + +void Watcher::slotProcExited( KProcess *proc ) +{ + DaemonData *daemon = findDaemonFromProcess( proc ); + + if ( proc->normalExit() ) + { + emitExited( daemon ); + return; + } + + if ( daemon ) + { + if ( --daemon->restartOnFailure <= 0 ) + { + if ( KMessageBox::questionYesNo( 0L, + i18n("<qt>The server with the command line" + "<br>%1<br>" + "is not available anymore. Do you want to " + "restart it?" ).arg( daemon->commandline ), + i18n("Service Failure"), i18n("Restart Server"), i18n("Do Not Restart") ) + == KMessageBox::Yes ) + { + daemon->restartOnFailure = 1; + } + } + + if ( daemon->restartOnFailure > 0 ) + { + startDaemon( daemon ); + return; + } + } + + emitFailure( daemon ); +} + +bool Watcher::startDaemon( DaemonData *daemon ) +{ + if ( daemon->process->start( KProcess::NotifyOnExit ) ) + return true; + + else + { + if ( KMessageBox::questionYesNo( 0L, + i18n("Unable to start the server with the " + "command line" + "<br>%1<br>" + "Try again?").arg( daemon->commandline ), + i18n("Service Failure"), i18n("Try Again"), i18n("Do Not Try") ) + == KMessageBox::Yes ) + { + return startDaemon( daemon ); + } + } + + return false; +} + +void Watcher::slotTimeout() +{ + QTimer *timer = static_cast<QTimer*>( const_cast<QObject *>( sender() ) ); + DaemonData *daemon = findDaemonFromTimer( timer ); + if ( daemon ) + { + if ( daemon->apps.isEmpty() ) + { + // the daemon and KProcess might get deleted by killing the + // KProcess (through slotProcExited()), so don't dereference + // daemon after proc->kill() + QString key = daemon->daemonKey; + + // noone registered during the timeout, so kill the daemon + if ( !daemon->process->kill() ) + daemon->process->kill( SIGKILL ); + + m_daemons.remove( key ); + } + } +} + +DaemonData * Watcher::findDaemonFromProcess( KProcess *proc ) +{ + DaemonData *daemon; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; (daemon = it.current()); ++it ) + { + if ( daemon->process == proc ) + return daemon; + } + + return 0L; +} + +DaemonData * Watcher::findDaemonFromTimer( QTimer *timer ) +{ + DaemonData *daemon; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; (daemon = it.current()); ++it ) + { + if ( daemon->timer == timer ) + return daemon; + } + + return 0L; +} + +void Watcher::slotAppUnregistered( const QCString& appId ) +{ + if ( m_daemons.isEmpty() ) + return; + + DaemonData *daemon; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; (daemon = it.current()); ++it ) + { + if ( daemon->apps.find( appId ) != -1 ) + unrequireDaemon( daemon, appId ); + } +} + +void Watcher::emitExited( DaemonData *daemon ) +{ + if ( daemon ) + { + daemonExited( daemon->daemonKey, + daemon->process->pid(), + daemon->process->exitStatus() ); + + m_daemons.remove( daemon->daemonKey ); + } +} + +void Watcher::emitFailure( DaemonData *daemon ) +{ + if ( daemon ) + { + daemonDied( daemon->daemonKey, daemon->process->pid() ); + m_daemons.remove( daemon->daemonKey ); // deletes daemon + KProcess + } +} + +extern "C" { + KDE_EXPORT KDEDModule *create_daemonwatcher(const QCString & obj ) + { + return new Watcher( obj ); + } +} + + +#include "watcher.moc" diff --git a/kmrml/kmrml/server/watcher.h b/kmrml/kmrml/server/watcher.h new file mode 100644 index 00000000..67d9b5e1 --- /dev/null +++ b/kmrml/kmrml/server/watcher.h @@ -0,0 +1,107 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + 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, version 2. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef LAUNCHER_H +#define LAUNCHER_H + +#include <qdict.h> +#include <qmap.h> +#include <qstrlist.h> +#include <qstringlist.h> +#include <qtimer.h> + +#include <kdedmodule.h> +#include <kprocess.h> + +namespace KMrml +{ + class DaemonData + { + public: + DaemonData( const QString& key, const QString& cmd, + uint time, int numRestarts ) + : daemonKey( key ), + commandline( cmd ), + timeout( time ), + apps( true ), // deep copies + restartOnFailure( numRestarts ), + process( 0L ), + timer( 0L ) + { + } + ~DaemonData() + { + delete process; + delete timer; + } + QString daemonKey; + QString commandline; + uint timeout; + QStrList apps; + int restartOnFailure; + KProcess *process; + QTimer *timer; + }; + + class Watcher : public KDEDModule + { + Q_OBJECT + K_DCOP + + public: + Watcher( const QCString& name = "daemonwatcher" ); + ~Watcher(); + + k_dcop: + virtual bool requireDaemon( const QCString& clientAppId, + const QString& daemonKey, + const QString& commandline, + uint timeout = 60 /* seconds */, + int numRestarts = 5 ); + virtual void unrequireDaemon( const QCString& clientAppId, + const QString& daemonKey ); + virtual QStringList runningDaemons() const; + + k_dcop_signals: + void daemonExited(const QString& daemonKey, pid_t pid, int exitStatus); + void daemonDied( const QString& daemonKey, pid_t pid ); + + protected: + bool startDaemon( DaemonData *daemon ); + + protected slots: + virtual void slotTimeout(); + + private: + void unrequireDaemon( DaemonData *daemon, const QCString& clientAppId); + DaemonData *findDaemonFromProcess( KProcess *proc ); + DaemonData *findDaemonFromTimer( QTimer *timer ); + + void emitExited( DaemonData *daemon ); + void emitFailure( DaemonData *daemon ); + + private slots: + void slotProcExited( KProcess *proc ); + void slotAppUnregistered( const QCString& appId ); + + QDict<DaemonData> m_daemons; + }; + +} + +#endif // LAUNCHER_H |