class KeywordsRepeater(WizardWidget): drag_label = "NA <NA>" def __init__(self, thesaurus_label='Thesaurus', keywords_label='Keywords:', line_name='kw', parent=None): self.thesaurus_label = thesaurus_label self.keywords_label = keywords_label self.line_name = line_name self.keywords = None WizardWidget.__init__(self, parent=parent) def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_keywords_repeater.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.ui.thesaurus_label = self.thesaurus_label widget_kwargs = {'label': self.keywords_label, 'line_name': self.line_name, 'required': True} self.keywords = RepeatingElement(add_text='Add keyword', remove_text='Remove last', widget_kwargs=widget_kwargs) self.keywords.ui.italic_label.setStyleSheet('') self.keywords.add_another() self.ui.keywords_layout.insertWidget(0, self.keywords) def lock(self): self.ui.fgdc_themekt.setReadOnly(True) self.keywords.ui.addAnother.setEnabled(False) def get_keywords(self): return [kw.added_line.text() for kw in self.keywords.get_widgets()] def add_another(self, locked=False): widget = self.keywords.add_another() widget.setObjectName(self.line_name) widget.added_line.setReadOnly(locked) return widget def get_widgets(self): return self.keywords.get_widgets()
class Citeinfo(WizardWidget): # drag_label = "Citation information <citeinfo>" acceptable_tags = ['citation', 'citeinfo'] def __init__(self, parent=None, include_lwork=True): self.include_lwork = include_lwork self.schema = 'bdp' WizardWidget.__init__(self, parent=parent) def build_ui(self, ): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_citeinfo.Ui_parent_form() self.ui.setupUi(self) if self.include_lwork: self.lworkcit_widget = Citeinfo(parent=self, include_lwork=False) self.lworkcit_widget.ui.lbl_dataset_title.setText('Larger Work Title') self.ui.lworkcite_widget.layout().addWidget(self.lworkcit_widget) self.lworkcit_widget.ui.fgdc_geoform.setEditText('publication') else: self.ui.fgdc_lworkcit.hide() self.include_lworkext_change(self.ui.radio_lworkyes.isChecked()) self.ui.series_ext.hide() self.ui.pub_ext.hide() self.ui.pubdate_widget = FGDCDate(label='YYYYMMDD ', show_format=False, required=True, fgdc_name='fgdc_pubdate') self.ui.pubdate_layout.addWidget(self.ui.pubdate_widget) self.onlink_list = RepeatingElement(add_text='Add online link', remove_text='Remove last', widget_kwargs={'label': 'Link', 'line_name':'fgdc_onlink'}) self.onlink_list.add_another() self.ui.onlink_layout.addWidget(self.onlink_list) self.fgdc_origin = RepeatingElement(add_text='Add originator', remove_text='Remove last', widget_kwargs={'label': 'Originator', 'line_name':'fgdc_origin', 'required':True}) self.fgdc_origin.add_another() self.ui.originator_layout.addWidget(self.fgdc_origin) self.setup_dragdrop(self) def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_lworkyes.toggled.connect(self.include_lworkext_change) self.ui.radio_seriesyes.toggled.connect(self.include_seriesext_change) self.ui.radio_pubinfoyes.toggled.connect(self.include_pubext_change) def include_seriesext_change(self, b): """ Extended citation to support series information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.series_ext.show() else: self.ui.series_ext.hide() def include_pubext_change(self, b): """ Extended citation to support publication information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.pub_ext.show() else: self.ui.pub_ext.hide() def include_lworkext_change(self, b): """ Extended citation to support a larger body of information for the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.lworkcite_widget.show() else: self.ui.lworkcite_widget.hide() def _to_xml(self): """ encapsulates the QLineEdit text in an element tag Returns ------- citation element tag in xml tree """ citeinfo = xml_utils.xml_node('citeinfo') for origin in self.fgdc_origin.get_widgets(): xml_utils.xml_node('origin', text=origin.added_line.text(), parent_node=citeinfo) pubdate = xml_utils.xml_node("pubdate", text=self.ui.pubdate_widget.get_date(), parent_node=citeinfo) title = xml_utils.xml_node("title", self.ui.fgdc_title.text(), parent_node=citeinfo) geoform = xml_utils.xml_node("geoform", self.ui.fgdc_geoform.currentText(), parent_node=citeinfo) if self.ui.radio_seriesyes.isChecked(): serinfo = xml_utils.xml_node('serinfo', parent_node=citeinfo) sername = xml_utils.xml_node('sername', text=self.ui.fgdc_sername.text(), parent_node=serinfo) issue = xml_utils.xml_node('issue', text=self.ui.fgdc_issue.text(), parent_node=serinfo) if self.ui.radio_pubinfoyes.isChecked(): pubinfo = xml_utils.xml_node('pubinfo', parent_node=citeinfo) pubplace = xml_utils.xml_node('pubplace', parent_node=pubinfo, text=self.ui.fgdc_pubplace.text()) publish = xml_utils.xml_node('publish', parent_node=pubinfo, text=self.ui.fgdc_publish.text()) for onlink in self.onlink_list.get_widgets(): if onlink.added_line.text() != '': onlink_node = xml_utils.xml_node('onlink', parent_node=citeinfo, text=onlink.added_line.text()) if self.include_lwork and self.ui.radio_lworkyes.isChecked(): lworkcit = xml_utils.xml_node('lworkcit', parent_node=citeinfo) lwork = self.lworkcit_widget._to_xml() lworkcit.append(lwork) return citeinfo def _from_xml(self, citeinfo): """ parses the xml code into the relevant citation elements Parameters ---------- citation - the xml element status and its contents Returns ------- None """ try: if citeinfo.tag == "citation": citeinfo = citeinfo.xpath('citeinfo')[0] elif citeinfo.tag != 'citeinfo': print("The tag is not 'citation' or 'citeinfo'") return self.fgdc_origin.clear_widgets() originators = citeinfo.findall("origin") if originators : self.fgdc_origin.clear_widgets(add_another=False) for origin in citeinfo.findall('origin'): origin_widget = self.fgdc_origin.add_another() origin_widget.added_line.setText(origin.text) else: self.fgdc_origin.add_another() if citeinfo.findall('geoform'): self.ui.fgdc_geoform.setEditText(citeinfo.findall('geoform')[0].text) utils.populate_widget_element(self.ui.pubdate_widget.ui.fgdc_caldate, citeinfo, 'pubdate') utils.populate_widget_element(self.ui.fgdc_title, citeinfo, 'title') self.onlink_list.clear_widgets() if citeinfo.findall("onlink"): for onlink in citeinfo.findall('onlink'): onlink_widget = self.onlink_list.widgets[0] onlink_widget.added_line.setText(onlink.text) if citeinfo.xpath('serinfo'): self.ui.radio_seriesyes.setChecked(True) utils.populate_widget(self, citeinfo.xpath('serinfo')[0]) else: self.ui.radio_seriesyes.setChecked(False) pubinfo = citeinfo.xpath('pubinfo') if pubinfo: self.ui.radio_pubinfoyes.setChecked(True) utils.populate_widget_element(self.ui.fgdc_publish, pubinfo[0], 'publish') utils.populate_widget_element(self.ui.fgdc_pubplace, pubinfo[0], 'pubplace') else: self.ui.radio_pubinfoyes.setChecked(False) self.ui.radioButton_8.setChecked(True) if citeinfo.xpath('lworkcit'): try: self.ui.radio_lworkyes.setChecked(True) self.lworkcit_widget._from_xml(citeinfo.xpath('lworkcit/citeinfo')[0]) except AttributeError: msg = 'you pasted a citation element into the larger work citation area' msg += '\n that contained a larger work citation' msg += '\n Multiple nested larger work citations are not currently supported in the tool' msg += '\n\n the larger work citation being pasted will be ignored' QMessageBox.warning(self, "Dropped Content Warning", msg) else: self.ui.radio_lworkno.setChecked(True) except KeyError: pass
class Citation(WizardWidget): # drag_label = "Citation <citation>" def __init__(self, parent=None, include_lwork=True): self.include_lwork = include_lwork self.schema = 'bdp' WizardWidget.__init__(self, parent=parent) def build_ui(self, ): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_Citation.Ui_fgdc_citation() self.ui.setupUi(self) if self.include_lwork: self.lworkcit_widget = Citation(parent=self, include_lwork=False) self.ui.lworkcite_widget.layout().addWidget(self.lworkcit_widget) else: self.ui.fgdc_lworkcit.hide() self.include_lworkext_change(self.ui.radio_lworkyes.isChecked()) self.ui.series_ext.hide() self.ui.pub_ext.hide() self.ui.pubdate_widget = SingleDate(label='YYYMMDD ', show_format=False, required=True) self.ui.pubdate_layout.addWidget(self.ui.pubdate_widget) self.onlink_list = RepeatingElement(add_text='Add online link', remove_text='Remove last', widget_kwargs={ 'label': 'Link', 'line_name': 'fgdc_onlink' }) self.onlink_list.add_another() self.ui.onlink_layout.addWidget(self.onlink_list) self.fgdc_origin = RepeatingElement(add_text='Add originator', remove_text='Remove last', widget_kwargs={ 'label': 'Originator', 'line_name': 'fgdc_origin', 'required': True }) self.fgdc_origin.add_another() self.ui.originator_layout.addWidget(self.fgdc_origin) self.setup_dragdrop(self) def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_lworkyes.toggled.connect(self.include_lworkext_change) self.ui.radio_seriesyes.toggled.connect(self.include_seriesext_change) self.ui.radio_pubinfoyes.toggled.connect(self.include_pubext_change) def include_seriesext_change(self, b): """ Extended citation to support series information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.series_ext.show() else: self.ui.series_ext.hide() def include_pubext_change(self, b): """ Extended citation to support publication information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.pub_ext.show() else: self.ui.pub_ext.hide() def include_lworkext_change(self, b): """ Extended citation to support a larger body of information for the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.lworkcite_widget.show() else: self.ui.lworkcite_widget.hide() def dragEnterEvent(self, e): """ Only accept Dragged items that can be converted to an xml object with a root tag called 'citation' Parameters ---------- e : qt event Returns ------- None """ mime_data = e.mimeData() if e.mimeData().hasFormat('text/plain'): parser = etree.XMLParser(ns_clean=True, recover=True, encoding='utf-8') element = etree.fromstring(mime_data.text(), parser=parser) if element.tag in ['citation', 'citeinfo']: e.accept() else: e.ignore() def switch_schema(self, schema): self.schema = schema if schema == 'bdp': self.ui.geoform_groupbox.show() else: self.ui.geoform_groupbox.hide() if self.include_lwork: self.lworkcit_widget.switch_schema(self.schema) def _to_xml(self): """ encapsulates the QLineEdit text in an element tag Returns ------- citation element tag in xml tree """ citeinfo = xml_utils.xml_node('citeinfo') for origin in self.fgdc_origin.get_widgets(): xml_utils.xml_node('origin', text=origin.added_line.text(), parent_node=citeinfo) pubdate = xml_utils.xml_node("pubdate", text=self.ui.pubdate_widget.get_date(), parent_node=citeinfo) title = xml_utils.xml_node("title", self.ui.fgdc_title.text(), parent_node=citeinfo) if self.schema == 'bdp': geoform = xml_utils.xml_node("geoform", self.ui.fgdc_geoform.currentText(), parent_node=citeinfo) if self.ui.radio_seriesyes.isChecked(): serinfo = xml_utils.xml_node('serinfo', parent_node=citeinfo) sername = xml_utils.xml_node('serinfo', text=self.ui.fgdc_sername.text(), parent_node=serinfo) issue = xml_utils.xml_node('issue', text=self.ui.fgdc_issue.text(), parent_node=serinfo) if self.ui.radio_pubinfoyes.isChecked(): pubinfo = xml_utils.xml_node('pubinfo', parent_node=citeinfo) pubplace = xml_utils.xml_node('pubplace', parent_node=pubinfo, text=self.ui.fgdc_pubplace.text()) publish = xml_utils.xml_node('publish', parent_node=pubinfo, text=self.ui.fgdc_publish.text()) for onlink in self.onlink_list.get_widgets(): if onlink.added_line.text() != '': onlink_node = xml_utils.xml_node('onlink', parent_node=citeinfo, text=onlink.added_line.text()) if self.include_lwork and self.ui.radio_lworkyes.isChecked(): lworkcit = xml_utils.xml_node('lworkcit', parent_node=citeinfo) lwork = self.lworkcit_widget._to_xml() lworkcit.append(lwork) return citeinfo def _from_xml(self, citeinfo): """ parses the xml code into the relevant citation elements Parameters ---------- citation - the xml element status and its contents Returns ------- None """ try: if citeinfo.tag == "citation": citeinfo = citeinfo.xpath('citeinfo')[0] elif citeinfo.tag != 'citeinfo': print("The tag is not 'citation' or 'citeinfo'") return self.fgdc_origin.clear_widgets() if citeinfo.findall("origin"): for origin in citeinfo.findall('origin'): origin_widget = self.fgdc_origin.widgets[0] origin_widget.added_line.setText(origin.text) else: self.fgdc_origin.add_another() if citeinfo.findall('geoform'): self.ui.fgdc_geoform.setEditText( citeinfo.findall('geoform')[0].text) utils.populate_widget_element( self.ui.pubdate_widget.ui.fgdc_caldate, citeinfo, 'pubdate') utils.populate_widget_element(self.ui.fgdc_title, citeinfo, 'title') self.onlink_list.clear_widgets() if citeinfo.findall("onlink"): for onlink in citeinfo.findall('onlink'): onlink_widget = self.onlink_list.widgets[0] onlink_widget.added_line.setText(onlink.text) if citeinfo.xpath('serinfo'): self.ui.radio_seriesyes.setChecked(True) utils.populate_widget(self.ui.fgdc_serinfo, citeinfo.xpath('serinfo')[0]) else: self.ui.radio_seriesyes.setChecked(False) pubinfo = citeinfo.xpath('pubinfo') if pubinfo: self.ui.radio_pubinfoyes.setChecked(True) utils.populate_widget_element(self.ui.fgdc_publish, pubinfo[0], 'publish') utils.populate_widget_element(self.ui.fgdc_pubplace, pubinfo[0], 'pubplace') else: self.ui.radio_pubinfoyes.setChecked(False) if citeinfo.xpath('lworkcit'): self.ui.radio_lworkyes.setChecked(True) self.lworkcit_widget._from_xml( citeinfo.xpath('lworkcit/citeinfo')[0]) except KeyError: pass
class Timeperd(WizardWidget): # drag_label = "Time Period of Content <timeperd>" acceptable_tags = ['timeperd'] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_timeperd.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.single_date = FGDCDate(label=' Single Date ', fgdc_name='fgdc_caldate') self.ui.fgdc_sngdate.layout().insertWidget(0, self.single_date) self.range_start_date = FGDCDate(label='Start ', fgdc_name='fgdc_begdate') self.range_end_date = FGDCDate(label='End ', fgdc_name='fgdc_enddate') self.ui.layout_daterange.addWidget(self.range_start_date) self.ui.layout_daterange.addWidget(self.range_end_date) date_widget_kwargs = { 'show_format': False, 'label': 'Individual Date ', 'fgdc_name': 'fgdc_caldate', 'parent_fgdc_name': 'fgdc_sngdate' } self.multi_dates = RepeatingElement(widget=FGDCDate, widget_kwargs=date_widget_kwargs) self.multi_dates.add_another() self.switch_primary() def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_single.toggled.connect(self.switch_primary) self.ui.radio_range.toggled.connect(self.switch_primary) self.ui.radio_multiple.toggled.connect(self.switch_primary) def switch_primary(self): """ Switches form to reflect either organization or person primary Returns ------- None """ if self.ui.radio_single.isChecked(): self.findChild(QStackedWidget, "fgdc_timeinfo").setCurrentIndex(0) self.ui.fgdc_sngdate.show() self.ui.fgdc_rngdates.hide() self.ui.fgdc_mdattim.hide() self.ui.fgdc_mdattim.layout().removeWidget(self.multi_dates) elif self.ui.radio_range.isChecked(): self.findChild(QStackedWidget, "fgdc_timeinfo").setCurrentIndex(1) self.ui.fgdc_rngdates.hide() self.ui.fgdc_rngdates.show() self.ui.fgdc_mdattim.hide() self.ui.fgdc_mdattim.layout().removeWidget(self.multi_dates) elif self.ui.radio_multiple.isChecked(): self.findChild(QStackedWidget, "fgdc_timeinfo").setCurrentIndex(2) self.ui.fgdc_sngdate.hide() self.ui.fgdc_rngdates.hide() self.ui.fgdc_mdattim.layout().addWidget(self.multi_dates) self.ui.fgdc_mdattim.show() def _to_xml(self): """ encapsulates the QTabWidget text for Metadata Time in an element tag Returns ------- timeperd element tag in xml tree """ timeperd = xml_utils.xml_node('timeperd') timeinfo = xml_utils.xml_node("timeinfo", parent_node=timeperd) tabIndex = self.ui.fgdc_timeinfo.currentIndex() if tabIndex == 0: sngdate = xml_utils.xml_node("sngdate", parent_node=timeinfo) caldate = xml_utils.xml_node('caldate', parent_node=sngdate, text=self.single_date.get_date()) if tabIndex == 1: rngdates = xml_utils.xml_node("rngdates", parent_node=timeinfo) begdate = xml_utils.xml_node("begdate", parent_node=rngdates, text=self.range_start_date.get_date()) enddate = xml_utils.xml_node("enddate", parent_node=rngdates, text=self.range_end_date.get_date()) if tabIndex == 2: mdattim = xml_utils.xml_node("mdattim", parent_node=timeinfo) for single_date in self.multi_dates.get_widgets(): single_date_node = xml_utils.xml_node("sngdate", parent_node=mdattim) caldate = xml_utils.xml_node('caldate', parent_node=single_date_node, text=single_date.get_date()) current = xml_utils.xml_node('current', parent_node=timeperd, text=self.ui.fgdc_current.currentText()) return timeperd def _from_xml(self, timeperd): """ parses the xml code into the relevant timeperd elements Parameters ---------- metadata_date - the xml element timeperd and its contents Returns ------- None """ try: if timeperd.tag == 'timeperd': if timeperd.findall("current"): current_text = timeperd.findtext("current") current_box = self.findChild(QComboBox, 'fgdc_current') current_box.setCurrentText(current_text) else: pass timeinfo_stack = self.ui.fgdc_timeinfo if timeperd.xpath("timeinfo/rngdates"): self.ui.radio_range.setChecked(True) timeinfo_stack.setCurrentIndex(1) begdate = timeperd.findtext("timeinfo/rngdates/begdate") self.range_start_date.set_date(begdate) enddate = timeperd.findtext("timeinfo/rngdates/enddate") self.range_end_date.set_date(enddate) elif timeperd.xpath("timeinfo/mdattim"): self.ui.radio_multiple.setChecked(True) timeinfo_stack.setCurrentIndex(2) self.multi_dates.clear_widgets(add_another=False) for caldate in timeperd.xpath( 'timeinfo/mdattim/sngdate/caldate'): date_widget = self.multi_dates.add_another() date_widget.set_date(caldate.text) elif timeperd.xpath("timeinfo/sngdate"): self.ui.radio_single.setChecked(True) timeinfo_stack.setCurrentIndex(0) sngdate = timeperd.findtext("timeinfo/sngdate/caldate") self.single_date.set_date(sngdate) else: pass else: print("The tag is not timeperd") except KeyError: pass
class ThemeList(WizardWidget): # drag_label = "Theme Keywords <keywords>" acceptable_tags = ['keywords'] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_theme_list.Ui_theme_list() self.ui.setupUi(self) self.setup_dragdrop(self) self.ui.theme_tabs.setStyleSheet("QTabBar::tab::disabled {width: 0; height: 0; margin: 0; padding: 0; border: none;} ") self.iso_kws = RepeatingElement(which='vertical', add_text='Add additonal', widget=IsoKeyword, remove_text='Remove Keyword', italic_text='ISO Topic Category Keywords') self.iso_kws.add_another() self.ui.iso_keywords_layout.addWidget(self.iso_kws) self.thesauri = [] def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.btn_add_thesaurus.clicked.connect(self.add_another) self.ui.btn_remove_selected.clicked.connect(self.remove_selected) self.ui.btn_add_iso.clicked.connect(self.add_iso) self.ui.btn_search_controlled.clicked.connect(self.search_controlled) def add_another(self, click=False, tab_label='', locked=False): if 'None' not in [t.get_thesaurus_name() for t in self.thesauri] and \ tab_label == '': theme_widget = self.add_keyword(keyword='', thesaurus='None', locked=False) else: theme_widget = Theme() theme_widget.ui.fgdc_themekt.textChanged.connect(self.changed_thesaurus) self.ui.theme_tabs.addTab(theme_widget, tab_label) self.ui.theme_tabs.setCurrentIndex(self.ui.theme_tabs.count()-1) self.thesauri.append(theme_widget) return theme_widget def changed_thesaurus(self, s): current_index = self.ui.theme_tabs.currentIndex() current_tab = self.ui.theme_tabs.setTabText(current_index, 'Thesaurus: ' + s) def remove_selected(self): current_index = self.ui.theme_tabs.currentIndex() if current_index == 0: self.remove_iso() else: self.ui.theme_tabs.removeTab(current_index) del self.thesauri[current_index-1] def remove_iso(self): self.ui.theme_tabs.setTabEnabled(0, False) self.ui.fgdc_theme.hide() def add_iso(self): self.ui.theme_tabs.setTabEnabled(0, True) self.ui.fgdc_theme.show() self.ui.theme_tabs.setCurrentIndex(0) self.repaint() def get_children(self, widget): children = [] if self.ui.theme_tabs.isTabEnabled(0): children.append(self.ui.fgdc_theme) for theme in self.thesauri: children.append(theme) return children def clear_widget(self, remove_iso=False): self.iso_kws.clear_widgets() if remove_iso: self.remove_iso() for i in range(len(self.thesauri), 0, -1): self.ui.theme_tabs.setCurrentIndex(i) self.remove_selected() def search_controlled(self): self.thesaurus_search = ThesaurusSearch.ThesaurusSearch(add_term_function=self.add_keyword, parent=self) self.thesaurus_search.setWindowTitle('Search USGS Controlled Vocabularies') self.thesaurus_search.show() def add_keyword(self, keyword=None, thesaurus=None, locked=True): theme_widget = None for theme in self.thesauri: if theme.ui.fgdc_themekt.text() == thesaurus: theme_widget = theme if theme_widget is None: shortname = thesaurus.split(' ')[0] theme_widget = self.add_another(tab_label=shortname, locked=locked) theme_widget.ui.fgdc_themekt.setText(thesaurus) if locked: theme_widget.lock() self.changed_thesaurus(shortname) theme_widget.add_keyword(keyword, locked=locked) return theme_widget def _to_xml(self): """ encapsulates the QPlainTextEdit text in an element tag Returns ------- procstep element tag in xml tree """ keywords = xml_utils.xml_node('keywords') if self.ui.theme_tabs.isTabEnabled(0): theme = xml_utils.xml_node('theme', parent_node=keywords) themekt = xml_utils.xml_node('themekt', text=self.ui.fgdc_themekt.text(), parent_node=theme) for isokw in self.iso_kws.get_widgets(): themekey = xml_utils.xml_node('themekey', text=isokw.ui.fgdc_themekey.currentText(), parent_node=theme) for theme in self.thesauri: theme_xml = theme._to_xml() keywords.append(theme_xml) return keywords def _from_xml(self, keywords_xml): """ parses the xml code into the relevant procstep elements Parameters ---------- process_step - the xml element status and its contents Returns ------- None """ self.clear_widget(remove_iso=True) self.original_xml = keywords_xml if keywords_xml.tag == 'keywords': for theme_xml in xml_utils.search_xpath(keywords_xml, 'theme', False): themekt = xml_utils.get_text_content(theme_xml, 'themekt') if themekt is not None and 'iso 19115' in themekt.lower(): self.add_iso() self.iso_kws.clear_widgets(add_another=False) for themekey in xml_utils.search_xpath(theme_xml, 'themekey', only_first=False): iso = self.iso_kws.add_another() iso.ui.fgdc_themekey.setCurrentText(themekey.text) else: theme = self.add_another() theme._from_xml(theme_xml)
class SourceInput(WizardWidget): drag_label = "Source Information <srcinfo>" def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_sourceinput.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.src_info = RepeatingElement(which='tab', tab_label='Source', add_text='Source Input', widget=SRCInfo, remove_text='Remove Source', italic_text='Source') self.src_info.add_another() self.ui.frame_sourceinfo.layout().addWidget(self.src_info) self.ui.frame_sourceinfo.hide() def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_sourceyes.toggled.connect(self.include_sources_change) def include_sources_change(self, b): """ Extended citation to support a larger body of information for the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.frame_sourceinfo.show() else: self.ui.frame_sourceinfo.hide() def dragEnterEvent(self, e): """ Only accept Dragged items that can be converted to an xml object with a root tag called 'accconst' Parameters ---------- e : qt event Returns ------- None """ print("pc drag enter") mime_data = e.mimeData() if e.mimeData().hasFormat('text/plain'): parser = etree.XMLParser(ns_clean=True, recover=True, encoding='utf-8') element = etree.fromstring(mime_data.text(), parser=parser) if element.tag == 'lineage': e.accept() else: e.ignore() def clear_widget(self): self.ui.radio_sourceno_2.setChecked(True) WizardWidget.clear_widget(self) def _to_xml(self): """ encapsulates the text in an element tree representing Sources Input Returns ------- series of srcinfo element tag in lineage xml tree """ lineage = etree.Element('lineage') if self.ui.radio_sourceyes.isChecked(): print("in to xml") cnt = 0 srcinfo_list = self.src_info.get_widgets() for srcinfo in srcinfo_list: lineage.append(srcinfo._to_xml()) # while cnt < len(list_widgets): # #lineage.append(list_widgets[cnt]._to_xml()) # lineage.append(SRCInfo._to_xml(list_widgets[cnt])) # cnt += 1 return lineage # elif self.ui.radio_sourceno.isChecked(): # pass def _from_xml(self, xml_srcinput): """ parses the xml code into the relevant accconst elements Parameters ---------- access_constraints - the xml element status and its contents Returns ------- None """ try: if xml_srcinput.tag == 'lineage': self.src_info.clear_widgets(add_another=False) self.ui.frame_sourceinfo.show() self.ui.radio_sourceyes.setChecked(True) xml_srcinput = xml_srcinput.findall('srcinfo') if xml_srcinput: for srcinput in xml_srcinput: srcinfo_widget = self.src_info.add_another() srcinfo_widget._from_xml(srcinput) else: self.ui.radio_sourceno_2.setChecked(True) self.src_info.add_another() except KeyError: pass
class ProcStep(WizardWidget): # drag_label = "Process Step <procstep>" def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_procstep.Ui_Form()#.Ui_USGSContactInfoWidgetMain() self.ui.setupUi(self) self.setup_dragdrop(self) self.proc_step = RepeatingElement(which='tab', tab_label='Step', add_text='Additional Step', widget=ProcessStep, remove_text='Remove Step', italic_text='Processing Steps Taken') #self.proc_step = RepeatingElement(params=params, which='tab', tab_label='Source',) self.proc_step.add_another() self.ui.widget_procstep.layout().addWidget(self.proc_step) def dragEnterEvent(self, e): """ Only accept Dragged items that can be converted to an xml object with a root tag called 'accconst' Parameters ---------- e : qt event Returns ------- None """ print("pc drag enter") mime_data = e.mimeData() if e.mimeData().hasFormat('text/plain'): parser = etree.XMLParser(ns_clean=True, recover=True, encoding='utf-8') element = etree.fromstring(mime_data.text(), parser=parser) if element.tag == 'lineage': e.accept() else: e.ignore() def _to_xml(self): """ encapsulates the etree process step in an element tag Returns ------- procstep portion of the lineageg element tag in xml tree """ lineage = etree.Element('lineage') procstep_list = self.proc_step.get_widgets() for procstep in procstep_list: lineage.append(procstep._to_xml()) return lineage def _from_xml(self, xml_procstep): """ parses the xml code into the relevant accconst elements Parameters ---------- access_constraints - the xml element status and its contents Returns ------- None """ try: if xml_procstep.tag == 'lineage': self.proc_step.clear_widgets(add_another=False) xml_procstep = xml_procstep.findall('procstep') if xml_procstep: for procstep in xml_procstep: procdesc_widget = self.proc_step.add_another() procdesc_widget._from_xml(procstep) else: self.proc_step.add_another() except KeyError: pass
class ProcessStep(WizardWidget): # drag_label = "Process Step <procstep>" acceptable_tags = ['procstep'] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_ProcessStep.Ui_Form() self.ui.setupUi(self) self.ui.fgdc_procdesc.heightMin = 150 self.setup_dragdrop(self) self.single_date = FGDCDate(show_format=False, required=True, label='', fgdc_name='fgdc_procdate') self.proccont = ProcessContact() self.ui.fgdc_procdate.setLayout(QVBoxLayout()) self.ui.fgdc_procdate.layout().insertWidget(0, self.single_date) self.ui.widget_proccont.layout().insertWidget(0, self.proccont) self.srcused_list = RepeatingElement(add_text='Add another', remove_text='Remove last', widget_kwargs={ 'label': 'Source used', 'line_name': 'fgdc_srcused' }) self.srcused_list.add_another() self.ui.srcused_groupbox.layout().addWidget(self.srcused_list) self.srcprod_list = RepeatingElement(add_text='Add another', remove_text='Remove last', widget_kwargs={ 'label': 'Source produced:', 'line_name': 'fgdc_srcprod' }) self.srcprod_list.add_another() self.ui.srcprod_groupbox.layout().addWidget(self.srcprod_list) self.clear_widget() def clear_widget(self): super(self.__class__, self).clear_widget() self.proccont.ui.rbtn_no.setChecked(True) def to_xml(self): """ encapsulates the QPlainTextEdit text in an element tag Returns ------- procstep element tag in xml tree """ procstep = xml_utils.xml_node(tag='procstep') procdesc = xml_utils.xml_node(tag='procdesc') procdesc.text = self.findChild(QPlainTextEdit, "fgdc_procdesc").toPlainText() procstep.append(procdesc) for srcused in self.srcused_list.get_widgets(): if srcused.text(): xml_utils.xml_node('srcused', text=srcused.text(), parent_node=procstep) procdate = xml_utils.xml_node(tag='procdate') date_var = self.single_date.findChild(QLineEdit, "fgdc_procdate").text() procdate.text = date_var procstep.append(procdate) for srcprod in self.srcprod_list.get_widgets(): if srcprod.text(): xml_utils.xml_node('srcprod', text=srcprod.text(), parent_node=procstep) if self.proccont.ui.rbtn_yes.isChecked(): proccont = self.proccont.to_xml() procstep.append(proccont) return procstep def from_xml(self, xml_processstep): """ parses the xml code into the relevant procstep elements Parameters ---------- process_step - the xml element status and its contents Returns ------- None """ try: if xml_processstep.tag == 'procstep': utils.populate_widget(self, xml_processstep) if xml_processstep.xpath('procdate'): self.single_date.set_date( xml_processstep.xpath('procdate')[0].text) if xml_processstep.xpath('proccont'): self.proccont.ui.rbtn_yes.setChecked(True) cntinfo_node = xml_processstep.xpath('proccont/cntinfo')[0] self.proccont.from_xml(cntinfo_node) else: self.proccont.ui.rbtn_no.setChecked(True) pass srcuseds = xml_processstep.findall("srcused") if srcuseds: self.srcused_list.clear_widgets(add_another=False) for srcused in srcuseds: srcused_widget = self.srcused_list.add_another() srcused_widget.setText(srcused.text) else: self.srcused_list.clear_widgets(add_another=True) srcprods = xml_processstep.findall("srcprod") if srcprods: self.srcprod_list.clear_widgets(add_another=False) for srcprod in srcprods: srcprod_widget = self.srcprod_list.add_another() srcprod_widget.setText(srcprod.text) else: self.srcprod_list.clear_widgets(add_another=True) else: print("The tag is not procstep") except KeyError: pass
class Taxoncl(WizardWidget): drag_label = "taxon class <taxoncl>" acceptable_tags = ["taxoncl"] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_taxoncl.Ui_fgdc_taxoncl() self.ui.setupUi(self) widget_kwargs = {"line_name": "common", "required": False} self.commons = RepeatingElement( add_text="Add Common", remove_text="Remove last", widget_kwargs=widget_kwargs, show_buttons=False, ) self.commons.add_another() self.ui.horizontalLayout_4.addWidget(self.commons) self.child_taxoncl = [] self.setup_dragdrop(self) def clear_widget(self): """ Clears all content from this widget Returns ------- None """ self.ui.fgdc_taxonrn.clear() self.ui.fgdc_taxonrv.clear() self.commons.clear_widgets() for taxoncl in self.child_taxoncl: taxoncl.deleteLater() self.child_taxoncl = [] def to_xml(self): """ encapsulates the QTabWidget text for Metadata Time in an element tag Returns ------- timeperd element tag in xml tree """ taxoncl = xml_utils.xml_node("taxoncl") taxonrn = xml_utils.xml_node("taxonrn", text=self.ui.fgdc_taxonrn.text(), parent_node=taxoncl) taxonrv = xml_utils.xml_node("taxonrv", text=self.ui.fgdc_taxonrv.text(), parent_node=taxoncl) common_names = [c.text() for c in self.commons.get_widgets()] for common_name in common_names: if common_name: common = xml_utils.xml_node("common", text=common_name, parent_node=taxoncl) for child_taxoncl in self.child_taxoncl: taxoncl.append(child_taxoncl.to_xml()) return taxoncl def from_xml(self, taxoncl): """ parses the xml code into the relevant timeperd elements Parameters ---------- metadata_date - the xml element timeperd and its contents Returns ------- None """ try: if taxoncl.tag == "taxoncl": self.ui.fgdc_taxonrn.setText(taxoncl.xpath("taxonrn")[0].text) self.ui.fgdc_taxonrv.setText(taxoncl.xpath("taxonrv")[0].text) commons = xml_utils.search_xpath(taxoncl, "common", only_first=False) if commons: self.commons.clear_widgets(add_another=False) for common in commons: this_common = self.commons.add_another() this_common.setText(common.text) children_taxoncl = taxoncl.xpath("taxoncl") for child_taxoncl in children_taxoncl: child_widget = Taxoncl() child_widget.from_xml(child_taxoncl) self.ui.child_taxoncl.layout().addWidget(child_widget) self.child_taxoncl.append(child_widget) else: print("The tag is not a detailed") except KeyError: pass
class Crossref_list(WizardWidget): drag_label = "Cross Reference <crossref>" acceptable_tags = ['idinfo'] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_crossref.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.crossrefs = RepeatingElement(which='tab', tab_label='Crossref', add_text=' Add Additional Crossref ', widget=Crossref, remove_text=' Remove Selected Crossref ', italic_text='') self.crossrefs.add_another() self.ui.crossref_widget.layout().addWidget(self.crossrefs) self.ui.crossref_widget.hide() def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_crossrefyes.toggled.connect(self.crossref_used_change) def crossref_used_change(self, b): if b: self.ui.crossref_widget.show() else: self.ui.crossref_widget.hide() def has_content(self): return self.ui.radio_crossrefyes.isChecked() def get_children(self, widget=None): children = [] for crossref in self.crossrefs.get_widgets(): children.append(crossref) return children def clear_widget(self): super(Crossref_list, self).clear_widget() self.ui.radio_crossrefno.setChecked(True) def to_xml(self): """ encapsulates the etree process step in an element tag Returns ------- procstep portion of the lineageg element tag in xml tree """ crossrefs = [] idinfo = xml_utils.xml_node(tag='idinfo') for crossref in self.crossrefs.get_widgets(): idinfo.append(crossref.to_xml()) return idinfo def from_xml(self, xml_idinfo): """ parses the xml code into the relevant accconst elements Parameters ---------- access_constraints - the xml element status and its contents Returns ------- None """ try: if xml_idinfo.tag == 'idinfo': self.crossrefs.clear_widgets(add_another=False) crossrefs = xml_utils.search_xpath(xml_idinfo, 'crossref', only_first=False) if crossrefs: self.ui.radio_crossrefyes.setChecked(True) else: self.crossrefs.add_another() self.ui.radio_crossrefno.setChecked(True) for crossref in crossrefs: crossref_widget = self.crossrefs.add_another() crossref_widget.from_xml(xml_utils.search_xpath(crossref, 'citeinfo')) except KeyError: self.ui.radio_crossrefno.setChecked(True)
class ProcStep(WizardWidget): # drag_label = "Process Step <procstep>" acceptable_tags = ['lineage'] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_procstep.Ui_Form() #.Ui_USGSContactInfoWidgetMain() self.ui.setupUi(self) self.setup_dragdrop(self) self.proc_step = RepeatingElement(which='tab', tab_label='Step', add_text='Additional Step', widget=ProcessStep, remove_text='Remove Step', italic_text='Processing Steps Taken') #self.proc_step = RepeatingElement(params=params, which='tab', tab_label='Source',) self.proc_step.add_another() self.ui.widget_procstep.layout().addWidget(self.proc_step) def _to_xml(self): """ encapsulates the etree process step in an element tag Returns ------- procstep portion of the lineageg element tag in xml tree """ lineage = etree.Element('lineage') procstep_list = self.proc_step.get_widgets() for procstep in procstep_list: lineage.append(procstep._to_xml()) return lineage def _from_xml(self, xml_procstep): """ parses the xml code into the relevant accconst elements Parameters ---------- access_constraints - the xml element status and its contents Returns ------- None """ try: if xml_procstep.tag == 'lineage': self.proc_step.clear_widgets(add_another=False) xml_procstep = xml_procstep.findall('procstep') if xml_procstep: for procstep in xml_procstep: procdesc_widget = self.proc_step.add_another() procdesc_widget._from_xml(procstep) else: self.proc_step.add_another() except KeyError: pass
class SourceInput(WizardWidget): drag_label = "Source Information <srcinfo>" acceptable_tags = ['lineage'] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_sourceinput.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.src_info = RepeatingElement(which='tab', tab_label='Source', add_text='Add Source', widget=SRCInfo, remove_text='Remove Source', italic_text='Source') self.src_info.add_another() self.ui.frame_sourceinfo.layout().addWidget(self.src_info) self.ui.frame_sourceinfo.hide() def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_sourceyes.toggled.connect(self.include_sources_change) def include_sources_change(self, b): """ Extended citation to support a larger body of information for the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.frame_sourceinfo.show() else: self.ui.frame_sourceinfo.hide() def clear_widget(self): self.ui.radio_sourceno_2.setChecked(True) WizardWidget.clear_widget(self) def to_xml(self): """ encapsulates the text in an element tree representing Sources Input Returns ------- series of srcinfo element tag in lineage xml tree """ lineage = xml_utils.xml_node(tag='lineage') if self.ui.radio_sourceyes.isChecked(): cnt = 0 srcinfo_list = self.src_info.get_widgets() for srcinfo in srcinfo_list: lineage.append(srcinfo.to_xml()) return lineage def from_xml(self, xml_srcinput): """ parses the xml code into the relevant accconst elements Parameters ---------- access_constraints - the xml element status and its contents Returns ------- None """ try: if xml_srcinput.tag == 'lineage': self.src_info.clear_widgets(add_another=False) self.ui.frame_sourceinfo.show() self.ui.radio_sourceyes.setChecked(True) xml_srcinput = xml_srcinput.findall('srcinfo') if xml_srcinput: for srcinput in xml_srcinput: srcinfo_widget = self.src_info.add_another() srcinfo_widget.from_xml(srcinput) else: self.ui.radio_sourceno_2.setChecked(True) self.src_info.add_another() except KeyError: pass
class Citeinfo(WizardWidget): # drag_label = "Citation information <citeinfo>" acceptable_tags = ['citation', 'citeinfo'] def __init__(self, parent=None, include_lwork=True): self.origin_hint = 'Suggested format "FIRST M. LAST"' self.include_lwork = include_lwork self.schema = 'bdp' WizardWidget.__init__(self, parent=parent) self.doi_lookup = None self.highlighter = Highlighter(self.ui.fgdc_title.document()) self.ui.fgdc_title.textChanged.connect(self.remove_returns) def remove_returns(self): self.ui.fgdc_title.textChanged.disconnect() cursor = self.ui.fgdc_title.textCursor() curtext = self.ui.fgdc_title.toPlainText() newtext = curtext.replace('\n', ' ') self.ui.fgdc_title.setPlainText(newtext) self.ui.fgdc_title.setTextCursor(cursor) self.ui.fgdc_title.textChanged.connect(self.remove_returns) def build_ui(self, ): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_citeinfo.Ui_parent_form() self.ui.setupUi(self) if self.include_lwork: self.lworkcit_widget = Citeinfo(parent=self, include_lwork=False) self.lworkcit_widget.ui.lbl_dataset_title.setText( 'Larger Work Title') self.ui.lworkcite_widget.layout().addWidget(self.lworkcit_widget) self.lworkcit_widget.ui.fgdc_geoform.setEditText('publication') else: self.ui.fgdc_lworkcit.hide() self.include_lworkext_change(self.ui.radio_lworkyes.isChecked()) self.ui.series_ext.hide() self.ui.pub_ext.hide() self.ui.pubdate_widget = FGDCDate(label='YYYYMMDD ', show_format=False, required=True, fgdc_name='fgdc_pubdate') self.ui.pubdate_layout.addWidget(self.ui.pubdate_widget) self.onlink_list = RepeatingElement( add_text='Add online link', remove_text='Remove last', italic_text= 'Is there a link to the data or the agency that produced it? if so, provide the URL(s) ', widget_kwargs={ 'label': 'Link', 'line_name': 'fgdc_onlink' }) self.onlink_list.add_another() self.ui.onlink_layout.addWidget(self.onlink_list) self.fgdc_origin = RepeatingElement( add_text='Add originator', remove_text='Remove last', italic_text= 'Who created the dataset? List the organization and/or person(s)', widget_kwargs={ 'label': 'Originator', 'line_name': 'fgdc_origin', 'required': True, 'placeholder_text': self.origin_hint, 'spellings': False }, ) self.ui.originator_layout.addWidget(self.fgdc_origin) self.fgdc_origin.add_another() self.setup_dragdrop(self) if not hananero_installed: self.ui.btn_import_doi.hide() def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_lworkyes.toggled.connect(self.include_lworkext_change) self.ui.radio_seriesyes.toggled.connect(self.include_seriesext_change) self.ui.radio_pubinfoyes.toggled.connect(self.include_pubext_change) self.ui.btn_import_doi.clicked.connect(self.get_doi_citation) 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 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 cancel(self): self.doi_lookup.deleteLater() self.doi_lookup = None def dragEnterEvent(self, e): """ Only accept Dragged items that can be converted to an xml object with a root tag called in our list of acceptable_tags Parameters ---------- e : qt event Returns ------- """ mime_data = e.mimeData() if e.mimeData().hasUrls(): if 'doi' in e.mimeData().urls()[0].url().lower(): e.accept() elif e.mimeData().hasFormat('text/plain'): if self.is_doi_str(mime_data.text()): e.accept() else: try: element = xml_utils.string_to_node(mime_data.text()) if element is not None and element.tag in self.acceptable_tags: e.accept() except AttributeError: e.ignore() else: e.ignore() def is_doi_str(self, string): if string.startswith('https://doi.org'): return True if string.startswith('doi.org'): return True if string.startswith('http://dx.doi.org'): return True if string.startswith('doi:'): return True cleaned_doi = doi_utils.clean_doi(string).lower().strip() if cleaned_doi.startswith('doi:'): return True return False def dropEvent(self, e): """ Updates the form with the contents of an xml node dropped onto it. Parameters ---------- e : qt event Returns ------- None """ try: e.setDropAction(Qt.CopyAction) e.accept() mime_data = e.mimeData() if mime_data.hasUrls() or \ self.is_doi_str(mime_data.text()): if self.is_doi_str(mime_data.text()): doi = mime_data.text() else: doi = e.mimeData().urls()[0].url() try: citeinfo = doi_utils.get_doi_citation(doi) 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) else: element = xml_utils.string_to_node(mime_data.text()) self.from_xml(element) except: e = sys.exc_info()[0] print('problem drop', e) def include_seriesext_change(self, b): """ Extended citation to support series information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.series_ext.show() else: self.ui.series_ext.hide() def include_pubext_change(self, b): """ Extended citation to support publication information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.pub_ext.show() else: self.ui.pub_ext.hide() def include_lworkext_change(self, b): """ Extended citation to support a larger body of information for the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.lworkcite_widget.show() else: self.ui.lworkcite_widget.hide() def clear_widget(self): WizardWidget.clear_widget(self) self.ui.radio_pubinfono.setChecked(True) self.ui.radio_seriesno.setChecked(True) def to_xml(self): """ encapsulates the QLineEdit text in an element tag Returns ------- citation element tag in xml tree """ citeinfo = xml_utils.xml_node('citeinfo') for origin in self.fgdc_origin.get_widgets(): xml_utils.xml_node('origin', text=origin.text(), parent_node=citeinfo) pubdate = xml_utils.xml_node("pubdate", text=self.ui.pubdate_widget.get_date(), parent_node=citeinfo) title = xml_utils.xml_node("title", self.ui.fgdc_title.toPlainText(), parent_node=citeinfo) geoform = xml_utils.xml_node("geoform", self.ui.fgdc_geoform.currentText(), parent_node=citeinfo) if self.ui.radio_seriesyes.isChecked(): serinfo = xml_utils.xml_node('serinfo', parent_node=citeinfo) sername = xml_utils.xml_node('sername', text=self.ui.fgdc_sername.text(), parent_node=serinfo) issue = xml_utils.xml_node('issue', text=self.ui.fgdc_issue.text(), parent_node=serinfo) if self.ui.radio_pubinfoyes.isChecked() and \ (self.ui.fgdc_pubplace.text() != '' or self.ui.fgdc_publish.text() != ''): pubinfo = xml_utils.xml_node('pubinfo', parent_node=citeinfo) pubplace = xml_utils.xml_node('pubplace', parent_node=pubinfo, text=self.ui.fgdc_pubplace.text()) publish = xml_utils.xml_node('publish', parent_node=pubinfo, text=self.ui.fgdc_publish.text()) if self.ui.fgdc_othercit.toPlainText(): othercit = xml_utils.xml_node("othercit", self.ui.fgdc_othercit.toPlainText(), parent_node=citeinfo) for onlink in self.onlink_list.get_widgets(): if onlink.text() != '': onlink_node = xml_utils.xml_node('onlink', parent_node=citeinfo, text=onlink.text()) if self.include_lwork and self.ui.radio_lworkyes.isChecked(): lworkcit = xml_utils.xml_node('lworkcit', parent_node=citeinfo) lwork = self.lworkcit_widget.to_xml() lworkcit.append(lwork) return citeinfo def from_xml(self, citeinfo): """ parses the xml code into the relevant citation elements Parameters ---------- citation - the xml element status and its contents Returns ------- None """ self.original_xml = citeinfo self.clear_widget() try: if citeinfo.tag == "citation": citeinfo = citeinfo.xpath('citeinfo')[0] elif citeinfo.tag != 'citeinfo': print("The tag is not 'citation' or 'citeinfo'") return self.fgdc_origin.clear_widgets(add_another=False) originators = citeinfo.findall("origin") if originators: self.fgdc_origin.clear_widgets(add_another=False) for origin in citeinfo.findall('origin'): origin_widget = self.fgdc_origin.add_another() origin_widget.setText(origin.text) else: self.fgdc_origin.add_another() if citeinfo.findall('geoform'): self.ui.fgdc_geoform.setEditText( citeinfo.findall('geoform')[0].text) utils.populate_widget_element( self.ui.pubdate_widget.ui.fgdc_caldate, citeinfo, 'pubdate') utils.populate_widget_element(self.ui.fgdc_title, citeinfo, 'title') utils.populate_widget_element(self.ui.fgdc_othercit, citeinfo, 'othercit') self.onlink_list.clear_widgets() if citeinfo.findall("onlink"): self.onlink_list.clear_widgets(add_another=False) for onlink in citeinfo.findall('onlink'): self.onlink_list.add_another() onlink_widget = self.onlink_list.widgets[-1] onlink_widget.setText(onlink.text) if citeinfo.xpath('serinfo'): self.ui.radio_seriesyes.setChecked(True) utils.populate_widget(self, citeinfo.xpath('serinfo')[0]) else: self.ui.radio_seriesyes.setChecked(False) pubinfo = citeinfo.xpath('pubinfo') if pubinfo: self.ui.radio_pubinfoyes.setChecked(True) utils.populate_widget_element(self.ui.fgdc_publish, pubinfo[0], 'publish') utils.populate_widget_element(self.ui.fgdc_pubplace, pubinfo[0], 'pubplace') else: self.ui.radio_pubinfoyes.setChecked(False) self.ui.radio_pubinfono.setChecked(True) if citeinfo.xpath('lworkcit'): try: self.ui.radio_lworkyes.setChecked(True) self.lworkcit_widget.from_xml( citeinfo.xpath('lworkcit/citeinfo')[0]) except AttributeError: msg = 'you pasted a citation element into the larger work citation area' msg += '\n that contained a larger work citation' msg += '\n Multiple nested larger work citations are not currently supported in the tool' msg += '\n\n the larger work citation being pasted will be ignored' QMessageBox.warning(self, "Dropped Content Warning", msg) else: self.ui.radio_lworkno.setChecked(True) except KeyError: pass
class ThemeList(WizardWidget): # drag_label = "Theme Keywords <keywords>" def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_theme_list.Ui_theme_list() self.ui.setupUi(self) self.setup_dragdrop(self) self.ui.theme_tabs.setStyleSheet("QTabBar::tab::disabled {width: 0; height: 0; margin: 0; padding: 0; border: none;} ") self.iso_kws = RepeatingElement(which='vertical', add_text='Add additonal', widget=IsoKeyword, remove_text='Remove Keyword', italic_text='ISO Topic Category Keywords') self.iso_kws.add_another() self.ui.iso_keywords_layout.addWidget(self.iso_kws) self.thesauri = [] def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.btn_add_thesaurus.clicked.connect(self.add_another) self.ui.btn_remove_selected.clicked.connect(self.remove_selected) self.ui.btn_add_iso.clicked.connect(self.add_iso) self.ui.btn_search_controlled.clicked.connect(self.search_controlled) def add_another(self, click=False, tab_label='', locked=False): if 'None' not in [t.get_thesaurus_name() for t in self.thesauri] and \ tab_label == '': theme_widget = self.add_keyword(keyword='', thesaurus='None', locked=False) else: theme_widget = Theme() theme_widget.ui.fgdc_themekt.textChanged.connect(self.changed_thesaurus) self.ui.theme_tabs.addTab(theme_widget, tab_label) self.ui.theme_tabs.setCurrentIndex(self.ui.theme_tabs.count()-1) self.thesauri.append(theme_widget) return theme_widget def changed_thesaurus(self, s): current_index = self.ui.theme_tabs.currentIndex() current_tab = self.ui.theme_tabs.setTabText(current_index, 'Thesaurus: ' + s) def remove_selected(self): current_index = self.ui.theme_tabs.currentIndex() if current_index == 0: self.ui.theme_tabs.setTabEnabled(0, False) self.ui.iso_tab.hide() else: self.ui.theme_tabs.removeTab(current_index) del self.thesauri[current_index-1] def add_iso(self): self.ui.theme_tabs.setTabEnabled(0, True) self.ui.iso_tab.show() def clear_widget(self): self.iso_kws.clear_widgets() for i in range(len(self.thesauri), 0, -1): self.ui.theme_tabs.setCurrentIndex(i) self.remove_selected() def search_controlled(self): self.thesaurus_search = ThesaurusSearch.ThesaurusSearch(add_term_function=self.add_keyword) self.thesaurus_search.setWindowTitle('Theme Keyword Thesaurus Search') fg = self.frameGeometry() self.thesaurus_search.move(fg.topRight() - QPoint(150, -25)) self.thesaurus_search.show() def add_keyword(self, keyword=None, thesaurus=None, locked=True): theme_widget = None for theme in self.thesauri: if theme.ui.fgdc_themekt.text() == thesaurus: theme_widget = theme if theme_widget is None: shortname = thesaurus.split(' ')[0] theme_widget = self.add_another(tab_label=shortname, locked=locked) theme_widget.ui.fgdc_themekt.setText(thesaurus) if locked: theme_widget.lock() self.changed_thesaurus(shortname) theme_widget.add_keyword(keyword, locked=locked) return theme_widget def dragEnterEvent(self, e): """ Only accept Dragged items that can be converted to an xml object with a root tag called 'procstep' Parameters ---------- e : qt event Returns ------- None """ print("pc drag enter") mime_data = e.mimeData() if e.mimeData().hasFormat('text/plain'): parser = etree.XMLParser(ns_clean=True, recover=True, encoding='utf-8') element = etree.fromstring(mime_data.text(), parser=parser) if element.tag == 'keywords': e.accept() else: e.ignore() def _to_xml(self): """ encapsulates the QPlainTextEdit text in an element tag Returns ------- procstep element tag in xml tree """ keywords = xml_utils.xml_node('keywords') for theme in self.thesauri: theme_xml = theme._to_xml() keywords.append(theme_xml) return keywords def _from_xml(self, keywords_xml): """ parses the xml code into the relevant procstep elements Parameters ---------- process_step - the xml element status and its contents Returns ------- None """ self.clear_widget() self.original_xml = keywords_xml if keywords_xml.tag == 'keywords': for theme_xml in keywords_xml.xpath('theme'): if theme_xml.xpath('themekt'): themekt = theme_xml.xpath('themekt')[0] if 'iso 19115' in themekt.text.lower(): self.iso_kws.clear_widgets(add_another=False) for themekey in theme_xml.xpath('themekey'): iso = self.iso_kws.add_another() iso.ui.comboBox.setCurrentText(themekey.text) else: theme = self.add_another() theme._from_xml(theme_xml)
class Citeinfo(WizardWidget): # drag_label = "Citation information <citeinfo>" acceptable_tags = ["citation", "citeinfo"] def __init__(self, parent=None, include_lwork=True): self.origin_hint = 'Suggested format "First M. Last"' self.include_lwork = include_lwork self.schema = "bdp" WizardWidget.__init__(self, parent=parent) self.doi_lookup = None self.highlighter = Highlighter(self.ui.fgdc_title.document()) self.ui.fgdc_title.textChanged.connect(self.remove_returns) self.ui.fgdc_title.setMaximumHeight(self.ui.fgdc_geoform.height()) self.ui.fgdc_title.mouseMoveEvent = self.mouse_move def mouse_move(self, e): """ over ride the mouse move event to ignore mouse movement (scrolling), but only in the vertical dimension. Makes this plain text edit look and feel like a line edit. Parameters ---------- e : pyqt event Returns ------- None """ if (e.y() < self.ui.fgdc_title.height() - 3 and e.x() < self.ui.fgdc_title.width() - 3): QPlainTextEdit.mouseMoveEvent(self.ui.fgdc_title, e) self.ui.fgdc_title.verticalScrollBar().setValue( self.ui.fgdc_title.verticalScrollBar().minimum()) def remove_returns(self): """ After changes to the title, we need to make sure that the user has not entered any line returns, since the title is not intended to be a multiline string. Any line returns "\n" will be replace with a ' ' Returns ------- None """ self.ui.fgdc_title.textChanged.disconnect() old_position = self.ui.fgdc_title.textCursor().position() curtext = self.ui.fgdc_title.toPlainText() newtext = curtext.replace("\n", " ") self.ui.fgdc_title.setPlainText(newtext) cursor = self.ui.fgdc_title.textCursor() cursor.setPosition(old_position) self.ui.fgdc_title.setTextCursor(cursor) self.ui.fgdc_title.textChanged.connect(self.remove_returns) def build_ui(self, ): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_citeinfo.Ui_parent_form() self.ui.setupUi(self) if self.include_lwork: self.lworkcit_widget = Citeinfo(parent=self, include_lwork=False) self.lworkcit_widget.ui.lbl_dataset_title.setText( "Larger Work Title") self.ui.lworkcite_widget.layout().addWidget(self.lworkcit_widget) self.lworkcit_widget.ui.fgdc_geoform.setEditText("publication") else: self.ui.fgdc_lworkcit.hide() self.include_lworkext_change(self.ui.radio_lworkyes.isChecked()) self.ui.series_ext.hide() self.ui.pub_ext.hide() self.ui.pubdate_widget = FGDCDate( label="YYYYMMDD ", show_format=False, required=True, fgdc_name="fgdc_pubdate", ) self.ui.pubdate_layout.addWidget(self.ui.pubdate_widget) self.onlink_list = RepeatingElement( add_text="Add online link", remove_text="Remove last", italic_text= "Is there a link to the data or the agency that produced it? if so, provide the URL(s) ", widget_kwargs={ "label": "Link", "line_name": "fgdc_onlink" }, ) self.onlink_list.add_another() self.ui.onlink_layout.addWidget(self.onlink_list) self.fgdc_origin = RepeatingElement( add_text="Add originator", remove_text="Remove last", italic_text= "Who created the dataset? List the organization and/or person(s)", widget_kwargs={ "label": "Originator", "line_name": "fgdc_origin", "required": True, "placeholder_text": self.origin_hint, "spellings": False, }, ) self.ui.originator_layout.addWidget(self.fgdc_origin) self.fgdc_origin.add_another() self.setup_dragdrop(self) if not hananero_installed: self.ui.btn_import_doi.hide() def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.radio_lworkyes.toggled.connect(self.include_lworkext_change) self.ui.radio_seriesyes.toggled.connect(self.include_seriesext_change) self.ui.radio_pubinfoyes.toggled.connect(self.include_pubext_change) self.ui.btn_import_doi.clicked.connect(self.get_doi_citation) 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 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 cancel(self): self.doi_lookup.deleteLater() self.doi_lookup = None def dragEnterEvent(self, e): """ Only accept Dragged items that can be converted to an xml object with a root tag called in our list of acceptable_tags Parameters ---------- e : qt event Returns ------- """ mime_data = e.mimeData() if e.mimeData().hasUrls(): if "doi" in e.mimeData().urls()[0].url().lower(): e.accept() elif e.mimeData().hasFormat("text/plain"): if self.is_doi_str(mime_data.text()): e.accept() else: try: element = xml_utils.string_to_node(mime_data.text()) if element is not None and element.tag in self.acceptable_tags: e.accept() except AttributeError: e.ignore() else: e.ignore() def is_doi_str(self, string): if string.startswith("https://doi.org"): return True if string.startswith("doi.org"): return True if string.startswith("http://dx.doi.org"): return True if string.startswith("doi:"): return True cleaned_doi = doi_utils.clean_doi(string).lower().strip() if cleaned_doi.startswith("doi:"): return True return False def dropEvent(self, e): """ Updates the form with the contents of an xml node dropped onto it. Parameters ---------- e : qt event Returns ------- None """ try: e.setDropAction(Qt.CopyAction) e.accept() mime_data = e.mimeData() if mime_data.hasUrls() or self.is_doi_str(mime_data.text()): if self.is_doi_str(mime_data.text()): doi = mime_data.text() else: doi = e.mimeData().urls()[0].url() try: citeinfo = doi_utils.get_doi_citation(doi) 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) else: element = xml_utils.string_to_node(mime_data.text()) self.from_xml(element) except: e = sys.exc_info()[0] print("problem drop", e) def include_seriesext_change(self, b): """ Extended citation to support series information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.series_ext.show() else: self.ui.series_ext.hide() def include_pubext_change(self, b): """ Extended citation to support publication information of the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.pub_ext.show() else: self.ui.pub_ext.hide() def include_lworkext_change(self, b): """ Extended citation to support a larger body of information for the record. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.lworkcite_widget.show() else: self.ui.lworkcite_widget.hide() def clear_widget(self): WizardWidget.clear_widget(self) self.ui.radio_pubinfono.setChecked(True) self.ui.radio_seriesno.setChecked(True) def to_xml(self): """ encapsulates the QLineEdit text in an element tag Returns ------- citation element tag in xml tree """ citeinfo = xml_utils.xml_node("citeinfo") for origin in self.fgdc_origin.get_widgets(): xml_utils.xml_node("origin", text=origin.text(), parent_node=citeinfo) pubdate = xml_utils.xml_node("pubdate", text=self.ui.pubdate_widget.get_date(), parent_node=citeinfo) title = xml_utils.xml_node("title", self.ui.fgdc_title.toPlainText(), parent_node=citeinfo) if self.ui.fgdc_edition.text(): othercit = xml_utils.xml_node("edition", self.ui.fgdc_edition.text(), parent_node=citeinfo) geoform = xml_utils.xml_node("geoform", self.ui.fgdc_geoform.currentText(), parent_node=citeinfo) if self.ui.radio_seriesyes.isChecked(): serinfo = xml_utils.xml_node("serinfo", parent_node=citeinfo) sername = xml_utils.xml_node("sername", text=self.ui.fgdc_sername.text(), parent_node=serinfo) issue = xml_utils.xml_node("issue", text=self.ui.fgdc_issue.text(), parent_node=serinfo) if self.ui.radio_pubinfoyes.isChecked() and ( self.ui.fgdc_pubplace.text() != "" or self.ui.fgdc_publish.text() != ""): pubinfo = xml_utils.xml_node("pubinfo", parent_node=citeinfo) pubplace = xml_utils.xml_node("pubplace", parent_node=pubinfo, text=self.ui.fgdc_pubplace.text()) publish = xml_utils.xml_node("publish", parent_node=pubinfo, text=self.ui.fgdc_publish.text()) if self.ui.fgdc_othercit.toPlainText(): othercit = xml_utils.xml_node("othercit", self.ui.fgdc_othercit.toPlainText(), parent_node=citeinfo) for onlink in self.onlink_list.get_widgets(): if onlink.text() != "": onlink_node = xml_utils.xml_node("onlink", parent_node=citeinfo, text=onlink.text()) if self.include_lwork and self.ui.radio_lworkyes.isChecked(): lworkcit = xml_utils.xml_node("lworkcit", parent_node=citeinfo) lwork = self.lworkcit_widget.to_xml() lworkcit.append(lwork) return citeinfo def from_xml(self, citeinfo): """ parses the xml code into the relevant citation elements Parameters ---------- citation - the xml element status and its contents Returns ------- None """ self.original_xml = citeinfo self.clear_widget() try: if citeinfo.tag == "citation": citeinfo = citeinfo.xpath("citeinfo")[0] elif citeinfo.tag != "citeinfo": print("The tag is not 'citation' or 'citeinfo'") return self.fgdc_origin.clear_widgets(add_another=False) originators = citeinfo.findall("origin") if originators: self.fgdc_origin.clear_widgets(add_another=False) for origin in citeinfo.findall("origin"): origin_widget = self.fgdc_origin.add_another() origin_widget.setText(origin.text) else: self.fgdc_origin.add_another() if citeinfo.findall("geoform"): self.ui.fgdc_geoform.setEditText( citeinfo.findall("geoform")[0].text) utils.populate_widget_element( self.ui.pubdate_widget.ui.fgdc_caldate, citeinfo, "pubdate") utils.populate_widget_element(self.ui.fgdc_title, citeinfo, "title") utils.populate_widget_element(self.ui.fgdc_edition, citeinfo, "edition") utils.populate_widget_element(self.ui.fgdc_othercit, citeinfo, "othercit") self.onlink_list.clear_widgets() if citeinfo.findall("onlink"): self.onlink_list.clear_widgets(add_another=False) for onlink in citeinfo.findall("onlink"): self.onlink_list.add_another() onlink_widget = self.onlink_list.widgets[-1] onlink_widget.setText(onlink.text) if citeinfo.xpath("serinfo"): self.ui.radio_seriesyes.setChecked(True) utils.populate_widget(self, citeinfo.xpath("serinfo")[0]) else: self.ui.radio_seriesyes.setChecked(False) pubinfo = citeinfo.xpath("pubinfo") if pubinfo: self.ui.radio_pubinfoyes.setChecked(True) utils.populate_widget_element(self.ui.fgdc_publish, pubinfo[0], "publish") utils.populate_widget_element(self.ui.fgdc_pubplace, pubinfo[0], "pubplace") else: self.ui.radio_pubinfoyes.setChecked(False) self.ui.radio_pubinfono.setChecked(True) if citeinfo.xpath("lworkcit"): try: self.ui.radio_lworkyes.setChecked(True) self.lworkcit_widget.from_xml( citeinfo.xpath("lworkcit/citeinfo")[0]) except AttributeError: msg = "you pasted a citation element into the larger work citation area" msg += "\n that contained a larger work citation" msg += "\n Multiple nested larger work citations are not currently supported in the tool" msg += "\n\n the larger work citation being pasted will be ignored" QMessageBox.warning(self, "Dropped Content Warning", msg) else: self.ui.radio_lworkno.setChecked(True) except KeyError: pass
class ProcStep(WizardWidget): # drag_label = "Process Step <procstep>" acceptable_tags = ['lineage'] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_procstep.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.proc_step = RepeatingElement(which='tab', tab_label='Step', add_text='Additional Step', widget=ProcessStep, remove_text='Remove Step', italic_text='Describe the methods performed to collect or generate the data.\n Provide as much detail as possible.') self.proc_step.add_another() self.ui.widget_procstep.layout().addWidget(self.proc_step) def to_xml(self): """ encapsulates the etree process step in an element tag Returns ------- procstep portion of the lineageg element tag in xml tree """ lineage = xml_utils.xml_node(tag='lineage') procstep_list = self.proc_step.get_widgets() for procstep in procstep_list: lineage.append(procstep.to_xml()) return lineage def from_xml(self, xml_procstep): """ parses the xml code into the relevant accconst elements Parameters ---------- access_constraints - the xml element status and its contents Returns ------- None """ try: if xml_procstep.tag == 'lineage': self.proc_step.clear_widgets(add_another=False) xml_procstep = xml_procstep.findall('procstep') if xml_procstep: for procstep in xml_procstep: procdesc_widget = self.proc_step.add_another() procdesc_widget.from_xml(procstep) else: self.proc_step.add_another() except KeyError: pass
class KeywordsRepeater(WizardWidget): drag_label = "NA <NA>" def __init__( self, thesaurus_label="Thesaurus", keywords_label="Keywords:", line_name="kw", spellings=True, parent=None, ): self.thesaurus_label = thesaurus_label self.keywords_label = keywords_label self.line_name = line_name self.keywords = None self.spellings = spellings WizardWidget.__init__(self, parent=parent) def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_keywords_repeater.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.ui.thesaurus_label = self.thesaurus_label widget_kwargs = { "label": self.keywords_label, "line_name": self.line_name, "required": True, "spellings": self.spellings, } self.keywords = RepeatingElement( add_text="Add keyword", remove_text="Remove last", widget_kwargs=widget_kwargs, ) self.keywords.ui.italic_label.setStyleSheet("") self.keywords.add_another() self.ui.keywords_layout.insertWidget(0, self.keywords) def lock(self): self.ui.fgdc_themekt.setReadOnly(True) self.keywords.ui.addAnother.setEnabled(False) def get_keywords(self): return [kw.text() for kw in self.keywords.get_widgets()] def add_another(self, locked=False): widget = self.keywords.add_another() widget.setObjectName(self.line_name) widget.added_line.setReadOnly(locked) return widget def get_widgets(self): return self.keywords.get_widgets()
class ThemeList(WizardWidget): # drag_label = "Theme Keywords <keywords>" acceptable_tags = ["keywords"] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_theme_list.Ui_theme_list() self.ui.setupUi(self) self.setup_dragdrop(self) self.ui.theme_tabs.setStyleSheet( "QTabBar::tab::disabled {width: 0; height: 0; margin: 0; padding: 0; border: none;} " ) self.iso_kws = RepeatingElement( which="vertical", add_text="Add additonal", widget=IsoKeyword, remove_text="Remove Keyword", italic_text="ISO Topic Category Keywords", ) self.iso_kws.add_another() self.ui.iso_keywords_layout.addWidget(self.iso_kws) self.thesauri = [] def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ self.ui.btn_add_thesaurus.clicked.connect(self.add_another) self.ui.btn_remove_selected.clicked.connect(self.remove_selected) self.ui.btn_add_iso.clicked.connect(self.add_iso) self.ui.btn_search_controlled.clicked.connect(self.search_controlled) def add_another(self, click=False, tab_label="", locked=False): if ( "None" not in [t.get_thesaurus_name() for t in self.thesauri] and tab_label == "" ): theme_widget = self.add_keyword(keyword="", thesaurus="None", locked=False) else: theme_widget = Theme() theme_widget.ui.fgdc_themekt.textChanged.connect(self.changed_thesaurus) self.ui.theme_tabs.addTab(theme_widget, tab_label) self.ui.theme_tabs.setCurrentIndex(self.ui.theme_tabs.count() - 1) self.thesauri.append(theme_widget) return theme_widget def changed_thesaurus(self, s): current_index = self.ui.theme_tabs.currentIndex() self.ui.theme_tabs.setTabText(current_index, "Thesaurus: " + s) def remove_selected(self): current_index = self.ui.theme_tabs.currentIndex() if current_index == 0: self.remove_iso() else: self.ui.theme_tabs.removeTab(current_index) del self.thesauri[current_index - 1] def remove_iso(self): self.ui.theme_tabs.setTabEnabled(0, False) self.ui.fgdc_theme.hide() def add_iso(self): self.ui.theme_tabs.setTabEnabled(0, True) self.ui.theme_tabs.setTabText(0, "ISO 19115") self.ui.fgdc_theme.show() self.ui.theme_tabs.setCurrentIndex(0) self.resize(100, 100) def get_children(self, widget): children = [] if self.ui.theme_tabs.isTabEnabled(0): children.append(self.ui.fgdc_theme) for theme in self.thesauri: children.append(theme) return children def clear_widget(self, remove_iso=False): self.iso_kws.clear_widgets() if remove_iso: self.remove_iso() for i in range(len(self.thesauri), -1, -1): self.ui.theme_tabs.setCurrentIndex(i) self.remove_selected() self.ui.fgdc_themekt.setText("ISO 19115 Topic Category") def search_controlled(self): self.thesaurus_search = ThesaurusSearch.ThesaurusSearch( add_term_function=self.add_keyword, parent=self ) self.thesaurus_search.setWindowTitle("Search USGS Controlled Vocabularies") self.thesaurus_search.show() def add_keyword(self, keyword=None, thesaurus=None, locked=True): theme_widget = None for i, theme in enumerate(self.thesauri): if theme.ui.fgdc_themekt.text() == thesaurus: theme_widget = theme try: self.ui.theme_tabs.setCurrentIndex(i + 1) except IndexError: pass if theme_widget is None: shortname = thesaurus.split(" ")[0] theme_widget = self.add_another(tab_label=shortname, locked=locked) theme_widget.ui.fgdc_themekt.setText(thesaurus) if locked: theme_widget.lock() self.changed_thesaurus(shortname) theme_widget.add_keyword(keyword, locked=locked) return theme_widget def to_xml(self): """ encapsulates the QPlainTextEdit text in an element tag Returns ------- procstep element tag in xml tree """ keywords = xml_utils.xml_node("keywords") if self.ui.theme_tabs.isTabEnabled(0): theme = xml_utils.xml_node("theme", parent_node=keywords) themekt = xml_utils.xml_node( "themekt", text=self.ui.fgdc_themekt.text(), parent_node=theme ) for isokw in self.iso_kws.get_widgets(): themekey = xml_utils.xml_node( "themekey", text=isokw.ui.fgdc_themekey.currentText(), parent_node=theme, ) for theme in self.thesauri: theme_xml = theme.to_xml() if ( theme_xml.xpath("themekt")[0].text == "None" and len(theme_xml.xpath("themekey")) == 1 and theme_xml.xpath("themekey")[0].text is None and len(self.thesauri) >= 2 ): # Skip themes that still have the default thesaurus ('None') # with no keywords entered, # when they added an additional thesaurus pass else: keywords.append(theme_xml) return keywords def from_xml(self, keywords_xml): """ parses the xml code into the relevant procstep elements Parameters ---------- process_step - the xml element status and its contents Returns ------- None """ self.clear_widget(remove_iso=True) self.original_xml = keywords_xml if keywords_xml.tag == "keywords": for theme_xml in xml_utils.search_xpath(keywords_xml, "theme", False): themekt = xml_utils.get_text_content(theme_xml, "themekt") if themekt is not None and "iso 19115" in themekt.lower(): self.add_iso() self.iso_kws.clear_widgets(add_another=False) for themekey in xml_utils.search_xpath( theme_xml, "themekey", only_first=False ): iso = self.iso_kws.add_another() iso.ui.fgdc_themekey.setCurrentText(themekey.text) else: theme = self.add_another() theme.from_xml(theme_xml)
class Vertdef(WizardWidget): # drag_label = "Time Period information <vertdef>" acceptable_tags = ["vertdef", "altsys", "depthsys"] def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = UI_vertdef.Ui_Form() self.ui.setupUi(self) self.setup_dragdrop(self) self.altres_list = RepeatingElement( widget_kwargs={ "label": "Altitude Resolution", "line_name": "fgdc_altres", "required": True, }, add_text="+", remove_text="-", ) self.altres_list.add_another() self.ui.altsys_contents.layout().insertWidget(1, self.altres_list) self.depthres_list = RepeatingElement( widget_kwargs={ "label": "Depth Resolution", "line_name": "fgdc_depthres", "required": True, }, add_text="+", remove_text="-", ) self.depthres_list.add_another() self.ui.depthsys_contents.layout().insertWidget(1, self.depthres_list) def connect_events(self): """ Connect the appropriate GUI components with the corresponding functions Returns ------- None """ # self.ui.radio_single.toggled.connect(self.switch_primary) self.ui.rbtn_yes.toggled.connect(self.include_vertdef_change) self.ui.rbtn_yes_alt.toggled.connect(self.include_alt_change) self.ui.rbtn_yes_depth.toggled.connect(self.include_depth_change) def has_content(self): """ Returns if the widget contains legitimate content that should be written out to xml By default this is always true but should be implement in each subclass with logic to check based on contents Returns ------- bool : True if there is content, False if no """ return self.ui.rbtn_yes.isChecked() def include_vertdef_change(self, b): """ Extended vertical definition section. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.content_layout.show() else: self.ui.content_layout.hide() def include_vertdef_change(self, b): """ Extended vertical definition section. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.content_layout.show() else: self.ui.content_layout.hide() def include_alt_change(self, b): """ Extended vertical definition section. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.altsys_contents.show() else: self.ui.altsys_contents.hide() def include_depth_change(self, b): """ Extended vertical definition section. Parameters ---------- b: qt event Returns ------- None """ if b: self.ui.depthsys_contents.show() else: self.ui.depthsys_contents.hide() def clear_widget(self): WizardWidget.clear_widget(self) self.ui.rbtn_no.setChecked(True) self.ui.rbtn_no_alt.setChecked(True) self.ui.rbtn_no_depth.setChecked(True) def to_xml(self): """ encapsulates the QTabWidget text for Metadata Time in an element tag Returns ------- timeinfo element tag in xml tree """ if self.ui.rbtn_yes.isChecked(): vertdef = xml_utils.xml_node("vertdef") if self.ui.rbtn_yes_alt.isChecked(): altsys = xml_utils.xml_node("altsys", parent_node=vertdef) altdatum = xml_utils.xml_node( "altdatum", text=self.ui.fgdc_altdatum.currentText(), parent_node=altsys, ) for widget in self.altres_list.get_widgets(): altres = xml_utils.xml_node( "altres", widget.added_line.toPlainText(), parent_node=altsys) altunits = xml_utils.xml_node( "altunits", text=self.ui.fgdc_altunits.currentText(), parent_node=altsys, ) altenc = xml_utils.xml_node( "altenc", text=self.ui.fgdc_altenc.currentText(), parent_node=altsys) if self.ui.rbtn_yes_depth.isChecked(): depth = xml_utils.xml_node("depthsys", parent_node=vertdef) depthdn = xml_utils.xml_node( "depthdn", text=self.ui.fgdc_depthdn.currentText(), parent_node=depth, ) for widget in self.depthres_list.get_widgets(): depthres = xml_utils.xml_node( "depthres", widget.added_line.toPlainText(), parent_node=depth) depthdu = xml_utils.xml_node( "depthdu", text=self.ui.fgdc_depthdu.currentText(), parent_node=depth, ) depthem = xml_utils.xml_node( "depthem", text=self.ui.fgdc_depthem.currentText(), parent_node=depth, ) return vertdef else: return None def from_xml(self, vertdef): """ parses the xml code into the relevant timeinfo elements Parameters ---------- metadata_date - the xml element timeinfo and its contents Returns ------- None """ self.clear_widget() try: if vertdef.tag == "vertdef": self.ui.rbtn_yes.setChecked(True) if vertdef.xpath("altsys"): self.ui.rbtn_yes_alt.setChecked(True) self.altres_list.clear_widgets(add_another=False) for altres in vertdef.xpath("altsys/altres"): altres_widget = self.altres_list.add_another() altres_widget.added_line.setPlainText(altres.text) if len(vertdef.xpath("altsys/altres")) == 0: self.altres_list.add_another() else: self.ui.rbtn_no_alt.setChecked(True) if vertdef.xpath("depthsys"): self.ui.rbtn_yes_depth.setChecked(True) self.depthres_list.clear_widgets(add_another=False) for depthres in vertdef.xpath("depthsys/depthres"): depthres_widget = self.depthres_list.add_another() depthres_widget.added_line.setPlainText(depthres.text) if len(vertdef.xpath("depthsys/depthres")) == 0: self.depthres_list.add_another() else: self.ui.rbtn_no_depth.setChecked(True) utils.populate_widget(self, vertdef) else: print("The tag is not a vertdef") except KeyError: pass