class ProductDetailsWidget(ProwlerSqlWidget): """Base class for the AmzProductDetailsWidget and VndProductDetailsWidget classes. Doesn't have it's own UI, but depends on certain UI elements (like self.titleLine) to be available. """ def __init__(self, parent=None): super(ProductDetailsWidget, self).__init__(parent=parent) self.setupUi(self) # Populate the columns self.set_source(None) # Set up the data widget mapper self.mapper = QDataWidgetMapper(self) self.mapper.setModel(self.model) self.mapper.setItemDelegate(DataMapperDelegate(self)) self.mapper.currentIndexChanged.connect(self.rewind_lines) self.mapper.addMapping(self.titleLine, self.model.fieldIndex('title')) self.mapper.addMapping(self.brandLine, self.model.fieldIndex('brand')) self.mapper.addMapping(self.modelLine, self.model.fieldIndex('model')) self.mapper.addMapping(self.skuLine, self.model.fieldIndex('sku')) self.mapper.addMapping(self.upcLine, self.model.fieldIndex('upc')) self.mapper.addMapping(self.priceBox, self.model.fieldIndex('price')) self.mapper.addMapping(self.quantityBox, self.model.fieldIndex('quantity')) self.model.modelReset.connect(self.mapper.toFirst) def rewind_lines(self): """Reset text lines to home position.""" self.titleLine.home(False) self.brandLine.home(False) self.modelLine.home(False)
class JPMainTableModel(QtSql.QSqlRelationalTableModel): # _tp中存放需要添加到数据映射器中的控件类型 # 要添加的控件,必须用字段名命名(大小写敏感) _tp = (QtWidgets.QLineEdit, QtWidgets.QDateEdit, QtWidgets.QComboBox, QtWidgets.QTextEdit, QtWidgets.QCheckBox, QtWidgets.QSpinBox) def __init__(self, parent: QWidget, tableName: str, filter: str = None, db=QtSql.QSqlDatabase()): '''用于窗体模式进行数据编辑时的主窗体数据模型。\n 会自动增加数据映射器,但是外键字段要使用addComboBoxData方法增加列表文字。 最后要调用tofirst()方法定位编辑的记录。\n 注:数据映射器不能增删记录,只能编辑 ''' super().__init__(parent=parent, db=db) self.parent = parent self.setTable(tableName) if filter: self.setFilter(filter) self.select() rec = self.record() self.mapper = QDataWidgetMapper(parent) self.mapper.setModel(self) self.mapper.setItemDelegate(_JPRelationalDelegate(parent, self.mapper)) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) for i in range(rec.count()): widget = parent.findChild(self._tp, rec.fieldName(i)) if widget: if not isinstance(widget, QComboBox): self.mapper.addMapping(widget, i) def toFirst(self): # 定位到模型中第一条记录 self.mapper.toFirst() def addComboBoxData(self, fieldName: str, dataList: list, displayColumn: int = 0, modelColumn: int = 1): '''给模型中添加一个QComboBox控件的数据源。\n dataList为行来源数据源,列表对象.\n displayColumn为Combobox中要显示文字位于列表中的列号(首列为0)\n modelColumn为要保存到模型中数据在列表中的列号(首列为0)\n ''' widget = self.parent.findChild(QComboBox, fieldName) if widget is not None: widget.setModel( _JPComboBoxModel(widget, dataList, displayColumn, modelColumn)) self.mapper.addMapping(widget, self.fieldIndex(fieldName)) def saveData(self): pass
def setMappings(mappings): """Set the mappings between the model and widgets. TODO: - Should this be extended to accept other columns? - Check if the already has the model. """ column = 1 mappers = list() for widget, obj in mappings: mapper = QDataWidgetMapper(widget) # logger.debug(obj.model()) mapper.setModel(obj.model()) mapper.addMapping(widget, column) delegate = Delegate(widget) mapper.setItemDelegate(delegate) mapper.setRootIndex(obj.parent().index()) mapper.setCurrentModelIndex(obj.index()) # QDataWidgetMapper needs a focus event to notice a change in the data. # To make sure the model is informed about the change, I connected the # stateChanged signal of the QCheckBox to the submit slot of the # QDataWidgetMapper. The same idea goes for the QComboBox. # https://bugreports.qt.io/browse/QTBUG-1818 if isinstance(widget, QCheckBox): signal = widget.stateChanged try: signal.disconnect() except TypeError: pass signal.connect(mapper.submit) elif isinstance(widget, QComboBox): signal = widget.currentTextChanged try: signal.disconnect() except TypeError: pass signal.connect(mapper.submit) mappers.append(mapper) return mappers
class ArmorEditor(ArmorEditorWidgetBase, ArmorEditorWidget): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self.model = None self.parts_tree_model = ArmorSetTreeModel() self.skill_model = SkillTranslationModel() self.armor_item_mapper = QDataWidgetMapper(self) self.armor_item_mapper.setItemDelegate(ItemDelegate()) self.armor_item_mapper.setModel(self.parts_tree_model) self.parts_tree_view.setModel(self.parts_tree_model) self.parts_tree_view.activated.connect( self.handle_parts_tree_activated) self.import_export_manager = ImportExportManager(self.parts_tree_view) self.import_export_manager.connect_custom_context_menu() for it in ("set_skill1_value", "set_skill2_value", "skill1_value", "skill2_value", "skill3_value"): getattr(self, it).setModel(self.skill_model) mappings = [ (self.id_value, Column.id, b"text"), (self.name_value, Column.gmd_name_index, b"text"), (self.description_value, Column.gmd_desc_index, b"text"), (self.setid_value, Column.set_id), (self.set_group_value, Column.set_group), (self.type_value, Column.type, b"currentIndex"), (self.order_value, Column.order), (self.variant_value, Column.variant, b"currentIndex"), (self.equip_slot_value, Column.equip_slot, b"currentIndex"), (self.gender_value, Column.gender, b"currentIndex"), (self.mdl_main_id_value, Column.mdl_main_id), (self.mdl_secondary_id_value, Column.mdl_secondary_id), (self.icon_color_value, Column.icon_color), (self.defense_value, Column.defense), (self.rarity_value, Column.rarity), (self.cost_value, Column.cost), (self.fire_res_value, Column.fire_res), (self.water_res_value, Column.water_res), (self.thunder_res_value, Column.thunder_res), (self.ice_res_value, Column.ice_res), (self.dragon_res_value, Column.dragon_res), (self.set_skill1_value, Column.set_skill1), (self.set_skill1_lvl_value, Column.set_skill1_lvl), (self.set_skill2_value, Column.set_skill2), (self.set_skill2_lvl_value, Column.set_skill2_lvl), (self.skill1_value, Column.skill1), (self.skill1_lvl_value, Column.skill1_lvl), (self.skill2_value, Column.skill2), (self.skill2_lvl_value, Column.skill2_lvl), (self.skill3_value, Column.skill3), (self.skill3_lvl_value, Column.skill3_lvl), (self.num_gem_slots, Column.num_gem_slots), (self.gem_slot1_lvl_value, Column.gem_slot1_lvl), (self.gem_slot2_lvl_value, Column.gem_slot2_lvl), (self.gem_slot3_lvl_value, Column.gem_slot3_lvl), ] for mapping in mappings: self.armor_item_mapper.addMapping(*mapping) def handle_parts_tree_activated(self, qindex: QModelIndex): if isinstance(qindex.internalPointer(), ArmorSetNode): return self.armor_item_mapper.setRootIndex(qindex.parent()) self.armor_item_mapper.setCurrentModelIndex(qindex) entry = qindex.internalPointer().ref self.crafting_requirements_editor.set_current(entry.id) def set_model(self, model): self.model = model if self.model is None: self.parts_tree_model = None self.parts_tree_view.setModel(None) return self.skill_model.update(model.get_relation_data("t9n_skill_pt")) self.crafting_requirements_editor.set_model(model, None) self.parts_tree_model.update(model) self.configure_tree_view() def configure_tree_view(self): header = self.parts_tree_view.header() header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setStretchLastSection(False) for i in range(2, self.parts_tree_model.columnCount(None)): header.hideSection(i)
class PhoneLogDlg(QDialog): FIRST, PREV, NEXT, LAST = range(4) def __init__(self, parent=None): super(PhoneLogDlg, self).__init__(parent) callerLabel = QLabel("&Caller:") self.callerEdit = QLineEdit() callerLabel.setBuddy(self.callerEdit) today = QDate.currentDate() startLabel = QLabel("&Start:") self.startDateTime = QDateTimeEdit() startLabel.setBuddy(self.startDateTime) self.startDateTime.setDateRange(today, today) self.startDateTime.setDisplayFormat(DATETIME_FORMAT) endLabel = QLabel("&End:") self.endDateTime = QDateTimeEdit() endLabel.setBuddy(self.endDateTime) self.endDateTime.setDateRange(today, today) self.endDateTime.setDisplayFormat(DATETIME_FORMAT) topicLabel = QLabel("&Topic:") topicEdit = QLineEdit() topicLabel.setBuddy(topicEdit) outcomeLabel = QLabel("&Outcome:") self.outcomeComboBox = QComboBox() outcomeLabel.setBuddy(self.outcomeComboBox) firstButton = QPushButton() firstButton.setIcon(QIcon(":/first.png")) prevButton = QPushButton() prevButton.setIcon(QIcon(":/prev.png")) nextButton = QPushButton() nextButton.setIcon(QIcon(":/next.png")) lastButton = QPushButton() lastButton.setIcon(QIcon(":/last.png")) addButton = QPushButton("&Add") addButton.setIcon(QIcon(":/add.png")) deleteButton = QPushButton("&Delete") deleteButton.setIcon(QIcon(":/delete.png")) quitButton = QPushButton("&Quit") quitButton.setIcon(QIcon(":/quit.png")) if not MAC: addButton.setFocusPolicy(Qt.NoFocus) deleteButton.setFocusPolicy(Qt.NoFocus) fieldLayout = QGridLayout() fieldLayout.addWidget(callerLabel, 0, 0) fieldLayout.addWidget(self.callerEdit, 0, 1, 1, 3) fieldLayout.addWidget(startLabel, 1, 0) fieldLayout.addWidget(self.startDateTime, 1, 1) fieldLayout.addWidget(endLabel, 1, 2) fieldLayout.addWidget(self.endDateTime, 1, 3) fieldLayout.addWidget(topicLabel, 2, 0) fieldLayout.addWidget(topicEdit, 2, 1, 1, 3) fieldLayout.addWidget(outcomeLabel, 3, 0) fieldLayout.addWidget(self.outcomeComboBox, 3, 1, 1, 3) navigationLayout = QHBoxLayout() navigationLayout.addWidget(firstButton) navigationLayout.addWidget(prevButton) navigationLayout.addWidget(nextButton) navigationLayout.addWidget(lastButton) fieldLayout.addLayout(navigationLayout, 4, 0, 1, 2) buttonLayout = QVBoxLayout() buttonLayout.addWidget(addButton) buttonLayout.addWidget(deleteButton) buttonLayout.addStretch() buttonLayout.addWidget(quitButton) layout = QHBoxLayout() layout.addLayout(fieldLayout) layout.addLayout(buttonLayout) self.setLayout(layout) self.model = QSqlRelationalTableModel(self) self.model.setTable("calls") self.model.setRelation(OUTCOMEID, QSqlRelation("outcomes", "id", "name")) self.model.setSort(STARTTIME, Qt.AscendingOrder) self.model.select() self.mapper = QDataWidgetMapper(self) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.setModel(self.model) self.mapper.setItemDelegate(QSqlRelationalDelegate(self)) self.mapper.addMapping(self.callerEdit, CALLER) self.mapper.addMapping(self.startDateTime, STARTTIME) self.mapper.addMapping(self.endDateTime, ENDTIME) self.mapper.addMapping(topicEdit, TOPIC) relationModel = self.model.relationModel(OUTCOMEID) self.outcomeComboBox.setModel(relationModel) self.outcomeComboBox.setModelColumn(relationModel.fieldIndex("name")) self.mapper.addMapping(self.outcomeComboBox, OUTCOMEID) self.mapper.toFirst() firstButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.FIRST)) prevButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.PREV)) nextButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.NEXT)) lastButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.LAST)) addButton.clicked.connect(self.addRecord) deleteButton.clicked.connect(self.deleteRecord) quitButton.clicked.connect(self.done) self.setWindowTitle("Phone Log") def done(self, result=None): self.mapper.submit() QDialog.done(self, True) def addRecord(self): row = self.model.rowCount() self.mapper.submit() self.model.insertRow(row) self.mapper.setCurrentIndex(row) now = QDateTime.currentDateTime() self.startDateTime.setDateTime(now) self.endDateTime.setDateTime(now) self.outcomeComboBox.setCurrentIndex( self.outcomeComboBox.findText("Unresolved")) self.callerEdit.setFocus() def deleteRecord(self): caller = self.callerEdit.text() starttime = self.startDateTime.dateTime().toString(DATETIME_FORMAT) if (QMessageBox.question( self, "Delete", "Delete call made by<br>{0} on {1}?".format(caller, starttime), QMessageBox.Yes | QMessageBox.No) == QMessageBox.No): return row = self.mapper.currentIndex() self.model.removeRow(row) self.model.submitAll() self.model.select() if row + 1 >= self.model.rowCount(): row = self.model.rowCount() - 1 self.mapper.setCurrentIndex(row) def saveRecord(self, where): row = self.mapper.currentIndex() self.mapper.submit() if where == PhoneLogDlg.FIRST: row = 0 elif where == PhoneLogDlg.PREV: row = 0 if row <= 1 else row - 1 elif where == PhoneLogDlg.NEXT: row += 1 if row >= self.model.rowCount(): row = self.model.rowCount() - 1 elif where == PhoneLogDlg.LAST: row = self.model.rowCount() - 1 self.mapper.setCurrentIndex(row)
class WpDatGEditor(WeaponGunEditorWidgetBase, WeaponGunEditorWidget): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self.model = None self.item_model = WpDatGTableModel(self) self.weapon_tree_view.setModel(self.item_model) self.shell_table_model = ShellTableModel() self.shell_table_view.setModel(self.shell_table_model) self.bottle_table_model = BottleTableModel(self) self.mapper = QDataWidgetMapper(self) self.mapper.setItemDelegate(ItemDelegate()) self.mapper.setModel(self.item_model) self.bottle_mapper = QDataWidgetMapper(self) self.bottle_mapper.setItemDelegate(ItemDelegate()) self.bottle_mapper.setModel(self.bottle_table_model) self.weapon_tree_view.activated.connect( self.handle_weapon_tree_view_activated) self.skill_model = SkillTranslationModel() self.skill_id_value.setModel(self.skill_model) self.import_export_manager = ImportExportManager( self.weapon_tree_view, WpDatGPlugin.import_export.get("safe_attrs")) self.import_export_manager.connect_custom_context_menu() mappings = [ (self.id_value, WpDatGEntry.id.index, b"text"), (self.name_value, WpDatGEntry.gmd_name_index.index, b"text"), (self.description_value, WpDatGEntry.gmd_description_index.index, b"text"), (self.order_value, WpDatGEntry.order.index), (self.tree_id_value, WpDatGEntry.tree_id.index), (self.tree_position_value, WpDatGEntry.tree_position.index), (self.is_fixed_upgrade_value, WpDatGEntry.is_fixed_upgrade.index, b"checked"), (self.base_model_id_value, WpDatGEntry.base_model_id.index), (self.part1_id_value, WpDatGEntry.part1_id.index), (self.part2_id_value, WpDatGEntry.part2_id.index), (self.color_value, WpDatGEntry.color.index), (self.muzzle_type_value, WpDatGEntry.muzzle_type.index, b"currentIndex"), (self.barrel_type_value, WpDatGEntry.barrel_type.index, b"currentIndex"), (self.magazine_type_value, WpDatGEntry.magazine_type.index, b"currentIndex"), (self.scope_type_value, WpDatGEntry.scope_type.index, b"currentIndex"), (self.rarity_value, WpDatGEntry.rarity.index), (self.cost_value, WpDatGEntry.crafting_cost.index), (self.raw_damage_value, WpDatGEntry.raw_damage.index), (self.affinity_value, WpDatGEntry.affinity.index), (self.defense_value, WpDatGEntry.defense.index), (self.deviation_value, WpDatGEntry.deviation.index, b"currentIndex"), (self.special_ammo_type_value, WpDatGEntry.special_ammo_type.index, b"currentIndex"), (self.element_id_value, WpDatGEntry.element_id.index, b"currentIndex"), (self.element_damage_value, WpDatGEntry.element_damage.index), (self.hidden_element_id_value, WpDatGEntry.hidden_element_id.index, b"currentIndex"), (self.hidden_element_damage_value, WpDatGEntry.hidden_element_damage.index), (self.elderseal_value, WpDatGEntry.elderseal.index, b"currentIndex"), (self.num_gem_slots, WpDatGEntry.num_gem_slots.index), (self.gem_slot1_lvl_value, WpDatGEntry.gem_slot1_lvl.index), (self.gem_slot2_lvl_value, WpDatGEntry.gem_slot2_lvl.index), (self.gem_slot3_lvl_value, WpDatGEntry.gem_slot3_lvl.index), (self.skill_id_value, WpDatGEntry.skill_id.index), ] for mapping in mappings: self.mapper.addMapping(*mapping) mappings = [ (self.close_range_value, BbtblEntry.close_range.index, b"currentIndex"), (self.power_value, BbtblEntry.power.index, b"currentIndex"), (self.paralysis_value, BbtblEntry.paralysis.index, b"currentIndex"), (self.poison_value, BbtblEntry.poison.index, b"currentIndex"), (self.sleep_value, BbtblEntry.sleep.index, b"currentIndex"), (self.blast_value, BbtblEntry.blast.index, b"currentIndex"), ] for mapping in mappings: self.bottle_mapper.addMapping(*mapping) @property def is_bow_type(self): return self.model.attrs.get("equip_type") == WeaponType.Bow def handle_weapon_tree_view_activated(self, qindex: QModelIndex): self.mapper.setCurrentModelIndex(qindex) entry = self.item_model.entries[qindex.row()] self.tabs_weapon_details.setTabText( 0, self.item_model.data(qindex, Qt.DisplayRole)) self.crafting_requirements_editor.set_current(entry.id) if self.is_bow_type: index = self.bottle_table_model.index(entry.special_ammo_type, 0) self.bottle_mapper.setCurrentModelIndex(index) else: index = self.shell_table_model.index(entry.shell_table_id, 0, QModelIndex()) self.shell_table_view.setRootIndex(index) self.shell_table_view.expandAll() def set_model(self, model): self.model = model self.item_model.update(model) self.skill_model.update(model.get_relation_data("t9n_skill_pt")) self.crafting_requirements_editor\ .set_model(model, model.attrs.get("equip_type")) if self.is_bow_type: self.bottle_table_model.update(model) self.hide_tab(self.tab_shell_table) self.special_ammo_type_value.deleteLater() self.special_ammo_type_label.deleteLater() else: self.shell_table_model.update(model) self.hide_tab(self.tab_bottle_table) self.configure_tree_view() def configure_tree_view(self): for index, col in enumerate(self.item_model.fields): self.weapon_tree_view.hideColumn(index) self.weapon_tree_view.showColumn(WpDatGEntry.id.index) self.weapon_tree_view.showColumn(WpDatGEntry.gmd_name_index.index) header = self.weapon_tree_view.header() header.setSectionResizeMode(WpDatGEntry.gmd_name_index.index, QHeaderView.Stretch) header.setSectionResizeMode(WpDatGEntry.id.index, QHeaderView.ResizeToContents) def hide_tab(self, widget): index = self.tabs_weapon_details.indexOf(widget) self.tabs_weapon_details.removeTab(index)
class WpDatEditor(WeaponEditorWidgetBase, WeaponEditorWidget): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self.model = None self.skill_model = SkillTranslationModel() self.table_model = WpDatTableModel(self) self.weapon_tree_view.activated.connect( self.handle_weapon_tree_view_activated) self.kire_widget.set_model(KireGaugeModelEntryAdapter()) self.mapper = QDataWidgetMapper(self) self.mapper.setItemDelegate(ItemDelegate()) self.mapper.setModel(self.table_model) self.skill_id_value.setModel(self.skill_model) self.import_export_manager = ImportExportManager(self.weapon_tree_view) self.import_export_manager.connect_custom_context_menu() mappings = [ (self.id_value, WpDatEntry.id.index, b"text"), (self.name_value, WpDatEntry.gmd_name_index.index, b"text"), (self.description_value, WpDatEntry.gmd_description_index.index, b"text"), (self.order_value, WpDatEntry.order.index), (self.tree_id_value, WpDatEntry.tree_id.index), (self.tree_position_value, WpDatEntry.tree_position.index), (self.is_fixed_upgrade_value, WpDatEntry.is_fixed_upgrade.index, b"checked"), (self.base_model_id_value, WpDatEntry.base_model_id.index), (self.part1_id_value, WpDatEntry.part1_id.index), (self.part2_id_value, WpDatEntry.part2_id.index), (self.color_value, WpDatEntry.color.index), (self.rarity_value, WpDatEntry.rarity.index), (self.cost_value, WpDatEntry.crafting_cost.index), (self.raw_damage_value, WpDatEntry.raw_damage.index), (self.affinity_value, WpDatEntry.affinity.index), (self.defense_value, WpDatEntry.defense.index), (self.handicraft_value, WpDatEntry.handicraft.index, b"currentIndex"), (self.element_id_value, WpDatEntry.element_id.index, b"currentIndex"), (self.element_damage_value, WpDatEntry.element_damage.index), (self.hidden_element_id_value, WpDatEntry.hidden_element_id.index, b"currentIndex"), (self.hidden_element_damage_value, WpDatEntry.hidden_element_damage.index), (self.elderseal_value, WpDatEntry.elderseal.index, b"currentIndex"), (self.num_gem_slots, WpDatEntry.num_gem_slots.index), (self.gem_slot1_lvl_value, WpDatEntry.gem_slot1_lvl.index), (self.gem_slot2_lvl_value, WpDatEntry.gem_slot2_lvl.index), (self.gem_slot3_lvl_value, WpDatEntry.gem_slot3_lvl.index), (self.skill_id_value, WpDatEntry.skill_id.index), (self.wep1_id_value, WpDatEntry.wep1_id.index), (self.wep2_id_value, WpDatEntry.wep2_id.index), (self.kire_widget, WpDatEntry.kire_id.index), ] for mapping in mappings: self.mapper.addMapping(*mapping) def handle_weapon_tree_view_activated(self, qindex: QModelIndex): self.mapper.setCurrentModelIndex(qindex) entry = self.table_model.entries[qindex.row()] self.crafting_requirements_editor.set_current(entry.id) def set_model(self, model): self.model = model self.skill_model.update(model.get_relation_data("t9n_skill_pt")) self.table_model.update(self.model) self.weapon_tree_view.setModel(self.table_model) self.crafting_requirements_editor.set_model(model, self.get_equip_type()) self.configure_tree_view() def configure_tree_view(self): for index, col in enumerate(self.table_model.columns): self.weapon_tree_view.hideColumn(index) self.weapon_tree_view.showColumn(WpDatEntry.id.index) self.weapon_tree_view.showColumn(WpDatEntry.gmd_name_index.index) header = self.weapon_tree_view.header() header.setSectionResizeMode(WpDatEntry.gmd_name_index.index, QHeaderView.Stretch) header.setSectionResizeMode(WpDatEntry.id.index, QHeaderView.ResizeToContents) def get_equip_type(self): return self.model.attrs.get("equip_type")
class MovieInfoView(QWidget): ID_DESC = 0 ID_CHECK = 1 ID_CTRL = 2 def __init__(self): super().__init__() self.initWidgets() self.mapWidget2Model() def initWidgets(self): from collections import OrderedDict self.controls = OrderedDict() self.controls['path'] = ['Path:', QLineEdit()] self.controls['title'] = ['Title:', QLineEdit()] self.controls['originaltitle'] = ['Original Title:', QLineEdit()] self.controls['rating'] = ['Rating:', RatingWidget()] self.controls['year'] = ['Year:', QLineEdit()] self.controls['releasedate'] = ['Release Date:', QLineEdit()] self.controls['id'] = ['ID:', QLineEdit()] self.controls['studio'] = ['Studio:', QLineEdit()] self.controls['set'] = ['Movie Set:', QLineEdit()] self.controls['plot'] = ['Plot:', QPlainTextEdit()] self.controls['genre'] = ['Genre:', GenreWidget()] self.controls['actor'] = ['Actor:', GenreWidget()] left = QGridLayout() row = 0 for _, ctrl in self.controls.items(): check = QCheckBox() check.stateChanged.connect(self.onChecked) ctrl.insert(self.ID_CHECK, check) left.addWidget(ctrl[self.ID_CHECK], row, 0, Qt.AlignTop | Qt.AlignRight) left.addWidget(QLabel(ctrl[self.ID_DESC]), row, 1, Qt.AlignTop | Qt.AlignRight) left.addWidget(ctrl[self.ID_CTRL], row, 2) row += 1 right = QVBoxLayout() self.poster = CoverWidget('poster') self.fanart = CoverWidget('fanart', False) right.addWidget(self.poster) right.addWidget(self.fanart) layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addLayout(left) layout.addLayout(right) self.setLayout(layout) def mapWidget2Model(self): self.mapper = QDataWidgetMapper(self) self.model = MovieInfoModel() self.mapper.setModel(self.model) index = 0 for key, ctrl in self.controls.items(): if 'genre' == key or 'actor' == key or 'rating' == key: self.mapper.addMapping(ctrl[self.ID_CTRL], index, b'Value') else: self.mapper.addMapping(ctrl[self.ID_CTRL], index) index += 1 self.mapper.addMapping(self.poster, index) index += 1 self.mapper.addMapping(self.fanart, index) self.mapper.setItemDelegate(MovieInfoDelegate()) def onChecked(self, state): columnFilter = [] for key, val in self.controls.items(): if val[self.ID_CHECK].isChecked(): columnFilter.append(key) self.model.setColumnFilter(columnFilter) def setMovieInfo(self, movieinfo, bypassFilter): if not movieinfo: return self.model.setMovieInfo(movieinfo, bypassFilter) self.mapper.toFirst() def clearMovieInfo(self, forceClear=True, keepColumnFilter=False): self.model.clearMovieInfo(forceClear, keepColumnFilter) if not keepColumnFilter: for _, val in self.controls.items(): val[self.ID_CHECK].setCheckState(Qt.Unchecked) self.mapper.toFirst() def saveMovieInfo(self): import traceback #print('updateMovie') try: self.model.saveMovieInfo() except: traceback.print_exc()
class APISFilm(QDialog, FORM_CLASS): FIRST, PREV, NEXT, LAST = range(4) OBLIQUE, VERTICAL = range(2) def __init__(self, iface, dbm, imageRegistry, apisLayer, parent=None): """Constructor.""" super(APISFilm, self).__init__(parent) self.iface = iface self.dbm = dbm self.imageRegistry = imageRegistry self.apisLayer = apisLayer self.parent = parent self.setupUi(self) # Initial window size/pos last saved. Use default values for first time if GetWindowSize("film"): self.resize(GetWindowSize("film")) if GetWindowPos("film"): self.move(GetWindowPos("film")) self.printingOptionsDlg = None self.settings = QSettings(QSettings().value("APIS/config_ini"), QSettings.IniFormat) self.editMode = False self.addMode = False self.initalLoad = True #self.uiInitalEntryQgsDate.setCalendarPopup(False) #self.uiLastChangesQgsDate.setCalendarPopup(False) # Signals/Slot Connections self.rejected.connect(self.onReject) self.uiOkBtn.clicked.connect(self.onAccept) self.uiCancelBtn.clicked.connect(self.cancelEdit) self.uiSaveBtn.clicked.connect(self.saveEdits) self.uiFilmSelectionBtn.clicked.connect(self.openFilmSelectionDialog) self.uiNewFilmBtn.clicked.connect(self.openNewFilmDialog) self.uiSearchFilmBtn.clicked.connect(self.openSearchFilmDialog) self.uiEditWeatherBtn.clicked.connect(self.openEditWeatherDialog) self.uiExportPdfBtn.clicked.connect(self.exportDetailsPdf) self.uiShowFlightPathBtn.clicked.connect(lambda: self.openFlightPathDialog([self.uiCurrentFilmNumberEdit.text()])) # For LaLe Mode if self.settings.value("APIS/disable_site_and_findspot", "0") != "1": self.uiListSitesOfFilmBtn.setEnabled(True) self.uiListSitesOfFilmBtn.clicked.connect(self.openSiteSelectionListDialog) else: self.uiListSitesOfFilmBtn.setEnabled(False) self.uiListImagesOfFilmBtn.clicked.connect(self.openImageSelectionListDialog) self.uiExtractGpsFromImagesBtn.clicked.connect(self.extractGpsFromImages) self.uiWeatherCodeEdit.textChanged.connect(self.generateWeatherCode) self.uiFilmModeCombo.currentIndexChanged.connect(self.onFilmModeChanged) self.uiEditProjectTableBtn.clicked.connect(lambda: self.openSystemTableEditorDialog("projekt", self.uiProjectSelectionCombo)) self.uiEditCopyrightTableBtn.clicked.connect(lambda: self.openSystemTableEditorDialog("copyright", self.uiCopyrightCombo)) # self.uiEditProjectTableBtn.clicked.connect(lambda: VersionToCome()) # self.uiEditCopyrightTableBtn.clicked.connect(lambda: VersionToCome()) # init Project Btn self.uiAddProjectBtn.clicked.connect(self.addProject) self.uiRemoveProjectBtn.clicked.connect(self.removeProject) # Setup Sub-Dialogs self.filmSelectionDlg = APISFilmNumberSelection(self) self.newFilmDlg = APISFilmNew(parent=self) self.searchFilmDlg = APISFilmSearch(self.dbm, self) # (self.iface, self.dbm) self.editWeatherDlg = APISWeather(self.iface, self.dbm, self) self.flightPathDlg = APISFlightPath(self.iface, self.dbm, self.apisLayer, self) self.siteSelectionListDlg = APISSiteSelectionList(self.iface, self.dbm, self.imageRegistry, self.apisLayer, self) self.imageSelectionListDlg = APISImageSelectionList(self.iface, self.dbm, self.imageRegistry, self.apisLayer, parent=self) self.systemTableEditorDlg = None # Setup film model self.model = QSqlRelationalTableModel(self, self.dbm.db) self.model.setTable("film") self.model.select() while (self.model.canFetchMore()): self.model.fetchMore() self.setupMapper() self.setupComboBox(self.uiProjectSelectionCombo, "projekt", 0, None) self.setupComboBox(self.newFilmDlg.uiProducerCombo, "hersteller", 2, None) self.setupNavigation() self.mapper.toFirst() self.initalLoad = False def setupMapper(self): self.mapper = QDataWidgetMapper(self) self.mapper.currentIndexChanged.connect(self.onCurrentIndexChanged) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.setItemDelegate(FilmDelegate()) self.mapper.setModel(self.model) self.mandatoryEditors = [self.uiImageCountEdit, self.uiCameraCombo, self.uiFilmMakeCombo, self.uiFilmModeCombo] self.disableEditorsIfOblique = [self.uiCameraNumberEdit, self.uiCalibratedFocalLengthEdit] # LineEdits & PlainTextEdits self.intValidator = QIntValidator() self.doubleValidator = QDoubleValidator() self.lineEditMaps = { "filmnummer": { "editor": self.uiCurrentFilmNumberEdit }, "hersteller": { "editor": self.uiProducerEdit }, "anzahl_bilder": { "editor": self.uiImageCountEdit, "validator": self.intValidator }, "militaernummer": { "editor": self.uiMilitaryNumberEdit }, "militaernummer_alt": { "editor": self.uiOldMilitaryNumberEdit }, "form1": { "editor": self.uiFormat1Edit }, "form2": { "editor": self.uiFormat2Edit }, "kalibrierungsnummer": { "editor": self.uiCameraNumberEdit }, "kammerkonstante": { "editor": self.uiCalibratedFocalLengthEdit, "validator": self.doubleValidator }, "kassettennummer": { "editor": self.uiCassetteEdit }, "art_ausarbeitung": { "editor": self.uiFilmMakeEdit }, "fotograf": { "editor": self.uiPhotographerEdit }, "pilot": { "editor": self.uiPilotEdit }, "flugzeug": { "editor": self.uiAirplaneEdit }, "abflug_flughafen": { "editor": self.uiDepartureAirportEdit }, "ankunft_flughafen": { "editor": self.uiArrivalAirportEdit }, "flugzeit": { "editor": self.uiFlightDurationEdit }, "wetter": { "editor": self.uiWeatherCodeEdit }, "kommentar": { "editor": self.uiCommentsPTxt } } for key, item in self.lineEditMaps.items(): self.mapper.addMapping(item["editor"], self.model.fieldIndex(key)) if "validator" in item: item["editor"].setValidator(item["validator"]) #item["editor"].textChanged.connect(partial(self.onLineEditChanged, item["editor"])) item["editor"].textChanged.connect(self.onLineEditChanged) #Text #self.mapper.addMapping(self.uiCommentsPTxt, self.model.fieldIndex("kommentar")) # Date and Times self.mapper.addMapping(self.uiFlightDate, self.model.fieldIndex("flugdatum")) #self.mapper.addMapping(self.uiFlightQgsDate, self.model.fieldIndex("flugdatum")) self.mapper.addMapping(self.uiInitalEntryDate, self.model.fieldIndex("datum_ersteintrag")) #self.mapper.addMapping(self.uiInitalEntryQgsDate, self.model.fieldIndex("datum_ersteintrag")) self.mapper.addMapping(self.uiLastChangesDate, self.model.fieldIndex("datum_aenderung")) #self.mapper.addMapping(self.uiLastChangesQgsDate, self.model.fieldIndex("datum_aenderung")) self.mapper.addMapping(self.uiDepartureTime, self.model.fieldIndex("abflug_zeit")) self.mapper.addMapping(self.uiArrivalTime, self.model.fieldIndex("ankunft_zeit")) self.uiDepartureTime.timeChanged.connect(self.onFlightTimeChanged) self.uiArrivalTime.timeChanged.connect(self.onFlightTimeChanged) # ComboBox without Model self.mapper.addMapping(self.uiFilmModeCombo, self.model.fieldIndex("weise")) self.uiFilmModeCombo.editTextChanged.connect(self.onLineEditChanged) completer = QCompleter(self.uiFilmModeCombo.model()) self.uiFilmModeCombo.setCompleter(completer) self.uiFilmModeCombo.lineEdit().setValidator(InListValidator([self.uiFilmModeCombo.itemText(i) for i in range(self.uiFilmModeCombo.count())], self.uiFilmModeCombo.lineEdit(), None, self)) # ComboBox with Model self.comboBoxMaps = { "archiv": { "editor": self.uiArchiveCombo, "table": "hersteller", "modelcolumn": 2, "depend": None }, "kamera": { "editor": self.uiCameraCombo, "table": "kamera", "modelcolumn": 0, "depend": [{"form1": self.uiFormat1Edit}, {"form2": self.uiFormat2Edit}] }, "filmfabrikat": { "editor": self.uiFilmMakeCombo, "table": "film_fabrikat", "modelcolumn": 0, "depend": [{"art": self.uiFilmMakeEdit}] }, "target": { "editor": self.uiTargetCombo, "table": "target", "modelcolumn": 0, "depend": None }, "copyright": { "editor": self.uiCopyrightCombo, "table": "copyright", "modelcolumn": 0, "depend": None } } for key, item in self.comboBoxMaps.items(): self.mapper.addMapping(item["editor"], self.model.fieldIndex(key)) self.setupComboBox(item["editor"], item["table"], item["modelcolumn"], item["depend"]) item["editor"].editTextChanged.connect(self.onLineEditChanged) self.mapper.addMapping(self.uiProjectList, self.model.fieldIndex("projekt")) def fixComboBoxDropDownListSizeAdjustemnt(self, cb): scroll = 0 if cb.count() <= cb.maxVisibleItems() else QApplication.style().pixelMetric(QStyle.PM_ScrollBarExtent) iconWidth = cb.iconSize().width() max = 0 for i in range(cb.count()): width = cb.view().fontMetrics().width(cb.itemText(i)) if max < width: max = width QMessageBox.information(self, "info", "scroll: {0}, max: {1}, icon: {2}".format(scroll, max, iconWidth)) #cb.view().setMinimumWidth(scroll + max) def setupComboBox(self, editor, table, modelColumn, depend): model = QSqlRelationalTableModel(self, self.dbm.db) model.setTable(table) model.removeColumn(0) model.select() tv = QTableView() editor.setView(tv) tv.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) tv.setSelectionMode(QAbstractItemView.SingleSelection) tv.setSelectionBehavior(QAbstractItemView.SelectRows) tv.setAutoScroll(False) editor.setModel(model) editor.setModelColumn(modelColumn) editor.setInsertPolicy(QComboBox.NoInsert) tv.resizeColumnsToContents() tv.resizeRowsToContents() tv.verticalHeader().setVisible(False) tv.horizontalHeader().setVisible(True) #tv.setMinimumWidth(tv.horizontalHeader().length()) tv.horizontalHeader().setStretchLastSection(True) #tv.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) tv.resizeColumnsToContents() scroll = 0 if editor.count() <= editor.maxVisibleItems() else QApplication.style().pixelMetric(QStyle.PM_ScrollBarExtent) tv.setMinimumWidth(tv.horizontalHeader().length() + scroll) #self.fixComboBoxDropDownListSizeAdjustemnt(editor) #editor.resize(tv.horizontalHeader().sizeHint()) completer = QCompleter(editor.model()) editor.setCompleter(completer) #editor.setAutoCompletion(True) editor.lineEdit().setValidator(InListValidator([editor.itemText(i) for i in range(editor.count())], editor.lineEdit(), depend, self)) if depend: editor.currentIndexChanged.connect(partial(self.updateDepends, editor, depend)) def updateDepends(self, editor, depend): for dep in depend: for key, value in dep.items(): idx = editor.model().createIndex(editor.currentIndex(), editor.model().fieldIndex(key)) value.setText(str(editor.model().data(idx))) #QMessageBox.warning(None, "Test", str(idx)) def setupNavigation(self): self.uiFirstFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.FIRST)) self.uiPreviousFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.PREV)) self.uiNextFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.NEXT)) self.uiLastFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.LAST)) self.uiTotalFilmCountLbl.setText(str(self.model.rowCount())) self.intRecordValidator = QIntValidator(1, self.model.rowCount()) self.uiCurrentFilmCountEdit.setValidator(self.intRecordValidator) self.uiCurrentFilmCountEdit.setText(str(self.mapper.currentIndex() + 1)) self.uiCurrentFilmCountEdit.editingFinished.connect(lambda: self.loadRecordById(int(self.uiCurrentFilmCountEdit.text()) - 1)) # QMessageBox.warning(None, "Test", str(self.mapper.itemDelegate())) def enableItemsInLayout(self, layout, enable): for i in range(layout.count()): if layout.itemAt(i).widget(): layout.itemAt(i).widget().setEnabled(enable) def loadRecordByNavigation(self, mode): #self.mapper.submit() #self.submitChanges() self.initalLoad = True if mode == APISFilm.FIRST: self.mapper.toFirst() elif mode == APISFilm.PREV: self.mapper.toPrevious() elif mode == APISFilm.NEXT: self.mapper.toNext() elif mode == APISFilm.LAST: self.mapper.toLast() self.initalLoad = False def loadRecordById(self, id): #self.submitChanges self.initalLoad = True self.mapper.setCurrentIndex(id) self.initalLoad = False def loadRecordByKeyAttribute(self, attribute, value): #self.model.setFilter(attribute + " = '" + value + "'") #self.model.select() # self.mapper.toFirst() query = QSqlQuery(self.dbm.db) #qryStr = "select {0} from film where {0} = '{1}' limit 1".format(attribute, value) #qryStr = "SELECT rowid FROM film WHERE {0} = '{1}' limit 1".format(attribute, value) qryStr = "SELECT" \ " (SELECT COUNT(*)" \ " FROM film AS t2" \ " WHERE t2.rowid < t1.rowid" \ " ) + (" \ " SELECT COUNT(*)" \ " FROM film AS t3" \ " WHERE t3.rowid = t1.rowid AND t3.rowid < t1.rowid" \ " ) AS rowNum" \ " FROM film AS t1" \ " WHERE {0} = '{1}'" \ " ORDER BY t1.rowid ASC".format(attribute, value) query.exec_(qryStr) #QMessageBox.warning(None, "Test", str(query.size()) + ',' + str(query.numRowsAffected())) query.first() fn = query.value(0) if fn is not None: self.loadRecordById(fn) return True else: # Film does not exist QMessageBox.warning(None, "Film Nummer", str("Der Film mit der Nummer {0} existiert nicht!".format(value))) return False #self.model.setFilter('') #self.model.select() #while (self.model.canFetchMore()): #self.model.fetchMore() def submitChanges(self): self.mapper.submit() def onCurrentIndexChanged(self): self.uiCurrentFilmCountEdit.setText(str(self.mapper.currentIndex() + 1)) self.onFilmModeChanged() def onFlightTimeChanged(self): dTime = self.uiDepartureTime.time() aTime = self.uiArrivalTime.time() flightDuration = dTime.secsTo(aTime) self.uiFlightDurationEdit.setText(str(flightDuration / 60)) def disableIfOblique(self, isOblique): for editor in self.disableEditorsIfOblique: editor.setDisabled(isOblique) def onFilmModeChanged(self): if self.uiFilmModeCombo.currentText() == u'schräg': self.disableIfOblique(True) else: self.disableIfOblique(False) def onLineEditChanged(self): sender = self.sender() if not self.editMode and not self.initalLoad: self.startEditMode() if not self.initalLoad: sender.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(sender.metaObject().className())) self.editorsEdited.append(sender) def onComboBoxChanged(self, editor): pass def addProject(self): editor = self.uiProjectList value = self.uiProjectSelectionCombo.currentText() notInList = True for row in range(editor.count()): if value == editor.item(row).data(0): notInList = False break if notInList: editor.addItem(value) editor.sortItems() if not self.editMode and not self.initalLoad: self.startEditMode() if not self.initalLoad: editor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(editor.metaObject().className())) self.editorsEdited.append(editor) def removeProject(self): editor = self.uiProjectList editor.takeItem(self.uiProjectList.currentRow()) if not self.editMode and not self.initalLoad: self.startEditMode() if not self.initalLoad: editor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(editor.metaObject().className())) self.editorsEdited.append(editor) def onAccept(self): ''' Check DB Save options when pressing OK button Update Plugin Status ''' self.accept() def onReject(self): ''' Run some actions when the user closes the dialog ''' if self.editMode: res = self.cancelEdit() if res: self.close() else: self.show() else: self.close() def closeEvent(self, e): # Write window size and position to QSettings if self.editMode: self.onReject() else: SetWindowSizeAndPos("film", self.size(), self.pos()) e.accept() def extractGpsFromImages(self): key = self.uiCurrentFilmNumberEdit.text() e2p = Exif2Points(self.iface, key) layer = e2p.run() if layer: self.apisLayer.requestShapeFile(layer, groupName="Flugwege", addToCanvas=True) def exportDetailsPdf(self): if self.printingOptionsDlg is None: self.printingOptionsDlg = APISPrintingOptions(self) self.printingOptionsDlg.setWindowTitle("Druck Optionen: Film") self.printingOptionsDlg.configure(False, False, visPersonalDataChk=True) self.printingOptionsDlg.show() if self.printingOptionsDlg.exec_(): printPersonalData = self.printingOptionsDlg.printPersonalData() APISPrinterQueue([{'type': APISTemplatePrinter.FILM, 'idList': [self.uiCurrentFilmNumberEdit.text()], 'options': {'personalData': printPersonalData}}], OutputMode.MergeNone, openFile=self.printingOptionsDlg.uiOpenFilesChk.isChecked(), openFolder=self.printingOptionsDlg.uiOpenFolderChk.isChecked(), dbm=self.dbm, parent=self) def openSearchFilmDialog(self): """Run method that performs all the real work""" # show the dialog self.searchFilmDlg.show() #self.filmSelectionDlg.uiFilmNumberEdit.setFocus() # Run the dialog event loop and See if OK was pressed if self.searchFilmDlg.exec_(): # QMessageBox.warning(None, "FilmNumber", self.searchFilmDlg.generateSearchQuery()) model = QSqlRelationalTableModel(self, self.dbm.db) model.setTable("film") searchMode, searchFilter = self.searchFilmDlg.generateSearchFilter() # QMessageBox.information(self, "info", searchFilter) model.setFilter(searchFilter) model.select() rc = model.rowCount() while (model.canFetchMore()): model.fetchMore() rc = model.rowCount() query = QSqlQuery(self.dbm.db) searchQuery = "select filmnummer, substr(filmnummer, 3, 8) as 'ohne_hersteller', flugdatum, anzahl_bilder, weise, art_ausarbeitung, militaernummer, militaernummer_alt from film where {0}".format(searchFilter) query.exec_(searchQuery) querySize = 0 while(query.next()): querySize += 1 query.seek(-1) # if model.rowCount(): if querySize > 0: # open film selection list dialog searchListDlg = APISFilmSelectionList(self.iface, model, self.dbm, self.imageRegistry, parent=self) searchListDlg.uiFilmCountLbl.setText(str(rc)) searchListDlg.uiFilmCountDescriptionLbl.setText(u"Film gefunden" if model.rowCount() == 1 else u"Filme gefunden") searchListDlg.uiFilmSearchModeLbl.setText(searchMode) res = searchListDlg.loadFilmListBySqlQuery(query) if res and searchListDlg.exec_(): #QMessageBox.warning(None, "FilmNumber", unicode(searchListDlg.filmNumberToLoad)) self.loadRecordByKeyAttribute("filmnummer", searchListDlg.filmNumberToLoad) else: QMessageBox.warning(self, u"Film Suche", u"Keine Ergebnisse mit den angegebenen Suchkriterien.") self.openSearchFilmDialog() #QMessageBox.warning(None, "FilmNumber", u"{0}, rows: {1}".format(self.searchFilmDlg.generateSearchQuery(), model.rowCount())) # Get Search String/Query #if not self.loadRecordByKeyAttribute("filmnummer", self.filmSelectionDlg.filmNumber()): #self.openFilmSelectionDialog() def openFilmSelectionDialog(self): """Run method that performs all the real work""" self.filmSelectionDlg.show() self.filmSelectionDlg.uiFilmNumberEdit.setFocus() if self.filmSelectionDlg.exec_(): if not self.loadRecordByKeyAttribute("filmnummer", self.filmSelectionDlg.filmNumber()): self.openFilmSelectionDialog() def openNewFilmDialog(self): """Run method that performs all the real work""" self.newFilmDlg.show() if self.newFilmDlg.exec_(): self.addNewFilm(self.newFilmDlg.flightDate(), self.newFilmDlg.useLastEntry(), self.newFilmDlg.producer(), self.newFilmDlg.producerCode()) def openEditWeatherDialog(self): self.editWeatherDlg.setWeatherCode(self.uiWeatherCodeEdit.text()) self.editWeatherDlg.show() if self.editWeatherDlg.exec_(): self.uiWeatherCodeEdit.setText(self.editWeatherDlg.weatherCode()) #self.uiWeatherPTxt.setPlainText(self.editWeatherDlg.weatherDescription()) def generateWeatherCode(self): weatherDescription = self._generateWeatherCode(self.uiWeatherCodeEdit.text()) self.uiWeatherPTxt.setPlainText(weatherDescription) def _generateWeatherCode(self, weatherCode): categories = ["Low Cloud Amount", "Visibility Kilometres", "Low Cloud Height", "Weather", "Remarks Mission", "Remarks Weather"] query = QSqlQuery(self.dbm.db) pos = 0 help = 0 weatherDescription = "" for c in weatherCode: qryStr = "select description from wetter where category = '{0}' and code = '{1}' limit 1".format(categories[pos - help], c) query.exec_(qryStr) query.first() fn = query.value(0) if pos <= 5: weatherDescription += categories[pos] + ': ' + fn if pos < 5: weatherDescription += '\n' else: weatherDescription += '; ' + fn if pos >= 5: help += 1 pos += 1 return weatherDescription def openSystemTableEditorDialog(self, table, updateEditor): if self.dbm: self.systemTableEditorDlg = APISAdvancedInputDialog(self.dbm, table, False, parent=self) if self.systemTableEditorDlg.tableExists: if self.systemTableEditorDlg.exec_(): # See if OK was pressed # rec = self.systemTableEditorDlg.getRecord() # Update updateEditor # self.setupComboBox(self.uiProjectSelectionCombo, "projekt", 0, None) self.updateComboBox(updateEditor) else: QMessageBox.warning(self, "Tabelle nicht vorhanden", "Die Tabelle {0} ist in der APIS Datenbank nicht vorhanden".format(table)) else: QMessageBox.warning(self, "Warning Database", "Die APIS Datenbank konnte nicht gefunden werden.") def updateComboBox(self, updateEditor): updateEditor.model().select() tv = updateEditor.view() tv.resizeRowsToContents() tv.resizeColumnsToContents() scroll = 0 if updateEditor.count() <= updateEditor.maxVisibleItems() else QApplication.style().pixelMetric( QStyle.PM_ScrollBarExtent) tv.setMinimumWidth(tv.horizontalHeader().length() + scroll) updateEditor.setCurrentIndex(updateEditor.count() - 1) if updateEditor.validator(): updateEditor.lineEdit().setValidator( InListValidator([updateEditor.itemText(i) for i in range(updateEditor.count())], updateEditor.lineEdit(), None, self)) def openFlightPathDialog(self, filmList, toClose=None): self.flightPathDlg.viewFilms(filmList) # DEBUG self.flightPathDlg.show() if self.flightPathDlg.exec_(): #TODO load Data in TOC, Close Windows if toClose: toClose.close() self.close() def openSiteSelectionListDialog(self): if self.uiFilmModeCombo.currentIndex() == APISFilm.VERTICAL: fromTable = "luftbild_senk_fp" elif self.uiFilmModeCombo.currentIndex() == APISFilm.OBLIQUE: fromTable = "luftbild_schraeg_fp" query = QSqlQuery(self.dbm.db) query.prepare("SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer IN (SELECT DISTINCT fo.fundortnummer FROM fundort fo, {0} WHERE fo.geometry IS NOT NULL AND {0}.geometry IS NOT NULL AND {0}.filmnummer = '{1}' AND Intersects({0}.geometry, fo.geometry) AND fo.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundort' AND search_frame = {0}.geometry)) ORDER BY katastralgemeindenummer, land, fundortnummer_nn".format(fromTable, self.uiCurrentFilmNumberEdit.text())) query.exec_() info = u"gefunden, die vom Film {0} abgedeckt/geschnitten werden.".format(self.uiCurrentFilmNumberEdit.text()) res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query, info) if res: self.siteSelectionListDlg.show() if self.siteSelectionListDlg.exec_(): pass def openImageSelectionListDialog(self): if self.uiFilmModeCombo.currentIndex() == APISFilm.VERTICAL: fromTable = 'luftbild_senk_cp' spatialIndicator = 'massstab' elif self.uiFilmModeCombo.currentIndex() == APISFilm.OBLIQUE: fromTable = 'luftbild_schraeg_cp' spatialIndicator = 'radius' query = QSqlQuery(self.dbm.db) query.prepare("SELECT cp.bildnummer AS bildnummer, cp.filmnummer AS filmnummer, cp.{2} AS mst_radius, f.weise AS weise, f.art_ausarbeitung AS art FROM {0} AS cp, film AS f WHERE cp.filmnummer = '{1}' AND f.filmnummer = '{1}'".format(fromTable, self.uiCurrentFilmNumberEdit.text(), spatialIndicator)) query.exec_() res = self.imageSelectionListDlg.loadImageListBySqlQuery(query) if res: self.imageSelectionListDlg.show() if self.imageSelectionListDlg.exec_(): pass def addNewFilm(self, flightDate, useLastEntry, producer, producerCode): self.initalLoad = True self.addMode = True self.startEditMode() row = self.model.rowCount() self.mapper.submit() while (self.model.canFetchMore()): self.model.fetchMore() self.model.insertRow(row) if useLastEntry: #copy last row for c in range(1, self.model.columnCount()): value = self.model.data(self.model.createIndex(row - 1, c)) self.model.setData(self.model.createIndex(row, c), value) editor = self.mapper.mappedWidgetAt(c) if editor and not (value == 'NULL' or value == ''): cName = editor.metaObject().className() if (cName == "QLineEdit" or cName == "QDateEdit") and editor.isReadOnly(): pass else: editor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(editor.metaObject().className())) self.editorsEdited.append(editor) self.mapper.setCurrentIndex(row) self.uiTotalFilmCountLbl.setText(str(self.model.rowCount())) self.uiFlightDate.setDate(flightDate) #self.uiFlightQgsDate.setDate(flightDate) self.uiProducerEdit.setText(producer) self.uiArchiveCombo.lineEdit().setText(producer) if not useLastEntry: self.uiWeatherCodeEdit.setText("9990X") #now = QDateTime.currentDateTime() now = QDate.currentDate() self.uiInitalEntryDate.setDate(now) #self.uiInitalEntryQgsDate.setDateTime(now) self.uiLastChangesDate.setDate(now) #self.uiLastChangesQgsDate.setDateTime(now) self.uiFilmModeCombo.setEnabled(True) #Filmnummer hh = producerCode yyyy = flightDate.toString("yyyy") mm = flightDate.toString("MM") query = QSqlQuery(self.dbm.db) qryStr = "select max(filmnummer_nn) from film where filmnummer_hh_jjjj_mm = '{0}{1}{2}' limit 1".format(hh, yyyy, mm) query.exec_(qryStr) query.first() fn = query.value(0) if isinstance(fn, int): nn = str(fn + 1).zfill(2) else: nn = "01" self.uiCurrentFilmNumberEdit.setText("{0}{1}{2}{3}".format(hh, yyyy, mm, nn)) self.initalLoad = False def removeNewFilm(self): self.initalLoad = True row = self.mapper.currentIndex() self.model.removeRow(row) self.model.submitAll() while (self.model.canFetchMore()): self.model.fetchMore() self.uiTotalFilmCountLbl.setText(str(self.model.rowCount())) self.mapper.toLast() self.initalLoad = False def saveEdits(self): # Check Mandatory fields flag = False for mEditor in self.mandatoryEditors: cName = mEditor.metaObject().className() if cName == 'QLineEdit': value = mEditor.text() elif cName == 'QComboBox': value = mEditor.lineEdit().text() if value.strip() == "": flag = True mEditor.setStyleSheet("{0} {{background-color: rgb(240, 160, 160);}}".format(cName)) if mEditor not in self.editorsEdited: self.editorsEdited.append(mEditor) else: if mEditor in self.editorsEdited: mEditor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(cName)) #else: #mEditor.setStyleSheet("") if flag: QMessageBox.warning(self, self.tr(u"Benötigte Felder Ausfüllen"), self.tr(u"Füllen Sie bitte alle Felder aus, die mit * gekennzeichnet sind.")) return False #saveToModel currIdx = self.mapper.currentIndex() #now = QDateTime.currentDateTime() now = QDate.currentDate() self.uiLastChangesDate.setDate(now) #self.uiLastChangesQgsDate.setDateTime(now) res = self.mapper.submit() if not res: sqlError = self.mapper.model().lastError() QMessageBox.information(self, "Submit", u"Error: {0}, {1}".format(res, sqlError.text())) while (self.model.canFetchMore()): self.model.fetchMore() self.mapper.setCurrentIndex(currIdx) self.endEditMode() return True def cancelEdit(self): if self.editMode: result = QMessageBox.question(self, self.tr(u"Änderungen wurden vorgenommen!"), self.tr(u"Möchten Sie die Änerungen speichern?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) #save or not save if result == QMessageBox.Yes: res = self.saveEdits() if res: return True else: return False elif result == QMessageBox.No: if self.addMode: self.removeNewFilm() self.mapper.setCurrentIndex(self.mapper.currentIndex()) self.endEditMode() return True def startEditMode(self): self.editMode = True self.enableItemsInLayout(self.uiTopHorizontalLayout, False) self.enableItemsInLayout(self.uiBottomHorizontalLayout, False) self.uiOkBtn.setEnabled(False) self.uiSaveBtn.setEnabled(True) self.uiCancelBtn.setEnabled(True) self.editorsEdited = [] def endEditMode(self): self.editMode = False self.addMode = False self.enableItemsInLayout(self.uiTopHorizontalLayout, True) self.enableItemsInLayout(self.uiBottomHorizontalLayout, True) self.uiOkBtn.setEnabled(True) self.uiSaveBtn.setEnabled(False) self.uiCancelBtn.setEnabled(False) for editor in self.editorsEdited: cName = editor.metaObject().className() if (cName == "QLineEdit" or cName == "QDateEdit") and editor.isReadOnly(): editor.setStyleSheet("{0} {{background-color: rgb(218, 218, 218);}}".format(cName)) else: editor.setStyleSheet("") self.editorsEdited = [] self.uiFilmModeCombo.setEnabled(False) def showEvent(self, evnt): # QMessageBox.information(self, "info", "db requires update: {0}".format(self.dbm.dbRequiresUpdate)) if self.dbm.dbRequiresUpdate: self.initalLoad = True for editor in [self.uiArchiveCombo, self.uiCameraCombo, self.uiFilmMakeCombo, self.uiCopyrightCombo, self.uiProjectSelectionCombo, self.newFilmDlg.uiProducerCombo]: self.updateComboBox(editor) currIdx = self.mapper.currentIndex() self.model.select() while (self.model.canFetchMore()): self.model.fetchMore() self.mapper.setCurrentIndex(currIdx) self.dbm.dbRequiresUpdate = False self.initalLoad = False
class APISSharding(QDialog, FORM_CLASS): shardingEditsSaved = pyqtSignal(bool) def __init__(self, iface, dbm, parent=None): """Constructor.""" super(APISSharding, self).__init__(parent) self.iface = iface self.dbm = dbm self.setupUi(self) # Initial window size/pos last saved. Use default values for first time if GetWindowSize("sharding"): self.resize(GetWindowSize("sharding")) self.settings = QSettings(QSettings().value("APIS/config_ini"), QSettings.IniFormat) self.editMode = False self.addMode = False self.initalLoad = True # Signals/Slot Connections self.rejected.connect(self.onReject) #self.uiButtonBox.rejected.connect(self.onReject) self.uiOkBtn.clicked.connect(self.onAccept) self.uiCancelBtn.clicked.connect(self.cancelEdit) self.uiSaveBtn.clicked.connect(self.saveEdits) mViewPictures = QMenu() aViewPicturesPreview = mViewPictures.addAction( QIcon( os.path.join(QSettings().value("APIS/plugin_dir"), 'ui', 'icons', 'image.png')), "in Vorschau") aViewPicturesPreview.triggered.connect(self.viewPictures) aViewPicturesFolder = mViewPictures.addAction( QIcon( os.path.join(QSettings().value("APIS/plugin_dir"), 'ui', 'icons', 'image.png')), "in Ordner") aViewPicturesFolder.triggered.connect(self.openPictures) self.uiViewPicturesTBtn.setMenu(mViewPictures) self.uiViewPicturesTBtn.clicked.connect( self.uiViewPicturesTBtn.showMenu) mViewSketches = QMenu() aViewSketchesPreview = mViewSketches.addAction( QIcon( os.path.join(QSettings().value("APIS/plugin_dir"), 'ui', 'icons', 'sketch.png')), "in Vorschau") aViewSketchesPreview.triggered.connect(self.viewSketches) aViewSketchesFolder = mViewSketches.addAction( QIcon( os.path.join(QSettings().value("APIS/plugin_dir"), 'ui', 'icons', 'sketch.png')), "in Ordner") aViewSketchesFolder.triggered.connect(self.openSketches) self.uiViewSketchesTBtn.setMenu(mViewSketches) self.uiViewSketchesTBtn.clicked.connect( self.uiViewSketchesTBtn.showMenu) self.initalLoad = False def openSharding(self, siteNumber, shardingNumber): self.initalLoad = True self.siteNumber = siteNumber self.shardingNumber = shardingNumber #QMessageBox.warning(None, self.tr(u"Neu"), self.tr(u"{0}, {1}".format(siteNumber, shardingNumber))) # Setup sharding model self.model = QSqlRelationalTableModel(self, self.dbm.db) self.model.setTable("begehung") self.model.setFilter("fundortnummer='{0}' AND begehung='{1}'".format( self.siteNumber, self.shardingNumber)) res = self.model.select() self.setupMapper() self.mapper.toFirst() self.setKgNameAndCode() self.initalLoad = False def setKgNameAndCode(self): query = QSqlQuery(self.dbm.db) qryStr = u"select CASE WHEN katastralgemeinde IS NULL AND katastralgemeindenummer IS NULL THEN '--' ELSE katastralgemeindenummer || ' - ' || katastralgemeinde END AS kg FROM fundort WHERE fundortnummer = '{0}'".format( self.siteNumber) query.exec_(qryStr) query.first() self.uiCadastralCommunityEdit.setText(query.value(0)) def setupMapper(self): self.mapper = QDataWidgetMapper(self) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.setItemDelegate(ShardingDelegate()) self.mapper.setModel(self.model) self.mandatoryEditors = [self.uiShardingDate] # LineEdits & PlainTextEdits self.intValidator = QIntValidator() self.doubleValidator = QDoubleValidator() self.lineEditMaps = { "fundortnummer": { "editor": self.uiSiteNumberEdit }, "begehung": { "editor": self.uiShardingNumberEdit }, "name": { "editor": self.uiNameEdit }, "parzelle": { "editor": self.uiPlotPTxt }, "sichtbarkeit": { "editor": self.uiVisibilityEdit }, "verbleib": { "editor": self.uiWhereaboutsEdit }, "funde": { "editor": self.uiFindsPTxt }, "morphologie": { "editor": self.uiMorphologyPTxt }, "sonstiges": { "editor": self.uiMiscellaneousPTxt } } for key, item in self.lineEditMaps.items(): self.mapper.addMapping(item["editor"], self.model.fieldIndex(key)) if "validator" in item: item["editor"].setValidator(item["validator"]) #item["editor"].textChanged.connect(partial(self.onLineEditChanged, item["editor"])) item["editor"].textChanged.connect(self.onLineEditChanged) # Date and Times self.mapper.addMapping(self.uiShardingDate, self.model.fieldIndex("datum")) # ComboBox without Model self.mapper.addMapping(self.uiShardingTypeCombo, self.model.fieldIndex("begehtyp")) self.uiShardingTypeCombo.editTextChanged.connect( self.onLineEditChanged) # FIXME Pyqt5 AutoCompletion #self.uiShardingTypeCombo.setAutoCompletion(True) self.uiShardingTypeCombo.lineEdit().setValidator( InListValidator([ self.uiShardingTypeCombo.itemText(i) for i in range(self.uiShardingTypeCombo.count()) ], self.uiShardingTypeCombo.lineEdit(), None, self)) # ComboBox without Model self.mapper.addMapping(self.uiConditionPlantCoverCombo, self.model.fieldIndex("zustand_bewuchs")) self.uiConditionPlantCoverCombo.editTextChanged.connect( self.onLineEditChanged) # FIXME Pyqt5 AutoCompletion #self.uiConditionPlantCoverCombo.setAutoCompletion(True) self.uiConditionPlantCoverCombo.lineEdit().setValidator( InListValidator([ self.uiConditionPlantCoverCombo.itemText(i) for i in range(self.uiConditionPlantCoverCombo.count()) ], self.uiConditionPlantCoverCombo.lineEdit(), None, self)) # ComboBox without Model self.mapper.addMapping(self.uiConditionLightCombo, self.model.fieldIndex("zustand_licht")) self.uiConditionLightCombo.editTextChanged.connect( self.onLineEditChanged) # FIXME Pyqt5 AutoCompletion #self.uiConditionLightCombo.setAutoCompletion(True) self.uiConditionLightCombo.lineEdit().setValidator( InListValidator([ self.uiConditionLightCombo.itemText(i) for i in range(self.uiConditionLightCombo.count()) ], self.uiConditionLightCombo.lineEdit(), None, self)) # ComboBox without Model self.mapper.addMapping(self.uiConditionSoilCombo, self.model.fieldIndex("zustand_boden")) self.uiConditionSoilCombo.editTextChanged.connect( self.onLineEditChanged) # FIXME Pyqt5 AutoCompletion #self.uiConditionSoilCombo.setAutoCompletion(True) self.uiConditionSoilCombo.lineEdit().setValidator( InListValidator([ self.uiConditionSoilCombo.itemText(i) for i in range(self.uiConditionSoilCombo.count()) ], self.uiConditionSoilCombo.lineEdit(), None, self)) # ComboBox without Model self.mapper.addMapping(self.uiConditionMoistureCombo, self.model.fieldIndex("zustand_feuchtigkeit")) self.uiConditionMoistureCombo.editTextChanged.connect( self.onLineEditChanged) # FIXME Pyqt5 AutoCompletion #self.uiConditionMoistureCombo.setAutoCompletion(True) self.uiConditionMoistureCombo.lineEdit().setValidator( InListValidator([ self.uiConditionMoistureCombo.itemText(i) for i in range(self.uiConditionMoistureCombo.count()) ], self.uiConditionMoistureCombo.lineEdit(), None, self)) # ComboBox without Model self.mapper.addMapping(self.uiConditionRainCombo, self.model.fieldIndex("zustand_abgeregnet")) self.uiConditionRainCombo.editTextChanged.connect( self.onLineEditChanged) # FIXME Pyqt5 AutoCompletion #self.uiConditionRainCombo.setAutoCompletion(True) self.uiConditionRainCombo.lineEdit().setValidator( InListValidator([ self.uiConditionRainCombo.itemText(i) for i in range(self.uiConditionRainCombo.count()) ], self.uiConditionRainCombo.lineEdit(), None, self)) def onLineEditChanged(self): sender = self.sender() if not self.editMode and not self.initalLoad: self.startEditMode() if not self.initalLoad: sender.setStyleSheet( "{0} {{background-color: rgb(153, 204, 255);}}".format( sender.metaObject().className())) self.editorsEdited.append(sender) def onAccept(self): ''' Check DB Save options when pressing OK button Update Plugin Status ''' # Save Settings SetWindowSize("sharding", self.size()) self.accept() def onReject(self): ''' Run some actions when the user closes the dialog ''' if self.editMode: res = self.cancelEdit() if res: SetWindowSize("sharding", self.size()) self.close() else: self.show() else: SetWindowSize("sharding", self.size()) self.close() def addNewSharding(self, siteNumber): self.initalLoad = True self.siteNumber = siteNumber # get new sharding number query = QSqlQuery(self.dbm.db) qryStr = "SELECT CASE WHEN max(begehung) IS NULL THEN 1 ELSE max(begehung)+1 END begehungNeu FROM begehung WHERE fundortnummer='{0}'".format( self.siteNumber) query.exec_(qryStr) query.first() self.shardingNumber = query.value(0) self.model = QSqlRelationalTableModel(self, self.dbm.db) self.model.setTable("begehung") self.model.setFilter("fundortnummer='{0}'".format(self.siteNumber)) res = self.model.select() #self.model.submitAll() while (self.model.canFetchMore()): self.model.fetchMore() row = self.model.rowCount() #QMessageBox.information(None, "begehung", "{0}".format(row)) self.model.insertRow(row) #QMessageBox.information(None, "begehung", "{0}".format(self.model.rowCount())) self.setupMapper() self.mapper.toLast() self.addMode = True self.startEditMode() # self.mapper.submit() # self.model.insertRow(row) # self.mapper.setCurrentIndex(row) self.uiSiteNumberEdit.setText(self.siteNumber) self.uiShardingNumberEdit.setText(str(self.shardingNumber)) now = QDate.currentDate() self.uiShardingDate.setDate(now) self.setKgNameAndCode() #QMessageBox.warning(None, self.tr(u"Neu"), self.tr(u"{0}, {1}".format(siteNumber,nn))) self.initalLoad = False def removeNewSharding(self): self.initalLoad = True row = self.mapper.currentIndex() self.model.removeRow(row + 1) self.model.submitAll() while (self.model.canFetchMore()): self.model.fetchMore() self.mapper.toLast() self.initalLoad = False def saveEdits(self): #Check Mandatory fields flag = False for mEditor in self.mandatoryEditors: cName = mEditor.metaObject().className() if cName == 'QDateEdit': value = mEditor.date().toString("yyyy-MM-dd") elif cName == 'QLineEdit': value = mEditor.text() elif cName == 'QComboBox': if mEditor.isEditable(): value = mEditor.lineEdit().text() else: if mEditor.currentIndex == -1: value = '' else: value = '1' if value.strip() == "": flag = True mEditor.setStyleSheet( "{0} {{background-color: rgb(240, 160, 160);}}".format( cName)) if mEditor not in self.editorsEdited: self.editorsEdited.append(mEditor) else: if mEditor in self.editorsEdited: mEditor.setStyleSheet( "{0} {{background-color: rgb(153, 204, 255);}}".format( cName)) #else: #mEditor.setStyleSheet("") if flag: QMessageBox.warning( self, self.tr(u"Benötigte Felder Ausfüllen"), self. tr(u"Füllen Sie bitte alle Felder aus, die mit * gekennzeichnet sind." )) return False #saveToModel currIdx = self.mapper.currentIndex() #QMessageBox.information(None, "begehung", "{0}".format(currIdx)) #now = QDate.currentDate() #self.uiLastChangesDate.setDate(now) self.mapper.submit() self.mapper.setCurrentIndex(currIdx) # emit signal self.shardingEditsSaved.emit(True) self.endEditMode() return True def cancelEdit(self): currIdx = self.mapper.currentIndex() if self.editMode: result = QMessageBox.question( self, self.tr(u"Änderungen wurden vorgenommen!"), self.tr(u"Möchten Sie die Änerungen speichern?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) #save or not save if result == QMessageBox.Yes: res = self.saveEdits() if res: return True else: return False elif result == QMessageBox.No: if self.addMode: #self.close() self.done(1) self.removeNewSharding() self.endEditMode() return True else: self.mapper.setCurrentIndex(currIdx) self.endEditMode() return True def startEditMode(self): self.editMode = True self.uiOkBtn.setEnabled(False) self.uiSaveBtn.setEnabled(True) self.uiCancelBtn.setEnabled(True) self.editorsEdited = [] self.uiShardingDate.setReadOnly(not self.addMode) if self.uiShardingDate.isReadOnly(): self.uiShardingDate.setStyleSheet( "background-color: rgb(218, 218, 218);") else: self.uiShardingDate.setStyleSheet("") def endEditMode(self): self.editMode = False self.addMode = False self.uiOkBtn.setEnabled(True) self.uiSaveBtn.setEnabled(False) self.uiCancelBtn.setEnabled(False) self.uiShardingDate.setReadOnly(not self.addMode) self.uiShardingDate.setStyleSheet( "background-color: rgb(218, 218, 218);") for editor in self.editorsEdited: cName = editor.metaObject().className() if (cName == "QLineEdit" or cName == "QDateEdit") and editor.isReadOnly(): editor.setStyleSheet( "{0} {{background-color: rgb(218, 218, 218);}}".format( cName)) else: editor.setStyleSheet("") self.editorsEdited = [] def viewPictures(self): dirName = self.settings.value("APIS/insp_image_dir") folderNameType = self.settings.value("APIS/insp_image_foto_dir") folderNameSite = self.getFolderNameSite(self.siteNumber) path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType self.loadInImageViewer(path) def openPictures(self): dirName = self.settings.value("APIS/insp_image_dir") folderNameType = self.settings.value("APIS/insp_image_foto_dir") folderNameSite = self.getFolderNameSite(self.siteNumber) path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType if not OpenFileOrFolder(path): QMessageBox.information( self, u"Begehung", u"Das Verzeichnis '{0}' wurde nicht gefunden.".format(path)) def viewSketches(self): dirName = self.settings.value("APIS/insp_image_dir") folderNameType = self.settings.value("APIS/insp_image_sketch_dir") folderNameSite = self.getFolderNameSite(self.siteNumber) path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType self.loadInImageViewer(path) def openSketches(self): dirName = self.settings.value("APIS/insp_image_dir") folderNameType = self.settings.value("APIS/insp_image_sketch_dir") folderNameSite = self.getFolderNameSite(self.siteNumber) path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType if not OpenFileOrFolder(path): QMessageBox.information( None, u"Begehung", u"Das Verzeichnis '{0}' wurde nicht gefunden.".format(path)) def getFolderNameSite(self, siteNumber): query = QSqlQuery(self.dbm.db) #qryStr = u"SELECT trim(katastralgemeinde) || ' ' || trim(katastralgemeindenummer) || '.' || substr('000' || fundortnummer_nn_legacy, -3, 3) AS folderName FROM fundort f WHERE f.fundortnummer='{0}'".format(siteNumber) query.prepare( u"SELECT land || '\\' || CASE WHEN land = 'AUT' THEN replace(replace(replace(replace(lower(trim(katastralgemeinde)), '.',''), '-', ' '), '(', ''), ')', '') || ' ' ELSE '' END || substr('000000' || fundortnummer_nn, -6, 6) AS folderName FROM fundort f WHERE f.fundortnummer='{0}'" .format(siteNumber)) query.exec_() query.first() return query.value(0) def loadInImageViewer(self, path): dir = QDir(path) if dir.exists(): entryList = dir.entryList(['*.jpg'], QDir.Files) if len(entryList) > 0: # load in thumb viewer # QMessageBox.information(None, u"Begehung", u",".join(entryList)) imagePathList = [] for image in entryList: imagePathList.append(path + u'\\' + image) widget = APISThumbViewer() widget.load(imagePathList) widget.show() if widget.exec_(): pass # app.exec_() else: QMessageBox.information( self, u"Begehung", u"Es wurden keine Dateien [*.jpg] für diesen Fundort gefunden." ) else: QMessageBox.information( self, u"Begehung", u"Das Verzeichnis '{0}' wurde nicht gefunden.".format(path))
class CraftingRequirementsEditor(QWidget): def __init__(self, parent=None): super().__init__(parent=parent) layout = QGridLayout(self) self.setLayout(layout) layout.setContentsMargins(0, 0, 0, 0) self.model = None self.equip_type = None self._map_equip_id_to_index = {} self.item_model = StructTableModel(EqCrtEntry.fields(), self) self.item_mapper = QDataWidgetMapper(self) self.item_mapper.setItemDelegate(ItemDelegate()) self.item_mapper.setModel(self.item_model) self.t9n_item_model = ItmTranslationModel(self) self.add_row(0, "Item", "Quantity") self.add_row_edit(1, EqCrtEntry.item1_id.index, EqCrtEntry.item1_qty.index) self.add_row_edit(2, EqCrtEntry.item2_id.index, EqCrtEntry.item2_qty.index) self.add_row_edit(3, EqCrtEntry.item3_id.index, EqCrtEntry.item3_qty.index) self.add_row_edit(4, EqCrtEntry.item4_id.index, EqCrtEntry.item4_qty.index) self.layout().setRowStretch(4, 1) def set_current(self, equip_id): if equip_id in self._map_equip_id_to_index: self.setDisabled(False) index = self._map_equip_id_to_index[equip_id] self.item_mapper.setCurrentIndex(index) else: self.setDisabled(True) def add_row(self, row, value1, value2): self.layout().addWidget(QLabel(value1), row, 0, Qt.AlignTop) self.layout().addWidget(QLabel(value2), row, 1, Qt.AlignTop) def add_row_edit(self, row, mapping1, mapping2): id_editor = QComboBox(self) id_editor.setModel(self.t9n_item_model) id_editor.setEditable(True) qty_editor = QSpinBox(self) qty_editor.setMinimum(0) qty_editor.setMaximum(0xff) self.item_mapper.addMapping(id_editor, mapping1) self.item_mapper.addMapping(qty_editor, mapping2) self.layout().addWidget(id_editor, row, 0, Qt.AlignTop) self.layout().addWidget(qty_editor, row, 1, Qt.AlignTop) def set_model(self, model, equip_type): self.model = model self.equip_type = equip_type if model is None: return crafting_model = model.get_relation_data("crafting") t9n_item_model = model.get_relation_data("t9n_item") if crafting_model: self.item_model.update(crafting_model.entries) self._map_equip_id_to_index = { entry.equip_id: index for index, entry in enumerate(crafting_model.entries) if not equip_type or equip_type == entry.equip_type } if t9n_item_model: self.t9n_item_model.update(t9n_item_model)
class EditForm(QWidget, Ui_EditForm): def __init__(self, current_index, model): super().__init__() # uic.loadUi('editForm.ui', self) self.setupUi(self) # self.db = database self.db_map = QDataWidgetMapper(self) self.db_map.setModel(model) self.db_map.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.db_map.addMapping(self.lineEdit_name, 1) self.db_map.addMapping(self.lineEdit_inv_number, 2) self.db_map.addMapping(self.textEdit_comments, 3) self.db_map.addMapping(self.checkBox_on_balance, model.fieldIndex('is_on_balance')) relModel_status = model.relationModel(5) self.comboBox_status.setModel(relModel_status) self.comboBox_status.setModelColumn( relModel_status.fieldIndex("status_name")) self.db_map.setItemDelegate(QSqlRelationalDelegate(self)) self.db_map.addMapping(self.comboBox_status, 5) relModel_type = model.relationModel(6) self.comboBox_type.setModel(relModel_type) self.comboBox_type.setModelColumn( relModel_type.fieldIndex("goods_type_name")) self.db_map.setItemDelegate(QSqlRelationalDelegate(self)) self.db_map.addMapping(self.comboBox_type, 6) relModel_subtype = model.relationModel(7) self.comboBox_subtype.setModel(relModel_subtype) self.comboBox_subtype.setModelColumn( relModel_subtype.fieldIndex("goods_subtype_name")) self.db_map.setItemDelegate(QSqlRelationalDelegate(self)) self.db_map.addMapping(self.comboBox_subtype, 7) relModel_location = model.relationModel(8) self.comboBox_location.setModel(relModel_location) self.comboBox_location.setModelColumn( relModel_location.fieldIndex("location_name")) self.db_map.setItemDelegate(QSqlRelationalDelegate(self)) self.db_map.addMapping(self.comboBox_location, 8) relModel_responsible = model.relationModel(9) self.comboBox_responsible.setModel(relModel_responsible) self.comboBox_responsible.setModelColumn( relModel_responsible.fieldIndex("FIO")) self.db_map.setItemDelegate(QSqlRelationalDelegate(self)) self.db_map.addMapping(self.comboBox_responsible, 9) self.pushBtn_save.clicked.connect(self.save_item) self.pushBtn_cancel.clicked.connect(self.cancel) self.pushBtn_next.clicked.connect(self.db_map.toNext) self.pushBtn_prev.clicked.connect(self.db_map.toPrevious) self.pushBtn_close.clicked.connect(self.close) self.db_map.setCurrentIndex(current_index.row()) def save_item(self): self.db_map.submit() def cancel(self): self.db_map.setCurrentIndex(self.db_map.currentIndex())