# HG changeset patch # User Chris Cannam # Date 1224002195 0 # Node ID ef14acd6d1023b469364d1d486f79487ec345fd3 # Parent 64e64e304a12b9b12060098fac16c9f83f36fedc * Add beginnings of capability to search plugins that are not yet installed -- lots more work to do here, though diff -r 64e64e304a12 -r ef14acd6d102 base/TextMatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/TextMatcher.cpp Tue Oct 14 16:36:35 2008 +0000 @@ -0,0 +1,124 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2008 QMUL. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "TextMatcher.h" + +TextMatcher::TextMatcher() +{ +} + +TextMatcher::~TextMatcher() +{ +} + +void +TextMatcher::test(Match &match, QStringList keywords, QString text, + QString textType, int score) +{ +/* + if (text.toLower() == keyword.toLower()) { + match.score += score * 1.5; + match.fragments << tr("%1: %2").arg(textType).arg(text); + return; + } +*/ + int len = text.length(); + int prevEnd = 0; + QString fragment; + + while (1) { + + bool first = (prevEnd == 0); + + int idx = -1; + QString keyword; + + for (int ki = 0; ki < keywords.size(); ++ki) { + int midx = text.indexOf(keywords[ki], prevEnd, Qt::CaseInsensitive); + if (midx >= 0 && midx < len) { + if (midx < idx || idx == -1) { + idx = midx; + keyword = keywords[ki]; + } + } + } + + if (idx < 0 || idx >= len) break; + + int klen = keyword.length(); + + if (first) { + match.score += score; + } else { + match.score += score / 4; + } + + int start = idx; + int end = start + klen; + + if (start == 0) match.score += 1; + if (end == len) match.score += 1; + + if (start > prevEnd + 14) { + QString s = text.right((len - start) + 10); + s = XmlExportable::encodeEntities(s.left(10)) + "" + + XmlExportable::encodeEntities(s.left(klen + 10).right(klen)) + + ""; + fragment += QString("...%1").arg(s); + } else { + QString s = text.right(len - prevEnd); + s = XmlExportable::encodeEntities(s.left(start - prevEnd)) + "" + + XmlExportable::encodeEntities(s.left(end - prevEnd).right(klen)) + + ""; + fragment += s; + } + + prevEnd = end; + } + + if (prevEnd > 0 && prevEnd < len) { + int n = len - prevEnd; + fragment += + XmlExportable::encodeEntities(text.right(n).left(n < 8 ? n : 8)); + } + + if (fragment != "") { + match.fragments[textType] = fragment; + } +} + +bool +TextMatcher::Match::operator<(const Match &m) const +{ + if (score != m.score) { + return score < m.score; + } + if (key != m.key) { + return key < m.key; + } + if (fragments.size() != m.fragments.size()) { + return fragments.size() < m.fragments.size(); + } + + for (FragmentMap::const_iterator + i = fragments.begin(), + j = m.fragments.begin(); + i != fragments.end(); ++i, ++j) { + if (i->first != j->first) return i->first < j->first; + if (i->second != j->second) return i->second < j->second; + } + + return false; +} diff -r 64e64e304a12 -r ef14acd6d102 base/TextMatcher.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/TextMatcher.h Tue Oct 14 16:36:35 2008 +0000 @@ -0,0 +1,56 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2008 QMUL. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _TEXT_MATCHER_H_ +#define _TEXT_MATCHER_H_ + +#include +#include +#include "XmlExportable.h" + +#include + +/// A rather eccentric interface for matching texts in differently-scored fields + +class TextMatcher +{ +public: + TextMatcher(); + virtual ~TextMatcher(); + + struct Match + { + QString key; // This field is not used by TextMatcher + int score; + typedef std::map FragmentMap; // text type -> fragment + FragmentMap fragments; + + Match() : score(0) { } + Match(const Match &m) : + key(m.key), score(m.score), fragments(m.fragments) { } + + bool operator<(const Match &m) const; // sort by score first + }; + + void test(Match &match, // existing match record to be augmented + QStringList keywords, // search terms + QString text, // to search within + QString textType, // key to use for fragment map + int score); // relative weight for hits within this text type + +}; + + +#endif diff -r 64e64e304a12 -r ef14acd6d102 base/base.pro --- a/base/base.pro Mon Oct 13 13:53:05 2008 +0000 +++ b/base/base.pro Tue Oct 14 16:36:35 2008 +0000 @@ -40,6 +40,7 @@ Serialiser.h \ StorageAdviser.h \ TempDirectory.h \ + TextMatcher.h \ Thread.h \ UnitDatabase.h \ ViewManagerBase.h \ @@ -67,6 +68,7 @@ Serialiser.cpp \ StorageAdviser.cpp \ TempDirectory.cpp \ + TextMatcher.cpp \ Thread.cpp \ UnitDatabase.cpp \ ViewManagerBase.cpp \ diff -r 64e64e304a12 -r ef14acd6d102 data/fileio/FileSource.cpp --- a/data/fileio/FileSource.cpp Mon Oct 13 13:53:05 2008 +0000 +++ b/data/fileio/FileSource.cpp Tue Oct 14 16:36:35 2008 +0000 @@ -743,7 +743,9 @@ QString filepart = m_url.path().section('/', -1, -1, QString::SectionSkipEmpty); - QString extension = filepart.section('.', -1); + QString extension = ""; + if (filepart.contains('.')) extension = filepart.section('.', -1); + QString base = filepart; if (extension != "") { base = base.left(base.length() - extension.length() - 1); diff -r 64e64e304a12 -r ef14acd6d102 rdf/PluginRDFDescription.cpp --- a/rdf/PluginRDFDescription.cpp Mon Oct 13 13:53:05 2008 +0000 +++ b/rdf/PluginRDFDescription.cpp Tue Oct 14 16:36:35 2008 +0000 @@ -18,6 +18,10 @@ #include "PluginRDFIndexer.h" #include "SimpleSPARQLQuery.h" +#include "data/fileio/FileSource.h" + +#include "base/Profiler.h" + #include "plugin/PluginIdentifier.h" #include @@ -25,6 +29,7 @@ using std::endl; PluginRDFDescription::PluginRDFDescription(QString pluginId) : + m_source(0), m_pluginId(pluginId), m_haveDescription(false) { @@ -45,6 +50,7 @@ PluginRDFDescription::~PluginRDFDescription() { + delete m_source; } bool @@ -53,6 +59,44 @@ return m_haveDescription; } +QString +PluginRDFDescription::getPluginName() const +{ + return m_pluginName; +} + +QString +PluginRDFDescription::getPluginDescription() const +{ + return m_pluginDescription; +} + +QString +PluginRDFDescription::getPluginMaker() const +{ + return m_pluginMaker; +} + +QStringList +PluginRDFDescription::getOutputIds() const +{ + QStringList ids; + for (OutputDispositionMap::const_iterator i = m_outputDispositions.begin(); + i != m_outputDispositions.end(); ++i) { + ids.push_back(i->first); + } + return ids; +} + +QString +PluginRDFDescription::getOutputName(QString outputId) const +{ + if (m_outputNames.find(outputId) == m_outputNames.end()) { + return ""; + } + return m_outputNames.find(outputId)->second; +} + PluginRDFDescription::OutputDisposition PluginRDFDescription::getOutputDisposition(QString outputId) const { @@ -104,9 +148,95 @@ bool PluginRDFDescription::indexURL(QString url) { + Profiler profiler("PluginRDFDescription::indexURL"); + QString type, soname, label; PluginIdentifier::parseIdentifier(m_pluginId, type, soname, label); + bool success = true; + + QString local = url; + + if (FileSource::isRemote(url) && + FileSource::canHandleScheme(url)) { + + m_source = new FileSource(url); + if (!m_source->isAvailable()) { + delete m_source; + m_source = 0; + return false; + } + m_source->waitForData(); + local = QUrl::fromLocalFile(m_source->getLocalFilename()).toString(); + } + + if (!indexMetadata(local, label)) success = false; + if (!indexOutputs(local, label)) success = false; + + return success; +} + +bool +PluginRDFDescription::indexMetadata(QString url, QString label) +{ + Profiler profiler("PluginRDFDescription::indexMetadata"); + + QString queryTemplate = + QString( + " PREFIX vamp: " + " PREFIX foaf: " + " PREFIX dc: " + " SELECT ?%4 FROM <%1> " + " WHERE { " + " ?plugin a vamp:Plugin ; " + " vamp:identifier \"%2\" ; " + " %3 ?%4 . " + " }") + .arg(url) + .arg(label); + + SimpleSPARQLQuery::Value v; + + v = SimpleSPARQLQuery::singleResultQuery + (queryTemplate.arg("vamp:name").arg("name"), "name"); + + if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") { + m_pluginName = v.value; + } + + v = SimpleSPARQLQuery::singleResultQuery + (queryTemplate.arg("dc:description").arg("description"), "description"); + + if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") { + m_pluginDescription = v.value; + } + + v = SimpleSPARQLQuery::singleResultQuery + (QString( + " PREFIX vamp: " + " PREFIX foaf: " + " SELECT ?name FROM <%1> " + " WHERE { " + " ?plugin a vamp:Plugin ; " + " vamp:identifier \"%2\" ; " + " foaf:maker ?maker . " + " ?maker foaf:name ?name . " + " }") + .arg(url) + .arg(label), "name"); + + if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") { + m_pluginMaker = v.value; + } + + return true; +} + +bool +PluginRDFDescription::indexOutputs(QString url, QString label) +{ + Profiler profiler("PluginRDFDescription::indexOutputs"); + SimpleSPARQLQuery query (QString ( @@ -166,6 +296,8 @@ m_outputDispositions[outputId] = OutputSparse; } else if (outputType.contains("TrackLevelOutput")) { m_outputDispositions[outputId] = OutputTrackLevel; + } else { + m_outputDispositions[outputId] = OutputDispositionUnknown; } if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) { @@ -177,14 +309,25 @@ } } + SimpleSPARQLQuery::Value v; + + v = SimpleSPARQLQuery::singleResultQuery + (QString(" PREFIX vamp: " + " PREFIX dc: " + " SELECT ?title FROM <%1> " + " WHERE { <%2> dc:title ?title } ") + .arg(url).arg(outputUri), "title"); + + if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") { + m_outputNames[outputId] = v.value; + } + QString queryTemplate = QString(" PREFIX vamp: " " SELECT ?%3 FROM <%1> " " WHERE { <%2> vamp:computes_%3 ?%3 } ") .arg(url).arg(outputUri); - SimpleSPARQLQuery::Value v; - v = SimpleSPARQLQuery::singleResultQuery (queryTemplate.arg("event_type"), "event_type"); diff -r 64e64e304a12 -r ef14acd6d102 rdf/PluginRDFDescription.h --- a/rdf/PluginRDFDescription.h Mon Oct 13 13:53:05 2008 +0000 +++ b/rdf/PluginRDFDescription.h Tue Oct 14 16:36:35 2008 +0000 @@ -17,6 +17,7 @@ #define _PLUGIN_RDF_DESCRIPTION_H_ #include +#include #include class FileSource; @@ -37,6 +38,13 @@ }; bool haveDescription() const; + + QString getPluginName() const; + QString getPluginDescription() const; + QString getPluginMaker() const; + + QStringList getOutputIds() const; + QString getOutputName(QString outputId) const; OutputDisposition getOutputDisposition(QString outputId) const; QString getOutputEventTypeURI(QString outputId) const; QString getOutputFeatureAttributeURI(QString outputId) const; @@ -47,14 +55,21 @@ typedef std::map OutputDispositionMap; typedef std::map OutputStringMap; + FileSource *m_source; QString m_pluginId; bool m_haveDescription; + QString m_pluginName; + QString m_pluginDescription; + QString m_pluginMaker; + OutputStringMap m_outputNames; OutputDispositionMap m_outputDispositions; OutputStringMap m_outputEventTypeURIMap; OutputStringMap m_outputFeatureAttributeURIMap; OutputStringMap m_outputSignalTypeURIMap; OutputStringMap m_outputUnitMap; bool indexURL(QString url); + bool indexMetadata(QString url, QString label); + bool indexOutputs(QString url, QString label); }; #endif diff -r 64e64e304a12 -r ef14acd6d102 rdf/PluginRDFIndexer.cpp --- a/rdf/PluginRDFIndexer.cpp Mon Oct 13 13:53:05 2008 +0000 +++ b/rdf/PluginRDFIndexer.cpp Tue Oct 14 16:36:35 2008 +0000 @@ -20,6 +20,8 @@ #include "data/fileio/FileSource.h" #include "plugin/PluginIdentifier.h" +#include "base/Profiler.h" + #include #include @@ -93,9 +95,9 @@ PluginRDFIndexer::~PluginRDFIndexer() { - while (!m_cache.empty()) { - delete *m_cache.begin(); - m_cache.erase(m_cache.begin()); + while (!m_sources.empty()) { + delete *m_sources.begin(); + m_sources.erase(m_sources.begin()); } } @@ -122,13 +124,7 @@ QString baseUrl = QUrl(uri).toString(QUrl::RemoveFragment); - FileSource source(baseUrl); - if (source.isAvailable()) { - source.waitForData(); - if (indexFile(source.getLocalFilename())) { - m_cache.insert(new FileSource(source)); - } - } + indexURL(baseUrl); if (m_uriToIdMap.find(uri) == m_uriToIdMap.end()) { m_uriToIdMap[uri] = ""; @@ -175,6 +171,23 @@ bool PluginRDFIndexer::indexURL(QString urlString) { + Profiler profiler("PluginRDFIndexer::indexURL"); + + QString localString = urlString; + + if (FileSource::isRemote(urlString) && + FileSource::canHandleScheme(urlString)) { + + FileSource *source = new FileSource(urlString); + if (!source->isAvailable()) { + delete source; + return false; + } + source->waitForData(); + localString = QUrl::fromLocalFile(source->getLocalFilename()).toString(); + m_sources.insert(source); + } + // cerr << "PluginRDFIndexer::indexURL: url = <" << urlString.toStdString() << ">" << endl; SimpleSPARQLQuery query @@ -206,7 +219,7 @@ " } " " } " ) - .arg(urlString)); + .arg(localString)); SimpleSPARQLQuery::ResultList results = query.execute(); diff -r 64e64e304a12 -r ef14acd6d102 rdf/PluginRDFIndexer.h --- a/rdf/PluginRDFIndexer.h Mon Oct 13 13:53:05 2008 +0000 +++ b/rdf/PluginRDFIndexer.h Tue Oct 14 16:36:35 2008 +0000 @@ -41,12 +41,12 @@ protected: PluginRDFIndexer(); + std::set m_sources; typedef std::map StringMap; StringMap m_uriToIdMap; StringMap m_idToUriMap; StringMap m_idToDescriptionMap; bool indexFile(QString path); - std::set m_cache; static PluginRDFIndexer *m_instance; }; diff -r 64e64e304a12 -r ef14acd6d102 rdf/SimpleSPARQLQuery.cpp --- a/rdf/SimpleSPARQLQuery.cpp Mon Oct 13 13:53:05 2008 +0000 +++ b/rdf/SimpleSPARQLQuery.cpp Tue Oct 14 16:36:35 2008 +0000 @@ -121,7 +121,7 @@ m_reporter(0), m_cancelled(false) { - std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl; +// std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl; } SimpleSPARQLQuery::Impl::~Impl() diff -r 64e64e304a12 -r ef14acd6d102 transform/TransformFactory.cpp --- a/transform/TransformFactory.cpp Mon Oct 13 13:53:05 2008 +0000 +++ b/transform/TransformFactory.cpp Tue Oct 14 16:36:35 2008 +0000 @@ -24,6 +24,9 @@ #include "vamp-sdk/PluginHostAdapter.h" #include "vamp-sdk/hostext/PluginWrapper.h" +#include "rdf/PluginRDFIndexer.h" +#include "rdf/PluginRDFDescription.h" + #include "base/XmlExportable.h" #include @@ -44,6 +47,12 @@ return m_instance; } +TransformFactory::TransformFactory() : + m_transformsPopulated(false), + m_uninstalledTransformsPopulated(false) +{ +} + TransformFactory::~TransformFactory() { } @@ -51,7 +60,7 @@ TransformList TransformFactory::getAllTransformDescriptions() { - if (m_transforms.empty()) populateTransforms(); + if (!m_transformsPopulated) populateTransforms(); std::set dset; for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); @@ -73,7 +82,7 @@ TransformDescription TransformFactory::getTransformDescription(TransformId id) { - if (m_transforms.empty()) populateTransforms(); + if (!m_transformsPopulated) populateTransforms(); if (m_transforms.find(id) == m_transforms.end()) { return TransformDescription(); @@ -82,10 +91,60 @@ return m_transforms[id]; } +TransformList +TransformFactory::getUninstalledTransformDescriptions() +{ + if (!m_uninstalledTransformsPopulated) populateUninstalledTransforms(); + + std::set dset; + for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin(); + i != m_uninstalledTransforms.end(); ++i) { +// cerr << "inserting transform into set: id = " << i->second.identifier.toStdString() << endl; + dset.insert(i->second); + } + + TransformList list; + for (std::set::const_iterator i = dset.begin(); + i != dset.end(); ++i) { +// cerr << "inserting transform into list: id = " << i->identifier.toStdString() << endl; + list.push_back(*i); + } + + return list; +} + +TransformDescription +TransformFactory::getUninstalledTransformDescription(TransformId id) +{ + if (!m_uninstalledTransformsPopulated) populateUninstalledTransforms(); + + if (m_uninstalledTransforms.find(id) == m_uninstalledTransforms.end()) { + return TransformDescription(); + } + + return m_uninstalledTransforms[id]; +} + +TransformFactory::TransformInstallStatus +TransformFactory::getTransformInstallStatus(TransformId id) +{ + if (!m_transformsPopulated) populateTransforms(); + if (!m_uninstalledTransformsPopulated) populateUninstalledTransforms(); + + if (m_transforms.find(id) != m_transforms.end()) { + return TransformInstalled; + } + if (m_uninstalledTransforms.find(id) != m_uninstalledTransforms.end()) { + return TransformNotInstalled; + } + return TransformUnknown; +} + + std::vector TransformFactory::getAllTransformTypes() { - if (m_transforms.empty()) populateTransforms(); + if (!m_transformsPopulated) populateTransforms(); std::set types; for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); @@ -104,7 +163,7 @@ std::vector TransformFactory::getTransformCategories(QString transformType) { - if (m_transforms.empty()) populateTransforms(); + if (!m_transformsPopulated) populateTransforms(); std::set categories; for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); @@ -131,7 +190,7 @@ std::vector TransformFactory::getTransformMakers(QString transformType) { - if (m_transforms.empty()) populateTransforms(); + if (!m_transformsPopulated) populateTransforms(); std::set makers; for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); @@ -216,6 +275,8 @@ m_transforms[identifier] = desc; } + + m_transformsPopulated = true; } void @@ -448,6 +509,73 @@ } } +void +TransformFactory::populateUninstalledTransforms() +{ + if (!m_uninstalledTransforms.empty()) return; + if (m_transforms.empty()) populateTransforms(); + + //!!! This will be amazingly slow + + QStringList ids = PluginRDFIndexer::getInstance()->getIndexedPluginIds(); + + for (QStringList::const_iterator i = ids.begin(); i != ids.end(); ++i) { + + PluginRDFDescription desc(*i); + + QString name = desc.getPluginName(); +// if (name == "") { +// std::cerr << "TransformFactory::populateUninstalledTransforms: " +// << "No name available for plugin " << i->toStdString() +// << ", skipping" << std::endl; +// continue; +// } + + QString description = desc.getPluginDescription(); + QString maker = desc.getPluginMaker(); + + QStringList oids = desc.getOutputIds(); + + for (QStringList::const_iterator j = oids.begin(); j != oids.end(); ++j) { + + TransformId tid = Transform::getIdentifierForPluginOutput(*i, *j); + + if (m_transforms.find(tid) != m_transforms.end()) { + std::cerr << "TransformFactory::populateUninstalledTransforms: " + << tid.toStdString() << " is installed, skipping" << std::endl; + continue; + } + + std::cerr << "TransformFactory::populateUninstalledTransforms: " + << "adding " << tid.toStdString() << std::endl; + + QString oname = desc.getOutputName(*j); + if (oname == "") oname = *j; + + TransformDescription td; + td.type = tr("Analysis"); //!!! should be enum or something + td.category = ""; + td.identifier = tid; + + if (oids.size() == 1) { + td.name = name; + } else if (name != "") { + td.name = tr("%1: %2").arg(name).arg(oname); + } + + td.friendlyName = name; //!!!??? + td.description = description; + td.longDescription = ""; //!!! + td.maker = maker; + td.units = ""; + td.configurable = false; + + m_uninstalledTransforms[tid] = td; + } + } + + m_uninstalledTransformsPopulated = true; +} Transform TransformFactory::getDefaultTransformFor(TransformId id, size_t rate) @@ -787,27 +915,6 @@ setParametersFromPlugin(t, plugin); delete plugin; } -/* -TransformFactory::SearchResults -TransformFactory::search(QStringList keywords) -{ - SearchResults results; - SearchResults partial; - for (int i = 0; i < keywords.size(); ++i) { - partial = search(keywords[i]); - for (SearchResults::const_iterator j = partial.begin(); - j != partial.end(); ++j) { - if (results.find(j->first) == results.end()) { - results[j->first] = j->second; - } else { - results[j->first].score += j->second.score; - results[j->first].fragments << j->second.fragments; - } - } - } - return results; -} -*/ TransformFactory::SearchResults TransformFactory::search(QString keyword) @@ -828,21 +935,42 @@ } SearchResults results; + TextMatcher matcher; for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); i != m_transforms.end(); ++i) { - Match match; + TextMatcher::Match match; - match.transform = i->first; + match.key = i->first; - searchTest(match, keywords, i->second.type, tr("Plugin type"), 10); - searchTest(match, keywords, i->second.category, tr("Category"), 20); - searchTest(match, keywords, i->second.identifier, tr("System Identifier"), 5); - searchTest(match, keywords, i->second.name, tr("Name"), 30); - searchTest(match, keywords, i->second.description, tr("Description"), 20); - searchTest(match, keywords, i->second.maker, tr("Maker"), 10); - searchTest(match, keywords, i->second.units, tr("Units"), 10); + matcher.test(match, keywords, i->second.type, tr("Plugin type"), 5); + matcher.test(match, keywords, i->second.category, tr("Category"), 20); + matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 6); + matcher.test(match, keywords, i->second.name, tr("Name"), 30); + matcher.test(match, keywords, i->second.description, tr("Description"), 20); + matcher.test(match, keywords, i->second.maker, tr("Maker"), 10); + matcher.test(match, keywords, i->second.units, tr("Units"), 10); + + if (match.score > 0) results[i->first] = match; + } + + if (m_uninstalledTransforms.empty()) populateUninstalledTransforms(); + + for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin(); + i != m_uninstalledTransforms.end(); ++i) { + + TextMatcher::Match match; + + match.key = i->first; + + matcher.test(match, keywords, i->second.type, tr("Plugin type"), 2); + matcher.test(match, keywords, i->second.category, tr("Category"), 10); + matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 3); + matcher.test(match, keywords, i->second.name, tr("Name"), 15); + matcher.test(match, keywords, i->second.description, tr("Description"), 10); + matcher.test(match, keywords, i->second.maker, tr("Maker"), 5); + matcher.test(match, keywords, i->second.units, tr("Units"), 5); if (match.score > 0) results[i->first] = match; } @@ -850,103 +978,3 @@ return results; } -void -TransformFactory::searchTest(Match &match, QStringList keywords, QString text, - QString textType, int score) -{ -/* - if (text.toLower() == keyword.toLower()) { - match.score += score * 1.5; - match.fragments << tr("%1: %2").arg(textType).arg(text); - return; - } -*/ - int len = text.length(); - int prevEnd = 0; - QString fragment; - - while (1) { - - bool first = (prevEnd == 0); - - int idx = -1; - QString keyword; - - for (int ki = 0; ki < keywords.size(); ++ki) { - int midx = text.indexOf(keywords[ki], prevEnd, Qt::CaseInsensitive); - if (midx >= 0 && midx < len) { - if (midx < idx || idx == -1) { - idx = midx; - keyword = keywords[ki]; - } - } - } - - if (idx < 0 || idx >= len) break; - - int klen = keyword.length(); - - if (first) { - match.score += score; - } else { - match.score += score / 4; - } - - int start = idx; - int end = start + klen; - - if (start == 0) match.score += 1; - if (end == len) match.score += 1; - - if (start > prevEnd + 14) { - QString s = text.right((len - start) + 10); - s = XmlExportable::encodeEntities(s.left(10)) + "" + - XmlExportable::encodeEntities(s.left(klen + 10).right(klen)) - + ""; - fragment += tr("...%1").arg(s); - } else { - QString s = text.right(len - prevEnd); - s = XmlExportable::encodeEntities(s.left(start - prevEnd)) + "" + - XmlExportable::encodeEntities(s.left(end - prevEnd).right(klen)) - + ""; - fragment += s; - } - - prevEnd = end; - } - - if (prevEnd > 0 && prevEnd < len) { - int n = len - prevEnd; - fragment += - XmlExportable::encodeEntities(text.right(n).left(n < 8 ? n : 8)); - } - - if (fragment != "") { - match.fragments[textType] = fragment; - } -} - -bool -TransformFactory::Match::operator<(const Match &m) const -{ - if (score != m.score) { - return score < m.score; - } - if (transform != m.transform) { - return transform < m.transform; - } - if (fragments.size() != m.fragments.size()) { - return fragments.size() < m.fragments.size(); - } - - for (FragmentMap::const_iterator - i = fragments.begin(), - j = m.fragments.begin(); - i != fragments.end(); ++i, ++j) { - if (i->first != j->first) return i->first < j->first; - if (i->second != j->second) return i->second < j->second; - } - - return false; -} - diff -r 64e64e304a12 -r ef14acd6d102 transform/TransformFactory.h --- a/transform/TransformFactory.h Mon Oct 13 13:53:05 2008 +0000 +++ b/transform/TransformFactory.h Tue Oct 14 16:36:35 2008 +0000 @@ -18,6 +18,8 @@ #include "TransformDescription.h" +#include "base/TextMatcher.h" + #include #include @@ -31,6 +33,7 @@ Q_OBJECT public: + TransformFactory(); virtual ~TransformFactory(); static TransformFactory *getInstance(); @@ -38,25 +41,22 @@ TransformList getAllTransformDescriptions(); TransformDescription getTransformDescription(TransformId id); + TransformList getUninstalledTransformDescriptions(); + TransformDescription getUninstalledTransformDescription(TransformId id); + + typedef enum { + TransformUnknown, + TransformInstalled, + TransformNotInstalled + } TransformInstallStatus; + + TransformInstallStatus getTransformInstallStatus(TransformId id); + std::vector getAllTransformTypes(); std::vector getTransformCategories(QString transformType); std::vector getTransformMakers(QString transformType); - struct Match - { - TransformId transform; - int score; - typedef std::map FragmentMap; - FragmentMap fragments; - - Match() : score(0) { } - Match(const Match &m) : - transform(m.transform), score(m.score), fragments(m.fragments) { } - - bool operator<(const Match &m) const; // sort by score first - }; - - typedef std::map SearchResults; + typedef std::map SearchResults; SearchResults search(QString keyword); SearchResults search(QStringList keywords); @@ -178,15 +178,18 @@ protected: typedef std::map TransformDescriptionMap; + TransformDescriptionMap m_transforms; + bool m_transformsPopulated; + + TransformDescriptionMap m_uninstalledTransforms; + bool m_uninstalledTransformsPopulated; void populateTransforms(); + void populateUninstalledTransforms(); void populateFeatureExtractionPlugins(TransformDescriptionMap &); void populateRealTimePlugins(TransformDescriptionMap &); - void searchTest(Match &match, QStringList keywords, QString text, - QString textType, int score); - Vamp::PluginBase *instantiateDefaultPluginFor(TransformId id, size_t rate); static TransformFactory *m_instance;