class ClientUI(QWidget): def __init__(self): super().__init__() # self.window = QWidget() self.resize(1000, 600) self.setWindowTitle("拍一拍聊天室") # 聊天窗口 self.messageBrowser = QTextBrowser() # 字体选择 self.fontComboBox = QFontComboBox() self.fontComboBox.setObjectName("fontComboBox") self.fontComboBox.currentFontChanged.connect( self.on_fontComboBox_currentFontChanged) # 字体大小 self.sizeComboBox = QComboBox() self.sizeComboBox.setObjectName("SizeComboBox") self.sizeComboBox.setCurrentIndex(0) for i in range(31): self.sizeComboBox.addItem("") _translate = QCoreApplication.translate self.sizeComboBox.setCurrentText(_translate("Widget", "10")) for i in range(31): self.sizeComboBox.setItemText(i, _translate("Widget", str(i + 10))) self.sizeComboBox.currentIndexChanged.connect( self.on_SizeComboBox_currentIndexChanged) # 加粗 self.boldToolBtn = QToolButton() self.boldToolBtn.setContextMenuPolicy(Qt.DefaultContextMenu) icon = QIcon() root = QFileInfo(__file__).absolutePath() # 获取根目录 icon.addPixmap(QPixmap(root + "/image/bold.png"), QIcon.Normal, QIcon.Off) self.boldToolBtn.setIcon(icon) self.boldToolBtn.setIconSize(QSize(22, 22)) self.boldToolBtn.setCheckable(True) self.boldToolBtn.setAutoRaise(True) self.boldToolBtn.setObjectName("boldToolBtn") self.boldToolBtn.setToolTip(_translate("Widget", "加粗")) self.boldToolBtn.setText(_translate("Widget", "...")) self.boldToolBtn.clicked.connect(self.on_boldToolBtn_clicked) # 斜体 self.italicToolBtn = QToolButton() icon1 = QIcon() icon1.addPixmap(QPixmap(root + "/image/italic.png"), QIcon.Normal, QIcon.Off) self.italicToolBtn.setIcon(icon1) self.italicToolBtn.setIconSize(QSize(22, 22)) self.italicToolBtn.setCheckable(True) self.italicToolBtn.setAutoRaise(True) self.italicToolBtn.setObjectName("italicToolBtn") self.italicToolBtn.setToolTip(_translate("Widget", "倾斜")) self.italicToolBtn.setText(_translate("Widget", "...")) self.italicToolBtn.clicked.connect(self.on_italicToolBtn_clicked) # 下划线 self.underlineToolBtn = QToolButton() icon2 = QIcon() icon2.addPixmap(QPixmap(root + "/image/under.png"), QIcon.Normal, QIcon.Off) self.underlineToolBtn.setIcon(icon2) self.underlineToolBtn.setIconSize(QSize(22, 22)) self.underlineToolBtn.setCheckable(True) self.underlineToolBtn.setAutoRaise(True) self.underlineToolBtn.setObjectName("underlineToolBtn") self.underlineToolBtn.setToolTip(_translate("Widget", "下划线")) self.underlineToolBtn.setText(_translate("Widget", "...")) self.underlineToolBtn.clicked.connect(self.on_underlineToolBtn_clicked) # 颜色 self.colorToolBtn = QToolButton() icon3 = QIcon() icon3.addPixmap(QPixmap(root + "/image/color.png"), QIcon.Normal, QIcon.Off) self.colorToolBtn.setIcon(icon3) self.colorToolBtn.setIconSize(QSize(22, 22)) self.colorToolBtn.setAutoRaise(True) self.colorToolBtn.setObjectName("colorToolBtn") self.colorToolBtn.setToolTip(_translate("Widget", "更改字体颜色")) self.colorToolBtn.setText(_translate("Widget", "...")) self.colorToolBtn.clicked.connect(self.on_colorToolBtn_clicked) # 聊天记录 self.saveToolBtn = QToolButton() icon4 = QIcon() icon4.addPixmap(QPixmap(root + "/image/save.png"), QIcon.Normal, QIcon.Off) self.saveToolBtn.setIcon(icon4) self.saveToolBtn.setIconSize(QSize(22, 22)) self.saveToolBtn.setAutoRaise(True) self.saveToolBtn.setObjectName("saveToolBtn") self.saveToolBtn.setToolTip(_translate("Widget", "保存聊天记录")) self.saveToolBtn.setText(_translate("Widget", "...")) self.saveToolBtn.clicked.connect(self.on_saveToolBtn_clicked) self.clearToolBtn = QToolButton() icon5 = QIcon() icon5.addPixmap(QPixmap(root + "/image/clear.png"), QIcon.Normal, QIcon.Off) self.clearToolBtn.setIcon(icon5) self.clearToolBtn.setIconSize(QSize(22, 22)) self.clearToolBtn.setAutoRaise(True) self.clearToolBtn.setObjectName("clearToolBtn") self.clearToolBtn.setToolTip(_translate("Widget", "清空聊天记录")) self.clearToolBtn.setText(_translate("Widget", "...")) self.clearToolBtn.clicked.connect(self.on_clearToolBtn_clicked) # 发送按钮 self.sendButton = QPushButton('发送') self.sendButton.clicked.connect(self.sendChatMsg) # 发送功能横向布局 functionboxLayout = QHBoxLayout() functionboxLayout.addWidget(self.fontComboBox) functionboxLayout.addWidget(self.sizeComboBox) functionboxLayout.addWidget(self.boldToolBtn) functionboxLayout.addWidget(self.italicToolBtn) functionboxLayout.addWidget(self.underlineToolBtn) functionboxLayout.addWidget(self.colorToolBtn) functionboxLayout.addWidget(self.saveToolBtn) functionboxLayout.addWidget(self.clearToolBtn) functionboxLayout.addStretch(1) functionboxLayout.addWidget(self.sendButton) # 输入框 self.messageEdit = QTextEdit() # 左侧竖向布局,三行 vhoxLayout_left = QVBoxLayout() vhoxLayout_left.addWidget(self.messageBrowser) vhoxLayout_left.addLayout(functionboxLayout) vhoxLayout_left.addWidget(self.messageEdit) vhoxLayout_left.setStretch(0, 4) vhoxLayout_left.setStretch(1, 1) vhoxLayout_left.setStretch(2, 2) # 在线用户列表 self.userView = QTreeWidget() self.userView.setHeaderLabels(["用户列表"]) self.userView_online_node = QTreeWidgetItem(self.userView) self.userView_online_node.setText(0, "在线用户") self.userView_all_node = QTreeWidgetItem(self.userView) self.userView_all_node.setText(0, "所有用户") self.userView.setContextMenuPolicy(Qt.CustomContextMenu) self.userView.customContextMenuRequested.connect(self.userView_menu) # 公共栏Label self.announcement_label = QLabel() self.announcement_label.setText("公告栏") # 公告栏 self.announcement_edit = QTextEdit() self.announcement_edit.setEnabled(False) # 左侧竖向布局,一整块 vhoxLayout_right = QVBoxLayout() vhoxLayout_right.addWidget(self.userView) vhoxLayout_right.addWidget(self.announcement_label) vhoxLayout_right.addWidget(self.announcement_edit) # 最大布局,横向两列 hboxLayout = QHBoxLayout(self) hboxLayout.addLayout(vhoxLayout_left) hboxLayout.addLayout(vhoxLayout_right) hboxLayout.setStretch(0, 3) hboxLayout.setStretch(1, 1) self.show() def update_admin_UI(self): self.announcement_edit.setEnabled(True) self.announcement_edit.setContextMenuPolicy(Qt.CustomContextMenu) self.announcement_edit.customContextMenuRequested.connect( lambda: handler.announcement(self.announcement_edit.toPlainText())) def userView_menu(self): item = self.userView.currentItem() menu = QMenu(self.userView) if item.parent().text(0) == '在线用户': menu.addAction('拍一拍').triggered.connect( lambda: handler.pai_yi_pai(myname, item.text(0))) elif admin: menu.addAction('删除').triggered.connect( lambda: handler.delete_user(item.text(0))) menu.exec_(QCursor.pos()) def mergeFormatDocumentOrSelection(self, format): cursor = self.messageEdit.textCursor() if not cursor.hasSelection(): cursor.select(QTextCursor.Document) cursor.mergeCharFormat(format) self.messageEdit.mergeCurrentCharFormat(format) def on_fontComboBox_currentFontChanged(self, p0): fmt = QTextCharFormat() fmt.setFont(p0) # fmt.setFontFamily(p0) self.mergeFormatDocumentOrSelection(fmt) self.messageEdit.setFocus() # 字体大小 def on_SizeComboBox_currentIndexChanged(self, p0): fmt = QTextCharFormat() p0 += 10 fmt.setFontPointSize(p0) self.mergeFormatDocumentOrSelection(fmt) self.messageEdit.setFocus() def on_boldToolBtn_clicked(self, checked): fmt = QTextCharFormat() fmt.setFontWeight(checked and QFont.Bold or QFont.Normal) self.mergeFormatDocumentOrSelection(fmt) self.messageEdit.setFocus() def on_italicToolBtn_clicked(self, checked): fmt = QTextCharFormat() fmt.setFontItalic(checked) self.mergeFormatDocumentOrSelection(fmt) self.messageEdit.setFocus() def on_underlineToolBtn_clicked(self, checked): fmt = QTextCharFormat() fmt.setFontUnderline(checked) self.mergeFormatDocumentOrSelection(fmt) self.messageEdit.setFocus() def on_colorToolBtn_clicked(self): col = QColorDialog.getColor(self.messageEdit.textColor(), self) if not col.isValid(): return fmt = QTextCharFormat() fmt.setForeground(col) self.mergeFormatDocumentOrSelection(fmt) self.messageEdit.setFocus() def on_saveToolBtn_clicked(self): print(self.messageBrowser.document().isEmpty()) if self.messageBrowser.document().isEmpty(): QMessageBox.warning(self, "警告", "聊天记录为空,无法保存!", QMessageBox.Ok) else: fileName = QFileDialog.getSaveFileName(self, "保存聊天记录", "./聊天记录", ("HTML-Files (*.html)")) if fileName[0]: if self.saveFile(fileName[0]): QMessageBox.information(self, "聊天记录保存", "保存成功!") def saveFile(self, fileName): SuffixFileName = fileName.split(".")[1] if SuffixFileName in ("html"): content = self.messageBrowser.toHtml() else: content = self.messageBrowser.toPlainText() try: with codecs.open(fileName, 'w', encoding="utf-8") as f: f.write(content) return True except IOError: QMessageBox.critical(self, "保存错误", "聊天记录保存失败!") return False def on_clearToolBtn_clicked(self): self.messageBrowser.clear() def getMessage(self): msg = self.messageEdit.toHtml() self.messageEdit.clear() self.messageEdit.setFocus() return msg def sendChatMsg(self): sendMsg(ALL_MSG, self.getMessage(), myname) self.messageEdit.clear() def showMsg(self, msg, name): time = QDateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss") if name == '拍拍': self.messageBrowser.setTextColor(Qt.darkGreen) self.messageBrowser.append("[" + name + "] " + time) self.messageBrowser.append(msg) elif name != myname: self.messageBrowser.setTextColor(Qt.blue) self.messageBrowser.append("[" + name + "] " + time) self.messageBrowser.append(msg) else: self.messageBrowser.setTextColor(Qt.red) self.messageBrowser.append("[我] " + time) self.messageBrowser.append(msg) def addUserNode(self, group, name): self.userView.expandAll() newUser = QTreeWidgetItem(group) newUser.setText(0, name) newUser.setIcon(0, QIcon('image/user.jpg')) if (name == myname): newUser.setBackground(0, QColor(255, 0, 0, 100)) if name == '拍拍': newUser.setBackground(0, QColor(0, 255, 0, 100)) def removeUserNode(self, name): n = self.userView_online_node.childCount() for i in range(n): if self.userView_online_node.child(i).text(0) == name: self.userView_online_node.removeChild( self.userView_online_node.child(i)) break def removeAllNode(self, name): n = self.userView_all_node.childCount() for i in range(n): if self.userView_all_node.child(i).text(0) == name: self.userView_all_node.removeChild( self.userView_all_node.child(i)) break def userJoin(self, name): self.messageBrowser.setTextColor(Qt.gray) self.messageBrowser.append('系统消息:' + name + '上线了') self.addUserNode(self.userView_online_node, name) def userLeft(self, name): self.messageBrowser.setTextColor(Qt.gray) self.messageBrowser.append('系统消息:' + name + '离开了') self.removeUserNode(name) def pai_yi_pai(self, name, toname): self.messageBrowser.setTextColor(Qt.gray) self.messageBrowser.append(name + ' 拍了拍 ' + toname) if toname == myname: app.alert(self, 2000) def setHandler(self, handler): self.handler = handler def handler(self, msg): global admin type = msg[0] if type == ALL_MSG: self.showMsg(msg[1], msg[2]) elif type == USR_JOIN: self.userJoin(msg[1]) elif type == USR_LEFT: self.userLeft(msg[1]) elif type == USR_LOGIN: admin = msg[2] if admin: self.update_admin_UI() elif type == ALL_ONLINE_USR: for i in msg[1]: self.userJoin(i) self.announcement_edit.setText(msg[2]) for i in msg[3]: self.addUserNode(self.userView_all_node, i) elif type == PAI_YI_PAI: self.pai_yi_pai(msg[1], msg[2]) elif type == ANNOUNCEMENT: self.announcement_edit.setText(msg[1]) elif type == DELETE_USR: self.removeUserNode(msg[1]) self.removeAllNode(msg[1])
class project: projectName = "" paratextFolder = "" audioFolderName = "" textFont = "" textSize = 0 fileType = "" bBook = False currentBook = 1 currentChapter = 1 def project(self): pass def readProject(self, currentProject): try: print("Reading project " + currentProject) refMatcher = re.compile("^CurrentReference=([^ ]+) (\\d+)$") for line in open(currentProject + '.prj'): line = line.strip() mtch = refMatcher.match(line) if mtch: self.currentBook = mtch.group(1) # bk = mtch.group(1) # for i, b in enumerate(data.data.book): # if b.equals(bk): # self.currentBook = i # break self.currentChapter = mtch.group(2) elif line.startswith("ProjectName="): self.projectName = line[len("ProjectName="):] elif line.startswith("VersionName="): self.projectName = line[len("VersionName="):] elif line.startswith("ParatextFolder="): self.paratextFolder = line[len("ParatextFolder="):] elif line.startswith("SoundFolder="): self.audioFolderName = line[len("SoundFolder="):] elif line.startswith("AudioFolder="): self.audioFolderName = line[len("AudioFolder="):] elif line.startswith("Font="): self.textFont = line[len("Font="):] elif line.startswith("FontSize="): self.textSize = int(line[len("FontSize=")]) elif line.startswith("FileType="): self.fileType = line[len("FileType="):] self.bBook = self.fileType == "Book" else: print("Unknown project option: ", line) except FileNotFoundError: print("Failed to open project file") self.writeProject(currentProject) pass except Exception as detail: print("Exception reading project file: ", detail) pass def writeProject(self, currentProject): print("Writing project file") try: fh = open(currentProject + ".prj", "w+") fh.write("CurrentReference=" + self.currentBook + " " + str(self.currentChapter) + "\n") fh.write("ProjectName=" + self.projectName + "\n") fh.write("ParatextFolder=" + self.paratextFolder + "\n") fh.write("AudioFolder=" + self.audioFolderName + "\n") fh.write("Font=" + self.textFont + "\n") fh.write("FontSize=" + str(self.textSize) + "\n") fh.write("FileType=" + self.fileType + "\n") fh.close() except Exception as detail: print("IOException writing project file: ", detail) pass # class Ui_Dialog(object): def setupUi(self, Dialog, proj, newProject): try: self.dialog = Dialog self.proj = proj Dialog.setObjectName("Dialog") Dialog.resize(400, 357) self.buttonBox = QDialogButtonBox(Dialog) self.buttonBox.setGeometry(QRect(30, 310, 341, 32)) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.groupBox = QGroupBox(Dialog) self.groupBox.setGeometry(QRect(10, 0, 381, 61)) self.groupBox.setObjectName("groupBox") self.lineEditProjectName = QLineEdit(self.groupBox) self.lineEditProjectName.setGeometry(QRect(10, 30, 361, 23)) self.lineEditProjectName.setObjectName("lineEditProjectName") self.groupBox_2 = QGroupBox(Dialog) self.groupBox_2.setGeometry(QRect(10, 60, 381, 61)) self.groupBox_2.setObjectName("groupBox_2") self.comboBoxProjectType = QComboBox(self.groupBox_2) self.comboBoxProjectType.setGeometry(QRect(10, 30, 361, 23)) self.comboBoxProjectType.setObjectName("comboBoxProjectType") self.groupBox_3 = QGroupBox(Dialog) self.groupBox_3.setGeometry(QRect(10, 120, 381, 61)) self.groupBox_3.setObjectName("groupBox_3") self.lineEditSourcePath = QLineEdit(self.groupBox_3) self.lineEditSourcePath.setGeometry(QRect(10, 30, 271, 23)) self.lineEditSourcePath.setObjectName("lineEditSourcePath") self.pushButtonBrowseSource = QPushButton(self.groupBox_3) self.pushButtonBrowseSource.setGeometry(QRect(290, 30, 80, 23)) self.pushButtonBrowseSource.setObjectName("pushButtonBrowseSource") self.groupBox_4 = QGroupBox(Dialog) self.groupBox_4.setGeometry(QRect(10, 180, 381, 61)) self.groupBox_4.setObjectName("groupBox_4") self.pushButtonBrowseAudio = QPushButton(self.groupBox_4) self.pushButtonBrowseAudio.setGeometry(QRect(290, 30, 80, 23)) self.pushButtonBrowseAudio.setObjectName("pushButtonBrowseAudio") self.lineEditAudioFilesPath = QLineEdit(self.groupBox_4) self.lineEditAudioFilesPath.setGeometry(QRect(10, 30, 271, 23)) self.lineEditAudioFilesPath.setObjectName("lineEditAudioFilesPath") self.groupBox_5 = QGroupBox(Dialog) self.groupBox_5.setGeometry(QRect(10, 240, 381, 61)) self.groupBox_5.setObjectName("groupBox_5") self.comboBoxFont = QFontComboBox(self.groupBox_5) self.comboBoxFont.setGeometry(QRect(10, 30, 271, 23)) self.comboBoxFont.setObjectName("comboBoxFont") self.lineEditFontSize = QLineEdit(self.groupBox_5) self.lineEditFontSize.setGeometry(QRect(290, 30, 81, 23)) self.lineEditFontSize.setObjectName("lineEditFontSize") # set up fields if newProject: self.projectName = "" self.paratextFolder = "c:\\My Paratext 8 Projects" self.textFont = "Times New Roman" self.textSize = 25 self.fileType = "Paratext" typeList = ("Paratext", "Book", "BART") # self.comboBoxProjectType.clear() for index, i in enumerate(typeList): self.comboBoxProjectType.addItem(i) index = self.comboBoxProjectType.findText(self.fileType, Qt.MatchFixedString) if index >= 0: self.comboBoxProjectType.setCurrentIndex(index) self.lineEditProjectName.setText(self.projectName) self.lineEditSourcePath.setText(self.paratextFolder) self.lineEditAudioFilesPath.setText(self.audioFolderName) index = self.comboBoxFont.findText(self.textFont, Qt.MatchFixedString) if index >= 0: self.comboBoxFont.setCurrentIndex(index) self.lineEditFontSize.setText(str(self.textSize)) self.retranslateUi(Dialog) self.pushButtonBrowseSource.clicked.connect(self.browse_source) self.pushButtonBrowseAudio.clicked.connect(self.browse_audio_path) self.lineEditProjectName.textChanged.connect( self.lineEditProjectName_changed) self.comboBoxProjectType.currentTextChanged.connect( self.comboBoxProjectType_changed) self.comboBoxFont.currentTextChanged.connect( self.comboBoxFont_changed) self.lineEditFontSize.textChanged.connect( self.lineEditFontSize_changed) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) QMetaObject.connectSlotsByName(Dialog) except Exception as detail: print("Exception: " + detail) def retranslateUi(self, Dialog): _translate = QCoreApplication.translate Dialog.setWindowTitle(_translate("Dialog", "Dialog")) self.groupBox.setTitle(_translate("Dialog", "Project name")) self.groupBox_2.setTitle(_translate("Dialog", "Type")) self.groupBox_3.setTitle(_translate("Dialog", "Source")) self.pushButtonBrowseSource.setText(_translate("Dialog", "Browse...")) self.groupBox_4.setTitle(_translate("Dialog", "Audio files folder")) self.pushButtonBrowseAudio.setText(_translate("Dialog", "Browse...")) self.groupBox_5.setTitle(_translate("Dialog", "Font")) def accept(self): self.writeProject(self.projectName) print("Saved project " + self.projectName) self.dialog.close() def reject(self): print("Cancel") self.dialog.close() def comboBoxProjectType_changed(self): self.fileType = self.comboBoxProjectType.currentText() # print("Changing project type to " + self.fileType) self.bBook = True if self.fileType == "Paratext": self.paratextFolder = "c:\\Paratext\\My Paratext 8 Projects\\" + self.lineEditProjectName.text( ) self.bBook = False elif self.fileType == "Book": self.paratextFolder = "" else: self.paratextFolder = "" self.lineEditSourcePath.setText(self.paratextFolder) def lineEditProjectName_changed(self): self.comboBoxProjectType_changed() self.lineEditSourcePath.setText(self.paratextFolder) self.projectName = self.lineEditProjectName.text() def comboBoxFont_changed(self): self.textFont = self.comboBoxFont.currentText() def lineEditFontSize_changed(self): self.textSize = int(self.lineEditFontSize.text()) def browse_source(self): try: my_dir = QFileDialog.getExistingDirectory(self.dialog, "Open a folder", self.paratextFolder, QFileDialog.ShowDirsOnly) if my_dir: self.paratextFolder = my_dir self.lineEditSourcePath.setText(self.paratextFolder) # except TypeError as detail: # print (detail) except Exception: print("Failed choose Paratext folder: ") # + detail) def browse_audio_path(self): try: my_dir = QFileDialog.getExistingDirectory(self.dialog, "Open a folder", self.audioFolderName, QFileDialog.ShowDirsOnly) if my_dir: self.audioFolderName = my_dir self.lineEditAudioFilesPath.setText(self.audioFolderName) # except TypeError as detail: # print (detail) except Exception: print("Failed choose audio folder: ") # + detail)