def clear_graphics(graphics_view: PlotWidget, table_view: QTableView):
        """
        static method for clearing content in all graphics

        Parameters
        ----------
        graphics_view   : PlotWidget
                          graphics view to place chart
        table_view      : QTableView
                          table view to link graphics_view

        """
        Assertor.assert_data_types([graphics_view, table_view],
                                   [PlotWidget, QTableView])
        table_view.setModel(None)
        table_view.clearSpans()
        graphics_view.clear()
Exemple #2
0
class UI(QWidget):
    def __init__(self):
        super().__init__()
        self.db = DBManager()
        self.cached_file_list = [
        ]  # DB를 통해 검색하지 않고, 메모리에 올려서 검색을 수행하기 위한 파일 리스트
        self.count = 0  # 사용자 입력값이 2개 이상일 때 처리해주기 위해 구성

        # 테이블 갱신
        self.initUI()

        # 디렉토리를 탐색해서 파일 리스트를 얻은 후, DB에 insert 하는 작업까지 수행하는 쓰레드
        self.scan_thread = ScanThread()
        self.scan_thread.set_db(self.db)
        self.scan_thread.finish_scan_signal.connect(self.finish_scan)
        self.start_thread(mode=1)

        # DB 정보를 읽기 위한 쓰레드
        self.read_db_thread = ReadDBThread()
        self.read_db_thread.set_db(self.db)
        self.read_db_thread.finish_read_signal.connect(self.finish_read)
        self.start_thread(mode=0)

        # 새로 생성된 파일정보를 DB에 넣기 위한 쓰레드
        self.insert_db_thread = InsertDBThread()
        self.insert_db_thread.set_db(self.db)

        # 삭제된 파일정보를 DB에서 제거하기 위한 쓰레드
        self.delete_db_thread = DeleteDBThread()
        self.delete_db_thread.set_db(self.db)

        # 각 드라이브 별로 파일 변화 감지를 수행하는 쓰레드를 관리하는 쓰레드
        self.manager_observer_thread = ManagerObserverThread()
        self.manager_observer_thread.file_change_signal.connect(
            self.control_updated_file)
        self.start_thread(mode=2)

        self.check_time = checkTime()
        self.check_time.timeout.connect(self.processing_time_out)

    ####################################################################################################################
    # initTable
    # = 테이블 표시를 위한 기본 설정을 하는 메소드이다.
    #   테이블의 entry를 클릭 했을 때, 파일이나 디렉토리를 실행하기 위한 이벤트(execute_file)를 연결해주고,
    #   테이블의 헤더를 클릭 했을 때 정렬 기능을 실행하기 위한 이벤트(sort_data)도 연결해준다.
    ###################################################################################################################
    def initTable(self):
        self.header_sorted_state = [False, False, False]
        self.table_model = TableModel()

        self.tableview.setSortingEnabled(True)

        self.tableview.doubleClicked.connect(self.execute_file)
        self.tableview.horizontalHeader().sectionClicked.connect(
            self.sort_data)

    ####################################################################################################################
    # inintUI
    # = UI를 초기화하기 위한 메소드이다.
    #   사용자 입력을 받기 위한 LineEdit, 검색된 결과 개수를 표시하기 위한 Label, 검색된 결과를 표시하기 위한 tableview
    #   위젯들을 포함한다.
    ####################################################################################################################
    def initUI(self):

        # 사용자 입력을 받는 위젯
        self.qle = QLineEdit(self)
        self.qle.textEdited.connect(self.update_table_data)

        # 검색된 결과의 개수를 표시하는 위젯
        self.label = QLabel(self)

        # 검색된 결과를 표시하는 테이블
        self.tableview = QTableView()
        self.initTable()

        # UI 구성
        self.vbox = QVBoxLayout()
        self.vbox.addWidget(self.qle)
        self.vbox.addWidget(self.tableview)
        self.vbox.addWidget(self.label)

        self.setLayout(self.vbox)
        self.setWindowTitle('File Search Program')
        self.setGeometry(300, 100, 1500, 800)
        self.show()

    ####################################################################################################################
    # displayFiles
    # - file_list : 테이블 상에 표시한 파일들의 정보를 담고 있는 리스트 ( 파일명, 경로, 크기를 튜플 형태로 저장)
    # = 검색 결과에 의해 갱신되는 테이블을 나타내는 메소드
    ####################################################################################################################
    def displayFiles(self, file_list):
        total = len(file_list)
        self.label.setText("총 {0} 개 검색됨".format(total))

        self.tableview.clearSpans()
        self.table_model.layoutAboutToBeChanged.emit()
        self.table_model.setData(file_list)
        self.table_model.layoutChanged.emit()

        self.tableview.setModel(self.table_model)
        self.tableview.setColumnWidth(0, 600)
        self.tableview.setColumnWidth(1, 600)
        self.tableview.setColumnWidth(2, 80)

    ########################################################################################################################
    # start_thread
    # - mode : 시작하게 될 쓰레드를 명시하기 위한 변수
    # = 인자로 받은 mode을 통해 실행할 쓰레드를 결정하고, 쓰레드를 실행한다.
    ########################################################################################################################
    def start_thread(self, mode):
        if mode == 0:  #read_db_thread -> DB로부터 파일 정보 읽기
            self.read_db_thread.start()

        elif mode == 1:  #scan_thread -> 파일 시스템 스캔 및 DB 저장
            self.scan_thread.start()

        elif mode == 2:  #manager_observer_thread -> 파일 변화를 감지하는 Observer를 thread을 생성하고, 이벤트 처리
            self.manager_observer_thread.start()

        elif mode == 3:  #insert_db_thread -> DB에 추가된 파일 정보 저장
            self.insert_db_thread.start()

        elif mode == 4:  #delete_db_thread -> DB에서 삭제된 파일 정보 제거
            self.delete_db_thread.start()

    ########################################################################################################################
    # insert_fileinfo
    # - file_info : 추가하게 될 파일 정보가 들어있는 리스트(파일명, 경로, 사이즈)
    # = 인자로 받은 file_info를 통해 파일 정보를 갱신하고, 테이블을 갱신하는 메소드를 호출한다.
    ########################################################################################################################
    def insert_fileinfo(self, file_info):
        self.cached_file_list.append(file_info)
        self.check_time.start()

    ########################################################################################################################
    # delete_fileinfo
    # - file_info : 삭제하게 될 파일 정보가 들어있는 리스트(파일명, 경로)
    # = 인자로 받은 file_info를 통해 파일명과 경로명이 일치하는 파일 정보를 삭제하고, 테이블을 갱신하는 메소드를 호출한다.
    ########################################################################################################################
    def delete_fileinfo(self, file_info):
        file_name = file_info[0]
        dir_name = file_info[1]

        for f in self.cached_file_list:
            if f[0] == file_name and f[1] == dir_name:
                self.cached_file_list.remove(f)
                break

        self.check_time.start()

    def processing_time_out(self):
        self.update_table_data(True)

########################################################################################################################
#     이벤트 핸들러 메소드
########################################################################################################################

####################################################################################################################
# sort_data
# - column_index : 선택 된 헤더의 column_index
# = 헤더(File, Path, Size(kb))를 클릭했을 때 정렬을 수행하기 위한 이벤트 처리 메소드
#   각 헤더 마다 가지고 있는 header_sorted_state 정보를 통해 해당 열에 대한 정렬 기준을 수립한다.
#   False -> 오름 차순으로, True -> 내림 차순으로 적용
####################################################################################################################

    @pyqtSlot(int)
    def sort_data(self, column_index):
        self.table_model.layoutAboutToBeChanged.emit()
        table_data = self.table_model.getData()

        if self.header_sorted_state[column_index]:  # 내림 차순
            table_data = sorted(
                table_data,
                key=lambda f: f[column_index]
                if column_index == 2 else f[column_index].upper(),
                reverse=True)
            self.header_sorted_state[column_index] = False
        else:  # 오름 차순
            table_data = sorted(
                table_data,
                key=lambda f: f[column_index]
                if column_index == 2 else f[column_index].upper())
            self.header_sorted_state[column_index] = True

        self.table_model.setData(table_data)
        self.table_model.layoutChanged.emit()

    ####################################################################################################################
    # execute_file
    # - signal : 선택된 tableview의 entry에 대한 정보를 담고 있는 QModeIndex 객체
    # = 테이블 상에서 entry을 더블 클릭했을 때 파일 실행 또는 디렉토리 열기를 수행하기 위한 이벤트 처리 메소드
    #   경로를 더블 클릭 시 -> 해당 디렉토리 열기
    #   파일명 또는 사이즈를 더블 클릭 시 -> 해당 파일 실행
    ####################################################################################################################
    @pyqtSlot(QModelIndex)
    def execute_file(self, signal):
        row = signal.row()
        col = signal.column()

        if col == 1:  # 파일 경로 더블 클릭 -> 해당 디렉토리 열기
            index = signal.sibling(row, col)
            index_dict = self.table_model.itemData(index)
            path = index_dict.get(0)
        else:  # 파일 명 더블 클릭 -> 해당 파일 실행
            findex = signal.sibling(row, 0)
            findex_dict = self.table_model.itemData(findex)
            file_name = findex_dict.get(0)

            pindex = signal.sibling(row, 1)
            pindex_dict = self.table_model.itemData(pindex)
            path = pindex_dict.get(0)
            path = path + "\\" + file_name

        webbrowser.open(path)

    ####################################################################################################################
    # finish_scan
    # = scan_thread의 동작이 완료되었을 때을 위한 이벤트 처리 메소드
    #   start_thread 메소드를 통해 파일 변화를 감지하는 manager_observer_thread를 실행한다.
    #   또한 파일 시스템 스캔을 통해 얻은 파일 정보를 cached_file_list에 갱신한다.
    #   사용자 입력값에 따라 변경사항을 테이블에 표시한다.
    ####################################################################################################################
    @pyqtSlot(list)
    def finish_scan(self, file_list):
        self.finish_scan_flag = True
        self.cached_file_list = file_list
        len(self.cached_file_list)
        self.update_table_data()

    ########################################################################################################################
    # finish_read
    # = read_db_thread 에 의해 프로그램 시작 후, DB에서 파일 정보를 읽어왔을 때 시그널을 받게 되는 메소드
    #   수집된 파일 정보를 나타내는 cached_file_list를 갱신하고, 해당 값을 테이블에 표시한다.
    ########################################################################################################################
    @pyqtSlot(list)
    def finish_read(self, file_list):
        self.cached_file_list = file_list
        self.displayFiles(file_list)

    ########################################################################################################################
    # update_table_data
    # = 사용자 입력값 변경 시 또는 파일 정보에 변화가 생겼을 때, 입력값을 기준으로 테이블에 표시할 파일 정보를 생성하는 메소드
    #   생성된 파일 정보를 displayFiles 메소드를 통해 테이블 나타낸다.
    ########################################################################################################################
    @pyqtSlot()
    def update_table_data(self, time_out=False):
        text = self.qle.text().upper()

        if self.count < 2 and len(text) > 0 and not time_out:
            self.count = self.count + 1
            self.check_time.start()
            return

        self.count = 0

        # file_list의 첫번째 항목인 file_name을 토대로 text 값을 포함하고 있으면 displayed_file_list에 추가한다.
        displayed_file_list = [
            file_info for file_info in self.cached_file_list
            if text in file_info[0].upper()
        ]
        self.displayFiles(displayed_file_list)

    ########################################################################################################################
    # control_updated_file
    # - file_infos : 파일 변경 감지에 따라 대상이 되는 파일 정보가 저장되어있는 리스트이며
    #   0번 인덱스는 실질적인 파일 정보가 들어가 있고,
    #   1번 인덱스에는 어떠한 파일 변경 이벤트가 발생했는지를 나타낸다.
    # = file_infos를 통해 파일 변경 이벤트를 구분하고, 각 이벤트에 맞게 테이블 갱신 및 DB 갱신을 수행하는 메소드를 호출한다.
    ########################################################################################################################
    @pyqtSlot(list)
    def control_updated_file(self, file_infos):
        mode = file_infos[1]
        file_info = file_infos[0]

        if mode == 3:  # insert
            self.insert_fileinfo(file_info)
            self.insert_db_thread.set_file_info(file_info)

        elif mode == 4:  # delete
            self.delete_fileinfo(file_info)
            self.delete_db_thread.set_file_info(file_info)

        self.start_thread(mode)