Esempio n. 1
0
    def __init__(self, *args):
        QtGui.QMainWindow.__init__(self, *args)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.texteditInterlinear.setReadOnly(True)

        self.initConnects()
        self.initSettings()
        self.project = PoioProject(os.getcwd())
        self.ui.listFiles.setModel(self.project)
        self.initCorpusReader()
        self.currentFilter = AnnotationTreeFilter()
Esempio n. 2
0
    def __init__(self, *args):
        """
        Initialize Main Window
        """
        QtGui.QMainWindow.__init__(self, *args)

        # self.reset_data_structure_type(poioapi.data.GRAID)
        self.vertical_position_of_file = {}

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.init_connects()
        self.init_settings()
        self.project = PoioProject(os.getcwd())
        self.ui.listFiles.setModel(self.project)
        self.init_corpus()

        self.add_search_tab()
    def __init__(self, *args):
        """
        The consctructor of the main application object, i.e. the main window.
        Calls a lot of other init methods.
        """
        QtGui.QMainWindow.__init__(self, *args)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.init_vars()
        self.init_connects()
        self.init_settings()

        self.init = 0

        self.project = PoioProject(os.getcwd())
        self.ui.listFiles.setModel(self.project)
        self.ui.projectManager.setShown(False)
        self.ui.projectBtn.setStyleSheet(""" QPushButton#projectBtn
                                            {
                                                border-style: outset;
                                                border-width: 1px;
                                                border-color: black;
                                                padding: 1px;
                                            }
                                            QPushButton#projectBtn:checked
                                            {
                                                background-color: lightblue;
                                                border-style: inset;
                                                border-width: 2px;
                                            }""")

        self.ui.textedit.append_title(
            self.tr("Please create or open a file..."))

        self._dialog_find_and_replace = FindReplaceDialog(self)
        self._dialog_find_and_replace.setModal(False)
        self._dialog_find_and_replace.set_text_edit(self.ui.textedit)

        self._dialog_find = FindDialog(self)
        self._dialog_find.setModal(False)
        self._dialog_find.set_text_edit(self.ui.textedit)
Esempio n. 4
0
class PoioAnalyzer(QtGui.QMainWindow):
    """The main window of the PoioAnalyzer application."""

    def __init__(self, *args):
        """
        Initialize Main Window
        """
        QtGui.QMainWindow.__init__(self, *args)

        # self.reset_data_structure_type(poioapi.data.GRAID)
        self.vertical_position_of_file = {}

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.init_connects()
        self.init_settings()
        self.project = PoioProject(os.getcwd())
        self.ui.listFiles.setModel(self.project)
        self.init_corpus()

        self.add_search_tab()

    def init_corpus(self):
        """
        Initializes an empty corpus.
        """
        # print sys.path
        self.corpus = poioapi.corpus.CorpusGraphs()

    def init_connects(self):
        """
        Initializes all signal/slots connections of the application.
        """
        # Menu buttons
        self.ui.actionPrint.triggered.connect(self.printdoc)
        self.ui.actionQuit.triggered.connect(self.close)
        self.ui.actionAboutPoioAnalyzer.triggered.connect(self.about_dialog)
        self.ui.actionZoom_In.triggered.connect(self.zoom_in)
        self.ui.actionZoom_Out.triggered.connect(self.zoom_out)
        self.ui.actionReset_Zoom.triggered.connect(self.reset_zoom)

        # Push Buttons
        self.ui.buttonAddFiles.pressed.connect(self.add_files)
        self.ui.buttonRemoveFiles.pressed.connect(self.remove_files)

        # Filter and Search
        self.ui.buttonSearch.pressed.connect(self.apply_filter)
        self.ui.buttonCloseThisSearch.pressed.connect(self.search_tab_closed)
        self.ui.buttonClearThisSearch.pressed.connect(self.search_tab_cleared)
        self.ui.tabWidget.currentChanged.connect(self.search_tab_changed)

        self.ui.listFiles.activated.connect(self.set_current_file_in_result_view)
        self.ui.actionExportSearchResult.triggered.connect(self.export_search_results)

        # Quick Search
        # QtCore.QObject.connect(self.ui.actionQuickSearch, QtCore.SIGNAL("triggered()"), self.ui.lineeditQuickSearch.setFocus)
        # QtCore.QObject.connect(self.ui.lineeditQuickSearch, QtCore.SIGNAL("textChanged(const QString &)"), self.findFromStart)
        # QtCore.QObject.connect(self.ui.lineeditQuickSearch, QtCore.SIGNAL("returnPressed()"), self.findNext)

    def init_settings(self):
        """
        Initialize QSettings;
        Set default zoom to 100%
        """
        QtCore.QCoreApplication.setOrganizationName("Interdisciplinary Centre for Social and Language Documentation")
        QtCore.QCoreApplication.setOrganizationDomain("cidles.eu")
        QtCore.QCoreApplication.setApplicationName("PoioAnalyzer")
        settings = QtCore.QSettings()
        settings.setValue("FontZoom", 100)

    # def reset_data_structure_type(self, data_structure_type):
    #    self.data_structure_type = data_structure_type
    #    self.structure_type_handler = poioapi.data.data_structure_handler_for_type(
    #        data_structure_type
    #    )

    def remove_files(self):
        """
        Remove files from the "Added files list"
        """
        countRemoved = 0
        for i in self.ui.listFiles.selectedIndexes():
            self.project.removeFilePathAt(i.row() - countRemoved)
            countRemoved = countRemoved + 1
        self.init_corpus()
        self.project.setAllFilesAsNew()
        self.update_corpus_reader()
        self.update_result_view()

    def add_files(self):
        """
        Loads the file as filepath;
        Tells the user the time it took to load the file selected.
        """
        # PySide version
        # filepaths, types = QtGui.QFileDialog.getOpenFileNames(self, self.tr("Add Files"), "", self.tr("Elan files (*.eaf);;Toolbox files (*.txt);;All files (*.*)"))
        # PyQt version
        filepaths = QtGui.QFileDialog.getOpenFileNames(
            self,
            self.tr("Add Files"),
            "",
            self.tr("Elan files (*.eaf);;Pickle files (*.pickle);;Typecraft files (*.xml)"),
        )
        # filepaths = QtGui.QFileDialog.getOpenFileNames(self, self.tr("Add Files"), "", self.tr("Elan files (*.eaf);;Toolbox files (*.txt);;Kura files (*.xml);;All files (*.*)"))
        self.project.addFilePaths(filepaths)
        start = time.time()
        self.update_corpus_reader()
        end = time.time()
        print("Time elapsed = ", end - start, "seconds")
        start = time.time()
        self.update_result_view()
        end = time.time()
        print("Time elapsed = ", end - start, "seconds")
        self.update_search_tabs_with_tier_names()
        self.apply_filter()

    def update_corpus_reader(self):
        """
        Updates the shown opened files view
        """
        itemsCount = self.project.rowCount()
        progress = QtGui.QProgressDialog(self.tr("Loading Files..."), self.tr("Abort"), 0, itemsCount, self.parent())
        progress.setWindowModality(QtCore.Qt.WindowModal)
        incompatible_files = []
        for i in range(itemsCount):
            progress.setValue(i)
            poiofile = self.project.poioFileAt(i)
            if poiofile.is_new:
                # print poiofile.filepath
                try:
                    self.corpus.add_item(poiofile.filepath, poiofile.type)
                except poioapi.data.UnknownFileFormatError:
                    incompatible_files.append(poiofile.filepath)
                poiofile.is_new = False
            if progress.wasCanceled():
                self.init_corpus()
                break
        progress.setValue(itemsCount)
        if len(incompatible_files) > 0:
            QtGui.QMessageBox.warning(
                self,
                "Cannot add files",
                "The following files could not be added to the project:"
                "<br/><br/><b>{0}</b><br/><br/>The file format was not "
                "recognized.<br/><b>The file will not be diplayed in the "
                "search result view</b>.".format(", ".join(incompatible_files)),
            )

    def set_current_file_in_result_view(self, modelIndex):
        """
        Sets what shows up in the result view

        ...

        Parameters
        ----------
        modelIndex :
        """
        e_id = "#file_{0}".format(modelIndex.row())
        e = self.ui.webviewResult.page().mainFrame().findFirstElement(e_id)
        if not e.isNull():
            e.evaluateJavaScript("this.scrollIntoView(true);")

    def update_result_view(self):
        """
        Updates the view screen with the refreshed data and zoom settings
        """
        settings = QtCore.QSettings()
        html = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>\n'
        i = 0
        for filepath, annotationgraph in self.corpus:
            html += '<h1 id="file_{1}">{0}</h1>\n'.format(os.path.basename(str(filepath)), i)
            html += annotationgraph.as_html_table(True, False)
            i += 1
        html += "</body></html>"

        # self.ui.webviewResult.settings().setUserStyleSheetUrl(
        #    QtCore.QUrl(":/css/css/resultview.css")) #.setStyleSheet("td { border: 1px solid black; }")

        # stylesheet_url = QtCore.QUrl.fromLocalFile("h:/ProjectsWin/git-github/Poio/ui/css/resultview.css")

        css = QtCore.QByteArray(
            "td { border: 1px solid black; }\ntable { margin-top: 10px; }\ntd.element_id { margin-left: 10px; margin-right: 10px; font-weight:bold; }\ntd.ann_type { margin-left: 10px; margin-right: 10px; font-variant:small-caps; }\nbody {}"
        )
        if sys.version_info < (3, 0):
            zoom = str(settings.value("FontZoom").toInt()[0])
            css = QtCore.QByteArray(
                "td { font-size: "
                + zoom
                + "%; border: 1px solid black; }\ntable { margin-top: 10px; }\ntd.element_id { margin-left: 10px; margin-right: 10px; font-weight:bold; }\ntd.ann_type { margin-left: 10px; margin-right: 10px; font-variant:small-caps; }\nbody { font-size: "
                + zoom
                + "%; }"
            )
        else:
            zoom = str(settings.value("FontZoom"))
            self.ui.webviewResult.setTextSizeMultiplier(int(zoom) / 100)

        self.ui.webviewResult.settings().setUserStyleSheetUrl(
            QtCore.QUrl("data:text/css;charset=utf-8;base64," + str(css.toBase64()))
        )
        self.ui.webviewResult.setHtml(html)

    def zoom_in(self):
        """
        Increase the zoom setting by 10 % when the menu button is clicked
        until the 200% zoom limit is reached
        """
        settings = QtCore.QSettings()
        if sys.version_info < (3, 0):
            currentzoom = settings.value("FontZoom").toInt()[0]
        else:
            currentzoom = settings.value("FontZoom")
        if currentzoom < 200:
            zoom = currentzoom + 10
            settings.setValue("FontZoom", zoom)
            self.update_result_view()

    def zoom_out(self):
        """
        Decreases the zoom setting by 10 % when the menu button is clicked
        until the 50% zoom limit is reached
        """
        settings = QtCore.QSettings()
        if sys.version_info < (3, 0):
            currentzoom = settings.value("FontZoom").toInt()[0]
        else:
            currentzoom = settings.value("FontZoom")
        if currentzoom > 50:
            zoom = currentzoom - 10
            settings.setValue("FontZoom", zoom)
            self.update_result_view()

    def reset_zoom(self):
        """
        Resets the zoom setting to the default value of 100%
        """
        settings = QtCore.QSettings()
        settings.setValue("FontZoom", 100)
        self.update_result_view()

    def printdoc(self):
        """
        Prints the document in the view
        """
        printer = QPrinter()

        setup = QPageSetupDialog(printer)
        setup.setWindowTitle("Print - Page Settings")

        if setup.exec_() == QDialog.Accepted:
            dialog = QPrintDialog(printer, self)
            dialog.setWindowTitle("Print Document")

            if dialog.exec_() == QDialog.Accepted:
                self.ui.webviewResult.print_(printer)

    def export_search_results(self):
        """
        Exports the current annotationtree as HTML
        """

        export_file = QtGui.QFileDialog.getSaveFileName(
            self, self.tr("Export Search Result"), "", self.tr("HTML file (*.html)")
        )
        export_file = str(export_file)
        OUT = codecs.open(export_file, "w", "utf-8")
        html = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>\n'
        for filepath, annotation_graph in self.corpus:
            html += "<h1>{0}</h1>\n".format(os.path.basename(filepath))
            html += annotation_graph.as_html_table(True, False)
        html += "</body></html>"
        OUT.write(html)
        OUT.close()

    # def findFromStart(self, exp):
    #    self.ui.texteditInterlinear.setTextCursor(QtGui.QTextCursor(self.ui.texteditInterlinear.document()))
    #    if not self.ui.texteditInterlinear.find(exp) and exp != "":
    #        self.statusBar().showMessage(self.tr("No match found."), 2000)

    # def findNext(self):
    #    found = self.ui.texteditInterlinear.find(self.ui.lineeditQuickSearch.text())
    #    if not found:
    #        self.statusBar().showMessage(self.tr("Restarting search from beginning of document."), 2000)
    #        found = self.findFromStart(self.ui.lineeditQuickSearch.text())
    #    return found

    def apply_filter(self):
        """
        Check for the search options and update the resul view
        """
        for _, annotation_graph in self.corpus:
            annotation_graph.init_filters()

        for i in range(0, self.ui.tabWidget.currentIndex() + 1):
            search_terms = dict()
            for tier in self.corpus.tier_names:
                inputfield = self.ui.tabWidget.findChild(QtGui.QLineEdit, "lineedit_{0}_{1}".format(tier, i + 1))
                if inputfield:
                    search_terms[tier] = str(inputfield.text())
                # currentFilter.set_filter_for_type(ann_type, str(inputfield.text()))

            checkbox = self.ui.tabWidget.findChild(QtGui.QCheckBox, "checkboxInvert_%i" % (i + 1))
            is_inverted = checkbox.isChecked()
            checkbox = self.ui.tabWidget.findChild(QtGui.QCheckBox, "checkboxContained_%i" % (i + 1))
            is_contained = checkbox.isChecked()

            radiobutton_or = self.ui.tabWidget.findChild(QtGui.QRadioButton, "radiobuttonOr_%i" % (i + 1))
            boolean_op = poioapi.annotationtree.AnnotationTreeFilter.AND
            if radiobutton_or.isChecked():
                boolean_op = poioapi.annotationtree.AnnotationTreeFilter.OR

            for _, annotation_graph in self.corpus:
                # annotation_graph.init_filters()
                filter = annotation_graph.create_filter_for_dict(search_terms)
                filter.inverted = is_inverted
                filter.contained_matches = is_contained
                filter.booleab_operation = boolean_op
                annotation_graph.append_filter(filter)

        self.update_result_view()

    def search_tab_changed(self, index):
        """
        Check if the search tab changed

        ...

        Parameters
        ----------
        index : int
        """

        if index == self.ui.tabWidget.count() - 1:
            self.add_search_tab()

        else:
            self.apply_filter()

    def _add_search_box_to_widget(self, widget, nr_of_tab, tier_name):
        label = QtGui.QLabel(widget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(label.sizePolicy().hasHeightForWidth())
        label.setSizePolicy(sizePolicy)
        label.setSizeIncrement(QtCore.QSize(1, 0))
        label.setText(
            QtGui.QApplication.translate(
                "TabWidgetSearch", "{0}:".format(tier_name), None, QtGui.QApplication.UnicodeUTF8
            )
        )
        label.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        widget.ui.layoutLabels.addWidget(label)

        lineedit = QtGui.QLineEdit(self.ui.tabWidget)
        lineedit.setSizeIncrement(QtCore.QSize(2, 0))
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
        lineedit.setSizePolicy(sizePolicy)
        lineedit.setObjectName("lineedit_{0}_{1}".format(tier_name, nr_of_tab))
        widget.ui.layoutLineedits.addWidget(lineedit)
        lineedit.returnPressed.connect(self.apply_filter)

    def add_search_tab(self):
        """
        Add a search tab
        """
        nr_of_new_tab = self.ui.tabWidget.count()
        widget_search = QtGui.QWidget()
        widget_search.ui = Ui_TabWidgetSearch()
        widget_search.ui.setupUi(widget_search)
        widget_search.setObjectName("%s_%i" % (widget_search.objectName(), nr_of_new_tab))

        for i, tier in enumerate(self.corpus.tier_names):
            self._add_search_box_to_widget(widget_search, nr_of_new_tab, tier)

        # update names of checkboxes and radiobuttons in search
        for child_widget in widget_search.findChildren(QtGui.QWidget):
            child_name = child_widget.objectName()
            if child_name.startswith("checkbox") or child_name.startswith("radiobutton"):
                child_widget.setObjectName("%s_%i" % (child_name, nr_of_new_tab))

        self.ui.tabWidget.insertTab(nr_of_new_tab - 1, widget_search, "Search %i" % nr_of_new_tab)
        self.ui.tabWidget.setCurrentIndex(nr_of_new_tab - 1)

    def update_search_tabs_with_tier_names(self):
        for i in range(0, self.ui.tabWidget.count() - 1):
            widget = self.ui.tabWidget.widget(i)

            # remove search boxes for non-existent tiers
            existing_searches = []
            for child_widget in widget.findChildren(QtGui.QWidget):
                if child_widget.objectName().startswith("lineedit_"):
                    _, suffix = child_widget.objectName().split("_", 1)
                    tier_name, _ = suffix.rsplit("_", 1)
                    print(tier_name)
                    if tier_name not in self.corpus.tier_names:
                        child_widget.hide()
                        child_widget.deleteLater()
                        del child_widget
                    existing_searches.append(suffix)

            # add new tiers
            for tier in self.corpus.tier_names:
                if tier not in existing_searches:
                    self._add_search_box_to_widget(widget, i + 1, tier)

    def update_search_tab_widget_names(self):
        """
        Updates the search tab
        """
        for i in range(0, self.ui.tabWidget.count() - 1):
            widget = self.ui.tabWidget.widget(i)
            for childWidget in widget.findChildren(QtGui.QWidget):
                childWidget.setObjectName("%s_%i" % (childWidget.objectName()[:-2], i + 1))
            self.ui.tabWidget.setTabText(i, "Search %i" % (i + 1))

    def search_tab_closed(self):
        """
        Closes the search tab
        """
        # always leave at least one Search tab open
        if self.ui.tabWidget.indexOf(self.ui.tabNewSearch) < 2:
            return
        currentIndex = self.ui.tabWidget.currentIndex()
        if currentIndex < 1:
            return
        widgetSearch = self.ui.tabWidget.currentWidget()
        self.ui.tabWidget.setCurrentIndex(currentIndex - 1)
        self.ui.tabWidget.removeTab(currentIndex)
        widgetSearch.close()
        widgetSearch.deleteLater()
        del widgetSearch
        self.update_search_tab_widget_names()

    def search_tab_cleared(self):
        """
        Clears the search tab
        """
        widget = self.ui.tabWidget.currentWidget()
        for childWidget in widget.findChildren(QtGui.QWidget):
            if childWidget.objectName().startswith("lineedit_"):
                childWidget.setText("")
        self.apply_filter()

    def about_dialog(self):
        """
        Popup a message box containing the "About Information"
        of Poio Analyser
        """
        QtGui.QMessageBox.about(
            self,
            "About Poio Analyzer",
            """<b>Poio Analyzer v0.3.0</b>
               <br/><br/>
               Poio Analyzer is an analysis tool for linguists
               to analyze interlinear data. It is developed by
               Peter Bouda at the
               <b><a href=\"http://www.cidles.eu\">
                  Interdisciplinary Centre for Social and Language
                  Documentation</a>
                </b>
                <br/><br/>
                Please send bug reports and
                comments to <b><a href=\"mailto:[email protected]\">
                [email protected]</a></b>.
                <br/><br/>
                For more information visit the website of the project:
                <br/>
                <b><a href="http://media.cidles.eu/poio/">
                    http://media.cidles.eu/poio/
                </a></b>
                <br/><br/>
                All rights reserved. See LICENSE file for details.
                """,
        )
class PoioGRAID(QtGui.QMainWindow):
    """The main window of the PoioGRAID application."""

    def __init__(self, *args):
        """
        The consctructor of the main application object, i.e. the main window.
        Calls a lot of other init methods.
        """
        QtGui.QMainWindow.__init__(self, *args)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.init_vars()
        self.init_connects()
        self.init_settings()

        self.init = 0

        self.project = PoioProject(os.getcwd())
        self.ui.listFiles.setModel(self.project)
        self.ui.projectManager.setShown(False)
        self.ui.projectBtn.setStyleSheet(""" QPushButton#projectBtn
                                            {
                                                border-style: outset;
                                                border-width: 1px;
                                                border-color: black;
                                                padding: 1px;
                                            }
                                            QPushButton#projectBtn:checked
                                            {
                                                background-color: lightblue;
                                                border-style: inset;
                                                border-width: 2px;
                                            }""")

        self.ui.textedit.append_title(
            self.tr("Please create or open a file..."))

        self._dialog_find_and_replace = FindReplaceDialog(self)
        self._dialog_find_and_replace.setModal(False)
        self._dialog_find_and_replace.set_text_edit(self.ui.textedit)

        self._dialog_find = FindDialog(self)
        self._dialog_find.setModal(False)
        self._dialog_find.set_text_edit(self.ui.textedit)

    def init_vars(self):
        """
        Initializes several attributes of the application, for example
        creates an empty annotation tree and a data structure type.
        """
        self.reset_data_structure_type(poioapi.data.GRAID)

        self.filepath = None
        self.projectfilepath = None
        self.title = ''

    def init_settings(self):
        """
        Load application settings from QSettings object.
        """
        QtCore.QCoreApplication.setOrganizationName(
            "Interdisciplinary Centre for Social and Language Documentation");
        QtCore.QCoreApplication.setOrganizationDomain("cidles.eu");
        QtCore.QCoreApplication.setApplicationName("PoioGRAID");
        #settings = QtCore.QSettings()

    def init_connects(self):
        """
        Initializes all signal/slots connections of the application.
        """

        # Files
        self.ui.actionOpenFile.triggered.connect(self.open_file)
        self.ui.actionSaveFile.triggered.connect(self.save_file)
        self.ui.actionSaveFileAs.triggered.connect(self.save_file_as)
        self.ui.actionOpen_Project.triggered.connect(self.open_project)
        self.ui.actionSave_Project.triggered.connect(self.save_project)
        self.ui.actionSave_Project_as.triggered.connect(self.save_project_as)
        self.ui.actionNewFile.triggered.connect(self.new_file)

        # Application stuff
        self.ui.actionQuit.triggered.connect(self.close)
        self.ui.actionAboutPoioGRAID.triggered.connect(self.about_dialog)

        # insert and delete tables and columns
        self.ui.actionInsertUtteranceAfter.triggered.connect(
            self.insert_utterance_after)
        self.ui.actionInsertUtteranceBefore.triggered.connect(
            self.insert_utterance_before)
        self.ui.actionDeleteUtterance.triggered.connect(
            self.delete_utterance)

        self.ui.actionInsertColumnBefore.triggered.connect(
            self.insert_column_before)
        self.ui.actionInsertColumnAfter.triggered.connect(
            self.insert_column_after)
        self.ui.actionDeleteColumn.triggered.connect(self.delete_column)

        # find and replace
        self.ui.actionFindAndReplace.triggered.connect(
            self.find_and_replace)
        self.ui.actionFind.triggered.connect(self.find)

        # Poio Project
        self.ui.listFiles.activated.connect(self.open_selected_file)
        self.connect(self.ui.projectBtn,SIGNAL("toggled()"),self.show_project)
        self.connect(self.ui.addfileBtn,SIGNAL("clicked()"),self.add_file)
        self.connect(self.ui.removefileBtn,SIGNAL("clicked()"),self.remove_file)
        self.connect(self.ui.saveprojectBtn,SIGNAL("clicked()"),self.save_project)
        self.connect(self.ui.openprojectBtn,SIGNAL("clicked()"),self.open_project)


    def about_dialog(self):
        """
        Display the About dialog.
        """
        about = QtGui.QMessageBox(self)
        about.setTextFormat(QtCore.Qt.RichText)
        about.setWindowTitle(self.tr("About PoioGRAID"))
        about.setText(self.tr("<b>PoioGRAID 0.2.1</b><br/>Poio GRAID Editor "
                              "by the <a href=\"http://www.cidles.eu\">"
                              "Interdisciplinary Centre for Social and "
                              "Language Documentation</a>.<br/><br/>All "
                              "rights reserved. See LICENSE file for details."
                              "<br/><br/>For more information visit the "
                              "website:<br/><a href=\"http://media.cidles.eu"
                              "/poio/\">http://media.cidles.eu/poio/"
                              "</a>"))
        about.exec_()

    def reset_data_structure_type(self, data_structure_type):
        self.annotation_tree = poioapi.annotationtree.AnnotationTree(
            data_structure_type)
        self.ui.textedit.structure_type_handler =\
            self.annotation_tree.structure_type_handler

    def show_project(self):
        """
        Show or hide the project manager.
        """
        self.ui.projectManager.setShown(self.ui.projectBtn.isChecked())

    def open_file(self):
        """
        Prompt the user for a file, add it to the project and open it.
        """
        filepaths = QtGui.QFileDialog.getOpenFileNames(self, self.tr("Open File"), "", self.tr("Pickle files (*.pickle);;All files (*.*)"))
        if len(filepaths) == 1:
            self.project.clear()
            self.project.addFilePaths(filepaths)
            self.open_file_at_path(filepaths[0])

    def open_file_at_path(self, filepath):
        """
        Load the data into the annotation tree and then update the text edit widget.

        ...

        Parameters
        ----------
        filepath: str
        """
        if filepath != '':
            self.annotation_tree.load_tree_from_pickle(filepath)
            self.ui.textedit.structure_type_handler =\
                self.annotation_tree.structure_type_handler

        #file = open(filepath, "rb")
            #data = pickle.load(file)
            #if data[0] == 'poio_pickle_v2':
            #    self.reset_data_structure_type(data[1])
            #    self.annotation_tree.tree = data[2]
            #else:
            #    file.seek(0)
            #    self.reset_data_structure_type(poioapi.data.GRAID)
            #    self.annotation_tree.tree = pickle.load(file)
            #file.close()
            self.update_textedit()
            self.filepath = filepath

    def open_project(self):
        """
        Prompt the user for a project, clear previous project and screen and open the project in the manager.
        """
        path = QtGui.QFileDialog.getOpenFileNames(
            self,
            self.tr("Open Project"),
            "",
            self.tr("Poio project file (*.poioprj);;All files (*.*)"))
        if len(path) > 0:
            self.project.clear()
            self.annotation_tree.tree = []
            self.update_textedit()
            self.projectfilepath = path[0]
            self.project.openproject(path[0])

    def add_file(self):
        """
        Add a file to the current project
        """
        filepaths = QtGui.QFileDialog.getOpenFileNames(self, self.tr("Add Files"), "", self.tr("Pickle files (*.pickle);;All files (*.*)"))
        self.project.addFilePaths(filepaths)
        self.open_file_at_path(filepaths[0])

    def remove_file(self):
        """
        Remove the selected file from the current project
        """
        countRemoved = 0
        for i in self.ui.listFiles.selectedIndexes():
            currentrow = i.row()-countRemoved
            project = self.project.poioFileAt(currentrow)
            self.project.removeFilePathAt(currentrow)

            if self.filepath == project.filepath:
                self.ui.textedit.clear()

            countRemoved += 1

    def open_selected_file(self):
        """
        Open the selected file in the manager to the TextEdit Screen
        """
        selected = self.ui.listFiles.selectedIndexes()
        count = 0
        for item in self.project.projectfiles:
            if item.filepath == 'tmp\\untitled.pickle':
                ret = self.project.saveuntitled()
                if ret == QMessageBox.Save:
                    path = self.save_file_as()
                    self.project.removeFilePathAt(count)
                    self.project.addFilePath(path)
                elif ret == QMessageBox.Discard:
                    self.project.removeFilePathAt(count)
                elif ret == QMessageBox.Cancel:
                    return
            count +=1
        if len(selected) == 1:
            project = self.project.poioFileAt(selected[0].row())
            self.open_file_at_path(project.filepath)

    def update_textedit(self):
        """
        Updates the text edit view with the data from the annotation tree.
        """
        self.ui.textedit.blockSignals(True)
        self.ui.textedit.clear()
        self.ui.textedit.append_title(self.title)

        for element in self.annotation_tree.elements():
            self.ui.textedit.append_element(element)

        self.ui.textedit.scrollToAnchor("title")
        self.ui.textedit.blockSignals(False)

    def delete_utterance(self):
        """
        Delete one utterance from the text edit widget and from the annotation
        tree.
        """
        deleted_id = self.ui.textedit.delete_current_element()
        if deleted_id:
            self.annotation_tree.remove_element(deleted_id)

    def insert_utterance_before(self):
        """
        Insert an utteranance *before* the currently edited utterance in the
        text view. Then adds the utterance to the annotation tree.
        """
        element = self.annotation_tree.empty_element()
        current_id = self.ui.textedit.insert_element(element)
        if current_id:
            self.annotation_tree.insert_element(element, current_id)

    def insert_utterance_after(self):
        """
        Insert an utteranance *after* the currently edited utterance in the
        text view. Then adds the utterance to the annotation tree.
        """
        element = self.annotation_tree.empty_element()
        current_id = self.ui.textedit.insert_element(element, True)
        if current_id:
            self.annotation_tree.insert_element(element, current_id, True)

    def delete_column(self):
        """
        Deletes the column that is currently edited in the text view. Also
        remove all annotation and sub-elements belonging to this column.
        Then delete the elements from the annotation tree.
        """
        self.ui.textedit.delete_column_at_cursor()

    def insert_column_before(self):
        """
        Inserts an empty column at the current cursor position *before* the
        currently edited element. Then insert the element into the annotation
        tree.
        """
        next_id = self.ui.textedit.insert_column_at_cursor(
            self.annotation_tree.next_annotation_id, False)
        self.annotation_tree.next_annotation_id = next_id

    def insert_column_after(self):
        """
        Inserts an empty column at the current cursor position *after* the
        currently edited element. Then insert the element into the annotation
        tree.
        """
        next_id = self.ui.textedit.insert_column_at_cursor(
            self.annotation_tree.next_annotation_id, True)
        self.annotation_tree.next_annotation_id = next_id

    def new_file(self):
        """
        Create a new file from a given input text. The user has to enter the
        text in an input dialog. There are two types of input text: plain text
        or tb style text (with markup like ``\sl`` at the beginning of lines).
        """
        dialog = QtGui.QDialog(self)
        ui = Ui_NewFileGraid()
        ui.setupUi(dialog)
        ret = dialog.exec_()
        if ret == QtGui.QDialog.Accepted:
            # get the data structure type that the user chose
            combo_data_structure_type = ui.comboDataStructureType.currentText()
            data_structure_type = poioapi.data.GRAID
            if combo_data_structure_type == "GRAID2 (Diana)":
                data_structure_type = poioapi.data.GRAIDDIANA

            self.reset_data_structure_type(data_structure_type)

            self.title = ""
            self.statusBar().showMessage(self.tr("Parsing text..."), 5)
            if ui.radioButtoTbStyleText.isChecked():
                self._parse_tb_style_text(
                    ui.textedit.document().toPlainText())
            else:
                self._parse_plain_text(
                    ui.textedit.document().toPlainText())
            self.statusBar().showMessage(self.tr("Parsing done."), 5)
            self.update_textedit()
            self.project.addFilePath('tmp\\untitled.pickle')

    def save_file(self):
        """
        Save the current data into a file. If no filename is specified yet
        then ask for the path and filename by opening a file dialog.
        """
        if not self.filepath:
            self.save_file_as()
        else:
            tree = self.ui.textedit.annotation_tree_from_document()
            self.annotation_tree.tree = tree
            file = open(self.filepath, "wb")
            pickle.dump(['poio_pickle_v2',
                         self.annotation_tree.data_structure_type,
                         self.annotation_tree.tree], file)
            file.close()
            self.statusBar().showMessage(self.tr("File saved."), 5)

    def save_file_as(self):
        """
        Open a file dialog and ask for path and filename for the file. Then
        call `PoioGRAID.save_file()`.
        """
        filepath = QtGui.QFileDialog.getSaveFileName(
            self,
            self.tr("Save File As"),
            "",
            self.tr("Pickle file (*.pickle);;All files (*.*)"))
        if filepath != '':
            if not filepath.endswith(".pickle"):
                filepath += ".pickle"
            self.filepath = filepath
            self.save_file()
            return filepath
        else:
            return

    def save_project(self):
        """
        Save the current project in the manager.
        Prompt for a path if the current project didn't exist yet
        """
        if not self.projectfilepath:
            self.save_project_as()
        else:
            self.save_file()
            self.project.saveprojectas(self.projectfilepath)

    def save_project_as(self):
        """
        Prompt for a path and save the current project to it
        """
        self.save_file()
        savepath = ""
        savepath = QtGui.QFileDialog.getSaveFileName(
            self,
            self.tr("Save Project As"),
            "",
            self.tr("Poio project file (*.poioprj);;All files (*.*)"))
        if savepath !="":
            self.project.saveprojectas(savepath)
            self.projectfilepath = savepath

    def find_and_replace(self):
        """
        Shows find and replace dialog
        """
        self._dialog_find_and_replace.show()

    def find(self):
        """
        Shows find dialog
        """
        self._dialog_find.show()

    # Private functions #######################################################

    def _parse_plain_text(self, text):
        """
        Parses plain text data into an annotation tree.

        ...

        Parameters
        ----------
        text : str
        """
        lines = text.split("\n")

        progress = QtGui.QProgressDialog(self.tr("Parsing text..."), self.tr("Abort"), 0, len(lines), self.parent())
        progress.setWindowModality(QtCore.Qt.WindowModal)

        for i, line in enumerate(lines):
            progress.setValue(i)

            line = line.strip()
            utterance = line
            clause_unit = re.sub("[.,;:]", "", line)
            words = clause_unit.split()

            il_elements = list()
            for w in words:
                if self.annotation_tree.data_structure_type == \
                        poioapi.data.GRAID:
                    il_elements.append([
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' :  w },
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' : '' },
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' : '' }])
                elif self.annotation_tree.data_structure_type ==\
                                        poioapi.data.GRAIDDIANA:
                    il_elements.append([
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' :  w },
                            # morphemes
                            [
                            [
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' : '' },
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' : '' }
                            ]
                            ],
                            # graid1, graid 3
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' : '' },
                            { 'id' : self.annotation_tree.next_annotation_id,
                              'annotation' : '' }])

                elements = [ [
                { 'id' : self.annotation_tree.next_annotation_id,
                  'annotation' : clause_unit },
                il_elements,
                { 'id' : self.annotation_tree.next_annotation_id,
                  'annotation' : '' }] ]

            utterance = [ { 'id' : self.annotation_tree.next_annotation_id,
                            'annotation' : utterance },
                          elements,
                          { 'id' : self.annotation_tree.next_annotation_id,
                            'annotation' : '' },
                          { 'id' : self.annotation_tree.next_annotation_id,
                            'annotation' : '' } ]
            if self.annotation_tree.data_structure_type ==\
               poioapi.data.GRAIDDIANA:
                utterance.append(
                        { 'id' : self.annotation_tree.next_annotation_id,
                          'annotation' : '' })

            self.annotation_tree.append_element(utterance)
            if (progress.wasCanceled()):
                initCorpusReader()
                break

        progress.setValue(len(lines))

    def _parse_tb_style_text(self, text):
        """
        Parses tb style data into an annotation tree. In tb style data lines
        start with markup like ``\sl``.

        ...

        Parameters
        ----------
        text : str
        """
        block = list()

        lines = text.split("\n")
        line = lines.pop(0)
        title = []
        while not line.startswith("\\"):
            if line:
                title.append(line)
            line = lines.pop(0)

        self.title = " ".join(title)

        for line in lines:
            if line and line.startswith("\\id") and len(block):
                utterance = self._parse_element_from_tb_style(block)
                self.annotation_tree.append_element(utterance)
                block = list()
            elif line:
                if line.startswith("\\"):
                    block.append(line.strip())

        utterance = self._parse_element_from_tb_style(block)
        self.annotation_tree.append_element(utterance)

        #print self.annotation_tree.tree

    def _parse_element_from_tb_style(self, block):
        """
        Helper function for `PoioGRAID._parse_tb_style_text()`. Parse one
        paragraph of tb style data.
        ...

        Parameters
        ----------
        block : list
        """
        element_tb = dict()
        utterance = ""
        translation = ""
        comment = ""

        for line in block:
            line = re.sub(" +", " ", line)
            line = line.strip()
            line_elements = line.split(None, 1)
            if len(line_elements) < 2:
                type = line
                text = ""
            else:
                type = line_elements[0]
                text = line_elements[1]

            if type.startswith("\\"):
                if type[1:] == "sl":
                    #text = re.sub("\(\d+\) ?", "", text)
                    utterance = text
                    utterance = re.sub("\d?# ?", "", utterance)
                    utterance = re.sub(" +", " ", utterance)
                    utterance = utterance.strip()

                if type[1:] == "ft":
                    translation = text

                elif type[1:] == "com":
                    comment = text

                else:
                    #text = re.sub("^x ", "", text)
                    element_tb[type[1:]] = list()
                    last_start = 0
                    for m in re.finditer("(?:\d?#|$)", text):
                        element_tb[type[1:]].append(
                            text[last_start:m.start(0)])
                        last_start = m.end(0)
        elements = []
        for i, phrase in enumerate(element_tb['sl']):
            words = phrase.split()
            wfw = []
            try:
                wfw = element_tb['wfw'][i].split()
            except IndexError:
                pass
            except KeyError:
                pass

            graid1 = []
            try:
                graid1 = element_tb['gr_1'][i].split()
            except IndexError:
                pass
            except KeyError:
                pass

            graid2 = ''
            try:
                graid2 = element_tb['gr_2'][i]
            except IndexError:
                pass
            except KeyError:
                pass

            il_elements = []
            for i in range(max(len(words), len(wfw), len(graid1))):
                e1 = ''
                e2 = ''
                e3 = ''
                if i < len(words):
                    e1 = words[i]
                if i < len(wfw):
                    e2 = wfw[i]
                if i < len(graid1):
                    e3 = graid1[i]
                il_elements.append([
                    { 'id' : self.annotation_tree.next_annotation_id,
                      'annotation' :  e1 },
                    { 'id' : self.annotation_tree.next_annotation_id,
                      'annotation' : e2 },
                    { 'id' : self.annotation_tree.next_annotation_id,
                      'annotation' : e3 }])

            elements.append([
                { 'id' : self.annotation_tree.next_annotation_id,
                  'annotation' : phrase },
                il_elements,
                { 'id' : self.annotation_tree.next_annotation_id,
                  'annotation' : graid2 }])

        return [ { 'id' : self.annotation_tree.next_annotation_id,
                   'annotation' : utterance },
                  elements,
                  { 'id' : self.annotation_tree.next_annotation_id,
                    'annotation' : translation },
                  { 'id' : self.annotation_tree.next_annotation_id,
                    'annotation' : comment } ]
Esempio n. 6
0
class PoioAnalyzer(QtGui.QMainWindow):
    """The main window of the PoioAnalyzer application."""

    def __init__(self, *args):
        QtGui.QMainWindow.__init__(self, *args)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.texteditInterlinear.setReadOnly(True)

        self.initConnects()
        self.initSettings()
        self.project = PoioProject(os.getcwd())
        self.ui.listFiles.setModel(self.project)
        self.initCorpusReader()
        self.currentFilter = AnnotationTreeFilter()

    def initCorpusReader(self):
        self.corpusreader = GlossCorpusReader(
            utterancetierTypes=self.arrUtteranceTierTypes,
            wordtierTypes=self.arrWordTierTypes,
            translationtierTypes=self.arrTranslationTierTypes,
            morphemetierTypes=self.arrMorphemeTierTypes,
            glosstierTypes=self.arrGlossTierTypes,
        )

    def updateCorpusReaderFilter(self):
        self.currentFilter.resetMatchObject()
        for [filepath, annotationtree] in self.corpusreader.annotationtrees:
            new_filter = copy.deepcopy(self.currentFilter)
            annotationtree.updateLastFilter(new_filter)

    def updateCorpusReader(self):
        itemsCount = self.project.rowCount()
        progress = QtGui.QProgressDialog(self.tr("Loading Files..."), self.tr("Abort"), 0, itemsCount, self.parent())
        progress.setWindowModality(QtCore.Qt.WindowModal)
        for i in range(itemsCount):
            progress.setValue(i)
            poiofile = self.project.poioFileAt(i)
            if poiofile.isNew:
                self.corpusreader.addFile(poiofile.filepath, poiofile.type)
                poiofile.setIsNew(False)
            if progress.wasCanceled():
                initCorpusReader()
                break
        progress.setValue(itemsCount)
        self.updateCorpusReaderFilter()

    def initConnects(self):
        QtCore.QObject.connect(self.ui.buttonAddFiles, QtCore.SIGNAL("pressed()"), self.addFiles)
        QtCore.QObject.connect(self.ui.buttonRemoveFiles, QtCore.SIGNAL("pressed()"), self.removeFiles)

        # Filter and Search
        QtCore.QObject.connect(self.ui.buttonSearch, QtCore.SIGNAL("pressed()"), self.applyFilter)
        QtCore.QObject.connect(self.ui.lineeditSearchUtterances, QtCore.SIGNAL("returnPressed()"), self.applyFilter)
        QtCore.QObject.connect(self.ui.lineeditSearchWords, QtCore.SIGNAL("returnPressed()"), self.applyFilter)
        QtCore.QObject.connect(self.ui.lineeditSearchMorphemes, QtCore.SIGNAL("returnPressed()"), self.applyFilter)
        QtCore.QObject.connect(self.ui.lineeditSearchGlosses, QtCore.SIGNAL("returnPressed()"), self.applyFilter)
        QtCore.QObject.connect(self.ui.lineeditSearchTranslations, QtCore.SIGNAL("returnPressed()"), self.applyFilter)

        # Quick Search
        QtCore.QObject.connect(
            self.ui.actionQuickSearch, QtCore.SIGNAL("triggered()"), self.ui.lineeditQuickSearch.setFocus
        )
        QtCore.QObject.connect(
            self.ui.lineeditQuickSearch, QtCore.SIGNAL("textChanged(const QString &)"), self.findFromStart
        )
        QtCore.QObject.connect(self.ui.lineeditQuickSearch, QtCore.SIGNAL("returnPressed()"), self.findNext)

    def initSettings(self):
        QtCore.QCoreApplication.setOrganizationName("Interdisciplinary Centre for Social and Language Documentation")
        QtCore.QCoreApplication.setOrganizationDomain("cidles.eu")
        QtCore.QCoreApplication.setApplicationName("PoioAnalyzer")
        settings = QtCore.QSettings()
        self.strMorphemeSeperator = unicode(settings.value("Ann/MorphSep", QtCore.QVariant("-")).toString())
        self.strGlossSepereator = unicode(settings.value("Ann/GlossSep", QtCore.QVariant(":")).toString())
        self.strEmptyCharacter = unicode(settings.value("Ann/EmptyChar", QtCore.QVariant("#")).toString())
        self.arrUtteranceTierTypes = unicode(
            settings.value(
                "Ann/UttTierTypeRefs", QtCore.QVariant(u"utterance|utterances|Äußerung|Äußerungen")
            ).toString()
        ).split("|")
        self.arrWordTierTypes = unicode(
            settings.value("Ann/WordTierTypeRefs", QtCore.QVariant(u"words|word|Wort|Worte|Wörter")).toString()
        ).split("|")
        self.arrMorphemeTierTypes = unicode(
            settings.value("Ann/MorphTierTypeRefs", QtCore.QVariant(u"morpheme|morphemes|Morphem|Morpheme")).toString()
        ).split("|")
        self.arrGlossTierTypes = unicode(
            settings.value("Ann/GlossTierTypeRefs", QtCore.QVariant(u"glosses|gloss|Glossen|Gloss|Glosse")).toString()
        ).split("|")
        self.arrTranslationTierTypes = unicode(
            settings.value(
                "Ann/TransTierTypeRefs", QtCore.QVariant(u"translation|translations|Übersetzung|Übersetzungen")
            ).toString()
        ).split("|")

    def removeFiles(self):
        pass

    def addFiles(self):
        filepaths = QtGui.QFileDialog.getOpenFileNames(
            self, self.tr("Add Files"), "", self.tr("Elan files (*.eaf);;Toolbox files (*.txt);;All files (*.*)")
        )
        self.project.addFilePaths(filepaths)
        start = time.time()
        self.updateCorpusReader()
        end = time.time()
        print "Time elapsed = ", end - start, "seconds"
        start = time.time()
        self.updateIlTextEdit()
        end = time.time()
        print "Time elapsed = ", end - start, "seconds"

    def updateIlTextEdit(self):
        self.ui.texteditInterlinear.clear()
        self.ui.texteditInterlinear.setReadOnly(True)
        itemsCount = self.project.rowCount()
        for [filepath, annotationtree] in self.corpusreader.annotationtrees:
            self.ui.texteditInterlinear.appendTitle(os.path.basename(filepath))
            utterancesIds = annotationtree.getFilteredUtteranceIds()
            filter = annotationtree.lastFilter()
            for id in utterancesIds:
                utterance = annotationtree.getUtteranceById(id)
                if id in filter.matchobject["utterance"]:
                    offset = 0
                    for g in filter.matchobject["utterance"][id]:
                        utterance = (
                            utterance[: g[0] + offset] + '<span style="color:green;">' + utterance[g[0] + offset :]
                        )
                        offset = offset + len('<span style="color:green;">')
                        utterance = utterance[: g[1] + offset] + "</span>" + utterance[g[1] + offset :]
                        offset = offset + len("</span>")
                translations = annotationtree.getTranslationsForUtterance(id)
                if len(translations) == 0:
                    translationId = annotationtree.newTranslationForUtteranceId(id, "")
                    translations = [[translationId, self.strEmptyCharacter]]
                else:
                    new_translations = []
                    for t in translations:
                        if t[1] == "":
                            new_t = self.strEmptyCharacter
                            new_translations.append = [t[0], new_t]
                        if t[0] in filter.matchobject["translation"]:
                            offset = 0
                            new_t = t[1]
                            for g in filter.matchobject["translation"][t[0]]:
                                new_t = new_t[: g[0] + offset] + '<span style="color:green;">' + new_t[g[0] + offset :]
                                offset = offset + len('<span style="color:green;">')
                                new_t = new_t[: g[1] + offset] + "</span>" + new_t[g[1] + offset :]
                                offset = offset + len("</span>")
                            new_translations.append([t[0], new_t])
                        else:
                            new_translations.append([t[0], t[1]])
                        translations = new_translations
                wordIds = annotationtree.getWordIdsForUtterance(id)
                ilElements = []
                for wid in wordIds:
                    strWord = annotationtree.getWordById(wid)
                    if strWord == "":
                        strWord = self.strEmptyCharacter
                    strMorphemes = annotationtree.getMorphemeStringForWord(wid)
                    if strMorphemes == "":
                        strMorphemes = strWord
                    strGlosses = annotationtree.getGlossStringForWord(wid)
                    if strGlosses == "":
                        strGlosses = self.strEmptyCharacter

                    markWord = False
                    if wid in filter.matchobject["word"]:
                        markWord = True
                    ilElements.append([wid, strWord, strMorphemes, strGlosses, markWord])

                self.ui.texteditInterlinear.appendUtterance(id, utterance, ilElements, translations)

        self.ui.texteditInterlinear.scrollToAnchor("#")

    def findFromStart(self, exp):
        self.ui.texteditInterlinear.setTextCursor(QtGui.QTextCursor(self.ui.texteditInterlinear.document()))
        if not self.ui.texteditInterlinear.find(exp) and exp != "":
            self.statusBar().showMessage(self.tr("No match found."), 2000)

    def findNext(self):
        found = self.ui.texteditInterlinear.find(self.ui.lineeditQuickSearch.text())
        if not found:
            self.statusBar().showMessage(self.tr("Restarting search from beginning of document."), 2000)
            found = self.findFromStart(self.ui.lineeditQuickSearch.text())
        return found

    def applyFilter(self):
        self.currentFilter.setUtteranceFilter(unicode(self.ui.lineeditSearchUtterances.text()))
        self.currentFilter.setTranslationFilter(unicode(self.ui.lineeditSearchTranslations.text()))
        self.currentFilter.setWordFilter(unicode(self.ui.lineeditSearchWords.text()))
        self.currentFilter.setMorphemeFilter(unicode(self.ui.lineeditSearchMorphemes.text()))
        self.currentFilter.setGlossFilter(unicode(self.ui.lineeditSearchGlosses.text()))

        self.currentFilter.setInvertedFilter(self.ui.checkboxInvert.isChecked())
        self.currentFilter.setContainedMatches(self.ui.checkboxContained.isChecked())

        if self.ui.radiobuttonAnd.isChecked():
            self.currentFilter.setBooleanOperation(AnnotationTreeFilter.AND)
        elif self.ui.radiobuttonOr.isChecked():
            self.currentFilter.setBooleanOperation(AnnotationTreeFilter.OR)

        self.updateCorpusReaderFilter()
        self.updateIlTextEdit()