فهرست منبع

Premiere version fonctionnelle

olivier.massot 7 سال پیش
والد
کامیت
dd2b1820f9
5فایلهای تغییر یافته به همراه311 افزوده شده و 23 حذف شده
  1. 255 17
      Viewer.py
  2. 7 3
      core.py
  3. BIN
      enregistrer_16.png
  4. 3 3
      main.py
  5. 46 0
      qt_viewer.ui

+ 255 - 17
Viewer.py

@@ -5,21 +5,180 @@
 from PyQt5 import uic
 from PyQt5.Qt import Qt, QEvent, QGraphicsScene, QPointF, QFileDialog, \
     QApplication, QMessageBox, QTreeWidgetItem, \
-    QGraphicsTextItem
+    QGraphicsTextItem, QGraphicsItem, QGraphicsRectItem, \
+    QBrush, QColor, QGraphicsLineItem, QLineF, \
+    QPen, QPainter, QSvgGenerator, QSize, QRect
 from PyQt5.QtWidgets import QMainWindow, QGraphicsView
 from path import Path
 
+from core import AccessObject
 import core
 
 
 Ui_window, _ = uic.loadUiType(Path(__file__).parent / 'qt_viewer.ui')
 
+palette = {
+            "tables": QColor(240, 240, 20),
+            "queries": QColor(210, 50, 210),
+            "modules": QColor(220, 10, 33),
+            "relations": QColor(122, 50, 209),
+            "reports": QColor(25, 10, 220),
+            "forms": QColor(10, 180, 220),
+            "scripts": QColor(40, 220, 10),
+          }
+
+v_spacing = 120
+cell_width = 150
+cell_spacing = 25
+
 class GraphicsObject(QGraphicsTextItem):
-    def __init__(self, obj, parent=None, scene=None):
+    items = []
+    def __init__(self, obj, parent=None):
+        super(GraphicsObject, self).__init__("", parent=parent)
         self.obj = obj
-        super(GraphicsObject, self).__init__("...", parent=parent)
-        self.setHtml("<b>{}</b>".format(obj.nom))
-        self.setTextWidth(200)
+        self._text = "[{}] <b>{}</b>".format(obj.type_, obj.nom)
+        self.links = []
+        self._x = 0
+        self._y = 0
+        self.setHtml(self._text)
+
+        self.setTextWidth(cell_width)
+        self.setFlag(QGraphicsItem.ItemIsMovable, True)
+        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
+        self.setFlag(QGraphicsItem.ItemIsFocusable, True)
+
+        self._addRect()
+        self._addAnchors()
+        GraphicsObject.items.append(self)
+
+    def _addRect(self):
+        pen = QPen(palette[self.obj.type_])
+        self.rect = QGraphicsRectItem(self.boundingRect(), parent=self)
+        self.rect.setPen(pen)
+
+    def topAnchorCenter(self):
+        return self.mapToScene(QPointF((self.boundingRect().topLeft().x() + self.boundingRect().topRight().x() / 2), self.boundingRect().topLeft().y()))
+
+    def bottomAnchorCenter(self):
+        return self.mapToScene(QPointF((self.boundingRect().topLeft().x() + self.boundingRect().topRight().x() / 2), self.boundingRect().bottomLeft().y()))
+
+    def _addAnchors(self):
+        x = (self.boundingRect().topLeft().x() + self.boundingRect().topRight().x() / 2)
+        ytop = self.boundingRect().topLeft().y()
+        ybottom = self.boundingRect().bottomLeft().y()
+        self.top_anchor = QGraphicsRectItem(x - 3, ytop - 3, 6, 6, parent=self)
+        self.bottom_anchor = QGraphicsRectItem(x - 3, ybottom - 3, 6, 6, parent=self)
+        self.top_anchor.setBrush(QBrush(QColor(255, 153, 51)))
+        self.bottom_anchor.setBrush(QBrush(QColor(255, 153, 51)))
+
+    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()
+
+class GraphicsRootObject(GraphicsObject):
+    def __init__(self, obj, parent=None):
+        super(GraphicsRootObject, self).__init__(obj, parent=parent)
+        self.level = 0
+        self.deps = []
+        self.refs = []
+
+    def xleft(self):
+        return 0
+
+#     def compute_coords(self):
+#         return 0, 0
+
+    def compute_coords(self):
+        return (0.5 * self.emprise() - (cell_width / 2 + cell_spacing)), 0
+
+    def emprise(self):
+        return max([self.dep_emprise(), self.ref_emprise()])
+
+    def dep_emprise(self):
+        return sum([d.dep_emprise() for d in self.deps]) if self.deps else (cell_width + 2 * cell_spacing)
+
+    def ref_emprise(self):
+        return sum([r.ref_emprise() for r in self.refs]) if self.refs else (cell_width + 2 * cell_spacing)
+
+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
+
+    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):
+        return sum([d.dep_emprise() for d in self.deps]) if self.deps else (cell_width + 2 * cell_spacing)
+
+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
+
+    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):
+        return sum([d.ref_emprise() for d in self.refs]) if self.refs else (cell_width + 2 * cell_spacing)
+
+
+
+
+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)
+
+    def select(self, active):
+        pen = QPen()
+        if active:
+            pen.setColor(QColor("blue"))
+            pen.setWidth(2)
+        else:
+            pen.setColor(QColor("black"))
+            pen.setWidth(1)
+        self.setPen(pen)
 
 
 class Viewer(QMainWindow):
@@ -36,28 +195,27 @@ class Viewer(QMainWindow):
         self.ui.progressBar.setVisible(False)
         self.ui.stackedWidget.setCurrentIndex(0)
 
+        self.ui.btn_test.clicked.connect(self.test)
+
         self.ui.btn_select.clicked.connect(self.run)
         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.treeWidget.itemClicked.connect(self.itemSelected)
+        self.ui.btn_save.clicked.connect(self.save_to_png)
+        self.ui.treeWidget.itemClicked.connect(self.treeItemSelected)
 
         core.Analyse.report = self.update_progression
 
         self.ui.view.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
-        self.ui.view.setDragMode(QGraphicsView.NoDrag)
         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)
-        self.ui.view.centerOn(QPointF(0, 0))
         self.fit_in_view()
 
-
-    def eventFilter(self, obj, event):
+    def eventFilter(self, _, event):
         if event.type() == QEvent.Wheel:
             if event.angleDelta().y() > 0:
                 self.zoom_plus()
@@ -75,6 +233,21 @@ class Viewer(QMainWindow):
     def zoom_minus(self):
         self.ui.view.scale(0.8, 0.8)
 
+    def save_to_png(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("SVG Generator Example Drawing")
+        gen.setDescription("An SVG drawing created by the SVG Generator "
+                                    "Example provided with Qt.")
+        painter = QPainter(gen)
+        self._scene.render(painter)
+        painter.end()
+
     def update_progression(self, i, total, msg=""):
         self.ui.progressBar.setMaximum(total)
         self.ui.progressBar.setValue(i)
@@ -84,8 +257,8 @@ class Viewer(QMainWindow):
 
     def run(self):
 
-#         source_dir = QFileDialog.getExistingDirectory(self, "Sélectionner le répertoire des sources", "", QFileDialog.ShowDirsOnly)
-        source_dir = r"C:\dev\access\AGRHum\source"
+        source_dir = QFileDialog.getExistingDirectory(self, "Sélectionner le répertoire des sources", "", QFileDialog.ShowDirsOnly)
+#         source_dir = r"C:\dev\access\AGRHum\source"
 
         self.ui.progressBar.setVisible(True)
         self.ui.lbl_repertoire.setText(source_dir)
@@ -124,9 +297,74 @@ class Viewer(QMainWindow):
         self.ui.treeWidget.setColumnHidden(1, True)
         self.ui.treeWidget.expandToDepth(1)
 
-    def itemSelected(self, item):
+    def clear_scene(self):
+        self._scene.clear()
+        GraphicsObject.items = []
+
+    def maj_scene_with(self, root_object):
+        self.clear_scene()
+        root = GraphicsRootObject(root_object)
+        self._scene.addItem(root)
+
+        def _addDeps(go):
+            for dep in go.obj.deps:
+                if dep in [go.obj for go in GraphicsObject.items]:
+                    print("ref circulaire: {}".format(dep))
+                    continue
+                gdep = GraphicsDepObject(dep, go)
+                self._scene.addItem(gdep)
+
+                link = GraphicsLink(go, gdep)
+                self._scene.addItem(link)
+                if dep.deps:
+                    _addDeps(gdep)
+        _addDeps(root)
+
+        def _addRefs(go):
+            for ref in go.obj.refs:
+                if ref in [go.obj for go in GraphicsObject.items]:
+                    print("ref circulaire: {}".format(ref))
+                    continue
+                gref = GraphicsRefObject(ref, go)
+                self._scene.addItem(gref)
+
+                link = GraphicsLink(gref, go)
+                self._scene.addItem(link)
+                if ref.refs:
+                    _addRefs(gref)
+        _addRefs(root)
+
+        for item in GraphicsObject.items:
+            item._x, item._y = item.compute_coords()
+            item.update()
+
+        self.ui.btn_save.setEnabled(True)
+        self.fit_in_view()
+
+    def treeItemSelected(self, item):
         index = item.data(1, 0)
         obj = core.Analyse.objects[index]
-
-        go = GraphicsObject(obj)
-        self._scene.addItem(go)
+        self.maj_scene_with(obj)
+
+    def test(self):
+        a = AccessObject("queries", "testA", "")
+        b = AccessObject("queries", "testB", "")
+        c = AccessObject("tables", "testC", "")
+        d = AccessObject("tables", "testD", "")
+        e = AccessObject("modules", "testE", "")
+        f = AccessObject("relations", "testF", "")
+        g = AccessObject("reports", "testG", "")
+        h = AccessObject("forms", "testH", "")
+        i = AccessObject("scripts", "testI", "")
+
+        j = AccessObject("reports", "testJ", "")
+        k = AccessObject("forms", "testK", "")
+        l = AccessObject("scripts", "testL", "")
+
+        b.deps = [e, f, g]
+        c.deps = [h, i]
+        a.deps = [b, c, d]
+        j.refs = [k, l]
+        a.refs = [j]
+
+        self.maj_scene_with(a)

+ 7 - 3
core.py

@@ -41,6 +41,7 @@ class AccessObject():
         self.functions = []
         self.sourcefile = sourcefile
         self.deps = []
+        self.refs = []
 
     def __repr__(self):
         return "<{}: {}>".format(self.type_, self.nom)
@@ -49,8 +50,9 @@ class AccessObject():
         if not obj in self.deps:
             self.deps.append(obj)
 
-    def to_json(self):
-        pass
+    def add_ref(self, obj):
+        if not obj in self.ref_by:
+            self.refs.append(obj)
 
 class Analyse():
     objects = []
@@ -100,10 +102,12 @@ class Analyse():
                     continue
                 if getrx(object_.nom).search(source):
                     subject.add_dep(object_)
+                    object_.add_ref(subject)
                     continue
                 for fname in object_.functions:
                     if getrx(fname).search(source):
                         subject.add_dep(object_)
+                        object_.add_ref(subject)
                         break
 
         cls.report(total, total, "Analyse terminée")
@@ -118,7 +122,7 @@ if __name__ == "__main__":
     datafile = here / "access_data.txt"
     datafile.remove_p()
 
-    def main_report(i, total, msg=""):
+    def main_report(*_, msg=""):
         print(msg)
     Analyse.report = main_report
 

BIN
enregistrer_16.png


+ 3 - 3
main.py

@@ -1,14 +1,14 @@
 '''
-Created on 13 mars 2017
 
-@author: olinox
+@author: olivier.massot, mars 2017
 '''
 import sys
 
 from PyQt5.Qt import QApplication, QMessageBox
+# import ipdb
+
 from Viewer import Viewer
 
-# import ipdb
 
 if __name__ == '__main__':
     app = QApplication(sys.argv)

+ 46 - 0
qt_viewer.ui

@@ -152,6 +152,9 @@
           <property name="horizontalScrollBarPolicy">
            <enum>Qt::ScrollBarAsNeeded</enum>
           </property>
+          <property name="dragMode">
+           <enum>QGraphicsView::RubberBandDrag</enum>
+          </property>
           <property name="transformationAnchor">
            <enum>QGraphicsView::AnchorUnderMouse</enum>
           </property>
@@ -319,6 +322,42 @@
           </property>
          </widget>
         </item>
+        <item>
+         <spacer name="horizontalSpacer">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Fixed</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>15</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QToolButton" name="btn_save">
+          <property name="enabled">
+           <bool>false</bool>
+          </property>
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text">
+           <string>...</string>
+          </property>
+          <property name="icon">
+           <iconset>
+            <normaloff>enregistrer_16.png</normaloff>enregistrer_16.png</iconset>
+          </property>
+         </widget>
+        </item>
         <item>
          <spacer name="horizontalSpacer_2">
           <property name="orientation">
@@ -332,6 +371,13 @@
           </property>
          </spacer>
         </item>
+        <item>
+         <widget class="QPushButton" name="btn_test">
+          <property name="text">
+           <string>test</string>
+          </property>
+         </widget>
+        </item>
        </layout>
       </item>
      </layout>