Explorar el Código

修改 addFile 窗口的文件、地址栏

mrh hace 3 años
padre
commit
8750755742

+ 1 - 0
gui.py

@@ -21,6 +21,7 @@ def run_forever(GUI):
     app = QApplication(sys.argv)
     mainWindows = MainWindow(GUI)
     mainWindows.sig.connect(handle_signal)
+    mainWindows.show_analyze_window()
     app.exec_()
     
 def run_in_thread(GUI:QObject):

+ 0 - 175
ui/AddFile-bak.ui

@@ -1,175 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>AddFileWindows</class>
- <widget class="QMainWindow" name="AddFileWindows">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>469</width>
-    <height>418</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>MainWindow</string>
-  </property>
-  <widget class="QWidget" name="centralwidget">
-   <layout class="QGridLayout" name="gridLayout">
-    <item row="0" column="0">
-     <layout class="QVBoxLayout" name="verticalLayout">
-      <item>
-       <layout class="QHBoxLayout" name="horizontalLayout">
-        <item>
-         <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0,0,0,0">
-          <item>
-           <widget class="QRadioButton" name="radioButton">
-            <property name="text">
-             <string>Filelist</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QRadioButton" name="radioButton_2">
-            <property name="text">
-             <string>Netlist</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QRadioButton" name="radioButton_3">
-            <property name="text">
-             <string>Verilog 2001</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QRadioButton" name="radioButton_4">
-            <property name="text">
-             <string>Verilog 2005</string>
-            </property>
-            <property name="checked">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QRadioButton" name="radioButton_5">
-            <property name="text">
-             <string>SystemVerilog 2005</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QRadioButton" name="radioButton_6">
-            <property name="text">
-             <string>SystemVerilog 2009</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QRadioButton" name="radioButton_7">
-            <property name="text">
-             <string>SystemVerilog 2012</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <spacer name="verticalSpacer">
-            <property name="orientation">
-             <enum>Qt::Vertical</enum>
-            </property>
-            <property name="sizeHint" stdset="0">
-             <size>
-              <width>20</width>
-              <height>40</height>
-             </size>
-            </property>
-           </spacer>
-          </item>
-         </layout>
-        </item>
-        <item>
-         <widget class="QTableWidget" name="tableWidget">
-          <property name="editTriggers">
-           <set>QAbstractItemView::NoEditTriggers</set>
-          </property>
-          <attribute name="horizontalHeaderVisible">
-           <bool>true</bool>
-          </attribute>
-          <attribute name="horizontalHeaderHighlightSections">
-           <bool>true</bool>
-          </attribute>
-          <attribute name="verticalHeaderVisible">
-           <bool>false</bool>
-          </attribute>
-          <row>
-           <property name="text">
-            <string>新建行</string>
-           </property>
-          </row>
-          <column>
-           <property name="text">
-            <string>path</string>
-           </property>
-          </column>
-         </widget>
-        </item>
-       </layout>
-      </item>
-      <item>
-       <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,0">
-        <item>
-         <spacer name="horizontalSpacer">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item>
-         <widget class="QPushButton" name="bnt_OK">
-          <property name="text">
-           <string>OK</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QPushButton" name="bnt_Cancel">
-          <property name="text">
-           <string>Cancel</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QPushButton" name="bnt_Apply">
-          <property name="text">
-           <string>Apply</string>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </item>
-     </layout>
-    </item>
-   </layout>
-  </widget>
-  <widget class="QMenuBar" name="menubar">
-   <property name="geometry">
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>469</width>
-     <height>23</height>
-    </rect>
-   </property>
-  </widget>
-  <widget class="QStatusBar" name="statusbar"/>
- </widget>
- <resources/>
- <connections/>
-</ui>

+ 162 - 0
ui/AddFile.py

@@ -0,0 +1,162 @@
+import os
+import sys
+from decimal import *
+from PySide2.QtWidgets import *
+from PySide2.QtCore import *
+from PySide2.QtGui import *
+from ui.ui_AddFile import Ui_AddFileWindow
+from ui.addressBar.addressbar import BreadcrumbsAddressBar
+from ui.file_browser.file_list import get_files_dirs
+from ui.file_browser.PathObject import PathObject
+from ui.file_browser.filewidget import FileWidget
+
+
+class AddFileWindow(Ui_AddFileWindow, QDialog):
+    def __init__(self, parent, path) -> None:
+        super().__init__()
+        self.file_suffix = ["Supported Files(*.v *.sv *.f *.lst *.list)", "All files(*.*)"]
+        self.setupUi(self)
+        self.init_file_browser(path)
+        
+        self.move(parent.x()+(parent.width()-self.width())/2,parent.y()+(parent.height()-self.height())/2)
+        self.show()
+        self.fileTable.cellDoubleClicked.connect(self.open_item)
+        self.path_obj = PathObject(path)
+        self.dir_stack = []
+        self.show_file_list()
+        self.comboBox.addItems(self.file_suffix)
+        
+    def init_file_browser(self, path):
+        # 表格随窗口适应大小
+        self.fileTable.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+        self.address_bar = BreadcrumbsAddressBar(self)
+        self.address_bar.path_selected.connect(self.path_select)
+        self.verticalLayout_3.insertWidget(0, self.address_bar)
+
+    def path_select(self, path):
+        self.path_obj.set(path)
+        self.open_folder(path)
+
+
+    def update_path(self):
+        path_text = self.pathBar.text()
+        if os.path.isdir(path_text):
+            self.dir_stack.clear()
+            self.path_obj.set(path_text)
+            self.show_file_list()
+        else:
+            self.path_error_popup()
+            self.pathBar.setText(str(self.path_obj))
+
+    def path_error_popup(self):
+        msg = QMessageBox()
+        msg.setWindowTitle("Error")
+        msg.setText("Invalid path!")
+        msg.setIcon(QMessageBox.Critical)
+        x = msg.exec_()
+
+    def show_file_list(self):
+        self.files, self.dirs = get_files_dirs(self.path_obj)
+        self.update_counts()
+        self.fileTable.setRowCount(0)
+
+        height = self.fileTable.verticalHeader().defaultSectionSize()
+        for dir in self.dirs:
+            row = self.fileTable.rowCount()
+            self.fileTable.insertRow(row)
+            fwidget = FileWidget(dir.name, dir.type, height)
+            self.fileTable.setCellWidget(row, 0, fwidget)
+
+        for f in self.files:
+            row = self.fileTable.rowCount()
+            self.fileTable.insertRow(row)
+            fwidget = FileWidget(f.name, f.type, height)
+            self.fileTable.setCellWidget(row, 0, fwidget)
+        # self.fileTable.resizeRowsToContents()
+        # self.fileTable
+        # self.show_count()
+
+    def format_size(self, size):
+        if size < 999:
+            return f"{size} B"
+        if size < 999999:
+            num = Decimal(size / 1000)
+            return f"{round(num, 2)} KB"
+        if size < 999999999:
+            num = Decimal(size / 1000000)
+            return f"{round(num, 2)} MB"
+        else:
+            num = Decimal(size / 1000000000)
+            return f"{round(num, 2)} GB"
+
+    def update_counts(self):
+        self.file_count = len(self.files)
+        self.dir_count = len(self.dirs)
+
+    def open_item(self, row, column):
+        if column != 0:
+            return
+        widg = self.fileTable.cellWidget(row, column)
+        name = widg.get_text()
+        self.dir_stack.clear()
+        abs_path = os.path.join(self.path_obj.pathtext, name)
+        if os.path.isfile(os.path.join(self.path_obj.pathtext, name)):
+            self.open_file(abs_path)
+        elif os.path.isdir(abs_path):
+            self.address_bar.set_path(abs_path)
+    
+    
+    def open_folder(self, dir):
+        if self.path_obj.is_root():
+            self.dir_stack.clear()
+        self.path_obj.set(dir)
+        self.show_file_list()
+        
+    def open_file(self, file):
+        path = PathObject(str(self.path_obj))
+        path.set(file)
+        print(file)
+
+    def back(self):
+        if self.path_obj.is_root():
+            return
+        dir = self.path_obj.back()
+        self.dir_stack.append(dir)
+        self.show_file_list()
+
+    def forward(self):
+        if len(self.dir_stack) == 0:
+            return
+        dir = self.dir_stack[-1]
+        self.dir_stack.pop()
+        self.path_obj.add(dir)
+        self.show_file_list()
+
+    def path_error_popup(self):
+        msg = QMessageBox()
+        msg.setWindowTitle("Error")
+        msg.setText("Invalid path!")
+        msg.setIcon(QMessageBox.Critical)
+        msg.exec_()
+
+    def show_count(self):
+        count_text = ""
+        count = self.file_count + self.dir_count
+
+        if count == 1:
+            count_text += "1 item ("
+        else:
+            count_text += f"{count} items ("
+
+        if self.dir_count == 1:
+            count_text += "1 folder, "
+        else:
+            count_text += f"{self.dir_count} dirs, "
+
+        if self.file_count == 1:
+            count_text += "1 file)"
+        else:
+            count_text += f"{self.file_count} files)"
+
+        self.status_bar.showMessage(count_text)
+

+ 118 - 64
ui/AddFile.ui

@@ -9,8 +9,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>374</width>
-    <height>270</height>
+    <width>562</width>
+    <height>469</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -91,68 +91,122 @@
         </layout>
        </item>
        <item>
-        <widget class="QTableWidget" name="tableWidget">
-         <property name="editTriggers">
-          <set>QAbstractItemView::NoEditTriggers</set>
-         </property>
-         <attribute name="horizontalHeaderVisible">
-          <bool>true</bool>
-         </attribute>
-         <attribute name="horizontalHeaderHighlightSections">
-          <bool>true</bool>
-         </attribute>
-         <attribute name="verticalHeaderVisible">
-          <bool>false</bool>
-         </attribute>
-         <row>
-          <property name="text">
-           <string>新建行</string>
-          </property>
-         </row>
-         <column>
-          <property name="text">
-           <string>path</string>
-          </property>
-         </column>
-        </widget>
-       </item>
-      </layout>
-     </item>
-     <item>
-      <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,0">
-       <item>
-        <spacer name="horizontalSpacer">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>40</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QPushButton" name="bnt_OK">
-         <property name="text">
-          <string>OK</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QPushButton" name="bnt_Cancel">
-         <property name="text">
-          <string>Cancel</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QPushButton" name="bnt_Apply">
-         <property name="text">
-          <string>Apply</string>
-         </property>
-        </widget>
+        <layout class="QVBoxLayout" name="verticalLayout_3">
+         <item>
+          <widget class="QTableWidget" name="fileTable">
+           <property name="font">
+            <font>
+             <pointsize>12</pointsize>
+            </font>
+           </property>
+           <property name="autoScrollMargin">
+            <number>0</number>
+           </property>
+           <property name="editTriggers">
+            <set>QAbstractItemView::NoEditTriggers</set>
+           </property>
+           <property name="selectionMode">
+            <enum>QAbstractItemView::SingleSelection</enum>
+           </property>
+           <property name="selectionBehavior">
+            <enum>QAbstractItemView::SelectRows</enum>
+           </property>
+           <property name="showGrid">
+            <bool>false</bool>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+           <attribute name="horizontalHeaderVisible">
+            <bool>false</bool>
+           </attribute>
+           <attribute name="horizontalHeaderMinimumSectionSize">
+            <number>0</number>
+           </attribute>
+           <attribute name="horizontalHeaderDefaultSectionSize">
+            <number>5</number>
+           </attribute>
+           <attribute name="verticalHeaderVisible">
+            <bool>false</bool>
+           </attribute>
+           <attribute name="verticalHeaderCascadingSectionResizes">
+            <bool>false</bool>
+           </attribute>
+           <attribute name="verticalHeaderMinimumSectionSize">
+            <number>17</number>
+           </attribute>
+           <attribute name="verticalHeaderDefaultSectionSize">
+            <number>17</number>
+           </attribute>
+           <attribute name="verticalHeaderHighlightSections">
+            <bool>false</bool>
+           </attribute>
+           <column>
+            <property name="text">
+             <string>新建列</string>
+            </property>
+           </column>
+          </widget>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0">
+           <item>
+            <spacer name="horizontalSpacer_2">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+           <item>
+            <widget class="QComboBox" name="comboBox"/>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,0">
+           <item>
+            <spacer name="horizontalSpacer">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+           <item>
+            <widget class="QPushButton" name="bnt_OK">
+             <property name="text">
+              <string>OK</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QPushButton" name="bnt_Cancel">
+             <property name="text">
+              <string>Cancel</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QPushButton" name="bnt_Apply">
+             <property name="text">
+              <string>Apply</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
        </item>
       </layout>
      </item>

+ 0 - 210
ui/Analyze-bak.ui

@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>AnalyzeWindow</class>
- <widget class="QMainWindow" name="AnalyzeWindow">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>446</width>
-    <height>354</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>MainWindow</string>
-  </property>
-  <widget class="QWidget" name="centralwidget">
-   <layout class="QGridLayout" name="gridLayout">
-    <item row="0" column="0">
-     <layout class="QVBoxLayout" name="verticalLayout">
-      <item>
-       <layout class="QHBoxLayout" name="horizontalLayout">
-        <item>
-         <widget class="QTableWidget" name="tableWidget">
-          <property name="editTriggers">
-           <set>QAbstractItemView::NoEditTriggers</set>
-          </property>
-          <property name="selectionMode">
-           <enum>QAbstractItemView::SingleSelection</enum>
-          </property>
-          <property name="selectionBehavior">
-           <enum>QAbstractItemView::SelectRows</enum>
-          </property>
-          <attribute name="horizontalHeaderVisible">
-           <bool>false</bool>
-          </attribute>
-          <attribute name="horizontalHeaderCascadingSectionResizes">
-           <bool>false</bool>
-          </attribute>
-          <attribute name="horizontalHeaderDefaultSectionSize">
-           <number>111</number>
-          </attribute>
-          <attribute name="horizontalHeaderHighlightSections">
-           <bool>true</bool>
-          </attribute>
-          <attribute name="verticalHeaderVisible">
-           <bool>false</bool>
-          </attribute>
-          <attribute name="verticalHeaderCascadingSectionResizes">
-           <bool>false</bool>
-          </attribute>
-          <row>
-           <property name="text">
-            <string>新建行</string>
-           </property>
-          </row>
-          <row>
-           <property name="text">
-            <string>新建行</string>
-           </property>
-          </row>
-          <row>
-           <property name="text">
-            <string>新建行</string>
-           </property>
-          </row>
-          <column>
-           <property name="text">
-            <string>新建列</string>
-           </property>
-          </column>
-          <column>
-           <property name="text">
-            <string>新建列</string>
-           </property>
-          </column>
-         </widget>
-        </item>
-        <item>
-         <layout class="QVBoxLayout" name="verticalLayout_2">
-          <item>
-           <widget class="QPushButton" name="bnt_AddFile">
-            <property name="text">
-             <string>Add File</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QPushButton" name="pushButton_5">
-            <property name="text">
-             <string>Add Path</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QPushButton" name="bnt_Remove">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="text">
-             <string>Remove</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <spacer name="verticalSpacer">
-            <property name="orientation">
-             <enum>Qt::Vertical</enum>
-            </property>
-            <property name="sizeHint" stdset="0">
-             <size>
-              <width>20</width>
-              <height>40</height>
-             </size>
-            </property>
-           </spacer>
-          </item>
-          <item>
-           <widget class="QPushButton" name="pushButton_7">
-            <property name="text">
-             <string>Remove All</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <spacer name="verticalSpacer_2">
-            <property name="orientation">
-             <enum>Qt::Vertical</enum>
-            </property>
-            <property name="sizeHint" stdset="0">
-             <size>
-              <width>20</width>
-              <height>40</height>
-             </size>
-            </property>
-           </spacer>
-          </item>
-         </layout>
-        </item>
-       </layout>
-      </item>
-      <item>
-       <layout class="QHBoxLayout" name="horizontalLayout_2">
-        <item>
-         <spacer name="horizontalSpacer">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item>
-         <widget class="QPushButton" name="pushButton_2">
-          <property name="text">
-           <string>OK</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QPushButton" name="pushButton_4">
-          <property name="text">
-           <string>Cancel</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QPushButton" name="pushButton_3">
-          <property name="text">
-           <string>Apply</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <spacer name="horizontalSpacer_2">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-       </layout>
-      </item>
-     </layout>
-    </item>
-   </layout>
-  </widget>
-  <widget class="QMenuBar" name="menubar">
-   <property name="geometry">
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>446</width>
-     <height>23</height>
-    </rect>
-   </property>
-  </widget>
-  <widget class="QStatusBar" name="statusbar"/>
- </widget>
- <resources/>
- <connections/>
-</ui>

+ 20 - 40
ui/Analyze.py

@@ -3,32 +3,10 @@ from PySide2.QtWidgets import *
 from PySide2.QtCore import *
 from PySide2.QtGui import *
 from ui.ui_Analyze import Ui_AnalyzeWindow
-from ui.ui_AddFile import Ui_AddFileWindow
+from ui.AddFile import AddFileWindow
 import GuiType
 
 
-class AddFileWindow(Ui_AddFileWindow, QDialog):
-    def __init__(self, parent) -> None:
-        super().__init__()
-        self.file_suffix = [".f *.lst *.list *.v *.sv", "All Files"]
-        self.setupUi(self)
-        self.init_tableWidget()
-        
-        self.move(parent.x()+(parent.width()-self.width())/2,parent.y()+(parent.height()-self.height())/2)
-        self.show()
-        
-    def init_tableWidget(self):
-        # 表格随窗口适应大小
-        self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
-        self.tableWidget.setHorizontalHeaderItem(0, QTableWidgetItem("/etc"))
-        comBox1 = QComboBox()
-        comBox1.addItems(self.file_suffix)
-        self.tableWidget.setCellWidget(0,0,comBox1)
-        
-        files = os.listdir(os.getcwd())
-        for i in range(0, 3):
-            self.tableWidget.insertRow(i)
-            self.tableWidget.setItem(i,0, QTableWidgetItem(files[i]))
             
     
 
@@ -40,10 +18,11 @@ class AnalyzeWindow(Ui_AnalyzeWindow, QDialog):
         self.setupUi(self)
         self.init_tableWidget()
         
-        self.bnt_AddFile.clicked.connect(self.add_file_dialog)
-        self.bnt_AddPath.clicked.connect(self.add_file_windows)
-        self.bnt_Remove.clicked.connect(self.add_file_windows)
-        self.bnt_RemoveAll.clicked.connect(self.add_file_windows)
+        self.bnt_AddFile.clicked.connect(self.add_file_windows)
+        self.tableWidget.mousePressEvent = self.mouseclick
+        # self.bnt_AddPath.clicked.connect(self.add_file_windows)
+        # self.bnt_Remove.clicked.connect(self.add_file_windows)
+        # self.bnt_RemoveAll.clicked.connect(self.add_file_windows)
         
         self.move(mainWindow.x()+(mainWindow.width()-self.width())/2,mainWindow.y()+(mainWindow.height()-self.height())/2)
         self.show()
@@ -69,29 +48,30 @@ class AnalyzeWindow(Ui_AnalyzeWindow, QDialog):
         self.tableWidget.setItem(2,1, QTableWidgetItem("/"))
     
     def add_file_windows(self):
-        dialog = AddFileWindow(self)
+        dialog = AddFileWindow(self, os.getcwd())
         dialog.exec_()
 
     def add_file_dialog(self):
         f = QFileDialog()
-        res= f.getOpenFileName(filter="Verilog or Netlist Files((*.v);;SystemVerilog Files(*.sv);;Filelists(*.f *.lst *.list);;All files(*.*)")
+        res= f.getOpenFileName(filter="Verilog or Netlist Files(*.v);;SystemVerilog Files(*.sv);;Filelists(*.f *.lst *.list);;All files(*.*)")
         print(res)
         
-    def mousePressEvent(self, event:QPoint):
-        print('event')
+    def mouseclick(self, event:QMouseEvent):
         p = event.pos()
-        index = QModelIndex(p)
-        if not index.isValid():
-            print('not valide')
-            # setCurrentIndex(QModelIndex())
-            # emit sigPressEmpty()
-            return
-        super().mousePressEvent(event)
+        index = self.tableWidget.indexAt(p)
+        if index.row() == -1:
+            self.tableWidget.clearSelection()
+        else:
+            self.tableWidget.selectRow(index.row())
     
     def itemClicked(self):
         print("itemClicked")
     def clicked(self):
         print("clicked")
+        
     def itemSelectionChanged(self):
-        self.bnt_Remove.setEnabled(True)
-        print("itemSelectionChanged")
+        if self.tableWidget.selectedItems():
+            self.bnt_Remove.setEnabled(True)
+        else:
+            self.bnt_Remove.setEnabled(False)
+        # print("itemSelectionChanged", self.tableWidget.selectedItems())

+ 2 - 2
ui/Analyze.ui

@@ -9,8 +9,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>400</width>
-    <height>300</height>
+    <width>478</width>
+    <height>384</height>
    </rect>
   </property>
   <property name="windowTitle">

+ 1 - 1
ui/__init__.py

@@ -1 +1 @@
-import ui
+from ui import *

+ 460 - 0
ui/addressBar/addressbar.py

@@ -0,0 +1,460 @@
+"""
+Qt navigation bar with breadcrumbs
+Andrey Makarov, 2019
+"""
+
+import os
+import platform
+from pathlib import Path
+from typing import Union
+
+from qtpy import QtCore, QtGui, QtWidgets
+from qtpy.QtCore import Qt
+
+from .layouts import LeftHBoxLayout
+from .models_views import FilenameModel, MenuListView
+from .stylesheet import style_root_toolbutton
+
+if platform.system() == "Windows":
+    from .platform.windows import get_path_label
+
+TRANSP_ICON_SIZE = 40, 40  # px, size of generated semi-transparent icons
+cwd_path = Path()  # working dir (.) https://stackoverflow.com/q/51330297
+
+
+class BreadcrumbsAddressBar(QtWidgets.QFrame):
+    "Windows Explorer-like address bar"
+    listdir_error = QtCore.Signal(Path)  # failed to list a directory
+    path_error = QtCore.Signal(Path)  # entered path does not exist
+    path_selected = QtCore.Signal(Path)
+
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.os_type = platform.system()
+
+        self.style_crumbs = StyleProxy(
+            QtWidgets.QStyleFactory.create(
+                QtWidgets.QApplication.instance().style().objectName()
+            ),
+            QtGui.QPixmap("iconfinder_icon-ios7-arrow-right_211607.png")
+        )
+
+        layout = QtWidgets.QHBoxLayout(self)
+
+        self.file_ico_prov = QtWidgets.QFileIconProvider()
+        self.fs_model = FilenameModel('dirs')
+
+        pal = self.palette()
+        pal.setColor(QtGui.QPalette.Background,
+                     pal.color(QtGui.QPalette.Base))
+        self.setPalette(pal)
+        self.setAutoFillBackground(True)
+        self.setFrameShape(self.StyledPanel)
+        self.layout().setContentsMargins(4, 0, 0, 0)
+        self.layout().setSpacing(0)
+
+        self.path_icon = QtWidgets.QLabel(self)
+        layout.addWidget(self.path_icon)
+
+        # Edit presented path textually
+        self.line_address = QtWidgets.QLineEdit(self)
+        self.line_address.setFrame(False)
+        self.line_address.hide()
+        self.line_address.keyPressEvent = self.line_address_keyPressEvent
+        self.line_address.focusOutEvent = self.line_address_focusOutEvent
+        self.line_address.contextMenuEvent = self.line_address_contextMenuEvent
+        layout.addWidget(self.line_address)
+        # Add QCompleter to address line
+        completer = self.init_completer(self.line_address, self.fs_model)
+        completer.activated.connect(self.set_path)
+
+        # Container for `btn_crumbs_hidden`, `crumbs_panel`, `switch_space`
+        self.crumbs_container = QtWidgets.QWidget(self)
+        crumbs_cont_layout = QtWidgets.QHBoxLayout(self.crumbs_container)
+        crumbs_cont_layout.setContentsMargins(0, 0, 0, 0)
+        crumbs_cont_layout.setSpacing(0)
+        layout.addWidget(self.crumbs_container)
+
+        # Monitor breadcrumbs under cursor and switch popup menus
+        self.mouse_pos_timer = QtCore.QTimer(self)
+        self.mouse_pos_timer.timeout.connect(self.mouse_pos_timer_event)
+
+        # Hidden breadcrumbs menu button
+        self.btn_root_crumb = QtWidgets.QToolButton(self)
+        self.btn_root_crumb.setAutoRaise(True)
+        self.btn_root_crumb.setPopupMode(QtWidgets.QToolButton.InstantPopup)
+        self.btn_root_crumb.setArrowType(Qt.RightArrow)
+        self.btn_root_crumb.setStyleSheet(style_root_toolbutton)
+        self.btn_root_crumb.setMinimumSize(self.btn_root_crumb.minimumSizeHint())
+        crumbs_cont_layout.addWidget(self.btn_root_crumb)
+        menu = QtWidgets.QMenu(self.btn_root_crumb)  # FIXME:
+        menu.aboutToShow.connect(self._hidden_crumbs_menu_show)
+        menu.aboutToHide.connect(self.mouse_pos_timer.stop)
+        self.btn_root_crumb.setMenu(menu)
+        self.init_rootmenu_places(menu)  # Desktop, Home, Downloads...
+        self.update_rootmenu_devices()  # C:, D:...
+
+        # Container for breadcrumbs
+        self.crumbs_panel = QtWidgets.QWidget(self)
+        crumbs_layout = LeftHBoxLayout(self.crumbs_panel)
+        crumbs_layout.widget_state_changed.connect(self.crumb_hide_show)
+        crumbs_layout.setContentsMargins(0, 0, 0, 0)
+        crumbs_layout.setSpacing(0)
+        crumbs_cont_layout.addWidget(self.crumbs_panel)
+
+        # Clicking on empty space to the right puts the bar into edit mode
+        self.switch_space = QtWidgets.QWidget(self)
+        # s_policy = self.switch_space.sizePolicy()
+        # s_policy.setHorizontalStretch(1)
+        # self.switch_space.setSizePolicy(s_policy)
+        self.switch_space.mouseReleaseEvent = self.switch_space_mouse_up
+        # crumbs_cont_layout.addWidget(self.switch_space)
+        crumbs_layout.set_space_widget(self.switch_space)
+
+        self.btn_browse = QtWidgets.QToolButton(self)
+        self.btn_browse.setAutoRaise(True)
+        self.btn_browse.setText("...")
+        self.btn_browse.setToolTip("Browse for folder")
+        self.btn_browse.clicked.connect(self._browse_for_folder)
+        layout.addWidget(self.btn_browse)
+
+        self.setMaximumHeight(self.line_address.height())  # FIXME:
+
+        self.ignore_resize = False
+        self.path_ = None
+        self.set_path(Path())
+
+    @staticmethod
+    def init_completer(edit_widget, model):
+        "Init QCompleter to work with filesystem"
+        completer = QtWidgets.QCompleter(edit_widget)
+        completer.setCaseSensitivity(Qt.CaseInsensitive)
+        completer.setModel(model)
+        # Optimize performance https://stackoverflow.com/a/33454284/1119602
+        popup = completer.popup()
+        popup.setUniformItemSizes(True)
+        popup.setLayoutMode(QtWidgets.QListView.Batched)
+        edit_widget.setCompleter(completer)
+        edit_widget.textEdited.connect(model.setPathPrefix)
+        return completer
+
+    def get_icon(self, path: Union[str, Path]):
+        "Path -> QIcon"
+        fileinfo = QtCore.QFileInfo(str(path))
+        dat = self.file_ico_prov.icon(fileinfo)
+        if fileinfo.isHidden():
+            pmap = QtGui.QPixmap(*TRANSP_ICON_SIZE)
+            pmap.fill(Qt.transparent)
+            painter = QtGui.QPainter(pmap)
+            painter.setOpacity(0.5)
+            dat.paint(painter, 0, 0, *TRANSP_ICON_SIZE)
+            painter.end()
+            dat = QtGui.QIcon(pmap)
+        return dat
+
+    def line_address_contextMenuEvent(self, event):
+        self.line_address_context_menu_flag = True
+        QtWidgets.QLineEdit.contextMenuEvent(self.line_address, event)
+
+    def line_address_focusOutEvent(self, event):
+        if getattr(self, 'line_address_context_menu_flag', False):
+            self.line_address_context_menu_flag = False
+            return  # do not cancel edit on context menu
+        self._cancel_edit()
+
+    def _hidden_crumbs_menu_show(self):
+        "SLOT: fill menu with hidden breadcrumbs list"
+        self.mouse_pos_timer.start(100)
+        menu = self.sender()
+        if hasattr(self, 'actions_hidden_crumbs'):
+            for action in self.actions_hidden_crumbs:
+                menu.removeAction(action)
+        self.actions_hidden_crumbs = []
+
+        first_action = menu.actions()[0]  # places section separator
+        for i in self.crumbs_panel.layout().widgets('hidden'):
+            action = QtWidgets.QAction(self.get_icon(i.path), i.text(), menu)
+            action.path = i.path
+            action.triggered.connect(self.set_path)
+            menu.insertAction(first_action, action)
+            self.actions_hidden_crumbs.append(action)
+            first_action = action
+
+    def init_rootmenu_places(self, menu):
+        "Init common places actions in menu"
+        menu.addSeparator()
+        QSP = QtCore.QStandardPaths
+        uname = os.environ.get('USER') or os.environ.get('USERNAME') or "Home"
+        for name, path in (
+                ("Desktop", QSP.writableLocation(QSP.DesktopLocation)),
+                (uname, QSP.writableLocation(QSP.HomeLocation)),
+                ("Documents", QSP.writableLocation(QSP.DocumentsLocation)),
+                ("Downloads", QSP.writableLocation(QSP.DownloadLocation)),
+                ):
+            if self.os_type == "Windows":
+                name = self.get_path_label(path)
+            action = menu.addAction(self.get_icon(path), name)
+            action.path = path
+            action.triggered.connect(self.set_path)
+
+    def get_path_label(self, drive_path):
+        "Try to get path label using Shell32 on Windows"
+        return get_path_label(drive_path.replace("/", "\\"))
+
+    @staticmethod
+    def list_network_locations():
+        "List (name, path) locations in Network Shortcuts folder on Windows"
+        HOME = QtCore.QStandardPaths.HomeLocation
+        user_folder = QtCore.QStandardPaths.writableLocation(HOME)
+        network_shortcuts = user_folder + "/AppData/Roaming/Microsoft/Windows/Network Shortcuts"
+        for i in Path(network_shortcuts).iterdir():
+            if not i.is_dir():
+                continue
+            link = Path(i) / "target.lnk"
+            if not link.exists():
+                continue
+            path = QtCore.QFileInfo(str(link)).symLinkTarget()
+            if path:  # `symLinkTarget` doesn't read e.g. FTP links
+                yield i.name, path
+
+    def update_rootmenu_devices(self):
+        "Init or rebuild device actions in menu"
+        menu = self.btn_root_crumb.menu()
+        if hasattr(self, 'actions_devices'):
+            for action in self.actions_devices:
+                menu.removeAction(action)
+        self.actions_devices = [menu.addSeparator()]
+        for i in QtCore.QStorageInfo.mountedVolumes():  # QDir.drives():
+            path, label = i.rootPath(), i.displayName()
+            if label == path and self.os_type == "Windows":
+                label = self.get_path_label(path)
+            elif self.os_type == "Linux" and not path.startswith("/media"):
+                # Add to list only volumes in /media
+                continue
+            caption = "%s (%s)" % (label, path.rstrip(r"\/"))
+            action = menu.addAction(self.get_icon(path), caption)
+            action.path = path
+            action.triggered.connect(self.set_path)
+            self.actions_devices.append(action)
+        if self.os_type == "Windows":  # Network locations
+            for label, path in self.list_network_locations():
+                action = menu.addAction(self.get_icon(path), label)
+                action.path = path
+                action.triggered.connect(self.set_path)
+                self.actions_devices.append(action)
+
+    def _browse_for_folder(self):
+        path = QtWidgets.QFileDialog.getExistingDirectory(
+            self, "Choose folder", str(self.path()))
+        if path:
+            self.set_path(path)
+
+    def line_address_keyPressEvent(self, event):
+        "Actions to take after a key press in text address field"
+        if event.key() == Qt.Key_Escape:
+            self._cancel_edit()
+        elif event.key() in (Qt.Key_Return, Qt.Key_Enter):
+            self.set_path(self.line_address.text())
+            self._show_address_field(False)
+        # elif event.text() == os.path.sep:  # FIXME: separator cannot be pasted
+        #     print('fill completer data here')
+        #     paths = [str(i) for i in
+        #              Path(self.line_address.text()).iterdir() if i.is_dir()]
+        #     self.completer.model().setStringList(paths)
+        else:
+            QtWidgets.QLineEdit.keyPressEvent(self.line_address, event)
+
+    def _clear_crumbs(self):
+        layout = self.crumbs_panel.layout()
+        while layout.count():
+            widget = layout.takeAt(0).widget()
+            if widget:
+                # Unset style or `StyleProxy.drawPrimitive` is called once with
+                # mysterious `QWidget` instead of `QToolButton` (Windows 7)
+                widget.setStyle(None)
+                widget.deleteLater()
+    
+    @staticmethod
+    def path_title(path: Path):
+        "Get folder name or drive name"
+        # FIXME: C:\ has no name. Use rstrip on Windows only?
+        return path.name or str(path).upper().rstrip(os.path.sep)
+
+    def _insert_crumb(self, path):
+        btn = QtWidgets.QToolButton(self.crumbs_panel)
+        btn.setAutoRaise(True)
+        btn.setPopupMode(btn.MenuButtonPopup)
+        btn.setStyle(self.style_crumbs)
+        btn.mouseMoveEvent = self.crumb_mouse_move
+        btn.setMouseTracking(True)
+        btn.setText(self.path_title(path))
+        btn.path = path
+        btn.clicked.connect(self.crumb_clicked)
+        menu = MenuListView(btn)
+        menu.aboutToShow.connect(self.crumb_menu_show)
+        menu.setModel(self.fs_model)
+        menu.clicked.connect(self.crumb_menuitem_clicked)
+        menu.activated.connect(self.crumb_menuitem_clicked)
+        menu.aboutToHide.connect(self.mouse_pos_timer.stop)
+        btn.setMenu(menu)
+        self.crumbs_panel.layout().insertWidget(0, btn)
+        btn.setMinimumSize(btn.minimumSizeHint())  # fixed size breadcrumbs
+        sp = btn.sizePolicy()
+        sp.setVerticalPolicy(sp.Minimum)
+        btn.setSizePolicy(sp)
+        # print(self._check_space_width(btn.minimumWidth()))
+        # print(btn.size(), btn.sizeHint(), btn.minimumSizeHint())
+
+    def crumb_mouse_move(self, event):
+        ...
+        # print('move!')
+
+    def crumb_menuitem_clicked(self, index):
+        "SLOT: breadcrumb menu item was clicked"
+        self.set_path(index.data(Qt.EditRole))
+
+    def crumb_clicked(self):
+        "SLOT: breadcrumb was clicked"
+        self.set_path(self.sender().path)
+
+    def crumb_menu_show(self):
+        "SLOT: fill subdirectory list on menu open"
+        menu = self.sender()
+        self.fs_model.setPathPrefix(str(menu.parent().path) + os.path.sep)
+        menu.clear_selection()  # clear currentIndex after applying new model
+        self.mouse_pos_timer.start(100)
+
+    def set_path(self, path=None):
+        """
+        Set path displayed in this BreadcrumbsAddressBar
+        Returns `False` if path does not exist or permission error.
+        Can be used as a SLOT: `sender().path` is used if `path` is `None`)
+        """
+        path, emit_err = Path(path or self.sender().path), None
+        try:  # C: -> C:\, folder\..\folder -> folder
+            path = path.resolve()
+        except PermissionError:
+            emit_err = self.listdir_error
+        if not path.exists():
+            emit_err = self.path_error
+        self._cancel_edit()  # exit edit mode
+        if emit_err:  # permission error or path does not exist
+            emit_err.emit(path)
+            return False
+        self._clear_crumbs()
+        self.path_ = path
+        self.line_address.setText(str(path))
+        self._insert_crumb(path)
+        for i in path.parents:
+            if i == cwd_path:
+                break
+            self._insert_crumb(i)
+        self.path_icon.setPixmap(self.get_icon(self.path_).pixmap(16, 16))
+        self.path_selected.emit(self.path_)
+        return True
+
+    def _cancel_edit(self):
+        "Set edit line text back to current path and switch to view mode"
+        self.line_address.setText(str(self.path()))  # revert path
+        self._show_address_field(False)  # switch back to breadcrumbs view
+
+    def path(self):
+        "Get path displayed in this BreadcrumbsAddressBar"
+        return self.path_
+
+    def switch_space_mouse_up(self, event):
+        "EVENT: switch_space mouse clicked"
+        if event.button() != Qt.LeftButton:  # left click only
+            return
+        self._show_address_field(True)
+
+    def _show_address_field(self, b_show):
+        "Show text address field"
+        if b_show:
+            self.crumbs_container.hide()
+            self.line_address.show()
+            self.line_address.setFocus()
+            self.line_address.selectAll()
+        else:
+            self.line_address.hide()
+            self.crumbs_container.show()
+
+    def crumb_hide_show(self, widget, state:bool):
+        "SLOT: a breadcrumb is hidden/removed or shown"
+        layout = self.crumbs_panel.layout()
+        arrow = Qt.LeftArrow if layout.count_hidden() > 0 else Qt.RightArrow
+        self.btn_root_crumb.setArrowType(arrow)
+        # if layout.count_hidden() > 0:
+        #     ico = QtGui.QIcon("iconfinder_icon-ios7-arrow-left_211689.png")
+        # else:
+        #     ico = QtGui.QIcon("iconfinder_icon-ios7-arrow-right_211607.png")
+        # self.btn_root_crumb.setIcon(ico)
+
+    def minimumSizeHint(self):
+        # print(self.layout().minimumSize().width())
+        return QtCore.QSize(150, self.line_address.height())
+
+    def mouse_pos_timer_event(self):
+        "Monitor breadcrumbs under cursor and switch popup menus"
+        pos = QtGui.QCursor.pos()
+        app = QtCore.QCoreApplication.instance()
+        w = app.widgetAt(pos)
+        active_menu = app.activePopupWidget()
+        if (w and isinstance(w, QtWidgets.QToolButton) and
+            w is not active_menu.parent() and
+            (w is self.btn_root_crumb or w.parent() is self.crumbs_panel)
+        ):
+            active_menu.close()
+            w.showMenu()
+
+class StyleProxy(QtWidgets.QProxyStyle):
+    win_modern = ("windowsxp", "windowsvista")
+
+    def __init__(self, style, arrow_pix):
+        super().__init__(style)
+        self.arrow_pix = arrow_pix
+        self.stylename = self.baseStyle().objectName()
+
+    def drawPrimitive(self, pe, opt, p: QtGui.QPainter, widget):
+        # QToolButton elements:
+        # 13: PE_PanelButtonCommand (Fusion) - Fusion button background, called from 15 and 24 calls
+        # 15: PE_PanelButtonTool (Windows, Fusion) - left part background (XP/Vista styles do not draw it with `drawPrimitive`)
+        # 19: PE_IndicatorArrowDown (Windows, Fusion) - right part down arrow (XP/Vista styles draw it in 24 call)
+        # 24: PE_IndicatorButtonDropDown (Windows, XP, Vista, Fusion) - right part background (+arrow for XP/Vista)
+        # 
+        # Arrow is drawn along with PE_IndicatorButtonDropDown (XP/Vista)
+        # https://github.com/qt/qtbase/blob/0c51a8756377c40180619046d07b35718fcf1784/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp#L1406
+        # https://github.com/qt/qtbase/blob/0c51a8756377c40180619046d07b35718fcf1784/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp#L666
+        # drawBackground paints with DrawThemeBackgroundEx WinApi function
+        # https://docs.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-drawthemebackgroundex
+        if (self.stylename in self.win_modern and
+            pe == self.PE_IndicatorButtonDropDown
+            ):
+            pe = self.PE_IndicatorArrowDown  # see below
+        if pe == self.PE_IndicatorArrowDown:
+            opt_ = QtWidgets.QStyleOptionToolButton()
+            widget.initStyleOption(opt_)
+            rc = super().subControlRect(self.CC_ToolButton, opt_,
+                                        self.SC_ToolButtonMenu, widget)
+            if self.stylename in self.win_modern:
+                # By default PE_IndicatorButtonDropDown draws arrow along
+                # with right button art. Draw 2px clipped left part instead
+                path = QtGui.QPainterPath()
+                path.addRect(QtCore.QRectF(rc))
+                p.setClipPath(path)
+                super().drawPrimitive(self.PE_PanelButtonTool, opt, p, widget)
+            # centered square
+            rc.moveTop(int((rc.height() - rc.width()) / 2))
+            rc.setHeight(rc.width())
+            # p.setRenderHint(p.Antialiasing)
+            p.drawPixmap(rc, self.arrow_pix, QtCore.QRect())
+        else:
+            super().drawPrimitive(pe, opt, p, widget)
+
+    def subControlRect(self, cc, opt, sc, widget):
+        rc = super().subControlRect(cc, opt, sc, widget)
+        if (self.stylename in self.win_modern and
+            sc == self.SC_ToolButtonMenu
+            ):
+            rc.adjust(-2, 0, 0, 0)  # cut 2 left pixels to create flat edge
+        return rc

+ 114 - 0
ui/addressBar/layouts.py

@@ -0,0 +1,114 @@
+from qtpy import QtCore, QtWidgets
+from qtpy.QtCore import Qt
+
+class LeftHBoxLayout(QtWidgets.QHBoxLayout):
+    '''
+    Left aligned horizontal layout.
+    Hides items similar to Windows Explorer address bar.
+    '''
+    # Signal is emitted when an item is hidden/shown or removed with `takeAt`
+    widget_state_changed = QtCore.Signal(object, bool)
+
+    def __init__(self, parent=None, minimal_space=0.1):
+        super().__init__(parent)
+        self.first_visible = 0
+        self.set_space_widget()
+        self.set_minimal_space(minimal_space)
+
+    def set_space_widget(self, widget=None, stretch=1):
+        """
+        Set widget to be used to fill empty space to the right
+        If `widget`=None the stretch item is used (by default)
+        """
+        super().takeAt(self.count())
+        if widget:
+            super().addWidget(widget, stretch)
+        else:
+            self.addStretch(stretch)
+
+    def space_widget(self):
+        "Widget used to fill free space"
+        return self[self.count()]
+
+    def setGeometry(self, rc:QtCore.QRect):
+        "`rc` - layout's rectangle w/o margins"
+        super().setGeometry(rc)  # perform the layout
+        min_sp = self.minimal_space()
+        if min_sp < 1:  # percent
+            min_sp *= rc.width()
+        free_space = self[self.count()].geometry().width() - min_sp
+        if free_space < 0 and self.count_visible() > 1:  # hide more items
+            widget = self[self.first_visible].widget()
+            widget.hide()
+            self.first_visible += 1
+            self.widget_state_changed.emit(widget, False)
+        elif free_space > 0 and self.count_hidden():  # show more items
+            widget = self[self.first_visible-1].widget()
+            w_width = widget.width() + self.spacing()
+            if w_width <= free_space:  # enough space to show next item
+                # setGeometry is called after show
+                QtCore.QTimer.singleShot(0, widget.show)
+                self.first_visible -= 1
+                self.widget_state_changed.emit(widget, True)
+
+    def count_visible(self):
+        "Count of visible widgets"
+        return self.count(visible=True)
+
+    def count_hidden(self):
+        "Count of hidden widgets"
+        return self.count(visible=False)
+
+    def minimumSize(self):
+        margins = self.contentsMargins()
+        return QtCore.QSize(margins.left() + margins.right(),
+                            margins.top() + 24 + margins.bottom())
+
+    def addWidget(self, widget, stretch=0, alignment=None):
+        "Append widget to layout, make its width fixed"
+        # widget.setMinimumSize(widget.minimumSizeHint())  # FIXME:
+        super().insertWidget(self.count(), widget, stretch,
+                             alignment or Qt.Alignment(0))
+
+    def count(self, visible=None):
+        "Count of items in layout: `visible`=True|False(hidden)|None(all)"
+        cnt = super().count() - 1  # w/o last stretchable item
+        if visible is None:  # all items
+            return cnt
+        if visible:  # visible items
+            return cnt - self.first_visible
+        return self.first_visible  # hidden items
+
+    def widgets(self, state='all'):
+        "Iterate over child widgets"
+        for i in range(self.first_visible if state=='visible' else 0,
+                       self.first_visible if state=='hidden' else self.count()
+                       ):
+            yield self[i].widget()
+
+    def set_minimal_space(self, value):
+        """
+        Set minimal size of space area to the right:
+        [0.0, 1.0) - % of the full width
+        [1, ...) - size in pixels
+        """
+        self._minimal_space = value
+        self.invalidate()
+
+    def minimal_space(self):
+        "See `set_minimal_space`"
+        return self._minimal_space
+
+    def __getitem__(self, index):
+        "`itemAt` slices wrapper"
+        if index < 0:
+            index = self.count() + index
+        return self.itemAt(index)
+
+    def takeAt(self, index):
+        "Return an item at the specified `index` and remove it from layout"
+        if index < self.first_visible:
+            self.first_visible -= 1
+        item = super().takeAt(index)
+        self.widget_state_changed.emit(item.widget(), False)
+        return item

+ 170 - 0
ui/addressBar/models_views.py

@@ -0,0 +1,170 @@
+import os.path
+from pathlib import Path
+from qtpy import QtCore, QtWidgets
+from qtpy.QtCore import Qt
+
+class FilenameModel(QtCore.QStringListModel):
+    """
+    Model used by QCompleter for file name completions.
+    Constructor options:
+    `filter_` (None, 'dirs') - include all entries or folders only
+    `fs_engine` ('qt', 'pathlib') - enumerate files using `QDir` or `pathlib`
+    `icon_provider` (func, 'internal', None) - a function which gets path
+                                               and returns QIcon
+    """
+    def __init__(self, filter_=None, fs_engine='qt', icon_provider='internal'):
+        super().__init__()
+        self.current_path = None
+        self.fs_engine = fs_engine
+        self.filter = filter_
+        if icon_provider == 'internal':
+            self.icons = QtWidgets.QFileIconProvider()
+            self.icon_provider = self.get_icon
+        else:
+            self.icon_provider = icon_provider
+
+    def data(self, index, role):
+        "Get names/icons of files"
+        default = super().data(index, role)
+        if role == Qt.DecorationRole and self.icon_provider:
+            # self.setData(index, dat, role)
+            return self.icon_provider(super().data(index, Qt.DisplayRole))
+        if role == Qt.DisplayRole:
+            return Path(default).name
+        return default
+
+    def get_icon(self, path):
+        "Internal icon provider"
+        return self.icons.icon(QtCore.QFileInfo(path))
+
+    def get_file_list(self, path):
+        "List entries in `path` directory"
+        lst = None
+        if self.fs_engine == 'pathlib':
+            lst = self.sort_paths([i for i in path.iterdir()
+                                   if self.filter != 'dirs' or i.is_dir()])
+        elif self.fs_engine == 'qt':
+            qdir = QtCore.QDir(str(path))
+            qdir.setFilter(qdir.NoDotAndDotDot | qdir.Hidden |
+                (qdir.Dirs if self.filter == 'dirs' else qdir.AllEntries))
+            names = qdir.entryList(sort=QtCore.QDir.DirsFirst |
+                                   QtCore.QDir.LocaleAware)
+            lst = [str(path / i) for i in names]
+        return lst
+
+    @staticmethod
+    def sort_paths(paths):
+        "Windows-Explorer-like filename sorting (for 'pathlib' engine)"
+        dirs, files = [], []
+        for i in paths:
+            if i.is_dir():
+                dirs.append(str(i))
+            else:
+                files.append(str(i))
+        return sorted(dirs, key=str.lower) + sorted(files, key=str.lower)
+
+    def setPathPrefix(self, prefix):
+        path = Path(prefix)
+        if not prefix.endswith(os.path.sep):
+            path = path.parent
+        if path == self.current_path:
+            return  # already listed
+        if not path.exists():
+            return  # wrong path
+        self.setStringList(self.get_file_list(path))
+        self.current_path = path
+
+
+class MenuListView(QtWidgets.QMenu):
+    """
+    QMenu with QListView.
+    Supports `activated`, `clicked`, `setModel`.
+    """
+    max_visible_items = 16
+
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.listview = lv = QtWidgets.QListView()
+        lv.setFrameShape(lv.NoFrame)
+        lv.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+        pal = lv.palette()
+        pal.setColor(pal.Base, self.palette().color(pal.Window))
+        lv.setPalette(pal)
+
+        act_wgt = QtWidgets.QWidgetAction(self)
+        act_wgt.setDefaultWidget(lv)
+        self.addAction(act_wgt)
+
+        self.activated = lv.activated
+        self.clicked = lv.clicked
+        self.setModel = lv.setModel
+
+        lv.sizeHint = self.size_hint
+        lv.minimumSizeHint = self.size_hint
+        lv.mousePressEvent = self.mouse_press_event
+        lv.mouseMoveEvent = self.update_current_index
+        lv.setMouseTracking(True)  # receive mouse move events
+        lv.leaveEvent = self.clear_selection
+        lv.mouseReleaseEvent = self.mouse_release_event
+        lv.keyPressEvent = self.key_press_event
+        lv.setFocusPolicy(Qt.NoFocus)  # no focus rect
+        lv.setFocus()
+
+        self.last_index = QtCore.QModelIndex()  # selected index
+        self.flag_mouse_l_pressed = False
+
+    def key_press_event(self, event):
+        key = event.key()
+        if key in (Qt.Key_Return, Qt.Key_Enter):
+            if self.last_index.isValid():
+                self.activated.emit(self.last_index)
+            self.close()
+        elif key == Qt.Key_Escape:
+            self.close()
+        elif key in (Qt.Key_Down, Qt.Key_Up):
+            model = self.listview.model()
+            row_from, row_to = 0, model.rowCount()-1
+            if key == Qt.Key_Down:
+                row_from, row_to = row_to, row_from
+            if self.last_index.row() in (-1, row_from):  # no index=-1
+                index = model.index(row_to, 0)
+            else:
+                shift = 1 if key == Qt.Key_Down else -1
+                index = model.index(self.last_index.row()+shift, 0)
+            self.listview.setCurrentIndex(index)
+            self.last_index = index
+
+    def update_current_index(self, event):
+        self.last_index = self.listview.indexAt(event.pos())
+        self.listview.setCurrentIndex(self.last_index)
+
+    def clear_selection(self, event=None):
+        self.listview.clearSelection()
+        # selectionModel().clear() leaves selected item in Fusion theme
+        self.listview.setCurrentIndex(QtCore.QModelIndex())
+        self.last_index = QtCore.QModelIndex()
+    
+    def mouse_press_event(self, event):
+        if event.button() == Qt.LeftButton:
+            self.flag_mouse_l_pressed = True
+            self.update_current_index(event)
+
+    def mouse_release_event(self, event):
+        """
+        When item is clicked w/ left mouse button close menu, emit `clicked`.
+        Check if there was left button press event inside this widget.
+        """
+        if event.button() == Qt.LeftButton and self.flag_mouse_l_pressed:
+            self.flag_mouse_l_pressed = False
+            if self.last_index.isValid():
+                self.clicked.emit(self.last_index)
+            self.close()
+
+    def size_hint(self):
+        lv = self.listview
+        width = lv.sizeHintForColumn(0)
+        width += lv.verticalScrollBar().sizeHint().width()
+        if isinstance(self.parent(), QtWidgets.QToolButton):
+            width = max(width, self.parent().width())
+        visible_rows = min(self.max_visible_items, lv.model().rowCount())
+        return QtCore.QSize(width, visible_rows * lv.sizeHintForRow(0))

+ 13 - 0
ui/addressBar/stylesheet.py

@@ -0,0 +1,13 @@
+"Stylesheets to customize Qt controls"
+
+style_root_toolbutton = """
+    QToolButton::right-arrow {
+        image: url(ui/addressBar/iconfinder_icon-ios7-arrow-right_211607.png);
+    }
+    QToolButton::left-arrow {
+        image: url(ui/addressBar/iconfinder_icon-ios7-arrow-left_211689.png);
+    }
+    QToolButton::menu-indicator {
+        image: none; /* https://stackoverflow.com/a/19993662 */
+    }
+"""

+ 11 - 0
ui/file_browser/FileObject.py

@@ -0,0 +1,11 @@
+# Object representation of files
+
+class FileObject:
+
+    def __init__(self, name, size, type):
+        self.name = name
+        self.size = size
+        self.type = type
+
+    def __str__(self):
+        return self.name

+ 29 - 0
ui/file_browser/PathObject.py

@@ -0,0 +1,29 @@
+# This class manages the browser's current path
+class PathObject:
+
+    def __init__(self, text):
+        text = text.replace('\\', '/')
+        self.pathtext = text
+
+    def __str__(self):
+        return self.pathtext
+
+    def set(self, text:str):
+        text = str(text).replace('\\', '/')
+        self.pathtext = text
+
+    def add(self, dir):  # adds a folder's name to the end of the path
+        self.pathtext += '/'
+        self.pathtext += str(dir)
+
+    def back(self):  # removes the current folder from the end of the path
+        if "/" not in self.pathtext:
+            return
+        dir = self.pathtext.rsplit('/', 1)[1]
+        self.pathtext = self.pathtext.rsplit('/', 1)[0]
+        return dir
+
+    def is_root(self):
+        if "/" not in self.pathtext:
+            return True
+        return False

+ 76 - 0
ui/file_browser/file_list.py

@@ -0,0 +1,76 @@
+import os
+from .PathObject import PathObject
+from .FileObject import FileObject
+
+filetype = {
+    "txt": "Text",
+    "doc": "Text",
+    "rtf": "Text",
+    "odt": "Text",
+    "mp3": "Music",
+    "flac": "Music",
+    "wav": "Music",
+    "mp4": "Video",
+    "flv": "Video",
+    "mkv": "Video",
+    "avi": "Video",
+    "webm": "Video",
+    "mov": "Video",
+    "jpg": "Image",
+    "jpeg": "Image",
+    "png": "Image",
+    "gif": "Image",
+    "bmp": "Image",
+    "tiff": "Image",
+    "webp": "Image",
+    "exe": "Executable"
+}
+
+# determines a file's type, based on its extension
+def determine_type(file_name):
+    try:
+        extension = str(file_name).rsplit('.', 1)[1]
+        type = filetype.get(extension, "File")
+        return type
+    except:
+        return "File"
+
+
+# creates two FileObject lists, containing all the files and
+# folders found in the path given as argument
+def get_files_dirs(path):
+    # lists for storing files and folders as FileObjects
+    files = []
+    dirs = []
+
+    # inserts all file and folder names (strings) found in the path into file_names
+    file_names = os.listdir(str(path))
+    dir_names = []
+
+    # removes some unwanted folders
+    try:
+        file_names.remove("System Volume Information")
+        file_names.remove("$RECYCLE.BIN")
+        file_names.remove("found.000")
+    except:
+        pass
+
+    # find all folders from file_names and copy them to folder_names
+    for f in file_names:
+        if os.path.isdir(str(path) + "/" + f):
+            dir_names.append(f)
+
+    # removes folders from file_names and creates a FileObject for each folder
+    for dir in dir_names:
+        file_names.remove(dir)
+        dir_obj = FileObject(dir, 0, "Folder")
+        dirs.append(dir_obj)
+
+    # creates a FileObject for each file
+    for f in file_names:
+        size = os.stat(str(path) + "/" + f).st_size
+        type = determine_type(f)
+        file_obj = FileObject(f, size, type)
+        files.append(file_obj)
+
+    return files, dirs

+ 54 - 0
ui/file_browser/filewidget.py

@@ -0,0 +1,54 @@
+from PySide2 import QtCore, QtGui, QtWidgets
+from PySide2.QtWidgets import (QWidget, QLabel, QApplication,
+                             QHBoxLayout, QVBoxLayout, QFormLayout,QStyle )
+from PySide2.QtGui import QPixmap,QIcon,Qt
+
+
+class FileWidget(QWidget):
+    icons = {
+        "Folder": QStyle.SP_DirIcon,
+        "File": QStyle.SP_FileIcon
+    }
+    def __init__(self, text, filetype, height=17):
+        super().__init__()
+        self.setFixedHeight(height)
+        # self.setStyleSheet("*{margin:0px;border: 1px solid red}")
+        self.text = text
+        self.type = filetype
+        self.icon = QLabel(self)
+        self.icon.setFixedHeight(self.height())
+        self.fileName = QLabel(self)
+        self.fileName.setMargin(0)
+        self.fileName.setAlignment(Qt.AlignmentFlag.AlignVCenter)
+        self.setLayout(QFormLayout())
+        self.layout().setMargin(0)
+        # QFormLayout().setFormAlignment(Qt.AlignmentFlag.AlignTop)
+        self.layout().setFormAlignment(Qt.AlignmentFlag.AlignTop)
+        self.layout().setWidget(0, QtWidgets.QFormLayout.LabelRole, self.icon)
+        self.layout().setWidget(0, QtWidgets.QFormLayout.FieldRole, self.fileName)
+
+        self.set_icon()
+
+        self.fileName.setText(text)
+
+    def get_text(self):
+        return self.text
+
+    def set_icon(self):
+        QStyle_SP_ICON = self.icons.get(self.type)
+        if not QStyle_SP_ICON:
+            # 在 file_list.py 中会有其它类型的文件,如:MP3,doc,video 等,图标默认只显示 File 即可
+            QStyle_SP_ICON = self.icons.get("File")
+        
+        icon = QIcon(QApplication.style().standardIcon(QStyle_SP_ICON))
+        m_pix = icon.pixmap(self.icon.size())
+        self.icon.setPixmap(m_pix)
+        self.icon.setScaledContents(True)
+
+
+if __name__ == "__main__":
+    import sys
+    app = QtWidgets.QApplication(sys.argv)
+    Form = FileWidget("Sample Folder", "Folder")
+    Form.show()
+    sys.exit(app.exec_())

+ 0 - 155
ui/ui_AddFile-bak.py

@@ -1,155 +0,0 @@
-# -*- coding: utf-8 -*-
-
-################################################################################
-## Form generated from reading UI file 'AddFile-bak.ui'
-##
-## Created by: Qt User Interface Compiler version 5.15.0
-##
-## WARNING! All changes made in this file will be lost when recompiling UI file!
-################################################################################
-
-from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
-    QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
-from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
-    QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
-    QPixmap, QRadialGradient)
-from PySide2.QtWidgets import *
-
-
-class Ui_AddFileWindows(object):
-    def setupUi(self, AddFileWindows):
-        if not AddFileWindows.objectName():
-            AddFileWindows.setObjectName(u"AddFileWindows")
-        AddFileWindows.resize(469, 418)
-        self.centralwidget = QWidget(AddFileWindows)
-        self.centralwidget.setObjectName(u"centralwidget")
-        self.gridLayout = QGridLayout(self.centralwidget)
-        self.gridLayout.setObjectName(u"gridLayout")
-        self.verticalLayout = QVBoxLayout()
-        self.verticalLayout.setObjectName(u"verticalLayout")
-        self.horizontalLayout = QHBoxLayout()
-        self.horizontalLayout.setObjectName(u"horizontalLayout")
-        self.verticalLayout_2 = QVBoxLayout()
-        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
-        self.radioButton = QRadioButton(self.centralwidget)
-        self.radioButton.setObjectName(u"radioButton")
-
-        self.verticalLayout_2.addWidget(self.radioButton)
-
-        self.radioButton_2 = QRadioButton(self.centralwidget)
-        self.radioButton_2.setObjectName(u"radioButton_2")
-
-        self.verticalLayout_2.addWidget(self.radioButton_2)
-
-        self.radioButton_3 = QRadioButton(self.centralwidget)
-        self.radioButton_3.setObjectName(u"radioButton_3")
-
-        self.verticalLayout_2.addWidget(self.radioButton_3)
-
-        self.radioButton_4 = QRadioButton(self.centralwidget)
-        self.radioButton_4.setObjectName(u"radioButton_4")
-        self.radioButton_4.setChecked(True)
-
-        self.verticalLayout_2.addWidget(self.radioButton_4)
-
-        self.radioButton_5 = QRadioButton(self.centralwidget)
-        self.radioButton_5.setObjectName(u"radioButton_5")
-
-        self.verticalLayout_2.addWidget(self.radioButton_5)
-
-        self.radioButton_6 = QRadioButton(self.centralwidget)
-        self.radioButton_6.setObjectName(u"radioButton_6")
-
-        self.verticalLayout_2.addWidget(self.radioButton_6)
-
-        self.radioButton_7 = QRadioButton(self.centralwidget)
-        self.radioButton_7.setObjectName(u"radioButton_7")
-
-        self.verticalLayout_2.addWidget(self.radioButton_7)
-
-        self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
-
-        self.verticalLayout_2.addItem(self.verticalSpacer)
-
-
-        self.horizontalLayout.addLayout(self.verticalLayout_2)
-
-        self.tableWidget = QTableWidget(self.centralwidget)
-        if (self.tableWidget.columnCount() < 1):
-            self.tableWidget.setColumnCount(1)
-        __qtablewidgetitem = QTableWidgetItem()
-        self.tableWidget.setHorizontalHeaderItem(0, __qtablewidgetitem)
-        if (self.tableWidget.rowCount() < 1):
-            self.tableWidget.setRowCount(1)
-        __qtablewidgetitem1 = QTableWidgetItem()
-        self.tableWidget.setVerticalHeaderItem(0, __qtablewidgetitem1)
-        self.tableWidget.setObjectName(u"tableWidget")
-        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
-        self.tableWidget.horizontalHeader().setVisible(True)
-        self.tableWidget.horizontalHeader().setHighlightSections(True)
-        self.tableWidget.verticalHeader().setVisible(False)
-
-        self.horizontalLayout.addWidget(self.tableWidget)
-
-
-        self.verticalLayout.addLayout(self.horizontalLayout)
-
-        self.horizontalLayout_2 = QHBoxLayout()
-        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
-        self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
-
-        self.horizontalLayout_2.addItem(self.horizontalSpacer)
-
-        self.bnt_OK = QPushButton(self.centralwidget)
-        self.bnt_OK.setObjectName(u"bnt_OK")
-
-        self.horizontalLayout_2.addWidget(self.bnt_OK)
-
-        self.bnt_Cancel = QPushButton(self.centralwidget)
-        self.bnt_Cancel.setObjectName(u"bnt_Cancel")
-
-        self.horizontalLayout_2.addWidget(self.bnt_Cancel)
-
-        self.bnt_Apply = QPushButton(self.centralwidget)
-        self.bnt_Apply.setObjectName(u"bnt_Apply")
-
-        self.horizontalLayout_2.addWidget(self.bnt_Apply)
-
-
-        self.verticalLayout.addLayout(self.horizontalLayout_2)
-
-
-        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
-
-        AddFileWindows.setCentralWidget(self.centralwidget)
-        self.menubar = QMenuBar(AddFileWindows)
-        self.menubar.setObjectName(u"menubar")
-        self.menubar.setGeometry(QRect(0, 0, 469, 23))
-        AddFileWindows.setMenuBar(self.menubar)
-        self.statusbar = QStatusBar(AddFileWindows)
-        self.statusbar.setObjectName(u"statusbar")
-        AddFileWindows.setStatusBar(self.statusbar)
-
-        self.retranslateUi(AddFileWindows)
-
-        QMetaObject.connectSlotsByName(AddFileWindows)
-    # setupUi
-
-    def retranslateUi(self, AddFileWindows):
-        AddFileWindows.setWindowTitle(QCoreApplication.translate("AddFileWindows", u"MainWindow", None))
-        self.radioButton.setText(QCoreApplication.translate("AddFileWindows", u"Filelist", None))
-        self.radioButton_2.setText(QCoreApplication.translate("AddFileWindows", u"Netlist", None))
-        self.radioButton_3.setText(QCoreApplication.translate("AddFileWindows", u"Verilog 2001", None))
-        self.radioButton_4.setText(QCoreApplication.translate("AddFileWindows", u"Verilog 2005", None))
-        self.radioButton_5.setText(QCoreApplication.translate("AddFileWindows", u"SystemVerilog 2005", None))
-        self.radioButton_6.setText(QCoreApplication.translate("AddFileWindows", u"SystemVerilog 2009", None))
-        self.radioButton_7.setText(QCoreApplication.translate("AddFileWindows", u"SystemVerilog 2012", None))
-        ___qtablewidgetitem = self.tableWidget.horizontalHeaderItem(0)
-        ___qtablewidgetitem.setText(QCoreApplication.translate("AddFileWindows", u"path", None));
-        ___qtablewidgetitem1 = self.tableWidget.verticalHeaderItem(0)
-        ___qtablewidgetitem1.setText(QCoreApplication.translate("AddFileWindows", u"\u65b0\u5efa\u884c", None));
-        self.bnt_OK.setText(QCoreApplication.translate("AddFileWindows", u"OK", None))
-        self.bnt_Cancel.setText(QCoreApplication.translate("AddFileWindows", u"Cancel", None))
-        self.bnt_Apply.setText(QCoreApplication.translate("AddFileWindows", u"Apply", None))
-    # retranslateUi
-

+ 50 - 24
ui/ui_AddFile.py

@@ -21,7 +21,7 @@ class Ui_AddFileWindow(object):
         if not AddFileWindow.objectName():
             AddFileWindow.setObjectName(u"AddFileWindow")
         AddFileWindow.setWindowModality(Qt.ApplicationModal)
-        AddFileWindow.resize(374, 270)
+        AddFileWindow.resize(562, 469)
         self.gridLayout = QGridLayout(AddFileWindow)
         self.gridLayout.setObjectName(u"gridLayout")
         self.verticalLayout = QVBoxLayout()
@@ -73,25 +73,47 @@ class Ui_AddFileWindow(object):
 
         self.horizontalLayout.addLayout(self.verticalLayout_2)
 
-        self.tableWidget = QTableWidget(AddFileWindow)
-        if (self.tableWidget.columnCount() < 1):
-            self.tableWidget.setColumnCount(1)
+        self.verticalLayout_3 = QVBoxLayout()
+        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
+        self.fileTable = QTableWidget(AddFileWindow)
+        if (self.fileTable.columnCount() < 1):
+            self.fileTable.setColumnCount(1)
         __qtablewidgetitem = QTableWidgetItem()
-        self.tableWidget.setHorizontalHeaderItem(0, __qtablewidgetitem)
-        if (self.tableWidget.rowCount() < 1):
-            self.tableWidget.setRowCount(1)
-        __qtablewidgetitem1 = QTableWidgetItem()
-        self.tableWidget.setVerticalHeaderItem(0, __qtablewidgetitem1)
-        self.tableWidget.setObjectName(u"tableWidget")
-        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
-        self.tableWidget.horizontalHeader().setVisible(True)
-        self.tableWidget.horizontalHeader().setHighlightSections(True)
-        self.tableWidget.verticalHeader().setVisible(False)
-
-        self.horizontalLayout.addWidget(self.tableWidget)
-
-
-        self.verticalLayout.addLayout(self.horizontalLayout)
+        self.fileTable.setHorizontalHeaderItem(0, __qtablewidgetitem)
+        self.fileTable.setObjectName(u"fileTable")
+        font = QFont()
+        font.setPointSize(12)
+        self.fileTable.setFont(font)
+        self.fileTable.setAutoScrollMargin(0)
+        self.fileTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
+        self.fileTable.setSelectionMode(QAbstractItemView.SingleSelection)
+        self.fileTable.setSelectionBehavior(QAbstractItemView.SelectRows)
+        self.fileTable.setShowGrid(False)
+        self.fileTable.setWordWrap(False)
+        self.fileTable.horizontalHeader().setVisible(False)
+        self.fileTable.horizontalHeader().setMinimumSectionSize(0)
+        self.fileTable.horizontalHeader().setDefaultSectionSize(5)
+        self.fileTable.verticalHeader().setVisible(False)
+        self.fileTable.verticalHeader().setCascadingSectionResizes(False)
+        self.fileTable.verticalHeader().setMinimumSectionSize(17)
+        self.fileTable.verticalHeader().setDefaultSectionSize(5)
+        self.fileTable.verticalHeader().setHighlightSections(False)
+
+        self.verticalLayout_3.addWidget(self.fileTable)
+
+        self.horizontalLayout_3 = QHBoxLayout()
+        self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
+        self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+        self.horizontalLayout_3.addItem(self.horizontalSpacer_2)
+
+        self.comboBox = QComboBox(AddFileWindow)
+        self.comboBox.setObjectName(u"comboBox")
+
+        self.horizontalLayout_3.addWidget(self.comboBox)
+
+
+        self.verticalLayout_3.addLayout(self.horizontalLayout_3)
 
         self.horizontalLayout_2 = QHBoxLayout()
         self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
@@ -115,7 +137,13 @@ class Ui_AddFileWindow(object):
         self.horizontalLayout_2.addWidget(self.bnt_Apply)
 
 
-        self.verticalLayout.addLayout(self.horizontalLayout_2)
+        self.verticalLayout_3.addLayout(self.horizontalLayout_2)
+
+
+        self.horizontalLayout.addLayout(self.verticalLayout_3)
+
+
+        self.verticalLayout.addLayout(self.horizontalLayout)
 
 
         self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
@@ -135,10 +163,8 @@ class Ui_AddFileWindow(object):
         self.radioButton_5.setText(QCoreApplication.translate("AddFileWindow", u"SystemVerilog 2005", None))
         self.radioButton_6.setText(QCoreApplication.translate("AddFileWindow", u"SystemVerilog 2009", None))
         self.radioButton_7.setText(QCoreApplication.translate("AddFileWindow", u"SystemVerilog 2012", None))
-        ___qtablewidgetitem = self.tableWidget.horizontalHeaderItem(0)
-        ___qtablewidgetitem.setText(QCoreApplication.translate("AddFileWindow", u"path", None));
-        ___qtablewidgetitem1 = self.tableWidget.verticalHeaderItem(0)
-        ___qtablewidgetitem1.setText(QCoreApplication.translate("AddFileWindow", u"\u65b0\u5efa\u884c", None));
+        ___qtablewidgetitem = self.fileTable.horizontalHeaderItem(0)
+        ___qtablewidgetitem.setText(QCoreApplication.translate("AddFileWindow", u"\u65b0\u5efa\u5217", None));
         self.bnt_OK.setText(QCoreApplication.translate("AddFileWindow", u"OK", None))
         self.bnt_Cancel.setText(QCoreApplication.translate("AddFileWindow", u"Cancel", None))
         self.bnt_Apply.setText(QCoreApplication.translate("AddFileWindow", u"Apply", None))

+ 0 - 162
ui/ui_Analyze-bak.py

@@ -1,162 +0,0 @@
-# -*- coding: utf-8 -*-
-
-################################################################################
-## Form generated from reading UI file 'Analyze-bak.ui'
-##
-## Created by: Qt User Interface Compiler version 5.15.0
-##
-## WARNING! All changes made in this file will be lost when recompiling UI file!
-################################################################################
-
-from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
-    QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
-from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
-    QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
-    QPixmap, QRadialGradient)
-from PySide2.QtWidgets import *
-
-
-class Ui_AnalyzeWindow(object):
-    def setupUi(self, AnalyzeWindow):
-        if not AnalyzeWindow.objectName():
-            AnalyzeWindow.setObjectName(u"AnalyzeWindow")
-        AnalyzeWindow.resize(446, 354)
-        self.centralwidget = QWidget(AnalyzeWindow)
-        self.centralwidget.setObjectName(u"centralwidget")
-        self.gridLayout = QGridLayout(self.centralwidget)
-        self.gridLayout.setObjectName(u"gridLayout")
-        self.verticalLayout = QVBoxLayout()
-        self.verticalLayout.setObjectName(u"verticalLayout")
-        self.horizontalLayout = QHBoxLayout()
-        self.horizontalLayout.setObjectName(u"horizontalLayout")
-        self.tableWidget = QTableWidget(self.centralwidget)
-        if (self.tableWidget.columnCount() < 2):
-            self.tableWidget.setColumnCount(2)
-        __qtablewidgetitem = QTableWidgetItem()
-        self.tableWidget.setHorizontalHeaderItem(0, __qtablewidgetitem)
-        __qtablewidgetitem1 = QTableWidgetItem()
-        self.tableWidget.setHorizontalHeaderItem(1, __qtablewidgetitem1)
-        if (self.tableWidget.rowCount() < 3):
-            self.tableWidget.setRowCount(3)
-        __qtablewidgetitem2 = QTableWidgetItem()
-        self.tableWidget.setVerticalHeaderItem(0, __qtablewidgetitem2)
-        __qtablewidgetitem3 = QTableWidgetItem()
-        self.tableWidget.setVerticalHeaderItem(1, __qtablewidgetitem3)
-        __qtablewidgetitem4 = QTableWidgetItem()
-        self.tableWidget.setVerticalHeaderItem(2, __qtablewidgetitem4)
-        self.tableWidget.setObjectName(u"tableWidget")
-        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
-        self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
-        self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
-        self.tableWidget.horizontalHeader().setVisible(False)
-        self.tableWidget.horizontalHeader().setCascadingSectionResizes(False)
-        self.tableWidget.horizontalHeader().setDefaultSectionSize(111)
-        self.tableWidget.horizontalHeader().setHighlightSections(True)
-        self.tableWidget.verticalHeader().setVisible(False)
-        self.tableWidget.verticalHeader().setCascadingSectionResizes(False)
-
-        self.horizontalLayout.addWidget(self.tableWidget)
-
-        self.verticalLayout_2 = QVBoxLayout()
-        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
-        self.bnt_AddFile = QPushButton(self.centralwidget)
-        self.bnt_AddFile.setObjectName(u"bnt_AddFile")
-
-        self.verticalLayout_2.addWidget(self.bnt_AddFile)
-
-        self.pushButton_5 = QPushButton(self.centralwidget)
-        self.pushButton_5.setObjectName(u"pushButton_5")
-
-        self.verticalLayout_2.addWidget(self.pushButton_5)
-
-        self.bnt_Remove = QPushButton(self.centralwidget)
-        self.bnt_Remove.setObjectName(u"bnt_Remove")
-        self.bnt_Remove.setEnabled(False)
-
-        self.verticalLayout_2.addWidget(self.bnt_Remove)
-
-        self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
-
-        self.verticalLayout_2.addItem(self.verticalSpacer)
-
-        self.pushButton_7 = QPushButton(self.centralwidget)
-        self.pushButton_7.setObjectName(u"pushButton_7")
-
-        self.verticalLayout_2.addWidget(self.pushButton_7)
-
-        self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
-
-        self.verticalLayout_2.addItem(self.verticalSpacer_2)
-
-
-        self.horizontalLayout.addLayout(self.verticalLayout_2)
-
-
-        self.verticalLayout.addLayout(self.horizontalLayout)
-
-        self.horizontalLayout_2 = QHBoxLayout()
-        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
-        self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
-
-        self.horizontalLayout_2.addItem(self.horizontalSpacer)
-
-        self.pushButton_2 = QPushButton(self.centralwidget)
-        self.pushButton_2.setObjectName(u"pushButton_2")
-
-        self.horizontalLayout_2.addWidget(self.pushButton_2)
-
-        self.pushButton_4 = QPushButton(self.centralwidget)
-        self.pushButton_4.setObjectName(u"pushButton_4")
-
-        self.horizontalLayout_2.addWidget(self.pushButton_4)
-
-        self.pushButton_3 = QPushButton(self.centralwidget)
-        self.pushButton_3.setObjectName(u"pushButton_3")
-
-        self.horizontalLayout_2.addWidget(self.pushButton_3)
-
-        self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
-
-        self.horizontalLayout_2.addItem(self.horizontalSpacer_2)
-
-
-        self.verticalLayout.addLayout(self.horizontalLayout_2)
-
-
-        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
-
-        AnalyzeWindow.setCentralWidget(self.centralwidget)
-        self.menubar = QMenuBar(AnalyzeWindow)
-        self.menubar.setObjectName(u"menubar")
-        self.menubar.setGeometry(QRect(0, 0, 446, 23))
-        AnalyzeWindow.setMenuBar(self.menubar)
-        self.statusbar = QStatusBar(AnalyzeWindow)
-        self.statusbar.setObjectName(u"statusbar")
-        AnalyzeWindow.setStatusBar(self.statusbar)
-
-        self.retranslateUi(AnalyzeWindow)
-
-        QMetaObject.connectSlotsByName(AnalyzeWindow)
-    # setupUi
-
-    def retranslateUi(self, AnalyzeWindow):
-        AnalyzeWindow.setWindowTitle(QCoreApplication.translate("AnalyzeWindow", u"MainWindow", None))
-        ___qtablewidgetitem = self.tableWidget.horizontalHeaderItem(0)
-        ___qtablewidgetitem.setText(QCoreApplication.translate("AnalyzeWindow", u"\u65b0\u5efa\u5217", None));
-        ___qtablewidgetitem1 = self.tableWidget.horizontalHeaderItem(1)
-        ___qtablewidgetitem1.setText(QCoreApplication.translate("AnalyzeWindow", u"\u65b0\u5efa\u5217", None));
-        ___qtablewidgetitem2 = self.tableWidget.verticalHeaderItem(0)
-        ___qtablewidgetitem2.setText(QCoreApplication.translate("AnalyzeWindow", u"\u65b0\u5efa\u884c", None));
-        ___qtablewidgetitem3 = self.tableWidget.verticalHeaderItem(1)
-        ___qtablewidgetitem3.setText(QCoreApplication.translate("AnalyzeWindow", u"\u65b0\u5efa\u884c", None));
-        ___qtablewidgetitem4 = self.tableWidget.verticalHeaderItem(2)
-        ___qtablewidgetitem4.setText(QCoreApplication.translate("AnalyzeWindow", u"\u65b0\u5efa\u884c", None));
-        self.bnt_AddFile.setText(QCoreApplication.translate("AnalyzeWindow", u"Add File", None))
-        self.pushButton_5.setText(QCoreApplication.translate("AnalyzeWindow", u"Add Path", None))
-        self.bnt_Remove.setText(QCoreApplication.translate("AnalyzeWindow", u"Remove", None))
-        self.pushButton_7.setText(QCoreApplication.translate("AnalyzeWindow", u"Remove All", None))
-        self.pushButton_2.setText(QCoreApplication.translate("AnalyzeWindow", u"OK", None))
-        self.pushButton_4.setText(QCoreApplication.translate("AnalyzeWindow", u"Cancel", None))
-        self.pushButton_3.setText(QCoreApplication.translate("AnalyzeWindow", u"Apply", None))
-    # retranslateUi
-

+ 1 - 1
ui/ui_Analyze.py

@@ -21,7 +21,7 @@ class Ui_AnalyzeWindow(object):
         if not AnalyzeWindow.objectName():
             AnalyzeWindow.setObjectName(u"AnalyzeWindow")
         AnalyzeWindow.setWindowModality(Qt.ApplicationModal)
-        AnalyzeWindow.resize(400, 300)
+        AnalyzeWindow.resize(478, 384)
         self.gridLayout = QGridLayout(AnalyzeWindow)
         self.gridLayout.setObjectName(u"gridLayout")
         self.verticalLayout = QVBoxLayout()