<commit_before># coding: utf-8
from collections import Counter
from math import pi as PI
from os import path

import numpy as np
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QItemSelection, QItemSelectionModel

from Orange.widgets import widget, gui, settings
from Orange.widgets.utils.itemmodels import PyTableModel
from orangecontrib.text.corpus import Corpus
from orangecontrib.text.topics import Topics


class SelectedWords(set):
    def __init__(self, widget):
        self.widget = widget

    def _update_webview(self):
        self.widget.webview.evalJS('SELECTED_WORDS = {};'.format(list(self)))

    def _update_filter(self):
        filter = set()
        if self.widget.corpus is not None:
            for i, doc in enumerate(self.widget.corpus.ngrams):
                if any(i in doc for i in self):
                    filter.add(i)
        if filter:
            self.widget.send(Output.CORPUS, self.widget.corpus[list(filter), :])
        else:
            self.widget.send(Output.CORPUS, None)

    def add(self, word):
        if word not in self:
            super().add(word)
            self._update_webview()
            self._update_filter()

    def remove(self, word):
        if word in self:
            super().remove(word)
            self._update_webview()
            self._update_filter()

    def clear(self):
        super().clear()
        self._update_webview()
        self._update_filter()
        self.widget.tableview.clearSelection()


class Output:
    CORPUS = 'Corpus'


class OWWordCloud(widget.OWWidget):
    name = "Word Cloud"
    priority = 10000
    icon = "icons/WordCloud.svg"
    inputs = [
        ('Topics', Topics, 'on_topics_change'),
        (Output.CORPUS, Corpus, 'on_corpus_change'),
    ]
    outputs = [('Corpus', Corpus)]

    graph_name = 'webview'

    selected_words = settings.ContextSetting(SelectedWords('whatevar (?)'))
    words_color = settings.Setting(True)
    words_tilt = settings.Setting(0)

    def __init__(self):
        super().__init__()
        self.n_topic_words = 0
        self.documents_info_str = ''
        self.selected_words = SelectedWords(self)
        self.webview = None
        self.topics = None
        self.corpus = None
        self.corpus_counter = None
        self._create_layout()

    @QtCore.pyqtSlot(str, result=str)
    def word_clicked(self, word):
        """Called from JavaScript"""
        if not word:
            self.selected_words.clear()
            return ''
        selection = QItemSelection()
        for i, row in enumerate(self.tablemodel):
            for j, val in enumerate(row):
                if val == word:
                    index = self.tablemodel.index(i, j)
                    selection.select(index, index)
        if word not in self.selected_words:
            self.selected_words.add(word)
            self.tableview.selectionModel().select(
                selection, QItemSelectionModel.Select | QItemSelectionModel.Rows)
            return 'selected'
        else:
            self.selected_words.remove(word)
            self.tableview.selectionModel().select(
                selection, QItemSelectionModel.Deselect | QItemSelectionModel.Rows)
            return ''

    def _new_webview(self):
        HTML = '''
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
html, body {margin:0px;padding:0px;width:100%;height:100%;}
span:hover {color:OrangeRed !important}
span.selected {color:red !important}
</style>
</head>
<body id="canvas"></body>
</html>'''
        if self.webview:
            self.mainArea.layout().removeWidget(self.webview)
        self.webview = gui.WebviewWidget(self.mainArea, self, HTML, debug=True)<commit_msg>OWWordCloud: instantiate WebView differently (fwd-compat)<commit_after># coding: utf-8
from collections import Counter
from math import pi as PI
from os import path

import numpy as np
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QItemSelection, QItemSelectionModel

from Orange.widgets import widget, gui, settings
from Orange.widgets.utils.itemmodels import PyTableModel
from orangecontrib.text.corpus import Corpus
from orangecontrib.text.topics import Topics


class SelectedWords(set):
    def __init__(self, widget):
        self.widget = widget

    def _update_webview(self):
        self.widget.webview.evalJS('SELECTED_WORDS = {};'.format(list(self)))

    def _update_filter(self):
        filter = set()
        if self.widget.corpus is not None:
            for i, doc in enumerate(self.widget.corpus.ngrams):
                if any(i in doc for i in self):
                    filter.add(i)
        if filter:
            self.widget.send(Output.CORPUS, self.widget.corpus[list(filter), :])
        else:
            self.widget.send(Output.CORPUS, None)

    def add(self, word):
        if word not in self:
            super().add(word)
            self._update_webview()
            self._update_filter()

    def remove(self, word):
        if word in self:
            super().remove(word)
            self._update_webview()
            self._update_filter()

    def clear(self):
        super().clear()
        self._update_webview()
        self._update_filter()
        self.widget.tableview.clearSelection()


class Output:
    CORPUS = 'Corpus'


class OWWordCloud(widget.OWWidget):
    name = "Word Cloud"
    priority = 10000
    icon = "icons/WordCloud.svg"
    inputs = [
        ('Topics', Topics, 'on_topics_change'),
        (Output.CORPUS, Corpus, 'on_corpus_change'),
    ]
    outputs = [('Corpus', Corpus)]

    graph_name = 'webview'

    selected_words = settings.ContextSetting(SelectedWords('whatevar (?)'))
    words_color = settings.Setting(True)
    words_tilt = settings.Setting(0)

    def __init__(self):
        super().__init__()
        self.n_topic_words = 0
        self.documents_info_str = ''
        self.selected_words = SelectedWords(self)
        self.webview = None
        self.topics = None
        self.corpus = None
        self.corpus_counter = None
        self._create_layout()

    @QtCore.pyqtSlot(str, result=str)
    def word_clicked(self, word):
        """Called from JavaScript"""
        if not word:
            self.selected_words.clear()
            return ''
        selection = QItemSelection()
        for i, row in enumerate(self.tablemodel):
            for j, val in enumerate(row):
                if val == word:
                    index = self.tablemodel.index(i, j)
                    selection.select(index, index)
        if word not in self.selected_words:
            self.selected_words.add(word)
            self.tableview.selectionModel().select(
                selection, QItemSelectionModel.Select | QItemSelectionModel.Rows)
            return 'selected'
        else:
            self.selected_words.remove(word)
            self.tableview.selectionModel().select(
                selection, QItemSelectionModel.Deselect | QItemSelectionModel.Rows)
            return ''

    def _new_webview(self):
        HTML = '''
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
html, body {margin:0px;padding:0px;width:100%;height:100%;}
span:hover {color:OrangeRed !important}
span.selected {color:red !important}
</style>
</head>
<body id="canvas"></body>
</html>'''
        if self.webview:
            self.mainArea.layout().removeWidget(self.webview)
        webview = self.webview = gui.WebviewWidget(self.mainArea, self, debug=False)
        webview.setHtml(HTML)
        self.mainArea.layout().addWidget(webview)
{'fraction_non_alphanumeric': 0.10954575378538513, 'fraction_numerical': 0.005266622778143515, 'mean_word_length': 2.435549525101764, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '400315', 'n_tokens_mistral': 2321, 'n_tokens_neox': 2216, 'n_words': 511}