class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.resize(600, 300) self.model = QDirModel(self) # 1 self.model.setReadOnly(False) self.model.setSorting(QDir.Name | QDir.IgnoreCase) self.tree = QTreeView(self) # 2 self.tree.setModel(self.model) self.tree.clicked.connect(self.show_info) self.index = self.model.index(QDir.currentPath()) self.tree.expand(self.index) self.tree.scrollTo(self.index) self.info_label = QLabel(self) # 3 self.v_layout = QVBoxLayout() self.v_layout.addWidget(self.tree) self.v_layout.addWidget(self.info_label) self.setLayout(self.v_layout) def show_info(self): # 4 index = self.tree.currentIndex() file_name = self.model.fileName(index) file_path = self.model.filePath(index) file_info = 'File Name: {}\nFile Path: {}'.format(file_name, file_path) self.info_label.setText(file_info)
class MyCentralWidget(QWidget): def __init__(self, parent=None, flags=Qt.WindowFlags()): super().__init__(parent=parent, flags=flags) self.initUI() self.pix = '' def initUI(self): hbox = QHBoxLayout(self) self.lefttopframe = MyPixmap() # self.lefttopframe.frameWidth = 40 self.lefttopframe.setMinimumWidth(150) self.lefttopframe.setFrameShape(QFrame.StyledPanel) # leftbottomframe = QFrame(self) self.dirmodel = QDirModel() qtree = QTreeView() qtree.setMaximumWidth(300) qtree.setModel(self.dirmodel) qtree.setRootIndex( self.dirmodel.index(QDir.currentPath() + '/mapeditor/Maps')) qtree.doubleClicked.connect(self.tree_clicked) # leftbottomframe.setFrameShape(QFrame.StyledPanel) splitter = QSplitter(Qt.Vertical) splitter.handleWidth = 20 splitter.addWidget(self.lefttopframe) splitter.addWidget(qtree) self.rightframe = MyPixmap(self) # rightframe.set_tileset() self.rightframe.setFrameShape(QFrame.StyledPanel) splitter2 = QSplitter(Qt.Horizontal) splitter2.addWidget(splitter) splitter2.addWidget(self.rightframe) hbox.addWidget(splitter2) self.setLayout(hbox) def tree_clicked(self, idx): print(self.dirmodel.fileName(idx)) self.rightframe.set_tileset(QDir.currentPath() + '/mapeditor/' + self.dirmodel.filePath(idx)) def paintEvent(self, e): painter = QPainter(self) if self.pix != '': painter.drawPixmap(self.lefttopframe.rect(), self.pix) def set_tileset(self, path): # print ('set tileset %s' % path) self.path = path self.pix = QPixmap() self.pix.load(path)
class MyApp(QMainWindow): def __init__(self): super(MyApp, self).__init__() loadUi("ui/main_window.ui", self) self.setWindowTitle("Openpose GUI") self.setWindowIcon(QIcon('media/logo.png')) self.params = { # "net_resolution": "128x96", # uncomment if cuda error "model_folder": "models/", "body": 1, "render_pose": 0, "render_threshold": 0.1, "hand": False, "hand_render": 1, "hand_render_threshold": 0.2, "face": False, "face_render": 1, "face_render_threshold": 0.4, "disable_blending": False # black blackgroud if True } self.datum = op.Datum() self.op_wrapper = op.WrapperPython() self.tree_model = QDirModel() self.fourcc = cv2.VideoWriter_fourcc(*'XVID') self.cap = cv2.VideoCapture() self.save_window = SaveWindow() self.timer = QTimer() self.timer.timeout.connect(self.show_frame) self.out_path = "output" self.out_img_path = os.path.join(self.out_path, "{}/img") self.out_body_path = os.path.join(self.out_path, "{}/keypoint_body") self.out_hand_path = os.path.join(self.out_path, "{}/keypoint_hand") self.out_face_path = os.path.join(self.out_path, "{}/keypoint_face") self.webcam_open = False self.is_writing = False self.is_gesture_recognition = False self.timestamp = "" self.start_time = 0 self.count = 0 self.gesture_model = self.get_gesture_model( "models/gesture/[email protected]") self.idx_to_gesture = { 0: 'eight', 1: 'five', 2: 'handssors', 3: 'normal', 4: 'ten' } # {'eight': 0, 'five': 1, 'handssors': 2, 'normal': 3} self.gesture_threshold = 0.57 self.init_openpose() self.init_checkbox() self.init_pushbutton() self.init_radiobutton() self.init_slider() self.init_treeview() self.init_others() def init_openpose(self): self.op_wrapper.configure(self.params) self.op_wrapper.start() def init_checkbox(self): self.checkBox_body.setChecked(False) # 默认设置为选中 self.checkBox_hand.setChecked(False) # 默认设置为选中 self.checkBox_face.setChecked(False) # 默认设置为选中 self.checkBox_gesture.setChecked(False) # 默认设置为选中 self.checkBox_gesture.setEnabled(False) # 默认设置为选中 self.checkBox_body.stateChanged.connect( self.check_body) # 状态改变触发check_box_changed函数 self.checkBox_hand.stateChanged.connect( self.check_hand) # 状态改变触发check_box_changed函数 self.checkBox_face.stateChanged.connect( self.check_face) # 状态改变触发check_box_changed函数 self.checkBox_gesture.stateChanged.connect(self.check_gesture) def init_radiobutton(self): self.radioButton_black.setEnabled(False) self.radioButton_rgb.setEnabled(False) self.radioButton_black.setChecked(False) self.radioButton_rgb.setChecked(True) self.radioButton_black.toggled.connect(self.change_background) # self.radioButton_rgb.toggled.connect(self.changeBackground) def init_pushbutton(self): self.pushButton_webcam.clicked.connect(self.run_webcam) self.pushButton_folder.clicked.connect(self.change_folder) self.pushButton_save.clicked.connect(self.save_current) self.pushButton_record.clicked.connect(self.record_video) self.pushButton_record.setEnabled(False) def init_slider(self): self.horizontalSlider_Body.setEnabled(False) self.horizontalSlider_Hand.setEnabled(False) self.horizontalSlider_Face.setEnabled(False) self.horizontalSlider_Body.setMaximum(100) self.horizontalSlider_Body.setMinimum(0) self.horizontalSlider_Body.setValue(1) self.horizontalSlider_Hand.setMaximum(100) self.horizontalSlider_Hand.setMinimum(0) self.horizontalSlider_Hand.setValue(20) self.horizontalSlider_Face.setMaximum(100) self.horizontalSlider_Face.setMinimum(0) self.horizontalSlider_Face.setValue(40) self.label_threshold_body.setText(str(1)) self.label_threshold_hand.setText(str(20)) self.label_threshold_face.setText(str(40)) self.horizontalSlider_Body.sliderReleased.connect( self.change_body_threshold) self.horizontalSlider_Face.sliderReleased.connect( self.change_face_threshold) self.horizontalSlider_Hand.sliderReleased.connect( self.change_hand_threshold) def init_treeview(self): # 目录树 self.treeView_file.setModel(self.tree_model) self.treeView_file.setRootIndex(self.tree_model.index(os.getcwd())) self.treeView_file.show() self.treeView_file.doubleClicked.connect(self.tree_clicked) def init_others(self): # 图像显示标签 self.label_frame.setScaledContents(True) def save_record_frame(self, img): cv2.imwrite( os.path.join(self.out_img_path.format(self.timestamp), "{:0>4d}.jpg".format(self.count)), img) if self.checkBox_body.isChecked(): body = os.path.join(self.out_body_path.format(self.timestamp), "{:0>4d}_body.npy".format(self.count)) np.save(body, self.datum.poseKeypoints) if self.checkBox_hand.isChecked(): hand = os.path.join(self.out_hand_path.format(self.timestamp), "{:0>4d}_hand.npy".format(self.count)) np.save(hand, self.datum.handKeypoints) if self.checkBox_face.isChecked(): face = os.path.join(self.out_face_path.format(self.timestamp), "{:0>4d}_face.npy".format(self.count)) np.save(face, self.datum.faceKeypoints) def show_frame(self): _, frame = self.cap.read() if frame is None: print("camera error") return img = self.process_image(frame) if self.is_writing: self.count += 1 self.save_record_frame(img) # 保存图片,关节点 t = str(time.time() - self.start_time)[:4] cv2.putText(img, t, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255)) if self.is_gesture_recognition: hand_keypoints = self.datum.handKeypoints # print(hand_keypoints) for hand in hand_keypoints: if hand.size == 1: continue for i in range(hand.shape[0]): if np.sum(hand[i, :, 2]) < 21 * 0.5: continue single_hand = hand[i, :, :2] x, y, w, h = self.find_hand_bbox(single_hand) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 255)) gesture = self.gesture_recognize(single_hand) # 识别单个手 cv2.putText(img, gesture, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255)) self.update_label(img) def find_hand_bbox(self, single_hand): n_points = single_hand.shape[0] points_list = [] for i in range(n_points): if np.sum(single_hand[i, :]) != 0: points_list.append(single_hand[i, :]) rect = cv2.boundingRect(np.array(points_list)) return rect def gesture_recognize(self, hand): hand[:, 0] /= 640 hand[:, 1] /= 480 hand = ToTensor()(hand) if torch.cuda.is_available(): hand = hand.cuda() hand = hand.view(1, -1) out = self.gesture_model(hand) out = F.softmax(out, 1) value, index = torch.max(out, 1) if value.item() > self.gesture_threshold: print(self.idx_to_gesture[index.item()], value.item()) return self.idx_to_gesture[index.item()] else: return None def tree_clicked(self, file_index): file_name = self.tree_model.filePath(file_index) if file_name.endswith(('.jpg', '.png')): if self.webcam_open: QMessageBox.information(self, "Note", "Please stop webcam first", QMessageBox.Yes) return img = cv2.imdecode(np.fromfile(file_name, dtype=np.uint8), cv2.IMREAD_COLOR) # -1表示cv2.IMREAD_UNCHANGED result = self.process_image(img) self.update_label(result) def update_label(self, frame): frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # bgr -> rgb h, w, c = frame.shape # 获取图片形状 image = QImage(frame, w, h, 3 * w, QImage.Format_RGB888) pixmap = QPixmap.fromImage(image) self.label_frame.setPixmap(pixmap) def process_image(self, img): self.datum.cvInputData = img self.op_wrapper.emplaceAndPop([self.datum]) result = self.datum.cvOutputData return result def change_background(self): if self.radioButton_black.isChecked(): self.params['disable_blending'] = True else: self.params['disable_blending'] = False self.update_wrapper() def change_folder(self): folder_name = QFileDialog.getExistingDirectory(self, '标题', './') # 可设置默认路径 if folder_name: self.treeView_file.setRootIndex(self.tree_model.index(folder_name)) self.treeView_file.show() def save_current(self): pixmap = self.label_frame.pixmap() if not pixmap: QMessageBox.warning(self, "Note", "No data in frame", QMessageBox.Yes) return body_keypoint = copy.deepcopy( self.datum.poseKeypoints) if self.checkBox_body.isChecked( ) else None hand_keypoint = copy.deepcopy( self.datum.handKeypoints) if self.checkBox_hand.isChecked( ) else None face_keypoint = copy.deepcopy( self.datum.faceKeypoints) if self.checkBox_face.isChecked( ) else None self.save_window.setFrame(pixmap.copy(), body_keypoint, hand_keypoint, face_keypoint) self.save_window.show() def record_video(self): if not self.cap.isOpened(): QMessageBox.warning(self, "Note", "Please open webcam first", QMessageBox.Yes) return if not self.is_writing: # 启动录制 self.pushButton_webcam.setEnabled(False) self.pushButton_save.setEnabled(False) self.pushButton_folder.setEnabled(False) self.pushButton_record.setText("Stop Record") self.is_writing = True self.timestamp = str(int(time.time())) self.start_time = time.time() # 初始化路径 if not os.path.exists(self.out_img_path.format(self.timestamp)): os.makedirs(self.out_img_path.format(self.timestamp)) if not os.path.exists(self.out_body_path.format(self.timestamp)): os.makedirs(self.out_body_path.format(self.timestamp)) if not os.path.exists(self.out_hand_path.format(self.timestamp)): os.makedirs(self.out_hand_path.format(self.timestamp)) if not os.path.exists(self.out_face_path.format(self.timestamp)): os.makedirs(self.out_face_path.format(self.timestamp)) else: # 停止录制 self.pushButton_webcam.setEnabled(True) self.pushButton_save.setEnabled(True) self.pushButton_folder.setEnabled(True) self.pushButton_record.setText("Begin Record") self.is_writing = False QMessageBox.information(self, "Note", "Saving in {}".format(self.out_path), QMessageBox.Yes) self.timestamp = "" self.start_time = 0 self.count = 0 def run_webcam(self): if self.webcam_open: self.webcam_open = False self.cap.release() self.label_frame.clear() self.timer.stop() self.pushButton_webcam.setText("Open Webcam") self.pushButton_record.setEnabled(False) else: self.webcam_open = True self.cap.open(0) self.timer.start(20) self.pushButton_webcam.setText("Stop Webcam") self.pushButton_record.setEnabled(True) def check_body(self, status): flag = True if status == Qt.Checked else False render_pose = 1 if status == Qt.Checked else 0 self.horizontalSlider_Body.setEnabled(flag) self.radioButton_black.setEnabled(flag) self.radioButton_rgb.setEnabled(flag) self.params["render_pose"] = render_pose self.update_wrapper() def check_hand(self, status): flag = True if status == Qt.Checked else False self.horizontalSlider_Hand.setEnabled(flag) self.checkBox_gesture.setEnabled(flag) self.params["hand"] = flag self.update_wrapper() def check_face(self, status): flag = True if status == Qt.Checked else False self.horizontalSlider_Face.setEnabled(flag) self.params["face"] = flag self.update_wrapper() def check_gesture(self, status): flag = True if status == Qt.Checked else False self.is_gesture_recognition = flag def change_body_threshold(self): value = self.horizontalSlider_Body.value() print(value) self.params["render_threshold"] = value / 100 self.label_threshold_body.setText(str(value)) self.update_wrapper() def change_hand_threshold(self): value = self.horizontalSlider_Hand.value() print(value) self.params["hand_render_threshold"] = value / 100 self.label_threshold_hand.setText(str(value)) self.update_wrapper() def change_face_threshold(self): value = self.horizontalSlider_Face.value() print(value) self.params["face_render_threshold"] = value / 100 self.label_threshold_face.setText(str(value)) self.update_wrapper() def update_wrapper(self): self.op_wrapper.configure(self.params) self.op_wrapper.start() @staticmethod def get_gesture_model(weights_path): model = Model(42, 32, 5) if torch.cuda.is_available(): model.load_state_dict(torch.load(weights_path)) model = model.cuda() else: model.load_state_dict( torch.load(weights_path, map_location=lambda storage, loc: storage)) model.eval() return model
class MyMainWindow(QWidget, Ui_Form): def __init__(self, proPath, parent=None): super(MyMainWindow, self).__init__(parent) # self.setCentralWidget(self.widget) self.proPath = proPath #************** 初始化窗口 self.setupUi(self) # 设置窗口的标题 self.setWindowTitle('ftpFilesys') # 设置窗口的图标,引用当前目录下的web.png图片 self.setWindowIcon(QIcon(self.proPath + '/Icon/LOGO.jpg')) self.setSignal() self.downing = True #************** 初始化按键 # self.Bt_down.setEnabled(False) self.Bt_up.setEnabled(False) # 创建SSH对象 self.ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机,否则可能报错:paramiko.ssh_exception.SSHException: Server '192.168.43.140' not found in known_hosts self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ftp_root = "/home/sd/ftp/biaodingCloud" #************** 初始化变量 """FTP窗口""" self.ftp = myFTP() # 实例化FTP self.ftp.encoding = "utf-8" self.select_file = "" # listView中选择的文件名 self.file_list = [] # 存放查询FTP返回的当前目录所有文件列表 self.ftp_tip = [] #存储当前登陆信息 """本地窗口""" # self.sysfile = QFileSystemModel() # 获取本地文件系统 # self.sysfile.setRootPath('') # self.treeView_local.setModel(self.sysfile) self.model = QDirModel() self.model.setFilter(QtCore.QDir.Dirs | QtCore.QDir.NoDotAndDotDot) self.treeView_local.header().hide() # 隐藏表头 self.treeView_local.setModel(self.model) for col in range(1, 4): self.treeView_local.setColumnHidden(col, True) self.save_path = "" # self.treeView_local.setRootIndex(self.model.index(self.save_path)) self.save_name = "" self.lineEdit_ip.setText("192.168.200.11") self.lineEdit_port.setText("21") self.lineEdit_user.setText("admin") self.lineEdit_pwd.setText("123") # 信号绑定设置 def setSignal(self): self.Bt_link.clicked.connect(self.ftp_connect) self.Bt_down.clicked.connect(self.Bt_down_run) # self.Bt_up.clicked.connect(self.ftp_connect) # 任意输入框改变就可以重新使能连接按键 self.lineEdit_ip.editingFinished.connect(self.BtEnabled) self.lineEdit_port.editingFinished.connect(self.BtEnabled) self.lineEdit_user.editingFinished.connect(self.BtEnabled) self.lineEdit_pwd.editingFinished.connect(self.BtEnabled) self.treeWidget_master.itemClicked.connect(self.select_item_ftp) # self.treeView_local.doubleClicked.connect(self.select_item_local) self.treeView_local.expanded.connect(self.select_item_local) self.treeView_local.clicked.connect(self.select_item_local) # self.treeWidget_master.doubleClicked.connect(self.cd_button) # 按键使能 def BtEnabled(self): self.Bt_link.setEnabled(True) self.Bt_down.setEnabled(False) self.Bt_up.setEnabled(False) # ftp 连接登录 def ftp_connect(self): self.Text_log.append("linking...") self.treeWidget_master.clear() host = self.lineEdit_ip.text() # 获取IP地址框内容 port = int(self.lineEdit_port.text()) # 获取端口号,注意要转换为int usr = self.lineEdit_user.text() # 获取用户名 pwd = self.lineEdit_pwd.text() # 获取密码 self.ftp_tip.append(host) self.ftp_tip.append(port) self.ftp_tip.append(usr) self.ftp_tip.append(pwd) try: self.ftp.connect(host, port, timeout=10) # 连接FTP except: logging.warning('network connect time out') # 打印日志信息 self.Text_log.append("network connect time out") try: self.ftp.login(usr, pwd) # 登录FTP except: logging.warning("username or password error") # 打印日志信息 self.Text_log.append("username or password error") self.file_list = self.ftp.nlst() # 查询当前目录的所有文件列表 self.Bt_link.setEnabled(False) self.root = QTreeWidgetItem(self.treeWidget_master) self.root.setText(0, '/') # print(self.setItemIcon('/')) self.root.setIcon(0, QIcon(self.setItem_Icon('/'))) self.root.setToolTip(0, '/') # self.dirItem(self.file_list,self.root) self.dirItem(self.root) self.cursor = self.Text_log.textCursor() self.Text_log.moveCursor(self.cursor.End) self.Text_log.append("link success!") # 连接服务器 result = self.ssh.connect(hostname=b'192.168.200.11', port=22, username=b'fs_001', password=b'123') self.Text_log.append(result) print("link success!") self.treeWidget_master.itemExpanded.connect(self.dirItem_new) # for col in range(len(self.file_list)): # print(col) # self.treeWidget_master.setColumnHidden(col, True) # print(self.ftp.dir('/DetectMask.zip')) # 判断数据类型,设置图标 def setItem_Icon(self, obj): if "." in obj: # 是文件则不能进入 icon = self.proPath + "/Icon/file.png" else: # 是文件夹则可以进入 icon = self.proPath + "/Icon/folder.png" if ".jpg" in obj or ".jpeg" in obj or ".png" in obj: # 是文件则不能进入 icon = self.proPath + "/Icon/file_img.png" elif ".zip" in obj or ".rar" in obj or ".7z" in obj: icon = self.proPath + "/Icon/file_zip.png" elif ".xls" in obj or ".xlsx" in obj: icon = self.proPath + "/Icon/file_excel.png" elif ".ppt" in obj or "pptx" in obj: icon = self.proPath + "/Icon/file_ppt.png" elif ".doc" in obj or ".docx" in obj or ".7z" in obj: icon = self.proPath + "/Icon/file_word.png" elif ".pdf" in obj: icon = self.proPath + "/Icon/file_pdf.png" elif ".py" in obj: icon = self.proPath + "/Icon/file_python.png" return icon # 递归操作,遍历ftp服务器所有文件 def dirItem(self, item): # print(item.toolTip((0))) list = self.ftp.nlst(str(item.toolTip(0))) # for name1 in list: # print(" ",name1) #self.showMessage("加载... ", QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom, QtCore.Qt.black) for i, path in enumerate(list): name = path.split('/')[-1] child = QTreeWidgetItem(item) item.addChild(child) child.setIcon(0, QIcon(self.setItem_Icon(name))) child.setText(0, name) # print(self.ftp.pwd()) child.setToolTip(0, path) # print(child.toolTip(0)) # print(this,name) # 动态加载dirItem def dirItem_new(self, item): # print(item.toolTip((0))) # list=self.ftp.nlst(str(item.toolTip(0))) child_num = item.childCount() for i in range(child_num): cc_num = item.child(i).childCount() item.child(i).setExpanded(False) if cc_num >= 0: for j in range(cc_num): item.child(i).removeChild(item.child(i).child(j)) if self.checkFileDir(self.ftp, item.child(i).toolTip(0)) == "dir": self.dirItem(item.child(i)) # time.sleep(10) """递归操作,耗费资源+加载时间久,放弃""" # 递归操作,遍历ftp服务器所有文件 # def dirItem(self,list,item): # # list=self.ftp.nlst(str(item.toolTip(0))) # # self.showMessage("加载... ", QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom, QtCore.Qt.black) # for i,name in enumerate(list): # child = QTreeWidgetItem(item) # item.addChild(child) # child.setIcon(0,QIcon(self.setItem_Icon(name))) # child.setText(0,name) # child.setToolTip(0,self.ftp.pwd()) # # print(child.toolTip(0)) # # print(this,name) # this = self.checkFileDir(self.ftp, name) # if this == "dir": # # print(self.ftp.pwd(), name) # self.ftp.cwd(name) # filelist=self.ftp.nlst() # # for name1 in filelist: # # print(" ",name1) # self.dirItem(filelist,child) # self.ftp.cwd("..") # 判断是否为文件 def checkFileDir(self, ftp, file_name): """ 判断当前目录下的文件与文件夹 :param ftp: 实例化的FTP对象 :param file_name: 文件名/文件夹名 :return:返回字符串“File”为文件,“Dir”问文件夹,“Unknow”为无法识别 """ rec = "" try: rec = ftp.cwd(file_name) # 需要判断的元素 ftp.cwd("..") # 如果能通过路径打开必为文件夹,在此返回上一级 except ftplib.error_perm as fe: rec = fe # 不能通过路劲打开必为文件,抓取其错误信息 finally: # print(file_name,rec) if "550" in str(rec)[:3]: return "file" elif "250" in str(rec)[:3]: return "dir" else: return "unknow" # 单击选中,使能下载按键 def select_item_ftp(self, item): # print(item.text(0),item.columnCount()) self.select_item = item self.select_file = item.toolTip(0) # print(self.select_file) if '.' in self.select_file: # 如果是文件,则可下载 self.Bt_down.setEnabled(True) else: # 否则是文件夹,不能下载 self.Bt_down.setEnabled(False) # 选择文件保存目录 def select_item_local(self, obj): self.save_path = self.model.filePath(obj) # 更新主窗口显示 def handleDisplay(self, data): if "ERROR" in data: self.Text_log.append(data) self.Bt_link.setEnabled(True) else: self.cursor = self.Text_log.textCursor() self.cursor.select(QTextCursor.LineUnderCursor) self.cursor.removeSelectedText() # self.Text_log.moveCursor(QtGui.QTextCursor.StartOfLine, QtGui.QTextCursor.MoveAnchor) self.Text_log.insertPlainText(data) if data == "100%": self.downing = True self.Text_log.append("Download Success!") self.thread.quit() # 执行命令 # stdin:标准输入(就是你输入的命令);stdout:标准输出(就是命令执行结果);stderr:标准错误(命令执行过程中如果出错了就把错误打到这里),stdout和stderr仅会输出一个 self.mv_file() self.Bt_down.setEnabled(False) # 移动文件 def mv_file(self): old_file = False path, file = os.path.split(self.select_file) print(self.ftp_root + path + "/old_file/") # s = self.ftp.mkd(path + "/old_file/") stdin, stdout, stderr = self.ssh.exec_command( "mkdir %s" % (self.ftp_root + path + "/old_file/")) stdin, stdout, stderr = self.ssh.exec_command( "mv %s %s" % (self.ftp_root + self.select_file, self.ftp_root + path + "/old_file/" + file)) # # self.Text_log.append(str(stdout)) parent = self.select_item.parent() print(parent.toolTip(0)) parent.setExpanded(False) parent.removeChild(self.select_item) child_num = parent.childCount() for i in range(child_num): if self.checkFileDir(self.ftp, parent.child(i).toolTip(0)) == "dir": if parent.child(i).text(0) == "old_file": old_file = True if old_file == False: item_name = "old_file" child = QTreeWidgetItem(parent) parent.addChild(child) child.setIcon(0, QIcon(self.setItem_Icon(item_name))) child.setText(0, item_name) # print(self.ftp.pwd()) child.setToolTip(0, path + "/old_file") # else: # child_num = parent.childCount() # for i in range(child_num): # parent.removeChild(parent.child(i)) # self.dirItem(parent) parent.setExpanded(True) self.treeWidget_master.update() # self.select_item.setExpanded(True) # 下载晚间操作 def Bt_down_run(self): if self.save_path == "": self.Text_log.append("未选择保存路径") self.downing = True reply = QMessageBox.warning(self, "警告", "未选择保存路径", QMessageBox.Ok) return if self.select_file == "": self.Text_log.append("未选择下载文件") self.downing = True reply = QMessageBox.warning(self, "警告", "未选择下载文件", QMessageBox.Ok) return if self.downing == False: reply = QMessageBox.warning(self, "警告", "正在下载,请等待。。。", QMessageBox.Ok) return self.downing = False self.save_name = self.save_path + "/%s" % self.select_file.split( '/')[-1] # print(self.select_file, self.save_name) self.Text_log.append("开始下载,\"%s\"将文件下载到\"%s\"" % (self.select_file, self.save_name)) if self.checkFileDir(self.ftp, self.select_file) == "dir": self.Text_log.append("这是文件夹,不能下载") return print(self.save_name) if os.path.exists(self.save_name): reply = QMessageBox.warning(self, "文件已存在", "是否覆盖?", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: os.remove(self.save_name) else: self.downing = True return # 创建线程 self.down = down_Thread(self.ftp_tip, self.select_file, self.save_name) # self.down = down_Thread(self) # thread = MyThread(target=self.tcp_run, args=(self.ftp_tip,self.select_file,self.save_name)) # target = self.ftp.retrbinary, args = ("RETR %s" % self.select_file, open(self.save_name, 'wb').write) # 连接信号 self.down.update_date.connect(self.handleDisplay) self.thread = QThread() self.Text_log.append("0%") self.down.moveToThread(self.thread) # 开始线程 self.thread.started.connect(self.down.run) self.thread.start()
class Notebook(QMainWindow, Ui_CodePlus): r""" Notebook 类 """ def __init__(self, parent=None): super().__init__(parent) self.icon = QIcon() self.icon.addPixmap(QPixmap("./tianhou.ico"), QIcon.Normal, QIcon.Off) self.setWindowIcon(self.icon) self.setupUi(self) """-------- System ---------""" self.local_system = platform.system() """-------- Short Cuts ---------""" self.actionSave.setShortcut(QKeySequence(QKeySequence.Save)) self.actionUndo.setShortcut(QKeySequence(QKeySequence.Undo)) self.actionRedo.setShortcut(QKeySequence(QKeySequence.Redo)) self.actionNew.setShortcut(QKeySequence(QKeySequence.New)) self.actionCopy.setShortcut(QKeySequence(QKeySequence.Copy)) self.actionPaste.setShortcut(QKeySequence(QKeySequence.Paste)) self.actionCut.setShortcut(QKeySequence(QKeySequence.Cut)) self.actionFind.setShortcut(QKeySequence(QKeySequence.Find)) self.actionSelect_All.setShortcut(QKeySequence(QKeySequence.SelectAll)) """-------- Code ---------""" self.actionAbout_us.triggered.connect(self.aboutusEvent) # 关于我们 self.actionExit.triggered.connect(self.closeEvent) # 退出 self.actionPreference.triggered.connect( self.showpreferenceEvent) # 偏好设置 """-------- File ---------""" self.actionNew.triggered.connect(self.newfileEvent) # 新建 self.actionOpen_File.triggered.connect(self.openfileEvent) # 打开文件 self.actionOpen_Folder.triggered.connect(self.openfolderEvent) # 打开文件夹 self.actionSave.triggered.connect(self.savefileEvent) # 保存文件 self.actionSave_All.triggered.connect(self.saveallEvent) # 全部保存 self.actionSave_As.triggered.connect(self.saveasEvent) # 另存为 self.actionClose.triggered.connect(self.closefileEvent) # 关闭 self.tabWidget.tabCloseRequested.connect(self.closefileEvent) # 关闭tab """-------- Edit ---------""" self.actionUndo.triggered.connect(self.text_undo) # 撤销 self.actionRedo.triggered.connect(self.text_redo) # 重做 self.actionCut.triggered.connect(self.text_cut) # 剪切 self.actionCopy.triggered.connect(self.text_copy) # 复制 self.actionPaste.triggered.connect(self.text_paste) # 粘贴 self.actionFind.triggered.connect(self.text_find) # 查找 self.win_find_is_show = False self.actionSelect_All.triggered.connect(self.text_selectAll) # 全选 """-------- Language ---------""" self.actionPlain_Text.triggered.connect(self.selectLanguage) self.actionC.triggered.connect(self.selectLanguage) self.actionMarkdown.triggered.connect(self.selectLanguage) self.actionPython.triggered.connect(self.selectLanguage) """-------- Whatever... ---------""" self.actionQR_Code.triggered.connect(self.rewardEvent) # 打赏 """-------- Status bar ---------""" self.lb_margin = QtWidgets.QLabel() self.lb_lang = QtWidgets.QLabel() self.statusbar.addWidget(self.lb_margin, 4) self.statusbar.addWidget(self.lb_lang, 1) """-------- Dir Tree ---------""" self.model = QDirModel() """ view from source""" """-------- Run Event ---------""" self.dock_win = QtWidgets.QDockWidget() self.dock_tab = QtWidgets.QTabWidget() self.dock_win.setWidget(self.dock_tab) self.addDockWidget(Qt.BottomDockWidgetArea, self.dock_win) self.dock_tab.setTabPosition(QTabWidget.South) self.teridx = 0 self.dock_win.setFeatures(QDockWidget.DockWidgetVerticalTitleBar) self.dock_tab.setTabsClosable(True) self.dock_tab.tabCloseRequested.connect(self.run_close_event) self.run_event = False self.actionStop.setDisabled(True) """-------- Basic Configs ---------""" self.setAttribute(Qt.WA_DeleteOnClose, True) self.tabWidget.setAttribute(Qt.WA_DeleteOnClose, True) self.tabidx = 0 self.font_content = None # 字体和大小 self.interpreter = None # 解释器 self.preference = Preference(par=self) self.tab_dict = {} # 存放tab self.file_save_path = None # 保存文件的路径 self.language = 'txt' # 当前语言 """-------- Terminal ---------""" self.actionNew_Terminal.triggered.connect(self.new_terminal_event) # self.actionClose_Terminal.triggered.connect(self.close_terminal_event) """-------- Run ---------""" self.run_browser = RunBrowser(self.font_content) self.run_browser.startSignal.connect(self.run_start_event) self.run_browser.exitSignal.connect(self.run_exit_event) self.gcc = None self.actionRun.triggered.connect(self.new_run_event) self.actionStop.triggered.connect(self.stop_run) self.actionCompile.triggered.connect(self.compile_event) """--------tool------------""" self.actionWrite_Board.triggered.connect(self.OpenBoard) self.enableClickFlag = True # 改变tab enable的flag """所有语言类型为: txt -> 文本文件 md -> Markdown文件 c -> C文件 py -> Python文件 """ """-------- 初始执行的操作 ---------""" self.openIDEevent() def OpenBoard(self): textedit = self.__get_textEditor() self.boardwindow = PaintForm(textedit) self.boardwindow.show() def openIDEevent(self): tmp_path = '.tmp' def listdir(path): for item in os.listdir(path): if not item.startswith('.') and not item.endswith('.pkl'): yield item if not os.path.exists(tmp_path) or not os.path.exists( os.path.join(tmp_path, 'mapping.pkl')): self.__create_tab() # 初始创建一个tab self.tabWidget.currentChanged.connect(self.changeTab) # 切换tab触发 else: """读取缓存的文件""" with open(os.path.join(tmp_path, 'mapping.pkl'), 'rb') as f: mapping = pickle.load(f) tmp_files = listdir(tmp_path) for i, file in enumerate(tmp_files): file_path = os.path.join(tmp_path, file) if file.startswith('*'): file = file[1:] origin_path = mapping[file] self.openfileEvent(file_path, origin_path) if i == 0: self.tabWidget.currentChanged.connect( self.changeTab) # 切换tab触发 self.lb_lang.setText(self.language) def stop_run(self): self.run_browser.process.close() def run_start_event(self): self.actionRun.setDisabled(True) self.actionStop.setDisabled(False) def run_exit_event(self): self.actionRun.setDisabled(False) self.actionStop.setDisabled(True) def new_run_event(self): if not self.run_event: pix = QPixmap('./imgs/run.jpg') icon = QIcon() icon.addPixmap(pix) self.dock_tab.addTab(self.run_browser, 'Run ') index = self.dock_tab.count() - 1 self.dock_tab.setTabIcon(index, icon) self.dock_tab.setCurrentIndex(index) self.run_event = True cur_path = self.__get_textEditor().filepath if cur_path: if os.path.splitext(cur_path)[-1] == '.py': if not self.interpreter: QMessageBox.warning( self, '提示', '未设置有效的python解释器\n' + '->\n'.join([ 'Code', 'Preference', 'Environment', 'interpreter' ])) return cmd = ' '.join([self.interpreter, cur_path]) self.run_browser.start_process(cmd) elif os.path.splitext(cur_path)[-1] == '.c': cmd = os.path.splitext(cur_path)[0] + '.exe' if os.path.exists(cmd): self.run_browser.process.start(cmd) else: compile_cmd = 'gcc ' + cur_path self.run_browser.process.start(compile_cmd) self.run_browser.process.waitForFinished() if os.path.exists(cmd): self.run_browser.process.start(cmd) def compile_event(self): if not self.run_event: pix = QPixmap('./imgs/run.jpg') icon = QIcon() icon.addPixmap(pix) self.dock_tab.addTab(self.run_browser, 'Run ') index = self.dock_tab.count() - 1 self.dock_tab.setTabIcon(index, icon) self.dock_tab.setCurrentIndex(index) self.run_event = True cur_path = self.__get_textEditor().filepath if cur_path: if os.path.splitext(cur_path)[-1] == '.c': cmd = 'gcc ' + cur_path self.run_browser.start_process(cmd) def run_close_event(self): if not self.actionRun.isEnabled(): ref = QMessageBox.information(self, '提示', '还有项目正在运行\n确定退出?', QMessageBox.Yes | QMessageBox.No) if ref == QMessageBox.Yes: self.stop_run() else: return self.run_event = False self.dock_tab.removeTab(0) def new_terminal_event(self): if self.local_system == 'Windows': os.system('start cmd') elif self.local_system == 'Linux': os.system('gnome-terminal') elif self.local_system == 'Darwin': os.system('open -a Terminal .') def close_terminal_event(self): if self.local_system == 'Darwin': import appscript appscript.app('Terminal').do_script('exit') # def new_terminal_event(self): # from threading import Thread # t = Thread(target=self.aaa) # t.start() # # self.teridx += 1 # self.temp = QTextEdit() # time.sleep(1) # calc_hwnd = win32gui.FindWindow(None, u'C:\WINDOWS\system32\cmd.exe') # print(calc_hwnd) # # self.win = QWindow.fromWinId(calc_hwnd) # # self.new_tab = self.createWindowContainer(self.win, self.temp) # self.new_tab.showMaximized() # # self.win.setKeyboardGrabEnabled(True) # # self.win.setMouseGrabEnabled(True) # 查找 def text_find(self): textedit = self.__get_textEditor() # if isinstance(textedit, QTextEdit): if not self.win_find_is_show: self.win_find_is_show = True self.find_win = Find_Win(self, textedit) self.find_win.show() def text_undo(self): textedit = self.__get_textEditor() # if isinstance(textedit, QTextEdit): textedit.undo() def text_redo(self): textedit = self.__get_textEditor() # if isinstance(textedit, QTextEdit): textedit.redo() def text_copy(self): textedit = self.__get_textEditor() # if isinstance(textedit, QTextEdit): textedit.copy() def text_paste(self): textedit = self.__get_textEditor() # if isinstance(textedit, QTextEdit): textedit.paste() def text_cut(self): textedit = self.__get_textEditor() # if isinstance(textedit, QTextEdit): textedit.cut() def text_selectAll(self): textedit = self.__get_textEditor() # if isinstance(textedit, QTextEdit): textedit.selectAll() def selectLanguage(self): r""" 选择语言 :return: """ language_support = { 'Plain Text': 'txt', 'C': 'c', 'Markdown': 'md', 'Python': 'py' } textedit = self.__get_textEditor() signal_src = self.sender().text() language = language_support[signal_src] textedit.setlanguage(language) self.language = language self.lb_lang.setText(self.language) # if self.language == 'txt': # self.actionPlain_Text.setDisabled(True) if signal_src == 'Markdown': self.markdown_handler() else: self.normalmode_handler() def changeTab(self): # super().tabWidget.changeEvent() self.language = self.cur_language() self.lb_lang.setText(self.language) cur_tabs = self.tabWidget.count() if cur_tabs == 0: self.actionCut.setDisabled(True) self.actionFind.setDisabled(True) self.actionSave.setDisabled(True) self.actionSave_All.setDisabled(True) self.actionSave_As.setDisabled(True) self.actionClose.setDisabled(True) self.actionUndo.setDisabled(True) self.actionRedo.setDisabled(True) self.actionCopy.setDisabled(True) self.actionPaste.setDisabled(True) self.actionSelect_All.setDisabled(True) self.actionC.setDisabled(True) self.actionPython.setDisabled(True) self.actionPlain_Text.setDisabled(True) self.actionMarkdown.setDisabled(True) self.actionRun.setDisabled(True) self.actionCompile.setDisabled(True) self.enableClickFlag = False else: if not self.enableClickFlag: self.enableClickFlag = True self.actionCut.setDisabled(False) self.actionFind.setDisabled(False) self.actionSave.setDisabled(False) self.actionSave_All.setDisabled(False) self.actionSave_As.setDisabled(False) self.actionClose.setDisabled(False) self.actionUndo.setDisabled(False) self.actionRedo.setDisabled(False) self.actionCopy.setDisabled(False) self.actionPaste.setDisabled(False) self.actionSelect_All.setDisabled(False) self.actionC.setDisabled(False) self.actionPython.setDisabled(False) self.actionPlain_Text.setDisabled(False) self.actionMarkdown.setDisabled(False) self.actionRun.setDisabled(False) self.actionCompile.setDisabled(False) def cur_language(self): if self.tabWidget.count() == 0: return '' language = self.__get_textEditor().language return language def __find_tab_by_index(self, index): r""" 通过currentIndex获取字典中的 :param index: CurrentIndex :return: (str, object) 当前Tab名,TabItem 对象 """ cur_tab_name = self.tabWidget.widget(index).objectName() return cur_tab_name, self.tab_dict[cur_tab_name] def __get_textEditor(self, index=None): r""" 获取当前tab的textEditor :return: (object) textEditor """ if index is None: index = self.tabWidget.currentIndex() _, tabitem = self.__find_tab_by_index(index) return tabitem.text def __get_tabitem(self, index=None): r""" 获取当前tab :return: (object) tab """ if index is None: index = self.tabWidget.currentIndex() _, tabitem = self.__find_tab_by_index(index) return tabitem def newfileEvent(self): r""" 新建文件事件函数 :return: None """ self.__create_tab() def __create_tab(self, name=None): r""" 新建tab :return: None """ self.tabidx += 1 newfile_name = f'New File {self.tabidx}' if name is None else name if name: _, language = os.path.splitext(name) language = language[1:] else: language = 'txt' new_tabname = 'tab_' + str(self.tabidx) tab_new = QWidget() tab_new.setObjectName(new_tabname) layout = QGridLayout(tab_new) layout.setObjectName(f'layout_of_{new_tabname}') # text_editor = TextEditorS(name=newfile_name, parent_tabWidget=self.tabWidget, # language=language, font_size=self.fontsize) # text_editor = Editor() text_editor = IDEeditor(name=newfile_name, parent_tabWidget=self.tabWidget, language=language, font_content=self.font_content) text_editor.newFileSignal.connect(lambda: self.model.refresh()) # text_editor.textChange.connect(self.__handle_textChange) layout.addWidget(text_editor, 0, 0, 1, 1) tabitem = TabItem(tab_new, layout, text_editor) self.tab_dict[new_tabname] = tabitem self.tabWidget.addTab(tab_new, newfile_name) # 跳转到新页面 index = self.tabWidget.count() - 1 self.tabWidget.setCurrentIndex(index) if language == 'md': self.markdown_handler() def openfileEvent(self, file_path=None, mapping=None): r""" 打开文件事件函数 :return: None """ if not file_path: file_path, _ = QFileDialog.getOpenFileName( self, 'Choose a file', '/', 'All Files (*);;' 'Text Files (*.txt);;' 'Markdown Files (*.md);;' 'C Sources (*.c);;' 'Python Scripts (*.py)') if not file_path: return # 判断文件是否可读取 if os.path.isdir(file_path): # 屏蔽文件夹 return if not os.path.splitext(file_path)[-1] in ['.py', '.c', '.txt', '.md']: QMessageBox.warning(self, u'警告', u'文件类型不支持!') return if len(file_path): _, file_fullname = os.path.split(file_path) for tabitem in self.tab_dict.values(): tmp_edititem = tabitem.text if file_fullname == tmp_edititem.objectName(): index = self.tabWidget.indexOf(tabitem.tab) self.tabWidget.setCurrentIndex(index) return self.__create_tab(name=file_fullname) index = self.tabWidget.count() - 1 textedit = self.__get_textEditor(index=index) textedit.load(file_path, mapping) def openfolderEvent(self): folder_path = QFileDialog.getExistingDirectory(self, '请选择打开的文件夹') if folder_path: self.dirtree.setModel(self.model) self.dirtree.setRootIndex(self.model.index(folder_path)) self.dirtree.setAnimated(False) self.dirtree.setIndentation(20) self.dirtree.setSortingEnabled(True) self.dirtree.doubleClicked.connect(self.__choose_file) self.dirtree.setWindowTitle("Dir View") # self.dirtree.setHeaderHidden(True) def __choose_file(self, index): file_path = self.model.filePath(index) # print(file_path) self.openfileEvent(file_path) def saveasEvent(self): r""" 另存为事件函数 :return: None """ textedit = self.__get_textEditor() status = textedit.saveas() if status: """保存成功,设置tab名""" index = self.tabWidget.currentIndex() textedit = self.__get_textEditor(index) self.language = textedit.language self.lb_lang.setText(self.language) def savefileEvent(self): r""" 保存文件事件函数 :return: """ textedit = self.__get_textEditor() text_saveas = textedit.save() if text_saveas: self.language = textedit.language self.lb_lang.setText(self.language) def saveallEvent(self): r""" 全部保存 :return: """ for tabitem in self.tab_dict.values(): textedit = tabitem.text text_saveas = textedit.save() if text_saveas: self.language = textedit.language self.lb_lang.setText(self.language) def closefileEvent(self, index): r""" 关闭文件事件函数 :return: None """ if self.tabWidget.count() == 0: self.close() return cur_tab_name, tabitem = self.__find_tab_by_index(index) textedit = tabitem.text # print(cur_tab_name) if textedit.isModified(): """已修改文件,需要保存""" ret_code = QMessageBox.information( self, '提示', '文件尚未保存,确定退出?', QMessageBox.Yes | QMessageBox.No) # ret_code: Yes -- 16384 # No -- 65536 if ret_code == QMessageBox.Yes: textedit.closeText() self.tabWidget.removeTab(index) del self.tab_dict[cur_tab_name] else: textedit.closeText() self.tabWidget.removeTab(index) del self.tab_dict[cur_tab_name] def setFontSizeEvent(self): r""" 改变所有textedit的字体大小和样式 :return: """ for tabitem in self.tab_dict.values(): textedit = tabitem.text textedit.setFontSize(self.font_content) self.run_browser.set_font(self.font_content) def rewardEvent(self): r""" 打赏事件函数 :return: """ self.qrcode_window = Reward() self.qrcode_window.show() def showpreferenceEvent(self): r""" 调出偏好设置 :return: """ self.preference.show() def aboutusEvent(self): r""" 关于我们事件函数 :return: """ QMessageBox.information( self, 'About us', 'Monkey Editor v0.1\n' u'天猴工作室出品 \n' u'制作人:吴栋、廖满文、汪潇翔、文一晴、吴雨暄、张维天') def closeEvent(self, event): r""" 关闭notebook事件函数 :param event: :return: None """ # 缓存文件的文件夹 tmp_path = '.tmp' if os.path.exists(tmp_path): # os.system(f'rm -r {tmp_path}') shutil.rmtree(tmp_path) if len(self.tab_dict): os.mkdir(tmp_path) # check_quit = True increment = 1 mapping = {} # 地址映射表 for tabitem in self.tab_dict.values(): # 缓存当前未关闭的页面 textedit = tabitem.text if textedit.filepath is None: tmp_filename = f'Plain_{increment}.' + self.language mapping[tmp_filename] = None tmp_filepath = os.path.join(tmp_path, tmp_filename) increment += 1 else: _, tmp_filename = os.path.split(textedit.filepath) mapping[tmp_filename] = textedit.filepath tmp_filepath = os.path.join(tmp_path, tmp_filename) if textedit.isModified(): # check_quit = False tmp_filepath = os.path.join(tmp_path, '*' + tmp_filename) textedit.save(tmp_filepath) # 保存mapping try: with open(os.path.join(tmp_path, 'mapping.pkl'), 'wb') as f: pickle.dump(mapping, f) except: pass # if not check_quit: # ret_code = QMessageBox.information(self, '提示', '存在文件未保存,确定退出?', # QMessageBox.Yes | QMessageBox.No) # if ret_code == QMessageBox.Yes: # self.close() # else: # event.ignore() # else: # 保存preference self.preference.close() self.close() def markdown_handler(self): index = self.tabWidget.currentIndex() _, tabitem = self.__find_tab_by_index(index) current_tab = tabitem.tab current_layout = tabitem.layout current_text = tabitem.text # content = current_text.text() # content.replace(r'\r\n', r' \n') # content = '' # for i in range(linenum - 1): # current_content = current_text.document().findBlockByLineNumber(i).text() # current_content += ' \n' # content += current_content # for i in reversed(range(current_layout.count())): # current_layout.takeAt(i).widget().deleteLater() # markdown_tab = QtWidgets.QTabWidget(current_tab) # markdown_tab.setTabPosition(3) # orin = QWidget() # md = QWidget() # orin.setObjectName("orin") # md.setObjectName("md") # layout_orin = QGridLayout(orin) # text_editor_orin = TextEditorS(name='orin', parent_tabWidget=self.tabWidget, language=language) # layout_orin.addWidget(text_editor_orin, 0, 0, 1, 1) # layout_md = QGridLayout(md) # text_editor_txt = TextEditorS(name='md_txt', parent_tabWidget=self.tabWidget, # language='txt', font_content=self.font_content) text_browser_md = TextEditorS(name='md_show', parent_tabWidget=self.tabWidget, language='md') text_browser_md.setReadOnly(True) # text_editor_txt = TextEditorS(name='md_txt', parent_tabWidget=self.tabWidget, language='txt') # text_browser_md = TextEditorS(name='md_md', parent_tabWidget=self.tabWidget, language=self.language) # layout_md.addWidget(text_editor_txt, 0, 0, 1, 1) # layout_md.addWidget(text_browser_md, 0, 1, 1, 1) # markdown_tab.addTab(orin, 'orin') # markdown_tab.addTab(md, 'md') current_layout.addWidget(text_browser_md, 0, 1, 1, 1) # current_layout.addWidget(markdown_tab, 0, 0, 1, 1) tabitem = TabItem(current_tab, current_layout, current_text, text_browser_md) now_tabname = 'tab_' + str(self.tabidx) self.tab_dict[now_tabname] = tabitem current_text.linesChanged.connect(self.show_markdown) # text_editor_txt.document().blockCountChanged.connect(self.show_markdown) # text_editor_txt.setPlainText(content) # text_editor_txt.document().blockCountChanged.connect(self.show_markdown) def normalmode_handler(self): index = self.tabWidget.currentIndex() _, tabitem = self.__find_tab_by_index(index) current_tab = tabitem.tab current_layout = tabitem.layout current_text = tabitem.text if tabitem.textview != None: current_layout.itemAt(1).widget().close() tabitem = TabItem(current_tab, current_layout, current_text) now_tabname = 'tab_' + str(self.tabidx) self.tab_dict[now_tabname] = tabitem def show_markdown(self): current_tab = self.__get_tabitem() textedit = current_tab.text textview = current_tab.textview if textview != None: content = textedit.text() content = content.replace('\r\n', ' \n') textview.document().setMarkdown(content) # linenum = textedit.document().lineCount() # content = '' # for i in range(linenum - 1): # current_content = textedit.document().findBlockByLineNumber(i).text() # current_content += ' \n' # content += current_content def windowShow(self): youWin.show() #你的主页程序