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)
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_()
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)
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)
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()
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)
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()
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)
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)
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)
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()
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()
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)
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)
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)
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()
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_()
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)
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
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()