Пример #1
0
    def __init__(self, model):
        super().__init__()

        self._model = model

        layout = QGridLayout()
        splitter = QSplitter()

        self._bot_table = _BotTable()
        self._responses_tab = _ResponsesTab()
        self._execute_tab = _ExecuteTab(self._responses_tab, model)

        self._tab_widget = QTabWidget()
        self._tab_widget.addTab(self._execute_tab, "Execute")
        self._tab_widget.addTab(self._responses_tab, "Responses")

        splitter.setOrientation(Qt.Vertical)
        splitter.addWidget(self._bot_table)
        splitter.addWidget(self._tab_widget)
        splitter.setSizes([50, 100])

        layout.addWidget(splitter)
        self.setLayout(layout)

        self._register_listeners()
Пример #2
0
 def init_workspace(self):
     splitter = QSplitter(self)
     splitter.setOrientation(Qt.Vertical)
     splitter.sizePolicy().setVerticalPolicy(QSizePolicy.Maximum)
     query_edit = self.init_query_text_edit()
     self.on_disconnected()
     splitter.addWidget(query_edit)
     results_widget = self.init_results_widget()
     splitter.addWidget(results_widget)
     splitter.setSizes([100, 900])
     return splitter
Пример #3
0
    def init_workspace(self):
        # Create a splitter consisting of query edit and table view
        splitter = QSplitter(self)
        splitter.setOrientation(Qt.Vertical)
        splitter.sizePolicy().setVerticalPolicy(QSizePolicy.Maximum)

        # Initialize query edit file
        query_edit = self.init_query_text_edit()
        # Disable query control buttons by default
        self.on_disconnected()
        splitter.addWidget(query_edit)

        # Initialize result desiplaying widgets
        results_widget = self.init_results_widget()
        splitter.addWidget(results_widget)
        splitter.setSizes([100, 900])
        return splitter
Пример #4
0
    def setup_layout(self):
        # group the editor with the console
        vertical_splitter = QSplitter(self)
        vertical_splitter.setOrientation(Qt.Vertical)
        vertical_splitter.addWidget(self.editor_pane)
        vertical_splitter.addWidget(self.console)
        vertical_splitter.setStretchFactor(0, 3)
        vertical_splitter.setStretchFactor(1, 1)

        # group
        horizontal_splitter = QSplitter(self)
        horizontal_splitter.addWidget(self.explorer_tab)
        horizontal_splitter.addWidget(vertical_splitter)
        horizontal_splitter.addWidget(self.info_bar)
        horizontal_splitter.setStretchFactor(0, 1)
        horizontal_splitter.setStretchFactor(1, 4)
        horizontal_splitter.setStretchFactor(2, 1)
        self.setCentralWidget(horizontal_splitter)
Пример #5
0
class Snipdom(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)


        self.hsplit = QSplitter()
        self.setCentralWidget(self.hsplit)

        kernel_manager = QtInProcessKernelManager()
        kernel_manager.start_kernel()
        self.kernel = kernel_manager.kernel
        self.kernel.gui = 'qt'

        self.control = RichIPythonWidget(gui_completion="droplist")

        self.kernel.shell.push({'snipdom': self})

        kernel_client = kernel_manager.client()
        kernel_client.start_channels()

        self.control.kernel_manager = kernel_manager
        self.control.kernel_client = kernel_client

        self.vsplit = QSplitter()
        self.vsplit.setOrientation(Qt.Vertical)

        self.vsplit.addWidget(self.control)
        self.hsplit.addWidget(self.vsplit)

        self.sendButton = QPushButton("send")
        #self.sendButton.clicked.connect(self.sendcode)
        self.vsplit.addWidget(self.sendButton)

        self.bridge = Js2Py()
        self.bridge.sent.connect(self.codeFromJs)

        #lab = QtGui.QLabel(kernel.shell.history_manager.get_range(start=-1).next()[2])

    def codeFromJs(self, code):
        self.control.input_buffer = code
Пример #6
0
    def __init__(self, path, panel, parent):
        """
        Create widget.

        Arguments:
            obj (Command, Parameter): Command or Parameter being edited.
            parent (Optional[QWidget]): Parent widget.
        """
        super(ParameterTableWindow, self).__init__(path, panel, parent)
        view = ParameterTableView(panel, item_path=path,
                                  parent_item=None, parent=self)
        self._actions = {}
        self._setView(view)
        self._search.setVisible(False)
        self._plot = None

        if re.match("^.*[.]VALE$", path.path()) or \
            re.match("^.*[.](ABSCISSE|ORDONNEE)$", path.path()):
            self._plot = PlotWidget(view, self)
            self._plot.hide()

            splitter = QSplitter(self)
            splitter.setOrientation(Qt.Vertical)
            splitter.addWidget(view)
            splitter.addWidget(self._plot)
            self._scroll.setWidget(splitter)
        else:
            self._scroll.setWidget(view)

        view.selectionChanged.connect(self._updateState)

        tbar = QToolBar(self)
        tbar.setToolButtonStyle(Qt.ToolButtonIconOnly)

        tbar.addAction(\
            self._createAction(ParameterTableWindow.AppendRow,
                               load_icon("as_pic_add_row.png"),
                               translate("ParameterPanel", "Append row"),
                               translate("ParameterPanel",
                                         "Append row to the end of table"),
                               view.appendRow))

        tbar.addAction(\
            self._createAction(ParameterTableWindow.InsertRow,
                               load_icon("as_pic_insert_row.png"),
                               translate("ParameterPanel", "Insert row"),
                               translate("ParameterPanel",
                                         "Insert row at current position"),
                               view.insertRow))

        tbar.addAction(\
            self._createAction(ParameterTableWindow.RemoveRow,
                               load_icon("as_pic_remove_row.png"),
                               translate("ParameterPanel", "Remove rows"),
                               translate("ParameterPanel",
                                         "Remove selected rows"),
                               view.removeRows))

        tbar.addSeparator()

        tbar.addAction(\
            self._createAction(ParameterTableWindow.MoveRowUp,
                               load_icon("as_pic_move_up.png"),
                               translate("ParameterPanel", "Move up"),
                               translate("ParameterPanel",
                                         "Move selected rows up"),
                               view.moveRowsUp))

        tbar.addAction(\
            self._createAction(ParameterTableWindow.MoveRowDown,
                               load_icon("as_pic_move_down.png"),
                               translate("ParameterPanel", "Move down"),
                               translate("ParameterPanel",
                                         "Move selected rows down"),
                               view.moveRowsDown))

        tbar.addSeparator()

        if self._plot is not None:
            tbar.addAction(\
                self._createAction(ParameterTableWindow.FunctionPlot,
                                   load_icon("as_pic_show_plot.png"),
                                   translate("ParameterPanel",
                                             "Plot function"),
                                   translate("ParameterPanel",
                                             "Show/hide plot view"),
                                   self._plot.setVisible, True))
            tbar.addSeparator()

        tbar.addAction(\
            self._createAction(ParameterTableWindow.Import,
                               load_icon("as_pic_import_table.png"),
                               translate("ParameterPanel", "Import table"),
                               translate("ParameterPanel",
                                         "Import function data from file"),
                               view.importFile))

        self.addControlWidget(tbar)

        self._updateState()
Пример #7
0
class MainWidget(QWidget):  
    """Main window class that provides logic of the program.
    Allows to search concept and to show
    information about concepts and relations """
    def __init__(self, parent=None, application=None):
        super().__init__(parent)
        self.parent = parent
        self.application = application
        self.db = self.openDatabase()
        self.initUI()


    def initActions(self):
        """initalization of actions for main windows"""

        self.help_action = QAction("&Help", self)
        self.help_action.setShortcut("F1")
        self.help_action.setStatusTip('Help')
        self.help_action.triggered.connect(lambda: HelpDialog(self))

        self.about_action = QAction("&About", self)
        self.about_action.setStatusTip('About')
        self.about_action.triggered.connect(self.showAboutMessage)        

        self.new_db_action = QAction("New DB", self)
        self.new_db_action.setShortcut("Ctrl+N")
        self.new_db_action.triggered.connect(self.openNewDB)

        self.delete_сoncept_action = QAction("&Delete", self)
        self.delete_сoncept_action.setShortcut("DEL")
        self.delete_сoncept_action.setStatusTip("Delete")
        self.delete_сoncept_action.triggered.connect(lambda: self.delete(Concept))

        self.delete_subcategory_action = QAction("&Delete subcategory", self)
        self.delete_subcategory_action.triggered.connect(lambda: self.delete(Subcategory))

        self.edit_concept_action = QAction("&Edit", self)
        self.edit_concept_action.setShortcut("F2")
        self.edit_concept_action.triggered.connect(self.editConcept)

        self.edit_relation_action = QAction("&Edit", self)
        self.edit_relation_action.setShortcut("Ctrl+F2")
        self.edit_relation_action.triggered.connect(self.editRelation)

        self.exit_action = QAction("&Exit", self)
        self.exit_action.setShortcut("ESC")
        self.exit_action.triggered.connect(self.close)

        self.select_relation_action = QAction("&Select relation", self)
        self.select_relation_action.triggered.connect(self.setRelationDescription)

        self.delete_relation_action = QAction("&Delete", self)
        self.delete_relation_action.setShortcut("Ctrl+DEL")
        self.delete_relation_action.triggered.connect(lambda: self.delete(Relation))

        
    def showAboutMessage(self):
        try:
            with open("about.txt") as f:
                text = f.read()
                QMessageBox.about(self.parent, "About application", text)
        except: pass
            
    def openNewDB(self):
        """This method deletes setting.py file and closes current application session.
        This uses for creating a new instance of Main Window.
        """
        if os.path.exists("setting.py"):
            os.remove("setting.py")
            self.parent.close()
            self.application.exit(1)
            


    def initUI(self):
        
        self.initActions()
        self.add_data_button = QPushButton("Add data", self)
        self.export_button = QPushButton("Export references", self)
        self.search_box = QGroupBox()
        self.concept_list = QListWidget(self)
        self.relation_list = QListWidget(self)
        self.result_table = QTextEdit(self)
        
        self.concept_list.selectionModel().selectionChanged.connect(self.searchRelations)
        
        self.concept_list.setSelectionMode(QAbstractItemView.ContiguousSelection)
        self.concept_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.concept_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.concept_list.customContextMenuRequested.connect(self.showConceptContextMenu)
        self.relation_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.relation_list.customContextMenuRequested.connect(self.showRelationContextMenu)
        self.relation_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
    
        self.relation_list.selectionModel().selectionChanged.connect(self.setRelationDescription)
        
        self.initSearchFrame(self.search_box)        
        self.grid = QGridLayout()
        self.result_table.setReadOnly(True)
        self.search()
        self.configWidgets()
        self.bindWidgets()
        self.show()
            
    def showConceptContextMenu(self, pos):
        if not len(self.concept_list.selectedItems()) == 1:
            return 
        global_position = self.concept_list.mapToGlobal(pos)
        my_menu = QMenu()
        my_menu.addAction(self.edit_concept_action)
        my_menu.addAction(self.delete_сoncept_action)
        my_menu.addAction(self.delete_subcategory_action)
        my_menu.addSeparator()
        my_menu.addAction(self.help_action)
        my_menu.addAction(self.exit_action)
        my_menu.exec(global_position)


    def initSearchFrame(self, frame):
        self.search_line = QLineEdit(frame)
        checkboxes = QGroupBox()
        checkboxes.setStyleSheet("border:0;")
        self.concept_checkbox = QCheckBox("Concept", checkboxes)
        self.description_checkbox = QCheckBox("Description", checkboxes)
        self.study_checkbox = QCheckBox("Study", checkboxes)
        self.reference_checkbox = QCheckBox("Reference", checkboxes)
        self.in_selected_checkbox = QCheckBox("Search in selected concepts", checkboxes)
        self.search_button = QPushButton("Search", checkboxes)
        
        
        checkboxes_layout = QGridLayout(checkboxes)
        checkboxes_layout.addWidget(self.concept_checkbox, 0, 0)
        checkboxes_layout.addWidget(self.description_checkbox, 0, 1)
        checkboxes_layout.addWidget(self.study_checkbox, 0, 2)
        checkboxes_layout.addWidget(self.reference_checkbox, 0, 3)
        checkboxes_layout.addWidget(self.in_selected_checkbox, 0, 4)
        
        checkboxes_layout.setContentsMargins(0, 0, 0, 0)
        self.concept_checkbox.setChecked(True)
        self.in_selected_checkbox.setChecked(True)
        grid = QGridLayout(frame)
        grid.addWidget(self.search_line, 1, 0)
        grid.addWidget(self.search_button, 1, 1)
        grid.addWidget(checkboxes, 2, 0, Qt.AlignLeft)
        frame.setLayout(grid)


    def getSearchData(self):
        """This method reads parameters of search line and checkboxes,
        and returns "Subcategory" class.
        None and [] uses for showing checkboxes that have been checked.
        """
        concept = self.search_line.text() if self.concept_checkbox.isChecked() else None
        
        if self.reference_checkbox.isChecked():
            reference = [
                #RelationReference(text=self.search_line.text()), 
                ConceptReference(text=self.search_line.text())
            ]  
        else:
            reference = []
        
        if self.description_checkbox.isChecked():
            description = [Description(text=self.search_line.text(), reference=reference)]
        else:
            description = [Description(reference=reference)]
    
        study = self.search_line.text() if self.study_checkbox.isChecked() else None
        
        if self.in_selected_checkbox.isChecked and len(self.concept_list.selectedItems()) > 1:
            selected_items_raw = self.concept_list.selectedItems()
            selected_items = [item.data(Qt.UserRole)[1] for item in selected_items_raw] 
        else:
            selected_items = []
        
        return Subcategory(subcategory=concept, description=description, study=study), selected_items

    # todo: doesn't work, becouse  need html + bib --> rendered bib
    def searchRelations(self):
        
        """This method triggers when the user clicked on the concept.
        This method selected ID of a subcategory from selected item in conceptions list
        and then searches and setting all information about this selected concept.
        """
        if not self.concept_list.selectedItems():
            self.setConceptDescription()
            self.setResult([], self.relation_list)
            return
        subcategory_id = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1].id
        self.setConceptDescription()
        result = self.db.search_relation(subcategory_id)
        self.setResult(result, self.relation_list)


    def showRelationContextMenu(self, pos):
        global_position = self.relation_list.mapToGlobal(pos)
        my_menu = QMenu()
        my_menu.addAction(self.edit_relation_action)
        my_menu.addAction(self.delete_relation_action)
        my_menu.addSeparator()
        my_menu.exec(global_position)


    def editRelation(self):
        """This method opens dialog for editing Relation"""

        if hasSlelectedItems(self.relation_list):
            relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2]
            dlg = EditRelationDialog(self, relation)
            if dlg.exec_():
                relation = dlg.getValue()
                self.db.update_relation(relation)
                self.select_relation_action.trigger()


    def editConcept(self):
        """This method opens dialog for editing Concept"""
        
        if hasSlelectedItems(self.concept_list):
            concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0]
            subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1]
            dlg = EditConceptDialog(self, concept, subcategory)
            
            if dlg.exec_():
                concept, subcategory = dlg.getValue()
                self.db.update_concept(concept)
                self.db.update_subcategory(subcategory)
                self.search()


    def delete(self, something):
        """This universal method for deleting something from the list and database.
        "something" parameter needs to be any of this types: Concept, Subcategory, Relation
        """
        if something == Concept:
            number = 0
            target_list = self.concept_list
        elif something == Subcategory:
            number = 1
            target_list = self.concept_list
        elif something == Relation:
            number = 2
            target_list = self.relation_list
        if hasSlelectedItems(target_list):
            something = target_list.selectedItems()[0].data(Qt.UserRole)[number]
            self.db.delete(something)
            self.search()


    # need refactoring
    def setRelationDescription(self):
        """This method retrieves information about relation,
        formats and sets it in description field.
        """
        if hasSlelectedItems(self.relation_list):
            relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2]
            concept1 = "{}{}".format(relation.node1.concept.name,
                                     ", {}".format(relation.node1.subcategory) if relation.node1.subcategory else "")
            concept2 = "{}{}".format(relation.node2.concept.name,
                                     ", {}".format(relation.node2.subcategory) if relation.node2.subcategory else "")

            description = relation.description
            study = relation.study
            references = relation.reference

            # HTML is used for a better information formating
            text = "<b>Relation between </b> \"{}\" <b>and</b> \"{}\"<p>".format(concept1, concept2)
            text += r"<b>Description:</b>" + "<br> {} <p>".format(description)
            text += r"<b>Study:</b> {} <p>".format(study)
            text += r"<b>References:</b><ol>"
            for ref in references:
                text += " <li> {} </li>".format(getBibRenderFromHTML(ref.text))
            text += "</ol><br>"
            self.result_table.setHtml(text)
        else:
            self.result_table.clear()

    # need refactoring
    def setConceptDescription(self):
        """This method retrieves information about concept,
        formats and sets it in description field.
        """
        if not self.concept_list.selectedItems():
            self.result_table.setHtml("")
            return 
        concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0]
        subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1]
        description = subcategory.description

        # HTML is used for a better information formating
        text = "<b>Concept:</b> {}<p>".format(concept.name)
        text += "<b>Subcategory:</b> {}<p>".format(subcategory.subcategory)
        text += "<b>Synonyms:</b> {}<p>".format(concept.synonyms)
        text += "<ol>"
        for des in description:
            text += "<li> {}".format("<b>Description:</b> <br>")
            text += "  {} <p>".format(des.text)
            text += "<ol>"
            text += "<b>References: </b>"
            for ref in des.reference:
                text += "<li>"
                text += "{}".format(getBibRenderFromHTML(ref.text))
                text += "</li>"
            text += "</ol>"
            text += "</li>"
        text += "</ol>"
        self.result_table.setHtml(text)


    def setResult(self, result, list):
        """This is a universal method for showing information
        in a relation field or in a concept field.
        """
        list.clear()
        for concept, subcategory, *other in result:
            item = QListWidgetItem()
            item.setData(Qt.UserRole, (concept, subcategory, *other))
            item.setText("{}{} {}".format(concept.name,
                                          "" if subcategory.subcategory == "" else ", ",
                                          subcategory.subcategory))
            list.insertItem(0, item)


    def search(self):
        subcategory, selected_items = self.getSearchData()
        result = self.db.search_nodes(subcategory, selected_items)
        self.setResult([], self.relation_list)
        self.setResult(result, self.concept_list)
        self.setResult([], self.relation_list)
        self.setRelationDescription()


    def configWidgets(self):
        self.grid.setAlignment(Qt.AlignTop)
        self.grid.setSpacing(5)

        self.menu_bar = QMenuBar(self)

        self.database_menu = self.menu_bar.addMenu("Database")
        self.database_menu.addAction(self.new_db_action)
        self.database_menu.addSeparator()
        self.database_menu.addAction(self.exit_action)

        self.concept_menu = self.menu_bar.addMenu("Concept")
        self.concept_menu.addAction(self.edit_concept_action)
        self.concept_menu.addAction(self.delete_сoncept_action)
        self.concept_menu.addAction(self.delete_subcategory_action)

        self.relation_menu = self.menu_bar.addMenu("Relation")
        self.relation_menu.addAction(self.edit_relation_action)
        self.relation_menu.addAction(self.delete_relation_action)

        self.help_menu = self.menu_bar.addMenu("Help")
        self.help_menu.addAction(self.help_action)
        self.help_menu.addAction(self.about_action)

        self.grid.setMenuBar(self.menu_bar)

        self.concept_box = QGroupBox("Concepts")
        self.concept_grid = QGridLayout()
        self.concept_grid.setContentsMargins(0, 10, 0, 0)
        self.concept_grid.addWidget(self.concept_list)
        self.concept_box.setLayout(self.concept_grid)

        self.relation_box = QGroupBox("Relations")
        self.relation_grid = QGridLayout()
        self.relation_grid.setContentsMargins(0, 10, 0, 0)
        self.relation_grid.addWidget(self.relation_list)
        self.relation_box.setLayout(self.relation_grid)

        self.description_box = QGroupBox("Description")
        self.description_grid = QGridLayout()
        self.description_grid.setContentsMargins(0, 10, 0, 0)
        self.description_grid.addWidget(self.result_table)
        self.description_box.setLayout(self.description_grid)

        self.concept_splitter = QSplitter(self)
        self.concept_splitter.addWidget(self.concept_box)
        self.concept_splitter.addWidget(self.relation_box)
        self.description_splitter = QSplitter(self)
        self.description_splitter.setOrientation(Qt.Vertical)
        self.description_splitter.addWidget(self.concept_splitter)
        self.description_splitter.addWidget(self.description_box)

        self.grid.addWidget(self.add_data_button, 1, 0, Qt.AlignLeft)
        self.grid.addWidget(self.export_button, 1, 1, Qt.AlignRight)
        self.grid.addWidget(self.search_box, 2, 0, 1, 2)
        self.grid.addWidget(self.description_splitter, 5, 0, 1, 2)
        self.setLayout(self.grid)


    def bindWidgets(self):
        self.add_data_button.clicked.connect(self.addData)
        self.search_button.clicked.connect(self.search)
        self.export_button.clicked.connect(self.exportReferences)
        self.search_line.returnPressed.connect(self.search)
        
    def exportReferences(self):
        references = self.db.get_all_references()
        references = [getPlainText(ref.text) for ref in references]
        references = list(set(references))
        references = [prepareBibStr(ref) for ref in references]
        final_text = ",\n\n".join(references)
        
        dlg = QFileDialog()
        file_path = dlg.getSaveFileName(self, "Save bibtex file")[0]
        if not (file_path == ""):
            # todo: check readBibsFromFile
            try:
                with open(file_path, 'w') as f:
                    f.write(final_text)
            except Exception as error:
                showError(error)
                
        
    def addData(self):
        dlg = NewDataDialog(self.db)
        dlg.exec_()
        self.search()

    def getPath(self):
        dialog = NewDBDialog()
        if dialog.exec_():
            
            path = dialog.path
            with open("setting.py", "w") as f:
                f.write("{{ 'last': r'{0}' }}".format(path))
            return path
        else:
            self.close()


    def openDatabase(self):
        if os.path.exists("setting.py"):
            with open("setting.py") as f:
                setting = eval(f.read())
            if "last" in setting:
                if os.path.exists(setting["last"]):
                    path = setting["last"]
                else:
                    path = self.getPath()
            else:
                path = self.getPath()
        else:
            path = self.getPath()
        if path is None:
            self.close()
            exit(0)
        else:
            return Graph(path)
        
    def closeEvent(self, event):
        event.ignore()
Пример #8
0
class MainWindow(QWidget):
    """Main window class that provides logic of the program.
    Allows to search concept and to show
    information about concepts and relations """
    def __init__(self, application):
        super().__init__()
        self.application = application
        self.db = self.openDatabase()
        self._initUI()


    def initActions(self):
        """initalization of actions for main windows"""

        self.help_action = QAction("&Help", self)
        self.help_action.setShortcut("F1")
        self.help_action.setStatusTip('Help')
        self.help_action.triggered.connect(lambda: HelpDialog(self))

        self.new_db_action = QAction("New DB", self)
        self.new_db_action.setShortcut("Ctrl+N")
        self.new_db_action.triggered.connect(self.openNewDB)

        self.delete_сoncept_action = QAction("&Delete", self)
        self.delete_сoncept_action.setShortcut("DEL")
        self.delete_сoncept_action.setStatusTip("Delete")
        self.delete_сoncept_action.triggered.connect(lambda: self.delete(Concept))

        self.delete_subcategory_action = QAction("&Delete subcategory", self)
        self.delete_subcategory_action.triggered.connect(lambda: self.delete(Subcategory))

        self.edit_concept_action = QAction("&Edit", self)
        self.edit_concept_action.setShortcut("F2")
        self.edit_concept_action.triggered.connect(self.editConcept)

        self.edit_relation_action = QAction("&Edit", self)
        self.edit_relation_action.setShortcut("Ctrl+F2")
        self.edit_relation_action.triggered.connect(self.editRelation)

        self.exit_action = QAction("&Exit", self)
        self.exit_action.setShortcut("ESC")
        self.exit_action.triggered.connect(self.close)

        self.select_relation_action = QAction("&Select relation", self)
        self.select_relation_action.triggered.connect(self.setRelationDescription)

        self.delete_relation_action = QAction("&Delete", self)
        self.delete_relation_action.setShortcut("Ctrl+DEL")
        self.delete_relation_action.triggered.connect(lambda: self.delete(Relation))


    def openNewDB(self):
        """This method deletes setting.py file and closes current application session.
        This uses for creating a new instance of Main Window.
        """
        if os.path.exists("setting.py"):
            os.remove("setting.py")
            self.application.exit(1)


    def _initUI(self):
        self.setWindowIcon(QIcon("logo.png"))
        self.setWindowTitle('GraphNotes')
        self.resize(1000, 700)
        self.initActions()
        self.add_data_button = QPushButton("Add data", self)
        self.search_box = QGroupBox()
        self._initSearchFrame(self.search_box)
        self.concept_list = QListWidget(self)
        self.relation_list = QListWidget(self)
        self.result_table = QTextEdit(self)
        self.concept_list.itemClicked.connect(self.searchRelations)
        self.concept_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.concept_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.concept_list.customContextMenuRequested.connect(self._showConceptContextMenu)
        self.relation_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.relation_list.customContextMenuRequested.connect(self._showRelationContextMenu)
        self.relation_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.relation_list.itemClicked.connect(self.setRelationDescription)
        self.grid = QGridLayout()
        self.result_table.setReadOnly(True)
        self.search()
        self._configWidgets()
        self._bindWidgets()
        self.show()


    def _showConceptContextMenu(self, pos):
        global_position = self.concept_list.mapToGlobal(pos)
        my_menu = QMenu()
        my_menu.addAction(self.edit_concept_action)
        my_menu.addAction(self.delete_сoncept_action)
        my_menu.addAction(self.delete_subcategory_action)
        my_menu.addSeparator()
        my_menu.addAction(self.help_action)
        my_menu.addAction(self.exit_action)
        my_menu.exec(global_position)


    def _initSearchFrame(self, frame):
        self.search_line = QLineEdit(frame)
        checkboxes = QGroupBox()
        checkboxes.setStyleSheet("border:0;")
        self.concept_checkbox = QCheckBox("Concept", checkboxes)
        self.description_checkbox = QCheckBox("Description", checkboxes)
        self.study_checkbox = QCheckBox("Study", checkboxes)
        self.search_button = QPushButton("Search", checkboxes)
        checkboxes_layout = QGridLayout(checkboxes)
        checkboxes_layout.addWidget(self.concept_checkbox, 0, 0)
        checkboxes_layout.addWidget(self.description_checkbox, 0, 1)
        checkboxes_layout.addWidget(self.study_checkbox, 0, 2)
        checkboxes_layout.setContentsMargins(0, 0, 0, 0)
        self.concept_checkbox.setChecked(True)
        grid = QGridLayout(frame)
        grid.addWidget(self.search_line, 1, 0)
        grid.addWidget(self.search_button, 1, 1)
        grid.addWidget(checkboxes, 2, 0, Qt.AlignLeft)
        frame.setLayout(grid)


    def getSearchData(self):
        """This method reads parameters of search line and checkboxes,
        and returns "Subcategory" class.
        None and [] uses for showing checkboxes that have been checked.
        """
        concept = self.search_line.text() if self.concept_checkbox.isChecked() else None
        description = [Description(text=self.search_line.text())] if self.description_checkbox.isChecked() else []
        study = self.search_line.text() if self.study_checkbox.isChecked() else None
        return Subcategory(subcategory=concept, description=description, study=study)


    def searchRelations(self):
        """This method triggers when the user clicked on the concept.
        This method selected ID of a subcategory from selected item in conceptions list
        and then searches and setting all information about this selected concept.
        """
        subcategory_id = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1].id
        self.setConceptDescription()
        result = self.db.search_relation(subcategory_id)
        self.setResult(result, self.relation_list)


    def _showRelationContextMenu(self, pos):
        global_position = self.relation_list.mapToGlobal(pos)
        my_menu = QMenu()
        my_menu.addAction(self.edit_relation_action)
        my_menu.addAction(self.delete_relation_action)
        my_menu.addSeparator()
        my_menu.exec(global_position)


    def editRelation(self):
        """This method opens dialog for editing Relation"""

        if self.relation_list.currentIndex().isValid():
            relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2]
            dlg = EditRelationDialog(self, relation)
            if dlg.exec_():
                relation = dlg.getValue()
                self.db.update_relation(relation)
                self.select_relation_action.trigger()


    def editConcept(self):
        """This method opens dialog for editing Concept"""
        if self.concept_list.currentIndex().isValid():
            concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0]
            subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1]
            dlg = EditConceptDialog(self, concept, subcategory)
            if dlg.exec_():
                concept, subcategory = dlg.getValue()
                self.db.update_concept(concept)
                self.db.update_subcategory(subcategory)
                self.search()


    def delete(self, something):
        """This universal method for deleting something from the list and database.
        "something" parameter needs to be any of this types: Concept, Subcategory, Relation
        """
        if something == Concept:
            number = 0
            target_list = self.concept_list
        elif something == Subcategory:
            number = 1
            target_list = self.concept_list
        elif something == Relation:
            number = 2
            target_list = self.relation_list
        if target_list.currentIndex().isValid():
            something = target_list.selectedItems()[0].data(Qt.UserRole)[number]
            self.db.delete(something)
            self.search()


    def setRelationDescription(self):
        """This method retrieves information about relation,
        formats and sets it in description field.
        """
        if self.relation_list.currentIndex().isValid():
            relation = self.relation_list.selectedItems()[0].data(Qt.UserRole)[2]
            concept1 = "{}{}".format(relation.node1.concept.name,
                                     ", {}".format(relation.node1.subcategory) if relation.node1.subcategory else "")
            concept2 = "{}{}".format(relation.node2.concept.name,
                                     ", {}".format(relation.node2.subcategory) if relation.node2.subcategory else "")

            description = relation.description
            study = relation.study
            references = relation.reference

            # HTML is used for a better information formating
            text = "<b>Relation between </b> \"{}\" <b>and</b> \"{}\"<p>".format(concept1, concept2)
            text += r"<b>Description:</b>" + "<br> {} <p>".format(description)
            text += r"<b>Study:</b> {} <p>".format(study)
            text += r"<b>References:</b><ol>"
            for ref in references:
                text += " <li> {} </li>".format(ref.text)
            text += "</ol><br>"
            self.result_table.setText(text)
        else:
            self.result_table.clear()


    def setConceptDescription(self):
        """This method retrieves information about concept,
        formats and sets it in description field.
        """
        concept = self.concept_list.selectedItems()[0].data(Qt.UserRole)[0]
        subcategory = self.concept_list.selectedItems()[0].data(Qt.UserRole)[1]
        description = subcategory.description

        # HTML is used for a better information formating
        text = "<b>Concept:</b> {}<p>".format(concept.name)
        text += "<b>Subcategory:</b> {}<p>".format(subcategory.subcategory)
        text += "<b>Synonyms:</b> {}<p>".format(concept.synonyms)
        text += "<ol>"
        for des in description:
            text += "<li> {}".format("<b>Description:</b> <br>")
            text += "  {} <p>".format(des.text)
            text += "<ol>"
            text += "<b>References: </b>"
            for ref in des.reference:
                text += "<li>"
                text += "{}".format(ref.text)
                text += "</li>"
            text += "</ol>"
            text += "</li>"
        text += "</ol>"
        self.result_table.setText(text)


    def setResult(self, result, list):
        """This is a universal method for showing information
        in a relation field or in a concept field.
        """
        list.clear()
        for concept, subcategory, *other in result:
            item = QListWidgetItem()
            item.setData(Qt.UserRole, (concept, subcategory, *other))
            item.setText("{}{} {}".format(concept.name,
                                          "" if subcategory.subcategory == "" else ", ",
                                          subcategory.subcategory))
            list.insertItem(0, item)


    def search(self):
        parameters = self.getSearchData()
        result = self.db.search_nodes(parameters)
        self.setResult([], self.relation_list)
        self.setResult(result, self.concept_list)
        self.setResult([], self.relation_list)
        self.setRelationDescription()


    def _configWidgets(self):
        self.grid.setAlignment(Qt.AlignTop)
        self.grid.setSpacing(5)

        self.menu_bar = QMenuBar(self)

        self.database_menu = self.menu_bar.addMenu("Database")
        self.database_menu.addAction(self.new_db_action)
        self.database_menu.addSeparator()
        self.database_menu.addAction(self.exit_action)

        self.concept_menu = self.menu_bar.addMenu("Concept")
        self.concept_menu.addAction(self.edit_concept_action)
        self.concept_menu.addAction(self.delete_сoncept_action)
        self.concept_menu.addAction(self.delete_subcategory_action)

        self.relation_menu = self.menu_bar.addMenu("Relation")
        self.relation_menu.addAction(self.edit_relation_action)
        self.relation_menu.addAction(self.delete_relation_action)

        self.help_menu = self.menu_bar.addMenu("Help")
        self.help_menu.addAction(self.help_action)

        self.grid.setMenuBar(self.menu_bar)

        self.concept_box = QGroupBox("Concepts")
        self.concept_grid = QGridLayout()
        self.concept_grid.setContentsMargins(0, 10, 0, 0)
        self.concept_grid.addWidget(self.concept_list)
        self.concept_box.setLayout(self.concept_grid)

        self.relation_box = QGroupBox("Relations")
        self.relation_grid = QGridLayout()
        self.relation_grid.setContentsMargins(0, 10, 0, 0)
        self.relation_grid.addWidget(self.relation_list)
        self.relation_box.setLayout(self.relation_grid)

        self.description_box = QGroupBox("Description")
        self.description_grid = QGridLayout()
        self.description_grid.setContentsMargins(0, 10, 0, 0)
        self.description_grid.addWidget(self.result_table)
        self.description_box.setLayout(self.description_grid)

        self.concept_splitter = QSplitter(self)
        self.concept_splitter.addWidget(self.concept_box)
        self.concept_splitter.addWidget(self.relation_box)
        self.description_splitter = QSplitter(self)
        self.description_splitter.setOrientation(Qt.Vertical)
        self.description_splitter.addWidget(self.concept_splitter)
        self.description_splitter.addWidget(self.description_box)

        self.grid.addWidget(self.add_data_button, 1, 0, Qt.AlignLeft)
        self.grid.addWidget(self.search_box, 2, 0, 1, 2)
        self.grid.addWidget(self.description_splitter, 5, 0, 1, 2)
        self.setLayout(self.grid)


    def _bindWidgets(self):
        self.add_data_button.clicked.connect(self.addData)
        self.search_button.clicked.connect(self.search)
        self.search_line.returnPressed.connect(self.search)


    def addData(self):
        dlg = NewDataDialog(self.db)
        dlg.exec_()
        self.search()


    def getPath(self):
        dialog = NewDBDialog()
        if dialog.exec_():
            print("EXEc")
            path = dialog.path
            with open("setting.py", "w") as f:
                f.write("{{ 'last': r'{0}' }}".format(path))
            return path
        else:
            self.close()


    def openDatabase(self):
        if os.path.exists("setting.py"):
            with open("setting.py") as f:
                setting = eval(f.read())
            if "last" in setting:
                if os.path.exists(setting["last"]):
                    path = setting["last"]
                else:
                    path = self.getPath()
            else:
                path = self.getPath()
        else:
            path = self.getPath()
        if path is None:
            self.close()
            exit(0)
        else:
            return Graph(path)
Пример #9
0
class MainWin(QMainWindow):
    def __init__(self, fileName=None, logName=None, parent=None):
        super(MainWin, self).__init__(parent)

        #self.setWindowIcon(QIcon(':/images/logo.png'))
        self.setToolButtonStyle(Qt.ToolButtonFollowStyle)
        self.setupFileActions()
        self.setupEditActions()
        self.setupTextActions()
        self.setupRunActions()
        self.initializeSettings()
        self.populateRunSettings()  # FIXME put in initializeSettings()?
        
        settingsMenu = QMenu('Settings', self)
        self.menuBar().addMenu(settingsMenu)
        settingsMenu.addAction('Configure...', self.configure)

        helpMenu = QMenu("Help", self)
        self.menuBar().addMenu(helpMenu)
        helpMenu.addAction("About", self.about)
        helpMenu.addAction("About &Qt", QApplication.instance().aboutQt)
 
        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Vertical)
        self.textPane = TextPane()
        self.logPane = LogPane()
        self.logBox = QGroupBox()
        self.logBox.setFlat(True)
        vbox = QVBoxLayout()
        vbox.addWidget(self.logPane)
        self.logBox.setLayout(vbox)
        self.splitter.addWidget(self.textPane)
        self.splitter.addWidget(QLabel()) # spacer
        self.splitter.addWidget(self.logBox)
        self.setCentralWidget(self.splitter)

        self.loadSrc(fileName)
        self.loadLog(logName)
        #if logName and (-1 == self.comboLogFile.findText(logName)):
            #self.comboLogFile.addItem(logName)

        self.logPane.setFocus()
        self.fontChanged(self.textPane.font())
        self.textPane.document().modificationChanged.connect(self.actionSave.setEnabled)
        self.textPane.document().modificationChanged.connect(self.setWindowModified)
        self.textPane.document().undoAvailable.connect(self.actionUndo.setEnabled)
        self.textPane.document().redoAvailable.connect( self.actionRedo.setEnabled)
        self.setWindowModified(self.textPane.document().isModified())
        self.actionSave.setEnabled(self.textPane.document().isModified())
        self.actionUndo.setEnabled(self.textPane.document().isUndoAvailable())
        self.actionRedo.setEnabled(self.textPane.document().isRedoAvailable())
        self.actionUndo.triggered.connect(self.textPane.undo)
        self.actionRedo.triggered.connect(self.textPane.redo)
        self.actionCut.setEnabled(False)
        self.actionCopy.setEnabled(False)
        self.actionCut.triggered.connect(self.textPane.cut)
        self.actionCopy.triggered.connect(self.textPane.copy)
        self.actionPaste.triggered.connect(self.textPane.paste)
        self.textPane.copyAvailable.connect(self.actionCut.setEnabled)
        self.textPane.copyAvailable.connect(self.actionCopy.setEnabled)
        QApplication.clipboard().dataChanged.connect(self.clipboardDataChanged)
        
        self.actionRun.triggered.connect(self.scannoCheck)       
        self.logPane.lineMatchChanged.connect(self.logLineMatchChanged)

    def closeEvent(self, e):
        if self.maybeSave():
            e.accept()
        else:
            e.ignore()

    def setupFileActions(self):
        tb = QToolBar(self)
        tb.setWindowTitle("File Actions")
        self.addToolBar(tb)

        menu = QMenu("&File", self)
        self.menuBar().addMenu(menu)

        self.actionNew = QAction("&New", self, priority=QAction.LowPriority,
                shortcut=QKeySequence.New, triggered=self.fileNew)
        tb.addAction(self.actionNew)
        menu.addAction(self.actionNew)

        self.actionOpen = QAction("&Open...", self, shortcut=QKeySequence.Open,
                triggered=self.fileOpen)
        tb.addAction(self.actionOpen)
        menu.addAction(self.actionOpen)
        menu.addSeparator()

        self.actionSave = QAction("&Save", self, shortcut=QKeySequence.Save,
                triggered=self.fileSave, enabled=False)
        tb.addAction(self.actionSave)
        menu.addAction(self.actionSave)

        self.actionSaveAs = QAction("Save &As...", self, priority=QAction.LowPriority,
                shortcut=Qt.CTRL + Qt.SHIFT + Qt.Key_S, triggered=self.fileSaveAs)
        menu.addAction(self.actionSaveAs)
        menu.addSeparator()
 
        self.actionQuit = QAction("&Quit", self, shortcut=QKeySequence.Quit, triggered=self.close)
        menu.addAction(self.actionQuit)

    def setupEditActions(self):
        tb = QToolBar(self)
        tb.setWindowTitle("Edit Actions")
        self.addToolBar(tb)

        menu = QMenu("&Edit", self)
        self.menuBar().addMenu(menu)

        self.actionUndo = QAction("&Undo", self, shortcut=QKeySequence.Undo)
        tb.addAction(self.actionUndo)
        menu.addAction(self.actionUndo)

        self.actionRedo = QAction("&Redo", self, priority=QAction.LowPriority, shortcut=QKeySequence.Redo)
        tb.addAction(self.actionRedo)
        menu.addAction(self.actionRedo)
        menu.addSeparator()

        self.actionCut = QAction("Cu&t", self, priority=QAction.LowPriority, shortcut=QKeySequence.Cut)
        tb.addAction(self.actionCut)
        menu.addAction(self.actionCut)

        self.actionCopy = QAction("&Copy", self, priority=QAction.LowPriority, shortcut=QKeySequence.Copy)
        tb.addAction(self.actionCopy)
        menu.addAction(self.actionCopy)

        self.actionPaste = QAction("&Paste", self, priority=QAction.LowPriority,
                shortcut=QKeySequence.Paste, enabled=(len(QApplication.clipboard().text()) != 0))
        tb.addAction(self.actionPaste)
        menu.addAction(self.actionPaste)

    def setupTextActions(self):
        tb = QToolBar(self)
        tb.setWindowTitle("Format Actions")
        self.addToolBar(tb)

        tb = QToolBar(self)
        tb.setAllowedAreas(Qt.TopToolBarArea | Qt.BottomToolBarArea)
        tb.setWindowTitle("Format Actions")
        self.addToolBarBreak(Qt.TopToolBarArea)
        self.addToolBar(tb)

        self.comboFont = QFontComboBox(tb)
        tb.addWidget(self.comboFont)
        self.comboFont.activated[str].connect(self.textFamily)

        self.comboSize = QComboBox(tb)
        self.comboSize.setObjectName("comboSize")
        tb.addWidget(self.comboSize)
        self.comboSize.setEditable(True)

        db = QFontDatabase()
        for size in db.standardSizes():
            self.comboSize.addItem('{}'.format(size))

        self.comboSize.activated[str].connect(self.textSize)
        self.comboSize.setCurrentIndex(self.comboSize.findText('{}'.format(QApplication.font().pointSize())))
        
    def setupRunActions(self):
        tb = QToolBar(self)
        tb.setWindowTitle("Run Actions")
        self.addToolBar(tb)

        menu = QMenu("Run", self)
        self.menuBar().addMenu(menu)

        self.actionRun = QAction(
                "&Run", self, shortcut=Qt.CTRL + Qt.Key_R)
        tb.addAction(self.actionRun)
        menu.addAction(self.actionRun)

        self.comboScannoFile = QComboBox(tb)
        self.comboScannoFile.setObjectName("comboScannoFile")
        tb.addWidget(self.comboScannoFile)
        self.comboScannoFile.setEditable(True)
        
        self.comboLogFile= QComboBox(tb)
        self.comboLogFile.setObjectName("comboLogFile")
        self.comboLogFile.setEditable(True)
        tb.addWidget(self.comboLogFile)
    
    def populateRunSettings(self):
        for f in self.scannoFiles():
            self.comboScannoFile.addItem(f)
        if self.defaultScannoFile:
            idx = self.comboScannoFile.findText(self.defaultScannoFile)
            self.comboScannoFile.setCurrentIndex(idx)

        self.comboLogFile.addItem('plog.txt')

    def loadSrc(self, src):
        if src:
            if not self.textPane.load(src):
                return False
        self.setCurrentFileName(src)
        return True

    def loadLog(self, log):
        if log:
            if not self.logPane.load(log):
                return False
            self.comboLogFile.clear()
            self.comboLogFile.addItem(log)
        else:
            self.logPane.clear()
            self.logPane.setEnabled(False)
            self.logBox.setTitle(self.tr('No log file loaded.'))
        return True
        
    def maybeSave(self):
        if not self.textPane.document().isModified():
            return True

        ret = QMessageBox.warning(self, 'GuiScannos',
                'The document has been modified.\n'
                'Do you want to save your changes?',
                QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)

        if ret == QMessageBox.Save:
            return self.fileSave()

        if ret == QMessageBox.Cancel:
            return False

        return True

    def setCurrentFileName(self, fileName=''):
        self.fileName = fileName
        self.textPane.document().setModified(False)

        if not fileName:
            shownName = 'untitled.txt'
            self.actionRun.setEnabled(False)
        else:
            shownName = QFileInfo(fileName).fileName()
            self.actionRun.setEnabled(True)

        self.setWindowTitle(self.tr('{}[*] - {}'.format(shownName, 'GUI Scannos')))
        self.setWindowModified(False)

    def fileNew(self):
        if self.maybeSave():
            self.textPane.clear()
            self.loadLog(None)  # clears logPane, logBox title, etc
            self.setCurrentFileName()

    def fileOpen(self):
        fn, _ = QFileDialog.getOpenFileName(self, 'Open File...', None, 'Text Files (*.txt);;All Files (*)')
        if fn:
            self.loadSrc(fn)
            self.loadLog(None)  # clears logPane, logBox title, etc

    def fileSave(self):
        if not self.fileName:
            return self.fileSaveAs()

        return self.textpane.save(self.fileName)

    def fileSaveAs(self):
        fn, _ = QFileDialog.getSaveFileName(self, "Save as...", None, "text files (*.txt);;All Files (*)")

        if not fn:
            return False

        self.setCurrentFileName(fn)
        return self.fileSave()

    def logLineMatchChanged(self):
        linenum = self.logPane.srcLineNum()
        col = self.logPane.srcColNum()
        s = self.logPane.srcScanno()
        self.textPane.setSelection(linenum, col, len(s))
    
    def textFamily(self, family):
        """Set font family for text and log panes."""
        
        self.textPane.setFontFamily(family)
        self.logPane.setFontFamily(family)

    def textSize(self, pointSize):
        """Set font size for text and log panes."""
        
        self.textPane.setFontPointSize(pointSize)
        self.logPane.setFontPointSize(pointSize)

    def clipboardDataChanged(self):
        self.actionPaste.setEnabled(len(QApplication.clipboard().text()) != 0)

    def about(self):
        QMessageBox.about(self, 'About', 'GUI for ppscannos.')

    def fontChanged(self, font):
        self.comboFont.setCurrentIndex(self.comboFont.findText(QFontInfo(font).family()))
        self.comboSize.setCurrentIndex(self.comboSize.findText('{}'.format(font.pointSize())))
        
    def scannoCheck(self):
        """Run ppscannos."""
        
        scannodir = os.path.dirname(self.ppscannos)
        cmd = sys.executable
        assert(cmd)
        scannoFile = self.comboScannoFile.currentText()
        if not scannoFile:
            scannoFile = self.defaultScannoFile
        scannoFile = scannodir + '/' + scannoFile
        src = self.fileName
        log = self.comboLogFile.currentText()
        if not log:
            log = './plog.txt'
        subprocess.call([cmd, self.ppscannos, '-s' + scannoFile, '-o' + log, '-i' + src])
        self.loadLog(log)
        self.logPane.setEnabled(True)
        
    def configure(self):
        """Configure application settings by way of a dialog."""
        
        dlg = ConfigDialog()
        if dlg.exec():
            self.setPPScannos(dlg.lineEditPPScannos.text())
            self.setDefaultScannoFile(dlg.comboScannoFiles.currentText())
            settings = QSettings(QApplication.organizationName(), QApplication.applicationName())
            settings.setValue('ppscannos', self.ppscannos)
            settings.setValue('defaultScannoFile', self.defaultScannoFile)

    def setPPScannos(self, s):
        self.ppscannos = s
        self.actionRun.setEnabled(self.ppscannos and os.path.exists(self.ppscannos))
        
    def scannoFiles(self):
        """Return list of .rc filenames (without path) that are in ppscannos directory."""
        
        if not self.ppscannos:
            return []
        return getRCFilesForDir(os.path.dirname(self.ppscannos))
        
    def setDefaultScannoFile(self, s):
        self.defaultScannoFile = s
        valid = False
        if self.defaultScannoFile and self.ppscannos and os.path.exists(self.ppscannos):
            if os.path.exists(os.path.dirname(self.ppscannos) + '/' + self.defaultScannoFile):
                valid = True
        self.actionRun.setEnabled(valid)
        
    def initializeSettings(self):
        """Load persistent config settings."""
        
        settings = QSettings()
        s = settings.value('ppscannos', type=str)
        if not s:
            # try the default
            s = os.path.expanduser('~') + '/ppscannos1/ppscannos1.py'
            #s = os.environ['HOME'] + '/ppscannos1/ppscannos1.py'
        self.setPPScannos(s)
        
        s = settings.value('defaultScannoFile', type=str)
        if (not s) and self.ppscannos:
            # try the default
            lst = getRCFilesForDir(os.path.dirname(self.ppscannos))
            if len(lst):
                # prefer 'regex.rc'; otherwise use the first one
                s = lst[0]
                for f in lst:
                    if f == 'regex.rc':
                        s = f
                        break
        self.setDefaultScannoFile(s)