class Form(QDialog): def __init__(self, parent=None): super(Form, self).__init__(parent) self.broswer = QTextBrowser() # display self.lineedit = QLineEdit( "Type an expression and press Enter") # input self.lineedit.selectAll() # ctr + a layout = QVBoxLayout() # a frame with 'X' and '--' and '[]' layout.addWidget(self.broswer) layout.addWidget(self.lineedit) self.setLayout(layout) self.lineedit.setFocus() setting = self.broswer.document() setting.setMaximumBlockCount(5) self.lineedit.returnPressed.connect(self.updateUi) self.setWindowTitle("Calculate") def updateUi(self): try: text = str(self.lineedit.text()) self.broswer.append( "%s = <b>%s</b>" % (text, eval(text))) # when fresh the list in broswer # maybe append triggle updating ui except Exception: traceback.print_exc() self.broswer.append("<font color=red>%s is invalid</font>" % text)
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.le = QLineEdit() self.le.returnPressed.connect(self.append_text) # 키보드에 엔터를 눌렀는지 확인해주는 이벤트 # 엔터를 누르면 append_text를 받아와서 입력값 자동 저장 self.tb = QTextBrowser() #QTextBrowser() 클래스를 이용해서 텍스트 브라우저 객체 생성 self.tb.setAcceptRichText(True) # 서식 있는 텍스트(Rich text)를 사용할 수 있음 # 디폴트로 True이기 때문에 없어도 되는 부분! self.tb.setOpenExternalLinks(True) # 외부 링크로의 연결 가능 self.clear_btn = QPushButton('Clear') # 버튼을 클릭하면 self.clear_btn.pressed.connect(self.clear_text) # Clear_text 메소드 호출 vbox = QVBoxLayout() # 레이아웃 해주기 위한 vbox 객체 생성! vbox.addWidget(self.le, 0) # .addWidget() 순서 정해줄 수 있음! vbox.addWidget(self.tb, 1) vbox.addWidget(self.clear_btn, 2) self.setLayout(vbox) self.setWindowTitle('QTextBrowser') self.setGeometry(300, 300, 300, 300) self.show() def append_text(self): text = self.le.text() self.tb.append(text) self.le.clear() # 입력값 초기화 시켜주는 함수! def clear_text(self): self.tb.clear()
class Form(QDialog): def __init__(self): # 作为主窗口,parent = none,可省略不写 super().__init__() # super()方法在python3中的新写法,更简洁 # 定义元件 self.browser = QTextBrowser() self.lineedit = QLineEdit("Type an expression and press Enter") self.lineedit.selectAll() # 布局 layout = QVBoxLayout() layout.addWidget(self.browser) layout.addWidget(self.lineedit) self.setLayout(layout) self.setWindowTitle("Calculate") self.lineedit.setFocus() # 关联信号与槽 self.lineedit.returnPressed.connect(self.updataUi) # 槽函数 def updataUi(self): try: text = str(self.lineedit.text()) self.browser.append("%s = <b>%s</b>" % (text, eval(text))) except: self.browser.append("<font color=red>%s is invalid!</font>" % text)
def show_help(self): MSG = "<h3>Issues</h3> <br>" \ "Please report any issues to " + GITHUB + " <br> " \ "<br>" \ "<h3>Steps</h3> <br> " \ "<strong>Step 1:</strong> Click 'Select SBML model' and upload a valid SBML model. The file format must be xml, json, yml or mat. Wait until the application reads the input file. <br>" \ "<strong>Step 2:</strong> Once the read of the input file is done the application will show the model id, number of reactions, number of metabolites and number of genes. Below it will display the buttons with the avaible operations. <br>" \ "<strong>Step 3:</strong> Click one of the following operations: <br>" \ "<ul> " \ " <li>'Generate spreadsheet': Generates a spreadsheet file with information about the model, reactions, metabolites, genes, dead-end metabolites found, chokepoint reactions and if the models is feasible, essential reactions and essential genes data. If the model choosed is large this proccess may take a long time. Some models may cause this procedures to block the application.</li>" \ " <li>'Save model without dead-end metabolites': Removes the dead-end metabolitos of the model along with the associated reactions and produces a new model. </li>" \ " <li>'Save model updated with flux variaiblity analysis': Produces a new model with the reactions bounds updated with the values obteined running flux variability analysis on the model.</li>" \ " <li>'Save model updated with flux variaiblity analysis without dead-end metabolites': Produces a new model with the reactions bounds updated with the values obteined running flux variability analysis on the model. After updating the model with flux variaiblity analysis it removes the dead-end metabolites of the model.</li>" \ "</ul>" \ "<strong>Step 4:</strong> Click 'Start' <br>" \ "<strong>Step 5:</strong> Once the operation chosen before ends, a window will display in order to choose the destination file. If the operation was 'generate spreadsheet' the output file must be xls or ods. If the operation produces a new models the output file must be xml, json, yml or mat. <br>" \ helpDialog = QDialog(self) # Added helpDialog.setAttribute(Qt.WA_DeleteOnClose) # Added browser = QTextBrowser() browser.append(MSG) layout = QVBoxLayout() layout.addWidget(browser) helpDialog.setLayout(layout) # Added helpDialog.setWindowTitle("Test App - Help") # Added for neatness helpDialog.show() # Changed
class Window(QWidget): def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) layout = QVBoxLayout(self) self.button1 = QPushButton('已连接', self, clicked=self.doTest) self.button2 = QPushButton('未连接', self) self.retView = QTextBrowser(self) layout.addWidget(self.button1) layout.addWidget(self.button2) layout.addWidget(self.retView) def doTest(self): self.retView.append(""" # button1 clicked 是否连接: %s, %s # button2 clicked 是否连接: %s, %s """ % ( self.isSignalConnected(self.button1, 'clicked()'), self.button1.receivers(self.button1.clicked) > 0, self.isSignalConnected(self.button2, 'clicked()'), self.button2.receivers(self.button2.clicked) > 0, )) def isSignalConnected(self, obj, name): """判断信号是否连接 :param obj: 对象 :param name: 信号名,如 clicked() """ index = obj.metaObject().indexOfMethod(name) if index > -1: method = obj.metaObject().method(index) if method: return obj.isSignalConnected(method) return False
class Form(QDialog): def __init__(self, parent=None): super(Form, self).__init__(parent) self.browser = QTextBrowser() self.lineedit = QLineEdit("Type an expression and press Enter") self.lineedit.selectAll() layout = QVBoxLayout() # 垂直盒式布局 layout.addWidget(self.browser) layout.addWidget(self.lineedit) # layout = QGridLayout() #网格布局 # layout.addWidget(self.browser,0, 0) # layout.addWidget(self.lineedit,0, 0) self.setLayout(layout) self.lineedit.setFocus() self.connect(self.lineedit, SIGNAL("returnPressed()"), self.updateUi) # 信号绑定到槽 self.setWindowTitle("Calculate") def updateUi(self): try: text = unicode(self.lineedit.text()) self.browser.append("%s = <b>%s</b>" % (text, eval(text))) except: self.browser.append( "<font color=red>%s is invalid!</font>" % text)
class Form(QDialog): def __init__(self, parent=None): super(Form, self).__init__(parent) self.browser = QTextBrowser() self.lineedit = QLineEdit("Type an expression and press Enter") self.lineedit.selectAll() layout = QVBoxLayout() layout.addWidget(self.browser) layout.addWidget(self.lineedit) self.setLayout(layout) self.lineedit.setFocus() self.lineedit.returnPressed.connect(self.updateUi) #antes: #self.connect(self.lineedit, SIGNAL("returnPressed()"), self.updateUi) self.setWindowTitle("Calculate") def updateUi(self): try: text = str(self.lineedit.text()) self.browser.append("{0} = <b>{1}</b>".format(text, eval(text))) except: self.browser.append("<font color=red>{0} is invalid!</font>" .format(text))
class JSONClass(QListWidget): #QWidget def __init__(self, parent=None): super().__init__(parent) self.initUI() def initUI(self): self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) vbox = QVBoxLayout() vbox.addWidget(self.tb, 1) self.setLayout(vbox) self.setWindowTitle('QTextBrowser') self.setGeometry(300, 300, 300, 300) self.show() self.append_text() def append_text(self): # allText = ['a', 'b', 'c', 'd', 'e'] allText = FileList for i in range(0, len(allText)): text = allText[i] self.tb.append(text)
def __init__(self, title, text, image, parent=None): super(AboutDialog, self).__init__(parent) layout = QVBoxLayout() titleLayout = QHBoxLayout() name_versionLabel = QLabel(title) contentsLayout = QHBoxLayout() aboutBrowser = QTextBrowser() aboutBrowser.append(text) aboutBrowser.setOpenExternalLinks(True) creditsBrowser = QTextBrowser() creditsBrowser.append(self.contributors()) creditsBrowser.setOpenExternalLinks(True) TabWidget = QTabWidget() TabWidget.addTab(aboutBrowser, self.tr('About')) TabWidget.addTab(creditsBrowser, self.tr('Contributors')) aboutBrowser.moveCursor(QTextCursor.Start) creditsBrowser.moveCursor(QTextCursor.Start) imageLabel = QLabel() imageLabel.setPixmap(QPixmap(image)) titleLayout.addWidget(imageLabel) titleLayout.addWidget(name_versionLabel) titleLayout.addStretch() contentsLayout.addWidget(TabWidget) buttonLayout = QHBoxLayout() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) buttonLayout.addWidget(buttonBox) layout.addLayout(titleLayout) layout.addLayout(contentsLayout) layout.addLayout(buttonLayout) self.setLayout(layout) buttonBox.clicked.connect(self.accept) self.setMinimumSize(QSize(380, 400)) self.setWindowTitle(self.tr('About Meteo-qt'))
class Window(QWidget): def __init__(self, parent=None): super(Window, self).__init__(parent) model = FileListModel(self) model.setDirPath(QLibraryInfo.location(QLibraryInfo.PrefixPath)) label = QLabel("Directory") lineEdit = QLineEdit() label.setBuddy(lineEdit) view = QListView() view.setModel(model) self.logViewer = QTextBrowser() self.logViewer.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)) lineEdit.textChanged.connect(model.setDirPath) lineEdit.textChanged.connect(self.logViewer.clear) model.numberPopulated.connect(self.updateLog) layout = QGridLayout() layout.addWidget(label, 0, 0) layout.addWidget(lineEdit, 0, 1) layout.addWidget(view, 1, 0, 1, 2) layout.addWidget(self.logViewer, 2, 0, 1, 2) self.setLayout(layout) self.setWindowTitle("Fetch More Example") def updateLog(self, number): self.logViewer.append("%d items added." % number)
class Window(QWidget): # 定义一个时间信号 timerSignal = pyqtSignal(str) def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) layout = QVBoxLayout(self) layout.addWidget(QPushButton('Python调用qml中的函数', self, clicked=self.callQmlFunc)) self.resultView = QTextBrowser(self) layout.addWidget(self.resultView) self._timer = QTimer(self, timeout=self.onTimeout) self._timer.start(2000) def onTimeout(self): # 定时器发送信号通知qml self.timerSignal.emit('定时器发来:' + str(time())) def callQmlFunc(self): # 主动调用qml中的appendText函数 engine.rootObjects()[0].appendText('我是被Python调用了') @pyqtSlot(int) def onValueChanged(self, value): # qml中的自定义信号valueChanged所绑定的槽函数 self.resultView.append('拉动条值: %s' % value) @pyqtSlot(str, result=str) # 可以获取返回值 def testSlot(self, name): # 被qml调用的函数 self.resultView.append('我被主动调用: %s' % name) return str(len(name))
class Window(QWidget): def __init__(self, parent=None): super(Window, self).__init__(parent) model = FileListModel(self) model.setDirPath(QLibraryInfo.location(QLibraryInfo.PrefixPath)) label = QLabel("Directory") lineEdit = QLineEdit() label.setBuddy(lineEdit) view = QListView() view.setModel(model) self.logViewer = QTextBrowser() self.logViewer.setSizePolicy( QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)) lineEdit.textChanged.connect(model.setDirPath) lineEdit.textChanged.connect(self.logViewer.clear) model.numberPopulated.connect(self.updateLog) layout = QGridLayout() layout.addWidget(label, 0, 0) layout.addWidget(lineEdit, 0, 1) layout.addWidget(view, 1, 0, 1, 2) layout.addWidget(self.logViewer, 2, 0, 1, 2) self.setLayout(layout) self.setWindowTitle("Fetch More Example") def updateLog(self, number): self.logViewer.append("%d items added." % number)
def __init__(self, title, text, image, contributors, parent=None): super(AboutDialog, self).__init__(parent) layout = QVBoxLayout() titleLayout = QHBoxLayout() name_versionLabel = QLabel(title) contentsLayout = QHBoxLayout() aboutBrowser = QTextBrowser() aboutBrowser.append(text) aboutBrowser.setOpenExternalLinks(True) creditsBrowser = QTextBrowser() creditsBrowser.append(contributors) creditsBrowser.setOpenExternalLinks(True) TabWidget = QTabWidget() TabWidget.addTab(aboutBrowser, self.tr('About')) TabWidget.addTab(creditsBrowser, self.tr('Contributors')) aboutBrowser.moveCursor(QTextCursor.Start) creditsBrowser.moveCursor(QTextCursor.Start) imageLabel = QLabel() imageLabel.setPixmap(QPixmap(image)) titleLayout.addWidget(imageLabel) titleLayout.addWidget(name_versionLabel) titleLayout.addStretch() contentsLayout.addWidget(TabWidget) buttonLayout = QHBoxLayout() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) buttonLayout.addWidget(buttonBox) layout.addLayout(titleLayout) layout.addLayout(contentsLayout) layout.addLayout(buttonLayout) self.setLayout(layout) buttonBox.clicked.connect(self.accept) self.setMinimumSize(QSize(380, 400)) self.setWindowTitle(self.tr('About Onkyo QT'))
class Form(QDialog): # 表单类的构造函数 def __init__(self, parent=None): # 用super方法进行初始化 super(Form, self).__init__(parent) # QTextBrowser()为只读文本框,不能对内容进行操作 self.browser = QTextBrowser() # QLineEdit()单行文本框。可给定初始化文本 self.lineedit = QLineEdit("Type an expression and <Enter>") # 并将文本全部选中 self.lineedit.selectAll() # 调整布局 layout = QVBoxLayout() layout.addWidget(self.browser) layout.addWidget(self.lineedit) # 使布局管理器获得表单部件和该表单的所有权 self.setLayout(layout) # 确定光标起始位置 self.lineedit.setFocus() # returnPressed:当用户在文本框内输入回车键的时候发送信号 # connect():当特定对象发射特定信号时调用指定函数 self.lineedit.returnPressed.connect(self.updateUi) self.setWindowTitle("Calculate") def updateUi(self): try: text = self.lineedit.text() self.browser.append("{0} = <b>{1}</b>".format(text, eval(text))) except: # 如果错误就将错误输出到QTextBrowser self.browser.append( "<font color=red>{0} is invalid!</font>".format(text))
class App(QWidget): def __init__(self, room): super().__init__() vbox = QVBoxLayout() self.text_browser = QTextBrowser() vbox.addWidget(self.text_browser) self.text_entry = Entry(room) self.text_entry.setFocus() vbox.addWidget(self.text_entry) self.setLayout(vbox) self.messages_future = None self._run(room) def closeEvent(self, e): if self.messages_future: self.messages_future.cancel() super().closeEvent(e) def _run(self, room): @coroutine def logger(): while True: message = (yield) self.text_browser.append(message['text']) self.messages_future = asyncio.ensure_future( room.get_messages(logger()))
def showPointsCharacteristics(characteristics: dict, textBrowser: QTextBrowser): textBrowser.clear() textBrowser.append( "АНАЛІЗ ДВОВИМІРНОГО ОБ'ЄКТУ\n \t\t\t|---Точкові статистичні оцінки---|\n" ) textBrowser.append(getPointCharacteristicsTable(characteristics))
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.le = QLineEdit() self.le.returnPressed.connect(self.append_text) self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) self.clear_btn = QPushButton('Clear') self.clear_btn.pressed.connect(self.clear_text) vbox = QVBoxLayout() vbox.addWidget(self.le, 0) vbox.addWidget(self.tb, 1) vbox.addWidget(self.clear_btn, 2) self.setLayout(vbox) self.setWindowTitle('QTextBrowser') self.setGeometry(300, 300, 300, 300) self.show() def append_text(self): text = self.le.text() self.tb.append(text) self.le.clear() def clear_text(self): self.tb.clear()
class Example(QDialog): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.lineedit = QLineEdit() okButton = QPushButton('OK') hb = QHBoxLayout() hb.addStretch(1) hb.addWidget(self.lineedit) hb.addWidget(okButton) self.textbrowser = QTextBrowser() vb = QVBoxLayout() vb.addStretch(1) vb.addWidget(self.textbrowser) vb.addLayout(hb) self.setLayout(vb) okButton.clicked.connect(self.updateUI) self.setWindowTitle("Execute") self.setGeometry(300, 300, 300, 300) def updateUI(self): try: text = self.lineedit.text() self.textbrowser.append("%s = <b>%s</b>" % (text, eval(text))) except: self.textbrowser.append("error!")
class LogView(QWidget): def __init__(self): super().__init__() self.browser = QTextBrowser() self.browser.setPlaceholderText('程序运行日志') self.clear_btn = QPushButton('清空') self.clear_btn.clicked.connect(lambda: self.browser.setText('')) self.v_layout = QVBoxLayout() self.v_layout.addWidget(self.browser) self.v_layout.addWidget(self.clear_btn) self.resize(600, 425) self.setLayout(self.v_layout) self.center() self.setWindowTitle(Const.project_name) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) def info(self, text: str): self.browser.append(text) def center(self): """ 居中窗口 """ qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft())
def __init__(self, parent): QWidget.__init__(self) self.ctrl = QApplication.instance().ctrl self.parent = parent self.setWindowTitle("About") hbox = QHBoxLayout() pic = QLabel(self) pix = QPixmap( os.path.join(self.ctrl.application_home, 'conf/img/logo_h.png')) pic.setPixmap(pix) hbox.addWidget(pic) vbox = QVBoxLayout() lbl_title = QLabel("Metadata Publishing Tool", self) lbl_title.setMinimumWidth(400) font = QFont() font.setPointSize(20) font.setBold(True) lbl_title.setFont(font) lbl_title.setContentsMargins(2, 5, 5, 7) lbl_title.setStyleSheet(Style.h2()) vbox.addWidget(lbl_title) #vbox.addSpacing(20) vbox.addStretch(1) grid = QGridLayout() grid.setContentsMargins(0, 0, 0, 0) # left, top, right, bottom grid.setVerticalSpacing(2) grid.setHorizontalSpacing(2) grid.addWidget(QLabel("Version: "), 1, 1) grid.addWidget(QLabel(version.__version__), 1, 2) grid.addWidget(QLabel("Release: "), 2, 1) grid.addWidget(QLabel(version.__release_date__), 2, 2) hbox_grid = QHBoxLayout() hbox_grid.addLayout(grid) hbox_grid.addStretch(1) vbox.addLayout(hbox_grid) vbox.addSpacing(10) txt = QTextBrowser() txt.setMinimumHeight(250) txt.setOpenExternalLinks(True) txt.setOpenLinks(False) txt.anchorClicked.connect(self.on_anchor_clicked) txt.append(version.__about__) vbox.addWidget(txt) hbox.addLayout(vbox) hbox.addStretch(1) self.setLayout(hbox) self.move(200, 200) self.setWindowFlags((self.windowFlags() | Qt.CustomizeWindowHint) & ~Qt.WindowMaximizeButtonHint & ~Qt.WindowMinimizeButtonHint) self.show()
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.le = QLineEdit() self.le.setPlaceholderText('기본 값 유윈스 학사공') self.le.returnPressed.connect(self.get_url_subject) self.btn = QPushButton('Start') self.btn.clicked.connect(self.get_url_subject) self.lbl = QLabel('과를 입력하세요.') self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) grid = QGridLayout() grid.addWidget(self.le, 0, 0, 1, 3) grid.addWidget(self.btn, 0, 3, 1, 1) grid.addWidget(self.lbl, 1, 0, 1, 4) grid.addWidget(self.tb, 2, 0, 1, 4) self.setLayout(grid) self.setWindowTitle('Web Crawler') self.setGeometry(100, 100, 450, 650) self.show() def get_url_subject(self): urls = [] subjects = [] major = self.le.text() if not major: self.lbl.setText('학사 공지사항입니다.') self.tb.clear() req = requests.get( 'https://uwins.ulsan.ac.kr/JBGJ/B/MIB01S.aspx?MenuID=MIB01S!1') html = req.text soup = BeautifulSoup(html, 'html.parser') id_links = soup.select('td:nth-child(1)') subject_links = soup.select('td.textWrap.Left') for id_link in id_links: id = id_link.text.strip() url = 'https://uwins.ulsan.ac.kr/JBGJ/B/MIB02S.aspx?MenuID=MIB01S!1&board_gb=A38002&seq=' + id + '&Grade=3¤t_page=1' urls.append(url) for subject_link in subject_links: subject = subject_link.text.strip() subjects.append(subject) for i in range(10): self.tb.append( str(i + 1) + '. ' + subjects[i] + ' (' + '<a href="' + urls[i] + '">링크</a>' + ')')
class Window(QWidget): KeyIds = {} def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) layout = QVBoxLayout(self) self.logView = QTextBrowser(self) self.logView.append("点击右上角关闭按钮会隐藏窗口,通过热键Alt+S来显示") self.logView.append("等待热键中") layout.addWidget(QPushButton("退出整个程序", self, clicked=self.onQuit)) layout.addWidget(self.logView) def unregisterHotKey(self, kid): ctypes.windll.user32.UnregisterHotKey(ctypes.c_int(self.winId()), kid) def registerHotKey(self, kid, modifier, key): key = str(key).upper() _modifier = Modifier.get(modifier, None) if not _modifier: return QMessageBox.critical(self, "错误", "modifier key {0}未找到".format(modifier)) success = ctypes.windll.user32.RegisterHotKey( ctypes.c_int(self.winId()), kid, _modifier, ord(key)) if success: self.KeyIds[kid] = modifier + "+" + key self.logView.append("热键:{0}+{1}注册{2}".format(modifier, key, "成功")) else: self.logView.append("热键:{0}+{1}注册{2}".format(modifier, key, "失败")) def onQuit(self): # 退出程序 for kid in self.KeyIds: self.unregisterHotKey(kid) QApplication.instance().quit() def closeEvent(self, event): # 忽略关闭窗口,直接隐藏 self.hide() return event.ignore() # 能监听热键,但是有个问题就是其它程序无法接受到事件 # 比如Ctrl+S,在记事本里随便输入内容按下Ctrl+S发现无法保存 def nativeEvent(self, eventType, message): if eventType == "windows_generic_MSG" or eventType == "windows_dispatcher_MSG": msg = ctypes.wintypes.MSG.from_address(message.__int__()) # 这段代码无法运行 # if ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0, # 0) != 0: if msg.message == WM_HOTKEY: if msg.wParam == 1: # Alt+S self.show() self.logView.append("id:{0}, {1} at time:{2}".format( msg.wParam, self.KeyIds.get(msg.wParam, None), datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) return True, 0 return super(Window, self).nativeEvent(eventType, message)
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.le = QLineEdit() self.le.setPlaceholderText('기본 값 유윈스 학사공') self.le.returnPressed.connect(self.ulsan_urls_subjects) self.btn = QPushButton('Start') self.btn.clicked.connect(self.ulsan_urls_subjects) self.lbl = QLabel('과를 입력하세요.') self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) grid = QGridLayout() grid.addWidget(self.le, 0, 0, 1, 3) grid.addWidget(self.btn, 0, 3, 1, 1) grid.addWidget(self.lbl, 1, 0, 1, 4) grid.addWidget(self.tb, 2, 0, 1, 4) self.setLayout(grid) self.setWindowTitle('Web Crawler') self.setGeometry(100, 100, 450, 650) self.show() def ulsan_urls_subjects(self): ulsan_urls = [] ulsan_subjects = [] ulsan_ major = self.le.text() if not major: self.lbl.setText('울산대 홈페이지 공지사항입니다.') self.tb.clear() req = requests.get('http://www.ulsan.ac.kr/unews/news/notice.aspx?o=L') html = req.text soup = BeautifulSoup(html, 'html.parser') id_links = soup.select('tr > td.no') subject_links = soup.select('tr > td.title') for id_link in id_links: id = id_link.text.strip() url = 'http://www.ulsan.ac.kr/unews/news/notice.aspx?o=R&a_no='+str(int(id)+2468) urls.append(url) for subject_link in subject_links: subject = subject_link.text.strip() subjects.append(subject) for i in range(10): self.tb.append(str(i + 1) + '. ' + subjects[i] + ' (' + '<a href="' + urls[i] + '">링크</a>' + ')')
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.le = QLineEdit() self.le.returnPressed.connect(self.append_text) self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) self.clear_btn = QPushButton('Clear') self.clear_btn.pressed.connect(self.clear_text) self.lbl1 = QLabel('Enter your sentence:') self.te = QTextEdit() self.te.setAcceptRichText(False) self.lbl2 = QLabel('The number of words is 0') self.te.textChanged.connect(self.text_changed) layout = QHBoxLayout() vbox1 = QVBoxLayout() vbox1.addWidget(self.lbl1) vbox1.addWidget(self.te) vbox1.addWidget(self.lbl2) vbox1.addStretch() vbox = QVBoxLayout() vbox.addWidget(self.le, 0) vbox.addWidget(self.tb, 1) vbox.addWidget(self.clear_btn, 2) layout.addLayout(vbox) layout.addLayout(vbox1) self.setLayout(layout) self.setWindowTitle('으에에ㅔ') self.setGeometry(300, 300, 700, 800) self.show() def append_text(self): text = self.le.text() self.tb.append(text) self.le.clear() def clear_text(self): self.tb.clear() def text_changed(self): text = self.te.toPlainText() self.lbl2.setText('The number of words is ' + str(len(text.split())))
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): # self.le = QLineEdit() # self.le.returnPressed.connect(self.append_text) self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) # self.clear_btn = QPushButton('Clear') # self.clear_btn.pressed.connect(self.clear_text) vbox = QVBoxLayout() # vbox.addWidget(self.le, 0) vbox.addWidget(self.tb, 1) # vbox.addWidget(self.clear_btn, 2) self.setLayout(vbox) self.setWindowTitle('QTextBrowser') self.setGeometry(300, 300, 300, 300) self.show() self.append_text() def append_text(self): allText = ['a', 'b', 'c', 'd', 'e'] # text = self.le.text() for i in range(0, len(allText)): text = allText[i] # self.i = self.i + 1 self.tb.append(text) # self.le.clear() # def clear_text(self): # # self.tb.clear() # if __name__ == '__main__': # # app = QApplication(sys.argv) # ex = MyApp() # sys.exit(app.exec_())
class QTextEditLogger(logging.Handler): def __init__(self, parent): super().__init__() self.widget = QTextBrowser(parent) def emit(self, record): msg = self.format(record) self.widget.append(msg) with open('log.log', 'a') as f: f.write(msg+"\n") f.close()
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.le = QLineEdit() self.le.setPlaceholderText('yymmdd') self.le.returnPressed.connect(self.crawl_news) self.btn = QPushButton('Start') self.btn.clicked.connect(self.crawl_news) self.lbl = QLabel('날짜를 입력하세요.') self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) grid = QGridLayout() grid.addWidget(self.le, 0, 0, 1, 3) grid.addWidget(self.btn, 0, 3, 1, 1) grid.addWidget(self.lbl, 1, 0, 1, 4) grid.addWidget(self.tb, 2, 0, 1, 4) self.setLayout(grid) self.setWindowTitle('Web Crawler') self.setGeometry(100, 100, 450, 650) self.show() def crawl_news(self): date = self.le.text() if date: self.lbl.setText('[20' + str(date) + '] 많이 본 뉴스입니다.') self.tb.clear() url_news = 'https://news.naver.com' url = url_news + '/main/ranking/popularDay.nhn?rankingType=popular_day&date=20' + date r = requests.get(url) html = r.content soup = BeautifulSoup(html, 'html.parser') titles_html = soup.select( '.ranking_section > ol > li > dl > dt > a') for i in range(len(titles_html)): title = titles_html[i].text link = url_news + titles_html[i].get('href') self.tb.append( str(i + 1) + '. ' + title + ' (' + '<a href="' + link + '">링크</a>' + ')')
def set_type_combo(self): txt = QTextBrowser(self) txt.append('请选择烟花类型:') txt.resize(230, 30) txt.move(10, 0) self.type_combo = QComboBox(self, minimumWidth=100) self.type_combo.addItem('球状烟花', FireworkType.Normal) self.type_combo.addItem('两次爆炸', FireworkType.MultiExplosion) self.type_combo.addItem('两个球状混合', FireworkType.DualMixture) self.type_combo.setCurrentIndex(-1) self.type_combo.resize(self.type_combo.sizeHint()) self.type_combo.move(110, 5)
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.le = QLineEdit() self.le.returnPressed.connect(self.append_text) # 줄편집기 하나를 만들었습니다. # # Enter키를 누르면 append_text 메서드가 호출됩니다. self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) # QTextBrowser() 클래스를 이용해서 텍스트 브라우저를 하나 만들었습니다. # # setAcceptRichText()를 True로 설정해주면, 서식 있는 텍스트 # (Rich text)를 사용할 수 있습니다. # # 디폴트로 True이기 때문에 없어도 되는 부분입니다. # # setOpenExternalLinks()를 True로 설정해주면, 외부 링크로의 연결이 가능합니다. self.clear_btn = QPushButton('Clear') self.clear_btn.pressed.connect(self.clear_text) # clear_btn을 클릭하면, clear_text 메서드가 호출됩니다. vbox = QVBoxLayout() vbox.addWidget(self.le, 0) vbox.addWidget(self.tb, 1) vbox.addWidget(self.clear_btn, 2) self.setLayout(vbox) self.setWindowTitle('QTextBrowser') self.setGeometry(300, 300, 300, 300) self.show() def append_text(self): text = self.le.text() self.tb.append(text) self.le.clear() # append_text 메서드는 줄편집기에 작성된 텍스트 # (self.le.text())를 텍스트 브라우저 (self.tb)에 append 해주는 기능을 합니다. # # 텍스트가 텍스트 브라우저에 추가되면, clear 메서드를 이용해서 줄편집기에 있던 # 텍스트는 없애줍니다. def clear_text(self): self.tb.clear()
class DebugInfo(QDockWidget): def __init__(self, parent=None): super(DebugInfo, self).__init__() self.head_info = None self.setWindowTitle('日志') self.setFeatures(QDockWidget.NoDockWidgetFeatures | QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.dock_widget_contents = QWidget() self.setWidget(self.dock_widget_contents) self.info_text_browser = QTextBrowser(self.dock_widget_contents) self.info_text_browser.setReadOnly(True) self.horizontal_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.clear_button = QPushButton("清除记录", self.dock_widget_contents) self.hLayout = QHBoxLayout() self.hLayout.addItem(self.horizontal_spacer) self.hLayout.addWidget(self.clear_button) self.vLayout = QVBoxLayout(self.dock_widget_contents) self.vLayout.setSpacing(4) self.vLayout.setContentsMargins(4, 4, 4, 4) self.vLayout.addWidget(self.info_text_browser) self.vLayout.addLayout(self.hLayout) self.clear_button.clicked.connect(self.clear) # self.dock_widget_contents.setMinimumWidth(300) def set_head_info(self, head_info): self.head_info = head_info self.clear() def set_text_browser(self, text_info): pass def clear(self): self.info_text_browser.clear() if self.head_info is not None: self.info_text_browser.append(self.head_info) h = self.height() w = self.width() self.resize(w, 10) self.resize(w, h)
class MyApp(QWidget): def __init__(self): super().__init__() self.icon = dir_icon + 'icon_qt.png' self.title = 'Ex5.19_QTextBrowser' self.posXY = (600, 45) self.windowSize = (300, 300) self.initUI() self.showBasic() def initUI(self): lb1 = QLabel('TEXT HISTORY :') lb2 = QLabel('TYPE & ENTER to Store ABOVE!') self.le = QLineEdit() self.le.returnPressed.connect(self.append_text) self.tb = QTextBrowser() self.tb.setAcceptRichText(True) self.tb.setOpenExternalLinks(True) clear_btn = QPushButton('Clear') clear_btn.pressed.connect(self.clear_text) vbox = QVBoxLayout() vbox.addWidget(lb1) vbox.addWidget(self.tb, 1) vbox.addWidget(lb2) vbox.addWidget(self.le, 0) vbox.addWidget(clear_btn, 2) self.setLayout(vbox) def showBasic(self): """Basci Attribution & Geometry display""" self.setWindowIcon(QIcon(self.icon)) self.setWindowTitle(self.title) self.setGeometry(*self.posXY, *self.windowSize) self.show() def append_text(self): """CallBack() When le.returnPressed.connect""" text = self.le.text() self.tb.append(text) self.le.clear() def clear_text(self): """CallBack() When clear_btn.pressed.connect""" self.tb.clear()
class SummaryWidget(QWidget): def __init__(self, parent=None): super().__init__() self.parent = parent self.setWindowTitle(self.tr("Installation Information")) self.setLayout(QVBoxLayout()) label1 = QLabel() label1.setText(self.tr("<h3>Take a look at the summary of your choices for the installation.</h3>")) self.layout().addWidget(label1) label2 = QLabel() label2.setText(self.tr("<h1>System Location</h1>")) self.layout().addWidget(label2) self.textbrowser1 = QTextBrowser() self.layout().addWidget(self.textbrowser1) label3 = QLabel() label3.setText(self.tr("<h1>Keyboard Layout</h1>")) self.layout().addWidget(label3) self.textbrowser2 = QTextBrowser() self.layout().addWidget(self.textbrowser2) label4 = QLabel() label4.setText(self.tr("<h1>Disk Partition</h1>")) self.layout().addWidget(label4) self.textbrowser3 = QTextBrowser() self.layout().addWidget(self.textbrowser3) def showEvent(self, event): self.textbrowser1.setText(self.tr("System time will be set to {}.\nSystem language will be set to {}.") .format(self.parent.lilii_settings["timezone"], self.parent.lilii_settings["lang"])) variant = None if self.parent.lilii_settings["keyboard_variant"] != None: variant = self.parent.lilii_settings["keyboard_variant"][-1] else: variant = "Default" self.textbrowser2.setText(self.tr("Keyboard model is choosen as {}.\nKeyboard kind is choosen as {}/{}.") .format(self.parent.lilii_settings["keyboard_model"][-1], self.parent.lilii_settings["keyboard_layout"][-1], variant)) self.textbrowser3.clear() if self.parent.lilii_settings["/"]: self.textbrowser3.append(self.tr("Root directory is {}.").format(self.parent.lilii_settings["/"])) if self.parent.lilii_settings["/home"]: self.textbrowser3.append(self.tr("Home directory is {}.").format(self.parent.lilii_settings["/home"])) if is_efi() and self.parent.lilii_settings["/boot/efi"]: self.textbrowser3.append(self.tr("Bootloader installation directory is {}.").format(self.parent.lilii_settings["/boot/efi"])) else: self.textbrowser3.append(self.tr("Bootloader installation disk: {}").format(self.parent.lilii_settings["bootloader"]))
class ContactWindow(QWidget): def __init__(self): super().__init__() self.initUI() self.getContactText() def initUI(self): self.textbox_contact_1 = QTextBrowser() layout = QHBoxLayout() layout.addWidget(self.textbox_contact_1) self.setLayout(layout) def getContactText(self): f = open("contact.txt", mode="r", encoding="utf-8") for line in f: self.textbox_contact_1.append(line)
class Form(QDialog): def __init__(self,parent=None): super(Form,self).__init__(parent) self.browser = QTextBrowser() self.browser.setFont(QFont("Consolas",12,QFont.StyleItalic)) self.lineedit = QLineEdit('Type an express and press Enter') self.lineedit.selectAll() layout = QVBoxLayout() layout.addWidget(self.browser) layout.addWidget(self.lineedit) self.setLayout(layout) self.lineedit.setFocus() # self.connect(self.lineedit,SIGNAL('returnPressed()'),self.updateUi) self.lineedit.returnPressed.connect(self.updateUi) self.setWindowTitle('Calculate') def updateUi(self): try: text = self.lineedit.text() self.browser.append('%s = %s' % (text, eval(text))) except: self.browser.append('%s is invalid!' % text)
class AboutDialog(QDialog): def __init__(self, title="Test", message="Test Text"): super(AboutDialog, self).__init__() self.title = title self.message = message self.initUI() def initUI(self): """ initUI() """ vbox = QVBoxLayout(self) grid1 = QGridLayout() grid1.setSpacing(10) self.text = QTextBrowser() self.text.setReadOnly(True) self.text.setOpenExternalLinks(True) self.text.append(self.message) self.text.moveCursor(QTextCursor.Start) self.text.ensureCursorVisible() vbox.addWidget(self.text) self.setLayout(vbox) self.setMinimumSize(550, 450) self.resize(550, 600) self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) self.setWindowTitle(self.title) iconWT = QIcon() iconWT.addPixmap(QPixmap(":images/DXF2GCODE-001.ico"), QIcon.Normal, QIcon.Off) self.setWindowIcon(QIcon(iconWT)) self.exec_()
class Dialog(QDialog): def __init__(self, parent=None): super(Dialog, self).__init__(parent) self._info = None self._text = '' self._convertedtext = '' self._encoding = None self.mainwindow = parent self.fromVersionLabel = QLabel() self.fromVersion = QLineEdit() self.reason = QLabel() self.toVersionLabel = QLabel() self.toVersion = QLineEdit() self.lilyChooser = lilychooser.LilyChooser() self.messages = QTextBrowser() self.diff = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap) self.uni_diff = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap) self.copyCheck = QCheckBox(checked= QSettings().value('convert_ly/copy_messages', True, bool)) self.tabw = QTabWidget() self.tabw.addTab(self.messages, '') self.tabw.addTab(self.diff, '') self.tabw.addTab(self.uni_diff, '') self.buttons = QDialogButtonBox( QDialogButtonBox.Reset | QDialogButtonBox.Save | QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttons.button(QDialogButtonBox.Ok).clicked .connect(self.accept) self.buttons.rejected.connect(self.reject) self.buttons.button(QDialogButtonBox.Reset).clicked.connect(self.run) self.buttons.button(QDialogButtonBox.Save).clicked.connect(self.saveFile) layout = QVBoxLayout() self.setLayout(layout) grid = QGridLayout() grid.addWidget(self.fromVersionLabel, 0, 0) grid.addWidget(self.fromVersion, 0, 1) grid.addWidget(self.reason, 0, 2, 1, 3) grid.addWidget(self.toVersionLabel, 1, 0) grid.addWidget(self.toVersion, 1, 1) grid.addWidget(self.lilyChooser, 1, 3, 1, 2) layout.addLayout(grid) layout.addWidget(self.tabw) layout.addWidget(self.copyCheck) layout.addWidget(widgets.Separator()) layout.addWidget(self.buttons) app.translateUI(self) qutil.saveDialogSize(self, 'convert_ly/dialog/size', QSize(600, 300)) app.settingsChanged.connect(self.readSettings) self.readSettings() self.finished.connect(self.saveCopyCheckSetting) self.lilyChooser.currentIndexChanged.connect(self.slotLilyPondVersionChanged) self.slotLilyPondVersionChanged() def translateUI(self): self.fromVersionLabel.setText(_("From version:")) self.toVersionLabel.setText(_("To version:")) self.copyCheck.setText(_("Save convert-ly messages in document")) self.copyCheck.setToolTip(_( "If checked, the messages of convert-ly are appended as a " "comment to the end of the document.")) self.tabw.setTabText(0, _("&Messages")) self.tabw.setTabText(1, _("&Changes")) self.tabw.setTabText(2, _("&Diff")) self.buttons.button(QDialogButtonBox.Reset).setText(_("Run Again")) self.buttons.button(QDialogButtonBox.Save).setText(_("Save as file")) self.setCaption() def saveCopyCheckSetting(self): QSettings().setValue('convert_ly/copy_messages', self.copyCheck.isChecked()) def readSettings(self): font = textformats.formatData('editor').font self.diff.setFont(font) diffFont = QFont("Monospace") diffFont.setStyleHint(QFont.TypeWriter) self.uni_diff.setFont(diffFont) def slotLilyPondVersionChanged(self): self.setLilyPondInfo(self.lilyChooser.lilyPondInfo()) def setCaption(self): version = self._info and self._info.versionString() or _("<unknown>") title = _("Convert-ly from LilyPond {version}").format(version=version) self.setWindowTitle(app.caption(title)) def setLilyPondInfo(self, info): self._info = info self.setCaption() self.toVersion.setText(info.versionString()) self.setConvertedText() self.setDiffText() self.messages.clear() def setConvertedText(self, text=''): self._convertedtext = text self.buttons.button(QDialogButtonBox.Ok).setEnabled(bool(text)) if text: self.diff.setHtml(htmldiff.htmldiff( self._text, text, _("Current Document"), _("Converted Document"), wrapcolumn=100)) else: self.diff.clear() def setDiffText(self, text=''): if text: from_filename = "current" # TODO: maybe use real filename here to_filename = "converted" # but difflib can choke on non-ascii characters, # see https://github.com/wbsoft/frescobaldi/issues/674 difflist = list(difflib.unified_diff( self._text.split('\n'), text.split('\n'), from_filename, to_filename)) diffHLstr = self.diffHighl(difflist) self.uni_diff.setHtml(diffHLstr) else: self.uni_diff.clear() def convertedText(self): return self._convertedtext or '' def setDocument(self, doc): v = documentinfo.docinfo(doc).version_string() if v: self.fromVersion.setText(v) self.reason.setText(_("(set in document)")) else: self.reason.clear() self._text = doc.toPlainText() self._encoding = doc.encoding() or 'UTF-8' self.setConvertedText() self.setDiffText() def run(self): """Runs convert-ly (again).""" fromVersion = self.fromVersion.text() toVersion = self.toVersion.text() if not fromVersion or not toVersion: self.messages.setPlainText(_( "Both 'from' and 'to' versions need to be set.")) return info = self._info command = info.toolcommand(info.ly_tool('convert-ly')) command += ['-f', fromVersion, '-t', toVersion, '-'] # if the user wants english messages, do it also here: LANGUAGE=C env = None if os.name == "nt": # Python 2.7 subprocess on Windows chokes on unicode in env env = util.bytes_environ() else: env = dict(os.environ) if sys.platform.startswith('darwin'): try: del env['PYTHONHOME'] except KeyError: pass try: del env['PYTHONPATH'] except KeyError: pass if QSettings().value("lilypond_settings/no_translation", False, bool): if os.name == "nt": # Python 2.7 subprocess on Windows chokes on unicode in env env[b'LANGUAGE'] = b'C' else: env['LANGUAGE'] = 'C' with qutil.busyCursor(): try: proc = subprocess.Popen(command, env = env, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) out, err = proc.communicate(util.platform_newlines(self._text).encode(self._encoding)) except OSError as e: self.messages.setPlainText(_( "Could not start {convert_ly}:\n\n" "{message}\n").format(convert_ly = command[0], message = e)) return out = util.universal_newlines(out.decode('UTF-8')) err = util.universal_newlines(err.decode('UTF-8')) self.messages.setPlainText(err) self.setConvertedText(out) self.setDiffText(out) if not out or self._convertedtext == self._text: self.messages.append('\n' + _("The document has not been changed.")) def saveFile(self): """Save content in tab as file""" tabdata = self.getTabData(self.tabw.currentIndex()) doc = self.mainwindow.currentDocument() orgname = doc.url().toLocalFile() filename = os.path.splitext(orgname)[0] + '['+tabdata.filename+']'+'.'+tabdata.ext caption = app.caption(_("dialog title", "Save File")) filetypes = '{0} (*.txt);;{1} (*.htm);;{2} (*)'.format(_("Text Files"), _("HTML Files"), _("All Files")) filename = QFileDialog.getSaveFileName(self.mainwindow, caption, filename, filetypes)[0] if not filename: return False # cancelled with open(filename, 'wb') as f: f.write(tabdata.text.encode('utf-8')) def getTabData(self, index): """Get content of current tab from current index""" if index == 0: return FileInfo('message', 'txt', self.messages.toPlainText()) elif index == 1: return FileInfo('html-diff', 'html', self.diff.toHtml()) elif index == 2: return FileInfo('uni-diff', 'diff', self.uni_diff.toPlainText()) def diffHighl(self, difflist): """Return highlighted version of input.""" result = [] for l in difflist: if l.startswith('-'): s = '<span style="color: red; white-space: pre-wrap;">' elif l.startswith('+'): s = '<span style="color: green; white-space: pre-wrap;">' else: s = '<span style="white-space: pre-wrap;">' h = l.replace('&', '&').replace('<', '<').replace('>', '>') result.append(s + h + '</span>') return '<br>'.join(result)
def onAbout(self, widget): dialog = QDialog(self) aboutText = self.tr("""<p>A simple applet for enable/disable webcams.</p> <p>Website: <a href="https://github.com/abbarrasa/openbox"> https://github.com/abbarrasa/openbox</a></p> <p>Based in <a href="https://extensions.gnome.org/extension/1477/webcam-manager/">Webcam Manager</a>.</p> <p>If you want to report a dysfunction or a suggestion, feel free to open an issue in <a href="https://github.com/abbarrasa/openbox/issues"> github</a>.""") creditsText = self.tr("""(c) 2018 Alberto Buitrago <%s>""") % base64.b64decode('YWJiYXJyYXNhQGdtYWlsLmNvbQ==').decode('utf-8') licenseText = self.tr("""<p>This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</p> <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.</p> <p>You should have received a copy of the GNU General Public License along with this program. If not, see <a href="https://www.gnu.org/licenses/gpl-3.0.html"> GNU General Public License version 3</a>.</p>""") layout = QVBoxLayout() titleLayout = QHBoxLayout() titleLabel = QLabel('<font size="4"><b>{0} {1}</b></font>'.format('Webcam Manager', VERSION)) contentsLayout = QHBoxLayout() aboutBrowser = QTextBrowser() aboutBrowser.append(aboutText) aboutBrowser.setOpenExternalLinks(True) creditsBrowser = QTextBrowser() creditsBrowser.append(creditsText) creditsBrowser.setOpenExternalLinks(True) licenseBrowser = QTextBrowser() licenseBrowser.append(licenseText) licenseBrowser.setOpenExternalLinks(True) TabWidget = QTabWidget() TabWidget.addTab(aboutBrowser, self.tr('About')) TabWidget.addTab(creditsBrowser, self.tr('Contributors')) TabWidget.addTab(licenseBrowser, self.tr('License')) aboutBrowser.moveCursor(QTextCursor.Start) creditsBrowser.moveCursor(QTextCursor.Start) licenseBrowser.moveCursor(QTextCursor.Start) icon = QIcon.fromTheme('camera-web') pixmap = icon.pixmap(QSize(64, 64)) imageLabel = QLabel() imageLabel.setPixmap(pixmap) titleLayout.addWidget(imageLabel) titleLayout.addWidget(titleLabel) titleLayout.addStretch() contentsLayout.addWidget(TabWidget) buttonLayout = QHBoxLayout() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok) buttonLayout.addWidget(buttonBox) layout.addLayout(titleLayout) layout.addLayout(contentsLayout) layout.addLayout(buttonLayout) buttonBox.clicked.connect(dialog.accept) dialog.setLayout(layout) dialog.setMinimumSize(QSize(480, 400)) dialog.setWindowTitle(self.tr('About Webcam Manager')) dialog.setWindowIcon(QIcon.fromTheme('help-about')) dialog.show()
class Chat(QMainWindow): def __init__(self): super(Chat, self).__init__() self.setWindowTitle('chat') self.createActions() self.createQWidget() self.createAboutQWidget() def about(self): self.bar.showMessage('about') self.aboutArea.show() def logout(self): self.outputArea.clear() self.loginArea.show() self.hide() def set_thing(self): self.bar.showMessage('set') def createActions(self): aboutAct = QAction("&about", self) aboutAct.triggered.connect(self.about) setAct = QAction("&set", self) setAct.triggered.connect(self.set_thing) logoutAct = QAction("&logout", self) logoutAct.triggered.connect(self.logout) self.bar = self.statusBar() self.bar.showMessage('hello') self.aboutmenu = self.menuBar() self.aboutmenu.addMenu('&about').addAction(aboutAct) self.aboutmenu.addMenu('&set').addAction(setAct) self.aboutmenu.addMenu('&logout').addAction(logoutAct) # this is ubuntu special thing, so you should input this to stop origin ubuntu menubar self.aboutmenu.setNativeMenuBar(False) def createQWidget(self): self.talkArea = QWidget() self.setCentralWidget(self.talkArea) #let QWidget in QMainWindwos #qtextbrowser and qpushbutton and qlineedit of self is self.talkArea self.outputArea = QTextBrowser(self.talkArea) self.pushButton = QPushButton("push", self.talkArea) self.inputtext = QLineEdit(self.talkArea) self.hbox = QHBoxLayout() self.hbox.addWidget(self.inputtext) self.hbox.addWidget(self.pushButton) #because qwidget only have setlayout, so use self.talkArea to set self.talkArea.setLayout(QVBoxLayout()) self.talkArea.layout().addWidget(self.outputArea) self.talkArea.layout().addLayout(self.hbox) self.pushButton.clicked.connect(self.push) self.talkArea.show() def push(self): self.outputArea.append(self.inputtext.text()) self.bar.showMessage(self.inputtext.text()) self.inputtext.clear() def loginQWidget(self): self.loginArea = QWidget() self.loginArea.setWindowTitle('login') self.label = QLabel('輸入ip:', self.loginArea) self.ip_input = QLineEdit(self.loginArea) self.login_button = QPushButton('login', self.loginArea) self.loginArea.setLayout(QVBoxLayout()) self.loginArea.layout().addWidget(self.label) self.loginArea.layout().addWidget(self.ip_input) self.loginArea.layout().addWidget(self.login_button) self.login_button.clicked.connect(self.login) self.loginArea.show() def login(self): self.show() self.ip_input.clear() self.loginArea.hide() def createAboutQWidget(self): self.aboutArea = QWidget() self.aboutArea.setWindowTitle('about') self.about_label = QLabel('這是我在工程獅計劃中的作品之一', self.aboutArea) self.aboutArea.setLayout(QVBoxLayout()) self.aboutArea.layout().addWidget(self.about_label)
class MainWindow(QWidget): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint) # self.setAttribute(Qt.WA_TranslucentBackground) self.resize(900, 700) self.__search_mode = {'fuzzy': 'fuzzy_search', 'precise': 'precise_search', 'reg': 'reg_search'} # self.__pbn_switch_view = None # 创建窗口部件 self.__widget_frame = QLabel() # window title self.__lab_title_fram = QLabel() self.__lab_title = QLabel('搜索辅助工具') self.__lab_title.setAlignment(Qt.AlignCenter) self.__lab_open_tool = QLabel('打开文件方式') self.__ln_open_tool = QLineEdit() self.__pbn_open_tool = QToolButton() self.__pbn_open_tool.setText('选择...') self.__ln_open_tool.setFixedHeight(20) self.__ln_open_tool.setFixedWidth(150) self.__pbn_open_tool.setFixedSize(48, 20) self.__lab_title_fram.setFixedHeight(50) # search mode self.__lab_mode_fram = QLabel() self.__rbn_fuzzy = QRadioButton('模糊搜索') self.__rbn_precise = QRadioButton('精确搜索') self.__rbn_reg = QRadioButton('正则表达式搜索') self.__rbn_fuzzy.setChecked(True) self.__lab_mode_fram.setFixedHeight(22) # search pattern self.__lab_pattern_fram = QLabel() self.__ln_file_name = QLineEdit() self.__ln_file_name.setPlaceholderText('请输入搜索条件或正则表达式......') self.__rbn_reg_Iyes = QRadioButton('区分大小写') self.__rbn_reg_Ino = QRadioButton('不区分大小写') self.__lab_pattern_fram.setFixedHeight(20) # search path self.__lab_path_fram = QLabel() self.__ln_file_path = QLineEdit() self.__ln_file_path.setPlaceholderText('请选择或输入路径......') self.__pbn_file_path = QToolButton() self.__pbn_file_path.setText('浏览...') self.__rbn_search_file = QRadioButton('检索文件名') self.__rbn_search_content = QRadioButton('检索文件内容') self.__pbn_file_path.setFixedSize(48, 20) self.__lab_path_fram.setFixedHeight(20) # search state self.__lab_state_fram = QLabel() self.__lab_state = QLabel('状态:暂无搜索结果!') self.__pbn_search = QPushButton('开始') self.__pbn_stop = QPushButton('停止') self.__pbn_search.setFixedWidth(89) self.__pbn_stop.setFixedWidth(89) self.__lab_state_fram.setFixedHeight(35) # search result self.__tabView = QTabWidget() self.__browser_result = QListWidget() self.__browser_error = QTextBrowser() self.__tabView.addTab(self.__browser_result, '匹配结果') self.__tabView.addTab(self.__browser_error, '错误结果') self.__btn_group_type = QButtonGroup() self.__btn_group_type.addButton(self.__rbn_search_file) self.__btn_group_type.addButton(self.__rbn_search_content) self.__rbn_search_file.setChecked(True) # radiobutton group self.__btn_group_re_I = QButtonGroup() self.__btn_group_re_I.addButton(self.__rbn_reg_Iyes) self.__btn_group_re_I.addButton(self.__rbn_reg_Ino) self.__rbn_reg_Iyes.setChecked(True) # lines ''' self.__line_1 = QFrame() self.__line_1.setFrameStyle(QFrame.HLine | QFrame.Sunken) ''' # 布局 # open tool self.__layout_tool_choose = QHBoxLayout() self.__layout_tool_choose.addWidget(self.__ln_open_tool) self.__layout_tool_choose.addWidget(self.__pbn_open_tool) self.__layout_tool_choose.setSpacing(0) self.__layout_tool_choose.setContentsMargins(0, 0, 0, 0) self.__layout_open_tool = QHBoxLayout() self.__layout_open_tool.addWidget(self.__lab_open_tool) self.__layout_open_tool.addLayout(self.__layout_tool_choose) self.__layout_open_tool.setSpacing(2) # window title self.__layout_title = QHBoxLayout() self.__layout_title.addStretch(5) self.__layout_title.addWidget(self.__lab_title) self.__layout_title.addStretch(1) self.__layout_title.addLayout(self.__layout_open_tool) self.__layout_title.setContentsMargins(0, 0, 0, 20) self.__lab_title_fram.setLayout(self.__layout_title) # search mode self.__layout_search_mode = QHBoxLayout() self.__layout_search_mode.addWidget(self.__rbn_fuzzy) self.__layout_search_mode.addStretch() self.__layout_search_mode.addWidget(self.__rbn_precise) self.__layout_search_mode.addStretch() self.__layout_search_mode.addWidget(self.__rbn_reg) self.__layout_search_mode.setContentsMargins(60, 0, 60, 0) self.__lab_mode_fram.setLayout(self.__layout_search_mode) # search pattern self.__layout_search_reg_I = QHBoxLayout() self.__layout_search_reg_I.addWidget(self.__rbn_reg_Iyes) self.__layout_search_reg_I.addWidget(self.__rbn_reg_Ino) self.__layout_pattern = QHBoxLayout() self.__layout_pattern.addWidget(self.__ln_file_name) self.__layout_pattern.addLayout(self.__layout_search_reg_I) self.__layout_pattern.setContentsMargins(0, 0, 0, 0) self.__lab_pattern_fram.setLayout(self.__layout_pattern) # search path self.__layout_choose_path = QHBoxLayout() self.__layout_choose_path.addWidget(self.__ln_file_path) self.__layout_choose_path.addWidget(self.__pbn_file_path) self.__layout_choose_path.setSpacing(0) self.__layout_path = QHBoxLayout() self.__layout_path.addLayout(self.__layout_choose_path) self.__layout_path.addWidget(self.__rbn_search_file) self.__layout_path.addWidget(self.__rbn_search_content) self.__layout_path.setContentsMargins(0, 0, 0, 0) self.__lab_path_fram.setLayout(self.__layout_path) # search state self.__layout_state = QHBoxLayout() self.__layout_state.addWidget(self.__lab_state) self.__layout_state.addWidget(self.__pbn_search) self.__layout_state.addWidget(self.__pbn_stop) self.__layout_state.setContentsMargins(0, 0, 0, 10) self.__lab_state_fram.setLayout(self.__layout_state) # top layout self.__layout_top = QVBoxLayout() self.__layout_top.addWidget(self.__lab_title_fram) self.__layout_top.addWidget(self.__lab_mode_fram) self.__layout_top.addWidget(self.__lab_pattern_fram) self.__layout_top.addWidget(self.__lab_path_fram) self.__layout_top.addWidget(self.__lab_state_fram) self.__layout_top.addWidget(self.__tabView) self.__layout_top.setSpacing(10) self.__widget_frame.setLayout(self.__layout_top) self.__layout_fram = QGridLayout() self.__layout_fram.addWidget(self.__widget_frame, 0, 0, 1, 1) self.__layout_fram.setContentsMargins(0, 0, 0, 0) self.setLayout(self.__layout_fram) # set object name self.__widget_frame.setObjectName('fram') self.__lab_title.setObjectName('lab_title') self.__ln_open_tool.setObjectName('ln_open_tool') self.__lab_mode_fram.setObjectName('mode_fram') self.__ln_file_name.setObjectName('ln_pattern') self.__ln_file_path.setObjectName('ln_path') self.__lab_state.setObjectName('state') self.__tabView.setObjectName('tabView') self.__browser_result.setObjectName('browser_result') self.__browser_error.setObjectName('browser_error') self.setStyleSheet( '#fram{' 'border-image: url(Images/bg);' '}' '#lab_title{' 'color: white;' 'font-size: 18pt;' '}' '#open_tool{' 'color: black;' '}' '#mode_fram{' # 'border-top: 1px solid rgba(20, 20, 20, 100);' # 'border-bottom: 1px solid rgba(20, 20, 20, 100);' 'background: rgba(0, 0, 0, 40);' '}' '#ln_open_tool, #ln_path{' 'border-top-left-radius: 2px;' 'border-bottom-left-radius: 2px;' '}' '#ln_pattern{' 'border-radius: 2px;' '}' '#state{' 'background: rgba(0, 0, 0, 40);' 'border-radius: 2px;' 'padding: 1px;' 'color: rgb(240, 240, 240);' '}' 'QTabBar::tab {' 'border: 0;' 'width: 90px;' 'height: 20px;' 'margin: 0 2px 0 0;' # top right bottom left # 'border-top-left-radius: 5px;' # 'border-top-right-radius: 5px;' 'color: rgb(200, 255, 255;);' '}' 'QTabBar::tab:selected{' 'background: rgba(25, 0, 0, 40);' 'border-left: 1px solid rgba(255, 255, 255, 200);' 'border-top: 1px solid rgba(255, 255, 255, 200);' 'border-right: 1px solid rgba(255, 255, 255, 200);' '}' 'QTabWidget:pane {' 'border: 1px solid rgba(255, 255, 255, 200);' 'background: rgba(0, 0, 0, 80);' '}' '#browser_result, #browser_error{' 'background: rgba(0, 0, 0, 0);' 'border: 0;' '}' 'QLineEdit{' 'background: rgba(0, 0, 0, 40);' 'border: 1px solid rgba(220, 220, 220, 200);' 'color: white;' 'height: 20px;' '}' 'QPushButton{' 'background: rgba(0, 0, 0, 100);' 'border-radius: 5px;' 'height: 20px;' 'color: white;' '}' 'QPushButton::hover{' 'background: rgba(0, 0, 0, 150);' '}' 'QToolButton{' 'background: rgba(0, 0, 0, 100);' 'color: white;' 'border-top-right-radius: 2px;' 'border-bottom-right-radius: 2px;' '}' 'QToolButton::hover{' 'background: rgba(0, 0, 0, 150);' '}' ) self.__ln_file_name.setFocus() self.__pbn_search.setShortcut(Qt.Key_Return) # 关联 信号/槽 self.__pbn_file_path.clicked.connect(self.choose_path) self.__pbn_search.clicked.connect(self.pbn_search_clicked) self.__pbn_stop.clicked.connect(self.pbn_stop) self.__pbn_open_tool.clicked.connect(self.choose_open_tool) self.__browser_result.doubleClicked.connect(self.listitem_clicked) # 线程间共享数据队列 queue_size = 10000 self.__queue_result = Queue(queue_size) self.__queue_error = Queue(queue_size) # 标记搜索状态 self.__searching = False # 强制结束子线程 self.__thread_killer = False # 重写鼠标按下事件 def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.offset = event.globalPos() - self.pos() # 重写鼠标移动事件 def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton: self.move(event.globalPos() - self.offset) # 检测记事本程序 def set_open_tool(self): if platform.architecture() == ('32bit', 'WindowsPE'): possible_dir = ['C:\\Program Files\\Sublime Text 2', 'C:\\Sublime Text 2', 'D:\\Program Files\\Sublime Text 2', 'D:\\Sublime Text 2', 'E:\\Program Files\\Sublime Text 2', 'E:\\Sublime Text 2', 'F:\\Program Files\\Sublime Text 2', 'F:\\Sublime Text 2', 'C:\\Program Files\\Notepad++', 'C:\\notepad++', 'D:\\Program Files\\Notepad++', 'D:\\notepad++', 'E:\\Program Files\\Notepad++', 'E:\\notepad++', 'F:\\Program Files\\Notepad++', 'F:\\notepad++', 'C:\\Windows\\System32'] elif platform.architecture() == ('32bit', 'ELF'): possible_dir = ['/usr/bin'] for rootdir in possible_dir: for root, dirs, files in walk(rootdir): for file in files: if file == 'sublime_text.exe' or file == 'notepad++.exe' or file == 'notepad.exe': self.__ln_open_tool.setText(join(root, file)) return # 搜索文件名 def search_from_filename(self, filepath, filename, mode='fuzzy_search', I=True): # check arguments of searching if filepath == '' or not exists(filepath): return False if mode not in self.__search_mode.values(): return False if filename == '': return False # count count = 0 # fuzzy mode if mode == self.__search_mode['fuzzy']: for root, dirs, files in walk(filepath): for each_file in files: # kill subThread if self.__thread_killer == True: return if filename in each_file: count += 1 self.__lab_state.setText('正在搜索......已搜到 %d 个文件' % count) self.__queue_result.put(join(root, each_file)) self.__tabView.setTabText(0, '匹配结果(%d)' % count) # precise mode elif mode == self.__search_mode['precise']: for root, dirs, files in walk(filepath): for each_file in files: # kill subThread if self.__thread_killer == True: return if filename == splitext(each_file)[0] or filename == each_file: count += 1 self.__lab_state.setText('正在搜索......已搜到 %d 个文件' % count) self.__queue_result.put(join(root, each_file)) self.__tabView.setTabText(0, '匹配结果(%d)' % count) # regular expression mode elif mode == self.__search_mode['reg']: if I: pattern = re.compile(r'%s' % filename) else: pattern = re.compile(r'%s' % filename, re.I) for root, dirs, files in walk(filepath): for each_file in files: # kill subThread if self.__thread_killer == True: return if re.search(pattern, each_file): count += 1 self.__lab_state.setText('正在搜索......已搜到 %d 个文件' % count) self.__queue_result.put(join(root, each_file)) self.__tabView.setTabText(0, '匹配结果(%d)' % count) self.__lab_state.setText('搜索完毕! 共搜到 %d 个文件' % count) # finished self.__searching = False # set serching flag # 搜索文件内容 def search_from_content(self, path, content, mode='fuzzy_search', I=True): if path == '' or not exists(path): return False if mode not in self.__search_mode.values(): return False if content == '': return False pass_file_count = 0 error_number = 0 current_file = '' processing_file = '' match_files_count = 0 if mode == self.__search_mode['reg']: if I: pattern = re.compile(r'%s' % content) else: pattern = re.compile(r'%s' % content, re.I) for root, dirs, files in walk(path): for each_file in [file for file in files if file.endswith('.h') or file.endswith('.cpp') or file.endswith('.cs')]: current_file = join(root, each_file) pass_file_count += 1 self.__lab_state.setText('正在搜索......%s' % current_file) try: for line_number, line in enumerate(open(current_file)): # kill subThread if self.__thread_killer == True: return if re.search(pattern, line): if processing_file != current_file: self.__queue_result.put('\n%s' % current_file) processing_file = current_file match_files_count += 1 self.__queue_result.put('line %s: %s' % (line_number, line.strip())) except Exception as error: self.__queue_error.put("%s\n(%s)\n" % (error, current_file)) pass_file_count -= 1 error_number += 1 continue self.__tabView.setTabText(0, '匹配结果(%d)' % match_files_count) else: for root, dirs, files in walk(path): for each_file in [file for file in files if file.endswith('.h') or file.endswith('.cpp') or file.endswith('.cs') or file.endswith('.txt') or file.endswith('.py')]: current_file = join(root, each_file) pass_file_count += 1 self.__lab_state.setText('正在搜索......%s' % current_file) try: for line_number, line in enumerate(open(current_file)): # kill subThread if self.__thread_killer == True: return if content in line: # 匹配成功 if processing_file != current_file: # 如果是新文件 self.__queue_result.put('\n%s' % current_file) # 文件名入队 processing_file = current_file # 更新文件标记 match_files_count += 1 self.__queue_result.put('line %s: %s' % (line_number, line.strip())) # 匹配行入队 except Exception as error: self.__queue_error.put("%s\n(%s)\n" % (error, current_file)) pass_file_count -= 1 error_number += 1 continue self.__tabView.setTabText(0, '匹配结果(%d)' % match_files_count) # self.__queue_result.put() self.__lab_state.setText('搜索完毕!成功匹配 %d 个文件,处理 %s 个文件,失败 %s 文件。' % (match_files_count, pass_file_count, error_number)) self.__searching = False # 单击选择路径按钮 def choose_path(self): path = QFileDialog.getExistingDirectory() if path != '': path = sep.join(path.split('/')) self.__ln_file_path.setText(path) # 选择打开文件工具 def choose_open_tool(self): path = QFileDialog.getOpenFileName() if path[0] != '': self.__ln_open_tool.setText(path[0]) # 显示搜索结果 def show_search_result(self): """将搜索结果加载到界面,供用户查看和操作""" line_block = [] # 定义临时列表,成批加载,避免刷新频率过高造成界面闪烁 block_size = 10 # 一次性加载的个数 while self.__searching or self.__queue_result.qsize(): # kill subThread if self.__thread_killer == True: return # if self.__searching or self.__queue_result.qsize() >= block_size: // 永远记住这个 bug (生产者-消费者 问题) if self.__queue_result.qsize() >= block_size: # 如果队列中不小于 block_size 个项 for i in range(block_size): # 取出 block_size 个项 line_block.append(self.__queue_result.get()) # 出队操作 self.__browser_result.addItems(line_block) # 一次性添加 block_size 个条目 line_block.clear() # 清空临时列表 elif self.__queue_result.qsize() >= 0: # 如果队列中小于 block_size 各项 item = self.__queue_result.get() # 出队一项 self.__browser_result.addItem(QListWidgetItem(item)) # 加载到界面 #self.__browser.setCurrentRow(self.__browser.count()-1) # 设置列表中最后一项为当前项,使列表不停滚动 sleep(0.05) # 给界面事件循环腾出时间,避免界面冻结 #self.__pbn_search.setEnabled(True) # 显示出错结果 def show_error_result(self): """打印略过的文件和出错原因,多为 I/O Error""" count = 0 while self.__queue_error.qsize() or self.__searching: # kill subThread if self.__thread_killer == True: return if self.__queue_error.qsize() <= 0: continue self.__browser_error.append(self.__queue_error.get()) count += 1 self.__tabView.setTabText(1, '错误结果(%d)' % count) # 单击检索按钮 def pbn_search_clicked(self): """To search allow the arguments from UI""" # 获取 UI 数据 file_path = self.__ln_file_path.text() file_name = self.__ln_file_name.text() # 检查参数 if file_path == '': QMessageBox(QMessageBox.Warning, '缺少参数!', '请输入搜索路径!', QMessageBox.Ok, self).exec_() return if file_name == '': QMessageBox(QMessageBox.Warning, '缺少参数!', '请输入匹配条件!', QMessageBox.Ok, self).exec_() return # 判断搜索模式 mode = self.__search_mode['fuzzy'] if self.__rbn_reg.isChecked(): mode = self.__search_mode['reg'] elif self.__rbn_fuzzy.isChecked(): mode = self.__search_mode['fuzzy'] elif self.__rbn_precise.isChecked(): mode = self.__search_mode['precise'] # 大小写敏感标记 I = True if self.__rbn_reg_Ino.isChecked(): I = False self.__browser_result.clear() self.__browser_error.clear() self.__tabView.setTabText(0, '匹配结果(0)') self.__tabView.setTabText(1, '错误结果(0)') self.__searching = True # 开启子线程,后台深度遍历 self.__thread_killer = False if self.__rbn_search_file.isChecked(): self.__lab_state.setText('正在搜索......已搜索到 0 个文件') self.__sub_thread_search = Thread(target=self.search_from_filename, args=(file_path, file_name, mode, I)) self.__sub_thread_search.start() else: self.__lab_state.setText('正在搜索......') self.__sub_thread_search = Thread(target=self.search_from_content, args=(file_path, file_name, mode, I)) self.__sub_thread_search.start() # 开启子线程,显示搜索结果 self.__sub_thread_show_result = Thread(target=self.show_search_result) self.__sub_thread_show_result.start() # 开启子线程,显示错误结果 self.__sub_thread_show_error = Thread(target=self.show_error_result) self.__sub_thread_show_error.start() # self.__pbn_search_file.setEnable(False) # self.__pbn_search_content.setEnable(False) # 单击停止按钮 def pbn_stop(self): if not self.__searching: return self.__thread_killer = True while self.__queue_result.qsize(): self.__queue_result.get() while self.__queue_error.qsize(): self.__queue_error.get() self.__lab_state.setText('搜索已停止!') self.__searching = False # 双击搜索结果 def listitem_clicked(self): """Double click to open the file from search result""" file_path = self.__browser_result.currentItem().text().strip() read_tool = self.__ln_open_tool.text() if not exists(file_path): QMessageBox.warning(self, '错误!', '请双击文件名\n%s 不是文件或打不开!' % file_path, QMessageBox.Ok) return if splitext(file_path)[1] in ['.jpg', '.png', '.jpeg', '.gif']: file_path = r'%s'.replace(' ', r'\ ') % file_path system('%s' % file_path) else: system('"%s" %s' % (read_tool, file_path))
class QChatWidget(QWidget): def __init__(self, chat_window, nick, parent=None): QWidget.__init__(self, parent) self.chat_window = chat_window self.nick = nick self.disabled = False self.cleared = False self.url_regex = re.compile(URL_REGEX) self.chat_log = QTextBrowser() self.chat_log.setOpenExternalLinks(True) self.chat_input = QTextEdit() self.chat_input.textChanged.connect(self.chatInputTextChanged) self.send_button = QPushButton("Send") self.send_button.clicked.connect(self.sendMessage) # Set the min height for the chatlog and a matching fixed height for the send button chat_input_font_metrics = QFontMetrics(self.chat_input.font()) self.chat_input.setMinimumHeight(chat_input_font_metrics.lineSpacing() * 3) self.send_button.setFixedHeight(chat_input_font_metrics.lineSpacing() * 3) hbox = QHBoxLayout() hbox.addWidget(self.chat_input) hbox.addWidget(self.send_button) # Put the chatinput and send button in a wrapper widget so they may be added to the splitter chat_input_wrapper = QWidget() chat_input_wrapper.setLayout(hbox) chat_input_wrapper.setMinimumHeight(chat_input_font_metrics.lineSpacing() * 3.7) # Put the chat log and chat input into a splitter so the user can resize them at will splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.chat_log) splitter.addWidget(chat_input_wrapper) splitter.setSizes([int(parent.height()), 1]) hbox = QHBoxLayout() hbox.addWidget(splitter) self.setLayout(hbox) self.typing_timer = QTimer() self.typing_timer.setSingleShot(True) self.typing_timer.timeout.connect(self.stoppedTyping) def setRemoteNick(self, nick): self.nick = nick def chatInputTextChanged(self): # Check if the text changed was the text box being cleared to avoid sending an invalid typing status if self.cleared: self.cleared = False return if str(self.chat_input.toPlainText())[-1:] == '\n': self.sendMessage() else: # Start a timer to check for the user stopping typing self.typing_timer.start(TYPING_TIMEOUT) self.sendTypingStatus(TYPING_START) def stoppedTyping(self): self.typing_timer.stop() if str(self.chat_input.toPlainText()) == '': self.sendTypingStatus(TYPING_STOP_WITHOUT_TEXT) else: self.sendTypingStatus(TYPING_STOP_WITH_TEXT) def sendMessage(self): if self.disabled: return else: pass self.typing_timer.stop() text = str(self.chat_input.toPlainText())[:-1] # Don't send empty messages if text == '': return # Convert URLs into clickable links text = self.__linkify(text) # Add the message to the message queue to be sent self.chat_window.client.getSession(self.remote_id).sendChatMessage(text) # Clear the chat input self.wasCleared = True self.chat_input.clear() self.appendMessage(text, MSG_SENDER) def sendTypingStatus(self, status): self.chat_window.client.getSession(self.remote_id).sendTypingMessage(status) def showNowChattingMessage(self, nick): self.nick = nick self.remote_id = self.chat_window.client.getClientId(self.nick) self.appendMessage("You are now securely chatting with " + self.nick + " :)", MSG_SERVICE, show_timestamp_and_nick=False) self.appendMessage("It's a good idea to verify the communcation is secure by selecting " "\"authenticate buddy\" in the options menu.", MSG_SERVICE, show_timestamp_and_nick=False) self.addNickButton = QPushButton('Add', self) self.addNickButton.setGeometry(584, 8, 31, 23) self.addNickButton.clicked.connect(self.addNickScreen) self.addNickButton.show() def addUser(self, user): nick = str(user.text()).lower() # Validate the given nick nickStatus = utils.isValidNick(nick) if nickStatus == errors.VALID_NICK: # TODO: Group chats pass elif nickStatus == errors.INVALID_NICK_CONTENT: QMessageBox.warning(self, errors.TITLE_INVALID_NICK, errors.INVALID_NICK_CONTENT) elif nickStatus == errors.INVALID_NICK_LENGTH: QMessageBox.warning(self, errors.TITLE_INVALID_NICK, errors.INVALID_NICK_LENGTH) elif nickStatus == errors.INVALID_EMPTY_NICK: QMessageBox.warning(self, errors.TITLE_EMPTY_NICK, errors.EMPTY_NICK) def addNickScreen(self): self.chat_log.setEnabled(False) self.chat_input.setEnabled(False) self.send_button.setEnabled(False) self.addNickButton.hide() self.addUserText = QLabel("Enter a username to add a user to the group chat.", self) self.addUserText.setGeometry(200, 20, 300, 100) self.addUserText.show() self.user = QLineEdit(self) self.user.setGeometry(200, 120, 240, 20) self.user.returnPressed.connect(self.addUser) self.user.show() self.addUserButton = QPushButton('Add User', self) self.addUserButton.setGeometry(250, 150, 150, 25) self.addUserButton.clicked.connect(lambda: self.addUser(self.user)) self.addUserButton.show() self.cancel = QPushButton('Cancel', self) self.cancel.setGeometry(298, 210, 51, 23) self.cancel.clicked.connect(lambda: self.chat_log.setEnabled(True)) self.cancel.clicked.connect(lambda: self.chat_input.setEnabled(True)) self.cancel.clicked.connect(lambda: self.send_button.setEnabled(True)) self.cancel.clicked.connect(self.addUserText.hide) self.cancel.clicked.connect(self.user.hide) self.cancel.clicked.connect(self.addUserButton.hide) self.cancel.clicked.connect(self.addNickButton.show) self.cancel.clicked.connect(self.cancel.hide) self.cancel.show() def appendMessage(self, message, source, show_timestamp_and_nick=True): color = self.__getColor(source) if show_timestamp_and_nick: timestamp = '<font color="' + color + '">(' + getTimestamp() + ') <strong>' + \ (self.chat_window.client.nick if source == MSG_SENDER else self.nick) + \ ':</strong></font> ' else: timestamp = '' # If the user has scrolled up (current value != maximum), do not move the scrollbar # to the bottom after appending the message shouldScroll = True scrollbar = self.chat_log.verticalScrollBar() if scrollbar.value() != scrollbar.maximum() and source != constants.SENDER: shouldScroll = False self.chat_log.append(timestamp + message) # Move the vertical scrollbar to the bottom of the chat log if shouldScroll: scrollbar.setValue(scrollbar.maximum()) def __linkify(self, text): matches = self.url_regex.findall(text) for match in matches: text = text.replace(match[0], '<a href="%s">%s</a>' % (match[0], match[0])) return text def __getColor(self, source): if source == MSG_SENDER: if qtUtils.is_light_theme: return '#0000CC' else: return '#6666FF' elif source == MSG_RECEIVER: if qtUtils.is_light_theme: return '#CC0000' else: return '#CC3333' else: if qtUtils.is_light_theme: return '#000000' else: return '#FFFFFF' def disable(self): self.disabled = True self.chat_input.setReadOnly(True) def enable(self): self.disabled = False self.chat_input.setReadOnly(False)
class Sansimera(QMainWindow): def __init__(self, parent=None): super(Sansimera, self).__init__(parent) self.settings = QSettings() self.timer = QTimer(self) self.timer_reminder = QTimer(self) self.timer_reminder.timeout.connect(self.reminder_tray) interval = self.settings.value('Interval') or '1' if interval != '0': self.timer_reminder.start(int(interval) * 60 * 60 * 1000) self.tentatives = 0 self.gui() self.lista = [] self.lista_pos = 0 self.eortazontes_shown = False self.eortazontes_names = '' def gui(self): self.systray = QSystemTrayIcon() self.icon = QIcon(':/sansimera.png') self.systray.setIcon(self.icon) self.systray.setToolTip('Σαν σήμερα...') self.menu = QMenu() self.exitAction = QAction('&Έξοδος', self) self.refreshAction = QAction('&Ανανέωση', self) self.aboutAction = QAction('&Σχετικά', self) self.notification_interval = QAction('Ει&δοποίηση εορταζόντων', self) self.menu.addAction(self.notification_interval) self.menu.addAction(self.refreshAction) self.menu.addAction(self.aboutAction) self.menu.addAction(self.exitAction) self.systray.setContextMenu(self.menu) self.notification_interval.triggered.connect(self.interval_namedays) self.exitAction.triggered.connect(exit) self.refreshAction.triggered.connect(self.refresh) self.aboutAction.triggered.connect(self.about) self.browser = QTextBrowser() self.browser.setOpenExternalLinks(True) self.setGeometry(600, 500, 400, 300) self.setWindowIcon(self.icon) self.setWindowTitle('Σαν σήμερα...') self.setCentralWidget(self.browser) self.systray.show() self.systray.activated.connect(self.activate) self.browser.append('Λήψη...') nicon = QIcon(':/next') picon = QIcon(':/previous') ricon = QIcon(':/refresh') iicon = QIcon(':/info') qicon = QIcon(':/exit') inicon = QIcon(':/notifications') self.nextAction = QAction('Επόμενο', self) self.nextAction.setIcon(nicon) self.previousAction = QAction('Προηγούμενο', self) self.refreshAction.triggered.connect(self.refresh) self.nextAction.triggered.connect(self.nextItem) self.previousAction.triggered.connect(self.previousItem) self.previousAction.setIcon(picon) self.refreshAction.setIcon(ricon) self.exitAction.setIcon(qicon) self.aboutAction.setIcon(iicon) self.notification_interval.setIcon(inicon) controls = QToolBar() self.addToolBar(Qt.BottomToolBarArea, controls) controls.setObjectName('Controls') controls.addAction(self.previousAction) controls.addAction(self.nextAction) controls.addAction(self.refreshAction) self.restoreState(self.settings.value("MainWindow/State", QByteArray())) self.refresh() def interval_namedays(self): dialog = sansimera_reminder.Reminder(self) dialog.applied_signal['QString'].connect(self.reminder) if dialog.exec_() == 1: print('Apply namedays reminder interval...') def reminder(self, time): self.settings.setValue('Interval', time) if time != '0': self.timer_reminder.start(int(time) * 60 * 60 * 1000) print('Reminder = ' + time + ' hour(s)') else: print('Reminder = None') def nextItem(self): if len(self.lista) >= 1: self.browser.clear() if self.lista_pos != len(self.lista)-1: self.lista_pos += 1 else: self.lista_pos = 0 self.browser.append(self.lista[self.lista_pos]) self.browser.moveCursor(QTextCursor.Start) else: return def previousItem(self): if len(self.lista) >= 1: self.browser.clear() if self.lista_pos == 0: self.lista_pos = len(self.lista)-1 else: self.lista_pos -= 1 self.browser.append(self.lista[self.lista_pos]) self.browser.moveCursor(QTextCursor.Start) else: return def refresh(self): try: if self.workThread.isRunning(): return except AttributeError: pass self.menu.hide() self.browser.clear() self.lista = [] self.systray.setToolTip('Σαν σήμερα...') self.browser.append('Λήψη...') self.tentatives = 0 self.eortazontes_shown = False self.download() def activate(self, reason): self.menu.hide() state = self.isVisible() if reason == 3: if state: self.hide() return else: self.show() return if reason == 1: self.menu.hide() self.menu.popup(QCursor.pos()) def download(self): self.workThread = WorkThread() self.workThread.online_signal[bool].connect(self.status) self.workThread.finished.connect(self.window) self.workThread.event['QString'].connect(self.addlist) self.workThread.names['QString'].connect(self.nameintooltip) self.workThread.start() def addlist(self, text): self.lista.append(text) def status(self, status): self.status_online = status def reminder_tray(self): text = self.eortazontes_names.replace('<br/>', '\n') urltexts = re.findall('(<a [\S]+php">)', text) urltexts.extend(['</a>', '<p>', '<div>']) show_notifier_text = text for i in urltexts: show_notifier_text = show_notifier_text.replace(i, '') show_notifier_text = show_notifier_text.replace('\n\n', '\n') show_notifier_text = show_notifier_text.replace('www.eortologio.gr)', 'www.eortologio.gr)\n') self.systray.showMessage('Εορτάζουν:\n', show_notifier_text) self.systray.setToolTip('Εορτάζουν:\n' + show_notifier_text) def nameintooltip(self, text): self.eortazontes_names = text for i in ['<br/>', '<div>']: text = text.replace(i, '') self.eortazontes_in_window = text if self.eortazontes_shown: return self.reminder_tray() self.eortazontes_shown = True def window(self): self.lista.append('<div class=""></div>' + self.eortazontes_in_window) if self.status_online: self.browser.clear() self.browser.append(self.lista[0]) self.lista_pos = 0 return else: if self.tentatives == 10: return self.timer.singleShot(5000, self.refresh) self.tentatives += 1 def closeEvent(self, event): self.settings.setValue("MainWindow/State", self.saveState()) def about(self): self.menu.hide() QMessageBox.about(self, "Εφαρμογή «Σαν σήμερα...»", """<b>sansimera-qt</b> v{0} <p>Δημήτριος Γλενταδάκης <a href="mailto:[email protected]">[email protected]</a> <br/>Ιστοσελίδα: <a href="https://github.com/dglent/sansimera-qt"> github sansimera-qt</a> <p>Εφαρμογή πλαισίου συστήματος για την προβολή <br/>των γεγονότων από την ιστοσελίδα <a href="http://www.sansimera.gr"> www.sansimera.gr</a><br/> Πηγή εορτολογίου: <a href="http://www.eortologio.gr"> www.eortologio.gr</a>, <a href="http://www.synaxari.gr"> www.synaxari.gr</a> <p>Άδεια χρήσης: GPLv3 <br/>Python {1} - Qt {2} - PyQt {3} σε {4}""".format( __version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system()))