def setData(self, idx: QModelIndex, value, role: int = Qt.EditRole): if not idx.isValid() or idx.column() != 1: return False if role == Qt.EditRole: if Id.depth(idx) == Id.Depth.D1 and idx.parent().row( ) == Row.ZEditOptions and isBoolOption(idx.row()): setattr(self.mergeFile, MERGE_OPTIONS[idx.row()][0], value is True) self.dataChanged.emit(idx, idx, [role]) return True if Id.depth(idx) == Id.Depth.D0: if idx.row() == Row.ModName: self.mergeFile.name = value if value is not None else "" self.dataChanged.emit(idx, idx, [role]) return True elif idx.row() == Row.PluginName: self.mergeFile.filename = value if value is not None else "" self.dataChanged.emit(idx, idx, [role]) return True elif Id.depth(idx) == Id.Depth.D1 and idx.parent().row( ) == Row.ZEditOptions: if idx.row() == OptionRow.Method: if value in MergeFile.METHOD_VALUES: self.mergeFile.method = value self.dataChanged.emit(idx, idx, [role]) return True elif idx.row() == OptionRow.ArchiveAction: if value in MergeFile.ARCHIVEACTION_VALUES: self.mergeFile.archiveAction = value self.dataChanged.emit(idx, idx, [role]) return True return False
def rowCount(self, parent: QModelIndex = QModelIndex()): depth = Id.depth(parent) if depth == Id.Depth.Invalid: return len(self.__merges) elif depth == Id.Depth.D0: return len(self.__merges[parent.row()].plugins) return 0
def _tooltip_data(self, idx: QModelIndex): depth = Id.depth(idx) if depth == Id.Depth.D1 and idx.parent().row() == Row.MergedPlugins: dataFolder = self.mergeFile.plugins[idx.row()].dataFolder return '"{}"'.format(dataFolder) hash = getattr(self.mergeFile.plugins[idx.row()], "hash", "") return "<html><head/><body><p>folder: " + dataFolder + "</p><p>hash: " + hash + "</p></body></html>"
def data(self, idx: QModelIndex, role: int = Qt.DisplayRole): depth = Id.depth(idx) if depth == Id.Depth.Invalid: return if role == Role.Data: # return the top level plugin if depth == Id.Depth.D0: return self.sourcePlugin(idx.row()) if depth == Id.Depth.D1: return self.sourcePlugin(Id.row(idx.internalId())) if depth == Id.Depth.D2: return self.sourcePlugin(Id.row(Id.parentId(idx.internalId()))) if role == Role.MergeAssociations: if depth == Id.Depth.D0: return self.mergeAssociations(idx.row()) if depth == Id.Depth.D1: return self.mergeAssociations(Id.row(idx.internalId())) if depth == Id.Depth.D2: return self.mergeAssociations( Id.row(Id.parentId(idx.internalId()))) if role == Role.Cell: return self._display_data(idx) if not idx.parent().isValid(): return if role == Qt.DisplayRole: return self._display_data(idx) return self._style_data(idx, role)
def data(self, idx: QModelIndex, role: int = Qt.DisplayRole): depth = Id.depth(idx) if depth == Id.Depth.Invalid: return if depth == Id.Depth.D0: if role == Role.Data: return self.__merges[idx.row()] if role == Qt.DisplayRole: if idx.column() == Column.Name: if idx.row() == 0: return self.tr("-- New Merge --") return self.__merges[idx.row()].name elif idx.column() == Column.PluginCount: return self.rowCount(idx) elif role == Qt.ForegroundRole: if idx.column() == Column.PluginCount: return QColor(Qt.lightGray).darker() elif role == Qt.FontRole: if idx.row() == 0: font = QFont() font.setBold(True) return font elif role == Qt.DecorationRole: if idx.column() == Column.Active and idx.row() > 0: if not self.__merges[idx.row()].modIsActive: return QIcon(Icon.INACTIVE) if depth == Id.Depth.D1 and idx.column() == Column.Name: if role == Role.Data: return self.__merges[idx.parent().row()] if role == Qt.DisplayRole: return self.__merges[idx.parent().row()].plugins[idx.row()].filename if role == Qt.ForegroundRole: return QColor(Qt.lightGray).darker()
def onViewDoubleClicked(self, idx: QModelIndex): idx = self.infoModel().mapToSource(idx) if Id.depth(idx) == Id.Depth.D2: if idx.parent().row() == Row.MergedBy or idx.parent().row() == Row.MergedPlugins: name = self.infoModel().sourceModel().data(idx.siblingAtColumn(1)) if name: self.doubleClicked.emit(name)
def flags(self, idx: QModelIndex = QModelIndex()): depth = Id.depth(idx) if depth == Id.Depth.D0: return Qt.ItemIsSelectable | Qt.ItemIsEnabled elif depth == Id.Depth.D1: return Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemNeverHasChildren else: return Qt.NoItemFlags
def mapToSource(self, proxyIdx: QModelIndex = QModelIndex()): depth = Id.depth(proxyIdx) if depth == Id.Depth.Invalid: return QModelIndex() if depth == Id.Depth.D0: return self.sourceModel().index(proxyIdx.row(), PluginColumn.PluginName) return QModelIndex()
def lessThan(self, left: QModelIndex, right: QModelIndex): # This sorts the plugins alpabetically, leaves the mods order unchanged depth = Id.depth(left) if depth == Id.Depth.D0: return left.row() < right.row() return ( self.sourceModel().data(left.siblingAtColumn(Column.Name)).lower() < self.sourceModel().data(right.siblingAtColumn(Column.Name)).lower() )
def _display_data(self, idx: QModelIndex): depth = Id.depth(idx) if depth == Id.Depth.D0: if idx.column() == Column.Property: if idx.row() == Row.ModName: return self.tr("Mod Name: ") if idx.row() == Row.PluginName: return self.tr("Plugin Name: ") if idx.row() == Row.WhenBuilt: return self.tr("Built On: ") if idx.row() == Row.ZEditOptions: return self.tr("zMerge Options: ") if idx.row() == Row.LoadOrder: return self.tr("Load Order: ") if idx.row() == Row.MergedPlugins: return self.tr("Merged Plugins: ") elif idx.column() == Column.Value: if idx.row() == Row.ModName: return self.mergeFile.name if idx.row() == Row.PluginName: return self.mergeFile.filename if idx.row() == Row.WhenBuilt: return self.mergeFile.dateBuilt if idx.row() == Row.ZEditOptions: return self.tr("({})").format(len(MERGE_OPTIONS)) if idx.row() == Row.LoadOrder: return self.tr("({})").format(len( self.mergeFile.loadOrder)) if idx.row() == Row.MergedPlugins: return self.tr("({})").format(len(self.mergeFile.plugins)) elif depth == Id.Depth.D1: parentRow = idx.parent().row() if parentRow == Row.LoadOrder: if idx.column() == 0: return "{}".format(idx.row() + 1) elif idx.column() == 1: return self.mergeFile.loadOrder[idx.row()] elif parentRow == Row.MergedPlugins: if idx.column() == 0: return "{}".format(idx.row() + 1) elif idx.column() == 1: return self.mergeFile.plugins[idx.row()].filename elif idx.column() == 2: return self.mergeFile.plugins[idx.row()].dataFolder if idx.parent().row() == Row.ZEditOptions: if idx.column() == 0: return MERGE_OPTIONS[idx.row()][1] elif idx.column() == 1: value = getattr(self.mergeFile, MERGE_OPTIONS[idx.row()][0], None) if isinstance(value, bool): return "true" if value else "false" return value
def flags(self, idx: QModelIndex): depth = Id.depth(idx) if depth == Id.Depth.D0: if idx.column() == Column.Active: return Qt.ItemIsEnabled | Qt.ItemIsSelectable else: return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemNeverHasChildren if depth == Id.Depth.D1: return Qt.ItemNeverHasChildren return Qt.NoItemFlags
def mapToReqModel(self, dataType: DataType, idx: QModelIndex): depth = Id.depth(idx) if depth == Id.Depth.Invalid: return QModelIndex() reqModel = self.requiresModel if dataType == DataType.Requires else self.requiredByModel if depth == Id.Depth.D0: return reqModel.index(idx.row(), Column.PluginName) if depth == Id.Depth.D1: return reqModel.index(idx.row(), 0, reqModel.index(idx.parent().row(), 0))
def _checkstate_data(self, idx: QModelIndex): return depth = Id.depth(idx) if (depth == Id.Depth.D1 and idx.column() == 1 and idx.parent().row() == Row.ZEditOptions and isBoolOption(idx.row())): if getattr(self.mergeFile, MERGE_OPTIONS[idx.row()][0], False): return Qt.Checked else: return Qt.Unchecked
def _display_data(self, idx: QModelIndex): depth = Id.depth(idx) if depth == Id.Depth.D0: if idx.column() == Column.Property: return self.tr("Plugin Name: ") if idx.column() == Column.Value: return self.data(idx, Role.Data).pluginName if depth == Id.Depth.D1: if idx.column() == Column.Property: if idx.row() == Row.MergedBy: return self.tr("Merged By: ") if idx.row() == Row.MergedPlugins: return self.tr("Merged Plugins: ") if idx.row() == Row.WhenBuilt: return self.tr("Built On: ") if idx.row() == Row.ZEditOptions: return self.tr("zMerge Options: ") if idx.column() == Column.Value: plugin = self.data(idx, Role.Data) plugins, merges = self.data(idx, Role.MergeAssociations) if idx.row() == Row.MergedBy and merges: return self.tr("({})").format(len(merges)) if idx.row() == Row.MergedPlugins and plugins: return self.tr("({})").format(len(plugins)) if idx.row() == Row.ZEditOptions and plugin.isMerge: return self.tr("({})").format(len(MERGE_OPTIONS)) if idx.row( ) == Row.WhenBuilt and plugin.isMerge and plugin.mergeFile: return plugin.mergeFile.dateBuilt if depth == Id.Depth.D2: if idx.parent().row() == Row.MergedBy: if idx.column() == 0: return "{}".format(idx.row() + 1) if idx.column() == 1: plugins, merges = self.data(idx, Role.MergeAssociations) return merges[idx.row()].pluginName if idx.parent().row() == Row.MergedPlugins: if idx.column() == 0: return "{}".format(idx.row() + 1) if idx.column() == 1: plugins, merges = self.data(idx, Role.MergeAssociations) return plugins[idx.row()].pluginName if idx.parent().row() == Row.ZEditOptions: if idx.column() == 0: return MERGE_OPTIONS[idx.row()][1] if idx.column() == 1: plugin = self.data(idx, Role.Data) return getattr(plugin.mergeFile, MERGE_OPTIONS[idx.row()][0], None)
def rowCount(self, parent: QModelIndex = QModelIndex()): if not self.sourceModel(): return 0 depth = Id.depth(parent) if depth == Id.Depth.Invalid: return self.sourceModel().rowCount() if depth != Id.Depth.D0: return 0 requiresParentIdx = self.requiresModel.index(parent.row(), 0) requiredByParentIdx = self.requiredByModel.index(parent.row(), 0) return max(self.requiresModel.rowCount(requiresParentIdx), self.requiredByModel.rowCount(requiredByParentIdx))
def _style_data(self, idx: QModelIndex, role: int): if role == Qt.FontRole: if idx.column() == 0 and Id.depth(idx) == Id.Depth.D1: font = QFont() font.setBold(True) return font return if role == Qt.ForegroundRole: if idx.column() == 1 and Id.depth(idx) == Id.Depth.D1: if idx.row() == Row.MergedPlugins or idx.row( ) == Row.MergedBy or idx.row() == Row.ZEditOptions: return QColor(Qt.lightGray) if idx.column() == 0 and Id.depth(idx) == Id.Depth.D2: if idx.parent().row() == Row.MergedPlugins or idx.parent().row( ) == Row.MergedBy: return QColor(Qt.lightGray) if role == Qt.TextAlignmentRole: if idx.column() == 0 and Id.depth(idx) == Id.Depth.D2: if idx.parent().row() == Row.MergedPlugins: return Qt.AlignRight
def flags(self, idx: QModelIndex): DEFAULT_FLAGS = Qt.ItemIsEnabled | Qt.ItemIsSelectable if not idx.isValid(): return Qt.NoItemFlags depth = Id.depth(idx) if idx.column() == 0: if depth == Id.Depth.D0: return DEFAULT_FLAGS if depth == Id.Depth.D1: if idx.row() == Row.MergedBy or idx.row( ) == Row.MergedPlugins or idx.row() == Row.ZEditOptions: return DEFAULT_FLAGS return DEFAULT_FLAGS | Qt.ItemNeverHasChildren
def rowCount(self, parent: QModelIndex = QModelIndex()): parentDepth = Id.depth(parent) if parentDepth == Id.Depth.Invalid: return len(Row) elif parent.column() != 0: return 0 elif parentDepth == Id.Depth.D0: if parent.row() == Row.LoadOrder: return len(self.mergeFile.loadOrder) elif parent.row() == Row.MergedPlugins: return len(self.mergeFile.plugins) elif parent.row() == Row.ZEditOptions: return len(MERGE_OPTIONS) return 0
def data(self, idx: QModelIndex, role: int = Qt.DisplayRole): depth = Id.depth(idx) if depth == Id.Depth.Invalid: return None if depth == Id.Depth.D0: # either model works here requiresIdx = self.requiresModel.index(idx.row(), 0) return self.requiresModel.data(requiresIdx, role) if idx.column() == DataType.Requires: requiresIdx = self.mapToReqModel(DataType.Requires, idx) return self.requiresModel.data(requiresIdx, role) requiredByIdx = self.mapToReqModel(DataType.RequiredBy, idx) return self.requiredByModel.data(requiredByIdx, role)
def rowCount(self, parent: QModelIndex = QModelIndex()): if self.sourceModel() is None: return 0 depth = Id.depth(parent) if depth == Id.Depth.Invalid: return self.sourceModel().rowCount() if depth != Id.Depth.D0: return 0 if parent.column() != 0: return 0 requirements, dependents = self.sourceModel().data( self.mapToSource(parent), Role.Associations) if self._dataType == DataType.Requires: return len(requirements) else: return len(dependents)
def data(self, idx: QModelIndex, role: int = Qt.DisplayRole): depth = Id.depth(idx) if depth == Id.Depth.Invalid: return None if depth == Id.Depth.D0: if role == Qt.DisplayRole or role == Role.Data: sourceIdx = self.sourceModel().index(idx.row(), PluginColumn.PluginName) return self.sourceModel().data(sourceIdx, role) if depth == Id.Depth.D1: sourceParentIdx = self.sourceModel().index(idx.parent().row(), PluginColumn.PluginName) requirements, dependents = self.sourceModel().data( sourceParentIdx, Role.Associations) association = requirements[idx.row( )] if self._dataType == DataType.Requires else dependents[ idx.row()] plugin = association.plugin isDirect = association.direct if role == Role.Data: return (plugin, isDirect) if role == Qt.DisplayRole: return association.plugin.pluginName elif role == Qt.DecorationRole: if plugin.isMissing: if plugin.isSelected or plugin.isSelectedAsMaster: return QIcon(Icon.INFO_MISSING_SELECTED) return QIcon(Icon.INFO_MISSING) else: if plugin.isSelected: return QIcon(Icon.INFO_SELECTED) elif plugin.isSelectedAsMaster: return QIcon(Icon.INFO_SELECTED_AS_MASTER) return QIcon(Icon.INFO_NOT_SELECTED) elif role == Qt.FontRole: if not isDirect: font = QFont() font.setItalic(True) return font elif role == Qt.ForegroundRole: if not isDirect: return QColor(Qt.lightGray).darker()
def flags(self, idx: QModelIndex): DEFAULT_FLAGS = Qt.ItemIsEnabled | Qt.ItemIsSelectable # May have children if not idx.isValid(): return Qt.NoItemFlags depth = Id.depth(idx) if idx.column() == 0 and depth == Id.Depth.D0: if idx.row() == Row.LoadOrder or idx.row( ) == Row.MergedPlugins or idx.row() == Row.ZEditOptions: return DEFAULT_FLAGS # These may have children else: if depth == Id.Depth.D0 and (idx.row() == Row.ModName or idx.row() == Row.PluginName): return DEFAULT_FLAGS | Qt.ItemNeverHasChildren | Qt.ItemIsEditable if depth == Id.Depth.D1 and idx.parent().row() == Row.ZEditOptions: if isBoolOption(idx.row()): return DEFAULT_FLAGS | Qt.ItemNeverHasChildren | Qt.ItemIsUserCheckable else: return DEFAULT_FLAGS | Qt.ItemNeverHasChildren | Qt.ItemIsEditable return DEFAULT_FLAGS | Qt.ItemNeverHasChildren
def rowCount(self, parent: QModelIndex = QModelIndex()): if not self.sourceModel(): return 0 depth = Id.depth(parent) if depth == Id.Depth.Invalid: return self.sourceModel().rowCount() if parent.column() != 0: return 0 if depth == Id.Depth.D0: return len(Row) if depth == Id.Depth.D1: plugin = self.sourcePlugin(Id.row(parent.internalId())) if not plugin.isMerge and not plugin.isMerged: return 0 plugins, merges = self.mergeAssociations( Id.row(parent.internalId())) if parent.row() == Row.MergedPlugins: return len(plugins) if parent.row() == Row.MergedBy: return len(merges) if plugin.mergeFile and parent.row() == Row.ZEditOptions: return len(MERGE_OPTIONS) return 0
def lessThan(self, left: QModelIndex, right: QModelIndex): depth = Id.depth(left) if depth == Id.Depth.D0: return left.row() < right.row() leftPlugin, _ = self.sourceModel().data(left, Role.Data) rightPlugin, _ = self.sourceModel().data(right, Role.Data) if not self._sortByPriority: return leftPlugin < rightPlugin right = rightPlugin.priority left = leftPlugin.priority noRight = right < 0 noLeft = left < 0 if noRight and noLeft: return leftPlugin < rightPlugin if noRight: return True if noLeft: return False return left < right
def filterAcceptsRow(self, srcRow: int, srcParent: QModelIndex) -> bool: if Id.depth(srcParent) == Id.Depth.D0: idx = self.sourceModel().index(srcRow, 1, srcParent) if not self.sourceModel().data(idx): return False return True
def isArchiveActionCell(idx: QModelIndex): return Id.depth(idx) == Id.Depth.D1 and idx.column() == 1 and idx.row( ) == OptionRow.ArchiveAction
def isMethodCell(idx: QModelIndex): return Id.depth(idx) == Id.Depth.D1 and idx.column() == 1 and idx.row( ) == OptionRow.Method