/src/trelby.py
Python | 2694 lines | 2633 code | 50 blank | 11 comment | 17 complexity | 2253f888f34b03267a6d464885926b7a MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- # -*- coding: iso-8859-1 -*-
- from error import *
- import autocompletiondlg
- import cfgdlg
- import characterreport
- import charmapdlg
- import commandsdlg
- import config
- import dialoguechart
- import finddlg
- import gutil
- import headersdlg
- import locationreport
- import locationsdlg
- import misc
- import myimport
- import mypickle
- import namesdlg
- import opts
- import pml
- import scenereport
- import scriptreport
- import screenplay
- import spellcheck
- import spellcheckdlg
- import spellcheckcfgdlg
- import splash
- import titlesdlg
- import util
- import viewmode
- import watermarkdlg
- import copy
- import datetime
- import os
- import os.path
- import signal
- import sys
- import time
- import wx
- from functools import partial
- #keycodes
- KC_CTRL_A = 1
- KC_CTRL_B = 2
- KC_CTRL_D = 4
- KC_CTRL_E = 5
- KC_CTRL_F = 6
- KC_CTRL_N = 14
- KC_CTRL_P = 16
- KC_CTRL_V = 22
- VIEWMODE_DRAFT,\
- VIEWMODE_LAYOUT,\
- VIEWMODE_SIDE_BY_SIDE,\
- VIEWMODE_OVERVIEW_SMALL,\
- VIEWMODE_OVERVIEW_LARGE,\
- = range(5)
- def refreshGuiConfig():
- global cfgGui
- cfgGui = config.ConfigGui(cfgGl)
- def getCfgGui():
- return cfgGui
- # keeps (some) global data
- class GlobalData:
- def __init__(self):
- self.confFilename = misc.confPath + "/default.conf"
- self.stateFilename = misc.confPath + "/state"
- self.scDictFilename = misc.confPath + "/spell_checker_dictionary"
- # current script config path
- self.scriptSettingsPath = misc.confPath
- # global spell checker (user) dictionary
- self.scDict = spellcheck.Dict()
- # recently used files list
- self.mru = misc.MRUFiles(5)
- if opts.conf:
- self.confFilename = opts.conf
- v = self.cvars = mypickle.Vars()
- v.addInt("posX", 0, "PositionX", -20, 9999)
- v.addInt("posY", 0, "PositionY", -20, 9999)
- # linux has bigger font by default so it needs a wider window
- defaultW = 750
- if misc.isUnix:
- defaultW = 800
- v.addInt("width", defaultW, "Width", 500, 9999)
- v.addInt("height", 830, "Height", 300, 9999)
- v.addInt("viewMode", VIEWMODE_DRAFT, "ViewMode", VIEWMODE_DRAFT,
- VIEWMODE_OVERVIEW_LARGE)
- v.addList("files", [], "Files",
- mypickle.StrUnicodeVar("", u"", ""))
- v.makeDicts()
- v.setDefaults(self)
- self.height = min(self.height,
- wx.SystemSettings_GetMetric(wx.SYS_SCREEN_Y) - 50)
- self.vmDraft = viewmode.ViewModeDraft()
- self.vmLayout = viewmode.ViewModeLayout()
- self.vmSideBySide = viewmode.ViewModeSideBySide()
- self.vmOverviewSmall = viewmode.ViewModeOverview(1)
- self.vmOverviewLarge = viewmode.ViewModeOverview(2)
- self.setViewMode(self.viewMode)
- self.makeConfDir()
- def makeConfDir(self):
- makeDir = not util.fileExists(misc.confPath)
- if makeDir:
- try:
- os.mkdir(misc.toPath(misc.confPath), 0755)
- except OSError, (errno, strerror):
- wx.MessageBox("Error creating configuration directory\n"
- "'%s': %s" % (misc.confPath, strerror),
- "Error", wx.OK, None)
- # set viewmode, the parameter is one of the VIEWMODE_ defines.
- def setViewMode(self, viewMode):
- self.viewMode = viewMode
- if viewMode == VIEWMODE_DRAFT:
- self.vm = self.vmDraft
- elif viewMode == VIEWMODE_LAYOUT:
- self.vm = self.vmLayout
- elif viewMode == VIEWMODE_SIDE_BY_SIDE:
- self.vm = self.vmSideBySide
- elif viewMode == VIEWMODE_OVERVIEW_SMALL:
- self.vm = self.vmOverviewSmall
- else:
- self.vm = self.vmOverviewLarge
- # load from string 's'. does not throw any exceptions and silently
- # ignores any errors.
- def load(self, s):
- self.cvars.load(self.cvars.makeVals(s), "", self)
- self.mru.items = self.files
- # save to a string and return that.
- def save(self):
- self.files = self.mru.items
- return self.cvars.save("", self)
- # save global spell checker dictionary to disk
- def saveScDict(self):
- util.writeToFile(self.scDictFilename, self.scDict.save(), mainFrame)
- class MyPanel(wx.Panel):
- def __init__(self, parent, id):
- wx.Panel.__init__(
- self, parent, id,
- # wxMSW/Windows does not seem to support
- # wx.NO_BORDER, which sucks
- style = wx.WANTS_CHARS | wx.NO_BORDER)
- hsizer = wx.BoxSizer(wx.HORIZONTAL)
- self.scrollBar = wx.ScrollBar(self, -1, style = wx.SB_VERTICAL)
- self.ctrl = MyCtrl(self, -1)
- hsizer.Add(self.ctrl, 1, wx.EXPAND)
- hsizer.Add(self.scrollBar, 0, wx.EXPAND)
- wx.EVT_COMMAND_SCROLL(self, self.scrollBar.GetId(),
- self.ctrl.OnScroll)
- wx.EVT_SET_FOCUS(self.scrollBar, self.OnScrollbarFocus)
- self.SetSizer(hsizer)
- # we never want the scrollbar to get the keyboard focus, pass it on to
- # the main widget
- def OnScrollbarFocus(self, event):
- self.ctrl.SetFocus()
- class MyCtrl(wx.Control):
- def __init__(self, parent, id):
- style = wx.WANTS_CHARS | wx.FULL_REPAINT_ON_RESIZE | wx.NO_BORDER
- wx.Control.__init__(self, parent, id, style = style)
- self.panel = parent
- wx.EVT_SIZE(self, self.OnSize)
- wx.EVT_PAINT(self, self.OnPaint)
- wx.EVT_ERASE_BACKGROUND(self, self.OnEraseBackground)
- wx.EVT_LEFT_DOWN(self, self.OnLeftDown)
- wx.EVT_LEFT_UP(self, self.OnLeftUp)
- wx.EVT_LEFT_DCLICK(self, self.OnLeftDown)
- wx.EVT_RIGHT_DOWN(self, self.OnRightDown)
- wx.EVT_MOTION(self, self.OnMotion)
- wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
- wx.EVT_CHAR(self, self.OnKeyChar)
- self.createEmptySp()
- self.updateScreen(redraw = False)
- def OnChangeType(self, event):
- cs = screenplay.CommandState()
- lt = idToLTMap[event.GetId()]
- self.sp.convertTypeTo(lt, True)
- self.sp.cmdPost(cs)
- if cs.needsVisifying:
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def clearVars(self):
- self.mouseSelectActive = False
- # find dialog stored settings
- self.findDlgFindText = ""
- self.findDlgReplaceText = ""
- self.findDlgMatchWholeWord= False
- self.findDlgMatchCase = False
- self.findDlgDirUp = False
- self.findDlgUseExtra = False
- self.findDlgElements = None
- def createEmptySp(self):
- self.clearVars()
- self.sp = screenplay.Screenplay(cfgGl)
- self.sp.titles.addDefaults()
- self.sp.headers.addDefaults()
- self.setFile(None)
- self.refreshCache()
- # update stuff that depends on configuration / view mode etc.
- def refreshCache(self):
- self.chX = util.getTextWidth(" ", pml.COURIER, self.sp.cfg.fontSize)
- self.chY = util.getTextHeight(self.sp.cfg.fontSize)
- self.pageW = gd.vm.getPageWidth(self)
- # conversion factor from mm to pixels
- self.mm2p = self.pageW / self.sp.cfg.paperWidth
- # page width and height on screen, in pixels
- self.pageW = int(self.pageW)
- self.pageH = int(self.mm2p * self.sp.cfg.paperHeight)
- def getCfgGui(self):
- return cfgGui
- def loadFile(self, fileName):
- s = util.loadFile(fileName, mainFrame)
- if s == None:
- return
- try:
- (sp, msg) = screenplay.Screenplay.load(s, cfgGl)
- except TrelbyError, e:
- wx.MessageBox("Error loading file:\n\n%s" % e, "Error",
- wx.OK, mainFrame)
- return
- if msg:
- misc.showText(mainFrame, msg, "Warning")
- self.clearVars()
- self.sp = sp
- self.setFile(fileName)
- self.refreshCache()
- # saved cursor position might be anywhere, so we can't just
- # display the first page
- self.makeLineVisible(self.sp.line)
- # save script to given filename. returns True on success.
- def saveFile(self, fileName):
- fileName = util.ensureEndsIn(fileName, ".trelby")
- if util.writeToFile(fileName, self.sp.save(), mainFrame):
- self.setFile(fileName)
- self.sp.markChanged(False)
- gd.mru.add(fileName)
- return True
- else:
- return False
- def importFile(self, fileName):
- if fileName.endswith("fdx"):
- lines = myimport.importFDX(fileName, mainFrame)
- elif fileName.endswith("celtx"):
- lines = myimport.importCeltx(fileName, mainFrame)
- elif fileName.endswith("astx"):
- lines = myimport.importAstx(fileName, mainFrame)
- elif fileName.endswith("fountain"):
- lines = myimport.importFountain(fileName, mainFrame)
- elif fileName.endswith("fadein"):
- lines = myimport.importFadein(fileName, mainFrame)
- else:
- lines = myimport.importTextFile(fileName, mainFrame)
- if not lines:
- return
- self.createEmptySp()
- self.sp.lines = lines
- self.sp.reformatAll()
- self.sp.paginate()
- self.sp.markChanged(True)
- # generate exportable text from given screenplay, or None.
- def getExportText(self, sp):
- inf = []
- inf.append(misc.CheckBoxItem("Include page markers"))
- dlg = misc.CheckBoxDlg(mainFrame, "Output options", inf,
- "Options:", False)
- if dlg.ShowModal() != wx.ID_OK:
- dlg.Destroy()
- return None
- return sp.generateText(inf[0].selected)
- def getExportHtml(self, sp):
- inf = []
- inf.append(misc.CheckBoxItem("Include Notes"))
- dlg = misc.CheckBoxDlg(mainFrame, "Output options", inf,
- "Options:", False)
- if dlg.ShowModal() != wx.ID_OK:
- dlg.Destroy()
- return None
- return sp.generateHtml(inf[0].selected)
- def setFile(self, fileName):
- self.fileName = fileName
- if fileName:
- self.setDisplayName(os.path.basename(fileName))
- else:
- self.setDisplayName(u"untitled")
- self.setTabText()
- mainFrame.setTitle(self.fileNameDisplay)
- def setDisplayName(self, name):
- i = 1
- while 1:
- if i == 1:
- tmp = name
- else:
- tmp = name + "-%d" % i
- matched = False
- for c in mainFrame.getCtrls():
- if c == self:
- continue
- if c.fileNameDisplay == tmp:
- matched = True
- break
- if not matched:
- break
- i += 1
- self.fileNameDisplay = tmp
- def setTabText(self):
- mainFrame.setTabText(self.panel, self.fileNameDisplay)
- # texts = gd.vm.getScreen(self, False)[0], or None, in which case it's
- # called in this function.
- def isLineVisible(self, line, texts = None):
- if texts == None:
- texts = gd.vm.getScreen(self, False)[0]
- # paranoia never hurts
- if len(texts) == 0:
- return False
- return (line >= texts[0].line) and (line <= texts[-1].line)
- def makeLineVisible(self, line, direction = config.SCROLL_CENTER):
- texts = gd.vm.getScreen(self, False)[0]
- if self.isLineVisible(line, texts):
- return
- gd.vm.makeLineVisible(self, line, texts, direction)
- def adjustScrollBar(self):
- height = self.GetClientSize().height
- # rough approximation of how many lines fit onto the screen.
- # accuracy is not that important for this, so we don't even care
- # about draft / layout mode differences.
- approx = int(((height / self.mm2p) / self.chY) / 1.3)
- self.panel.scrollBar.SetScrollbar(self.sp.getTopLine(), approx,
- len(self.sp.lines) + approx - 1, approx)
- def clearAutoComp(self):
- if self.sp.clearAutoComp():
- self.Refresh(False)
- # returns true if there are no contents at all and we're not
- # attached to any file
- def isUntouched(self):
- if self.fileName or (len(self.sp.lines) > 1) or \
- (len(self.sp.lines[0].text) > 0):
- return False
- else:
- return True
- def updateScreen(self, redraw = True, setCommon = True):
- self.adjustScrollBar()
- if setCommon:
- self.updateCommon()
- if redraw:
- self.Refresh(False)
- # update GUI elements shared by all scripts, like statusbar etc
- def updateCommon(self):
- cur = cfgGl.getType(self.sp.lines[self.sp.line].lt)
- if self.sp.tabMakesNew():
- tabNext = "%s" % cfgGl.getType(cur.newTypeTab).ti.name
- else:
- tabNext = "%s" % cfgGl.getType(cur.nextTypeTab).ti.name
- enterNext = cfgGl.getType(cur.newTypeEnter).ti.name
- page = self.sp.line2page(self.sp.line)
- pageCnt = self.sp.line2page(len(self.sp.lines) - 1)
- mainFrame.statusCtrl.SetValues(page, pageCnt, cur.ti.name, tabNext, enterNext)
- canUndo = self.sp.canUndo()
- canRedo = self.sp.canRedo()
- mainFrame.menuBar.Enable(ID_EDIT_UNDO, canUndo)
- mainFrame.menuBar.Enable(ID_EDIT_REDO, canRedo)
- mainFrame.toolBar.EnableTool(ID_EDIT_UNDO, canUndo)
- mainFrame.toolBar.EnableTool(ID_EDIT_REDO, canRedo)
- # apply per-script config
- def applyCfg(self, newCfg):
- self.sp.applyCfg(newCfg)
- self.refreshCache()
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- # apply global config
- def applyGlobalCfg(self, newCfgGl, writeCfg = True):
- global cfgGl
- oldCfgGl = cfgGl
- cfgGl = copy.deepcopy(newCfgGl)
- # if user has ventured from the old default directory, keep it as
- # the current one, otherwise set the new default as current.
- if misc.scriptDir == oldCfgGl.scriptDir:
- misc.scriptDir = cfgGl.scriptDir
- cfgGl.recalc()
- refreshGuiConfig()
- mainFrame.updateKbdCommands()
- for c in mainFrame.getCtrls():
- c.sp.cfgGl = cfgGl
- c.refreshCache()
- c.makeLineVisible(c.sp.line)
- c.adjustScrollBar()
- self.updateScreen()
- # in case tab colors have been changed
- mainFrame.tabCtrl.Refresh(False)
- mainFrame.statusCtrl.Refresh(False)
- mainFrame.noFSBtn.Refresh(False)
- mainFrame.toolBar.SetBackgroundColour(cfgGui.tabBarBgColor)
- if writeCfg:
- util.writeToFile(gd.confFilename, cfgGl.save(), mainFrame)
- mainFrame.checkFonts()
- def applyHeaders(self, newHeaders):
- self.sp.headers = newHeaders
- self.sp.markChanged()
- self.OnPaginate()
- # return an exportable, paginated Screenplay object, or None if for
- # some reason that's not possible / wanted. 'action' is the name of
- # the action, e.g. "export" or "print", that'll be done to the script,
- # and is used in dialogue with the user if needed.
- def getExportable(self, action):
- if cfgGl.checkOnExport:
- line = self.sp.findError(0)[0]
- if line != -1:
- if wx.MessageBox(
- "The script seems to contain errors.\n"
- "Are you sure you want to %s it?" % action, "Confirm",
- wx.YES_NO | wx.NO_DEFAULT, mainFrame) == wx.NO:
- return None
- sp = self.sp
- if sp.cfg.pdfRemoveNotes:
- sp = copy.deepcopy(self.sp)
- sp.removeElementTypes({screenplay.NOTE : None}, False)
- sp.paginate()
- return sp
- def OnEraseBackground(self, event):
- pass
- def OnSize(self, event):
- if misc.doDblBuf:
- size = self.GetClientSize()
- sb = wx.EmptyBitmap(size.width, size.height)
- old = getattr(self.__class__, "screenBuf", None)
- if (old == None) or (old.GetDepth() != sb.GetDepth()) or \
- (old.GetHeight() != sb.GetHeight()) or \
- (old.GetWidth() != sb.GetWidth()):
- self.__class__.screenBuf = sb
- self.makeLineVisible(self.sp.line)
- def OnLeftDown(self, event, mark = False):
- if not self.mouseSelectActive:
- self.sp.clearMark()
- self.updateScreen()
- pos = event.GetPosition()
- line, col = gd.vm.pos2linecol(self, pos.x, pos.y)
- self.mouseSelectActive = True
- if line is not None:
- self.sp.gotoPos(line, col, mark)
- self.updateScreen()
- def OnLeftUp(self, event):
- self.mouseSelectActive = False
- # to avoid phantom selections (Windows sends some strange events
- # sometimes), check if anything worthwhile is actually selected.
- cd = self.sp.getSelectedAsCD(False)
- if not cd or ((len(cd.lines) == 1) and (len(cd.lines[0].text) < 2)):
- self.sp.clearMark()
- def OnMotion(self, event):
- if event.LeftIsDown():
- self.OnLeftDown(event, mark = True)
- def OnRightDown(self, event):
- # No popup in the overview modes.
- if gd.viewMode in (VIEWMODE_OVERVIEW_SMALL, VIEWMODE_OVERVIEW_LARGE):
- return
- pos = event.GetPosition()
- line, col = gd.vm.pos2linecol(self, pos.x, pos.y)
- if self.sp.mark:
- m = mainFrame.rightClickMenuWithCut
- else:
- m = mainFrame.rightClickMenu
- if line is not None and (line != self.sp.line):
- self.sp.gotoPos(line, col, False)
- self.updateScreen()
- self.PopupMenu(m)
- def OnMouseWheel(self, event):
- if event.GetWheelRotation() > 0:
- delta = -cfgGl.mouseWheelLines
- else:
- delta = cfgGl.mouseWheelLines
- self.sp.setTopLine(self.sp.getTopLine() + delta)
- self.updateScreen()
- def OnScroll(self, event):
- pos = self.panel.scrollBar.GetThumbPosition()
- self.sp.setTopLine(pos)
- self.sp.clearAutoComp()
- self.updateScreen()
- def OnPaginate(self):
- self.sp.paginate()
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnAutoCompletionDlg(self):
- dlg = autocompletiondlg.AutoCompletionDlg(mainFrame,
- copy.deepcopy(self.sp.autoCompletion))
- if dlg.ShowModal() == wx.ID_OK:
- self.sp.autoCompletion = dlg.autoCompletion
- self.sp.markChanged()
- dlg.Destroy()
- def OnTitlesDlg(self):
- dlg = titlesdlg.TitlesDlg(mainFrame, copy.deepcopy(self.sp.titles),
- self.sp.cfg, cfgGl)
- if dlg.ShowModal() == wx.ID_OK:
- self.sp.titles = dlg.titles
- self.sp.markChanged()
- dlg.Destroy()
- def OnHeadersDlg(self):
- dlg = headersdlg.HeadersDlg(mainFrame,
- copy.deepcopy(self.sp.headers), self.sp.cfg, cfgGl,
- self.applyHeaders)
- if dlg.ShowModal() == wx.ID_OK:
- self.applyHeaders(dlg.headers)
- dlg.Destroy()
- def OnLocationsDlg(self):
- dlg = locationsdlg.LocationsDlg(mainFrame, copy.deepcopy(self.sp))
- if dlg.ShowModal() == wx.ID_OK:
- self.sp.locations = dlg.sp.locations
- self.sp.markChanged()
- dlg.Destroy()
- def OnSpellCheckerScriptDictionaryDlg(self):
- dlg = spellcheckcfgdlg.SCDictDlg(mainFrame,
- copy.deepcopy(self.sp.scDict), False)
- if dlg.ShowModal() == wx.ID_OK:
- self.sp.scDict = dlg.scDict
- self.sp.markChanged()
- dlg.Destroy()
- def OnWatermark(self):
- dlg = watermarkdlg.WatermarkDlg(
- mainFrame, self.sp, self.fileNameDisplay.replace(".trelby", ""))
- dlg.ShowModal()
- dlg.Destroy()
- def OnReportDialogueChart(self):
- self.sp.paginate()
- dialoguechart.genDialogueChart(mainFrame, self.sp)
- def OnReportCharacter(self):
- self.sp.paginate()
- characterreport.genCharacterReport(mainFrame, self.sp)
- def OnReportLocation(self):
- self.sp.paginate()
- locationreport.genLocationReport(mainFrame, self.sp)
- def OnReportScene(self):
- self.sp.paginate()
- scenereport.genSceneReport(mainFrame, self.sp)
- def OnReportScript(self):
- self.sp.paginate()
- scriptreport.genScriptReport(mainFrame, self.sp)
- def OnCompareScripts(self):
- if mainFrame.tabCtrl.getPageCount() < 2:
- wx.MessageBox("You need at least two scripts open to"
- " compare them.", "Error", wx.OK, mainFrame)
- return
- items = []
- for c in mainFrame.getCtrls():
- items.append(c.fileNameDisplay)
- dlg = misc.ScriptChooserDlg(mainFrame, items)
- sel1 = -1
- sel2 = -1
- if dlg.ShowModal() == wx.ID_OK:
- sel1 = dlg.sel1
- sel2 = dlg.sel2
- force = dlg.forceSameCfg
- dlg.Destroy()
- if sel1 == -1:
- return
- if sel1 == sel2:
- wx.MessageBox("You can't compare a script to itself.", "Error",
- wx.OK, mainFrame)
- return
- c1 = mainFrame.tabCtrl.getPage(sel1).ctrl
- c2 = mainFrame.tabCtrl.getPage(sel2).ctrl
- sp1 = c1.getExportable("compare")
- sp2 = c2.getExportable("compare")
- if not sp1 or not sp2:
- return
- if force:
- sp2 = copy.deepcopy(sp2)
- sp2.cfg = copy.deepcopy(sp1.cfg)
- sp2.reformatAll()
- sp2.paginate()
- s = sp1.compareScripts(sp2)
- if s:
- gutil.showTempPDF(s, cfgGl, mainFrame)
- else:
- wx.MessageBox("The scripts are identical.", "Results", wx.OK,
- mainFrame)
- def canBeClosed(self):
- if self.sp.isModified():
- if wx.MessageBox("The script has been modified. Are you sure\n"
- "you want to discard the changes?", "Confirm",
- wx.YES_NO | wx.NO_DEFAULT, mainFrame) == wx.NO:
- return False
- return True
- # page up (dir == -1) or page down (dir == 1) was pressed, handle it.
- # cs = CommandState.
- def pageCmd(self, cs, dir):
- if self.sp.acItems:
- cs.doAutoComp = cs.AC_KEEP
- self.sp.pageScrollAutoComp(dir)
- return
- texts, dpages = gd.vm.getScreen(self, False)
- # if user has scrolled with scrollbar so that cursor isn't seen,
- # just make cursor visible and don't move
- if not self.isLineVisible(self.sp.line, texts):
- gd.vm.makeLineVisible(self, self.sp.line, texts)
- cs.needsVisifying = False
- return
- self.sp.maybeMark(cs.mark)
- gd.vm.pageCmd(self, cs, dir, texts, dpages)
- def OnRevertScript(self):
- if self.fileName:
- if not self.canBeClosed():
- return
- self.loadFile(self.fileName)
- self.updateScreen()
- def OnUndo(self):
- self.sp.cmd("undo")
- self.sp.paginate()
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnRedo(self):
- self.sp.cmd("redo")
- self.sp.paginate()
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- # returns True if something was deleted
- def OnCut(self, doUpdate = True, doDelete = True, copyToClip = True):
- marked = self.sp.getMarkedLines()
- if not marked:
- return False
- cd = self.sp.getSelectedAsCD(doDelete)
- if copyToClip:
- mainFrame.clipboard = cd
- if doUpdate:
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- return doDelete
- def OnCopy(self):
- self.OnCut(doDelete = False)
- def OnCopySystem(self, formatted = False):
- cd = self.sp.getSelectedAsCD(False)
- if not cd:
- return
- tmpSp = screenplay.Screenplay(cfgGl)
- tmpSp.lines = cd.lines
- if formatted:
- # have to call paginate, otherwise generateText will not
- # process all the text
- tmpSp.paginate()
- s = tmpSp.generateText(False)
- else:
- s = util.String()
- for ln in tmpSp.lines:
- txt = ln.text
- if tmpSp.cfg.getType(ln.lt).export.isCaps:
- txt = util.upper(txt)
- s += txt + config.lb2str(ln.lb)
- s = str(s).replace("\n", os.linesep)
- if wx.TheClipboard.Open():
- wx.TheClipboard.UsePrimarySelection(False)
- wx.TheClipboard.Clear()
- wx.TheClipboard.AddData(wx.TextDataObject(s))
- wx.TheClipboard.Flush()
- wx.TheClipboard.Close()
- def OnPaste(self, clines = None):
- if not clines:
- cd = mainFrame.clipboard
- if not cd:
- return
- clines = cd.lines
- self.sp.paste(clines)
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnPasteSystemCb(self):
- s = ""
- if wx.TheClipboard.Open():
- wx.TheClipboard.UsePrimarySelection(False)
- df = wx.DataFormat(wx.DF_TEXT)
- if wx.TheClipboard.IsSupported(df):
- data = wx.TextDataObject()
- wx.TheClipboard.GetData(data)
- s = util.cleanInput(data.GetText())
- wx.TheClipboard.Close()
- s = util.fixNL(s)
- if len(s) == 0:
- return
- inLines = s.split("\n")
- # shouldn't be possible, but...
- if len(inLines) == 0:
- return
- lines = []
- for s in inLines:
- if s:
- lines.append(screenplay.Line(screenplay.LB_LAST,
- screenplay.ACTION, s))
- self.OnPaste(lines)
- def OnSelectScene(self):
- self.sp.cmd("selectScene")
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnSelectAll(self):
- self.sp.cmd("selectAll")
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnGotoScene(self):
- self.sp.paginate()
- self.clearAutoComp()
- scenes = self.sp.getSceneLocations()
- def validateFunc(s):
- if s in [x[0] for x in scenes]:
- return ""
- else:
- return "Invalid scene number."
- dlg = misc.TextInputDlg(mainFrame, "Enter scene number (%s - %s):" %\
- (scenes[0][0], scenes[-1][0]), "Goto scene", validateFunc)
- if dlg.ShowModal() == wx.ID_OK:
- for it in scenes:
- if it[0] == dlg.input:
- self.sp.line = it[1]
- self.sp.column = 0
- break
- # we need to refresh the screen in all cases because pagination
- # might have changed
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnGotoPage(self):
- self.sp.paginate()
- self.clearAutoComp()
- pages = self.sp.getPageNumbers()
- def validateFunc(s):
- if s in pages:
- return ""
- else:
- return "Invalid page number."
- dlg = misc.TextInputDlg(mainFrame, "Enter page number (%s - %s):" %\
- (pages[0], pages[-1]), "Goto page", validateFunc)
- if dlg.ShowModal() == wx.ID_OK:
- page = int(dlg.input)
- self.sp.line = self.sp.page2lines(page)[0]
- self.sp.column = 0
- # we need to refresh the screen in all cases because pagination
- # might have changed
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnInsertNbsp(self):
- self.OnKeyChar(util.MyKeyEvent(160))
- def OnFindNextError(self):
- self.clearAutoComp()
- line, msg = self.sp.findError(self.sp.line)
- if line != -1:
- self.sp.line = line
- self.sp.column = 0
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- else:
- msg = "No errors found."
- wx.MessageBox(msg, "Results", wx.OK, mainFrame)
- def OnFind(self):
- self.sp.clearMark()
- self.clearAutoComp()
- self.updateScreen()
- dlg = finddlg.FindDlg(mainFrame, self)
- dlg.ShowModal()
- dlg.saveState()
- dlg.Destroy()
- self.sp.clearMark()
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnSpellCheckerDlg(self):
- self.sp.clearMark()
- self.clearAutoComp()
- wasAtStart = self.sp.line == 0
- wx.BeginBusyCursor()
- if not spellcheck.loadDict(mainFrame):
- wx.EndBusyCursor()
- return
- sc = spellcheck.SpellChecker(self.sp, gd.scDict)
- found = sc.findNext()
- wx.EndBusyCursor()
- if not found:
- s = ""
- if not wasAtStart:
- s = "\n\n(Starting position was not at\n"\
- "the beginning of the script.)"
- wx.MessageBox("Spell checker found no errors." + s, "Results",
- wx.OK, mainFrame)
- return
- dlg = spellcheckdlg.SpellCheckDlg(mainFrame, self, sc, gd.scDict)
- dlg.ShowModal()
- if dlg.changedGlobalDict:
- gd.saveScDict()
- dlg.Destroy()
- self.sp.clearMark()
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnDeleteElements(self):
- # even though Screenplay.removeElementTypes does this as well, do
- # it here so that screen is cleared from the auto-comp box before
- # we open the dialog
- self.clearAutoComp()
- types = []
- for t in config.getTIs():
- types.append(misc.CheckBoxItem(t.name, False, t.lt))
- dlg = misc.CheckBoxDlg(mainFrame, "Delete elements", types,
- "Element types to delete:", True)
- ok = False
- if dlg.ShowModal() == wx.ID_OK:
- ok = True
- tdict = misc.CheckBoxItem.getClientData(types)
- dlg.Destroy()
- if not ok or (len(tdict) == 0):
- return
- self.sp.removeElementTypes(tdict, True)
- self.sp.paginate()
- self.makeLineVisible(self.sp.line)
- self.updateScreen()
- def OnSave(self):
- if self.fileName:
- self.saveFile(self.fileName)
- else:
- self.OnSaveScriptAs()
- def OnSaveScriptAs(self):
- if self.fileName:
- dDir = os.path.dirname(self.fileName)
- dFile = os.path.basename(self.fileName)
- else:
- dDir = misc.scriptDir
- dFile = u""
- dlg = wx.FileDialog(mainFrame, "Filename to save as",
- defaultDir = dDir,
- defaultFile = dFile,
- wildcard = "Trelby files (*.trelby)|*.trelby|All files|*",
- style = wx.SAVE | wx.OVERWRITE_PROMPT)
- if dlg.ShowModal() == wx.ID_OK:
- self.saveFile(dlg.GetPath())
- dlg.Destroy()
- def OnExportScript(self):
- sp = self.getExportable("export")
- if not sp:
- return
- dlg = wx.FileDialog(mainFrame, "Filename to export as",
- misc.scriptDir,
- wildcard = "PDF|*.pdf|"
- "RTF|*.rtf|"
- "Final Draft XML|*.fdx|"
- "HTML|*.html|"
- "Fountain|*.fountain|"
- "Formatted text|*.txt",
- style = wx.SAVE | wx.OVERWRITE_PROMPT)
- if dlg.ShowModal() == wx.ID_OK:
- misc.scriptDir = dlg.GetDirectory()
- choice = dlg.GetFilterIndex()
- if choice == 0:
- data = sp.generatePDF(True)
- suffix = ".pdf"
- elif choice == 1:
- data = sp.generateRTF()
- suffix = ".rtf"
- elif choice == 2:
- data = sp.generateFDX()
- suffix = ".fdx"
- elif choice == 3:
- data = self.getExportHtml(sp)
- suffix = ".html"
- elif choice == 4:
- data = sp.generateFountain()
- suffix = ".fountain"
- else:
- data = self.getExportText(sp)
- suffix = ".txt"
- fileName = util.ensureEndsIn(dlg.GetPath(), suffix)
- if data:
- util.writeToFile(fileName, data, mainFrame)
- dlg.Destroy()
- def OnPrint(self):
- sp = self.getExportable("print")
- if not sp:
- return
- s = sp.generatePDF(False)
- gutil.showTempPDF(s, cfgGl, mainFrame)
- def OnSettings(self):
- dlg = cfgdlg.CfgDlg(mainFrame, copy.deepcopy(cfgGl),
- self.applyGlobalCfg, True)
- if dlg.ShowModal() == wx.ID_OK:
- self.applyGlobalCfg(dlg.cfg)
- dlg.Destroy()
- def OnScriptSettings(self):
- dlg = cfgdlg.CfgDlg(mainFrame, copy.deepcopy(self.sp.cfg),
- self.applyCfg, False)
- if dlg.ShowModal() == wx.ID_OK:
- self.applyCfg(dlg.cfg)
- dlg.Destroy()
- def cmdAbort(self, cs):
- self.sp.abortCmd(cs)
- def cmdChangeToAction(self, cs):
- self.sp.toActionCmd(cs)
- def cmdChangeToCharacter(self, cs):
- self.sp.toCharacterCmd(cs)
- def cmdChangeToDialogue(self, cs):
- self.sp.toDialogueCmd(cs)
- def cmdChangeToNote(self, cs):
- self.sp.toNoteCmd(cs)
- def cmdChangeToParenthetical(self, cs):
- self.sp.toParenCmd(cs)
- def cmdChangeToScene(self, cs):
- self.sp.toSceneCmd(cs)
- def cmdChangeToShot(self, cs):
- self.sp.toShotCmd(cs)
- def cmdChangeToActBreak(self,cs):
- self.sp.toActBreakCmd(cs)
- def cmdChangeToTransition(self, cs):
- self.sp.toTransitionCmd(cs)
- def cmdDelete(self, cs):
- if not self.sp.mark:
- self.sp.deleteForwardCmd(cs)
- else:
- self.OnCut(doUpdate = False, copyToClip = False)
- def cmdDeleteBackward(self, cs):
- if not self.sp.mark:
- self.sp.deleteBackwardCmd(cs)
- else:
- self.OnCut(doUpdate = False, copyToClip = False)
- def cmdForcedLineBreak(self, cs):
- self.sp.insertForcedLineBreakCmd(cs)
- def cmdMoveDown(self, cs):
- self.sp.moveDownCmd(cs)
- def cmdMoveEndOfLine(self, cs):
- self.sp.moveLineEndCmd(cs)
- def cmdMoveEndOfScript(self, cs):
- self.sp.moveEndCmd(cs)
- def cmdMoveLeft(self, cs):
- self.sp.moveLeftCmd(cs)
- def cmdMovePageDown(self, cs):
- self.pageCmd(cs, 1)
- def cmdMovePageUp(self, cs):
- self.pageCmd(cs, -1)
- def cmdMoveRight(self, cs):
- self.sp.moveRightCmd(cs)
- def cmdMoveSceneDown(self, cs):
- self.sp.moveSceneDownCmd(cs)
- def cmdMoveSceneUp(self, cs):
- self.sp.moveSceneUpCmd(cs)
- def cmdMoveStartOfLine(self, cs):
- self.sp.moveLineStartCmd(cs)
- def cmdMoveStartOfScript(self, cs):
- self.sp.moveStartCmd(cs)
- def cmdMoveUp(self, cs):
- self.sp.moveUpCmd(cs)
- def cmdNewElement(self, cs):
- self.sp.splitElementCmd(cs)
- def cmdSetMark(self, cs):
- self.sp.setMarkCmd(cs)
- def cmdTab(self, cs):
- self.sp.tabCmd(cs)
- def cmdTabPrev(self, cs):
- self.sp.toPrevTypeTabCmd(cs)
- def cmdSpeedTest(self, cs):
- import undo
- self.speedTestUndo = []
- def testUndoFullCopy():
- u = undo.FullCopy(self.sp)
- u.setAfter(self.sp)
- self.speedTestUndo.append(u)
- def testReformatAll():
- self.sp.reformatAll()
- def testPaginate():
- self.sp.paginate()
- def testUpdateScreen():
- self.updateScreen()
- self.Update()
- def testAddRemoveChar():
- self.OnKeyChar(util.MyKeyEvent(ord("a")))
- self.OnKeyChar(util.MyKeyEvent(wx.WXK_BACK))
- def testDeepcopy():
- copy.deepcopy(self.sp)
- # contains (name, func) tuples
- tests = []
- for name, var in locals().iteritems():
- if callable(var):
- tests.append((name, var))
- tests.sort()
- count = 100
- print "-" * 20
- for name, func in tests:
- t = time.time()
- for i in xrange(count):
- func()
- t = time.time() - t
- print "%.5f seconds per %s" % (t / count, name)
- print "-" * 20
- # it's annoying having the program ask if you want to save after
- # running these tests, so pretend the script hasn't changed
- self.sp.markChanged(False)
- def cmdTest(self, cs):
- pass
- def OnKeyChar(self, ev):
- kc = ev.GetKeyCode()
- #print "kc: %d, ctrl/alt/shift: %d, %d, %d" %\
- # (kc, ev.ControlDown(), ev.AltDown(), ev.ShiftDown())
- cs = screenplay.CommandState()
- cs.mark = bool(ev.ShiftDown())
- scrollDirection = config.SCROLL_CENTER
- if not ev.ControlDown() and not ev.AltDown() and \
- util.isValidInputChar(kc):
- # WX2.6-FIXME: we should probably use GetUnicodeKey() (dunno
- # how to get around the isValidInputChar test in the preceding
- # line, need to test what GetUnicodeKey() returns on
- # non-input-character events)
- addChar = True
- # If there's something selected, either remove it, or clear selection.
- if self.sp.mark and cfgGl.overwriteSelectionOnInsert:
- if not self.OnCut(doUpdate = False, copyToClip = False):
- self.sp.clearMark()
- addChar = False
- if addChar:
- cs.char = chr(kc)
- if opts.isTest and (cs.char == "ĺ"):
- self.loadFile(u"sample.trelby")
- elif opts.isTest and (cs.char == "¤"):
- self.cmdTest(cs)
- elif opts.isTest and (cs.char == "˝"):
- self.cmdSpeedTest(cs)
- else:
- self.sp.addCharCmd(cs)
- else:
- cmd = mainFrame.kbdCommands.get(util.Key(kc,
- ev.ControlDown(), ev.AltDown(), ev.ShiftDown()).toInt())
- if cmd:
- scrollDirection = cmd.scrollDirection
- if cmd.isMenu:
- getattr(mainFrame, "On" + cmd.name)()
- return
- else:
- getattr(self, "cmd" + cmd.name)(cs)
- else:
- ev.Skip()
- return
- self.sp.cmdPost(cs)
- if cfgGl.paginateInterval > 0:
- now = time.time()
- if (now - self.sp.lastPaginated) >= cfgGl.paginateInterval:
- self.sp.paginate()
- cs.needsVisifying = True
- if cs.needsVisifying:
- self.makeLineVisible(self.sp.line, scrollDirection)
- self.updateScreen()
- def OnPaint(self, event):
- #ldkjfldsj = util.TimerDev("paint")
- ls = self.sp.lines
- if misc.doDblBuf:
- dc = wx.BufferedPaintDC(self, self.screenBuf)
- else:
- dc = wx.PaintDC(self)
- size = self.GetClientSize()
- marked = self.sp.getMarkedLines()
- lineh = gd.vm.getLineHeight(self)
- posX = -1
- cursorY = -1
- # auto-comp FontInfo
- acFi = None
- # key = font, value = ([text, ...], [(x, y), ...], [wx.Colour, ...])
- texts = {}
- # lists of underline-lines to draw, one for normal text and one
- # for header texts. list objects are (x, y, width) tuples.
- ulines = []
- ulinesHdr = []
- strings, dpages = gd.vm.getScreen(self, True, True)
- dc.SetBrush(cfgGui.workspaceBrush)
- dc.SetPen(cfgGui.workspacePen)
- dc.DrawRectangle(0, 0, size.width, size.height)
- dc.SetPen(cfgGui.tabBorderPen)
- dc.DrawLine(0,0,0,size.height)
- if not dpages:
- # draft mode; draw an infinite page
- lx = util.clamp((size.width - self.pageW) // 2, 0)
- rx = lx + self.pageW
- dc.SetBrush(cfgGui.textBgBrush)
- dc.SetPen(cfgGui.textBgPen)
- dc.DrawRectangle(lx, 5, self.pageW, size.height - 5)
- dc.SetPen(cfgGui.pageBorderPen)
- dc.DrawLine(lx, 5, lx, size.height)
- dc.DrawLine(rx, 5, rx, size.height)
- else:
- dc.SetBrush(cfgGui.textBgBrush)
- dc.SetPen(cfgGui.pageBorderPen)
- for dp in dpages:
- dc.DrawRectangle(dp.x1, dp.y1, dp.x2 - dp.x1 + 1,
- dp.y2 - dp.y1 + 1)
- dc.SetPen(cfgGui.pageShadowPen)
- for dp in dpages:
- # + 2 because DrawLine doesn't draw to end point but stops
- # one pixel short...
- dc.DrawLine(dp.x1 + 1, dp.y2 + 1, dp.x2 + 1, dp.y2 + 1)
- dc.DrawLine(dp.x2 + 1, dp.y1 + 1, dp.x2 + 1, dp.y2 + 2)
- for t in strings:
- i = t.line
- y = t.y
- fi = t.fi
- fx = fi.fx
- if i != -1:
- l = ls[i]
- if l.lt == screenplay.NOTE:
- dc.SetPen(cfgGui.notePen)
- dc.SetBrush(cfgGui.noteBrush)
- nx = t.x - 5
- nw = self.sp.cfg.getType(l.lt).width * fx + 10
- dc.DrawRectangle(nx, y, nw, lineh)
- dc.SetPen(cfgGui.textPen)
- util.drawLine(dc, nx - 1, y, 0, lineh)
- util.drawLine(dc, nx + nw, y, 0, lineh)
- if self.sp.isFirstLineOfElem(i):
- util.drawLine(dc, nx - 1, y - 1, nw + 2, 0)
- if self.sp.isLastLineOfElem(i):
- util.drawLine(dc, nx - 1, y + lineh,
- nw + 2, 0)
- if marked and self.sp.isLineMarked(i, marked):
- c1, c2 = self.sp.getMarkedColumns(i, marked)
- dc.SetPen(cfgGui.selectedPen)
- dc.SetBrush(cfgGui.selectedBrush)
- dc.DrawRectangle(t.x + c1 * fx, y, (c2 - c1 + 1) * fx,
- lineh)
- if mainFrame.showFormatting:
- dc.SetPen(cfgGui.bluePen)
- util.drawLine(dc, t.x, y, 0, lineh)
- extraIndent = 1 if self.sp.needsExtraParenIndent(i) else 0
- util.drawLine(dc,
- t.x + (self.sp.cfg.getType(l.lt).width - extraIndent) * fx,
- y, 0, lineh)
- dc.SetTextForeground(cfgGui.redColor)
- dc.SetFont(cfgGui.fonts[pml.NORMAL].font)
- dc.DrawText(config.lb2char(l.lb), t.x - 10, y)
- if not dpages:
- if cfgGl.pbi == config.PBI_REAL_AND_UNADJ:
- if self.sp.line2pageNoAdjust(i) != \
- self.sp.line2pageNoAdjust(i + 1):
- dc.SetPen(cfgGui.pagebreakNoAdjustPen)
- util.drawLine(dc, 0, y + lineh - 1,
- size.width, 0)
- if cfgGl.pbi in (config.PBI_REAL,
- config.PBI_REAL_AND_UNADJ):
- thisPage = self.sp.line2page(i)
- if thisPage != self.sp.line2page(i + 1):
- dc.SetPen(cfgGui.pagebreakPen)
- util.drawLine(dc, 0, y + lineh - 1,
- size.width, 0)
- if i == self.sp.line:
- posX = t.x
- cursorY = y
- acFi = fi
- dc.SetPen(cfgGui.cursorPen)
- dc.SetBrush(cfgGui.cursorBrush)
- dc.DrawRectangle(t.x + self.sp.column * fx, y, fx, fi.fy)
- if len(t.text) != 0:
- tl = texts.get(fi.font)
- if tl == None:
- tl = ([], [], [])
- texts[fi.font] = tl
- tl[0].append(t.text)
- tl[1].append((t.x, y))
- if t.line != -1:
- if cfgGl.useCustomElemColors:
- tl[2].append(cfgGui.lt2textColor(ls[t.line].lt))
- else:
- tl[2].append(cfgGui.textColor)
- else:
- tl[2].append(cfgGui.textHdrColor)
- if t.isUnderlined:
- if t.line != -1:
- uli = ulines
- else:
- uli = ulinesHdr
- uli.append((t.x, y + lineh - 1,
- len(t.text) * fx - 1))
- if ulines:
- dc.SetPen(cfgGui.textPen)
- for ul in ulines:
- util.drawLine(dc, ul[0], ul[1], ul[2], 0)
- if ulinesHdr:
- dc.SetPen(cfgGui.textHdrPen)
- for ul in ulinesHdr:
- util.drawLine(dc, ul[0], ul[1], ul[2], 0)
- for tl in texts.iteritems():
- gd.vm.drawTexts(self, dc, tl)
- if self.sp.acItems and (cursorY > 0):
- self.drawAutoComp(dc, posX, cursorY, acFi)
- def drawAutoComp(self, dc, posX, cursorY, fi):
- ac = self.sp.acItems
- asel = self.sp.acSel
- offset = 5
- selBleed = 2
- # scroll bar width
- sbw = 10
- size = self.GetClientSize()
- dc.SetFont(fi.font)
- show = min(self.sp.acMax, len(ac))
- doSbw = show < len(ac)
- startPos = (asel // show) * show
- endPos = min(startPos + show, len(ac))
- if endPos == len(ac):
- startPos = max(0, endPos - show)
- w = 0
- for i in range(len(ac)):
- tw = dc.GetTextExtent(ac[i])[0]
- w = max(w, tw)
- w += offset * 2
- h = show * fi.fy + offset * 2
- itemW = w - offset * 2 + selBleed * 2
- if doSbw:
- w += sbw + offset * 2
- sbh = h - offset * 2 + selBleed * 2
- posY = cursorY + fi.fy + 5
- # if the box doesn't fit on the screen in the normal position, put
- # it above the current line. if it doesn't fit there either,
- # that's just too bad, we don't support window sizes that small.
- if (posY + h) > size.height:
- posY = cursorY - h - 1
- dc.SetPen(cfgGui.autoCompPen)
- dc.SetBrush(cfgGui.autoCompBrush)
- dc.DrawRectangle(posX, posY, w, h)
- dc.SetTextForeground(cfgGui.autoCompFgColor)
- for i in range(startPos, endPos):
- if i == asel:
- dc.SetPen(cfgGui.autoCompRevPen)
- dc.SetBrush(cfgGui.autoCompRevBrush)
- dc.SetTextForeground(cfgGui.autoCompBgColor)
- dc.DrawRectangle(posX + offset - selBleed,
- posY + offset + (i - startPos) * fi.fy - selBleed,
- itemW,
- fi.fy + selBleed * 2)
- dc.SetTextForeground(cfgGui.autoCompBgColor)
- dc.SetPen(cfgGui.autoCompPen)
- dc.SetBrush(cfgGui.autoCompBrush)
- dc.DrawText(ac[i], posX + offset, posY + offset +
- (i - startPos) * fi.fy)
- if i == asel:
- dc.SetTextForeground(cfgGui.autoCompFgColor)
- if doSbw:
- dc.SetPen(cfgGui.autoCompPen)
- dc.SetBrush(cfgGui.autoCompRevBrush)
- util.drawLine(dc, posX + w - offset * 2 - sbw,
- posY, 0, h)
- dc.DrawRectangle(posX + w - offset - sbw,
- posY + offset - selBleed + int((float(startPos) /
- len(ac)) * sbh),
- sbw, int((float(show) / len(ac)) * sbh))
- class MyFrame(wx.Frame):
- def __init__(self, parent, id, title):
- wx.Frame.__init__(self, parent, id, title, name = "Trelby")
- if misc.isUnix:
- # automatically reaps zombies
- signal.signal(signal.SIGCHLD, signal.SIG_IGN)
- self.clipboard = None
- self.showFormatting = False
- self.SetSizeHints(gd.cvars.getMin("width"),
- gd.cvars.getMin("height"))
- self.MoveXY(gd.posX, gd.posY)
- self.SetSize(wx.Size(gd.width, gd.height))
- util.removeTempFiles(misc.tmpPrefix)
- self.mySetIcons()
- self.allocIds()
- fileMenu = wx.Menu()
- fileMenu.Append(ID_FILE_NEW, "&New\tCTRL-N")
- fileMenu.Append(ID_FILE_OPEN, "&Open...\tCTRL-O")
- fileMenu.Append(ID_FILE_SAVE, "&Save\tCTRL-S")
- fileMenu.Append(ID_FILE_SAVE_AS, "Save &As...")
- fileMenu.Append(ID_FILE_CLOSE, "&Close\tCTRL-W")
- fileMenu.Append(ID_FILE_REVERT, "&Revert")
- fileMenu.AppendSeparator()
- fileMenu.Append(ID_FILE_IMPORT, "&Import...")
- fileMenu.Append(ID_FILE_EXPORT, "&Export...")
- fileMenu.AppendSeparator()
- fileMenu.Append(ID_FILE_PRINT, "&Print (via PDF)\tCTRL-P")
- fileMenu.AppendSeparator()
- tmp = wx.Menu()
- tmp.Append(ID_SETTINGS_CHANGE, "&Change...")
- tmp.AppendSeparator()
- tmp.Append(ID_SETTINGS_LOAD, "Load...")
- tmp.Append(ID_SETTINGS_SAVE_AS, "Save as...")
- tmp.AppendSeparator()
- tmp.Append(ID_SETTINGS_SC_DICT, "&Spell checker dictionary...")
- settingsMenu = tmp
- fileMenu.AppendMenu(ID_FILE_SETTINGS, "Se&ttings", tmp)
- fileMenu.AppendSeparator()
- # "most recently used" list comes in here
- fileMenu.AppendSeparator()
- fileMenu.Append(ID_FILE_EXIT, "E&xit\tCTRL-Q")
- …
Large files files are truncated, but you can click here to view the full file