'''
@author: olivier.massot
'''
from PyQt5 import uic
from PyQt5.Qt import Qt, QEvent, QGraphicsScene, QPointF, QFileDialog, \
QApplication, QMessageBox, QTreeWidgetItem, \
QGraphicsTextItem, QGraphicsItem, QGraphicsRectItem, \
QBrush, QColor, QGraphicsLineItem, QLineF, \
QPen, QPainter, QSvgGenerator, QSize, QRect, QGraphicsItemGroup, \
QGraphicsColorizeEffect, QFont, QDialog, QTableWidgetItem, \
QListWidgetItem, QInputDialog, QIcon, QPixmap
from PyQt5.QtWidgets import QMainWindow, QGraphicsView
from path import Path
from core import ModuleObject
import core
Ui_window, _ = uic.loadUiType(Path(__file__).parent / 'qt_viewer.ui')
Ui_details, _ = uic.loadUiType(Path(__file__).parent / 'qt_details.ui')
Ui_select, _ = uic.loadUiType(Path(__file__).parent / 'qt_select_object.ui')
palette = {
"Table": QColor(240, 240, 20),
"Query": QColor(210, 50, 210),
"Module": QColor(220, 10, 33),
"Relation": QColor(122, 50, 209),
"Report": QColor(25, 10, 220),
"Form": QColor(10, 180, 220),
"Macro": QColor(40, 220, 10),
}
v_spacing = 120
cell_width = 150
cell_spacing = 25
class GraphicsObject(QGraphicsItemGroup):
items = []
def __init__(self, obj, parent=None):
super(GraphicsObject, self).__init__(parent=parent)
self.obj = obj
self.links = []
self._x = 0
self._y = 0
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
self.setAcceptHoverEvents(True)
self.label = QGraphicsTextItem()
self.label.setTextWidth(cell_width)
self.label.setZValue(2)
self.setText()
self.addToGroup(self.label)
pen = QPen(palette[self.obj.type_].darker(150))
pen.setWidth(2)
self.rect = QGraphicsRectItem(self.label.boundingRect())
self.rect.setPen(pen)
self.rect.setBrush(palette[self.obj.type_].lighter(150))
self.rect.setZValue(0)
self.addToGroup(self.rect)
self.topAnchorCoords = ((self.boundingRect().topLeft().x() + self.boundingRect().topRight().x() / 2), self.boundingRect().topLeft().y())
self.bottomAnchorCoords = ((self.boundingRect().topLeft().x() + self.boundingRect().topRight().x() / 2), self.boundingRect().bottomLeft().y())
self.top_anchor = QGraphicsRectItem(self.topAnchorCoords[0] - 3, self.topAnchorCoords[1] - 3, 6, 6)
self.bottom_anchor = QGraphicsRectItem(self.bottomAnchorCoords[0] - 3, self.bottomAnchorCoords[1] - 3, 6, 6)
for anchor in (self.top_anchor, self.bottom_anchor):
anchor.setBrush(QBrush(QColor(255, 153, 51)))
anchor.setZValue(1)
self.addToGroup(anchor)
effect = QGraphicsColorizeEffect()
effect.setColor(QColor(255, 255, 255))
effect.setStrength(0.35)
effect.setEnabled(False)
self.rect.setGraphicsEffect(effect)
self.setToolTip("[{}] '{}'".format(self.obj.type_, self.obj.name_))
GraphicsObject.items.append(self)
def setText(self):
self.label.setHtml(self.html())
def html(self):
return "[{}]
{}".format(self.obj.type_,
self.obj.name_)
def topAnchorCenter(self):
return self.mapToScene(QPointF(*self.topAnchorCoords))
def bottomAnchorCenter(self):
return self.mapToScene(QPointF(*self.bottomAnchorCoords))
def update(self):
if self.pos() is not QPointF(self._x, self._y):
self.setPos(QPointF(self._x, self._y))
for l in self.links:
l.update()
def paint(self, *args, **kwargs):
super(GraphicsObject, self).paint(*args, **kwargs)
self._x, self._y = self.pos().x(), self.pos().y()
self.update()
def setShining(self, active):
self.rect.graphicsEffect().setEnabled(active)
def hoverEnterEvent(self, _):
self.setShining(True)
def hoverLeaveEvent(self, _):
self.setShining(False)
class GraphicsRootObject(GraphicsObject):
def __init__(self, obj, parent=None):
super(GraphicsRootObject, self).__init__(obj, parent=parent)
self.level = 0
self.deps = []
self.refs = []
self._dep_emprise = 0
self._ref_emprise = 0
pen = QPen(QColor("red"))
pen.setWidth(2)
self.rect.setPen(pen)
def xleft(self):
return 0
def compute_coords(self):
return 0, 0
def dep_emprise(self):
if not self._dep_emprise:
self._dep_emprise = sum([d.dep_emprise() for d in self.deps]) if self.deps else (cell_width + 2 * cell_spacing)
return self._dep_emprise
def ref_emprise(self):
if not self._ref_emprise:
self._ref_emprise = sum([r.ref_emprise() for r in self.refs]) if self.refs else (cell_width + 2 * cell_spacing)
return self._ref_emprise
class GraphicsDepObject(GraphicsObject):
def __init__(self, obj, parentItem, parent=None):
super(GraphicsDepObject, self).__init__(obj, parent=parent)
self.deps = []
self.parentItem = parentItem
if parentItem:
parentItem.deps.append(self)
self.level = parentItem.level + 1
self._dep_emprise = 0
def xleft(self):
x0 = sum([n.dep_emprise() for n in self.parentItem.deps[0:self.parentItem.deps.index(self)]])
return self.parentItem.xleft() + x0
def compute_coords(self):
x0 = sum([n.dep_emprise() for n in self.parentItem.deps[0:self.parentItem.deps.index(self)]])
x = self.parentItem.xleft() + (0.5 * self.dep_emprise() - (cell_width / 2 + cell_spacing)) + x0
y = v_spacing * self.level
return x, y
def dep_emprise(self):
if not self._dep_emprise:
self._dep_emprise = sum([d.dep_emprise() for d in self.deps]) if self.deps else (cell_width + 2 * cell_spacing)
return self._dep_emprise
class GraphicsCloneDepObject(GraphicsDepObject):
def __init__(self, obj, childItem, parent=None):
super(GraphicsCloneDepObject, self).__init__(obj, childItem, parent)
self.bottom_anchor.setBrush(QColor("red"))
self.clone_of = next((item for item in GraphicsObject.items if item.obj is obj
and (type(item) in (GraphicsRootObject, GraphicsDepObject, GraphicsRefObject))))
self.setToolTip("L'objet [{}] '{}' a déjà été placé sur l'arbre".format(self.obj.type_, self.obj.name_))
def html(self):
return "* Clone *
" + super(GraphicsCloneDepObject, self).html()
@property
def deps(self):
return []
@deps.setter
def deps(self, value):
pass
def hoverEnterEvent(self, _):
self.setShining(True)
self.clone_of.setShining(True)
def hoverLeaveEvent(self, _):
self.setShining(False)
self.clone_of.setShining(False)
class GraphicsRefObject(GraphicsObject):
def __init__(self, obj, childItem, parent=None):
super(GraphicsRefObject, self).__init__(obj, parent=parent)
self.refs = []
self.childItem = childItem
if childItem:
childItem.refs.append(self)
self.level = childItem.level - 1
self._ref_emprise = 0
def xleft(self):
x0 = sum([n.ref_emprise() for n in self.childItem.refs[0:self.childItem.refs.index(self)]])
return self.childItem.xleft() + x0
def compute_coords(self):
x0 = sum([n.ref_emprise() for n in self.childItem.refs[0:self.childItem.refs.index(self)]])
return self.childItem.xleft() + (0.5 * self.ref_emprise() - (cell_width / 2 + cell_spacing)) + x0, v_spacing * self.level
def ref_emprise(self):
if not self._ref_emprise:
self._ref_emprise = sum([d.ref_emprise() for d in self.refs]) if self.refs else (cell_width + 2 * cell_spacing)
return self._ref_emprise
class GraphicsCloneRefObject(GraphicsRefObject):
def __init__(self, obj, childItem, parent=None):
super(GraphicsCloneRefObject, self).__init__(obj, childItem, parent)
self.top_anchor.setBrush(QColor("red"))
self.clone_of = next((item for item in GraphicsObject.items if item.obj is obj
and (type(item) in (GraphicsRootObject, GraphicsDepObject, GraphicsRefObject))))
self.setToolTip("L'objet [{}] '{}' a déjà été placé sur l'arbre".format(self.obj.type_, self.obj.name_))
def html(self):
return "* Clone *
" + super(GraphicsCloneRefObject, self).html()
@property
def refs(self):
return []
@refs.setter
def refs(self, value):
pass
def hoverEnterEvent(self, _):
self.setShining(True)
self.clone_of.setShining(True)
def hoverLeaveEvent(self, _):
self.setShining(False)
self.clone_of.setShining(False)
class GraphicsLink(QGraphicsLineItem):
items = []
def __init__(self, topGraphicsObject, bottomGraphicsObject, parent=None):
self.topGraphicsObject = topGraphicsObject
self.topGraphicsObject.links.append(self)
self.bottomGraphicsObject = bottomGraphicsObject
self.bottomGraphicsObject.links.append(self)
super(QGraphicsLineItem, self).__init__(parent=parent)
self.update()
def update(self):
line = QLineF(self.mapToScene(self.topGraphicsObject.bottomAnchorCenter()), self.mapToScene(self.bottomGraphicsObject.topAnchorCenter()))
self.setLine(line)
class Viewer(QMainWindow):
def __init__(self):
super (Viewer, self).__init__()
self.createWidgets()
def createWidgets(self):
self.ui = Ui_window()
self.ui.setupUi(self)
self.ui.progressBar.setVisible(False)
self.ui.stackedWidget.setCurrentIndex(0)
self.ui.stackedView.setCurrentIndex(0)
self.ui.btn_select.clicked.connect(self.selectSourceDir)
self.ui.btn_zoom_plus.clicked.connect(self.zoom_plus)
self.ui.btn_zoom_minus.clicked.connect(self.zoom_minus)
self.ui.btn_zoom_view.clicked.connect(self.fit_in_view)
self.ui.btn_zoom_center.clicked.connect(self.zoom_center)
self.ui.btn_svg.clicked.connect(self.to_svg)
self.ui.btn_save.clicked.connect(self.save)
self.ui.btn_load.clicked.connect(self.open)
self.ui.treeWidget.itemClicked.connect(self.treeItemSelected)
self.ui.btn_edit_item.clicked.connect(self.edit_selected_item)
self.ui.btn_graphic_view.clicked.connect(self.switch_graphic_view)
self.ui.btn_table_view.clicked.connect(self.switch_table_view)
self.ui.searchBoxDeps.textChanged.connect(self.filterTblDeps)
self.ui.searchBoxRefs.textChanged.connect(self.filterTblRefs)
self.ui.btnSearchTree.clicked.connect(self.searchTree)
self.ui.searchBoxTree.returnPressed.connect(self.searchTree)
self._title = ""
core.Analyse.report = self.update_progression
self.ui.view.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
self.ui.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.ui.view.viewport().installEventFilter(self)
self._scene = QGraphicsScene()
self._scene.setItemIndexMethod(QGraphicsScene.BspTreeIndex)
self.ui.view.setScene(self._scene)
helpLabel = QGraphicsTextItem()
helpLabel.setPlainText("Sélectionnez le répertoire contenant les sources de la base à analyser,\npuis sélectionnez dans la liste de droite un objet à partir duquel afficher les dépendances...")
helpLabel.setTextWidth(600)
font = QFont()
font.setItalic(True)
font.setWeight(63)
helpLabel.setFont(font)
self._scene.addItem(helpLabel)
def eventFilter(self, _, event):
if event.type() == QEvent.Wheel:
if event.angleDelta().y() > 0:
self.zoom_plus()
elif event.angleDelta().y() < 0:
self.zoom_minus()
return True
return False
def fit_in_view(self):
rect = self._scene.itemsBoundingRect()
rect.adjust(-50, -50, 50, 50)
self._scene.setSceneRect(rect)
self.ui.view.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio)
def zoom_plus(self):
self.ui.view.scale(1.2, 1.2)
def zoom_minus(self):
self.ui.view.scale(0.8, 0.8)
def zoom_center(self):
root = next((item for item in GraphicsObject.items if type(item) is GraphicsRootObject))
rect = root.boundingRect()
rect.adjust(-200, -200, 200, 200)
self.ui.view.fitInView(rect, Qt.KeepAspectRatio)
def switch_graphic_view(self):
self.ui.stackedView.setCurrentIndex(0)
def switch_table_view(self):
self.ui.stackedView.setCurrentIndex(1)
def to_svg(self):
fileName, _ = QFileDialog.getSaveFileName(self, "Save File", "", "Svg File (*.svg)")
if not fileName:
return
gen = QSvgGenerator()
gen.setFileName(fileName)
gen.setSize(QSize(1000, 1000))
gen.setViewBox(QRect(0, 0, 1000, 1000))
gen.setTitle("Access Analyser")
gen.setDescription("Access Analyser Report for {}".format(self._title))
painter = QPainter(gen)
self._scene.render(painter)
painter.end()
def save(self):
if not core.Analyse.objects:
return
filepath, _ = QFileDialog.getSaveFileName(self, 'Enregistrer sous', '', "Access Analyser Files (*.acan)")
if filepath:
core.Analyse.dump_to(filepath)
def open(self):
filepath, _ = QFileDialog.getOpenFileName(self, 'Charger les données de', '', "Access Analyser Files (*.acan)")
if filepath:
core.Analyse.load_from(filepath)
self._title = Path(filepath).name
self.load()
def update_progression(self, i, total, msg=""):
self.ui.progressBar.setMaximum(total)
self.ui.progressBar.setValue(i)
if msg:
self.ui.txtPanel.append(msg)
QApplication.processEvents()
def selectSourceDir(self):
source_dir = QFileDialog.getExistingDirectory(self, "Sélectionner le répertoire des sources", "", QFileDialog.ShowDirsOnly)
if not source_dir:
return
self.run(source_dir)
def run(self, source_dir):
source_dir = Path(source_dir)
self._title = source_dir
self.ui.stackedWidget.setCurrentIndex(0)
self.ui.progressBar.setVisible(True)
self.ui.txtPanel.clear()
core.Analyse.run(source_dir)
self.ui.progressBar.setVisible(False)
self.ui.txtPanel.clear()
self.load()
QMessageBox.information(self, "Analyse", "Analyse terminée: {} objets chargés en mémoire".format(len(core.Analyse.objects)))
def load(self):
self.clear_scene()
self.ui.treeWidget.clear()
self.ui.stackedWidget.setCurrentIndex(1)
topitem = QTreeWidgetItem()
topitem.setText(0, "Objets")
self.ui.treeWidget.addTopLevelItem(topitem)
groupes = {}
for index, obj in enumerate(core.Analyse.objects):
if not obj.type_ in groupes:
item = QTreeWidgetItem()
item.setText(0, obj.type_)
groupes[obj.type_] = item
topitem.addChild(item)
item = QTreeWidgetItem()
if any(len(m.warnings) > 0 for m in obj.mentions):
item.setIcon(0, QIcon(QPixmap(core.here / "rsc\\warning_16.png")))
item.setText(1, obj.name_)
item.setData(2, 0, index)
groupes[obj.type_].addChild(item)
self.ui.treeWidget.setColumnHidden(2, True)
self.ui.treeWidget.expandToDepth(1)
self.ui.btn_save.setEnabled(True)
def enable_view_buttons(self, enable):
self.ui.btn_zoom_plus.setEnabled(enable)
self.ui.btn_zoom_center.setEnabled(enable)
self.ui.btn_zoom_view.setEnabled(enable)
self.ui.btn_zoom_minus.setEnabled(enable)
self.ui.btn_graphic_view.setEnabled(enable)
self.ui.btn_table_view.setEnabled(enable)
def clear_scene(self):
self._scene.clear()
GraphicsObject.items = []
self.enable_view_buttons(False)
def maj_view_with(self, root_object):
self.switch_graphic_view()
self.clear_scene()
root = GraphicsRootObject(root_object)
self._scene.addItem(root)
def _addDeps(go):
for dep in go.obj.deps:
if dep not in [go.obj for go in GraphicsObject.items]:
gdep = GraphicsDepObject(dep, go)
if dep.deps:
_addDeps(gdep)
else:
gdep = GraphicsCloneDepObject(dep, go)
self._scene.addItem(gdep)
link = GraphicsLink(go, gdep)
self._scene.addItem(link)
_addDeps(root)
def _addRefs(go):
for ref in go.obj.refs:
if ref not in [go.obj for go in GraphicsObject.items]:
gref = GraphicsRefObject(ref, go)
if ref.refs:
_addRefs(gref)
else:
gref = GraphicsCloneRefObject(ref, go)
self._scene.addItem(gref)
link = GraphicsLink(gref, go)
self._scene.addItem(link)
_addRefs(root)
for item in GraphicsObject.items:
item._x, item._y = item.compute_coords()
if isinstance(item, GraphicsDepObject):
item._x -= (root.dep_emprise() - (cell_width + 2 * cell_spacing)) / 2
if isinstance(item, GraphicsRefObject):
item._x -= (root.ref_emprise() - (cell_width + 2 * cell_spacing)) / 2
item.update()
self.ui.tblDeps.clearContents()
self.ui.tblRefs.clearContents()
self.ui.tblDeps.setRowCount(0)
self.ui.tblRefs.setRowCount(0)
self.ui.lblRootTitle.setText("{}: {}".format(root_object.type_, root_object.name_))
for item in GraphicsObject.items:
if type(item) is GraphicsDepObject:
row = self.ui.tblDeps.rowCount()
self.ui.tblDeps.insertRow(row)
self.ui.tblDeps.setItem(row, 0, QTableWidgetItem(item.obj.type_))
self.ui.tblDeps.setItem(row, 1, QTableWidgetItem(item.obj.name_))
if type(item) is GraphicsRefObject:
row = self.ui.tblRefs.rowCount()
self.ui.tblRefs.insertRow(row)
self.ui.tblRefs.setItem(row, 0, QTableWidgetItem(item.obj.type_))
self.ui.tblRefs.setItem(row, 1, QTableWidgetItem(item.obj.name_))
self.enable_view_buttons(True)
self.fit_in_view()
def treeItemSelected(self, item):
index = item.data(2, 0)
if index is None:
self.ui.btn_edit_item.setEnabled(False)
return
obj = core.Analyse.objects[index]
self.maj_view_with(obj)
self.ui.btn_edit_item.setEnabled(True)
def filterTblDeps(self, filterStr):
for row in range(self.ui.tblDeps.rowCount()):
content = "{}{}".format(self.ui.tblDeps.item(row, 0).text(), self.ui.tblDeps.item(row, 1).text())
self.ui.tblDeps.setRowHidden(row, filterStr.lower() not in content.lower())
def filterTblRefs(self, filterStr):
for row in range(self.ui.tblRefs.rowCount()):
content = "{}{}".format(self.ui.tblRefs.item(row, 0).text(), self.ui.tblRefs.item(row, 1).text())
self.ui.tblRefs.setRowHidden(row, filterStr.lower() not in content.lower())
def searchTree(self):
filterStr = self.ui.searchBoxTree.text()
if not filterStr:
return
items = self.ui.treeWidget.findItems(filterStr, Qt.MatchContains | Qt.MatchRecursive, 1)
if not items:
QMessageBox.warning(self, "Recherche", "Aucun résultat pour '{}'".format(filterStr))
try:
start = items.index(self.ui.treeWidget.currentItem()) + 1
except ValueError:
start = 0
match = (items[start:] + items[:start])[0]
self.ui.treeWidget.setCurrentItem(match)
self.ui.treeWidget.scrollTo(self.ui.treeWidget.indexFromItem(match, 1))
def edit_selected_item(self):
index = self.ui.treeWidget.currentItem().data(2, 0)
obj = core.Analyse.objects[index]
dlg = DetailsDialog(obj, self)
dlg.show()
r = dlg.exec_()
if r:
core.Analyse.build_trees()
self.maj_view_with(obj)
if any(len(m.warnings) > 0 for m in obj.mentions):
self.ui.treeWidget.currentItem().setIcon(0, QIcon(QPixmap(core.here / "rsc\\warning_16.png")))
else:
self.ui.treeWidget.currentItem().setIcon(0, QIcon())
def keyPressEvent(self, e):
if e.key() == Qt.Key_S and e.modifiers() & Qt.ControlModifier:
self.save()
e.accept()
if e.key() == Qt.Key_Control:
self.ui.view.setDragMode(QGraphicsView.ScrollHandDrag)
e.accept()
def keyReleaseEvent(self, e):
if e.key() == Qt.Key_Control:
self.ui.view.setDragMode(QGraphicsView.RubberBandDrag)
class DetailsDialog(QDialog):
def __init__(self, obj, parent=None):
self.obj = obj
super (DetailsDialog, self).__init__(parent)
self.createWidgets()
def createWidgets(self):
self.ui = Ui_details()
self.ui.setupUi(self)
self.ui.tbl_mentions.verticalHeader().sectionDoubleClicked.connect(self.verticalHeaderDoubleClicked)
self.ui.tbl_mentions.itemClicked.connect(self.itemClicked)
self.ui.btn_add.clicked.connect(self.add_mention)
self.ui.btn_edit.clicked.connect(self.edit_mention)
self.ui.btn_del.clicked.connect(self.del_mention)
self.ui.btn_ok.clicked.connect(self.ok)
self.ui.btn_cancel.clicked.connect(self.ok)
self.ui.lbl_title.setText("{}: {}".format(self.obj.type_, self.obj.name_))
self.ui.tbl_mentions.hideColumn(0)
self.ui.tbl_mentions.setColumnWidth(1, 50)
self.ui.tbl_mentions.setColumnWidth(2, 70)
self.ui.tbl_mentions.setColumnWidth(3, 150)
self.load_table()
def load_table(self):
self.ui.tbl_mentions.setSortingEnabled(False)
self.ui.tbl_mentions.clearContents()
self.ui.tbl_mentions.setRowCount(len(self.obj.mentions))
for index, mention in enumerate(self.obj.mentions):
item = QTableWidgetItem("")
if len(mention.warnings) > 0:
item.setIcon(QIcon(QPixmap(core.here / "rsc\\warning_16.png")))
item.setToolTip("\n".join([w.text for w in mention.warnings]) + "\n\nDoucle-cliquer pour supprimer l'avertissement.")
self.ui.tbl_mentions.setVerticalHeaderItem(index, item)
item = QTableWidgetItem("")
item.setData(0, index)
self.ui.tbl_mentions.setItem(index, 0, item)
item = QTableWidgetItem("{}".format(mention.line))
self.ui.tbl_mentions.setItem(index, 1, item)
item = QTableWidgetItem("{}".format(mention.obj.type_))
self.ui.tbl_mentions.setItem(index, 2, item)
item = QTableWidgetItem("{}".format(mention.objname) if mention.obj.type_ != "Module" else "{}.{}".format(mention.obj.name_, mention.objname))
self.ui.tbl_mentions.setItem(index, 3, item)
item = QTableWidgetItem("{}".format(mention.quote))
item.setFont(QFont("Consolas", 8))
self.ui.tbl_mentions.setItem(index, 4, item)
self.ui.tbl_mentions.setSortingEnabled(True)
def itemClicked(self, _):
self.ui.btn_edit.setEnabled(True)
self.ui.btn_del.setEnabled(True)
def verticalHeaderDoubleClicked(self, row):
index = self.ui.tbl_mentions.item(row, 0).data(0)
mention = self.obj.mentions[index]
if mention.warnings:
if QMessageBox.question(self, "Confirmation", "Voulez-vous supprimer cet avertissement?") == QMessageBox.Yes:
del mention.warnings[:]
self.ui.tbl_mentions.verticalHeaderItem(row).setIcon(QIcon())
def add_mention(self):
dlg = ObjectSelectorDialog(parent=self)
dlg.show()
r = dlg.exec_()
if not r:
return
mention = core.Mention(0, dlg.obj.name_, "(ajouté manuellement)", dlg.obj)
linenum, _ = QInputDialog.getInt(self, "Ligne", "Numéro de ligne correspondant dans le code-source? (facultatif)", 0)
if linenum > 0:
mention.line = linenum
try:
with open(self.obj.sourcefile, "r", encoding='utf-8') as f:
mention.quote = next((line.strip() for i, line in enumerate(f) if i == linenum - 1)).strip()
except FileNotFoundError:
pass
self.obj.mentions.append(mention)
self.load_table()
def selected_index(self):
row = self.ui.tbl_mentions.currentRow()
if row < 0:
return None
return self.ui.tbl_mentions.item(row, 0).data(0)
def edit_mention(self):
row = self.ui.tbl_mentions.currentRow()
if row < 0:
return
item = QTableWidgetItem("")
item.setIcon(QIcon(QPixmap(core.here / "rsc\\edit_16.png")))
self.ui.tbl_mentions.setVerticalHeaderItem(row, item)
index = self.ui.tbl_mentions.item(row, 0).data(0)
mention = self.obj.mentions[index]
dlg = ObjectSelectorDialog(filterStr=mention.objname, parent=self)
dlg.show()
r = dlg.exec_()
if r:
mention.obj = dlg.obj
mention.warning = ""
self.load_table()
def del_mention(self):
index = self.selected_index()
if not QMessageBox.question(self, "Confirmation", "Etes-vous sûr de vouloir supprimer la référence sélectionnée?") == QMessageBox.Yes:
return
del self.obj.mentions[index]
self.load_table()
def ok(self):
self.done(1)
def cancel(self):
self.done(0)
def keyPressEvent(self, e):
if e.key() == Qt.Key_Delete:
if self.ui.tbl_mentions.currentRow() < 0:
return
self.del_mention()
e.accept()
class ObjectSelectorDialog(QDialog):
def __init__(self, filterStr="", parent=None):
self.obj = None
super (ObjectSelectorDialog, self).__init__(parent)
self.createWidgets()
self.ui.searchBox.setText(filterStr)
def createWidgets(self):
self.ui = Ui_select()
self.ui.setupUi(self)
for obj in core.Analyse.objects:
item = QListWidgetItem("{} - {}".format(obj.type_, obj.name_))
item.obj = obj
self.ui.listWidget.addItem(item)
self.ui.searchBox.textChanged.connect(self.filter)
self.ui.listWidget.itemClicked.connect(self.itemClicked)
self.ui.listWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
self.ui.btn_ok.clicked.connect(self.ok)
def itemClicked(self, item):
self.obj = item.obj
self.ui.btn_ok.setEnabled(True)
def itemDoubleClicked(self, item):
self.itemClicked(item)
self.ok()
def filter(self, filterStr):
for i in range(self.ui.listWidget.count()):
item = self.ui.listWidget.item(i)
item.setHidden(filterStr.lower() not in item.text().lower())
def ok(self):
self.done(1)
def done(self, status):
if not status:
self.obj = None
super(ObjectSelectorDialog, self).done(status)