class AllPSDisplay(Display):
    def __init__(self, parent=None, args=[], macros=None):
        super(AllPSDisplay, self).__init__(parent=parent,
                                           args=args,
                                           macros=None)
        # Placeholder for data to filter
        self.BBB_PS_list = []
        # Reference to the PyDMApplication
        self.app = QApplication.instance()
        self.app.setApplicationDisplayName(
            'Beaglebone Black - RS485 Serial Interface Controller')
        # Assemble the Widgets
        self.setup_ui()
        # Load data from file
        self.load_data()
        # Show all BBBs
        #self.do_search()

    def minimumSizeHint(self):
        # This is the default recommended size
        # for this screen
        return QtCore.QSize(1000, 600)

    def ui_filepath(self):
        # No UI file is being used
        return None

    def setup_ui(self):
        # Create the main layout
        main_layout = QVBoxLayout()
        self.setLayout(main_layout)

        # Create a Label to be the title
        lbl_title = QLabel(
            "Beaglebone Black - RS485 Serial Interface Controller\nControls Group"
        )
        # Add some StyleSheet to it
        lbl_title.setStyleSheet("\
            QLabel {\
                qproperty-alignment: AlignCenter;\
                border: 1px solid #FF17365D;\
                border-top-left-radius: 15px;\
                border-top-right-radius: 15px;\
                background-color: #FF17365D;\
                padding: 5px 0px;\
                color: rgb(255, 255, 255);\
                max-height: 40px;\
                font-size: 14px;\
            }")

        # Add the title label to the main layout
        main_layout.addWidget(lbl_title)

        # Create a GroupBox for subtitles
        legend_layout = QHBoxLayout()
        legend_layout.setGeometry(QtCore.QRect(10, 10, 50, 30))
        gb_legend = QGroupBox(parent=self)
        gb_legend.setLayout(legend_layout)

        # Create a squares and labels
        brush_black = QBrush(QColor(255, 255, 255))
        brush_black.setStyle(QtCore.Qt.SolidPattern)
        brush_orange = QBrush(QColor(193, 125, 17))
        brush_orange.setStyle(QtCore.Qt.SolidPattern)
        brush_blue = QBrush(QColor(52, 101, 164))
        brush_blue.setStyle(QtCore.Qt.SolidPattern)

        palette = QPalette()
        palette.setBrush(QPalette.Active, QPalette.Base, brush_black)
        palette.setBrush(QPalette.Inactive, QPalette.Base, brush_black)

        font = QFont()
        font.setItalic(True)

        self.color_IOC = QLineEdit()
        self.color_IOC.setEnabled(False)
        self.color_IOC.setMaximumSize(QtCore.QSize(15, 15))
        palette.setBrush(QPalette.Disabled, QPalette.Base, brush_blue)
        self.color_IOC.setPalette(palette)

        self.text_IOC = QLabel()
        self.text_IOC.setText("IOC")
        self.text_IOC.setFont(font)

        self.color_PES = QLineEdit()
        self.color_PES.setEnabled(False)
        self.color_PES.setMaximumSize(QtCore.QSize(15, 15))
        palette.setBrush(QPalette.Disabled, QPalette.Base, brush_orange)
        self.color_PES.setPalette(palette)

        self.text_PES = QLabel()
        self.text_PES.setText("PES")
        self.text_PES.setFont(font)

        # Add the created widgets to the layout
        legend_layout.addWidget(self.color_IOC)
        legend_layout.addWidget(self.text_IOC)
        legend_layout.addWidget(self.color_PES)
        legend_layout.addWidget(self.text_PES)

        # Add the Groupbox to the main layout
        main_layout.addWidget(gb_legend)

        # Create the Search Panel layout
        search_layout = QHBoxLayout()

        # Create a GroupBox with "Filtering" as Title
        gb_search = QGroupBox(parent=self)
        gb_search.setLayout(search_layout)

        # Create a label, line edit and button for filtering
        lbl_search = QLabel(text="Filter: ")
        self.txt_filter = QLineEdit()
        self.txt_filter.returnPressed.connect(self.do_search)
        btn_search = QPushButton()
        btn_search.setText("Search")
        btn_search.clicked.connect(self.do_search)

        # Add the created widgets to the layout
        search_layout.addWidget(lbl_search)
        search_layout.addWidget(self.txt_filter)
        search_layout.addWidget(btn_search)

        # Add the Groupbox to the main layout
        main_layout.addWidget(gb_search)

        # Create the Results Layout
        self.resultsLT_layout = QVBoxLayout()
        self.resultsLT_layout.setContentsMargins(0, 0, 0, 0)
        self.resultsBO_layout = QVBoxLayout()
        self.resultsBO_layout.setContentsMargins(0, 0, 0, 0)
        self.resultsSR_layout = QVBoxLayout()
        self.resultsSR_layout.setContentsMargins(0, 0, 0, 0)
        self.resultsDCL_layout = QVBoxLayout()
        self.resultsDCL_layout.setContentsMargins(0, 0, 0, 0)
        # Create a Frame to host the results of search
        self.frmLT_result = QFrame(parent=self)
        self.frmLT_result.setLayout(self.resultsLT_layout)
        self.frmBO_result = QFrame(parent=self)
        self.frmBO_result.setLayout(self.resultsBO_layout)
        self.frmSR_result = QFrame(parent=self)
        self.frmSR_result.setLayout(self.resultsSR_layout)
        self.frmDCL_result = QFrame(parent=self)
        self.frmDCL_result.setLayout(self.resultsDCL_layout)

        # Create a ScrollArea so we can properly handle many entries
        scroll_areaLT = QScrollArea(parent=self)
        scroll_areaBO = QScrollArea(parent=self)
        scroll_areaSR = QScrollArea(parent=self)
        scroll_areaDCL = QScrollArea(parent=self)
        scroll_areaLT.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        scroll_areaBO.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        scroll_areaSR.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        scroll_areaDCL.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        scroll_areaLT.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        scroll_areaBO.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        scroll_areaSR.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        scroll_areaDCL.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        scroll_areaLT.setWidgetResizable(True)
        scroll_areaBO.setWidgetResizable(True)
        scroll_areaSR.setWidgetResizable(True)
        scroll_areaDCL.setWidgetResizable(True)

        # Add the Frame to the scroll area
        scroll_areaLT.setWidget(self.frmLT_result)
        scroll_areaBO.setWidget(self.frmBO_result)
        scroll_areaSR.setWidget(self.frmSR_result)
        scroll_areaDCL.setWidget(self.frmDCL_result)

        # Create tabs
        self.tabWidget = QTabWidget(parent=self)
        self.tabLT = QWidget(self.tabWidget)
        self.tabWidget.addTab(self.tabLT, "LTs")
        self.LTLayout = QHBoxLayout(self.tabLT)
        self.LTLayout.setContentsMargins(0, 0, 0, 0)
        self.tabsBooster = QWidget(self.tabWidget)
        self.tabWidget.addTab(self.tabsBooster, "Booster")
        self.BOLayout = QHBoxLayout(self.tabsBooster)
        self.BOLayout.setContentsMargins(0, 0, 0, 0)
        self.tabsAnel = QWidget(self.tabWidget)
        self.tabWidget.addTab(self.tabsAnel, "Anel")
        self.SRLayout = QHBoxLayout(self.tabsAnel)
        self.SRLayout.setContentsMargins(0, 0, 0, 0)
        self.tabsDCLink = QWidget(self.tabWidget)
        self.tabWidget.addTab(self.tabsDCLink, "DC-Link")
        self.DCLLayout = QHBoxLayout(self.tabsDCLink)
        self.DCLLayout.setContentsMargins(0, 0, 0, 0)

        # Add the scroll area to the main layout
        main_layout.addWidget(self.tabWidget)

        # Add the scroll area to the main layout
        self.LTLayout.addWidget(scroll_areaLT)
        self.BOLayout.addWidget(scroll_areaBO)
        self.SRLayout.addWidget(scroll_areaSR)
        self.DCLLayout.addWidget(scroll_areaDCL)

    def load_data(self):
        # Extract the directory of this file...
        base_dir = os.path.dirname(os.path.realpath(__file__))
        # Concatenate the directory with the file name...
        data_file = os.path.join(base_dir, "ps-list.txt")
        # Open the file so we can read the data...
        self.BBB_PS_list = {}
        with open(data_file, 'r') as f:
            # For each line in the file...
            for current_line in f:
                self.BBB_PS_list[current_line.split()
                                 [0]] = current_line.split()[1:]

    def do_search(self):
        # For each widget inside the results frame, lets destroy them
        for widget in self.frmLT_result.findChildren(QWidget):
            widget.setParent(None)
            widget.deleteLater()
        for widget in self.frmBO_result.findChildren(QWidget):
            widget.setParent(None)
            widget.deleteLater()
        for widget in self.frmSR_result.findChildren(QWidget):
            widget.setParent(None)
            widget.deleteLater()
        for widget in self.frmDCL_result.findChildren(QWidget):
            widget.setParent(None)
            widget.deleteLater()

        # Grab the filter text
        filter_text = self.txt_filter.text()

        # For every entry in the dataset...
        for entry in self.BBB_PS_list:
            # Check if they match our filter
            if filter_text.upper() not in entry.upper():
                continue

            # Create macros list
            dict_macro_BBB = {
                "PS_CON": entry,
                "PYTHON":
                "python" if platform.system() == "Windows" else "python3"
            }
            for i in range(1, len(self.BBB_PS_list[entry]) + 1):
                dict_macro_BBB["PS{}".format(i)] = self.BBB_PS_list[entry][i -
                                                                           1]
            # Create a PyDMEmbeddedDisplay for this entry
            disp = PyDMEmbeddedDisplay(parent=self)
            PyDMApplication.instance().close_widget_connections(disp)
            disp.macros = json.dumps(dict_macro_BBB)
            disp.filename = 'PS_Controller.ui'
            disp.setMinimumWidth(700)
            disp.setMinimumHeight(40)
            disp.setMaximumHeight(100)

            # Add the Embedded Display to the Results Layout
            if "DCL" in entry:
                self.resultsDCL_layout.addWidget(disp)
            elif "SI" in entry:
                self.resultsSR_layout.addWidget(disp)
            elif "BO" in entry:
                self.resultsBO_layout.addWidget(disp)
            elif ("TB" in entry) or ("TS" in entry):
                self.resultsLT_layout.addWidget(disp)

            PyDMApplication.instance().establish_widget_connections(disp)
class Image_Editor(QFrame):
    # 整合注释功能和图片预览功能
    def __init__(self, *args, **kwargs):
        QFrame.__init__(self, *args, **kwargs)
        #self.Preview_Btn = QPushButton("Preview", self)
        #self.Save_Preview_Btn = QPushButton("Save Preview", self)
        #self.Save_Raw_Btn = QPushButton("Save Raw Images", self)
        self.Save_To_Dir = ''
        #self.Add_Anon_Btn = QPushButton("Add Anotation", self)
        #self.Action_Btns = Text_Act_Btn(self)
        self.Core = QFrame(self)

        #self.Anotation_Ref_Gene_Index = 0
        #self.Anotation_Split_Mode = "1"
        #self.Anotation = QVBoxLayout()
        #self.Anotation.setAlignment(Qt.AlignCenter)
        #self.Anotation_Frame = QFrame(self.Core)
        #self.Anotation_Frame.setStyleSheet("border:1px solid green")
        #self.Anotation_Frame.setContentsMargins(0, 0, 0, 0)
        #self.Anotation_Frame.setLayout(self.Anotation)

        self.Imgs = QVBoxLayout()
        self.Imgs.setAlignment(Qt.AlignCenter | Qt.AlignTop)
        self.Imgs.setSpacing(10)
        self.Imgs_Frame = QFrame(self.Core)
        self.Imgs_Frame.setContentsMargins(0, 0, 0, 0)
        #self.Imgs_Frame.setStyleSheet("border:1px solid red")
        self.Imgs_Frame.setLayout(self.Imgs)

        self.Imgs_Gene_List = []

        #self.Imgs_Frame.setStyleSheet("border:1px solid red")
        self.Img_DrawRects = []

        #self.Info = QTextEdit(self.Core)
        #self.Info.setMaximumHeight(300)
        hv = QVBoxLayout()
        #hv.addWidget(self.Preview_Btn)
        #td = QHBoxLayout()
        #td.addWidget(self.Save_Preview_Btn)
        #td.addWidget(self.Save_Raw_Btn)
        #hv.addLayout(td)
        #hv.addWidget(self.Add_Anon_Btn)
        #hv.addWidget(self.Action_Btns)
        core = QVBoxLayout()
        #core.setSpacing(0)
        core.setAlignment(Qt.AlignCenter)
        #core.addWidget(self.Anotation_Frame)
        core.addWidget(self.Imgs_Frame)
        #core.addWidget(self.Info)
        Sc = QScrollArea(self)

        self.Core.setLayout(core)
        Sc.setWidget(self.Core)
        Sc.setWidgetResizable(True)
        #Sc.setGeometry(Sc.parentWidget().geometry())
        #self.Core.setStyleSheet("border:1px solid yellow")
        hv.addWidget(Sc)
        # 顶层Layout
        main = QHBoxLayout()
        # 整体预览Frame
        #self.Preview = QLabel(self)
        #self.Preview.setStyleSheet("border:1px solid red")
        main.addLayout(hv)
        #main.addWidget(self.Preview)
        main.setStretch(0, 1)
        #main.setStretch(1, 1)

        self.setLayout(main)
        self.signal_connections()
        #self.setMinimumSize(500, 800)

    def signal_connections(self):
        #self.Add_Anon_Btn.clicked.connect(self.Add_Anotation)
        #self.Action_Btns.Action_Signal.connect(self.Adjust_Response)
        #self.Preview_Btn.clicked.connect(self.Gene_Preview)
        #self.Save_Preview_Btn.clicked.connect(self.Save_Img)
        #self.Save_Raw_Btn.clicked.connect(self.Save_Raw)
        pass

    def Add_Anotation(self):
        an = Anotation(self)
        # 后面添加split_str的验证
        #split_str = "1"
        # 改写使其能够同时接受参照Gene条带

        mt = Bound_Split_Dialog_Preview(self)
        for i in range(len(self.Imgs_Gene_List)):
            mt.Ref.addItem(self.Imgs_Gene_List[i], self.Img_DrawRects[i])
        if self.Anotation_Ref_Gene_Index == -1:
            mt.Ref.setCurrentIndex(len(self.Imgs_Gene_List) - 1)
        else:
            mt.Ref.setCurrentIndex(self.Anotation_Ref_Gene_Index)

        if mt.exec() == QDialog.Accepted:
            self.Anotation_Split_Mode = mt.Split_Width
            self.Anotation_Ref_Gene_Index = mt.Ref.currentIndex()
            start_pos = mt.bounds_x[0]
            end_pos = mt.bounds_x[len(mt.Split_Width)]
            an.SetColumn([mt.Split_str, mt.Split_Width], start_pos, end_pos)
            self.Anotation.addWidget(an)
            #self.Adjust_Point()

    def Adjust_Point(self):
        Ref_Img = self.Imgs.itemAt(
            self.Anotation_Ref_Gene_Index).widget().pixmap()
        Ref_Img = Ref_Img.toImage()
        w = Ref_Img.width()
        diff = int((self.Imgs_Frame.width() - w) / 2)
        for i in range(self.Anotation.count()):
            an = self.Anotation.itemAt(i).widget()
            an.setContentsMargins(diff + an.start_pos, 0,
                                  w - an.end_pos + diff, 0)

    def display_img(self, Tree_obj):
        max_height = 0
        max_width = 0
        genes = []
        # 先清空self.Imgs中的图片
        for i in range(self.Imgs.count()):
            self.Imgs.itemAt(i).widget().clear()

        for i in range(Tree_obj.topLevelItemCount()):
            t = Tree_obj.topLevelItem(i)
            img = t.Img_Block_Pre.Pre.PreView_Img
            genes.append(t.Img_Block_Pre.ImgB.WB.Img.Indicator[0].Name.text())
            rect = t.Img_Block_Pre.Pre.rect_fix(
                t.Img_Block_Pre.Pre.draw_rec[0]['rect'])
            self.Img_DrawRects.append({'img': img, 'rec': rect})
            try:
                q = self.Imgs.itemAt(i).widget()
            except AttributeError:
                q = QLabel(self.Imgs_Frame)
                self.Imgs.addWidget(q)
                q.setAlignment(Qt.AlignCenter)
            q.setPixmap(QPixmap.fromImage(img))

            #q.setMaximumSize(img.width(),img.height())
            #q.setMaximumHeight(img.height() + 4)
            max_height += img.height()
            max_width = max(max_width, img.width())
        #self.Imgs_Frame.setMaximumSize(max_width + self.Imgs.spacing() * 2, self.Imgs.spacing() * (i + 2) + max_height)
        self.Imgs_Gene_List = genes

    # @pyqtSlot()
    def Adjust_Response(self, par):
        def get_Current_Focus_cell():
            for i in range(self.Anotation.count()):
                row = self.Anotation.itemAt(i).widget()
                for j in range(row.layout().count()):
                    cell = row.layout().itemAt(j).widget()
                    if cell.Actived:
                        return row, cell
            return None, None

        row, cell = get_Current_Focus_cell()
        if type(par) == str:
            if "0" in par:
                target = row
            else:
                target = cell
            if target is not None:
                x, y, w, h = target.x(), target.y(), target.width(
                ), target.height()
                if '>' in par:
                    target.setGeometry(x + 1, y, w, h)
                    target.setFixedSize(w, h)
                if '<' in par:
                    target.setGeometry(x - 1, y, w, h)
                    target.setFixedSize(w, h)
                if '+' in par:
                    target.setGeometry(x - 1, y, w + 2, h)
                    target.setFixedSize(w + 2, h)
                if '-' in par:
                    target.setGeometry(x + 1, y, w - 2, h)
                    target.setFixedSize(w - 2, h)
        if type(par) == int:
            pass

    def Gene_Preview(self):
        # 寻找self.core里面所有的
        # Magic_Input, QLabel, QTextEdit
        anotations = self.Core.findChildren(Magic_Input)
        Imgs = self.Core.findChildren(QLabel)
        #Info = [self.Info]

        Img = QImage(self.Core.size(), QImage.Format_ARGB32)
        Img.fill(Qt.transparent)
        # Img.fill('white')
        pt = QPainter()
        pt.begin(Img)

        # 修正嵌套引起的坐标差异
        def Get_Pos_relative_to(t, a_parent_widget):
            dx = (t.width() - t.pixmap().width()) // 2
            dy = (t.height() - t.pixmap().height()) // 2
            x, y = t.x() + dx, t.y() + dy
            p = t.parent()
            while p != self.Core:
                x += p.x()
                y += p.y()
                p = p.parent()
            return x, y

        for img in Imgs:
            im = img.pixmap()
            x, y = Get_Pos_relative_to(img, self.Core)
            w, h = im.width(), im.height()
            pt.drawPixmap(x, y, w, h, im)

        for t in anotations:
            pt.setPen(QPen(QColor(0, 0, 0), 3))
            #pt.setFont(i['font'])
            x, y = Get_Pos_relative_to(t, self.Core)
            w, h = t.width(), t.height()
            pt.drawText(QRectF(x, y, w, h), Qt.AlignCenter, t.text())

        pt.end()
        #self.Preview.setPixmap(QPixmap.fromImage(Img))
        return Img

    def Save_Img(self):
        Img = self.Gene_Preview()
        Img = QPixmap.fromImage(Img)
        FileName = QFileDialog.getSaveFileName(self, 'Save as',
                                               self.Save_To_Dir, '*.png')[0]
        Img.save(FileName, 'png')
        dir, _, _ = File_path(FileName)
        self.Save_To_Dir = dir

    def Save_Raw(self):
        pass

    def resizeEvent(self, event):
        #self.Adjust_Point()
        #QFrame.resizeEvent(event)
        pass