def updateDisplay(self, tweak, slotIndex = 0, highlight = False) : if not self.updateable : # In the middle of a mouse move - don't regenerate (ie, delete) anything. return jsonResult = self.app.runGraphiteOverString(self.app.fontFileName, None, tweak.text, 10, #self.font.size, tweak.rtl, tweak.feats, tweak.lang, tweak.width) if jsonResult != False : self.json = jsonResult else : print "No Graphite result" self.json = None self.run = Run(tweak.rtl) if self.json : self.run.addSlots(self.json[-1]['output']) self.runView.loadRun(self.run, self.font, resize = False) if not self.runloaded : try : # Don't switch to the Slot tab, but just update the contents. self.runView.slotSelected.connect(self.app.tab_slot.changeData) self.runView.glyphSelected.connect(self.app.glyphAttrib.changeData) self.runloaded = True except : print "Selection connection failed" # Bring the Tweak tab to the front self.app.tab_results.setCurrentWidget(self.app.tab_tweakview) if highlight : self.highlightSlot(slotIndex)
def initializeLayout(self, xmlFile): vsplitter = QtGui.QSplitter() # allows sizing of results view vsplitter.setOrientation(QtCore.Qt.Vertical) vsplitter.setContentsMargins(0, 0, 0, 0) vsplitter.setHandleWidth(4) self.layout.addWidget(vsplitter) self.widget = QtGui.QWidget(vsplitter) vbox = QtGui.QVBoxLayout(self.widget) # MatchList + input control vbox.setContentsMargins(*Layout.buttonMargins) vbox.setSpacing(Layout.buttonSpacing) hbox = QtGui.QHBoxLayout( ) # just in case we want to add more buttons here vbox.addLayout(hbox) plabel = QtGui.QLabel("Search pattern:") hbox.addWidget(plabel) hbox.addStretch() hbox.setContentsMargins(*Layout.buttonMargins) hbox.setSpacing(Layout.buttonSpacing) searchGo = QtGui.QToolButton(self.widget) searchGo.setDefaultAction(self.aSearchGo) hbox.addWidget(searchGo) self.patternEdit = TextEditReturn(self.widget, self) self.patternEdit.setMaximumHeight(Layout.runEditHeight) vbox.addWidget(self.patternEdit) vbox.addSpacing(5) self.matchList = MatchList(self.app, self.font, xmlFile, self) #self.matchList.itemClicked.connect(self.itemClicked) vbox.addWidget(self.matchList) # line below MatchList line = QtGui.QFrame(self.widget) line.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Raised) line.setLineWidth(2) vbox.addWidget(line) vbox.addSpacing(2) # input control self.runEdit = QtGui.QPlainTextEdit(self.widget) self.runEdit.setMaximumHeight(Layout.runEditHeight) vbox.addWidget(self.runEdit) # control buttons hbox = QtGui.QHBoxLayout() vbox.addLayout(hbox) hbox.setContentsMargins(*Layout.buttonMargins) hbox.setSpacing(Layout.buttonSpacing) runGo = QtGui.QToolButton(self.widget) runGo.setDefaultAction(self.aRunGo) hbox.addWidget(runGo) hbox.addStretch() self.runRtl = QtGui.QCheckBox("RTL", self.widget) self.runRtl.setChecked(True if configintval(self.app.config, 'main', 'defaultrtl') else False) self.runRtl.setToolTip("Process text right to left") hbox.addWidget(self.runRtl) self.runFeats = QtGui.QToolButton(self.widget) #self.runFeats.setDefaultAction(self.aRunFeats) hbox.addWidget(self.runFeats) #runAdd = QtGui.QToolButton(self.widget) #runAdd.setDefaultAction(self.aRunAdd) #hbox.addWidget(runAdd) # test output self.run = Run(self.font, self.runRtl.isChecked()) self.runView = RunView(self.font) self.runView.gview.resize(self.runView.gview.width(), self.font.pixrect.height() + 5) vsplitter.addWidget(self.runView.gview)
class TweakView(QtGui.QWidget) : # tweaker => Tweaker # Communication with the Glyph and Slot tabs slotSelected = QtCore.Signal(DataObj, ModelSuper) glyphSelected = QtCore.Signal(DataObj, ModelSuper) @QtCore.Slot(DataObj, ModelSuper) def changeSlot(self, data, model) : self.slotSelected.emit(data, model) #self.tweaker.changeSlot(...) @QtCore.Slot(DataObj, ModelSuper) def changeGlyph(self, data, model) : self.glyphSelected.emit(data, model) if self.currsel and self.currsel != model : self.currsel.clearSelected() self.currsel = model def __init__(self, fontname, size, app = None, parent = None) : super(TweakView, self).__init__(parent) self.app = app self.runloaded = False self.tweaker = None # set later self.fontname = fontname self.setFont(size) if self.fontname and self.fontname != "": self._createRunView() self.currSlotIndex = -1 self.updateable = True def _createRunView(self) : layout = QtGui.QVBoxLayout(self) self.runView = TweakableRunView(self.font, run = None, parent = self) self.runView.gview.resize(self.runView.gview.width(), (self.font.pixrect.height() + 5)) layout.addWidget(self.runView.gview) # Ignore runView.tview - text view that shows the glyph names. def updateFromConfigSettings(self, fontname, config) : self.fontname = fontname self.setFont(configintval(config, 'ui', 'tweakglyphsize')) self._createRunView() def changeFontSize(self, size) : self.setFont(size) def setFont(self, size) : if self.fontname and self.fontname != "": fontfile = str(self.fontname) self.font = GraideFont() self.font.loadFont(fontfile, size) self.font.loadEmptyGlyphs() def setTweaker(self, tweaker) : # The Tweaker has all the data in it, which is needed to display the glyphs at their # adjusted offsets. self.tweaker = tweaker def setUpdateable(self, state) : self.updateable = state def updateDisplay(self, tweak, slotIndex = 0, highlight = False) : if not self.updateable : # In the middle of a mouse move - don't regenerate (ie, delete) anything. return jsonResult = self.app.runGraphiteOverString(self.app.fontFileName, None, tweak.text, 10, #self.font.size, tweak.rtl, tweak.feats, tweak.lang, tweak.width) if jsonResult != False : self.json = jsonResult else : print "No Graphite result" self.json = None self.run = Run(tweak.rtl) if self.json : self.run.addSlots(self.json[-1]['output']) self.runView.loadRun(self.run, self.font, resize = False) if not self.runloaded : try : # Don't switch to the Slot tab, but just update the contents. self.runView.slotSelected.connect(self.app.tab_slot.changeData) self.runView.glyphSelected.connect(self.app.glyphAttrib.changeData) self.runloaded = True except : print "Selection connection failed" # Bring the Tweak tab to the front self.app.tab_results.setCurrentWidget(self.app.tab_tweakview) if highlight : self.highlightSlot(slotIndex) # otherwise done in Tweaker::tweakChanged # end of updateDisplay def highlightSlot(self, slotIndex) : self.currSlotIndex = slotIndex self.runView.glyphClicked(None, slotIndex, False) # def snagKeyPress(self, event) : # self.runView.keyPressEvent(event) # self.runView.snagFocus() #end of class TweakView
def loadResults(self, font, jsonall, gdx = None, rtl = False, fontIsRtl = False) : self.rulesJson = [] self.collFixJson = [] self.selectRow(-1) self.currsel = None if jsonall : json = jsonall[-1] ###json = jsonall[0] else : json = {'passes' : [], 'output' : [] } # empty output num = len(json['passes']) + 1 # 0 = Init count = num runDir = "rtl" if rtl else "ltr" fontDir = "rtl" if fontIsRtl else "ltr" # JSON format: # 'passes': [ # 0: # 'id' : 1 # 'rundir' : 'ltr' # 'slotsdir' : 'rtl' # 'slots' : <initial data> # 'rules' : <rules run by pass 1> # 1: # 'id' : 2 # 'rundir' : 'ltr' # 'slotsdir' : 'rtl' # 'slots' : <output of pass 1> # 'rules' : <rules run by pass 2> # ... # N-1: # 'id' : N # 'slots' : <output of pass N-1> # 'rules' : <rules run by pass N> # ] # 'outputdir' : 'rtl' # 'output': <output of pass N> # Also note that pass IDs in JSON do not match pass indices in GDX when there is # a bidi pass. In JSON, the pass ID of a bidi pass in json is -1, with the # first positioning pass index = last subs pass + 1. (More accurately, -1 indicates # the INPUT to the bidi pass.) In GDX, pass indices include the bidi pass, so first # positioning pass index = last subs pass + 2. # # Best thing to do is to more or less ignore the JSON pass IDs, since they are not reliable. if count != self.rowCount() : if count < self.rowCount() : self.runViews = self.runViews[:count] self.setRowCount(count) w = 0 wt = 0 for j in range(num) : # Process the output of pass J which = input to pass J+1; the rules are listed with pass J-1. # Note for J = 0 there are no rules. run = Run(font, rtl) highlight = False if j < num - 1 : run.addSlots(json['passes'][j]['slots']) # output of pass J #passid = int(json['passes'][j]['id']) - 1 else : run.addSlots(json['output']) # final output #passid = j #print "*** in loadResults: pass",j,"***" #run.printDebug() if j == 0 : pname = "Init" if runDir != fontDir : pname += " (LTR) " if fontIsRtl else " (RTL) " # direction reversed self.rulesJson.append(None) self.collFixJson.append(None) self.dirLabels.append("") self.flipFlags.append(False) else : pname = "Pass: %d" % j if j < num - 1 : slotDir = json['passes'][j]['slotsdir'] passDir = json['passes'][j-1]['passdir'] # where the rules come from else : slotDir = json['outputdir'] passDir = json['passes'][j-1]['passdir'] # where the rules come from #print j,"- slot dir=",slotDir, "; pass dir=",passDir if slotDir != passDir : run.reverseDirection() #run.printDebug() flipFlag = False dirLabel = "" if gdx : pname += " - " + gdx.passTypes[j-1] # j-1 because Init is not in the passTypes array if passDir != fontDir : dirLabel = " (LTR)" if passDir == "ltr" else " (RTL)" # direction reversed pname += dirLabel + " " flipFlag = True self.flipFlags.append(flipFlag) self.dirLabels.append(dirLabel) if json['passes'][j-1].has_key('rules') and len(json['passes'][j-1]['rules']) : highlight = "active" self.rulesJson.append(json['passes'][j-1]['rules']) # rules are stored with previous pass :-( else : self.rulesJson.append(None) # Add rows for any collisions, if this is such a pass. if 1 < j and j < num and gdx and gdx.passTypes[j-1] == "positioning": thisSlots = json['output'] if (j == num - 1) else json['passes'][j]['slots'] if self.hasCollisionFixedSlot(json['passes'][j-1]['slots'], thisSlots) : highlight = "semi-active" if json['passes'][j-1].has_key('collisions') : self.collFixJson.append(json['passes'][j-1]['collisions']) else : self.collFixJson.append(None) # if passid == -1, NEXT pass is bidi pass (neww, newt) = self.addRun(font, run, pname, j, highlight = highlight) w = max(w, neww) wt = max(wt, newt) self.finishLoad(w, wt) # set column widths, etc