class ProfileFormWidget(QWidget): ''' classdocs ''' def __init__(self): ''' Constructor ''' QWidget.__init__(self) self._initGUI() def _initGUI(self): self.layout = QVBoxLayout() self.form = QFormLayout() self.name = QLineEdit() self.surname = QLineEdit() self.birthdate = QCalendarWidget() self.birthdate.setGridVisible(True) self.birthdate.setMinimumDate(QDate(1850, 1, 1)) self.birthdate.setMaximumDate(QDate.currentDate()) self.male = QRadioButton("Male") self.male.setChecked(True) self.female = QRadioButton("Female") self.height = QDoubleSpinBox() self.height.setMaximum(250) self.height.setMinimum(50) self.height.setValue(165) self.height.setSuffix(" cm") self.mass = QDoubleSpinBox() self.mass.setMaximum(300) self.mass.setMinimum(20) self.mass.setValue(60) self.mass.setSuffix(" Kg") btnLayout = QVBoxLayout() self.form.addRow("Name", self.name) self.form.addRow("Surname", self.surname) self.form.addRow("Birth date", self.birthdate) sexLayout = QHBoxLayout() sexLayout.addWidget(self.male) sexLayout.addWidget(self.female) self.form.addRow("Sex", sexLayout) self.form.addRow("Height", self.height) self.form.addRow("Mass", self.mass) self.layout.addLayout(self.form) self.layout.addLayout(btnLayout) self.setLayout(self.layout) def getLayout(self): return self.layout def getWidget(self): widget = QWidget() widget.setLayout(self.layout) return widget def setProfile(self, athlete): self.name.setText(athlete._name) self.surname.setText(athlete._surname) self.birthdate.setSelectedDate(athlete._birthDate) if athlete._sex == "Male": self.male.setChecked(True) else: self.female.setChecked(True) self.height.setValue(athlete._height) self.mass.setValue(athlete._mass) def getProfile(self): qDate = self.birthdate.selectedDate() birthDate = self.qDate_to_date(qDate) athleteProfile = Athlete(self.name.text(), self.surname.text(), self._getSex(), birthDate, self.height.value(), self.mass.value()) return athleteProfile def qDate_to_date(self, qDate): return date(qDate.year(), qDate.month(), qDate.day()) def _getSex(self): if (self.male.isChecked()): return "Male" elif (self.female.isChecked()): return "Female" else: print "Error: No sex selected" return False
class Form(QDialog): def __init__(self, state, term, candidates, result, parent=None): super().__init__(parent) Lib.prepareModalDialog(self) self.state = state self.term = term self.candidates = [] for candidate in candidates: self.candidates.append(humanizedCandidate( term, candidate.candidate, candidate.saf)) self.result = result self.setWindowTitle("Sort As — {}".format( QApplication.applicationName())) self.createWidgets() self.layoutWidgets() self.createConnections() self.updateUi() settings = QSettings() self.updateToolTips(bool(int(settings.value( Gopt.Key.ShowDialogToolTips, Gopt.Default.ShowDialogToolTips)))) def createWidgets(self): self.termLabel = Widgets.Label.HtmlLabel( "<p>Sort “{}” with</p>".format(Lib.elidePatchHtml(self.term, self.state))) self.radioButtons = [] seen = set() for index, candidate in enumerate(self.candidates, 1): candidate_word = str(candidate.candidate_word) name = self.nameForKind(candidate.kind, candidate_word) extra = "" if candidate_word in seen: extra = " (treat roman numbers as literal text)" else: seen.add(candidate_word) radioButton = QRadioButton("&{} “{}” as{} “{}”{}".format( index, candidate.term_word, name, candidate_word, extra)) self.radioButtons.append(radioButton) self.radioButtons[0].setChecked(True) self.customRadioButton = QRadioButton("&Custom:") self.tooltips.append((self.customRadioButton, """\ <p><b>Custom</b></p> <p>If checked, this entry's <b>Automatically Calculate Sort As</b> setting will be <i>unchecked</i>, and the sort as text entered here will be used as ther entry's sort as text.</p>""")) self.sortAsEdit = Widgets.LineEdit.LineEdit(self.state) self.tooltips.append((self.sortAsEdit, """\ <p><b>Custom Sort As editor</b></p> <p>If <b>Custom</b> is checked, this entry's <b>Automatically Calculate Sort As</b> setting will be <i>unchecked</i>, and the sort as text entered here will be used as ther entry's sort as text.</p>""")) self.sortAsEdit.setText(self.candidates[0].candidate) self.sortAsEdit.selectAll() self.buttonBox = QDialogButtonBox() self.okButton = QPushButton(QIcon(":/ok.svg"), "&OK") self.tooltips.append((self.okButton, """\ <p><b>OK</b></p> <p>Use the specified or custom sort as text for entry “{}”.</p>""".format(Lib.elidePatchHtml(self.term, self.state)))) self.buttonBox.addButton( self.okButton, QDialogButtonBox.AcceptRole) self.helpButton = QPushButton(QIcon(":/help.svg"), "Help") self.tooltips.append((self.helpButton, "Help on the Sort As dialog")) self.buttonBox.addButton( self.helpButton, QDialogButtonBox.HelpRole) def nameForKind(self, kind, candidate_word): name = kind.name.lower() if name == "unchanged": name = "" elif (name == "roman" or ( name == "phrase" and re.fullmatch(r"[\d.]+", candidate_word) is not None)): name = "number" if name: name = " " + name return name def layoutWidgets(self): vbox = QVBoxLayout() vbox.addWidget(self.termLabel) for radioButton in self.radioButtons: vbox.addWidget(radioButton) hbox = QHBoxLayout() hbox.addWidget(self.customRadioButton) hbox.addWidget(self.sortAsEdit) vbox.addLayout(hbox) vbox.addWidget(self.buttonBox) self.setLayout(vbox) def createConnections(self): for radioButton in itertools.chain((self.customRadioButton,), self.radioButtons): radioButton.toggled.connect(self.updateUi) self.sortAsEdit.textChanged.connect(self.updateUi) self.okButton.clicked.connect(self.accept) self.helpButton.clicked.connect(self.help) def help(self): self.state.help("xix_ref_dlg_sortas.html") def updateUi(self): self.sortAsEdit.setEnabled(self.customRadioButton.isChecked()) with Lib.BlockSignals(self.sortAsEdit): for i, radioButton in enumerate(self.radioButtons): if radioButton.isChecked(): self.sortAsEdit.setText(self.candidates[i].candidate) self.sortAsEdit.selectAll() break self.okButton.setEnabled( not self.customRadioButton.isChecked() or (self.customRadioButton.isChecked() and bool(self.sortAsEdit.toPlainText()))) def reject(self): self.accept() def accept(self): if self.customRadioButton.isChecked(): self.result.sortas = self.sortAsEdit.toPlainText() self.result.saf = Saf.CUSTOM else: for index, radioButton in enumerate(self.radioButtons): if radioButton.isChecked(): self.result.sortas = self.candidates[index].candidate kind = self.candidates[index].kind if kind is CandidateKind.LITERAL: saf = Saf.AUTO_BASIC elif kind is CandidateKind.NUMBER: saf = Saf.AUTO_NUMBER elif kind is CandidateKind.ROMAN: saf = Saf.AUTO_NUMBER_ROMAN elif kind is CandidateKind.PHRASE: saf = Saf.AUTO elif kind is CandidateKind.UNCHANGED: saf = self.candidates[index].saf self.result.saf = saf break super().accept()
class Form(QDialog): def __init__(self, state, parent=None): super().__init__(parent) Lib.prepareModalDialog(self) self.state = state self.setWindowTitle("Copy Entry — {}".format( QApplication.applicationName())) self.createWidgets() self.layoutWidgets() self.createConnections() self.updateUi() settings = QSettings() self.updateToolTips( bool( int( settings.value(Gopt.Key.ShowDialogToolTips, Gopt.Default.ShowDialogToolTips)))) def createWidgets(self): selectedEid = self.state.viewAllPanel.view.selectedEid self.selectedEntry = self.state.model.entry(selectedEid) self.entryLabel = QLabel("Copy ") termText = Lib.elidePatchHtml(self.selectedEntry.term, self.state) self.termLabel = Widgets.Label.HtmlLabel("“{}”".format(termText)) self.eidGroup = QGroupBox() self.copyToTopRadioButton = QRadioButton("to be a &Main Entry") self.tooltips.append((self.copyToTopRadioButton, """\ <p><b>to be a Main Entry</b></p> <p>Copy the original entry to be a Main Entry (even if it is already).</p>""")) self.subentryRadioButton = QRadioButton("to be a &Subentry of itself") self.tooltips.append((self.subentryRadioButton, """\ <p><b>to be a Subentry of itself</b></p> <p>Copy the original entry to be a subentry of the original entry.</p>""")) self.siblingRadioButton = QRadioButton("to be a Si&bling of itself") self.tooltips.append((self.subentryRadioButton, """\ <p><b>to be a Sibling of itself</b></p> <p>Copy the original entry to be a sibling of itself, i.e., to be a subentry of the original entry's parent.</p>""")) self.filteredEntry = self.circledEntry = None filteredEid = self.state.viewFilteredPanel.view.selectedEid if filteredEid is not None: self.filteredEntry = self.state.model.entry(filteredEid) circledEid = self.state.viewAllPanel.view.circledEid if circledEid is not None: self.circledEntry = self.state.model.entry(circledEid) self.filteredRadioButton = QRadioButton("under &Filtered") self.circledRadioButton = QRadioButton("under C&ircled") self.recentRadioButton = QRadioButton("under &Recent") self.tooltips.append( (self.recentRadioButton, """<p><b>under Recent</b></p> <p>Copy the current entry under a recently visited entry.</p>""")) self.filteredLabel = Widgets.Label.HtmlLabel() self.circledLabel = Widgets.Label.HtmlLabel() self.copyToTopRadioButton.setChecked(True) seen = {selectedEid} self.buttons = (self.copyToTopRadioButton, self.subentryRadioButton, self.filteredRadioButton, self.circledRadioButton, self.recentRadioButton) Forms.Util.setUpRadioButton( self, self.filteredEntry, self.filteredRadioButton, self.filteredLabel, self.buttons, seen, """<p><b>under Filtered</b></p> <p>Copy the current entry under the filtered entry “{}”.</p>""") Forms.Util.setUpRadioButton( self, self.circledEntry, self.circledRadioButton, self.circledLabel, self.buttons, seen, """<p><b>under Circled</b></p> <p>Copy the current entry under the circled entry “{}”.</p>""") self.recentComboBox = Forms.Util.createTermsComboBox( self.state, self.state.gotoEids, ignore=seen, maximum=MAX_RECENT) self.optionsGroup = QGroupBox() self.copyAllCheckBox = QCheckBox("Copy &All:") self.tooltips.append((self.copyAllCheckBox, """\ <p><b>Copy All</b></p> <p>If you check this checkbox, the other Copy checkboxes are checked in one go.</p>""")) self.copyXrefsCheckBox = QCheckBox("Cross-r&eferences") self.tooltips.append((self.copyXrefsCheckBox, """\ <p><b>Cross-references</b></p> <p>Copy cross-references from the original entry(ies) to the copied entry(ies).</p>""")) self.copyGroupsCheckBox = QCheckBox("&Groups") self.tooltips.append((self.copyGroupsCheckBox, """\ <p><b>Groups</b></p> <p>Copy groups from the original entry(ies) to the copied entry(ies).</p> <p>If you check the <b>Link Pages...</b> checkbox, this checkbox will be both checked and disabled, since linking is achieved by copying a linked group (creating one if necessary).</p>""")) self.copySubentriesCheckBox = QCheckBox("S&ubentries") self.tooltips.append((self.copySubentriesCheckBox, """\ <p><b>Subentries</b></p> <p>Copy the copied entry's subentries, subsubentries, and so on.</p>""")) self.linkPagesCheckBox = QCheckBox("&Link Pages between") self.linkLabel = Widgets.Label.HtmlLabel( "“{}” and its copy".format(termText)) self.tooltips.append((self.linkPagesCheckBox, """\ <p><b>Link Pages</b></p> <p>If the original entry belongs to a linked group, its copy is added to that linked group. If the original doesn't belong to a linked group, a new linked group is created with the name of the original's term, and both the original and its copy are added to this new linked group.</p> <p>If you check the this checkbox, the <b>Copy Groups</b> checkbox will be both checked and disabled, since linking is achieved by copying a linked group (creating one if necessary).</p>""")) self.withSeeCheckBox = QCheckBox("A&dd a") self.withSeeLabel1 = Widgets.Label.HtmlLabel( "<i>see</i> cross-reference from the copy to “{}”".format( termText)) self.withSeeLabel2 = Widgets.Label.HtmlLabel( "and <i>don't</i> copy the pages") self.withSeeLabel2.setIndent(self.fontMetrics().width("WW")) self.buttonBox = QDialogButtonBox() self.copyButton = QPushButton(QIcon(":/copy.svg"), "C&opy") self.tooltips.append((self.copyButton, """<p><b>Copy</b></p> <p>Copy the “{}” entry.</p>""".format(self.termLabel.text()))) self.buttonBox.addButton(self.copyButton, QDialogButtonBox.AcceptRole) self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Cancel") self.tooltips.append((self.closeButton, """<p><b>Cancel</b></p> <p>Close the dialog without making any changes to the index.</p>""")) self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole) self.helpButton = QPushButton(QIcon(":/help.svg"), "Help") self.tooltips.append( (self.helpButton, "Help on the Copy Entry dialog")) self.buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole) def layoutWidgets(self): layout = QVBoxLayout() entryLayout = QHBoxLayout() entryLayout.setSpacing(0) entryLayout.addWidget(self.entryLabel) entryLayout.addWidget(self.termLabel) entryLayout.addStretch() layout.addLayout(entryLayout) eidLayout = QVBoxLayout() eidLayout.addWidget(self.copyToTopRadioButton) eidLayout.addWidget(self.subentryRadioButton) eidLayout.addWidget(self.siblingRadioButton) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.filteredRadioButton) hbox.addWidget(self.filteredLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.circledRadioButton) hbox.addWidget(self.circledLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.recentRadioButton) hbox.addWidget(self.recentComboBox, 1) eidLayout.addLayout(hbox) eidLayout.addStretch() self.eidGroup.setLayout(eidLayout) layout.addWidget(self.eidGroup) vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(self.copyAllCheckBox) hbox.addWidget(self.copyXrefsCheckBox) hbox.addWidget(self.copyGroupsCheckBox) hbox.addWidget(self.copySubentriesCheckBox) hbox.addStretch() vbox.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.linkPagesCheckBox) hbox.addWidget(self.linkLabel) hbox.addStretch() vbox.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.withSeeCheckBox) hbox.addWidget(self.withSeeLabel1) hbox.addStretch() vbox.addLayout(hbox) vbox.addWidget(self.withSeeLabel2) self.optionsGroup.setLayout(vbox) layout.addWidget(self.optionsGroup) layout.addWidget(self.buttonBox) self.setLayout(layout) def createConnections(self): self.buttonBox.accepted.connect(self.copy) self.buttonBox.rejected.connect(self.reject) self.helpButton.clicked.connect(self.help) self.copyXrefsCheckBox.toggled.connect(self.updateUi) self.copyGroupsCheckBox.toggled.connect(self.updateUi) self.copySubentriesCheckBox.toggled.connect(self.updateUi) self.linkPagesCheckBox.toggled.connect(self.updateUi) self.withSeeCheckBox.toggled.connect(self.updateUi) self.copyAllCheckBox.toggled.connect(self.copyAll) self.recentRadioButton.toggled.connect(self.moveFocus) self.recentComboBox.currentIndexChanged[int].connect( self.recentChanged) def recentChanged(self): self.recentRadioButton.setChecked(True) self.updateUi() def moveFocus(self): if self.recentRadioButton.isChecked(): self.recentComboBox.setFocus() def updateUi(self): self.recentRadioButton.setEnabled(self.recentComboBox.count()) self.recentComboBox.setEnabled(self.recentComboBox.count()) enable = not self.withSeeCheckBox.isChecked() for widget in (self.copyAllCheckBox, self.copyXrefsCheckBox, self.copyGroupsCheckBox, self.copySubentriesCheckBox, self.linkPagesCheckBox): if not enable: widget.setChecked(False) widget.setEnabled(enable) self.linkLabel.setEnabled(enable) if enable: if self.linkPagesCheckBox.isChecked(): self.copyGroupsCheckBox.setChecked(True) self.copyGroupsCheckBox.setEnabled(False) else: self.copyGroupsCheckBox.setEnabled(True) self.copyAllCheckBox.setChecked( all(widget.isChecked() for widget in (self.copyXrefsCheckBox, self.copyGroupsCheckBox, self.copySubentriesCheckBox))) def copyAll(self, checked): if checked: for widget in (self.copyXrefsCheckBox, self.copyGroupsCheckBox, self.copySubentriesCheckBox): widget.setChecked(True) def help(self): self.state.help("xix_ref_dlg_copy.html") def copy(self): self.state.maybeSave() eid = self.selectedEntry.eid peid = None if self.copyToTopRadioButton.isChecked(): peid = ROOT description = "copy “{}” to be main entry" elif self.subentryRadioButton.isChecked(): peid = eid description = "copy “{}” to be subentry of itself" elif self.siblingRadioButton.isChecked(): peid = self.selectedEntry.peid description = "copy “{}” to be sibling of itself" elif self.filteredRadioButton.isChecked(): peid = self.filteredEntry.eid description = "copy “{}” under filtered" elif self.circledRadioButton.isChecked(): peid = self.circledEntry.eid description = "copy “{}” under circled" elif self.recentRadioButton.isChecked(): peid = self.recentComboBox.itemData( self.recentComboBox.currentIndex()) description = "copy “{}” under recently visited" if peid is not None: # Should always be True description = description.format( Lib.elidePatchHtml(self.selectedEntry.term, self.state)) self.state.model.copyEntry( Lib.CopyInfo(eid, peid, self.copyXrefsCheckBox.isChecked(), self.copyGroupsCheckBox.isChecked(), self.copySubentriesCheckBox.isChecked(), self.linkPagesCheckBox.isChecked(), self.withSeeCheckBox.isChecked(), description)) say(re.sub(r"^copy", "Copied", Lib.htmlToPlainText(description)), SAY_TIMEOUT) self.accept()
class ExportOrthoWin(QDialog ): #новый класс как приложение с интерфейсом и кодом def __init__(self, parent): #_____________Пременные уровня класса___________ self.OUT_dir = '' #выходная дирректория self.orthoBounds = [] # ВЫХОДНАЯ ПРОЕКЦИЯ по умолчанию #out_crs='PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' self.out_crs = PhotoScan.CoordinateSystem( 'PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' ) #out_crs=PhotoScan.CoordinateSystem('PROJCS["WGS 84 / UTM zone 38N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",45],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32638"]]') self.crsShapes = PhotoScan.CoordinateSystem( 'PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' ) self.DATA_OK = 0 #print ('orthoBounds=',len(self.orthoBounds)) #формат массива:0-имя ортофото, 1-Xmin, 2-Ymin, 3-sizeX, 4-sizeY, 5-ID полигона #__________________________________________________ QDialog.__init__(self, parent) self.setWindowTitle("Экспорт Орто по разграфке") #Заголвок окна self.resize(500, 250) #размер окна self.txt_comment = QLabel( " Модуль экспортирует ортофото и DEM из фотоскана по нарезке. \ Нарезка в текстовом файле: название листа, координаты нижнего левого угла, размеры. \n Проекция нарезки должна совпадать с проекцией выходного ортофотоплана.\ Листы делятся по нарезке, а внутри нарезки по блокам, размеры задаются. ФОРМАТ JPG \n При импорте SHP должно быть текстовое поле NAME \n \ Адрес сервера: " + ServerIP + " меняем в теле программы. Ваша версия фотоскана: " + PH_version + " \n") self.txt_comment.setWordWrap(True) self.now_prj = QLabel(str(self.out_crs)) self.select_prj = QPushButton("Выберете проекцию") #(" открыть ") self.select_prj.setFixedSize(170, 26) self.TXT_dif_pix = QLabel("<B>Размер пикселя: </B>") self.TXT_dif_pix.setFixedSize(170, 26) self.dif_pix = QLineEdit() self.dif_pix.setText('0.1') # Задает размер пикселя по умолчанию self.dif_pix.setFixedSize(100, 26) items_bloksize = ('5000', '8192', '10000', '15000', '20000', '25000', '29999', 'Full') # список с размерами тайлов #items_bloksize = {5000:5000, 8192:8192, 10000:10000, 15000:15000, 20000:20000, 25000:25000, 29999:29999} self.TXT_block_size = QLabel("<B>Размер блока: </B>", ) self.TXT_block_size.setFixedSize(170, 26) self.block_size = QComboBox() self.block_size.setFixedSize(100, 26) self.block_size.addItems(items_bloksize) self.block_size.setCurrentIndex( 1) #Устанавливает по умолчанию второе значение из списка - 8192 self.TXT_SHPname = QLabel("Файл разграфки SHP (NAME,poligons)") self.SHPname = QPushButton( "Выберете файл разграфки SHP") #(" открыть ") self.SHPname.setFixedSize(170, 26) self.TXT_filename = QLabel( "Файл разграфки TXT(имя; X0; Y0; sizeX; SizeY)") self.filename = QPushButton("Выберете Файл разграфки") #(" открыть ") self.filename.setFixedSize(170, 26) self.TXT_CheckOrthoDem = QLabel("Вид выходной продукции") self.TXT_CheckOrthoDem.setFixedSize(170, 26) self.CheckOrtho_Radio = QRadioButton("Ортофото") self.CheckOrtho_Radio.setChecked(True) self.CheckDem_Radio = QRadioButton("ДЕМ") self.TXT_OUTFOLDER = QLabel("Выходная дирректория") self.OUTFOLDER = QPushButton("Выберете дирректорию") #(" открыть ") self.OUTFOLDER.setFixedSize(170, 26) items_format = ( 'JPG', 'TIF' ) # список форматов, ПРИ выборе ДЕМ будет выбран второй формат - внимательно при изменении списка!!! self.file_format = QComboBox() self.file_format.setFixedSize(50, 26) self.file_format.addItems(items_format) self.file_format.setCurrentIndex( 0) #Устанавливает по умолчанию первое значение self.TXT_checkExportOrtho = QLabel("Построить ортофото:") # Ортофото self.TXT_checkExportOrtho.setFixedSize(170, 26) self.checkExportOrtho = QCheckBox() self.checkExportOrtho.setChecked(False) self.GoGo = QPushButton("Экспорт локально") #(" Экспорт локально ") self.GoGo.setFixedSize(170, 26) self.GoGo.setDisabled(True) self.GoGoNet = QPushButton("Экспорт по сети") #(" Экспорт по сети ") self.GoGoNet.setFixedSize(170, 26) self.GoGoNet.setDisabled(True) hbox0 = QHBoxLayout() hbox0.addWidget(self.txt_comment, alignment=0) hbox1 = QHBoxLayout() hbox1.addWidget(self.select_prj, alignment=0) hbox1.addWidget(self.now_prj, alignment=0) hbox2 = QHBoxLayout() hbox2.addWidget(self.TXT_block_size, alignment=1) hbox2.addWidget(self.block_size, alignment=1) hbox3 = QHBoxLayout() hbox3.addWidget(self.TXT_dif_pix, alignment=1) hbox3.addWidget(self.dif_pix, alignment=1) hbox4 = QHBoxLayout() #hbox4.addStretch(1) hbox4.addWidget(self.SHPname, alignment=0) hbox4.addWidget(self.TXT_SHPname, alignment=0) hbox5 = QHBoxLayout() #hbox5.addStretch(1) hbox5.addWidget(self.filename, alignment=0) hbox5.addWidget(self.TXT_filename, alignment=0) hbox51 = QHBoxLayout() hbox51.addWidget(self.TXT_CheckOrthoDem, alignment=0) hbox51.addWidget(self.CheckOrtho_Radio, alignment=0) hbox51.addWidget(self.CheckDem_Radio, alignment=0) hbox6 = QHBoxLayout() #hbox5.addStretch(1) hbox6.addWidget(self.OUTFOLDER, alignment=0) hbox6.addWidget(self.TXT_OUTFOLDER, alignment=0) hbox6.addWidget(self.file_format, alignment=0) hbox7 = QHBoxLayout() #build ortho hbox7.addWidget(self.TXT_checkExportOrtho, alignment=0) hbox7.addWidget(self.checkExportOrtho, alignment=0) hbox8 = QHBoxLayout() hbox8.addWidget(self.GoGo, stretch=0, alignment=0) hbox8.addWidget(self.GoGoNet, stretch=0, alignment=0) vbox = QVBoxLayout() #Определяем вбокс и забиваем его Нбоксами #vbox.addStretch(1) vbox.addLayout(hbox0) vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.addLayout(hbox3) vbox.addLayout(hbox4) vbox.addLayout(hbox5) vbox.addLayout(hbox51) #выбор, что строить орто или дем vbox.addLayout(hbox6) #Функция построения ортофото спрятана, поскольку работает не стабильно и построение ортофото для каждого листа в сумме занимает очень много времени, #гораздо больше, чем один раз построить ортофото для всех #vbox.addLayout(hbox7) #build ortho vbox.addLayout(hbox8) self.setLayout(vbox) self.select_prj.clicked.connect(self.set_projection) self.SHPname.clicked.connect(self.input_razgr_SHPname) self.filename.clicked.connect(self.input_razgr_name) self.OUTFOLDER.clicked.connect(self.input_out_dir) self.GoGo.clicked.connect(self.ortho_local) self.GoGoNet.clicked.connect(self.ortho_net) #Организация блокировки интерфейса для радио кнопок self.CheckOrtho_Radio.clicked.connect(self.CheckOrtho_Radio_DO) self.CheckDem_Radio.clicked.connect(self.CheckDem_Radio_DO) #____________ self.checkExportOrtho.clicked.connect( self.PrintChkStat) #Функция для проверки работы чека #self.WindowContextHelpButtonHint.clicked.connect(self.prog_hint) #self.WindowTitleHint.clicked.connect(self.prog_hint) self.exec() #____________________________________________________________________________ def PrintChkStat( self ): #Эта функция работает в принте с подстановкой и получение значения чека if self.checkExportOrtho.isChecked() == True: stat = 'ДА' else: stat = 'НЕТ' print('Строить орто %s здесь' % stat) def CheckOrtho_Radio_DO( self): #Если выбран Ортоф - формат Джипег и свободен!!! print("Орто") self.file_format.setCurrentIndex(0) self.file_format.setDisabled(False) def CheckDem_Radio_DO( self): #Если выбран ДЕМ - формат тифф и блокируется!!! print("DEM") self.file_format.setCurrentIndex(1) self.file_format.setDisabled(True) def ortho_local(self): self.export_ortho('local') def ortho_net(self): self.export_ortho('net') def prog_hint(self): print("OK") def unlock_export(self, sel): #Переменная нужна для разблокирования кнопки Экспорт. Два критических параметра:Файл разграфки и выходная дирректория, каждый добавляет по еденице. #Sel=5 блокирует кнопки при запуске сетевой обработки ''' DATA_OK логика работы: Для экспорта нужно задать выходную директорию и файл разграфки, текстовый или векторный при запуске сетевой обработки кнопки опять блокируются DATA_OK меняет только эта процедура!!! 0-ничего не задано экспорт заблокирован 1-выбран файл разграфки проверяем выбран ли путь, да, разблокируем 3 2-выбран путь проверяем выбран ли файл разграфки, да, разблокируем 3 ''' if sel == 5 and self.DATA_OK == 1: self.DATA_OK = 0 self.GoGo.setDisabled(True) self.GoGoNet.setDisabled(True) if sel == 5 and self.DATA_OK == 2: self.DATA_OK = 2 self.GoGo.setDisabled(True) self.GoGoNet.setDisabled(True) if sel == 5 and self.DATA_OK == 3: self.DATA_OK = 2 self.GoGo.setDisabled(True) self.GoGoNet.setDisabled(True) if self.DATA_OK == 1 and sel == 2: self.DATA_OK = 3 if self.DATA_OK == 2 and sel == 1: self.DATA_OK = 3 if self.DATA_OK == 0 and sel != 5: self.DATA_OK = sel if self.DATA_OK == 3 and sel != 5: self.GoGo.setDisabled(False) self.GoGoNet.setDisabled(False) print('unlock') print(sel, self.DATA_OK) def OrthoBoundCalc(self, Xn, Yn, XS, YS): # изменить под сетевую обработку с тайлами DifPix = float(self.dif_pix.text()) ''' Округление начала Если надо Xnround=floor(Xn/DifPix)*DifPix # Ynround=floor(Yn/DifPix)*DifPix ''' ''' if self.block_size.currentText()=='Full' or CommandStack==5 : #Экспорт целикового фрагмента print('границы целиковые') Xnround=Xn Ynround=Yn-DifPix XSround=ceil(XS/DifPix+1)*DifPix #Границы округляем в большую сторону и расширяем на пиксель YSround=ceil(YS/DifPix+1)*DifPix XSround=Xnround+XSround YSround=Ynround+YSround elif CommandStack==1 and self.block_size.currentText()!='Full': # Экспорт по тайлам print("Границы со сдвигом") BlockSize=float(self.block_size.currentText()) Xnround=Xn Ynround=Yn #-DifPix XSround=ceil(XS/DifPix+1)*DifPix #Границы округляем в большую сторону и расширяем на пиксель YSround=ceil(YS/DifPix+1)*DifPix YBlockSize=BlockSize*DifPix TileShift=YBlockSize-YSround Ynround=Ynround+TileShift XSround=Xnround+XSround YSround=Ynround+YSround+TileShift else: Print("Bound version error, OrthoBoundCalc") pass ''' Xnround = Xn Ynround = Yn - DifPix XSround = ceil( XS / DifPix + 1 ) * DifPix #Границы округляем в большую сторону и расширяем на пиксель YSround = ceil(YS / DifPix + 1) * DifPix XSround = Xnround + XSround YSround = Ynround + YSround point = [ ] #"Эта конструкция нужна для поиска максимальных координат квадрата при переходе из системы в систему print("точки") point.append(PhotoScan.Vector((Xnround, Ynround))) point.append(PhotoScan.Vector((Xnround, YSround))) point.append(PhotoScan.Vector((XSround, YSround))) point.append(PhotoScan.Vector((XSround, Ynround))) print("точки2") point_trans = [] point_trans.append( PhotoScan.CoordinateSystem.transform(point[0], self.crsShapes, self.out_crs)) point_trans.append( PhotoScan.CoordinateSystem.transform(point[1], self.crsShapes, self.out_crs)) point_trans.append( PhotoScan.CoordinateSystem.transform(point[2], self.crsShapes, self.out_crs)) point_trans.append( PhotoScan.CoordinateSystem.transform(point[3], self.crsShapes, self.out_crs)) x = [] y = [] for i in range(4): print(i) x.append(point_trans[i][0]) y.append(point_trans[i][1]) xMin = min(x) yMin = min(y) xMax = max(x) yMax = max(y) #OrthoBound=(Xnround,Ynround,XSround,YSround) OrthoBound = (Xnround, Ynround, XSround, YSround) print(OrthoBound) OrthoBound = (xMin, yMin, xMax, yMax) print(OrthoBound) return OrthoBound def input_razgr_SHPname(self): #global listShapes SHPname = '' #Векторный файл разграфки DataDir = os.path.dirname( __file__) # Дирректория по умолчанию - дирректория скрипта!! shpfilename = QFileDialog.getOpenFileName( self, 'выберете векторный файл разграфки', DataDir, filter='*.shp') #Координаты в выходной проекции #проверка на пустоту if not shpfilename[0] == '': SHP_name = shpfilename[0] else: return sname = os.path.basename(SHP_name) file_sname = os.path.splitext(sname)[0] print('Путь до шейпа: ', SHP_name) print('Имя шейпа: ', file_sname) chunk.importShapes(SHP_name, True) # Импорт шейпфайла с заменой shapes = chunk.shapes #Сделать проверку на ИМЯ ПОЛИГОНА #shapes=PhotoScan.app.document.chunk.shapes listShapes = shapes.items() #Массив (список) шейпов в проекте self.crsShapes = shapes.crs #Проекция шейпа print(self.crsShapes) PhotoScan.app.messageBox('Импортированы объекты: ' + str(shapes) + '\n Старые объекты удалены') #Получили список векторных объектов, загруженных в проект, теперь проходим по каждому объекту и определяем его минимум и максимум по коориднатам if len(listShapes) != 0: poligon_ID = 0 self.orthoBounds = [] for shape in listShapes: # ЗДЕСЬ определяются координаты минимум и максимум в текущей проекции в другой все по другому - Могут быть дыры # в OrthoBoundCalc стоит заглушка - имщет максимальные коориднаты углов прямоугольника после перепроецирования - можно но не совсем корректно x = [] y = [] vertices = shape.vertices for vertex in vertices: x.append(vertex[0]) y.append(vertex[1]) # Если есть NAME - это будет имя, если нет - имя шейпа и номер фичи if str(shape.label) == '': poligonName = str(file_sname) + '_' + str(poligon_ID) else: poligonName = str(shape.label) xMin = min(x) yMin = min(y) xSize = max(x) - min(x) ySize = max(y) - min(y) element = [poligonName, xMin, yMin, xSize, ySize, poligon_ID] self.orthoBounds.append( element) #ЭТО МАССИВ с ГРАНИЦАМИ ОРТОФОТО #формат массива:0-имя ортофото, 1-Xmin, 2-Ymin, 3-sizeX, 4-sizeY poligon_ID += 1 #Увеличение на единицу print(len(self.orthoBounds), poligon_ID) if len(self.orthoBounds) != 0: self.unlock_export(1) self.TXT_SHPname.setText(str(sname)) self.TXT_filename.setText( "Файл разграфки TXT(имя; X0; Y0; sizeX; SizeY)") else: PhotoScan.app.messageBox('Пустой SHP файл') self.unlock_export(5) print('orthoBounds=', len(self.orthoBounds)) # Шейп засосали, минимум максимум нашли, с обрезкой дальше разберемся #_____________________________________________________________________________ def input_razgr_name(self): TXT_name = '' #имя файла с разграфкой # КООРДИАНТЫ ДОЛЖНЫ БЫТЬ В ВЫХОДНОЙ ПРОЕКЦИИ!!!!! DataDir = os.path.dirname( __file__) # Дирректория по умолчанию - дирректория скрипта!! textfilename = QFileDialog.getOpenFileName( self, 'выберете файл разграфки', DataDir, filter='*.txt') #Координаты в выходной проекции #проверка текстфайлнайм на пустоту if not textfilename[0] == '': with open(textfilename[0]) as f: for line in f: znach = line.split(";") try: if not (isinstance(znach[0], str)): PhotoScan.app.messageBox('Неверный форматS') self.unlock_export(5) return if not (isinstance(float(znach[1]), (float, int))): PhotoScan.app.messageBox('Неверный формат1i') self.unlock_export(5) return if not (isinstance(float(znach[2]), (float, int))): PhotoScan.app.messageBox('Неверный формат2i') self.unlock_export(5) return if not (isinstance(float(znach[3]), (float, int))): PhotoScan.app.messageBox('Неверный формат3i') self.unlock_export(5) return if not (isinstance(float(znach[4]), (float, int))): PhotoScan.app.messageBox('Неверный формат4i') self.unlock_export(5) return except: PhotoScan.app.messageBox('Неверный формат_;') self.unlock_export(5) return else: return if not (textfilename[0] == ''): #Если все нормально заполняем orthoBounds TXT_name = textfilename self.orthoBounds = [] with open(TXT_name[0]) as f: count = 0 for line in f: znach = line.split(";") element = [ znach[0], znach[1], znach[2], znach[3], znach[4], count ] self.orthoBounds.append( element) #ЭТО МАССИВ с ГРАНИЦАМИ ОРТОФОТО count += 1 print('orthoBounds=', len(self.orthoBounds)) self.unlock_export( 1) #разблокирует экспорт, если заданы разграфка и дирректория self.TXT_filename.setText(str(TXT_name[0])) self.TXT_SHPname.setText("Файл разграфки SHP (NAME,poligons)") def set_projection(self): self.out_crs = PhotoScan.app.getCoordinateSystem( 'Система координат', self.out_crs) #Специальная форма для задания системы координат self.now_prj.setText(str(self.out_crs)) def input_out_dir(self): DataDir = os.path.dirname(__file__) outputdir = QFileDialog.getExistingDirectory(self, 'выберете дирректорию', DataDir) if not outputdir == '': self.OUT_dir = outputdir self.TXT_OUTFOLDER.setText(str(self.OUT_dir)) self.unlock_export( 2) #разблокирует экспорт, если заданы разграфка и дирректория else: return print('orthoBounds=', len(self.orthoBounds)) def export_ortho( self, proc_type ): # универсальная процедура экспорта для локлаьной и для сетевой обработки #global chunk ''' ЭТО ПРОВЕРКА ДЛЯ ПОСТРОЕНИЯ ОРТО ПЕРЕД РАБОТОЙ В ТЕКУЩЕЙ ВЕРСИИ ФУНКЦИЯ ОТКЛЮЧЕНА!! if self.checkExportOrtho.isChecked()==True: statOrthoBuild=True else: statOrthoBuild=False # 000000 Проверка на наличие ортофото или дем перед работой if (doc.chunk.orthomosaic==None and statOrthoBuild==False): PhotoScan.app.messageBox('Нет орто!!') return elif (doc.chunk.elevation==None and statOrthoBuild==True): PhotoScan.app.messageBox('Нет ДЕМ!!') return ''' #Определение вида экспорта - орто или дем if self.CheckOrtho_Radio.isChecked() == True: ExportType = 'ORTHO' elif self.CheckDem_Radio.isChecked() == True: ExportType = 'DEM' else: AssertionError("Какой процесс экспорта?") #ПРОВЕРКИ НАЛИЧИЯ ДЕМ И ОРТО if (doc.chunk.orthomosaic == None and ExportType == 'ORTHO'): PhotoScan.app.messageBox('Нет орто!!') return elif (doc.chunk.elevation == None and ExportType == 'DEM'): PhotoScan.app.messageBox('Нет ДЕМ!!') return file_format = self.file_format.currentText() print('orthoBounds=', len(self.orthoBounds)) task = [] #Это СПИСОК тасков DifPix = float(self.dif_pix.text()) if self.block_size.currentText() == 'Full': BlockSize = 0 else: BlockSize = int(self.block_size.currentText()) # Цикл для запуска ортофото локально или для забивания стека на сеть из массива try: for cu_string in self.orthoBounds: OName = cu_string[0] XMLeft = float(cu_string[1]) YMDown = float(cu_string[2]) sizeXM = float(cu_string[3]) sizeYM = float(cu_string[4]) shapeNumber = int(cu_string[5]) cu_Region = self.OrthoBoundCalc( XMLeft, YMDown, sizeXM, sizeYM ) #Функция вычисления границ # изменить под сетевую обработку с тайлами if file_format == 'JPG' and ExportType == 'ORTHO': fileoutname = self.OUT_dir + "\\ortho_" + OName + ".jpg" elif file_format == 'TIF' and ExportType == 'ORTHO': fileoutname = self.OUT_dir + "\\ortho_" + OName + ".tif" elif file_format == 'TIF' and ExportType == 'DEM': fileoutname = self.OUT_dir + "\\dem_" + OName + ".tif" else: print("Формат файла?") if proc_type == 'local': #КОММАНДЫ для локальной обработки print('Обработка локально') ''' ПОСТРОЕНИЕ ОРТОФОТО В ЭТОЙ ВЕРСИИ ОТКЛЮЧЕНО if statOrthoBuild==True: #chunk.buildOrthomosaic(surface=PhotoScan.ElevationData, blending=PhotoScan.MosaicBlending, color_correction=False, projection=self.out_crs, region=cu_Region,dx=DifPix, dy=DifPix) chunk.buildOrthomosaic(surface=PhotoScan.ElevationData, blending=PhotoScan.MosaicBlending, projection=self.out_crs, region=cu_Region,dx=DifPix, dy=DifPix) ''' if CommandStack == 1 and ExportType == 'ORTHO': if file_format == 'JPG': chunk.exportOrthomosaic(fileoutname, format="jpg", projection=self.out_crs, region=cu_Region, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True) elif file_format == 'TIF': chunk.exportOrthomosaic(fileoutname, format="tif", projection=self.out_crs, region=cu_Region, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression="jpeg", tiff_big=False) #сжатие LZW #elif file_format=='TIF': chunk.exportOrthomosaic(fileoutname, format="tif", region=cu_Region, projection=self.out_crs,dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression="lzw", tiff_big=False) else: print("Формат файла?") elif CommandStack == 5 and ExportType == 'ORTHO': if file_format == 'JPG': chunk.exportOrthomosaic( fileoutname, PhotoScan.RasterFormatTiles, PhotoScan.ImageFormatJPEG, region=cu_Region, projection=self.out_crs, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True) elif file_format == 'TIF': chunk.exportOrthomosaic( fileoutname, PhotoScan.RasterFormatTiles, PhotoScan.ImageFormatTIFF, region=cu_Region, projection=self.out_crs, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression=PhotoScan.TiffCompressionJPEG, tiff_big=False) #сжатие LZW #elif file_format=='TIF': chunk.exportOrthomosaic(fileoutname, PhotoScan.RasterFormatTiles,PhotoScan.ImageFormatTIFF, region=cu_Region, projection=self.out_crs,dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression=PhotoScan.TiffCompressionLZW, tiff_big=False) else: print("Формат файла?") elif CommandStack == 1 and ExportType == 'DEM': print("Экспорт ДЕМ локально") if file_format == 'TIF': chunk.exportDem(fileoutname, format="tif", projection=self.out_crs, region=cu_Region, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_big=False) elif CommandStack == 5 and ExportType == 'DEM': print("Экспорт ДЕМ локально") if file_format == 'TIF': chunk.exportDem(fileoutname, PhotoScan.RasterFormatTiles, PhotoScan.ImageFormatTIFF, region=cu_Region, projection=self.out_crs, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_big=False) elif proc_type == 'net': print('Обработка по сети') ''' ПОСТРОЕНИЕ ОРТОФОТО В ЭТОЙ ВЕРСИИ ОТКЛЮЧЕНО #Построить ортофото if statOrthoBuild==True: workBuild = PhotoScan.NetworkTask() # СОздаем ворк и забиваем его параметрами #Версионность if CommandStack==1: workBuild.params['ortho_surface'] = 0 workBuild.params['resolution_x'] = DifPix workBuild.params['resolution_y'] = DifPix elif CommandStack==5: workBuild.params['ortho_surface'] = 4 workBuild.params['resolution'] = DifPix else: return workBuild.name = "BuildOrthomosaic" workBuild.frames.append((chunk.key,0)) workBuild.params['network_distribute'] = True task.append(workBuild) #Добавляем задачу построения в таск ''' #Экспортировать ортофото workExport = PhotoScan.NetworkTask( ) # СОздаем ворк и забиваем его параметрами #ВЕРСИОННОСТЬ if CommandStack == 1 and ExportType == 'ORTHO': workExport.name = "ExportOrthomosaic" workExport.params['resolution_x'] = DifPix workExport.params['resolution_y'] = DifPix if file_format == 'JPG': workExport.params['raster_format'] = 2 elif file_format == 'TIF': workExport.params['raster_format'] = 1 else: print("Формат файла?") elif CommandStack == 5 and ExportType == 'ORTHO': workExport.name = "ExportRaster" workExport.params['resolution'] = DifPix if file_format == 'JPG': workExport.params['image_format'] = 1 elif file_format == 'TIF': workExport.params[ 'image_format'] = 2 #Значение на шару!!! ПРОВЕРИТЬ else: print("Формат файла?") elif CommandStack == 1 and ExportType == 'DEM': print("Экспорт ДЕМ по сети") workExport.name = "ExportDem" workExport.params['resolution_x'] = DifPix workExport.params['resolution_y'] = DifPix elif CommandStack == 5 and ExportType == 'DEM': #НЕ ОТЛАЖЕНО ПАРАМЕТРЫ НА ШАРУ print("Экспорт ДЕМ по сети") workExport.name = "ExportOrthomosaic" workExport.params['resolution'] = DifPix pass else: return workExport.frames.append((chunk.key, 0)) workExport.params['write_world'] = 1 if self.block_size.currentText( ) == 'Full': # Условие на запись тайлов workExport.params['write_tiles'] = 0 else: workExport.params['write_tiles'] = 1 workExport.params['tile_width'] = BlockSize workExport.params['tile_height'] = BlockSize workExport.params[ 'path'] = fileoutname #выходная дирректория с именем файла workExport.params['region'] = cu_Region # ВНИМАНИЕ! По сети нельзя экспортировать в пользовательской проекции ИЛИ проекция должна быть НА ВСЕХ НОДАХ workExport.params[ 'projection'] = self.out_crs.authority #Из объекта проекция берется только ее номер EPSG::32637 #ВНИМАНИЕ ЭКСПОРТ ОТКЛЮЧЕН!!!! task.append(workExport) #Добавляем задачу в таск else: print('Пока не задано') PhotoScan.app.messageBox('Обработка закончена') except Exception as e: print(e) PhotoScan.app.messageBox('Что-то пошло не так ((') return #break #Запуск сетевого стека, таска в обработку if proc_type == 'net': print(ProjectLocalPath_auto) print(ProjectPath) client.connect(ServerIP) batch_id = client.createBatch(ProjectPath, task) if batch_id == None: #Проверка наличия проекта в сети PhotoScan.app.messageBox( '<B>Этот проект уже запущен в обработку!!!<B>') self.unlock_export(5) else: print('Проект работает под номером ', batch_id) client.resumeBatch(batch_id) self.unlock_export(5) PhotoScan.app.messageBox( 'Проект поставлен в очередь сетевой обработки') client.disconnect() pass
class RateView(QGroupBox): '''The box containing the rate value''' def __init__(self, title = 'Rate', parent = None): '''Initialize''' super(RateView, self).__init__(parent) self.setTitle(title) self._createWidgets() def _createWidgets(self): '''Create the widgets contained in this box''' # Rate or lifetime chooser self.rate = QRadioButton('Rate', self) self.rate.setToolTip(ttt('Choose this to express exchange as rate')) self.lifetime = QRadioButton('Lifetime', self) self.lifetime.setToolTip(ttt('Choose this to express exchange as ' 'lifetime')) # Box containing value self.rate_value = QLineEdit(self) validate = QDoubleValidator(self.rate_value) validate.setDecimals(3) validate.setBottom(0.0) self.rate_value.setValidator(validate) self.rate_value.setToolTip(ttt('The rate or lifetime value')) # Unit self.unit = QComboBox(self) self.unit.setToolTip(ttt('Selects the input unit for the rate ' 'or lifetime')) def initUI(self): '''Lays out the widgets''' radios = QVBoxLayout() radios.addWidget(self.rate) radios.addWidget(self.lifetime) rate = QGridLayout() rate.addWidget(QLabel("Unit: "), 1, 1) rate.addWidget(self.unit, 1, 2) rate.addWidget(QLabel("Value: "), 2, 1) rate.addWidget(self.rate_value, 2, 2) total = QHBoxLayout() total.addLayout(radios) total.addStretch() total.addLayout(rate) self.setLayout(total) def makeConnections(self): '''Connect the widgets together''' # When one radio button is checked, change the combo box model # and un-check the other radio button self.rate.clicked.connect(self.setRateModel) self.lifetime.clicked.connect(self.setLifetimeModel) # If the text changes, emit that rate self.rate_value.editingFinished.connect(self.emitRate) # If the underlying model changes, adjust the text self.model.rateChanged.connect(self.updateRate) # If the unit changes, update rate self.unit.currentIndexChanged.connect(self.updateUnit) def setModel(self, model): '''Attaches models to the views''' self.model = model def setRate(self, rate): '''Set the rate manually''' self.rate_value.setText(str(rate)) self.rate_value.editingFinished.emit() def setUnit(self, unit): '''Set the unit manually''' if unit == 's': self.lifetime.click() self.unit.setCurrentIndex(0) elif unit == 'ns': self.lifetime.click() self.unit.setCurrentIndex(1) elif unit == 'ps': self.lifetime.click() self.unit.setCurrentIndex(2) elif unit == 'fs': self.lifetime.click() self.unit.setCurrentIndex(3) elif unit in ('Hz', 'hz'): self.rate.click() self.unit.setCurrentIndex(0) elif unit in ('GHz', 'ghz'): self.rate.click() self.unit.setCurrentIndex(1) elif unit in ('THz', 'thz'): self.rate.click() self.unit.setCurrentIndex(2) elif unit in ('PHz', 'phz'): self.rate.click() self.unit.setCurrentIndex(3) else: error.showMessage('Invalid unit: {0}'.format(unit)) ####### # SLOTS ####### def updateRate(self): '''Updates the rate of the text box''' # Do nothing if rate is not yet defined try: rate = self.model.rate except AttributeError: return if 0.1 > rate or rate > 100: self.rate_value.setText('{0:.3E}'.format(rate)) else: self.rate_value.setText('{0:.3F}'.format(rate)) def emitRate(self): '''Converts the text to a float and emits''' # Do nothing if there is no number try: self.model.setRate(float(self.rate_value.text())) except ValueError: pass def updateUnit(self): '''Update for a change of unit''' # If there is no unit yet, just set it try: unit = self.model.unit except AttributeError: self.model.setConverter(str(self.unit.currentText())) try: self.model.setRate(float(self.rate_value.text())) except ValueError: pass return # Convert unit appropriately if self.rate.isChecked(): if unit == 'Hz': conv = { 'GHz' : 1E-9, 'THz' : 1E-12, 'PHz' : 1E-15 } elif unit == 'GHz': conv = { 'Hz' : 1E9, 'THz' : 1E-3, 'PHz' : 1E-6 } elif unit == 'THz': conv = { 'Hz' : 1E12, 'GHz' : 1E3, 'PHz' : 1E-3 } elif unit == 'PHz': conv = { 'Hz' : 1E15, 'GHz' : 1E6, 'THz' : 1E3 } else: conv = { '' : 1, 'Hz' : 1, 'GHz' : 1, 'THz' : 1, 'PHz' : 1, } else: if unit == 's': conv = { 'ns' : 1E9, 'ps' : 1E12, 'fs' : 1E15 } elif unit == 'ns': conv = { 's' : 1E-9, 'ps' : 1E3, 'fs' : 1E6 } elif unit == 'ps': conv = { 's' : 1E-12, 'ns' : 1E-3, 'fs' : 1E3 } elif unit == 'fs': conv = { 's' : 1E-15, 'ns' : 1E-6, 'ps' : 1E-3 } else: conv = { '' : 1, 's' : 1, 'ns' : 1, 'ps' : 1, 'fs' : 1, } try: # Set the new converter, then change the rate self.model.setConverter(str(self.unit.currentText())) try: self.model.setRate(float(self.rate_value.text()) * conv[str(self.unit.currentText())]) except ValueError: pass except KeyError: pass # Save the new unit self.model.unit = str(self.unit.currentText()) def setRateModel(self): '''Change the model to use the rate''' if self.model.method == 'rate': return self.model.method = 'rate' indx = self.unit.currentIndex() self.unit.setModel(self.model.runits) self.model.unit = str(self.unit.itemText(indx)) self.unit.setCurrentIndex(indx) self.model.setConverter(self.model.unit) try: self.model.setRate(1 / float(self.rate_value.text())) except (ZeroDivisionError, ValueError): pass def setLifetimeModel(self): '''Change the model to use the lifetime''' if self.model.method == 'lifetime': return self.model.method = 'lifetime' indx = self.unit.currentIndex() self.unit.setModel(self.model.lunits) self.model.unit = str(self.unit.itemText(indx)) self.unit.setCurrentIndex(indx) self.model.setConverter(self.model.unit) try: self.model.setRate(1 / float(self.rate_value.text())) except (ZeroDivisionError, ValueError): pass
class OptionsContainer(QWidget): def __init__(self,main_window): QWidget.__init__(self) self.main_window = main_window self.layout = QGridLayout() self.setLayout(self.layout) self.lr = numpy.zeros(2) self.fps = QSpinBox() self.fps.setValue(25) self.fps.setMinimum(1) self.fps.setMaximum(1000) self.layout.addWidget(QLabel("FPS:"),10,10) self.layout.addWidget(self.fps,10,11) self.capture_area_group = QButtonGroup() self.capture_area_fs = QRadioButton("Full Screen") self.connect(self.capture_area_fs, SIGNAL("clicked()"),self.capture_area_change) self.capture_area_fs.setChecked(True) self.capture_area_sa = QRadioButton("Selected Area") self.connect(self.capture_area_sa, SIGNAL("clicked()"),self.capture_area_change) self.capture_area_group.addButton(self.capture_area_fs) self.capture_area_group.addButton(self.capture_area_sa) self.capture_area_group.setExclusive(True) self.layout.addWidget(self.capture_area_fs,12,10) self.layout.addWidget(self.capture_area_sa,12,11) self.sa_group = QGroupBox() self.sa_grid = QGridLayout() self.sa_group.setLayout(self.sa_grid) self.sa_ul_bt = QPushButton("Select Upper Left") self.connect(self.sa_ul_bt, SIGNAL("clicked()"), self.select_ul) self.sa_lr_bt = QPushButton("Select Lower Right") self.connect(self.sa_lr_bt, SIGNAL("clicked()"), self.select_lr) self.sa_x = QSpinBox() self.sa_y = QSpinBox() self.sa_w = QSpinBox() self.sa_h = QSpinBox() for sb in [self.sa_h,self.sa_w,self.sa_x,self.sa_y]: sb.setMaximum(999999) sb.setMinimum(0) self.sa_grid.addWidget(self.sa_ul_bt,14,10,1,1) self.sa_grid.addWidget(self.sa_lr_bt,15,10,1,1) self.sa_grid.addWidget(QLabel("x"),14,11,1,1) self.sa_grid.addWidget(self.sa_x,14,12,1,1) self.sa_grid.addWidget(QLabel("y"),15,11,1,1) self.sa_grid.addWidget(self.sa_y,15,12,1,1) self.sa_grid.addWidget(QLabel("w"),16,11,1,1) self.sa_grid.addWidget(self.sa_w,16,12,1,1) self.sa_grid.addWidget(QLabel("h"),17,11,1,1) self.sa_grid.addWidget(self.sa_h,17,12,1,1) self.sa_show_bt = QPushButton("Show Area") self.sa_show_bt.setCheckable(True) self.connect(self.sa_show_bt, SIGNAL("clicked()"), self.show_selected_area) self.sa_grid.addWidget(self.sa_show_bt,18,10,1,10) self.sa_group.hide() self.layout.addWidget(self.sa_group,14,10,1,10) self.capture_delay = QSpinBox() self.capture_delay.setMinimum(0) self.capture_delay.setMaximum(10000) self.layout.addWidget(QLabel("Capture Delay"),18,10,1,1) self.layout.addWidget(self.capture_delay,18,11,1,1) self.capture_bt = QPushButton("Capture") self.stop_capture_bt = QPushButton("Stop") self.stop_capture_bt.hide() self.layout.addWidget(self.capture_bt,20,10,1,10) self.layout.addWidget(self.stop_capture_bt,30,10,1,10) self.ffmpeg_flags = QLineEdit() self.ffmpeg_flags.setText("-qscale 0 -vcodec mpeg4") self.layout.addWidget(QLabel("FFMPEG Flags:"),40,10) self.layout.addWidget(self.ffmpeg_flags,50,10,1,10) self.encode_bt = QPushButton("Encode Video") self.layout.addWidget(self.encode_bt,60,10,1,10) self.open_dir_bt = QPushButton("Open Directory") self.layout.addWidget(self.open_dir_bt,80,10,1,10) self.connect(self.open_dir_bt, SIGNAL("clicked()"),self.open_cwd) self.selected_area = SelectedArea() def show_selected_area(self): x = self.sa_x.value() y = self.sa_y.value() w = self.sa_w.value() h = self.sa_h.value() self.selected_area.setGeometry(x,y,w,h) self.selected_area.activateWindow() self.selected_area.raise_() if(self.sa_show_bt.isChecked()): self.selected_area.show() else:self.selected_area.hide() def select_ul(self): print "select_ul" self.clicked = False self.tw = TransWindow() self.tw.mouse_press = False self.tw.show() self.connect(self.tw, SIGNAL("mouse_press()"),self.set_ul) def select_lr(self): print "select_lr" self.clicked = False self.tw = TransWindow() self.tw.mouse_press = False self.tw.show() self.connect(self.tw, SIGNAL("mouse_press()"),self.set_lr) def set_ul(self): self.sa_x.setValue( self.tw.pos[0]) self.sa_y.setValue( self.tw.pos[1]) self.sa_w.setValue( self.lr[0] - self.sa_x.value()) self.sa_h.setValue( self.lr[1] - self.sa_y.value()) self.show_selected_area() def set_lr(self): self.lr = numpy.array([self.tw.pos[0],self.tw.pos[1]]) self.sa_w.setValue( self.tw.pos[0] - self.sa_x.value()) self.sa_h.setValue( self.tw.pos[1] - self.sa_y.value()) self.show_selected_area() def capture_area_change(self): print "capture_area_change" if(self.capture_area_fs.isChecked()): self.sa_group.hide() else: self.sa_group.show() self.adjustSize() self.main_window.adjustSize() def open_cwd(self): #will need to detect os and change accordingly os.system("open {}".format(os.getcwd()))
class ProfileFormWidget(QWidget): ''' classdocs ''' def __init__(self): ''' Constructor ''' QWidget.__init__(self) self._initGUI() def _initGUI(self): self.layout = QVBoxLayout() self.form = QFormLayout() self.name = QLineEdit() self.surname = QLineEdit() self.birthdate = QCalendarWidget() self.birthdate.setGridVisible(True) self.birthdate.setMinimumDate(QDate(1850,1,1)) self.birthdate.setMaximumDate(QDate.currentDate()) self.male = QRadioButton("Male") self.male.setChecked(True) self.female = QRadioButton("Female") self.height = QDoubleSpinBox() self.height.setMaximum(250) self.height.setMinimum(50) self.height.setValue(165) self.height.setSuffix(" cm") self.mass = QDoubleSpinBox() self.mass.setMaximum(300) self.mass.setMinimum(20) self.mass.setValue(60) self.mass.setSuffix(" Kg") btnLayout = QVBoxLayout() self.form.addRow("Name", self.name) self.form.addRow("Surname", self.surname) self.form.addRow("Birth date",self.birthdate) sexLayout = QHBoxLayout() sexLayout.addWidget(self.male) sexLayout.addWidget(self.female) self.form.addRow("Sex", sexLayout) self.form.addRow("Height", self.height) self.form.addRow("Mass", self.mass) self.layout.addLayout(self.form) self.layout.addLayout(btnLayout) self.setLayout(self.layout) def getLayout(self): return self.layout def getWidget(self): widget = QWidget() widget.setLayout(self.layout) return widget def setProfile(self, athlete): self.name.setText(athlete._name) self.surname.setText(athlete._surname) self.birthdate.setSelectedDate(athlete._birthDate) if athlete._sex=="Male": self.male.setChecked(True) else: self.female.setChecked(True) self.height.setValue(athlete._height) self.mass.setValue(athlete._mass) def getProfile(self): qDate = self.birthdate.selectedDate() birthDate = self.qDate_to_date(qDate) athleteProfile = Athlete(self.name.text(), self.surname.text(), self._getSex(), birthDate, self.height.value(), self.mass.value()) return athleteProfile def qDate_to_date(self, qDate): return date(qDate.year(), qDate.month(),qDate.day()) def _getSex(self): if (self.male.isChecked()): return "Male" elif (self.female.isChecked()): return "Female" else : print "Error: No sex selected" return False
class _DelimitedDetectorWidget(_DetectorWidget): def _initUI(self): # Widgets self._rb_delimited = QRadioButton('Delimited') self._rb_delimited.setChecked(False) self._lbl_elevation = QLabel("Elevation") self._lbl_elevation.setStyleSheet("color: blue") self._txt_elevation = _AngleRangeWidget(_DelimitedDetector.elevation_rad) self._txt_elevation.setEnabled(False) self._txt_elevation.setRequired(False) self._lbl_azimuth = QLabel('Azimuth') self._lbl_azimuth.setStyleSheet("color: blue") self._txt_azimuth = _AngleRangeWidget(_DelimitedDetector.azimuth_rad) self._txt_azimuth.setEnabled(False) self._txt_azimuth.setRequired(False) self._rb_annular = QRadioButton('Annular') self._rb_annular.setChecked(True) self._lbl_takeoffangle = QLabel('Take-off angle') self._lbl_takeoffangle.setStyleSheet("color: blue") param_takeoffangle = \ AngleParameter(validators=range_validator(0.0, HALFPI), doc='Take-off angle from the x-y plane') param_takeoffangle._name = 'takeoffangle' self._txt_takeoffangle = AngleParameterWidget(param_takeoffangle) self._lbl_opening = QLabel('Opening') self._lbl_opening.setStyleSheet("color: blue") param_opening = \ AngleParameter(validators=range_validator(0.0, HALFPI, False), doc='Opening angle from the take-off angle (above and below)') param_opening._name = 'opening' self._txt_opening = AngleParameterWidget(param_opening) # Layouts layout = _DetectorWidget._initUI(self) layout.addRow(self._rb_delimited) sublayout = QFormLayout() sublayout.setContentsMargins(10, 0, 0, 0) if sys.platform == 'darwin': # Fix for Mac OS sublayout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow) sublayout.addRow(self._lbl_elevation, self._txt_elevation) sublayout.addRow(self._lbl_azimuth, self._txt_azimuth) layout.addRow(sublayout) layout.addRow(self._rb_annular) sublayout = QFormLayout() sublayout.setContentsMargins(10, 0, 0, 0) if sys.platform == 'darwin': # Fix for Mac OS sublayout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow) sublayout.addRow(self._lbl_takeoffangle, self._txt_takeoffangle) sublayout.addRow(self._lbl_opening, self._txt_opening) layout.addRow(sublayout) # Signals self._rb_delimited.toggled.connect(self._onToggle) self._rb_annular.toggled.connect(self._onToggle) return layout def _onToggle(self): state = self._rb_delimited.isChecked() self._txt_elevation.setEnabled(state) self._txt_azimuth.setEnabled(state) self._txt_elevation.setRequired(state) self._txt_azimuth.setRequired(state) self._txt_takeoffangle.setEnabled(not state) self._txt_opening.setEnabled(not state) self._txt_takeoffangle.setRequired(not state) self._txt_opening.setRequired(not state) def _getElevationValues(self): if self._rb_delimited.isChecked(): return self._txt_elevation.values() else: takeoffangles = self._txt_takeoffangle.values() openings = self._txt_opening.values() elevations = [] for takeoffangle, opening in product(takeoffangles, openings): elevation = (takeoffangle - opening, takeoffangle + opening) elevations.append(elevation) return elevations def _getAzimuthValues(self): if self._rb_delimited.isChecked(): return self._txt_azimuth.values() else: return [(0.0, TWOPI)] def setValue(self, value): self._rb_delimited.setChecked(True) self._txt_elevation.setValues(value.elevation_rad) self._txt_azimuth.setValues(value.azimuth_rad) self._txt_takeoffangle.setValues([]) self._txt_opening.setValues([]) def setReadOnly(self, state): _DetectorWidget.setReadOnly(self, state) style = 'color: none' if state else 'color: blue' self._rb_delimited.setEnabled(not state) self._rb_annular.setEnabled(not state) self._lbl_elevation.setStyleSheet(style) self._txt_elevation.setReadOnly(state) self._lbl_azimuth.setStyleSheet(style) self._txt_azimuth.setReadOnly(state) self._lbl_takeoffangle.setStyleSheet(style) self._txt_takeoffangle.setReadOnly(state) self._lbl_opening.setStyleSheet(style) self._txt_opening.setReadOnly(state)
class NetworkPane(BasePane): def __init__(self, setting_dict): BasePane.__init__( self ) networkLayout = QFormLayout() matchAlgorithmBox = QGroupBox() self.ccRadio = QRadioButton('Cross-correlation') self.dtwRadio = QRadioButton('DTW') self.dctRadio = QRadioButton('DCT') hbox = QHBoxLayout() hbox.addWidget(self.ccRadio) hbox.addWidget(self.dtwRadio) hbox.addWidget(self.dctRadio) matchAlgorithmBox.setLayout(hbox) networkLayout.addRow(QLabel('Similarity algorithm:'),matchAlgorithmBox) clusterBox = QGroupBox() self.completeRadio = QRadioButton('Complete') self.thresholdRadio = QRadioButton('Threshold') self.apRadio = QRadioButton('Affinity propagation') self.scRadio = QRadioButton('Spectral clustering') hbox = QHBoxLayout() hbox.addWidget(self.completeRadio) hbox.addWidget(self.thresholdRadio) hbox.addWidget(self.apRadio) hbox.addWidget(self.scRadio) clusterBox.setLayout(hbox) networkLayout.addRow(QLabel('Cluster algorithm:'),clusterBox) self.oneClusterCheck = QCheckBox() networkLayout.addRow(QLabel('Enforce single cluster:'),self.oneClusterCheck) self.thresholdEdit = QLineEdit() networkLayout.addRow(QLabel('Similarity threshold:'),self.thresholdEdit) self.setLayout(networkLayout) #set up defaults matchAlgorithm = setting_dict['dist_func'] clustAlgorithm = setting_dict['cluster_alg'] oneCluster = setting_dict['one_cluster'] if matchAlgorithm == 'xcorr': self.ccRadio.setChecked(True) elif matchAlgorithm == 'dct': self.dctRadio.setChecked(True) else: self.dtwRadio.setChecked(True) if clustAlgorithm == 'complete': self.completeRadio.setChecked(True) elif clustAlgorithm == 'threshold': self.thresholdRadio.setChecked(True) elif clustAlgorithm == 'affinity': self.apRadio.setChecked(True) elif clustAlgorithm == 'spectral': self.scRadio.setChecked(True) if oneCluster: self.oneClusterCheck.setChecked(True) self.thresholdEdit.setText(str(setting_dict['threshold'])) self.prev_state = setting_dict def get_current_state(self): setting_dict = {} if self.ccRadio.isChecked(): setting_dict['dist_func'] = 'xcorr' elif self.dctRadio.isChecked(): setting_dict['dist_func'] = 'dct' elif self.dtwRadio.isChecked(): setting_dict['dist_func'] = 'dtw' if self.completeRadio.isChecked(): setting_dict['cluster_alg'] = 'complete' elif self.thresholdRadio.isChecked(): setting_dict['cluster_alg'] = 'threshold' elif self.apRadio.isChecked(): setting_dict['cluster_alg'] = 'affinity' elif self.scRadio.isChecked(): setting_dict['cluster_alg'] = 'spectral' setting_dict['one_cluster'] = int(self.oneClusterCheck.isChecked()) setting_dict['threshold'] = float(self.thresholdEdit.text()) return setting_dict def is_changed(self): cur_state = self.get_current_state() if self.prev_state['dist_func'] != cur_state['dist_func']: return True return False for k in ['dist_func','cluster_alg']: if self.prev_state[k] != cur_state[k]: return True if cur_state['cluster_alg'] == 'threshold': if self.prev_state['threshold'] != cur_state['threshold']: return True elif cur_state['cluster_alg'] in {'affinity','spectral'}: if self.prev_state['one_cluster'] != cur_state['one_cluster']: return True return False
class RepresentationPane(BasePane): def __init__(self, setting_dict): BasePane.__init__( self ) repLayout = QVBoxLayout() genLayout = QFormLayout() self.winLenEdit = QLineEdit() genLayout.addRow(QLabel('Window length (s):'),self.winLenEdit) self.timeStepEdit = QLineEdit() genLayout.addRow(QLabel('Time step (s):'),self.timeStepEdit) self.minFreqEdit = QLineEdit() genLayout.addRow(QLabel('Minimum frequency (Hz):'),self.minFreqEdit) self.maxFreqEdit = QLineEdit() genLayout.addRow(QLabel('Maximum frequency (Hz):'),self.maxFreqEdit) self.numCoresEdit = QLineEdit() genLayout.addRow(QLabel('Number of cores (multiprocessing):'),self.numCoresEdit) repBox = QGroupBox() self.envelopeRadio = QRadioButton('Amplitude envelopes') self.mfccRadio = QRadioButton('MFCCs') self.mhecRadio = QRadioButton('MHECs') self.prosodyRadio = QRadioButton('Prosody') self.formantRadio = QRadioButton('Formants') hbox = QHBoxLayout() hbox.addWidget(self.envelopeRadio) hbox.addWidget(self.mfccRadio) #hbox.addWidget(self.mhecRadio) #hbox.addWidget(self.prosodyRadio) #hbox.addWidget(self.formantRadio) repBox.setLayout(hbox) genLayout.addRow(QLabel('Token representation:'),repBox) genWidget = QGroupBox('General') genWidget.setLayout(genLayout) repLayout.addWidget(genWidget) envLayout = QFormLayout() self.bandEdit = QLineEdit() envLayout.addRow(QLabel('Number of bands:'),self.bandEdit) self.gammatoneCheck = QCheckBox() envLayout.addRow(QLabel('Gammatone:'),self.gammatoneCheck) self.windowCheck = QCheckBox() envLayout.addRow(QLabel('Windowed:'),self.windowCheck) envWidget = QGroupBox('Amplitude envelopes') envWidget.setLayout(envLayout) repLayout.addWidget(envWidget) mfccLayout = QFormLayout() self.numCCEdit = QLineEdit() mfccLayout.addRow(QLabel('Number of coefficents:'),self.numCCEdit) self.numFiltersEdit = QLineEdit() mfccLayout.addRow(QLabel('Number of filters:'),self.numFiltersEdit) self.powerCheck = QCheckBox() mfccLayout.addRow(QLabel('Use power (first coefficient):'),self.powerCheck) mfccWidget = QGroupBox('MFCC') mfccWidget.setLayout(mfccLayout) repLayout.addWidget(mfccWidget) self.setLayout(repLayout) self.winLenEdit.setText(str(setting_dict['win_len'])) self.timeStepEdit.setText(str(setting_dict['time_step'])) freq_lims = setting_dict['freq_lims'] self.minFreqEdit.setText(str(freq_lims[0])) self.maxFreqEdit.setText(str(freq_lims[1])) self.numCoresEdit.setText(str(setting_dict['num_cores'])) rep = setting_dict['rep'] if rep == 'mfcc': self.mfccRadio.setChecked(True) elif rep == 'mhec': self.mhecRadio.setChecked(True) elif rep == 'prosody': self.prosodyRadio.setChecked(True) elif rep == 'formant': self.formantRadio.setChecked(True) elif rep == 'envelopes': self.envelopeRadio.setChecked(True) self.bandEdit.setText(str(setting_dict['envelope_bands'])) if setting_dict['use_gammatone']: self.gammatoneCheck.setChecked(True) if setting_dict['use_window']: self.windowCheck.setChecked(True) self.numFiltersEdit.setText(str(setting_dict['mfcc_filters'])) self.numCCEdit.setText(str(setting_dict['num_coeffs'])) if setting_dict['use_power']: self.powerCheck.setChecked(True) self.prev_state = setting_dict def get_current_state(self): setting_dict = {} if self.mfccRadio.isChecked(): setting_dict['rep'] = 'mfcc' elif self.mhecRadio.isChecked(): setting_dict['rep'] = 'mhec' elif self.prosodyRadio.isChecked(): setting_dict['rep'] = 'prosody' elif self.formantRadio.isChecked(): setting_dict['rep'] = 'formant' elif self.envelopeRadio.isChecked(): setting_dict['rep'] = 'envelopes' setting_dict['win_len'] = float(self.winLenEdit.text()) setting_dict['time_step'] = float(self.timeStepEdit.text()) setting_dict['freq_lims'] = (int(self.minFreqEdit.text()), int(self.maxFreqEdit.text())) setting_dict['num_cores'] = int(self.numCoresEdit.text()) setting_dict['envelope_bands'] = int(self.bandEdit.text()) setting_dict['use_gammatone'] = int(self.gammatoneCheck.isChecked()) setting_dict['use_window'] = int(self.windowCheck.isChecked()) setting_dict['num_coeffs'] = int(self.numCCEdit.text()) setting_dict['mfcc_filters'] = int(self.numFiltersEdit.text()) setting_dict['use_power'] = int(self.powerCheck.isChecked()) return setting_dict def is_changed(self): cur_state = self.get_current_state() if self.prev_state['rep'] != cur_state['rep']: return True if cur_state['rep'] == 'mfcc': for k in ['win_len','time_step','freq_lims', 'num_coeffs','mfcc_filters','use_power']: if cur_state[k] != self.prev_state[k]: return True elif cur_state['rep'] == 'envelopes': for k in ['freq_lims','envelope_bands', 'use_gammatone', 'use_window']: if cur_state[k] != self.prev_state[k]: return True if cur_state['use_window']: for k in ['win_len','time_step']: if cur_state[k] != self.prev_state[k]: return True return False
class PostViewWidget(HorsePanel): def __init__(self, parent, order_overview_widget, find_order_slot): global configuration super(PostViewWidget, self).__init__(parent) self.set_panel_title(_("Post overview")) self.bold_font = QFont(self.font()) self.bold_font.setBold(True) self.nb_cols = 8 # Number of columns in the operation definition table self.order_overview_widget = order_overview_widget self.button = QPushButton(_("Refresh"), self) self.button.clicked.connect(self.refresh_action) self.sort_by_deadline_button = QRadioButton(_("By deadline"), self) self.sort_by_deadline_button.toggled.connect(self.sort_by_deadline) self.sort_by_size_button = QRadioButton(_("By hours left to do"), self) self.sort_by_size_button.toggled.connect(self.sort_by_size) # hlayout = QHBoxLayout() # hlayout.setObjectName("halyout") # hlayout.setContentsMargins(0,0,0,0) # hlayout.addWidget(self.sort_by_deadline_button) # hlayout.addWidget(self.sort_by_size_button) # hlayout.addWidget(self.button) # hlayout.addStretch() self.navbar = NavBar(self, [(self.sort_by_deadline_button, None), (self.sort_by_size_button, None), (self.button, None), (_("Find"), find_order_slot)]) self.navbar.buttons[3].setObjectName("specialMenuButton") self.vlayout = QVBoxLayout(self) self.vlayout.setObjectName("Vlayout") self.vlayout.addWidget( TitleWidget(_("Posts Overview"), self, self.navbar)) self._table_model = QStandardItemModel(1, self.nb_cols, self) self.table_view = QTableView(None) self.table_view.setModel(self._table_model) self.table_view.selectionModel().currentChanged.connect( self.operation_selected) self.table_view.verticalHeader().hide() self.table_view.horizontalHeader().hide() self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) # This forces Qt to expand layout once I fill data in # FIXME dirty but I really don't get why setting # the mini width to something smaller (that happens at # startup, on first refresh) doesn't work self.table_view.setMinimumWidth(1) self.table_view.setMaximumWidth(1) self.post_view_scene = PostViewScene(self, order_overview_widget) self.post_view_scene_view = QGraphicsView(self) self.post_view_scene_view.setScene(self.post_view_scene) self.post_view_scene_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.splitter = QSplitter(Qt.Horizontal) self.splitter.addWidget( SubFrame(_("Posts"), self.table_view, self.splitter)) self.splitter.addWidget( SubFrame(_("Workload"), self.post_view_scene_view, self.splitter)) # self.splitter.setStretchFactor(0,1) self.splitter.setStretchFactor(1, 1) self.vlayout.addWidget(self.splitter) # hlayout = QHBoxLayout() # hlayout.addWidget(SubFrame(_("Posts"),self.table_view,self)) # hlayout.addWidget(SubFrame(_("Workload"),self.post_view_scene_view,self)) # hlayout.setStretch(1,1) # self.vlayout.addLayout(hlayout) self.vlayout.setStretch(0, 0) self.vlayout.setStretch(1, 1) self.setLayout(self.vlayout) self.timer = QTimer(self) self.timer.timeout.connect(self.slidePostsScene) self.current_view_y = 0 def _data_load(self): global dao all_operations = dao.operation_dao.load_all_operations_ready_for_production( ) operation_definitions = dao.operation_definition_dao.all_direct_frozen( ) return operation_definitions, all_operations def _reset_operation_definitions(self, operations): self._table_model.setColumnCount(1) self._table_model.setRowCount(len(operations)) # BUG This should be refreshed on reload() too row = col = 0 first_active = None for opdef in operations: if opdef.operation_definition_id in self.post_view_scene.drawn_operations_data: # currently total planned time t = self.post_view_scene.drawn_operations_data[ opdef.operation_definition_id] ndx = self._table_model.index(row, col) if not first_active: first_active = ndx self._table_model.setData( ndx, u"{} {}".format(opdef.description, t), Qt.DisplayRole) # self._table_model.setData(ndx,self.bold_font,Qt.FontRole) self._table_model.setData(self._table_model.index(row, col), opdef.operation_definition_id, Qt.UserRole) row += 1 else: pass # self._table_model.setData(self._table_model.index(row,col),opdef.description,Qt.DisplayRole) # = col + 1 # if col == self.nb_cols: # col = 0 # row += 1 self._table_model.setRowCount(row) # self.table_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # self.vlayout.setStretch(0,0) # self.vlayout.setStretch(1,10) # self.vlayout.setStretch(2,10000) # height = 0 # for c in range(self.table_view.model().rowCount()): # height += self.table_view.rowHeight(c) + 1 # +1 for cell border # self.table_view.setMinimumHeight(height) # self.table_view.setMaximumHeight(height) for i in range(self.nb_cols): self.table_view.resizeColumnToContents(i) self.table_view.setMaximumWidth(self.table_view.columnWidth(0)) self.table_view.setMinimumWidth(self.table_view.columnWidth(0)) self.table_view.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) self.table_view.update() self.splitter.update() return first_active def slide_to_operation(self, opdef_id): if opdef_id in self.post_view_scene.posts_offsets: self.slide_target_opdef_id = opdef_id # mainlog.debug("Target y = {}".format(self.post_view_scene.posts_offsets[self.slide_target_opdef])) self.timer.start(20) @Slot() def slidePostsScene(self): if self.slide_target_opdef_id is None: return # self.post_view_scene_view self.post_view_scene.set_cursor_on( self.slide_target_opdef_id ) # This done here also aviod some screen trashing v = self.post_view_scene_view.verticalScrollBar().value() # mainlog.debug( "slidePostsScene : {}".format(v)) r = self.post_view_scene.posts_offsets[self.slide_target_opdef_id] target_y = r.y() + r.height() / 2 delta = (target_y - self.current_view_y) * 0.4 self.current_view_y = self.current_view_y + delta self.post_view_scene_view.centerOn(0, self.current_view_y) # mainlog.debug( "slidePostsScene : {} / {}".format(target_y, self.current_view_y)) if self.post_view_scene_view.verticalScrollBar().value() == v: # Close enough => stop moving # FIXME not correct because we must stop when the view stops moving, not when the goal we set for centerOn is reached self.timer.stop() @Slot(QModelIndex, QModelIndex) def operation_selected(self, ndx_cur, ndx_old): if ndx_cur.isValid(): opdef = self._table_model.data(ndx_cur, Qt.UserRole) if opdef: self.slide_to_operation( self._table_model.data(ndx_cur, Qt.UserRole)) @Slot() def refresh_action(self): # FIXME reload operations as well operation_definitions, all_operations = self._data_load() # mainlog.debug("reload") if self.sort_by_deadline_button.isChecked(): self.post_view_scene.reload(self, operation_definitions, all_operations, 1) elif self.sort_by_size_button.isChecked(): self.post_view_scene.reload(self, operation_definitions, all_operations, 2) else: self.post_view_scene.reload(self, operation_definitions, all_operations, 0) # mainlog.debug("reset") first_active = self._reset_operation_definitions(operation_definitions) # self.table_view.selectionModel().currentChanged.connect(self.operation_selected) if first_active: self.table_view.setCurrentIndex(first_active) # mainlog.debug("done reset") @Slot(bool) def sort_by_deadline(self, checked): if checked: self.refresh_action() @Slot(bool) def sort_by_size(self, checked): if checked: self.refresh_action() order_part_double_clicked = Signal(int) # Callback that will be called by HooverBar def set_on_order_part(self, order_part_id): self.order_part_double_clicked.emit(order_part_id)
class Form(QDialog): def __init__(self, state, parent=None): super().__init__(parent) Lib.prepareModalDialog(self) self.state = state self.setWindowTitle("Move Entry — {}".format( QApplication.applicationName())) self.message = None self.createWidgets() self.layoutWidgets() self.createConnections() self.updateUi() settings = QSettings() self.updateToolTips( bool( int( settings.value(Gopt.Key.ShowDialogToolTips, Gopt.Default.ShowDialogToolTips)))) def createWidgets(self): selectedEid = self.state.viewAllPanel.view.selectedEid self.selectedEntry = self.state.model.entry(selectedEid) self.entryLabel = QLabel("Move ") self.termLabel = Widgets.Label.HtmlLabel("“{}”".format( Lib.elidePatchHtml(self.selectedEntry.term, self.state))) self.eidGroup = QGroupBox() parentEid = self.selectedEntry.peid self.moveToTopRadioButton = QRadioButton("to be a &Main Entry") self.grandParentEntry = None grandParentEid = None if parentEid != ROOT: grandParentEid = self.state.model.parentOf(parentEid) if grandParentEid != ROOT: self.grandParentEntry = self.state.model.entry(grandParentEid) self.grandParentRadioButton = QRadioButton("up under &Grandparent") self.filteredEntry = self.circledEntry = None filteredEid = self.state.viewFilteredPanel.view.selectedEid if filteredEid is not None: self.filteredEntry = self.state.model.entry(filteredEid) circledEid = self.state.viewAllPanel.view.circledEid if circledEid is not None: self.circledEntry = self.state.model.entry(circledEid) self.filteredRadioButton = QRadioButton("under &Filtered") self.circledRadioButton = QRadioButton("under C&ircled") self.recentRadioButton = QRadioButton("under &Recent") self.tooltips.append( (self.recentRadioButton, """<p><b>under Recent</b></p> <p>Move the current entry under a recently visited entry.</p>""")) self.grandParentLabel = Widgets.Label.HtmlLabel() self.filteredLabel = Widgets.Label.HtmlLabel() self.circledLabel = Widgets.Label.HtmlLabel() self.moveToTopRadioButton.setEnabled(parentEid != ROOT) self.moveToTopRadioButton.setChecked(parentEid != ROOT) seen = {selectedEid, self.selectedEntry.peid} self.buttons = (self.moveToTopRadioButton, self.grandParentRadioButton, self.filteredRadioButton, self.circledRadioButton, self.recentRadioButton) Forms.Util.setUpRadioButton( self, self.grandParentEntry, self.grandParentRadioButton, self.grandParentLabel, self.buttons, seen, """<p><b>under Grandparent</b></p> <p>Move the current entry up under its grandparent “{}”.</p>""") Forms.Util.setUpRadioButton( self, self.filteredEntry, self.filteredRadioButton, self.filteredLabel, self.buttons, seen, """<p><b>under Filtered</b></p> <p>Move the current entry under the filtered entry “{}”.</p>""") Forms.Util.setUpRadioButton( self, self.circledEntry, self.circledRadioButton, self.circledLabel, self.buttons, seen, """<p><b>under Circled</b></p> <p>Move the current entry under the circled entry “{}”.</p>""") self.recentComboBox = Forms.Util.createTermsComboBox( self.state, self.state.gotoEids, ignore=seen, maximum=MAX_RECENT) if self.recentComboBox.count() and all(not radio.isChecked() for radio in self.buttons): self.recentRadioButton.setChecked(True) self.recentComboBox.setFocus() self.buttonBox = QDialogButtonBox() self.moveButton = QPushButton(QIcon(":/move.svg"), "M&ove") self.tooltips.append((self.moveButton, """<p><b>Move</b></p> <p>Move the “{}” entry.</p>""".format(self.termLabel.text()))) self.buttonBox.addButton(self.moveButton, QDialogButtonBox.AcceptRole) self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Cancel") self.tooltips.append((self.closeButton, """<p><b>Cancel</b></p> <p>Close the dialog without making any changes to the index.</p>""")) self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole) self.helpButton = QPushButton(QIcon(":/help.svg"), "Help") self.tooltips.append( (self.helpButton, "Help on the Move Entry dialog")) self.buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole) def layoutWidgets(self): layout = QVBoxLayout() entryLayout = QHBoxLayout() entryLayout.setSpacing(0) entryLayout.addWidget(self.entryLabel) entryLayout.addWidget(self.termLabel) entryLayout.addStretch() layout.addLayout(entryLayout) eidLayout = QVBoxLayout() eidLayout.addWidget(self.moveToTopRadioButton) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.grandParentRadioButton) hbox.addWidget(self.grandParentLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.filteredRadioButton) hbox.addWidget(self.filteredLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.circledRadioButton) hbox.addWidget(self.circledLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.recentRadioButton) hbox.addWidget(self.recentComboBox, 1) eidLayout.addLayout(hbox) eidLayout.addStretch() self.eidGroup.setLayout(eidLayout) layout.addWidget(self.eidGroup) layout.addWidget(self.buttonBox) self.setLayout(layout) def createConnections(self): self.buttonBox.accepted.connect(self.move) self.buttonBox.rejected.connect(self.reject) self.helpButton.clicked.connect(self.help) self.recentRadioButton.toggled.connect(self.moveFocus) self.recentComboBox.currentIndexChanged[int].connect( self.recentChanged) def recentChanged(self): self.recentRadioButton.setChecked(True) self.updateUi() def moveFocus(self): if self.recentRadioButton.isChecked(): self.recentComboBox.setFocus() def updateUi(self): self.recentRadioButton.setEnabled(self.recentComboBox.count()) self.recentComboBox.setEnabled(self.recentComboBox.count()) self.moveButton.setEnabled( any(button.isChecked() for button in self.buttons)) def help(self): self.state.help("xix_ref_dlg_move.html") def move(self): self.state.maybeSave() eid = self.selectedEntry.eid if self.moveToTopRadioButton.isChecked(): self.state.model.moveToTop(eid) else: peid = None if self.grandParentRadioButton.isChecked(): peid = self.grandParentEntry.eid message = "move up" elif self.filteredRadioButton.isChecked(): peid = self.filteredEntry.eid message = "move under filtered" elif self.circledRadioButton.isChecked(): peid = self.circledEntry.eid message = "move under circled" elif self.recentRadioButton.isChecked(): peid = self.recentComboBox.itemData( self.recentComboBox.currentIndex()) message = "move under recently visited" if peid is not None: # Should always be True self.state.model.moveUnder(eid, peid, message) term = Lib.htmlToPlainText(self.state.model.term(eid)) if peid == ROOT: message = "Moved “{}” to be a main entry".format(term) else: message = "Moved “{}” under “{}”".format( term, Lib.htmlToPlainText(self.state.model.term(peid))) say(message, SAY_TIMEOUT) self.accept()
class Form(QDialog): def __init__(self, state, parent=None): super().__init__(parent) Lib.prepareModalDialog(self) self.state = state self.setWindowTitle("Add Cross-reference — {}".format( QApplication.applicationName())) self.createWidgets() self.layoutWidgets() self.createConnections() self.updateUi() settings = QSettings() self.updateToolTips( bool( int( settings.value(Gopt.Key.ShowDialogToolTips, Gopt.Default.ShowDialogToolTips)))) def createWidgets(self): selectedEid = self.state.viewAllPanel.view.selectedEid self.selectedEntry = self.state.model.entry(selectedEid) self.entry1Label = QLabel("cross-reference from ") self.termLabel = Widgets.Label.HtmlLabel("“{}”".format( Lib.elidePatchHtml(self.selectedEntry.term, self.state))) self.entry2Label = QLabel(" to") self.seeRadioButton = QRadioButton("&See") self.seeRadioButton.setChecked(True) self.tooltips.append((self.seeRadioButton, """<p><b>See</b></p> <p>Check to create a <i>see</i> cross-reference.</p>""")) self.alsoRadioButton = QRadioButton("See &Also") self.tooltips.append((self.alsoRadioButton, """<p><b>See Also</b></p> <p>Check to create a <i>see also</i> cross-reference.</p>""")) self.whichGroup = QGroupBox("Add") self.filteredEntry = self.circledEntry = None filteredEid = self.state.viewFilteredPanel.view.selectedEid if filteredEid is not None: self.filteredEntry = self.state.model.entry(filteredEid) circledEid = self.state.viewAllPanel.view.circledEid if circledEid is not None: self.circledEntry = self.state.model.entry(circledEid) self.filteredRadioButton = QRadioButton("&Filtered") self.circledRadioButton = QRadioButton("C&ircled") self.recentRadioButton = QRadioButton("&Recent") self.tooltips.append((self.recentRadioButton, """<p><b>Recent</b></p> <p>Create a cross-reference to a recently visited entry.</p>""")) self.filteredLabel = Widgets.Label.HtmlLabel() self.circledLabel = Widgets.Label.HtmlLabel() seen = {selectedEid} buttons = (self.filteredRadioButton, self.circledRadioButton, self.recentRadioButton) Forms.Util.setUpRadioButton( self, self.filteredEntry, self.filteredRadioButton, self.filteredLabel, buttons, seen, """<p><b>Filtered</b></p> <p>Create a cross-reference to the filtered entry “{}”.</p>""") Forms.Util.setUpRadioButton( self, self.circledEntry, self.circledRadioButton, self.circledLabel, buttons, seen, """<p><b>Circled</b></p> <p>Create a cross-reference to the circled entry “{}”.</p>""") self.recentComboBox = Forms.Util.createTermsComboBox( self.state, self.state.gotoEids, ignore=seen, maximum=MAX_RECENT) self.groupRadioButton = QRadioButton("All in &Group") self.groupComboBox = QComboBox() for i, (gid, name, linked) in enumerate(self.state.model.allGroups()): self.groupComboBox.addItem( QIcon(":/grouplink.svg" if linked else ":/groups.svg"), name, gid) if not self.groupComboBox.count(): self.groupRadioButton.setEnabled(False) self.groupComboBox.setEnabled(False) self.eidGroup = QGroupBox() self.genericTermRadioButton = QRadioButton("Generic &Term") self.tooltips.append((self.genericTermRadioButton, """\ <p><b>Generic Term</b></p> <p>Create a cross-reference to the given generic term.</p>""")) self.genericTermLineEdit = EnableOnClickLineEdit( self.state, self.genericTermRadioButton, self) self.tooltips.append((self.genericTermLineEdit, """\ <p><b>Generic Term text</b></p> <p>The generic term text styled (e.g., <b>bold</b>, <i>italic</i>), as it should appear in the final index.</p>""")) self.formatPanel = Widgets.FormatPanel.Panel(self.state, self) self.formatPanel.state.editors = [self.genericTermLineEdit] self.formatActions = self.formatPanel.formatActions self.buttonBox = QDialogButtonBox() self.addButton = QPushButton(QIcon(":/xref-add.svg"), "A&dd") self.tooltips.append((self.addButton, """<p><b>Add</b></p> <p>Add the specified cross-reference to the <b>Entry</b> {}.</p>""".format( self.termLabel.text()))) self.buttonBox.addButton(self.addButton, QDialogButtonBox.AcceptRole) self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Cancel") self.tooltips.append((self.closeButton, """<p><b>Cancel</b></p> <p>Close the dialog without making any changes to the index.</p>""")) self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole) self.helpButton = QPushButton(QIcon(":/help.svg"), "Help") self.tooltips.append( (self.helpButton, "Help on the Add Cross-reference dialog")) self.buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole) if (not self.filteredRadioButton.isChecked() and not self.circledRadioButton.isChecked()): if self.recentComboBox.count(): self.recentRadioButton.setChecked(True) else: self.genericTermRadioButton.setChecked(True) self.genericTermLineEdit.setFocus() def layoutWidgets(self): layout = QVBoxLayout() whichLayout = QHBoxLayout() whichLayout.addWidget(self.seeRadioButton) whichLayout.addWidget(self.alsoRadioButton) whichLayout.addStretch() self.whichGroup.setLayout(whichLayout) layout.addWidget(self.whichGroup) entryLayout = QHBoxLayout() entryLayout.setSpacing(0) entryLayout.addWidget(self.entry1Label) entryLayout.addWidget(self.termLabel) entryLayout.addWidget(self.entry2Label) entryLayout.addStretch() layout.addLayout(entryLayout) eidLayout = QVBoxLayout() hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.filteredRadioButton) hbox.addWidget(self.filteredLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.circledRadioButton) hbox.addWidget(self.circledLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.recentRadioButton) hbox.addWidget(self.recentComboBox, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.addWidget(self.groupRadioButton) hbox.addWidget(self.groupComboBox, 1) eidLayout.addLayout(hbox) grid = QGridLayout() grid.addWidget(self.formatPanel, 0, 0, 1, 2, Qt.AlignRight) grid.addWidget(self.genericTermRadioButton, 1, 0) grid.addWidget(self.genericTermLineEdit, 1, 1) eidLayout.addLayout(grid) eidLayout.addStretch() self.eidGroup.setLayout(eidLayout) layout.addWidget(self.eidGroup) layout.addWidget(self.buttonBox) self.setLayout(layout) def createConnections(self): self.buttonBox.accepted.connect(self.addXRef) self.buttonBox.rejected.connect(self.reject) self.helpButton.clicked.connect(self.help) self.filteredRadioButton.clicked.connect(self.updateUi) self.circledRadioButton.clicked.connect(self.updateUi) self.recentRadioButton.clicked.connect(self.updateUi) self.recentRadioButton.toggled.connect(self.moveFocus) self.recentComboBox.currentIndexChanged[int].connect( self.recentChanged) self.groupRadioButton.clicked.connect(self.updateUi) self.groupRadioButton.toggled.connect(self.moveFocus) self.groupComboBox.currentIndexChanged[int].connect(self.groupChanged) self.genericTermRadioButton.clicked.connect(self.updateUi) self.genericTermRadioButton.clicked.connect( self.genericTermLineEdit.setFocus) self.genericTermLineEdit.textChanged.connect(self.updateUi) self.genericTermLineEdit.enterPressed.connect(self.maybeAdd) def recentChanged(self): self.recentRadioButton.setChecked(True) self.updateUi() def groupChanged(self): self.groupRadioButton.setChecked(True) self.updateUi() def moveFocus(self): if self.recentRadioButton.isChecked(): self.recentComboBox.setFocus() elif self.groupRadioButton.isChecked(): self.groupComboBox.setFocus() def help(self): self.state.help("xix_ref_dlg_addxref.html") def updateUi(self): enable = (self.genericTermRadioButton.isChecked() or (self.groupRadioButton.isChecked() and self.groupComboBox.count())) for widget in (self.genericTermLineEdit, self.formatPanel): widget.setEnabled(enable) self.recentRadioButton.setEnabled(self.recentComboBox.count()) self.recentComboBox.setEnabled(self.recentComboBox.count()) enable = True if (self.filteredRadioButton.isChecked() and self.filteredEntry is None): enable = False if (self.circledRadioButton.isChecked() and self.circledEntry is None): enable = False if (self.recentRadioButton.isChecked() and self.recentComboBox.currentIndex() < 0): enable = False if (self.groupRadioButton.isChecked() and not self.groupComboBox.count()): enable = False if (self.genericTermRadioButton.isChecked() and self.genericTermLineEdit.isEmpty()): enable = False self.addButton.setEnabled(enable) def maybeAdd(self): if (self.genericTermRadioButton.isChecked() and not self.genericTermLineEdit.isEmpty()): self.addXRef() def addXRef(self): from_eid = self.selectedEntry.eid assert from_eid is not None kind = (XrefKind.SEE if self.seeRadioButton.isChecked() else XrefKind.SEE_ALSO) if self.groupRadioButton.isChecked(): gid = int( self.groupComboBox.itemData(self.groupComboBox.currentIndex())) for to_eid in tuple(self.state.model.eidsForGid(gid)): self.state.model.addXRef(from_eid, to_eid, kind) elif not self.genericTermRadioButton.isChecked(): to_eid = None if self.filteredRadioButton.isChecked(): to_eid = self.filteredEntry.eid elif self.circledRadioButton.isChecked(): to_eid = self.circledEntry.eid elif self.recentRadioButton.isChecked(): to_eid = self.recentComboBox.itemData( self.recentComboBox.currentIndex()) assert to_eid is not None self.state.model.addXRef(from_eid, to_eid, kind) else: term = self.genericTermLineEdit.toHtml() kind = (XrefKind.SEE_GENERIC if self.seeRadioButton.isChecked() else XrefKind.SEE_ALSO_GENERIC) self.state.model.addGenericXRef(from_eid, term, kind) say("Added cross-reference", SAY_TIMEOUT) self.accept()