annotate base/TextMatcher.cpp @ 1412:b7a9edee85e0 scale-ticks

Change loop to something that feels more correct, though it makes no difference to the tests here. More tests, one failing.
author Chris Cannam
date Thu, 04 May 2017 08:32:41 +0100
parents ef14acd6d102
children 48e9f538e6e9
rev   line source
Chris@457 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@457 2
Chris@457 3 /*
Chris@457 4 Sonic Visualiser
Chris@457 5 An audio file viewer and annotation editor.
Chris@457 6 Centre for Digital Music, Queen Mary, University of London.
Chris@457 7 This file copyright 2008 QMUL.
Chris@457 8
Chris@457 9 This program is free software; you can redistribute it and/or
Chris@457 10 modify it under the terms of the GNU General Public License as
Chris@457 11 published by the Free Software Foundation; either version 2 of the
Chris@457 12 License, or (at your option) any later version. See the file
Chris@457 13 COPYING included with this distribution for more information.
Chris@457 14 */
Chris@457 15
Chris@457 16 #include "TextMatcher.h"
Chris@457 17
Chris@457 18 TextMatcher::TextMatcher()
Chris@457 19 {
Chris@457 20 }
Chris@457 21
Chris@457 22 TextMatcher::~TextMatcher()
Chris@457 23 {
Chris@457 24 }
Chris@457 25
Chris@457 26 void
Chris@457 27 TextMatcher::test(Match &match, QStringList keywords, QString text,
Chris@457 28 QString textType, int score)
Chris@457 29 {
Chris@457 30 /*
Chris@457 31 if (text.toLower() == keyword.toLower()) {
Chris@457 32 match.score += score * 1.5;
Chris@457 33 match.fragments << tr("%1: <b>%2</b>").arg(textType).arg(text);
Chris@457 34 return;
Chris@457 35 }
Chris@457 36 */
Chris@457 37 int len = text.length();
Chris@457 38 int prevEnd = 0;
Chris@457 39 QString fragment;
Chris@457 40
Chris@457 41 while (1) {
Chris@457 42
Chris@457 43 bool first = (prevEnd == 0);
Chris@457 44
Chris@457 45 int idx = -1;
Chris@457 46 QString keyword;
Chris@457 47
Chris@457 48 for (int ki = 0; ki < keywords.size(); ++ki) {
Chris@457 49 int midx = text.indexOf(keywords[ki], prevEnd, Qt::CaseInsensitive);
Chris@457 50 if (midx >= 0 && midx < len) {
Chris@457 51 if (midx < idx || idx == -1) {
Chris@457 52 idx = midx;
Chris@457 53 keyword = keywords[ki];
Chris@457 54 }
Chris@457 55 }
Chris@457 56 }
Chris@457 57
Chris@457 58 if (idx < 0 || idx >= len) break;
Chris@457 59
Chris@457 60 int klen = keyword.length();
Chris@457 61
Chris@457 62 if (first) {
Chris@457 63 match.score += score;
Chris@457 64 } else {
Chris@457 65 match.score += score / 4;
Chris@457 66 }
Chris@457 67
Chris@457 68 int start = idx;
Chris@457 69 int end = start + klen;
Chris@457 70
Chris@457 71 if (start == 0) match.score += 1;
Chris@457 72 if (end == len) match.score += 1;
Chris@457 73
Chris@457 74 if (start > prevEnd + 14) {
Chris@457 75 QString s = text.right((len - start) + 10);
Chris@457 76 s = XmlExportable::encodeEntities(s.left(10)) + "<b>" +
Chris@457 77 XmlExportable::encodeEntities(s.left(klen + 10).right(klen))
Chris@457 78 + "</b>";
Chris@457 79 fragment += QString("...%1").arg(s);
Chris@457 80 } else {
Chris@457 81 QString s = text.right(len - prevEnd);
Chris@457 82 s = XmlExportable::encodeEntities(s.left(start - prevEnd)) + "<b>" +
Chris@457 83 XmlExportable::encodeEntities(s.left(end - prevEnd).right(klen))
Chris@457 84 + "</b>";
Chris@457 85 fragment += s;
Chris@457 86 }
Chris@457 87
Chris@457 88 prevEnd = end;
Chris@457 89 }
Chris@457 90
Chris@457 91 if (prevEnd > 0 && prevEnd < len) {
Chris@457 92 int n = len - prevEnd;
Chris@457 93 fragment +=
Chris@457 94 XmlExportable::encodeEntities(text.right(n).left(n < 8 ? n : 8));
Chris@457 95 }
Chris@457 96
Chris@457 97 if (fragment != "") {
Chris@457 98 match.fragments[textType] = fragment;
Chris@457 99 }
Chris@457 100 }
Chris@457 101
Chris@457 102 bool
Chris@457 103 TextMatcher::Match::operator<(const Match &m) const
Chris@457 104 {
Chris@457 105 if (score != m.score) {
Chris@457 106 return score < m.score;
Chris@457 107 }
Chris@457 108 if (key != m.key) {
Chris@457 109 return key < m.key;
Chris@457 110 }
Chris@457 111 if (fragments.size() != m.fragments.size()) {
Chris@457 112 return fragments.size() < m.fragments.size();
Chris@457 113 }
Chris@457 114
Chris@457 115 for (FragmentMap::const_iterator
Chris@457 116 i = fragments.begin(),
Chris@457 117 j = m.fragments.begin();
Chris@457 118 i != fragments.end(); ++i, ++j) {
Chris@457 119 if (i->first != j->first) return i->first < j->first;
Chris@457 120 if (i->second != j->second) return i->second < j->second;
Chris@457 121 }
Chris@457 122
Chris@457 123 return false;
Chris@457 124 }