"""
Implementation of Qt dialog boxes used by multiple sequence viewer.
Copyright Schrodinger, LLC. All rights reserved.
"""
# Contributors: Piotr Rotkiewicz
import glob
import math
import os
from past.utils import old_div
from schrodinger.infra import canvas2d
try:
    from schrodinger.Qt import QtCore
    from schrodinger.Qt import QtGui
    from schrodinger.Qt import QtWidgets
except:
    QtCore = None
    QtGui = None
    QtWidgets = None
# Canvas license for 2D tooltips
try:
    from schrodinger.application.canvas.base import ChmLicenseShared_isValid
    from schrodinger.application.canvas.utils import get_license
    if not ChmLicenseShared_isValid():
        canvas_license = get_license("LICENSE_SHARED")
except:
    raise
    canvas_license = None
_BLAST_RESULTS_DIALOG = None
_BLAST_SETTINGS_DIALOG = None
[docs]def createBlastSettingsDialog(parent, execute=True):
    dialog = BlastSettingsDialog(parent)
    if execute:
        _BLAST_SETTINGS_DIALOG.exec_()
    return dialog 
[docs]class BlastSettingsDialog(QtWidgets.QDialog):
[docs]    def __init__(self, parent):
        # Initialize base class.
        QtWidgets.QDialog.__init__(self, parent)
        self.setWindowTitle("Blast Search Settings")
        self.viewer = parent
        #Start Job button
        self.button_remove = QtWidgets.QPushButton(self)
        self.button_remove.setText("Start Job")
        self.button_remove.setDefault(True)
        self.button_remove.setToolTip("Start BLAST search job")
        self.button_remove.clicked.connect(self.accept)
        #Cancel button
        self.button_cancel = QtWidgets.QPushButton(self)
        self.button_cancel.setText("Cancel")
        self.button_cancel.setToolTip("Cancel search")
        self.button_cancel.clicked.connect(self.reject)
        self.button_layout = QtWidgets.QHBoxLayout()
        self.button_layout.addWidget(self.button_remove)
        self.button_layout.addWidget(self.button_cancel)
        self.layout = QtWidgets.QVBoxLayout(self)
        options_layout = QtWidgets.QVBoxLayout()
        program_choice_layout = QtWidgets.QHBoxLayout()
        program_choice_layout.addWidget(QtWidgets.QLabel("Search Tool:"))
        self.blast_button = QtWidgets.QRadioButton("BLAST")
        self.blast_button.setChecked(True)
        self.blast_button.setToolTip("Single iteration BLAST search")
        self.blast_button.clicked.connect(self.blastButtonClicked)
        program_choice_layout.addWidget(self.blast_button)
        self.psiblast_button = QtWidgets.QRadioButton("PSI-BLAST")
        self.psiblast_button.setChecked(False)
        self.psiblast_button.setToolTip(
            "Position-specific iterative BLAST search")
        program_choice_layout.addWidget(self.psiblast_button)
        self.psiblast_button.clicked.connect(self.psiblastButtonClicked)
        options_layout.addLayout(program_choice_layout)
        server_choice_layout = QtWidgets.QHBoxLayout()
        server_choice_layout.addWidget(QtWidgets.QLabel("BLAST Server:"))
        self.local_button = QtWidgets.QRadioButton("Local")
        self.local_button.setChecked(True)
        self.local_button.setToolTip("Use local BLAST installation")
        server_choice_layout.addWidget(self.local_button)
        self.remote_button = QtWidgets.QRadioButton("Remote (NCBI)")
        self.remote_button.setChecked(False)
        self.remote_button.setToolTip(
            "Use remote BLAST server at http://www.ncbi.nlm.hiv.gov")
        server_choice_layout.addWidget(self.remote_button)
        self.server_choice_group = QtWidgets.QButtonGroup()
        self.server_choice_group.addButton(self.local_button)
        self.server_choice_group.addButton(self.remote_button)
        options_layout.addLayout(server_choice_layout)
        options_layout.addWidget(QtWidgets.QLabel("Similarity Matrix:"))
        self.matrix_choice = QtWidgets.QComboBox(self)
        self.matrix_choice.setToolTip("Substitution matrix")
        for matrix in ["BLOSUM62", "BLOSUM80", "BLOSUM45", "PAM30", "PAM70"]:
            self.matrix_choice.addItem(matrix)
        options_layout.addWidget(self.matrix_choice)
        options_layout.addWidget(QtWidgets.QLabel("Gap Costs:"))
        self.gap_choice = QtWidgets.QComboBox(self)
        for gap in [
                "Exist: 11 Extend: 1", "Exist: 10 Extend: 1",
                "Exist: 12 Extend: 1", "Exist:  9 Extend: 2",
                "Exist:  8 Extend: 2", "Exist:  7 Extend: 2"
        ]:
            self.gap_choice.addItem(gap)
        options_layout.addWidget(self.gap_choice)
        self.evalue_input = QtWidgets.QDoubleSpinBox(self)
        self.evalue_input.setValue(1.0)
        self.evalue_input.setMinimum(-10.0)
        self.evalue_input.setMaximum(10.0)
        self.evalue_input.setEnabled(True)
        self.evalue_label = QtWidgets.QLabel("Expectation Value Threshold:")
        self.evalue_label.setEnabled(True)
        options_layout.addWidget(self.evalue_label)
        evalue_layout = QtWidgets.QHBoxLayout()
        evalue_layout.addWidget(QtWidgets.QLabel("10 ^ "))
        evalue_layout.addWidget(self.evalue_input)
        evalue_layout.addStretch()
        options_layout.addLayout(evalue_layout)
        word_choice_layout = QtWidgets.QHBoxLayout()
        word_choice_layout.addWidget(QtWidgets.QLabel("Word Size:"))
        self.word_2_button = QtWidgets.QRadioButton("2")
        self.word_2_button.setChecked(False)
        word_choice_layout.addWidget(self.word_2_button)
        self.word_3_button = QtWidgets.QRadioButton("3")
        self.word_3_button.setChecked(True)
        word_choice_layout.addWidget(self.word_3_button)
        word_choice_layout.addStretch()
        self.word_size_group = QtWidgets.QButtonGroup()
        self.word_size_group.addButton(self.word_2_button)
        self.word_size_group.addButton(self.word_3_button)
        options_layout.addLayout(word_choice_layout)
        self.filter_query = QtWidgets.QCheckBox()
        self.filter_query.setText("Filter Query")
        options_layout.addWidget(self.filter_query)
        self.iter_input = QtWidgets.QSpinBox(self)
        self.iter_input.setValue(3)
        self.iter_input.setMinimum(1)
        self.iter_input.setMaximum(10)
        self.iter_input.setEnabled(False)
        self.iter_label = QtWidgets.QLabel("Number of Iterations:")
        self.iter_label.setEnabled(False)
        options_layout.addWidget(self.iter_label)
        options_layout.addWidget(self.iter_input)
        self.threshold_input = QtWidgets.QDoubleSpinBox(self)
        self.threshold_input.setDecimals(3)
        self.threshold_input.setValue(0.005)
        self.threshold_input.setMinimum(1e-10)
        self.threshold_input.setMaximum(1e6)
        self.threshold_input.setEnabled(False)
        self.threshold_label = QtWidgets.QLabel("Inclusion Threshold:")
        self.threshold_label.setEnabled(False)
        options_layout.addWidget(self.threshold_label)
        options_layout.addWidget(self.threshold_input)
        options_layout.addStretch()
        #self.download_pdb = QtWidgets.QCheckBox()
        # self.download_pdb.setChecked(False)
        #self.download_pdb.setText("Download PDB for all templates")
        # options_layout.addWidget(self.download_pdb)
        database_layout = QtWidgets.QVBoxLayout()
        database_layout.addWidget(QtWidgets.QLabel("Database:"))
        self.database_choice = QtWidgets.QComboBox(self)
        self.database_choice.addItem("NCBI PDB (non redundant)")
        self.database_choice.addItem("NCBI PDB (all)")
        self.database_choice.addItem("NCBI NR")
        self.database_choice.setCurrentIndex(1)
        database_layout.addWidget(self.database_choice)
        database_layout.addStretch()
        columns_layout = QtWidgets.QHBoxLayout()
        columns_layout.addLayout(options_layout)
        columns_layout.addLayout(database_layout)
        self.layout.addLayout(columns_layout)
        button_layout = QtWidgets.QHBoxLayout()
        button_layout.addStretch()
        button_layout.addWidget(self.button_remove)
        button_layout.addWidget(self.button_cancel)
        self.layout.addLayout(button_layout)
        self.sizePolicy().setVerticalPolicy(QtWidgets.QSizePolicy.Maximum) 
[docs]    def runRemotely(self):
        return self.remote_button.isChecked() 
[docs]    def getMatrix(self):
        return self.matrix_choice.currentText() 
[docs]    def getExpValue(self):
        return math.pow(10.0, self.evalue_input.value()) 
[docs]    def getProgramName(self):
        if self.blast_button.isChecked():
            return "blastp"
        else:
            return "blastpgp" 
[docs]    def getGapCosts(self):
        gap_costs = [(11, 1), (12, 1), (9, 2), (8, 2), (7, 2)]
        return gap_costs[self.gap_choice.currentIndex()] 
[docs]    def getIThreshold(self):
        return self.threshold_input.value() 
[docs]    def getNIter(self):
        return self.iter_input.value() 
[docs]    def getWordSize(self):
        if self.word_3_button.isChecked():
            return 3
        return 2 
[docs]    def getDatabase(self):
        if self.database_choice.currentIndex() == 2:
            return "nr"
        return "pdb" 
[docs]    def getExpandHits(self):
        if self.database_choice.currentIndex() == 1:
            return True
        return False 
[docs]    def getFilter(self):
        if self.filter_query.isChecked():
            return "true"
        return "false" 
[docs]    def getAllSettings(self):
        """
        Returns all settings.
        """
        settings = {}
        settings["database"] = self.getDatabase()
        settings["matrix"] = self.getMatrix()
        settings["filter"] = self.getFilter()
        settings["ehits"] = self.getExpandHits()
        settings["evalue"] = self.getExpValue()
        settings["word_size"] = self.getWordSize()
        settings["progname"] = self.getProgramName()
        settings["i_threshold"] = self.getIThreshold()
        settings["n_iter"] = self.getNIter()
        gap_open, gap_extend = self.getGapCosts()
        settings["gap_open"] = gap_open
        settings["gap_extend"] = gap_extend
        run_remotely = self.runRemotely()
        settings["remotely"] = run_remotely
        # BIOLUM-3968 - Limit remmote BLAST to 200 hits
        if run_remotely:
            settings['-num_hits'] = 200
        return settings  
[docs]class BlastResultsDialog(QtWidgets.QDialog):
    """
    This class implements a BLAST search results panel.
    """
[docs]    def __init__(self, parent):
        # Initialize base class.
        QtWidgets.QDialog.__init__(self, parent)
        self.viewer = parent
        self.setWindowTitle("BLAST Search Results")
        self.selectButton = QtWidgets.QPushButton("Select Top")
        self.topInput = QtWidgets.QLineEdit()
        self.topInput.setValidator(QtGui.QIntValidator(0, 0, self.topInput))
        self.topInput.setText("0")
        self.clearButton = QtWidgets.QPushButton("Clear")
        self.closeButton = QtWidgets.QPushButton("Close")
        self.incorporateButton = QtWidgets.QPushButton(
            "Incorporate Selected Rows")
        self.spacer = QtWidgets.QWidget()
        self.spacer.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Preferred)
        self.buttonLayout = QtWidgets.QHBoxLayout()
        self.buttonLayout.addWidget(self.selectButton)
        self.buttonLayout.addWidget(self.topInput)
        self.buttonLayout.addWidget(self.spacer)
        self.buttonLayout.addWidget(self.clearButton)
        self.buttonLayout.addWidget(self.closeButton)
        self.buttonLayout.addWidget(self.incorporateButton)
        self.header_labels = [
            "ID", "E-value", "Score", "Length", "Identity", "Similarity",
            "Homology", "% Gaps", "Sequence Name", "PDB Title",
            "PDB Compound Name", "PDB Source", "Exp. Method", "Resolution",
            "PDB Heteroatoms", "PDB Family"
        ]
        self.resultsTable = QtWidgets.QTableWidget(0, len(self.header_labels))
        self.resultsTable.setAlternatingRowColors(True)
        self.table_font = self.resultsTable.font()
        self.table_font.setPointSize(10)
        self.resultsTable.setFont(self.table_font)
        self.resultsTable.setHorizontalHeaderLabels(self.header_labels)
        self.resultsTable.resizeColumnsToContents()
        self.resultsTable.sortItems(1, QtCore.Qt.AscendingOrder)
        self.resultsTable.setMouseTracking(True)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.resultsTable)
        self.remote_search = False
        self.download_pdb = QtWidgets.QCheckBox()
        self.download_pdb.setChecked(False)
        self.download_pdb.setText(
            "Download PDB structures for all incorporated templates")
        self.layout.addWidget(self.download_pdb)
        self.layout.addLayout(self.buttonLayout)
        self.resultsTable.resizeColumnToContents(1)
        self.resultsTable.horizontalHeader().setStretchLastSection(True)
        self.resultsTable.setWordWrap(False)
        self.incorporateButton.setFocus(QtCore.Qt.OtherFocusReason)
        self.resultsTable.itemSelectionChanged.connect(self.selectionChanged)
        self.resultsTable.cellEntered.connect(self.cellEntered)
        self.selectButton.clicked.connect(self.selectTopRows)
        self.closeButton.clicked.connect(self.closeDialog)
        self.clearButton.clicked.connect(self.clearContents)
        self.incorporateButton.clicked.connect(self.incorporateResults)
        self.selecting = False
        self.resize(self.resultsTable.width() + 15, self.resultsTable.height())
        self.sequences = {}
        self.sequence_group = None
        self.has_pdb_info = False
        self.pdb_info = {}
        self.old_query = None
        self.new_query = None 
[docs]    def closeDialog(self):
        """
        Empties the list of selected sequences and closes the dialog.
        """
        self.close() 
[docs]    def clearContents(self):
        """
        Clears the dialog contents.
        """
        self.resultsTable.clearContents()
        for row in range(self.resultsTable.rowCount() - 1):
            self.resultsTable.removeRow(0)
        self.sequences = {}
        self.resultsTable.resizeColumnsToContents() 
[docs]    def setSequenceGroup(self, sequence_group):
        self.sequence_group = sequence_group 
[docs]    def setNewQuerySequence(self, old_query, new_query):
        """
        Sets a replacement query sequence to be used if user accepts and
        incorporates the results.
        :param old_query: original query sequence in viewer
        :type old_query: `Sequence`
        :param new_query: modified sequence with gaps after BLAST search
        :type new_query: `Sequence`
        """
        self.old_query = old_query
        self.new_query = new_query 
[docs]    def incorporateResults(self):
        """
        This method prepares a list of sequences to incorporate
        and closes the dialog.
        """
        all_new_sequences = []
        for index in self.resultsTable.selectionModel().selectedRows():
            name = self.resultsTable.item(index.row(), 0).text() + ":" + \
                
self.resultsTable.item(index.row(),
                    self.header_labels.index("Sequence Name")).text()
            if name in self.sequences:
                new_sequence = self.sequences[name].copyForUndo(deep_copy=False)
                all_new_sequences.append(new_sequence)
                self.sequence_group.sequences.append(new_sequence)
        if self.sequence_group:
            self.sequence_group.unselectAllSequences()
            if self.old_query in self.sequence_group.sequences:
                # Replace query sequence with aligned one
                idx = self.sequence_group.sequences.index(self.old_query)
                seq = self.sequence_group.sequences[idx]
                # Replace the sequence with the aligned one, while preseving
                # the same reference/hash/memory location. Fix for BIOLUM-2416:
                seq.__dict__.update(self.new_query.__dict__)
                self.old_query = None
                self.new_query = None
            self.sequence_group.minimizeAlignment()
            for res in self.sequence_group.reference.residues:
                res.sequence = self.sequence_group.reference
            for child in self.sequence_group.reference.children:
                child.parent_sequence = self.sequence_group.reference
            if self.viewer:
                self.viewer.contents_changed = True
                self.viewer.updateView()
            self.hide()
            if self.download_pdb.isChecked():
                for seq in all_new_sequences:
                    seq.selected = True
                if self.viewer:
                    self.viewer.downloadPDB(remote_query=not self.remote_search)
                    self.viewer.runClustal(ignore_selection=True)
            if self.viewer:
                self.viewer.contents_changed = True
                self.viewer.updateView()
        self.close() 
[docs]    def selectTopRows(self):
        """
        Selects top rows according to the value of topInput field.
        """
        self.resultsTable.setRangeSelected(
            QtWidgets.QTableWidgetSelectionRange(
                0, 0,
                self.resultsTable.rowCount() - 1,
                self.resultsTable.columnCount() - 1), False)
        n_rows = int(self.topInput.text())
        self.resultsTable.setRangeSelected(
            QtWidgets.QTableWidgetSelectionRange(
                0, 0, n_rows - 1,
                self.resultsTable.columnCount() - 1), True) 
[docs]    def selectionChanged(self):
        if self.selecting:
            return
        self.selecting = True
        for item in self.resultsTable.selectedItems():
            row = item.row()
            # Select the entire row.
            self.resultsTable.setRangeSelected(
                QtWidgets.QTableWidgetSelectionRange(
                    row, 0, row,
                    self.resultsTable.columnCount() - 1), True)
        self.selecting = False 
[docs]    def cellEntered(self, row, column):
        """
        cellEntered signal handler for tool tip generation.
        """
        if column == 14:  # LIGAND column
            item = self.resultsTable.item(row, column)
            smiles = str(item.data(QtCore.Qt.UserRole))
            if smiles:
                item.setData(QtCore.Qt.ToolTipRole,
                             self.generate2DToolTip(smiles))
            else:
                item.setData(QtCore.Qt.ToolTipRole, "") 
[docs]    def addRow(self,
               sequence,
               name="",
               score=0.0,
               length=0,
               coverage=0.0,
               identity=0.0,
               similarity=0.0,
               homology=0.0,
               resolution=-1.0,
               pdb_id="",
               evalue=0.0,
               tooltip=None):
        """
        This method adds a new row to the BLAST results table.
        """
        row = self.resultsTable.rowCount()
        self.resultsTable.insertRow(row)
        new_item = QtWidgets.QTableWidgetItem(pdb_id)
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 0, new_item)
        id = new_item.text()
        new_item = QTableWidgetNumericalItem()
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        new_item.setData(QtCore.Qt.DisplayRole, evalue)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 1, new_item)
        new_item = QTableWidgetNumericalItem()
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        new_item.setData(QtCore.Qt.DisplayRole, score)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 2, new_item)
        new_item = QTableWidgetNumericalItem()
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        new_item.setData(QtCore.Qt.DisplayRole, length)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 3, new_item)
        new_item = QTableWidgetNumericalItem()
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        new_item.setData(QtCore.Qt.DisplayRole, identity)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 4, new_item)
        new_item = QTableWidgetNumericalItem()
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        new_item.setData(QtCore.Qt.DisplayRole, similarity)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 5, new_item)
        new_item = QTableWidgetNumericalItem()
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        new_item.setData(QtCore.Qt.DisplayRole, homology)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 6, new_item)
        new_item = QTableWidgetNumericalItem()
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        new_item.setData(QtCore.Qt.DisplayRole, coverage)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 7, new_item)
        if not self.has_pdb_info:
            self.initPDBInfo()
        pdb_info_items = {
            "TITLE:": 9,
            "COMPND:": 10,
            "SOURCE:": 11,
            "EXPDTA:": 12,
            "RESOLUTION:": 13,
            "HETNAM:": 14,
            "PFAM:": 15
        }
        if self.has_pdb_info:
            #"PDB Title", "PDB Compound Name",
            #"PDB Source", "Exp. Method", "Resolution",
            #"PDB Heteroatoms", "PDB Family" ]
            if pdb_id in list(self.pdb_info):
                pdb_info = self.pdb_info[pdb_id]
                for item in list(pdb_info_items):
                    if item in pdb_info:
                        new_item = QtWidgets.QTableWidgetItem(pdb_info[item])
                        new_item.setFont(self.table_font)
                        new_item.setFlags(QtCore.Qt.ItemIsSelectable |
                                          QtCore.Qt.ItemIsEnabled)
                        if item == "HETNAM:":
                            if "HETSMILES:" in pdb_info:
                                new_item.setData(QtCore.Qt.UserRole,
                                                 pdb_info["HETSMILES:"])
                        elif tooltip:
                            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
                        self.resultsTable.setItem(row, pdb_info_items[item],
                                                  new_item)
        new_item = QtWidgets.QTableWidgetItem(name)
        new_item.setFont(self.table_font)
        new_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        if tooltip:
            new_item.setData(QtCore.Qt.ToolTipRole, tooltip)
        self.resultsTable.setItem(row, 8, new_item)
        id += ":" + new_item.text()
        self.sequences[id] = sequence
        self.topInput.validator().setTop(self.resultsTable.rowCount()) 
[docs]    def initPDBInfo(self):
        """
        Initialize PDB header info.
        """
        if self.has_pdb_info:
            return
        psp_exec = os.getenv("PSP_EXEC")
        if not psp_exec:
            psp_exec = glob.glob(os.getenv("SCHRODINGER") + os.sep + "psp-v*")
            if psp_exec:
                psp_exec = psp_exec[0]
        if psp_exec:
            header_file_name = psp_exec + os.sep + ".." + os.sep + ".." + \
                                
os.sep + "data" + os.sep + "headerinfo.dat"
            try:
                header_file = open(header_file_name, "r")
            except:
                header_file_name = psp_exec + os.sep + "data" + os.sep + \
                                    
"headerinfo.dat"
                try:
                    header_file = open(header_file_name, "r")
                except:
                    return False
        else:
            return False
        try:
            header_file = open(header_file_name, "r")
            lines = header_file.readlines()
            header_file.close()
        except:
            return False
        self.pdb_info = {}
        pdb_id = ""
        for line in lines:
            names = line.split(' ', 1)
            if len(names) > 1:
                key = names[0]
                text = names[1].rstrip()
                if key == "ID:":
                    pdb_id = text
                    self.pdb_info[pdb_id] = {}
                elif pdb_id:
                    self.pdb_info[pdb_id][key] = text
        self.has_pdb_info = True
        return True 
[docs]    def updateTableGeometry(self):
        self.resultsTable.resizeColumnsToContents()
        self.resultsTable.resizeRowsToContents()
        self.topInput.validator().setTop(self.resultsTable.rowCount())
        self.topInput.setText(str(self.resultsTable.rowCount())) 
[docs]    def show(self):
        """
        Shows the panel.
        """
        QtWidgets.QDialog.show(self)
        self.setCursor(QtCore.Qt.ArrowCursor)  
[docs]def createBlastResultsDialog(parent=None):
    """
    Creates and returns BLAST results dialog.
    """
    return BlastResultsDialog(parent=parent)