热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

pyqt练习x3.11

#!usrbinenvpython#-*-coding:utf-8-*-######################################################

#!/usr/bin/env python

# -*- coding: utf-8 -*-

 

########################################################################################

#                                                                                      #

# Copyright (c) 2009 Jakob Kummerow                          #

#                                                                                      #

# 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.                                                                             #

#                                                                                      #

# 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.             #

#                                                                                      #

# You should have received a copy of the GNU General Public License along with         #

# this program.  If not, see .                           #

#                                                                                      #

########################################################################################

 

 

"""

Future ideas:

- auto-indenting: automatically increase/decrease indentation level. --> when?

- send further commands to Hugs without restarting --> major change, might need threads

- support GHCI --> would that be useful?

"""

 

import sys, os, re

from subprocess import Popen, PIPE

from tempfile import NamedTemporaryFile

from PyQt4.QtGui import * #@UnusedWildImport

from PyQt4.QtCore import * #@UnusedWildImport

 

fileFilter = "Haskell source files (*.hs);;All files (*.*)"

settingsFileName = ".config/hugsgui.conf"

fontfamily = "DejaVu Sans Mono"

 

class EditBox(QTextEdit):

 

def __init__(self, parent=None, defaultText=""):

QTextEdit.__init__(self)

self.setTabChangesFocus(False)

self.setAcceptRichText(False)

self.defaultText = defaultText

self.dirty = False

self.loadedFile = False

self.initialState()

self.connect(self, SIGNAL("textChanged()"), self.textChangedHandler)

# we need this to prevent the cursor from jumping back to the system‘s default font

self.connect(self, SIGNAL("currentCharFormatChanged(const QTextCharFormat&)"), self.resetCurrentCharFormat)

self.errorline = []

self.ffont = None

 

def clearInitially(self):

self.clear()

self.setTextColor(self.palette().color(QPalette.Active, QPalette.Text))

self.neverUsed = False

self.resetFont()

 

def initialState(self):

self.neverUsed = True

self.setTextColor(self.palette().color(QPalette.Disabled, QPalette.Text))

self.setPlainText(self.defaultText)

 

def highlightError(self, linenumber):

block = self.document().findBlockByLineNumber(linenumber)

format = block.blockFormat()

format.setBackground(QBrush(QColor(255, 128, 128, 255)))

cursor = self.textCursor()

cursor.setPosition(block.position())

cursor.setBlockFormat(format)

self.errorline += [block]

 

def resetErrorHighlight(self):

for line in self.errorline:

format = line.blockFormat()

format.clearBackground()

cursor = self.textCursor()

if line.position() < self.document().characterCount():

cursor.setPosition(line.position())

cursor.setBlockFormat(format)

self.errorline = []

 

def keyPressEvent(self, e):

if self.neverUsed:

self.clearInitially()

 

if e.key() == Qt.Key_Backtab:

# unindent, either current line only or all selected lines

maincursor = self.textCursor()

if not maincursor.hasSelection():

maincursor.movePosition(QTextCursor.StartOfBlock)

line = str(self.document().findBlockByNumber(maincursor.blockNumber()).text().toUtf8())

whitespace = re.match(r"(\s{0,2})", line).group(1)

for i in range(len(whitespace)): #@UnusedVariable

maincursor.deleteChar()

else:

block = self.document().findBlock(maincursor.selectionStart())

while True:

whitespace = re.match(r"(\s{0,2})", str(block.text().toUtf8())).group(1)

cursor = self.textCursor() 

cursor.setPosition(block.position())

for i in range(len(whitespace)): #@UnusedVariable

cursor.deleteChar()

if block.contains(maincursor.selectionEnd()):

break

block = block.next()

e.accept()

elif e.key() == Qt.Key_Tab:

# indent, either current line only or all selected lines

maincursor = self.textCursor()

if not maincursor.hasSelection():

maincursor.insertText("  ")

else:

block = self.document().findBlock(maincursor.selectionStart())

while True:

cursor = self.textCursor() 

cursor.setPosition(block.position())

cursor.insertText("  ")

if block.contains(maincursor.selectionEnd()):

break

block = block.next()

e.accept()

elif e.key() == Qt.Key_Return:

# copy whitespace from the beginning of the previous line

cursor = self.textCursor()

block = self.document().findBlockByNumber(cursor.blockNumber())

whitespace = re.match(r"(\s*)", str(block.text().toUtf8())).group(1)

QTextEdit.keyPressEvent(self, e)

cursor = self.textCursor()

format = cursor.blockFormat()

format.clearBackground()

cursor.setBlockFormat(format)

cursor.insertText(whitespace)

else:

QTextEdit.keyPressEvent(self, e)

 

def focusInEvent(self, e):

if self.neverUsed and e.reason() != Qt.ActiveWindowFocusReason:

self.clearInitially()

QTextEdit.focusInEvent(self, e)

 

def focusOutEvent(self, e):

if self.loadedFile == False and self.toPlainText() == "":

self.initialState()

QTextEdit.focusOutEvent(self, e)

 

def mousePressEvent(self, e):

if self.neverUsed:

self.clearInitially()

QTextEdit.mousePressEvent(self, e)

 

def toPlainText(self):

if self.neverUsed:

return ""

return str(QTextEdit.toPlainText(self).toUtf8())

 

def textChangedHandler(self):

if self.loadedFile == False and (self.neverUsed or self.toPlainText() == ""):

self.dirty = False

else:

self.dirty = True

 

def resetFont(self, fOnt=None):

if font != None:

self.ffont = font

newFormat = QTextCharFormat()

if self.ffont == None:

newFormat.setFontFamily(fontfamily)

else:

newFormat.setFont(self.ffont)

cursor = self.textCursor()

cursor.movePosition(QTextCursor.Start)

cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor)

cursor.mergeCharFormat(newFormat)

self.setCurrentCharFormat(cursor.charFormat())

 

def resetCurrentCharFormat(self):

format = self.textCursor().charFormat()

if self.ffont == None:

format.setFontFamily(fontfamily)

else:

format.setFont(self.ffont)

self.setCurrentCharFormat(format)

 

 

class HugsGUI(QMainWindow):

 

def __init__(self, parent=None):

QMainWindow.__init__(self, parent)

self.setWindowTitle(‘Hugs GUI‘)

 

self.editTextBox = EditBox(self, "Function definition file")

self.commandTextBox = EditBox(self, "Commands for interactive Hugs session")

 

self.outputTextBox = EditBox(self)

self.outputTextBox.setReadOnly(True)

self.outputTextBox.neverUsed = False

 

self.splitter = QSplitter(Qt.Vertical)

self.splitter.addWidget(self.editTextBox)

self.splitter.addWidget(self.commandTextBox)

self.splitter.addWidget(self.outputTextBox)

self.setCentralWidget(self.splitter)

 

toolbar = self.addToolBar("Main")

 

newAction = QAction("New", self)

newAction.setShortcut("Ctrl+N")

newAction.setToolTip("Create a new file (Ctrl+N)")

self.connect(newAction, SIGNAL("triggered()"), self.newFile)

toolbar.addAction(newAction)

 

openAction = QAction("Open...", self)

openAction.setShortcut("Ctrl+O")

openAction.setToolTip("Open file (Ctrl+O)")

self.connect(openAction, SIGNAL("triggered()"), self.openFile)

toolbar.addAction(openAction)

 

saveAction = QAction("Save...", self)

saveAction.setShortcut("Ctrl+S")

saveAction.setToolTip("Save file (Ctrl+S)")

self.connect(saveAction, SIGNAL("triggered()"), self.saveFile)

toolbar.addAction(saveAction)

 

saveAsAction = QAction("Save as...", self)

self.connect(saveAsAction, SIGNAL("triggered()"), self.saveFileAs)

toolbar.addAction(saveAsAction)

 

toolbar.addSeparator()

runAction = QAction("Run!", self)

runAction.setShortcut("F9")

runAction.setToolTip("Run (F9)")

self.connect(runAction, SIGNAL("triggered()"), self.runHugs)

toolbar.addAction(runAction)

 

self.autoSaveAction = QAction("AutoSave before running", self)

self.autoSaveAction.setCheckable(True)

self.autoSaveAction.setToolTip("Whether the current document should automatically be saved before executing it.")

 

self.interactiveSaveAction = QAction("Save commands for interactive mode", self)

self.interactiveSaveAction.setCheckable(True)

self.interactiveSaveAction.setToolTip("Whether the current command list for the interactive session should be saved on program exit.")

 

fontAction = QAction("Choose Font...", self)

fontAction.setToolTip("Show a dialog that allows choosing the font to use")

self.connect(fontAction, SIGNAL("triggered()"), self.chooseFont)

 

optionsbutton = QToolButton()

optionsbutton.setPopupMode(QToolButton.InstantPopup)

optionsbutton.setText("Options")

options = QMenu("Options", optionsbutton)

options.addAction(self.autoSaveAction)

options.addAction(self.interactiveSaveAction)

options.addAction(fontAction)

optionsbutton.setMenu(options)

toolbar.addSeparator()

toolbar.addWidget(optionsbutton)

 

self.filename = ""

self.ffont = None

 

self.loadSettings()

 

def closeEvent(self, event):

if self.editTextBox.dirty:

reply = QMessageBox.question(self, "Question", "Would you like to save your changes before quitting?",

QMessageBox.Save, QMessageBox.Discard, QMessageBox.Cancel)

if reply == QMessageBox.Save:

self.saveFile()

elif reply == QMessageBox.Cancel:

event.ignore()

return

event.accept()

self.saveSettings()

 

def runHugs(self):

code = self.editTextBox.toPlainText()

if code != "":

if (not self.autoSaveAction.isChecked()) or self.filename == "":

hsfile = NamedTemporaryFile(delete=False)

hsfilepath = hsfile.name

hsfile.file.write(code)

hsfile.file.close()

else:

if self.editTextBox.dirty:

self.saveFile()

hsfilepath = self.filename

else:

hsfilepath = ""

self.outputTextBox.setText("")

echo = self.commandTextBox.toPlainText()

if echo == "":

echo = ":q"

else:

echo = ":set +t\n" + echo

inputfile = NamedTemporaryFile(delete=False)

inputfilepath = inputfile.name

inputfile.file.write(echo)

inputfile.file.close()

if hsfilepath != "":

execstring = str("hugs " + hsfilepath + " < " + inputfilepath)

hugs_out = Popen(execstring, shell=True, stdout=PIPE)

else:

execstring = str("hugs < " + inputfilepath)

hugs_out = Popen(execstring, shell=True, stdout=PIPE)

hugs_out.wait()

show = 0

linenumber = 0

self.editTextBox.resetErrorHighlight()

self.commandTextBox.resetErrorHighlight()

while True:

l = hugs_out.stdout.readline()

if l.rstrip().endswith("> [Leaving Hugs]"): 

break

if l.startswith("Type :? for help") or l.startswith("Haskell 98 mode"):

show = 1

elif show == 1:

show = 2

if show == 2 and re.match(r"(.*?)> \1>", l) is not None:

l = l.partition("> ")[2]

show = 3

if show >= 2:

self.outputTextBox.append(l.strip())

if l.startswith("Hugs> ") or l.startswith("Main> "):

if l.startswith("Hugs> ERROR") or l.startswith("Main> ERROR"):

self.commandTextBox.highlightError(linenumber)

linenumber += 1

if l.startswith("ERROR"):

self.highlightError(l)

# clean up

if self.filename == "" and hsfilepath != "":

os.remove(hsfilepath)

os.remove(inputfilepath)

 

def highlightError(self, line):

linenumber = int(re.match(r"ERROR \".*?\":(\d+) ", line).group(1)) - 1

self.editTextBox.highlightError(linenumber)

 

def newFile(self):

if self.editTextBox.dirty:

reply = QMessageBox.question(self, "Question", "Would you like to save your changes before creating a new file?",

QMessageBox.Save, QMessageBox.Discard, QMessageBox.Cancel)

if reply == QMessageBox.Save:

self.saveFile()

elif reply == QMessageBox.Cancel:

return

self.editTextBox.clearInitially()

self.editTextBox.dirty = False

self.editTextBox.loadedFile = False

self.filename = ""

 

def openFile(self):

if self.editTextBox.dirty:

reply = QMessageBox.question(self, "Question", "Would you like to save your changes before loading another file?",

QMessageBox.Save, QMessageBox.Discard, QMessageBox.Cancel)

if reply == QMessageBox.Save:

self.saveFile()

elif reply == QMessageBox.Cancel:

return

filename = QFileDialog.getOpenFileName(self, "Open file", QString(), fileFilter)

if filename != "":

self.filename = filename

self.editTextBox.clearInitially()

with open(filename) as f:

self.editTextBox.setPlainText("".join(f.readlines()))

self.editTextBox.dirty = False

self.editTextBox.loadedFile = True

 

def saveFileAs(self):

filename = "" + QFileDialog.getSaveFileName(self, "Save file", "untitled.hs", fileFilter).toUtf8()

if filename != "":

self.filename = filename

self.saveFile()

 

def saveFile(self):

if self.filename == "":

self.saveFileAs()

else:

with open(self.filename, ‘w‘) as f:

f.write(self.editTextBox.toPlainText())

self.editTextBox.dirty = False

 

def chooseFont(self):

(selectedfont, ok) = QFontDialog.getFont(self.editTextBox.textCursor().charFormat().font(), self)

if ok:

self.ffont = selectedfont

self.setAllFonts()

 

def setAllFonts(self):

self.editTextBox.resetFont(self.ffont)

self.commandTextBox.resetFont(self.ffont)

self.outputTextBox.resetFont(self.ffont)

 

def saveSettings(self):

settingsfile = QDir.home().absoluteFilePath(settingsFileName)

settings = QSettings(settingsfile, QSettings.IniFormat)

settings.setValue("View/Size", self.size())

settings.setValue("View/Split", self.splitter.sizes())

settings.setValue("Settings/SaveOnRun", self.autoSaveAction.isChecked())

settings.setValue("Settings/SaveInteractive", self.interactiveSaveAction.isChecked())

if self.interactiveSaveAction.isChecked():

settings.setValue("Interactive/Commands", self.commandTextBox.toPlainText())

if self.ffont != None:

settings.setValue("Settings/Font", self.ffont)

 

def loadSettings(self):

settingsfile = QDir.home().absoluteFilePath(settingsFileName)

settings = QSettings(settingsfile, QSettings.IniFormat)

self.resize(settings.value("View/Size", QSize(800, 500)).toSize())

splits = settings.value("View/Split", [154, 154, 154]).toList()

for i in range(len(splits)):

(splits[i], ok) = splits[i].toInt() #@UnusedVariable

if splits[i] < 10:

splits[i] = 10

self.splitter.setSizes(splits)

self.autoSaveAction.setChecked(settings.value("Settings/SaveOnRun", True).toBool())

self.interactiveSaveAction.setChecked(settings.value("Settings/SaveInteractive", False).toBool())

if self.interactiveSaveAction.isChecked():

self.commandTextBox.clearInitially()

self.commandTextBox.setPlainText(settings.value("Interactive/Commands", "").toString())

settingsfont = settings.value("Settings/Font", None)

if not settingsfont == QVariant(None):

self.ffont = QFont(settingsfont)

self.setAllFonts()

 

if __name__ == ‘__main__‘:

app = QApplication(sys.argv)

 

mainwin = HugsGUI()

mainwin.show()

 

sys.exit(app.exec_())

 技术分享

pyqt练习x3.11


推荐阅读
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 在project.properties添加#Projecttarget.targetandroid-19android.library.reference.1..Sliding ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文介绍了一种解析GRE报文长度的方法,通过分析GRE报文头中的标志位来计算报文长度。具体实现步骤包括获取GRE报文头指针、提取标志位、计算报文长度等。该方法可以帮助用户准确地获取GRE报文的长度信息。 ... [详细]
author-avatar
平凡快乐的girl_819
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有