Example #1
0
    def __init__(self, parent=None):
        super(self.__class__, self).__init__()

        self.settings = QSettings("USGS", "pymdwizard")
        self.cur_fname = ""
        self.file_watcher = None

        # list of buttons for opening recently accessed files
        self.recent_file_actions = []
        # list of widgets that are currently styled as errors
        self.error_widgets = []
        # the last error widget that was highlighted
        self.last_highlight = None
        self.last_updated = None
        self.ui = None
        self.metadata_root = None
        self.build_ui()
        self.connect_events()
        self.env_cache = {}

        self.sb_file = False
        self.sb_locator = SBLocator(mainform=self)
        utils.set_window_icon(self.sb_locator)

        self.load_default()

        use_spelling = self.settings.value("use_spelling", "true")
        if isinstance(use_spelling, str):
            use_spelling = eval(use_spelling.capitalize())
        self.switch_spelling(use_spelling)
Example #2
0
    def add_contact(self):
        username = self.usgs_contact_ui.le_usgs_ad_name.text()
        # strip off the @usgs.gov if they entered one
        username = username.split("@")[0]

        if not username:
            return

        try:
            cntperp = utils.get_usgs_contact_info(username,
                                                  as_dictionary=False)
            if cntperp.getchildren()[0].getchildren()[0].text.strip():
                self.from_xml(cntperp)
                self.usgs_contact.deleteLater()
            else:
                msg = QMessageBox(self)
                utils.set_window_icon(msg)
                msg.setIcon(QMessageBox.Information)
                msg.setText("'{}' Not Found".format(username))
                msg.setInformativeText("The Metadata Wizard was unable to locate the provided user name in the USGS directory")
                msg.setWindowTitle("Name Not Found")
                msg.setStandardButtons(QMessageBox.Ok)
                msg.exec_()
        except:
            msg_text = "Make sure there is a working Internet connection or try again latter."
            msg = QMessageBox(self)
            utils.set_window_icon(msg)
            msg.setIcon(QMessageBox.Information)
            msg.setText("Issue encountered while searching contact information.")
            msg.setInformativeText(msg_text)
            msg.setWindowTitle("Problem encountered")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
Example #3
0
    def build_ui(self):
        """
        Build and modify this widget's GUI

        Returns
        -------
        None
        """
        self.ui = UI_MainWindow.Ui_MainWindow()
        self.ui.setupUi(self)

        utils.set_window_icon(self)

        self.metadata_root = MetadataRoot()
        self.ui.centralwidget.layout().addWidget(self.metadata_root)

        for i in range(PyMdWizardMainForm.max_recent_files):
            self.recent_file_actions.append(
                QAction(self, visible=False,
                        triggered=self.open_recent_file))
            self.ui.menuRecent_Files.addAction(self.recent_file_actions[i])
        self.update_recent_file_actions()

        self.ui.menuErrors.clear()

        settings = QSettings('USGS', 'pymdwizard')
        template_fname = settings.value('template_fname')

        if template_fname is not None:
            just_fname = os.path.split(template_fname)[-1]
            self.ui.actionCurrentTemplate.setText('Current: ' + just_fname)
Example #4
0
    def __init__(self,
                 previous_dnames=[],
                 last_kernel='',
                 default_kernel='pymdwizard <<default>>',
                 update_function=None,
                 parent=None):
        super(self.__class__, self).__init__(parent=parent)

        self.build_ui()
        self.connect_events()

        self.kernels = {}
        self.previous_dnames = previous_dnames
        if previous_dnames:
            self.ui.dname.setCurrentText(previous_dnames[0])

        self.default_kernel = default_kernel
        self.populate_kernels()
        self.update_function = update_function

        for dname in self.previous_dnames:
            self.ui.dname.addItem(dname)

        if last_kernel and last_kernel in self.kernels:
            index = self.ui.kernel.findText(last_kernel)
            if index >= 0:
                self.ui.kernel.setCurrentIndex(index)

        utils.set_window_icon(self)
        self.setStyleSheet(wiz_widget.NORMAL_STYLE)
Example #5
0
 def find_usgs_contact(self):
     self.usgs_contact = QDialog(parent=self)
     self.usgs_contact_ui = UI_USGSContactImporter.Ui_ImportUsgsUser()
     self.usgs_contact_ui.setupUi(self.usgs_contact)
     self.usgs_contact_ui.btn_OK.clicked.connect(self.add_contact)
     self.usgs_contact_ui.btn_cancel.clicked.connect(self.cancel)
     utils.set_window_icon(self.usgs_contact)
     self.usgs_contact.show()
Example #6
0
    def __init__(self, table=None, selected_items_df=None, parent=None):
        super(self.__class__, self).__init__()

        self.build_ui()
        self.connect_events()

        self.table_include = table
        self.selected_items_df = selected_items_df
        utils.set_window_icon(self)
Example #7
0
 def get_doi_citation(self):
     if self.doi_lookup is None:
         self.doi_lookup = QDialog(parent=self)
         self.doi_lookup_ui = UI_DOICiteinfoImporter.Ui_ImportUsgsUser()
         self.doi_lookup_ui.setupUi(self.doi_lookup)
         self.doi_lookup_ui.btn_OK.clicked.connect(self.add_doi)
         self.doi_lookup_ui.btn_cancel.clicked.connect(self.cancel)
         utils.set_window_icon(self.doi_lookup)
     self.doi_lookup.show()
Example #8
0
    def build_ui(self):
        """
        Build and modify this widget's GUI

        Returns
        -------
        None
        """
        self.ui = UI_ITISSearch.Ui_ItisSearchWidget()
        self.ui.setupUi(self)
        self.ui.splitter.setSizes([300, 100])
        utils.set_window_icon(self)
Example #9
0
    def __init__(self, add_term_function=None, parent=None, place=False):
        super(self.__class__, self).__init__(parent=parent)

        self.build_ui()
        self.connect_events()

        self.thesauri_lookup = {}
        self.thesauri_lookup_r = {}

        self.add_term_function = add_term_function

        self.place = place

        utils.set_window_icon(self)
Example #10
0
    def build_ui(self):
        """
        Build and modify this widget's GUI

        Returns
        -------
        None
        """
        self.ui = UI_MainWindow.Ui_MainWindow()
        self.ui.setupUi(self)

        utils.set_window_icon(self, remove_help=False)

        # Initial window size/pos last saved. Use default values for first time
        self.resize(self.settings.value("size", QSize(1300, 700)))
        self.move(self.settings.value("pos", QPoint(50, 50)))

        self.metadata_root = MetadataRoot()
        self.ui.centralwidget.layout().addWidget(self.metadata_root)

        for i in range(PyMdWizardMainForm.max_recent_files):
            self.recent_file_actions.append(
                QAction(self, visible=False, triggered=self.open_recent_file)
            )
            self.ui.menuRecent_Files.addAction(self.recent_file_actions[i])
        self.update_recent_file_actions()

        template_fname = self.settings.value("template_fname")

        if template_fname is not None:
            just_fname = os.path.split(template_fname)[-1]
            self.ui.actionCurrentTemplate.setText("Current: " + just_fname)

        if docx is None:
            self.ui.generate_review.setEnabled(False)

        self.setAcceptDrops(True)

        self.error_list = ErrorList(main_form=self)
        self.error_list_dialog = QDialog(self)
        self.error_list_dialog.setWindowTitle("FGDC Validation Errors")
        self.error_list_dialog.setLayout(self.error_list.layout())
        self.error_list_dialog.resize(600, 400)
Example #11
0
    def load_df(self, df):
        if len(df.columns) > 100:
            msgbox = QMessageBox(self)
            utils.set_window_icon(msgbox)
            msgbox.setIcon(QMessageBox.Question)

            msg = "There are more than 100 columns in the dataset you are"
            msg += " trying to build an Entity and Attribute section for!\n\n"
            msg += "The application can become sluggish or unresponsive when "
            msg += " loading and displaying that many columns.\n\n"
            msg += "Displaying more than 250 columns can cause the application"
            msg += " to crash.\n\n"
            msg += "Often datasets with that many columns are documented with"
            msg += " an overview instead of a detailed section, or using a "
            msg += " external data dictionary.\n\n"
            msg += "You have {} columns in this dataset.".format(
                len(df.columns))
            msg += "\n\nAre you sure you want to continue?"

            msgbox.setText(msg)
            msgbox.setWindowTitle("Too Many Columns Warning")
            msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            confirm = msgbox.exec_()

            if confirm == QMessageBox.No:
                return

        self.clear_children()

        i = 0

        for col_label in df.columns:
            col = df[col_label]
            attr_i = mdattr.Attr(parent=self)
            attr_i.ui.fgdc_attrlabl.setText(str(col_label))

            attr_i.set_series(col)
            attr_i.sniff_nodata()
            attr_i.ui.comboBox.setCurrentIndex(attr_i.guess_domain())
            self.append_attr(attr_i)

        self.attrs[0].supersize_me()
Example #12
0
    def launch_jupyter(self):
        """
        Launches a jupyter notebook server in our examples directory

        Returns
        -------
        None
        """
        last_kernel = self.settings.value('last_kernel', '')
        jupyter_dnames = self.settings.value('jupyter_dnames', [])
        if not jupyter_dnames:
            install_dir = utils.get_install_dname()
            jupyter_dnames = [os.path.join(install_dir, 'examples')]
            self.settings.setValue('jupyter_dnames', jupyter_dnames)

        self.jupyter_dialog = JupyterStarter(
            last_kernel=last_kernel,
            previous_dnames=jupyter_dnames,
            update_function=self.update_jupyter_dnames)
        utils.set_window_icon(self.jupyter_dialog)
        self.jupyter_dialog.show()
Example #13
0
    def launch_jupyter(self):
        """
        Launches a jupyter notebook server in our examples directory

        Returns
        -------
        None
        """
        from subprocess import Popen

        jupyter_dialog = JupyterLocationDialog()
        utils.set_window_icon(jupyter_dialog.msgBox)
        jupyter_dialog.msgBox.setWindowTitle("Where do you want to launch Jupyter?")
        ret = jupyter_dialog.msgBox.exec_()

        install_dir = utils.get_install_dname()
        if ret == 0:
            jupyter_dname = os.path.join(install_dir, 'examples')
        elif ret == 1:
            settings = QSettings('USGS', 'pymdwizard')
            last_jupyter_dname = settings.value('last_jupyter_dname')

            if last_jupyter_dname is None:
                last_jupyter_dname = os.path.join(install_dir, 'examples')
            jupyter_dname = QFileDialog.getExistingDirectory(self, "Select Directory to launch Jupyter from", last_jupyter_dname)
            if jupyter_dname:
                settings.setValue('last_jupyter_dname', jupyter_dname)
        else:
            return

        root_dir = os.path.dirname(install_dir)
        jupyterexe = os.path.join(root_dir, "Python35_64", "scripts", "jupyter.exe")

        if os.path.exists(jupyterexe) and os.path.exists(root_dir):
            p = Popen([jupyterexe, 'notebook'], cwd=jupyter_dname)

            msg = 'Jupyter launching...\nJupyter will start momentarily in a new tab in your default internet browser.'

            QMessageBox.information(self, "Launching Jupyter", msg)
Example #14
0
    def __init__(
        self,
        previous_dnames=[],
        last_kernel="",
        default_kernel="pymdwizard <<default>>",
        update_function=None,
        parent=None,
    ):
        super(self.__class__, self).__init__(parent=parent)

        self.build_ui()
        self.connect_events()

        self.kernels = {}
        self.previous_dnames = previous_dnames
        if previous_dnames:
            self.ui.dname.setCurrentText(previous_dnames[0])

        self.default_kernel = default_kernel
        self.populate_kernels()
        self.update_function = update_function

        for dname in self.previous_dnames:
            self.ui.dname.addItem(dname)

        if last_kernel and last_kernel in self.kernels:
            index = self.ui.kernel.findText(last_kernel)
            if index >= 0:
                self.ui.kernel.setCurrentIndex(index)

        utils.set_window_icon(self)
        self.setStyleSheet(wiz_widget.NORMAL_STYLE)

        try:
            import jupyterlab

            self.ui.usejupyterframe.setEnabled(True)
        except ImportError:
            self.ui.usejupyterframe.setEnabled(False)
Example #15
0
    def build_ui(self):
        """
        Build and modify this widget's GUI

        Returns
        -------
        None
        """
        self.ui = UI_MainWindow.Ui_MainWindow()
        self.ui.setupUi(self)

        utils.set_window_icon(self, remove_help=False)

        self.metadata_root = MetadataRoot()
        self.ui.centralwidget.layout().addWidget(self.metadata_root)

        for i in range(PyMdWizardMainForm.max_recent_files):
            self.recent_file_actions.append(
                QAction(self, visible=False, triggered=self.open_recent_file))
            self.ui.menuRecent_Files.addAction(self.recent_file_actions[i])
        self.update_recent_file_actions()

        settings = QSettings('USGS', 'pymdwizard')
        template_fname = settings.value('template_fname')

        if template_fname is not None:
            just_fname = os.path.split(template_fname)[-1]
            self.ui.actionCurrentTemplate.setText('Current: ' + just_fname)

        if docx is None:
            self.ui.generate_review.setEnabled(False)

        self.setAcceptDrops(True)

        self.error_list = ErrorList(main_form=self)
        self.error_list_dialog = QDialog(self)
        self.error_list_dialog.setWindowTitle('FGDC Validation Errors')
        self.error_list_dialog.setLayout(self.error_list.layout())
        self.error_list_dialog.resize(600, 400)
Example #16
0
    def add_doi(self):
        doi = self.doi_lookup_ui.le_doi.text()
        try:
            citeinfo = doi_utils.get_doi_citation(doi)

            if citeinfo is None:
                msgbox = QMessageBox(self)
                utils.set_window_icon(msgbox)
                msgbox.setIcon(QMessageBox.Warning)
                msg = "'{}' Not Found on DataCite".format(doi)
                msg += "\nMake sure the DOI is valid and active."
                msgbox.setText(msg)
                msgbox.setInformativeText("No matching citation found")
                msgbox.setWindowTitle("DOI Not Found")
                msgbox.setStandardButtons(QMessageBox.Ok)
                msgbox.exec_()
            else:
                self.from_xml(citeinfo.to_xml())
        except:
            msg = "We ran into a problem creating a citeinfo element from that DOI({})".format(
                doi)
            msg += "Check the DOI and/or manually create the citation for it"
            QMessageBox.warning(self, "Problem DOI", msg)
        self.cancel()
Example #17
0
    def add_contact(self):
        username = self.usgs_contact_ui.le_usgs_ad_name.text()

        if not username:
            return

        try:
            contact_dict = utils.get_contact_info(username)
            self.clear_widget()
            utils.populate_widget(self, contact_dict)

            addrtype_widget = self.findChild(QComboBox, 'fgdc_addrtype')
            addrtype = contact_dict['addrtype']
            addrtype_widget.setEditText(addrtype)
            if 'cntorgp' in contact_dict:
                rbtn_orgp = self.findChild(QRadioButton, 'rbtn_orgp')
                rbtn_orgp.setChecked(True)
            elif 'cntperp' in contact_dict:
                rbtn_perp = self.findChild(QRadioButton, 'rbtn_perp')
                rbtn_perp.setChecked(True)
            self.usgs_contact.deleteLater()

        except KeyError:
            pass

        except:
            msg_text = "Well, that didn't work."
            msg = QMessageBox(self)
            utils.set_window_icon(msg)
            msg.setIcon(QMessageBox.Information)
            msg.setText(
                "Issue encountered while searching contact information.")
            msg.setInformativeText(msg_text)
            msg.setWindowTitle("Problem encountered")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
Example #18
0
    def populate_domain_content(self, which='guess'):
        """
        Fill out this widget with the content from it's associated series

        Parameters
        ----------
        which : str, optional, one of 'guess' or the index to force
            if guess introspect the series associated with this attribute
            and make a best guess as to which domain to use.

        Returns
        -------
        None
        """
        self.clear_domain()

        if which == 'guess':
            self.sniff_nodata()
            index = self.guess_domain()
        else:
            index = which

        self.ui.comboBox.setCurrentIndex(index)

        if index == 0:
            self.domain = edom_list.EdomList(parent=self)
        elif index == 1:
            self.domain = rdom.Rdom(parent=self)
        elif index == 2:
            self.domain = codesetd.Codesetd(parent=self)
        else:
            self.domain = udom.Udom(parent=self)

        if self._domain_content[index] is not None:
            # This domain has been used before, display previous content
            self.domain.from_xml(self._domain_content[index])
        elif self.series is not None and index == 0:
            clean_series = data_io.clean_nodata(self.series, self.nodata)
            uniques = clean_series.unique()

            if len(uniques) > 100:
                msg = "There are more than 100 unique values in this field."
                msg += "\n This tool cannot smoothly display that many " \
                       "entries. "
                msg += "\nTypically an enumerated domain is not used with " \
                       "that many unique entries."
                msg += "\n\nOnly the first one hundred are displayed below!"
                msg += "\nYou will likely want to change the domain to one " \
                       "of the other options."
                QMessageBox.warning(self, "Too many unique entries", msg)
                self.domain.populate_from_list(uniques[:101])
            else:
                self.domain.populate_from_list(uniques)
        elif self.series is not None and index == 1:
            clean_series = data_io.clean_nodata(self.series, self.nodata)
            try:
                self.domain.ui.fgdc_rdommin.setText(str(clean_series.min()))
            except:
                self.domain.ui.fgdc_rdommin.setText('')
            try:
                self.domain.ui.fgdc_rdommax.setText(str(clean_series.max()))
            except:
                self.domain.ui.fgdc_rdommax.setText('')

            if not np.issubdtype(clean_series.dtype, np.number):
                msg = 'Caution! The contents of this column are stored in the' \
                      ' data source as "text".  The use of a range domain ' \
                      'type on text columns might give unexpected results, ' \
                      'especially for columns that contain date information.'
                msgbox = QMessageBox(QMessageBox.Warning,
                                     "Range domain on text field", msg)
                utils.set_window_icon(msgbox)
                msgbox.exec_()
        self.ui.attrdomv_contents.layout().addWidget(self.domain)
Example #19
0
    def from_xml(self, attr):
        """
        Populate widget with a representation of the passed XML element

        Parameters
        ----------
        attr : XML Element

        Returns
        -------
        None
        """
        try:
            self.clear_widget()
            if attr.tag == 'attr':

                utils.populate_widget(self, attr)
                attr_node = xml_utils.XMLNode(attr)
                attrdomvs = attr_node.xpath('attrdomv', as_list=True)
                attr_domains = [a.children[0].tag for a in attrdomvs]

                # pull out the first no data attribute domain
                for attrdomv in attrdomvs:
                    if attrdomv.children[0].tag == 'edom' and \
                            (attrdomv.children[0].children[0].text in self.nodata_matches or \
                            attrdomv.children[0].children[1].text.lower() in ['nodata', 'no data']
                            or (attr_domains.count('edom')==1) and len(attr_domains) > 1):
                        self.ui.rbtn_nodata_yes.setChecked(True)
                        self.nodata_content = (1,
                                               attrdomv.children[0].to_xml())
                        attrdomvs.remove(attrdomv)
                        attr_domains.remove('edom')
                        try:
                            edomv = attr.xpath(
                                "attrdomv/edom/edomv[text()='{}']".format(
                                    attrdomv.children[0].children[0].text))[0]
                            nd_attrdomv = edomv.getparent().getparent()
                            nd_attrdomv.getparent().remove(nd_attrdomv)
                        except:
                            pass
                        break

                if len(set(attr_domains)) > 1:
                    # multiple domain types present in this attr
                    msg = "Multiple domain types found in the attribute/column '{}'."
                    msg += "\ni.e. more than one of Enumerated, Range, "
                    msg += "Codeset, and Unrepresentable was used to "
                    msg += "was used to describe a single column.\n\n"
                    msg += "While this is valid in the FGDC schema the "
                    msg += "MetadataWizard is not designed to handle this."
                    msg += "\n\nOnly the first of these domains will be displayed "
                    msg += "and retained in the output saved from this tool."
                    msg += "\n\nIf having this structure is import please use"
                    msg += " a different tool for editing this section."
                    msg = msg.format(self.ui.fgdc_attrlabl.text())
                    msgbox = QMessageBox(QMessageBox.Warning,
                                         "Too many domain types", msg)
                    utils.set_window_icon(msgbox)
                    msgbox.exec_()

                if len(attrdomvs) == 0:
                    self.ui.comboBox.setCurrentIndex(3)
                elif attr_domains[0] == 'edom':
                    self.ui.comboBox.setCurrentIndex(0)
                    self._domain_content[0] = attr
                elif attr_domains[0] == 'udom':
                    self.ui.comboBox.setCurrentIndex(3)
                    self._domain_content[3] = attr.xpath('attrdomv/udom')[0]
                elif attr_domains[0] == 'rdom':
                    self.ui.comboBox.setCurrentIndex(1)
                    self._domain_content[1] = attr.xpath('attrdomv/rdom')[0]
                elif attr_domains[0] == 'codesetd':
                    self.ui.comboBox.setCurrentIndex(2)
                    self._domain_content[2] = attr.xpath(
                        'attrdomv/codesetd')[0]
                else:
                    self.ui.comboBox.setCurrentIndex(3)
            else:
                print("The tag is not attr")
        except KeyError:
            pass
Example #20
0
 def set_settings(self):
     self.settings_dialog = Settings(mainform=self)
     self.settings_dialog.setWindowTitle("MetadataWizard Settings")
     utils.set_window_icon(self.settings_dialog)
     self.settings_dialog.show()