def contentRendered(self, id, classObject, method, args, param, content): if classObject == CharacterDB: if method == 'filterDomainCharacters': chars = content # render page if chars: charLinks = [] for char in chars: charLinks.append( '<a class="character" href="#lookup(%s)">%s</a>' \ % (encodeBase64(char), char)) html = '<span class="character">%s</span>' \ % ' '.join(charLinks) else: html = '<span class="meta">%s</span>' % unicode( i18n('No results for the selected character domain')) self.handwritingResultView.setHtml( '<html><head><title>Results</title>' \ + '<link rel="StyleSheet" href="%s" type="text/css" />' \ % ('file://' + util.getData('style.css')) + '</head>' \ + '<body>%s</body>' % html \ + '</html>')
def getCharacterWithSamePronunciationSection(self, inputString): """Gets a list of characters with the same pronunciation.""" dictResult = self._searchDictionarySamePronunciationAs(inputString) # group by reading and character charDict = {} for char, charAlt, reading, translation in dictResult: if reading not in charDict: charDict[reading] = {} if char not in charDict[reading]: charDict[reading][char] = [] charDict[reading][char].append( (char, charAlt, reading, translation)) if charDict: html = '' for reading in sorted(charDict.keys(), reverse=True): characterLinks = [] for char in charDict[reading]: characterLinks.append('<li><span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char) \ + '</span>%s</li>' % self._getDictionaryInfo(char, charDict[reading][char])) html += '<h3>%s</h3>' % reading \ + '<ul>%s</ul>' % ' '.join(characterLinks) return '<div class="samereading">' + html + '</div>' else: return '<span class="meta">%s</span>' % gettext('No entries found')
def _getVocabularyTable(dictResult, useAltFunc=lambda x, y: False, smallSpacing=False): htmlList = [] for charString, charStringAlt, reading, translation in dictResult: if charString != charStringAlt \ and useAltFunc(charString, charStringAlt): displayCharString \ = DictionaryView._getDisplayCharStringRepresentation( charString, charStringAlt, forceBlocksOfFor=not smallSpacing) else: displayCharString \ = DictionaryView._getDisplayCharStringRepresentation( charString, forceBlocksOfFor=not smallSpacing) if len(charString) > 1: page = 'word' else: page = 'character' htmlList.append('<tr class="vocabularyEntry">' \ + '<td class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(page + ':' + charString), displayCharString) + '</td>' \ + '<td class="reading">%s</td>' \ % DictionaryView._getReadingRepresentation(reading, forceBlocksOfFor=not smallSpacing) \ + '<td class="translation">%s</td>' \ % DictionaryView._getTranslationRepresentation(translation) \ + '</tr>') return '\n'.join(htmlList)
def getVocabularySection(self, inputString): # we only need 4 entries, but because of double entries we might end up # with some being merged, also need +1 to show the "more entries" # play safe and select 10 # TODO true contains dictResult = self._dictionary.getForHeadword( '*' + inputString + '*', orderBy=['Weight'], limit=10) htmlList = [] if dictResult: htmlList.append('<table class="vocabulary">') # don't display alternative if the charString is found # in the given string showAlternative = lambda charString, _: \ (charString.find(inputString) < 0) htmlList.append(self._getVocabularyTable(dictResult[:4], useAltFunc=showAlternative)) htmlList.append('</table>') if len(dictResult) > 4: htmlList.append( '<a class="meta" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64('vocabulary' \ + ':' + inputString), gettext('All entries...'))) else: htmlList.append('<span class="meta">%s</span>' \ % gettext('No entries found')) return '\n'.join(htmlList)
def getMiniGeneralWordSection(self, inputString): characterLinks = [] for char in inputString: characterLinks.append( '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char)) return '<span class="headwordMini">%s</span>' % ''.join(characterLinks)
def getLayer(decompTree, isSubTree=False): if type(decompTree) != type(()): char = decompTree if char != u'?': if char in seenEntry: return '<span class="entry">' \ + '<span class="character">%s</span>' % char \ + '</span>' else: seenEntry.add(char) return '<span class="entry"><span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char) \ + '</span>%s</span>' % self._getDictionaryInfo(char) else: return '<span class="entry meta">%s</span>' \ % gettext('unknown') else: layout, char, tree = decompTree if char: if isSubTree: head = layout + '<span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char) \ + '</span>' \ + self._getDictionaryInfo(char) else: # don't show dictionary information for the root element head = layout \ + '<span class="character">%s</span>' % char else: head = layout subLayer = [] for idx, entry in enumerate(tree): cssClass = 'decomposition' if idx == len(tree) - 1: cssClass += ' last' subLayer.append('<li class="%s">%s</li>' \ % (cssClass, getLayer(entry, isSubTree=True))) return '<span class="entry">%s<ul>%s</ul></span>' \ % (head, ''.join(subLayer))
def getComponentSearchTable(self, components=[], includeEquivalentRadicalForms=False, includeSimilarCharacters=False): """ Gets a table of minimal components for searching characters by component. Annotates given characters and characters that would result in zero results if selected. """ componentsByStrokeCount = self.charDB.minimalCharacterComponents # TODO replace selected = components #selected = set([self.charDB.preferRadicalFormForCharacter(char) \ #for char in components]) if components: currentResultRadicals = self.charDB.getComponentsWithResults( components, includeEquivalentRadicalForms=includeEquivalentRadicalForms, includeSimilarCharacters=includeSimilarCharacters) else: currentResultRadicals = None htmlList = [] htmlList.append('<table class="component">') strokeCountList = componentsByStrokeCount.keys() strokeCountList.sort() for strokeCount in strokeCountList: htmlList.append('<tr><th>%d</th><td>' % strokeCount) for form in sorted(componentsByStrokeCount[strokeCount]): if form in selected: formClass = 'selectedComponent' elif currentResultRadicals != None \ and form not in currentResultRadicals: formClass = 'zeroResultComponent' else: formClass = '' formBase64 = util.encodeBase64(form) htmlList.append( '<a class="character" href="#component(%s)">' % formBase64 \ + '<span class="component %s" id="c%s">%s</span>' \ % (formClass, formBase64, form) \ + '</a>') htmlList.append('</td></tr>') htmlList.append('</table>') return "\n".join(htmlList)
def getComponentSearchResult(self, components, includeEquivalentRadicalForms=False, includeSimilarCharacters=False): """Gets a list of characters containing the given components.""" chars = self.charDB.getCharactersForComponents(components, includeEquivalentRadicalForms=includeEquivalentRadicalForms, includeSimilarCharacters=includeSimilarCharacters) if chars: charLinks = [] for char in chars: charLinks.append( '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char)) html = '<span class="character">%s</span>' % ' '.join(charLinks) else: html = '<p class="meta">%s</p>' % gettext('No entries') return html, len(chars)
def getCharacterWithComponentSection(self, inputString): """Gets a list of characters with the given character as component.""" chars = self._dictionary.charDB.getCharactersForComponents([inputString]) if inputString in chars: chars.remove(inputString) if chars: characterLinks = [] for char in chars: #characterLinks.append( #'<a class="character" href="#lookup(%s)">%s</a>' \ #% (util.encodeBase64(char), char)) characterLinks.append('<li><span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char) \ + '</span>%s</li>' % self._getDictionaryInfo(char)) return '<div class="components"><ul>%s</ul></div>' \ % ' '.join(characterLinks) else: return '<span class="meta">%s</span>' % gettext('No entries found')
def getVariantSection(self, inputString): variantEntries = self._dictionary.getVariantsForHeadword(inputString) variants = set([e.Headword for e in variantEntries if e.Headword != inputString]) variantLinks = [] for variant in variants: if variant == inputString: # e.g. 台 is listed as it's on variant, Unihan's policy continue variantLinks.append('<span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(variant), variant) \ + '</span>') if not variantLinks: return '' else: return '<div class="variantSection">'\ + '<span class="meta">%s</span> ' \ % ngettext("See variant:", "See variants:", len(variants)) \ + ', '.join(variantLinks) \ + '</div>'
def getSimilarsSection(self, inputString): """Returns a section of headwords with similar shape.""" similarEntries = self._dictionary.getSimilarsForHeadword(inputString, orderBy=['Reading']) #orderBy=['Reading', 'Headword']) # TODO doesn't work for CEDICT similars = [e.Headword for e in similarEntries if e.Headword != inputString] similarLinks = [] for similar in similars: similarLinks.append('<span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(similar), similar) \ + '</span>') if not similarLinks: return '' else: return '<div class="similarSection">'\ + '<span class="meta">%s</span> ' \ % ngettext("See similar headword:", "See similar headword:", len(similarLinks)) \ + ', '.join(similarLinks) \ + '</div>'
def getVocabularySearchSection(self, inputString): """ Gets the search results for the given string including exact maches and a shortened list of similar results and results including the given string. """ htmlList = [] htmlList.append('<table class="search">') # exact hits exactDictResult = self._dictionary.getFor(inputString, orderBy=['Weight']) if exactDictResult: htmlList.append('<tr><td colspan="3"><h3>%s</h3></td></tr>' \ % gettext('Matches')) # match against input string with regular expression htmlList.append(self._getVocabularyTable(exactDictResult, useAltFunc=lambda x, y: \ self._matchesInput(inputString, y) \ and not self._matchesInput(inputString, x))) # similar pronunciation similarDictResult = self._dictionary.getForSimilarReading( inputString, orderBy=['Weight'], limit=5) if similarDictResult: htmlList.append('<tr><td colspan="3"><h3>%s</h3></td></tr>' \ % gettext('Similar pronunciations')) htmlList.append(self._getVocabularyTable(similarDictResult[:4])) if len(similarDictResult) > 4: htmlList.append('<tr><td colspan="3">' \ + '<a class="meta" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64('similar' + ':' \ + inputString), gettext('All entries...')) + '</td></tr>') # other matches # TODO optimize and include other matches in exact run, after all # translation will be all searched with LIKE '% ... %' otherDictResult = self._dictionary.getFor('*' + inputString + '*', orderBy=['Weight']) if otherDictResult: htmlList.append('<tr><td colspan="3"><h3>%s</h3></td></tr>' \ % gettext('Other matches')) augmentedInput = '*' + inputString + '*' htmlList.append(self._getVocabularyTable(otherDictResult[:4], useAltFunc=lambda x, y: \ self._matchesInput(inputString, y) \ and not self._matchesInput(inputString, x))) if len(otherDictResult) > 4: htmlList.append('<tr><td colspan="3">' \ + '<a class="meta" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64('othervocabulary' + ':' \ + inputString), gettext('All entries...')) + '</td></tr>') # handle 0 result cases if not exactDictResult: if not similarDictResult and not otherDictResult: htmlList.append('<tr><td colspan="3">'\ + '<span class="meta">%s</span>' \ % gettext('No matches found') \ + '</td></tr>') else: htmlList.insert(0, '<tr><td colspan="3">'\ + '<span class="meta">%s</span>' \ % gettext('No exact matches found') \ + '</td></tr>') htmlList.append('</table>') return '\n'.join(htmlList)
def getMeaningSection(self, inputString): """ Gets a list of entries for the given character string, sorted by reading with annotated alternative character writing, audio and vocab handle. """ def getAudio(filePath): return (' <a class="audio" href="#play(%s)">%s</a>' % (urllib.quote(filePath.encode('utf8')), gettext('Listen'))) #audioHtml = ' <a class="audio" href="#" onclick="new Audio(\'%s\').play(); return false;">%s</a>' \ #% (urllib.quote(filePath.encode('utf8')), gettext('Listen')) #audioHtml = ' <audio src="%s" id="audio_%s" autoplay=false></audio><a class="audio" href="#" onClick="document.getElementById(\'audio_%s\').play(); return false;">%s</a>' \ #% (urllib.quote(filePath.encode('utf8')), reading, reading, gettext('Listen')) readings = [] translations = {} translationIndex = {} alternativeHeadwords = [] alternativeHeadwordIndex = {} # TODO index calculation is broken, e.g. 说 # TODO cache dictResult = self._dictionary.getForHeadword(inputString) for idx, entry in enumerate(dictResult): _, charStringAlt, reading, translation = entry # get unique sorted readings if reading not in readings: readings.append(reading) # save translation, take care of double entries if reading not in translations: translations[reading] = [] translationIndex[reading] = idx if translation not in translations[reading]: translations[reading].append(translation) # save alternative headword, save link to translation if charStringAlt not in alternativeHeadwords: alternativeHeadwords.append(charStringAlt) alternativeHeadwordIndex[charStringAlt] = [] # save link to translation alternativeHeadwordIndex[charStringAlt].append( translations[reading].index(translation)) htmlList = [] # show alternative headword when a) several different ones exist, # b) several entries exist, c) different to headword if self.showAlternativeHeadwords and alternativeHeadwords \ and (len(alternativeHeadwords) > 1 \ or inputString not in alternativeHeadwords): altHeadwordHtml = [] for altHeadword in alternativeHeadwords: if len(inputString) > 1: className = "word" else: className = "character" entry = '<span class="%s">' % className \ + '<a class="character" href="#lookup(%s)">%s</a></span>' \ % (util.encodeBase64(altHeadword), altHeadword) if len(readings) > 1 or len(translations[readings[0]]) > 1: indices = [str(i + 1) for i \ in alternativeHeadwordIndex[altHeadword]] altHeadwordHtml.append('<li>' + entry \ + '<span class="alternativeHeadwordIndex">%s</span>' \ % ' '.join(indices) \ + '</li>') else: altHeadwordHtml.append('<li>%s</li>' % entry) htmlList.append('<p><ul class="alternativeHeadword">%s</ul></p>' \ % ''.join(altHeadwordHtml)) # show entries if readings: htmlList.append('<table class="meaning">') for reading in readings: # get audio if available #filePath, audioHtml = getAudio(reading) filePath, audioHtml = ('', '') # TODO # get reading readingEntry = '<a class="reading" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(reading), self._getReadingRepresentation(reading, forceBlocksOfFor=False)) # get translations translationEntries = [] for translation in translations[reading]: translationEntries.append('<li class="translation">' \ + '<a class="addVocabulary" ' \ + 'href="#addvocab(%s;%s;%s;%s)"></a>' \ % (util.encodeBase64(inputString), util.encodeBase64(reading), util.encodeBase64(translation), util.encodeBase64(filePath)) \ + self._getTranslationRepresentation(translation) \ + '</li>') translationString = ''.join(translationEntries) # create table entry htmlList.append('<tr class="meaningEntry">' \ + '<td class="reading">%s%s</td>' \ % (readingEntry, audioHtml) \ + '<td><ol start="%d">%s</ol></td>' \ % (translationIndex[reading] + 1, translationString) \ + '</tr>') htmlList.append('</table>') else: htmlList.append('<span class="meta">%s</span>' \ % gettext('No dictionary entries found')) return '\n'.join(htmlList)
def getCharacterForRadical(self, radicalIndex, includeAllComponents=False): """Gets a list of characters classified under the given radical.""" # group by residual stroke count characterGroups = self.charDB.getCharacterListForKangxiRadicalIndex( radicalIndex, includeAllComponents=includeAllComponents) htmlList = [] # show main radical form htmlList.append('<h3>%s</h3>' \ % (gettext('Radical %(radical_index)d') \ % {'radical_index': radicalIndex})) charLinks = [] for strokeCount in sorted(characterGroups['radical'].keys()): for char in sorted(characterGroups['radical'][strokeCount]): charLinks.append('<span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char) \ + '</span>') htmlList.append(' '.join(charLinks)) radicalEntryDict = self.charDB.getRadicalDictionaryEntries() _, meaning = radicalEntryDict.get(radicalIndex, (None, None)) if meaning: htmlList.append(' <span class="translation">%s</span>' % meaning) radicalForms = self.charDB.kangxiRadicalForms _, strokeCount, _, _ = radicalForms[radicalIndex] if strokeCount: htmlList.append(' <span class="strokecount">(%s)</span>' \ % (ngettext('%(strokes)d stroke', '%(strokes)d strokes', strokeCount) % {'strokes': strokeCount})) htmlList.append('<h3>%s</h3>' % gettext('Characters')) # list sorted by residual stroke count if not characterGroups[None]: htmlList.append('<span class="meta">%s</span>' \ % gettext('no results found for the selected character domain')) else: htmlList.append('<table class="searchResult">') for strokeCount in sorted(characterGroups[None].keys()): if type(strokeCount) not in (type(0), type(0L)): # sort out non stroke count groups continue htmlList.append('<tr>' \ + '<th class="strokeCount">+%s</th><td>' % strokeCount) charLinks = [] for char in sorted(characterGroups[None][strokeCount]): charLinks.append('<span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char) \ + '</span>') htmlList.append(' '.join(charLinks)) htmlList.append('</td></tr>') # Add characters without stroke count information if None in characterGroups[None]: htmlList.append('<tr>' \ + '<th class="strokeCount">%s</th><td>' % gettext('Unknown')) charLinks = [] for char in sorted(characterGroups[None][None]): charLinks.append('<span class="character">' \ + '<a class="character" href="#lookup(%s)">%s</a>' \ % (util.encodeBase64(char), char) \ + '</span>') htmlList.append(' '.join(charLinks)) htmlList.append('</td></tr>') htmlList.append('</table>') return "\n".join(htmlList)