def on_addLexerButton_clicked(self):
     """
     Private slot to add the lexer association displayed to the list.
     """
     ext = self.editorFileExtEdit.text()
     if ext.startsWith(self.extsep):
         ext.replace(self.extsep, "")
     lexer = self.editorLexerCombo.currentText()
     if lexer in self.extras:
         pygmentsLexer = self.pygmentsLexerCombo.currentText()
         if pygmentsLexer.isEmpty():
             lexer = pygmentsLexer
         else:
             lexer = QString("Pygments|%1").arg(pygmentsLexer)
     if not ext.isEmpty() and not lexer.isEmpty():
         itmList = self.editorLexerList.findItems(\
             ext, Qt.MatchFlags(Qt.MatchExactly), 0)
         if itmList:
             index = self.editorLexerList.indexOfTopLevelItem(itmList[0])
             itm = self.editorLexerList.takeTopLevelItem(index)
             del itm
         itm = QTreeWidgetItem(self.editorLexerList, 
             QStringList() << ext << lexer)
         self.editorFileExtEdit.clear()
         self.editorLexerCombo.setCurrentIndex(0)
         self.pygmentsLexerCombo.setCurrentIndex(0)
         self.editorLexerList.sortItems(self.editorLexerList.sortColumn(), 
             self.editorLexerList.header().sortIndicatorOrder())
    def on_mEndMarkerToolButton_clicked(self):
        if self.timeStart != 0:
            self.timeEnd = time.time()
            print self.timeEnd
            if self.timeEnd - self.timeStart <= 2:
                self.timeStart = 0
                return
        s = QSettings()
        openDir = QString()

        if (not self.mEndMarkerLineEdit.text().isEmpty()):
            fi = QFileInfo(self.mEndMarkerLineEdit.text())
            openDir = fi.dir().absolutePath()

        if (openDir.isEmpty()):
            openDir = s.value("/UI/lastComposerMarkerDir",
                              QDir.homePath()).toString()

        svgFileName = QFileDialog.getOpenFileName(
            self, QString("End marker svg file"), openDir)
        if (not svgFileName.isNull()):
            fileInfo = QFileInfo(svgFileName)
            s.setValue("/UI/lastComposerMarkerDir", fileInfo.absolutePath())
            self.mArrow.beginCommand(QString("Arrow end marker"))
            self.mEndMarkerLineEdit.setText(svgFileName)
            self.mArrow.endCommand()
        self.timeStart = time.time()
Beispiel #3
0
 def __init__(self, values, target, parent=None):
     super(KeyButton, self).__init__(parent)
     # Save the target QLineEdit
     self.target = target
     # save the dictionary of values for each modifier state, and set up
     # parallel dicts of keytop display QStrings and tooltip QStrings.
     # Where a value is None, convert it to an empty QString.
     self.values = values
     self.glyphs = {}
     self.tooltips = {}
     for mode in self.values:
         py_string = self.values[mode]
         if py_string is not None:
             self.glyphs[mode] = QString(py_string)
             tip = QString()
             # A value can have multiple chars, put all in tooltip
             for uc in py_string:
                 if not tip.isEmpty(): tip.append(u'+')
                 tip.append(unicodedata.name(uc))
             self.tooltips[mode] = tip
         else:  # value is None, use empty strings
             self.glyphs[mode] = QString()
             self.tooltips[mode] = QString()
     # set constant properties
     self.setAlignment(Qt.AlignCenter)  # both horizontal and vertical
     self.setTextInteractionFlags(Qt.NoTextInteraction)
     self.setScaledContents(True)
     # Make our look square, at least 20px, but able to grow
     self.setMinimumSize(QSize(20, 20))
     self.setSizePolicy(SPOLICY)
     self.setFrameStyle(QFrame.Panel)
     self.setFrameShadow(QFrame.Raised)
     self.setLineWidth(3)
     # initialize with a glyph
     self.shift(0)
Beispiel #4
0
    def formatAssignValue(self, fieldName, value, upper):
        if self.type() == ("", None) or fieldName.isEmpty():
            return "1 = 1"

        isText = False
        if value.type() == "string" or value.type() == "stringlist":
            isText = True

        formatV = QString()
        if value.type() == "int" or value.type() == "uint" or value.type(
        ) == "double":
            formatV = value.toString()
        else:
            formatV = "'" + value.toString() + "'"

        #print("FORMATV es %s, %s y value era %s" % (formatV, type(formatV), value.toString()))

        if formatV.isEmpty():
            return "1 = 1"

        if upper and isText:
            fName = QString("upper(" + fieldName + ")")
        else:
            fName = QString(fieldName)

        return QString(fName + " = " + formatV)
Beispiel #5
0
 def __init__(self, values, target, parent=None):
     super(KeyButton, self).__init__(parent)
     # Save the target QLineEdit
     self.target = target
     # save the dictionary of values for each modifier state, and set up
     # parallel dicts of keytop display QStrings and tooltip QStrings.
     # Where a value is None, convert it to an empty QString.
     self.values = values
     self.glyphs = {}
     self.tooltips = {}
     for mode in self.values :
         py_string = self.values[mode]
         if py_string is not None:
             self.glyphs[mode] = QString(py_string)
             tip = QString()
             # A value can have multiple chars, put all in tooltip
             for uc in py_string :
                 if not tip.isEmpty(): tip.append(u'+')
                 tip.append(unicodedata.name(uc))
             self.tooltips[mode] = tip
         else : # value is None, use empty strings
             self.glyphs[mode] = QString()
             self.tooltips[mode] = QString()
     # set constant properties
     self.setAlignment(Qt.AlignCenter) # both horizontal and vertical
     self.setTextInteractionFlags(Qt.NoTextInteraction)
     self.setScaledContents(True)
     # Make our look square, at least 20px, but able to grow
     self.setMinimumSize(QSize(20,20))
     self.setSizePolicy(SPOLICY)
     self.setFrameStyle(QFrame.Panel)
     self.setFrameShadow(QFrame.Raised)
     self.setLineWidth(3)
     # initialize with a glyph
     self.shift(0)
Beispiel #6
0
 def setFilter(self, f):
     if not self.cursor_:
         return
     previousF = QString(self.cursor_.mainFilter())
     newF = QString(None)
     if previousF.isEmpty():
         newF = f
     elif previousF.contains(f):
         return
     else:
         newF = previousF + " AND " + f
     self.cursor_.setMainFilter(newF)
Beispiel #7
0
 def setFilter(self, f):
     if not self.cursor_:
         return
     previousF = QString(self.cursor_.mainFilter())
     newF = QString(None)
     if previousF.isEmpty():
         newF = f
     elif previousF.contains(f):
         return
     else:
         newF = previousF + " AND " + f
     self.cursor_.setMainFilter(newF)
 def __workingDirectory(path_):
     """
     Private function to determine working directory for the file dialog.
     
     @param path_ path of the intended working directory (string or QString)
     @return calculated working directory (QString)
     """
     path = QString(path_)
     if not path.isEmpty():
         info = QFileInfo(path)
         if info.exists() and info.isDir():
             return info.absoluteFilePath()
         return info.absolutePath()
     return QDir.currentPath()
class E4LineEdit(QLineEdit):
    """
    Class implementing a line edit widget showing some inactive text.
    """
    def __init__(self, parent = None, inactiveText = QString()):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        @param inactiveText text to be shown on inactivity (string or QString)
        """
        QLineEdit.__init__(self, parent)
        
        self.__inactiveText = QString(inactiveText)
    
    def inactiveText(self):
        """
        Public method to get the inactive text.
        
        return inactive text (QString)
        """
        return QString(self.__inactiveText)
    
    def setInactiveText(self, inactiveText):
        """
        Public method to set the inactive text.
        
        @param inactiveText text to be shown on inactivity (string or QString)
        """
        self.__inactiveText = QString(inactiveText)
        self.update()
    
    def paintEvent(self, evt):
        """
        Protected method handling a paint event.
        
        @param evt reference to the paint event (QPaintEvent)
        """
        QLineEdit.paintEvent(self, evt)
        if self.text().isEmpty() and \
           not self.__inactiveText.isEmpty() and \
           not self.hasFocus():
            panel = QStyleOptionFrameV2()
            self.initStyleOption(panel)
            textRect = \
                self.style().subElementRect(QStyle.SE_LineEditContents, panel, self)
            textRect.adjust(2, 0, 0, 0)
            painter = QPainter(self)
            painter.setPen(self.palette().brush(QPalette.Disabled, QPalette.Text).color())
            painter.drawText(textRect, Qt.AlignLeft | Qt.AlignVCenter, self.__inactiveText)
Beispiel #10
0
 def parameterValues(self):
     self.widget.selectAll()
     items = self.widget.selectedItems()
     first = True
     var = QString()
     for item in items:
         if first:
             var.append(item.text())
             first = False
         else:
             var.append("%s%s" % (self.sep, item.text()))
     if var.isEmpty():
         raise Exception("Error: Insufficient number of input variables")
     params = {self.id:var}
     return params
Beispiel #11
0
 def insertMarkers(self):
     # Copy the text and if it is empty, complain and exit.
     qi = QString(self.insertText.text())
     if qi.isEmpty():
         pqMsgs.warningMsg("No insert text specified")
         return
     # See how many pages are involved: all the ones that aren't marked skip
     n = 0
     for i in range(IMC.pageTable.size()):
         if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip:
             n += 1
     if n == 0:  # page table empty or all rows marked skip
         pqMsgs.warningMsg("No pages to give folios to")
         return
     m = "Insert this string at the top of {0} pages?".format(n)
     b = pqMsgs.okCancelMsg(QString(m), pqMsgs.trunc(qi, 35))
     if b:
         # Convert any '\n' in the text to the QT line delimiter char
         # we do this in the copy so the lineEdit text doesn't change
         qi.replace(QString(u'\\n'), QString(IMC.QtLineDelim))
         # get a cursor on the edit document
         tc = QTextCursor(IMC.editWidget.textCursor())
         tc.beginEditBlock()  # start single undoable operation
         # Working from the end of the document backward, go to the
         # top of each page and insert the string
         for i in reversed(range(IMC.pageTable.size())):
             if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip:
                 # Note the page's start position and set our work cursor to it
                 pos = IMC.pageTable.getCursor(i).position()
                 tc.setPosition(pos)
                 # Make a copy of the insert string replacing %f with this folio
                 f = IMC.pageTable.getDisplay(i)
                 qf = QString(qi)
                 qf.replace(QString(u'%f'), f, Qt.CaseInsensitive)
                 tc.insertText(qf)
                 # The insertion goes in ahead of the saved cursor position so now
                 # it points after the inserted string. Put it back where it was.
                 IMC.pageTable.setPosition(i, pos)
         tc.endEditBlock()  # wrap up the undo op
Beispiel #12
0
 def insertMarkers(self):
     # Copy the text and if it is empty, complain and exit.
     qi = QString(self.insertText.text())
     if qi.isEmpty() :
         pqMsgs.warningMsg("No insert text specified")
         return
     # See how many pages are involved: all the ones that aren't marked skip
     n = 0
     for i in range(IMC.pageTable.size()):
         if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip :
             n += 1
     if n == 0 : # page table empty or all rows marked skip
         pqMsgs.warningMsg("No pages to give folios to")
         return
     m = "Insert this string at the top of {0} pages?".format(n)
     b = pqMsgs.okCancelMsg(QString(m),pqMsgs.trunc(qi,35))
     if b :
         # Convert any '\n' in the text to the QT line delimiter char
         # we do this in the copy so the lineEdit text doesn't change
         qi.replace(QString(u'\\n'),QString(IMC.QtLineDelim))
         # get a cursor on the edit document
         tc = QTextCursor(IMC.editWidget.textCursor())
         tc.beginEditBlock() # start single undoable operation
         # Working from the end of the document backward, go to the
         # top of each page and insert the string
         for i in reversed( range( IMC.pageTable.size() ) ) :
             if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip :
                 # Note the page's start position and set our work cursor to it
                 pos = IMC.pageTable.getCursor(i).position()
                 tc.setPosition(pos)
                 # Make a copy of the insert string replacing %f with this folio
                 f = IMC.pageTable.getDisplay(i)
                 qf = QString(qi)
                 qf.replace(QString(u'%f'),f,Qt.CaseInsensitive)
                 tc.insertText(qf)
                 # The insertion goes in ahead of the saved cursor position so now
                 # it points after the inserted string. Put it back where it was.
                 IMC.pageTable.setPosition(i, pos)
         tc.endEditBlock() # wrap up the undo op
Beispiel #13
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):

        QMainWindow.__init__(self, parent)
        self.setupUi(self)

        self.fontDatabase = QFontDatabase()
        self.path = QString()

        self.connect(self.exitAction, SIGNAL("triggered()"), qApp,
                     SLOT("quit()"))

        self.updateStylesCombo(self.fontComboBox.currentFont().family())
        self.setWindowModified(False)

    @pyqtSignature("")
    def on_newAction_triggered(self):

        self.effectWidget.reset()
        self.setWindowModified(False)
        self.saveAsAction.setEnabled(False)
        self.saveAction.setEnabled(False)

    def on_fontComboBox_currentFontChanged(self, font):

        self.updateStylesCombo(font.family())

    def updateStylesCombo(self, family):

        self.styleComboBox.clear()

        styles = self.fontDatabase.styles(family)
        for style in styles:

            self.styleComboBox.addItem(style)

    @pyqtSignature("")
    def on_saveAsAction_triggered(self):

        filters = self.tr("Supported formats (%1)").arg(" ".join(
            map(lambda x: "*." + str(x),
                QImageWriter.supportedImageFormats())))
        path = QFileDialog.getSaveFileName(self, self.tr("Save Image"),
                                           self.path, filters)

        if path.isEmpty():
            return

        self.save(path)

    @pyqtSignature("")
    def on_saveAction_triggered(self):

        self.save(self.path)

    def save(self, path):

        rect = self.effectWidget.pathRect()
        image = QImage(rect.size().toSize(), QImage.Format_ARGB32)
        image.fill(qRgba(0, 0, 0, 0))
        self.effectWidget.paint(image, rect)
        if image.save(path):
            self.setWindowModified(False)
            self.saveAction.setEnabled(False)
            self.path = path

    def on_effectWidget_contentsChanged(self):

        self.setWindowModified(True)
        self.saveAsAction.setEnabled(True)
        self.saveAction.setEnabled(not self.path.isEmpty())
 def enableFindButton(self, text):
     print type(text), ":", len(text)
     print(text)
     t = QString(text)
     self.findButton.setEnabled(not t.isEmpty())
Beispiel #15
0
class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, parent = None):
    
        QMainWindow.__init__(self, parent)
        self.setupUi(self)
        
        self.fontDatabase = QFontDatabase()
        self.path = QString()
        
        self.connect(self.exitAction, SIGNAL("triggered()"),
                     qApp, SLOT("quit()"))
        
        self.updateStylesCombo(self.fontComboBox.currentFont().family())
        self.setWindowModified(False)
    
    @pyqtSignature("")
    def on_newAction_triggered(self):
    
        self.effectWidget.reset()
        self.setWindowModified(False)
        self.saveAsAction.setEnabled(False)
        self.saveAction.setEnabled(False)
    
    def on_fontComboBox_currentFontChanged(self, font):
    
        self.updateStylesCombo(font.family())
        
    def updateStylesCombo(self, family):
    
        self.styleComboBox.clear()
        
        styles = self.fontDatabase.styles(family)
        for style in styles:
        
            self.styleComboBox.addItem(style)
    
    @pyqtSignature("")
    def on_saveAsAction_triggered(self):
    
        filters = self.tr("Supported formats (%1)").arg(
            " ".join(map(lambda x: "*."+str(x), QImageWriter.supportedImageFormats()))
            )
        path = QFileDialog.getSaveFileName(self, self.tr("Save Image"),
            self.path, filters)
        
        if path.isEmpty():
            return
        
        self.save(path)
    
    @pyqtSignature("")
    def on_saveAction_triggered(self):
    
        self.save(self.path)
    
    def save(self, path):
    
        rect = self.effectWidget.pathRect()
        image = QImage(rect.size().toSize(), QImage.Format_ARGB32)
        image.fill(qRgba(0, 0, 0, 0))
        self.effectWidget.paint(image, rect)
        if image.save(path):
            self.setWindowModified(False)
            self.saveAction.setEnabled(False)
            self.path = path
    
    def on_effectWidget_contentsChanged(self):
    
        self.setWindowModified(True)
        self.saveAsAction.setEnabled(True)
        self.saveAction.setEnabled(not self.path.isEmpty())
Beispiel #16
0
class ShipContainer(object):

    def __init__(self, filename=QString()):
        self.filename = QString(filename)
        self.dirty = False
        self.ships = {}
        self.owners = set()
        self.countries = set()


    def ship(self, identity):
        return self.ships.get(identity)

        
    def addShip(self, ship):
        self.ships[id(ship)] = ship
        self.owners.add(unicode(ship.owner))
        self.countries.add(unicode(ship.country))
        self.dirty = True


    def removeShip(self, ship):
        del self.ships[id(ship)]
        del ship
        self.dirty = True


    def __len__(self):
        return len(self.ships)


    def __iter__(self):
        for ship in self.ships.values():
            yield ship


    def inOrder(self):
        return sorted(self.ships.values())


    def inCountryOwnerOrder(self):
        return sorted(self.ships.values(),
                      key=lambda x: (x.country, x.owner, x.name))


    def load(self):
        exception = None
        fh = None
        try:
            if self.filename.isEmpty():
                raise IOError, "no filename specified for loading"
            fh = QFile(self.filename)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError, unicode(fh.errorString())
            stream = QDataStream(fh)
            magic = stream.readInt32()
            if magic != MAGIC_NUMBER:
                raise IOError, "unrecognized file type"
            fileVersion = stream.readInt16()
            if fileVersion != FILE_VERSION:
                raise IOError, "unrecognized file type version"
            self.ships = {}
            while not stream.atEnd():
                name = QString()
                owner = QString()
                country = QString()
                description = QString()
                stream >> name >> owner >> country >> description
                teu = stream.readInt32()
                ship = Ship(name, owner, country, teu, description)
                self.ships[id(ship)] = ship
                self.owners.add(unicode(owner))
                self.countries.add(unicode(country))
            self.dirty = False
        except IOError, err:
            exception = err
        finally:
Beispiel #17
0
class helpDisplay(QWebView):
    def __init__(self, parent=None ):
        super(helpDisplay, self).__init__(parent)
        # make page unmodifiable
        self.page().setContentEditable(False)
        # initialize settings
        # Find out the nearest font to Palatino
        qf = QFont()
        qf.setStyleStrategy(QFont.PreferAntialias+QFont.PreferMatch)
        qf.setStyleHint(QFont.Serif)
        qf.setFamily(QString(u'Palatino'))
        qfi = QFontInfo(qf)
        # set the default font to that serif font
        self.settings().setFontFamily(QWebSettings.StandardFont, qfi.family())
        self.settings().setFontSize(QWebSettings.DefaultFontSize, 16)
        self.settings().setFontSize(QWebSettings.MinimumFontSize, 6)
        self.settings().setFontSize(QWebSettings.MinimumLogicalFontSize, 6)
        self.textZoomFactor = 1.0
        self.setTextSizeMultiplier(self.textZoomFactor)
        self.settings().setAttribute(QWebSettings.JavascriptEnabled, False)
        self.settings().setAttribute(QWebSettings.JavaEnabled, False)
        self.settings().setAttribute(QWebSettings.PluginsEnabled, False)
        self.settings().setAttribute(QWebSettings.ZoomTextOnly, True)
        #self.settings().setAttribute(QWebSettings.SiteSpecificQuirksEnabled, False)
        self.userFindText = QString()
        # Look for pqHelp.html in the app folder and copy its text into
        # a local buffer. If it isn't found, put a message there instead.
        # We need to keep it in order to implement the "back" function.
        helpPath = os.path.join(IMC.appBasePath,u'pqHelp.html')
        helpFile = QFile(helpPath)
        if not helpFile.exists():
            self.HTMLstring = QString('''<p>Unable to locate pqHelp.html.</p>
	    <p>Looking in {0}'''.format(helpPath)
                                )
        elif not helpFile.open(QIODevice.ReadOnly) :
            self.HTMLstring = QString('''<p>Unable to open pqHelp.html.</p>
	    <p>Looking in {0}</p><p>Error code {1}</p>'''.format(helpPath,
                                                                 helpFile.error())
                                                         )
        else:
            helpStream = QTextStream(helpFile)
            helpStream.setCodec('ISO8859-1')
            self.HTMLstring = helpStream.readAll()
        self.setHtml(self.HTMLstring)

    # Re-implement the parent's keyPressEvent in order to provide a simple
    # find function and font-zoom from ctl-plus/minus. We start the view at
    # 16 points and textSizeMultiplier of 1.0. Each time the user hits ctl-minus
    # we deduct 0.0625 from the multiplier, and for each ctl-+ we add 0.0625
    # (1/16) to the multiplier. This ought to cause the view to change up or
    # down by one point. We set a limit of 0.375 (6 points) at the low
    # end and 4.0 (64 points) at the top.
    def keyPressEvent(self, event):
        #pqMsgs.printKeyEvent(event)
        kkey = int( int(event.modifiers()) & IMC.keypadDeModifier) | int(event.key())
        if (kkey == IMC.ctl_F) or (kkey == IMC.ctl_G) : # ctl/cmd f/g
            event.accept()
            self.doFind(kkey)
        elif (kkey in IMC.zoomKeys) : # ctl-plus/minus
            zfactor = 0.0625 # zoom in
            if (kkey == IMC.ctl_minus) :
                zfactor = -zfactor # zoom out
            zfactor += self.textZoomFactor
            if (zfactor > 0.374) and (zfactor < 4.0) :
                self.textZoomFactor = zfactor
                self.setTextSizeMultiplier(self.textZoomFactor)
        elif (kkey in IMC.backKeys) : # ctl-B/[/left
            if self.page().history().currentItemIndex() > 1 :
                self.page().history().back()
            else :
                self.setHtml(self.HTMLstring)
                self.page().history().clear()
        else: # not ctl/cmd f or ctl/cmd-plus/minus, so,
            event.ignore()
            super(helpDisplay, self).keyPressEvent(event)

    # Implement a simple Find/Find-Next, same logic as in pqNotes,
    # but adjusted for our widget being a webview, and it does the
    # wraparound for us.
    def doFind(self,kkey):
        if (kkey == IMC.ctl_F) or (self.userFindText.isEmpty()) :
            # ctl+F, or ctl+G but no previous find done, show the find dialog
            # with a COPY of current selection as pqMsgs might truncate it
            prepText = QString(self.page().selectedText())
            (ok, self.userFindText) = pqMsgs.getFindMsg(self,prepText)
        # We should have some findText now, either left from previous find
        # on a ctl-G, or entered by user. If none, then user cleared dialog.
        if not self.userFindText.isEmpty() :
            if not self.page().findText(
                self.userFindText, QWebPage.FindWrapsAroundDocument
                ) :
                pqMsgs.beep()
Beispiel #18
0
class htmlPreview(QWidget):
    def __init__(self, parent=None):
        super(htmlPreview, self).__init__(parent)
        hbox = QHBoxLayout()
        self.refreshButton = QPushButton(u"Refresh")
        hbox.addWidget(self.refreshButton, 0)
        hbox.addStretch(1)
        self.refreshAndClearButton = QPushButton(u"Refresh + Clear")
        hbox.addWidget(self.refreshAndClearButton)
        vbox = QVBoxLayout()
        vbox.addLayout(hbox, 0)
        self.preview = QWebView(self)
        # save a shortcut reference to web page and its history
        self.webPage = self.preview.page()
        self.history = self.preview.page().history()
        vbox.addWidget(self.preview, 1)
        self.setLayout(vbox)
        # make the web preview uneditable
        self.webPage.setContentEditable(False)
        self.settings = self.preview.settings()
        # Find out the nearest font to Palatino
        qf = QFont()
        qf.setStyleStrategy(QFont.PreferAntialias + QFont.PreferMatch)
        qf.setStyleHint(QFont.Serif)
        qf.setFamily(QString(u'Palatino'))
        qfi = QFontInfo(qf)
        # set the default font to that serif font
        self.settings.setFontFamily(QWebSettings.StandardFont, qfi.family())
        self.settings.setFontSize(QWebSettings.DefaultFontSize, 16)
        self.settings.setFontSize(QWebSettings.MinimumFontSize, 6)
        self.settings.setFontSize(QWebSettings.MinimumLogicalFontSize, 6)
        self.zoomFactor = 1.0
        # Disable everything but bog-standard html, appropriate for PP
        self.settings.setAttribute(QWebSettings.JavascriptEnabled, False)
        self.settings.setAttribute(QWebSettings.JavaEnabled, False)
        self.settings.setAttribute(QWebSettings.PluginsEnabled, False)
        self.settings.setAttribute(QWebSettings.ZoomTextOnly, False)
        # the following causes a hard error in linux
        #self.settings.setAttribute(QWebSettings.SiteSpecificQuirksEnabled, False)
        # hook up the refresh buttons
        self.connect(self.refreshButton, SIGNAL("clicked()"),
                     self.refresh1Click)
        self.connect(self.refreshAndClearButton, SIGNAL("clicked()"),
                     self.refresh2Click)
        # hook up the load status signals
        self.connect(self.preview, SIGNAL("loadStarted()"), self.loadStarts)
        self.connect(self.preview, SIGNAL("loadProgress(int)"),
                     self.loadProgresses)
        self.connect(self.preview, SIGNAL("loadFinished(bool)"), self.loadEnds)
        # here we store the scroll position to return to after reloading
        self.scrollPosition = QPoint(0, 0)
        # here save the user's find text for ctl-g use
        self.findText = QString()
        # here store the base URL for the current book.
        self.baseURL = QUrl()
        # we do NOT initialize the preview (e.g. by calling self.refresh)
        # at construction time. It may be many hours before the user wants
        # to preview html. So require an explicit refresh click to do it.

    # Plain Refresh clicked.
    def refresh1Click(self):
        self.refresh(False)

    # Refresh + Clear clicked.
    def refresh2Click(self):
        self.refresh(True)

    # One or the other refresh button clicked.
    # Get the current scroll position (a QPoint that reflects the position of the
    # scrollbar "thumb" in the webview) from the QWebFrame that is associated with
    # the QWebPage that is displayed in our QWebView, and save it for use after
    # the loadEnds() signal is received, to restore the previous scroll position.
    #
    # If Refresh+Clear was clicked, clear the memory cache -- a function that is
    # strangely located in the web settings object, but whatever -- and then reload
    # the HTML contents from the editor document,
    def refresh(self, clearCache=False):
        # this could be first refresh for this book file, so set the
        # base URL for its images.
        sep = QChar(u'/')
        qsp = QString(IMC.bookDirPath)
        if not qsp.endsWith(sep):
            qsp.append(sep)
        self.baseURL = QUrl.fromLocalFile(qsp)
        # this might be the second or nth refresh of the book, note the
        # scroll position so we can restore it in loadEnds below. This
        # means that when you make a little edit at the end of a book, and
        # refresh the preview, you won't have to scroll down to the end
        # for the 500th time to see your changes.
        self.scrollPosition = self.webPage.mainFrame().scrollPosition()
        if clearCache:
            self.settings.clearMemoryCaches()
        # We are reloading our base page, so clear any history of prior links
        self.history.clear()
        self.preview.setHtml(IMC.editWidget.toPlainText(), self.baseURL)

    # handle the load-in-progress signals by running our main window's
    # progress bar
    def loadStarts(self):
        pqMsgs.startBar(100, "Loading HTML")

    def loadProgresses(self, amt):
        pqMsgs.rollBar(amt, refresh=False)

    def loadEnds(self, bool):
        pqMsgs.endBar()
        if bool:
            # load was ok, reset scroll position now the rendering is finished.
            self.webPage.mainFrame().setScrollPosition(self.scrollPosition)
            # our panel is visible (else how was Refresh clicked?) but it may
            # not have the keyboard focus. Right after refresh one usually wants
            # to use keys like page-up/dn, so get the focus to our webview
            # widget (not the page in it because the webview has the scroll
            # bars and other mechanism.)
            self.preview.setFocus(Qt.MouseFocusReason)
        else:
            pqMsgs.warningMsg("Some problem loading html")

    # Handle the docWillChange signal: tell ourselves to stop whatever we is doing.
    # If we are actually loading something, presumably that provokes a call to
    # loadEnds above.
    def docWillChange(self):
        self.preview.stop()

    # And on the ensuing docHasChanged signal, clear our document.
    def docHasChanged(self):
        self.preview.setHtml(QString())

    # Re-implement the parent's keyPressEvent in order to provide a simple
    # find function, font-zoom from ctl-plus/minus, and browser "back".
    # For the font size, we initialize the view at 16 points and
    # the textSizeMultiplier at 1.0. Each time the user hits ctl-minus
    # we deduct 0.0625 from the multiplier, and for each ctl-+ we add 0.0625
    # (1/16) to the multiplier. This ought to cause the view to change up or
    # down by one point. We set a limit of 0.375 (6 points) at the low
    # end and 4.0 (64 points) at the top.
    def keyPressEvent(self, event):
        kkey = int(int(event.modifiers()) & IMC.keypadDeModifier) | int(
            event.key())
        if (kkey == IMC.ctl_F) or (kkey == IMC.ctl_G):  # ctl/cmd f/g
            event.accept()
            self.doFind(kkey)
        elif (kkey in IMC.zoomKeys):  # ctrl-plus/minus
            zfactor = 0.0625  # zoom in
            if (kkey == IMC.ctl_minus):
                zfactor = -zfactor  # zoom out
            zfactor += self.zoomFactor
            if (zfactor > 0.374) and (zfactor < 4.0):
                self.zoomFactor = zfactor
                self.preview.setZoomFactor(self.zoomFactor)
        elif (kkey in IMC.backKeys):
            if self.history.currentItemIndex() > 1:
                self.webPage.triggerAction(QWebPage.Back)
            else:
                # reload the html of the book text, but don't call refresh
                # because it would capture the scroll position as of now,
                # and that relates to the linked page we are coming back from.
                # The scroll position noted the last time Refresh was clicked
                # will be instantiated in the loadEnds slot.
                self.history.clear()
                self.preview.setHtml(IMC.editWidget.toPlainText(),
                                     self.baseURL)
        else:  # not a key we support, so,
            event.ignore()
            super(htmlPreview, self).keyPressEvent(event)

    # Implement a simple Find/Find-Next, same logic as in pqNotes,
    # but adjusted for our widget being a webview, and it does the
    # wraparound for us.
    def doFind(self, kkey):
        if (kkey == IMC.ctl_F) or (self.findText.isEmpty()):
            # ctl+F, or ctl+G but no previous find done, show the find dialog
            # with a COPY of current selection as pqMsgs might truncate it
            prepText = QString(self.webPage.selectedText())
            (ok, self.findText) = pqMsgs.getFindMsg(self, prepText)
        # dialog or no dialog, we should have some findText now
        if not self.findText.isEmpty():
            if not self.webPage.findText(self.findText,
                                         QWebPage.FindWrapsAroundDocument):
                pqMsgs.beep()
Beispiel #19
0
class htmlPreview(QWidget):
    def __init__(self, parent=None ):
        super(htmlPreview, self).__init__(parent)
        hbox = QHBoxLayout()
        self.refreshButton = QPushButton(u"Refresh")
        hbox.addWidget(self.refreshButton,0)
        hbox.addStretch(1)
        self.refreshAndClearButton = QPushButton(u"Refresh + Clear")
        hbox.addWidget(self.refreshAndClearButton)
        vbox = QVBoxLayout()
        vbox.addLayout(hbox,0)
        self.preview = QWebView(self)
        # save a shortcut reference to web page and its history
        self.webPage = self.preview.page()
        self.history = self.preview.page().history()
        vbox.addWidget(self.preview,1)
        self.setLayout(vbox)
        # make the web preview uneditable
        self.webPage.setContentEditable(False)
        self.settings = self.preview.settings()
        # Find out the nearest font to Palatino
        qf = QFont()
        qf.setStyleStrategy(QFont.PreferAntialias+QFont.PreferMatch)
        qf.setStyleHint(QFont.Serif)
        qf.setFamily(QString(u'Palatino'))
        qfi = QFontInfo(qf)
        # set the default font to that serif font
        self.settings.setFontFamily(QWebSettings.StandardFont, qfi.family())
        self.settings.setFontSize(QWebSettings.DefaultFontSize, 16)
        self.settings.setFontSize(QWebSettings.MinimumFontSize, 6)
        self.settings.setFontSize(QWebSettings.MinimumLogicalFontSize, 6)
        self.zoomFactor = 1.0
        # Disable everything but bog-standard html, appropriate for PP
        self.settings.setAttribute(QWebSettings.JavascriptEnabled, False)
        self.settings.setAttribute(QWebSettings.JavaEnabled, False)
        self.settings.setAttribute(QWebSettings.PluginsEnabled, False)
        self.settings.setAttribute(QWebSettings.ZoomTextOnly, False)
        # the following causes a hard error in linux
        #self.settings.setAttribute(QWebSettings.SiteSpecificQuirksEnabled, False)
        # hook up the refresh buttons
        self.connect(self.refreshButton, SIGNAL("clicked()"),self.refresh1Click)
        self.connect(self.refreshAndClearButton, SIGNAL("clicked()"),self.refresh2Click)
        # hook up the load status signals
        self.connect(self.preview,SIGNAL("loadStarted()"),self.loadStarts )
        self.connect(self.preview,SIGNAL("loadProgress(int)"),self.loadProgresses )
        self.connect(self.preview,SIGNAL("loadFinished(bool)"),self.loadEnds )
        # here we store the scroll position to return to after reloading
        self.scrollPosition = QPoint(0,0)
        # here save the user's find text for ctl-g use
        self.findText = QString()
        # here store the base URL for the current book.
        self.baseURL = QUrl()
        # we do NOT initialize the preview (e.g. by calling self.refresh)
        # at construction time. It may be many hours before the user wants
        # to preview html. So require an explicit refresh click to do it.

    # Plain Refresh clicked.
    def refresh1Click(self) :
        self.refresh(False)
    # Refresh + Clear clicked.
    def refresh2Click(self) :
        self.refresh(True)

    # One or the other refresh button clicked.
    # Get the current scroll position (a QPoint that reflects the position of the
    # scrollbar "thumb" in the webview) from the QWebFrame that is associated with
    # the QWebPage that is displayed in our QWebView, and save it for use after
    # the loadEnds() signal is received, to restore the previous scroll position.
    #
    # If Refresh+Clear was clicked, clear the memory cache -- a function that is
    # strangely located in the web settings object, but whatever -- and then reload
    # the HTML contents from the editor document,
    def refresh(self, clearCache=False ):
        # this could be first refresh for this book file, so set the
        # base URL for its images.
        sep = QChar(u'/')
        qsp = QString(IMC.bookDirPath)
        if not qsp.endsWith(sep):
            qsp.append(sep)
        self.baseURL = QUrl.fromLocalFile(qsp)
        # this might be the second or nth refresh of the book, note the
        # scroll position so we can restore it in loadEnds below. This
        # means that when you make a little edit at the end of a book, and
        # refresh the preview, you won't have to scroll down to the end
        # for the 500th time to see your changes.
        self.scrollPosition = self.webPage.mainFrame().scrollPosition()
        if clearCache :
            self.settings.clearMemoryCaches()
        # We are reloading our base page, so clear any history of prior links
        self.history.clear()
        self.preview.setHtml(IMC.editWidget.toPlainText(),self.baseURL)

    # handle the load-in-progress signals by running our main window's
    # progress bar
    def loadStarts(self):
        pqMsgs.startBar(100,"Loading HTML")
    def loadProgresses(self,amt):
        pqMsgs.rollBar(amt, refresh=False)
    def loadEnds(self,bool):
        pqMsgs.endBar()
        if bool:
            # load was ok, reset scroll position now the rendering is finished.
            self.webPage.mainFrame().setScrollPosition(self.scrollPosition)
            # our panel is visible (else how was Refresh clicked?) but it may
            # not have the keyboard focus. Right after refresh one usually wants
            # to use keys like page-up/dn, so get the focus to our webview
            # widget (not the page in it because the webview has the scroll
            # bars and other mechanism.)
            self.preview.setFocus(Qt.MouseFocusReason)
        else:
            pqMsgs.warningMsg("Some problem loading html")

    # Handle the docWillChange signal: tell ourselves to stop whatever we is doing.
    # If we are actually loading something, presumably that provokes a call to
    # loadEnds above.
    def docWillChange(self) :
        self.preview.stop()
    # And on the ensuing docHasChanged signal, clear our document.
    def docHasChanged(self) :
        self.preview.setHtml(QString())

    # Re-implement the parent's keyPressEvent in order to provide a simple
    # find function, font-zoom from ctl-plus/minus, and browser "back".
    # For the font size, we initialize the view at 16 points and
    # the textSizeMultiplier at 1.0. Each time the user hits ctl-minus
    # we deduct 0.0625 from the multiplier, and for each ctl-+ we add 0.0625
    # (1/16) to the multiplier. This ought to cause the view to change up or
    # down by one point. We set a limit of 0.375 (6 points) at the low
    # end and 4.0 (64 points) at the top.
    def keyPressEvent(self, event):
        kkey = int( int(event.modifiers()) & IMC.keypadDeModifier) | int(event.key())
        if (kkey == IMC.ctl_F) or (kkey == IMC.ctl_G) : # ctl/cmd f/g
            event.accept()
            self.doFind(kkey)
        elif (kkey in IMC.zoomKeys) : # ctrl-plus/minus
            zfactor = 0.0625 # zoom in
            if (kkey == IMC.ctl_minus) :
                zfactor = -zfactor # zoom out
            zfactor += self.zoomFactor
            if (zfactor > 0.374) and (zfactor < 4.0) :
                self.zoomFactor = zfactor
                self.preview.setZoomFactor(self.zoomFactor)
        elif (kkey in IMC.backKeys) :
            if self.history.currentItemIndex() > 1 :
                self.webPage.triggerAction(QWebPage.Back)
            else :
                # reload the html of the book text, but don't call refresh
                # because it would capture the scroll position as of now,
                # and that relates to the linked page we are coming back from.
                # The scroll position noted the last time Refresh was clicked
                # will be instantiated in the loadEnds slot.
                self.history.clear()
                self.preview.setHtml(IMC.editWidget.toPlainText(),self.baseURL)
        else: # not a key we support, so,
            event.ignore()
            super(htmlPreview, self).keyPressEvent(event)

    # Implement a simple Find/Find-Next, same logic as in pqNotes,
    # but adjusted for our widget being a webview, and it does the
    # wraparound for us.
    def doFind(self,kkey):
        if (kkey == IMC.ctl_F) or (self.findText.isEmpty()) :
            # ctl+F, or ctl+G but no previous find done, show the find dialog
            # with a COPY of current selection as pqMsgs might truncate it
            prepText = QString(self.webPage.selectedText())
            (ok, self.findText) = pqMsgs.getFindMsg(self,prepText)
        # dialog or no dialog, we should have some findText now
        if not self.findText.isEmpty() :
            if not self.webPage.findText(
                self.findText, QWebPage.FindWrapsAroundDocument
                ) :
                pqMsgs.beep()
Beispiel #20
0
class Level(QFrame):
    def __init__(self, parent):
        QFrame.__init__(self,parent)

        self.filename = QString()
        self.copiedItem = QByteArray()
        self.pasteOffset = 5
        self.prevPoint = QPoint()
        self.addOffset = 5
        
        self.screenSize = (320, 240)
        self.bgColor = QColor(244,244,244)
        '''0.Portrait 1.Landscape'''
        self.orientation = 0
        self.currentItem = None
        

        self.printer = QPrinter(QPrinter.HighResolution)
        self.printer.setPageSize(QPrinter.Letter)


        '''1.Header'''
        self.levelBar = LevelBar(self)
        
        '''3.Tiler'''
        self.tiler = TileMapGrid(self)#Tiler(self)
        self.tiler.setMinimumHeight(100)
        #self.tiler.currentChanged.connect(self.closeDesigner)
        #self.tiler.setTabsClosable(True)
        #self.tiler.setTabShape(0)
        #self.tiler.hide()
        #self.levelLayout.addWidget(self.levelBar) 
        
        '''2.view'''
        viewLayoutWidget = QFrame()
        viewLayoutWidget.setFrameShape(QFrame.StyledPanel)
        viewLayout = QHBoxLayout(viewLayoutWidget)
        #viewLayout.setMargin(10)
        self.view = LevelView(viewLayoutWidget)
        '''scene'''
        self.scene = QGraphicsScene(self)
        #self.scene.selectionChanged.connect(self.setConnect)
        #self.view.setStyleSheet("border: 1px solid red;")
        
        self.setBackgroundColor(self.bgColor)
        self.setScreenSize(self.screenSize)
        
        self.view.setScene(self.scene)
        self.view.setAlignment(Qt.AlignCenter)
        self.scroll_off = 1
        self.setScrollBar()
        
        viewLayout.setMargin(0)
        viewLayout.addWidget(self.view)

        self.wrapped = [] # Needed to keep wrappers alive
        layout = QVBoxLayout(self)
        layout.addWidget(self.levelBar)
        layout.addWidget(viewLayoutWidget)
        layout.addWidget(self.tiler)
        layout.setMargin(0)
        self.setLayout(layout)
        
    def setScrollBar(self):
        if(self.scroll_off):
            self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.scroll_off = 0
        else:
            self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self.scroll_off = 1
        
    def setBackgroundColor(self,color):
        self.bgColor = color
        self.scene.setBackgroundBrush(QBrush(color))
        
    def setScreenSize(self,size):
        self.screenSize = size
        self.setOrientation(self.orientation)
        
    def setOrientation(self,idx):
        self.orientation = idx
        if(idx == 0):
            self.view.setMaximumSize(self.screenSize[1], self.screenSize[0])
            self.scene.setSceneRect(0, 0, self.screenSize[1], self.screenSize[0])
        else:
            self.view.setMaximumSize(self.screenSize[0], self.screenSize[1])
            self.scene.setSceneRect(0, 0, self.screenSize[0], self.screenSize[1])
        
    def offerSave(self):
        if (Dirty and QMessageBox.question(self,
                            "Designer - Unsaved Changes",
                            "Save unsaved changes?",
                            QMessageBox.Yes|QMessageBox.No) == 
           QMessageBox.Yes):
            self.save()


    def position(self):
        point = self.mapFromGlobal(QCursor.pos())
        if not self.view.geometry().contains(point):
            coord = random.randint(36, 144)
            point = QPoint(coord, coord)
        else:
            if point == self.prevPoint:
                point += QPoint(self.addOffset, self.addOffset)
                self.addOffset += 5
            else:
                self.addOffset = 5
                self.prevPoint = point
        return self.view.mapToScene(point)
    
    def selectedItem(self):
        items = self.scene.selectedItems()
        if len(items) == 1:
            return items[0]
        return None
    
    def current(self,item):
        self.scene.clearSelection()
        sceneItems = self.scene.items()
        for items in sceneItems:
            if(items != item):
                item.setSelected(False)
                if(item.isConnected()):
                    self.propertyBar.disconnectText(item)
                    item.setConnected(False)
        self.currentItem = item
        self.currentItem.setConnected(True)
        self.currentItem.setSelected(True)
        self.propertyBar.connectText(self.currentItem)
        self.propertyBar.initText(self.currentItem)


    def addText(self):
        item = TextItem("SomeText", self.position())
        self.connect(item, SIGNAL("current"),self.current)
        self.connect(item, SIGNAL("copy"),self.copy)
        self.connect(item, SIGNAL("cut"),self.cut)
        self.connect(item, SIGNAL("paste"),self.paste)
        self.connect(item, SIGNAL("delete"),self.delete)
        #self.current(item)
        self.scene.addItem(item)
        

    def copy(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copiedItem.clear()
        self.pasteOffset = 5
        stream = QDataStream(self.copiedItem, QIODevice.WriteOnly)
        self.writeItemToStream(stream, item)


    def cut(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copy()
        self.scene.removeItem(item)
        del item


    def paste(self):
        if self.copiedItem.isEmpty():
            return
        stream = QDataStream(self.copiedItem, QIODevice.ReadOnly)
        item = self.readItemFromStream(stream, self.pasteOffset)
        self.pasteOffset += 5
        #self.scene.addItem(item)
        
    def delete(self):
        items = self.scene.selectedItems()
        if (len(items) and QMessageBox.question(self,
                "Designer - Delete",
                "Delete {0} item{1}?".format(len(items),
                "s" if len(items) != 1 else ""),
                QMessageBox.Yes|QMessageBox.No) ==
                QMessageBox.Yes):
            while items:
                item = items.pop()
                self.scene.removeItem(item)
                del item
                
    def readItemFromStream(self, stream, offset=0):
        type = QString()
        position = QPointF()
        matrix = QMatrix()
        stream >> type >> position >> matrix
        if offset:
            position += QPointF(offset, offset)
        if type == "Text":
            text = QString()
            font = QFont()
            stream >> text >> font
            self.scene.addItem(TextItem(text, position, font, matrix))
        elif type == "Box":
            rect = QRectF()
            stream >> rect
            style = Qt.PenStyle(stream.readInt16())
            self.scene.addItem(BoxItem(position, style, matrix))
        elif type == "Pixmap":
            pixmap = QPixmap()
            stream >> pixmap
            self.scene.addItem(self.createPixmapItem(pixmap, position, matrix))


    def writeItemToStream(self, stream, item):
        if isinstance(item, QGraphicsTextItem):
            stream << QString("Text") << item.pos() \
                   << item.matrix() << item.toPlainText() << item.font()
        elif isinstance(item, QGraphicsPixmapItem):
            stream << QString("Pixmap") << item.pos() \
                   << item.matrix() << item.pixmap()
        elif isinstance(item, BoxItem):
            stream << QString("Box") << item.pos() \
                   << item.matrix() << item.rect
            stream.writeInt16(item.style)

    def rotate(self):
        for item in self.scene.selectedItems():
            item.rotate(30)


    def print_(self):
        dialog = QPrintDialog(self.printer)
        if dialog.exec_():
            painter = QPainter(self.printer)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setRenderHint(QPainter.TextAntialiasing)
            self.scene.clearSelection()
            #self.removeBorders()
            self.scene.render(painter)
            #self.addBorders()


    def open(self):
        self.offerSave()
        path = (QFileInfo(self.filename).path()
                if not self.filename.isEmpty() else ".")
        fname = QFileDialog.getOpenFileName(self,
                "Page Designer - Open", path,
                "Page Designer Files (*.pgd)")
        if fname.isEmpty():
            return
        self.filename = fname
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError, unicode(fh.errorString())
            items = self.scene.items()
            while items:
                item = items.pop()
                self.scene.removeItem(item)
                del item
            self.addBorders()
            stream = QDataStream(fh)
            stream.setVersion(QDataStream.Qt_4_2)
            magic = stream.readInt32()
            if magic != MagicNumber:
                raise IOError, "not a valid .pgd file"
            fileVersion = stream.readInt16()
            if fileVersion != FileVersion:
                raise IOError, "unrecognised .pgd file version"
            while not fh.atEnd():
                self.readItemFromStream(stream)
        except IOError, e:
            QMessageBox.warning(self, "Page Designer -- Open Error",
                    "Failed to open {0}: {1}".format(self.filename, e))
        finally:
Beispiel #21
0
class notesEditor(QPlainTextEdit):

    def __init__(self, parent=None, fontsize=12 ):
        super(notesEditor, self).__init__(parent)
        # Do not allow line-wrap; horizontal scrollbar appears when required.
        self.setLineWrapMode(QPlainTextEdit.NoWrap)
        # get same font as main editor uses
        self.setFont(pqMsgs.getMonoFont(12,False))
        self.connect(self.document(), SIGNAL("modificationChanged(bool)"),self.eek)
        self.findText = QString()

    # called from pqEdit.clear()
    def clear(self):
        self.clearing = True
        self.document().clear()
        self.document().setModified(False)
        self.findText = QString()
        self.clearing = False

    # slot to receive the modificationChanged(bool) signal from our document.
    # if it indicates we are modified, set needMetadataSave true if it isn't
    # already. Should the user undo out of all changes, modval will be false
    # and we clear our flag, possibly making the flag 0.
    def eek(self,modval):
        if not self.clearing :
            if modval :
                IMC.needMetadataSave |= IMC.notePanelChanged
            else :
                IMC.needMetadataSave &= (0xff ^ IMC.notePanelChanged)
        IMC.mainWindow.setWinModStatus()

    # Re-implement the parent's keyPressEvent in order to provide zoom:
    # ctrl-plus and ctrl-minus step the font size one point. Other keys:
    # shift-ctl-L inserts the current line number as {nnn}
    # ctl-L looks for a nearby {nnn} (braces required), selects it, and
    # tells the main editor to jump to that line.
    # shift-ctl-P insert the current page (scan) number as [nnn]
    # ctl-P looks for a nearby [nnn] (brackets required), selects it, and
    # tells the main editor to jump to that page position.
    def keyPressEvent(self, event):
        #pqMsgs.printKeyEvent(event)
        kkey = int( int(event.modifiers()) & IMC.keypadDeModifier) | int(event.key())
        if kkey in IMC.keysOfInterest :
            # tentatively assume we will process this key
            event.accept()
            if kkey in IMC.zoomKeys :
                n = (-1) if (kkey == IMC.ctl_minus) else 1
                p = self.fontInfo().pointSize() + n
                if (p > 3) and (p < 65): # don't let's get ridiculous, hmm?
                    f = self.font() # so get our font,
                    f.setPointSize(p) # change its point size +/-
                    self.setFont(f) # and put the font back
            elif (kkey == IMC.ctl_alt_M): # ctrl/cmd-m with shift
                self.insertLine()
            elif (kkey == IMC.ctl_M): # ctrl/cmd-m (no shift)
                self.goToLine()
            elif (kkey == IMC.ctl_alt_P): # ctl/cmd-p
                self.insertPage()
            elif (kkey == IMC.ctl_P): #ctl/cmd-P
                self.goToPage()
            elif (kkey == IMC.ctl_F) or (kkey == IMC.ctl_G): # ctl/cmd f/g
                self.doFind(kkey)
            else: # one of the keys we support but not in this panel
                event.ignore() # so clear the accepted flag
        else: # not one of our keys at all
            event.ignore() # ensure the accepted flag is off
        if not event.isAccepted() : # if we didn't handle it, pass it up
            super(notesEditor, self).keyPressEvent(event)

    # on ctl-alt-l (mac: opt-cmd-l), insert the current edit line number in
    # notes as {nnn}
    def insertLine(self):
        tc = self.textCursor()
        bn = IMC.editWidget.textCursor().blockNumber() # line num
        tc.insertText(u"{{{0}}}".format(bn))

    # on ctl-l (mac: cmd-l) look for a {nnn} line number "near" our cursor in
    # the notes. Strategy: find-backwards for '{', the forward for regex (\d+)\}
    def goToLine(self):
        tc = self.document().find(QString(u'{'),
                                  self.textCursor(), QTextDocument.FindBackward)
        if not tc.isNull(): # found it, or one. tc now selects the {
            re = QRegExp(QString(u'\{\d+\}'))
            tc.setPosition(tc.selectionStart()) # start looking left of {
            tc = self.document().find(re,tc)
            if not tc.isNull(): # found that.
                self.setTextCursor(tc) # highlight the found string
                qs = tc.selectedText() # "{nnn}"
                qs.remove(0,1) # "nnn}"
                qs.chop(1) # "nnn"
                # toInt returns a tuple, (int, flag) where flag is false
                # if the conversion fails. In this case it cannot fail
                # since we found \d+ in the first place. However, the
                # number might be invalid as a line number.
                (bn,flg) = qs.toInt() # line number as int
                doc = IMC.editWidget.document() # main document
                tb = doc.findBlockByNumber(bn) # text block number bn
                if tb.isValid(): # if it exists,
                    tc = IMC.editWidget.textCursor() # cursor on main doc
                    tc.setPosition(tb.position()) # set it on block
                    IMC.editWidget.setTextCursor(tc) # make it visible
                    IMC.editWidget.setFocus(Qt.TabFocusReason)
            else: # no {ddd} seen
                pqMsgs.beep()
        else: # no { preceding the cursor on same line
            pqMsgs.beep()
    # Insert current page number as [ppp]. Conveniently, pqPngs saves the
    # index of the current page in the page table whenever the cursor moves.
    # (BUG: if there is no pngs folder, that won't happen)
    def insertPage(self):
        tc = self.textCursor()
        if IMC.currentImageNumber is not None:
            tc.insertText("[{0}]".format(unicode(IMC.currentImageNumber)))

    # on ^p, look for [ppp] "near" our cursor in notes, and if found, tell
    # editor to go to that page text. See above for strategy.
    def goToPage(self):
        tc = self.document().find(QString(u'['),
                                  self.textCursor(), QTextDocument.FindBackward)
        if not tc.isNull(): # found it, or one. tc now selects the [
            re = QRegExp(QString(u'\[\d+\]'))
            tc.setPosition(tc.selectionStart()) # start looking left of [
            tc = self.document().find(re,tc)
            if not tc.isNull(): # found that.
                self.setTextCursor(tc) # highlight the found string
                qs = tc.selectedText() # "[nnn]"
                qs.remove(0,1) # "nnn]"
                qs.chop(1) # "nnn"
                (pn,flg) = qs.toInt() # page number as int
                pn -= 1 # index to that page in the page table
                if (pn >= 0) and (pn < IMC.pageTable.size()) :
                    etc = IMC.pageTable.getCursor(pn) # cursor for that page
                    doc = IMC.editWidget.document() # main document
                    IMC.editWidget.setTextCursor(etc) # make it visible
                    IMC.editWidget.setFocus(Qt.TabFocusReason)
                else: # should not occur
                    pqMsgs.beep()
            else: # no [ppp] seen
                pqMsgs.beep()
        else: # no [ preceding the cursor on same line
            pqMsgs.beep()

    # Do a simple find. getFindMsg returns (ok,find-text). This is a VERY
    # simple find from the present cursor position downward, case-insensitive.
    # If we get no hit we try once more from the top, thus in effect wrapping.
    def doFind(self,kkey):
        if (kkey == IMC.ctl_F) or (self.findText.isEmpty()) :
            # ctl+F, or ctl+G but no previous find done, show the find dialog
            # with a COPY of current selection as pqMsgs might truncate it
            prepText = QString(self.textCursor().selectedText())
            (ok, self.findText) = pqMsgs.getFindMsg(self,prepText)
        # dialog or no dialog, we should have some findText now
        if not self.findText.isEmpty() :
            if not self.find(self.findText): # no hits going down
                self.moveCursor(QTextCursor.Start) # go to top
                if not self.find(self.findText): # still no hit
                    pqMsgs.beep()
Beispiel #22
0
class MainForm(QDialog):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)
        
        self.filename = QString()
        self.scene = QGraphicsScene(self)
        self.view = GraphicsView(self.scene)

        self.view.setScene(self.scene)
        buttonLayout = QVBoxLayout()
        for text, slot in (
                ("&Open", self.addPixmap),
                ("&Quit", self.accept)):
            button = QPushButton(text)
            self.connect(button, SIGNAL("clicked()"), slot)
            if text == "&Quit":
                buttonLayout.addStretch(1)
            buttonLayout.addWidget(button)
        buttonLayout.addStretch()
        layout = QHBoxLayout()
        layout.addWidget(self.view, 1)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)
        self.setWindowTitle("Petal Picker")

    def addPixmap(self):
        path = (QFileInfo(self.filename).path()
                if not self.filename.isEmpty() else ".")
        fname = QFileDialog.getOpenFileName(self,
                "Add Pixmap", path,
                "Pixmap Files (*.bmp *.jpg *.png *.xpm)")
        if fname.isEmpty(): return
        self.createPixmapItem(QPixmap(fname))


    def createPixmapItem(self, pixmap, matrix=QMatrix()):
        global PIX
        item = QGraphicsPixmapItem(pixmap)
        PIX = item
#        item.setFlags(QGraphicsItem.ItemIsSelectable|
#                      QGraphicsItem.ItemIsMovable)
        item.setMatrix(matrix)
        self.scene.clearSelection()
        
        for i in self.scene.items():
            self.scene.removeItem(i)
        
        self.scene.addItem(item)
        self.view.fitInView(item,Qt.KeepAspectRatio)
        
        
        global DIRTY
        DIRTY = True
        
    def accept(self):
        global DIRTY
        if not DIRTY: QDialog.accept(self)
        if DIRTY:
            if self.confirm(): QDialog.accept(self)
            else: return

    def confirm(self):
        global DIRTY
        if (DIRTY and QMessageBox.question(self,
                            "Really Quit?",
                            "Really Quit?",
                            QMessageBox.Yes|QMessageBox.No) ==
            QMessageBox.Yes): return True
        else: return False
Beispiel #23
0
class helpDisplay(QWebView):
    def __init__(self, parent=None):
        super(helpDisplay, self).__init__(parent)
        # make page unmodifiable
        self.page().setContentEditable(False)
        # initialize settings
        # Find out the nearest font to Palatino
        qf = QFont()
        qf.setStyleStrategy(QFont.PreferAntialias + QFont.PreferMatch)
        qf.setStyleHint(QFont.Serif)
        qf.setFamily(QString(u'Palatino'))
        qfi = QFontInfo(qf)
        # set the default font to that serif font
        self.settings().setFontFamily(QWebSettings.StandardFont, qfi.family())
        self.settings().setFontSize(QWebSettings.DefaultFontSize, 16)
        self.settings().setFontSize(QWebSettings.MinimumFontSize, 6)
        self.settings().setFontSize(QWebSettings.MinimumLogicalFontSize, 6)
        self.textZoomFactor = 1.0
        self.setTextSizeMultiplier(self.textZoomFactor)
        self.settings().setAttribute(QWebSettings.JavascriptEnabled, False)
        self.settings().setAttribute(QWebSettings.JavaEnabled, False)
        self.settings().setAttribute(QWebSettings.PluginsEnabled, False)
        self.settings().setAttribute(QWebSettings.ZoomTextOnly, True)
        #self.settings().setAttribute(QWebSettings.SiteSpecificQuirksEnabled, False)
        self.userFindText = QString()
        # Look for pqHelp.html in the app folder and copy its text into
        # a local buffer. If it isn't found, put a message there instead.
        # We need to keep it in order to implement the "back" function.
        helpPath = os.path.join(IMC.appBasePath, u'pqHelp.html')
        helpFile = QFile(helpPath)
        if not helpFile.exists():
            self.HTMLstring = QString('''<p>Unable to locate pqHelp.html.</p>
	    <p>Looking in {0}'''.format(helpPath))
        elif not helpFile.open(QIODevice.ReadOnly):
            self.HTMLstring = QString('''<p>Unable to open pqHelp.html.</p>
	    <p>Looking in {0}</p><p>Error code {1}</p>'''.format(
                helpPath, helpFile.error()))
        else:
            helpStream = QTextStream(helpFile)
            helpStream.setCodec('ISO8859-1')
            self.HTMLstring = helpStream.readAll()
        self.setHtml(self.HTMLstring)

    # Re-implement the parent's keyPressEvent in order to provide a simple
    # find function and font-zoom from ctl-plus/minus. We start the view at
    # 16 points and textSizeMultiplier of 1.0. Each time the user hits ctl-minus
    # we deduct 0.0625 from the multiplier, and for each ctl-+ we add 0.0625
    # (1/16) to the multiplier. This ought to cause the view to change up or
    # down by one point. We set a limit of 0.375 (6 points) at the low
    # end and 4.0 (64 points) at the top.
    def keyPressEvent(self, event):
        #pqMsgs.printKeyEvent(event)
        kkey = int(int(event.modifiers()) & IMC.keypadDeModifier) | int(
            event.key())
        if (kkey == IMC.ctl_F) or (kkey == IMC.ctl_G):  # ctl/cmd f/g
            event.accept()
            self.doFind(kkey)
        elif (kkey in IMC.zoomKeys):  # ctl-plus/minus
            zfactor = 0.0625  # zoom in
            if (kkey == IMC.ctl_minus):
                zfactor = -zfactor  # zoom out
            zfactor += self.textZoomFactor
            if (zfactor > 0.374) and (zfactor < 4.0):
                self.textZoomFactor = zfactor
                self.setTextSizeMultiplier(self.textZoomFactor)
        elif (kkey in IMC.backKeys):  # ctl-B/[/left
            if self.page().history().currentItemIndex() > 1:
                self.page().history().back()
            else:
                self.setHtml(self.HTMLstring)
                self.page().history().clear()
        else:  # not ctl/cmd f or ctl/cmd-plus/minus, so,
            event.ignore()
            super(helpDisplay, self).keyPressEvent(event)

    # Implement a simple Find/Find-Next, same logic as in pqNotes,
    # but adjusted for our widget being a webview, and it does the
    # wraparound for us.
    def doFind(self, kkey):
        if (kkey == IMC.ctl_F) or (self.userFindText.isEmpty()):
            # ctl+F, or ctl+G but no previous find done, show the find dialog
            # with a COPY of current selection as pqMsgs might truncate it
            prepText = QString(self.page().selectedText())
            (ok, self.userFindText) = pqMsgs.getFindMsg(self, prepText)
        # We should have some findText now, either left from previous find
        # on a ctl-G, or entered by user. If none, then user cleared dialog.
        if not self.userFindText.isEmpty():
            if not self.page().findText(self.userFindText,
                                        QWebPage.FindWrapsAroundDocument):
                pqMsgs.beep()
class Lexer(object):
    """ 
    Class to implement the lexer mixin class.
    """
    def __init__(self):
        """
        Constructor
        """
        self.commentString = QString('')
        self.streamCommentString = {
            'start' : QString(''),
            'end' : QString('')
        }
        self.boxCommentString = {
            'start' : QString(''),
            'middle' : QString(''),
            'end' : QString('')
        }
        
        # last indented line wrapper
        self.lastIndented = -1
        self.lastIndentedIndex = -1
        
        # always keep tabs (for languages where tabs are esential
        self._alwaysKeepTabs = False
    
    def initProperties(self):
        """
        Public slot to initialize the properties.
        """
        # default implementation is a do nothing
        return
        
    def commentStr(self):
        """
        Public method to return the comment string.
        
        @return comment string (QString)
        """
        return self.commentString
        
    def canBlockComment(self):
        """
        Public method to determine, whether the lexer language supports a block comment.
        
        @return flag (boolean)
        """
        return not self.commentString.isEmpty()
        
    def streamCommentStr(self):
        """
        Public method to return the stream comment strings.
        
        @return stream comment strings (dictionary with two QStrings)
        """
        return self.streamCommentString
        
    def canStreamComment(self):
        """
        Public method to determine, whether the lexer language supports a stream comment.
        
        @return flag (boolean)
        """
        return \
            (not self.streamCommentString['start'].isEmpty()) and \
            (not self.streamCommentString['end'].isEmpty())
        
    def boxCommentStr(self):
        """
        Public method to return the box comment strings.
        
        @return box comment strings (dictionary with three QStrings)
        """
        return self.boxCommentString
        
    def canBoxComment(self):
        """
        Public method to determine, whether the lexer language supports a box comment.
        
        @return flag (boolean)
        """
        return \
            (not self.boxCommentString['start'].isEmpty()) and \
            (not self.boxCommentString['middle'].isEmpty()) and \
            (not self.boxCommentString['end'].isEmpty())
        
    def alwaysKeepTabs(self):
        """
        Public method to check, if tab conversion is allowed.
        
        @return flag indicating to keep tabs (boolean)
        """
        return self._alwaysKeepTabs
        
    def hasSmartIndent(self):
        """
        Public method indicating whether lexer can do smart indentation.
        
        @return flag indicating availability of smartIndentLine and
            smartIndentSelection methods (boolean)
        """
        return hasattr(self, 'getIndentationDifference')
        
    def smartIndentLine(self, editor):
        """
        Public method to handle smart indentation for a line.
        
        @param editor reference to the QScintilla editor object
        """
        cline, cindex = editor.getCursorPosition()
        
        # get leading spaces
        lead_spaces = editor.indentation(cline)
        
        # get the indentation difference
        indentDifference = self.getIndentationDifference(cline, editor)
        
        if indentDifference != 0:
            editor.setIndentation(cline, lead_spaces + indentDifference)
            editor.setCursorPosition(cline, cindex + indentDifference)
        
        self.lastIndented = cline
        
    def smartIndentSelection(self, editor):
        """
        Public method to handle smart indentation for a selection of lines.
        
        Note: The assumption is, that the first line determines the new
              indentation level.
        
        @param editor reference to the QScintilla editor object
        """
        if not editor.hasSelectedText():
            return
            
        # get the selection
        lineFrom, indexFrom, lineTo, indexTo = editor.getSelection()
        if lineFrom != self.lastIndented:
            self.lastIndentedIndex = indexFrom
        
        if indexTo == 0:
            endLine = lineTo - 1
        else:
            endLine = lineTo
        
        # get the indentation difference
        indentDifference = self.getIndentationDifference(lineFrom, editor)
        
        editor.beginUndoAction()
        # iterate over the lines
        for line in range(lineFrom, endLine+1):
            editor.setIndentation(line, 
                editor.indentation(line) + indentDifference)
        editor.endUndoAction()
        
        if self.lastIndentedIndex != 0:
            indexStart = indexFrom + indentDifference
        else:
            indexStart = 0
        if indexStart < 0:
            indexStart = 0
        indexEnd = indexTo != 0 and (indexTo + indentDifference) or 0
        if indexEnd < 0:
            indexEnd = 0
        editor.setSelection(lineFrom, indexStart, lineTo, indexEnd)
        
        self.lastIndented = lineFrom
    
    def autoCompletionWordSeparators(self):
        """
        Public method to return the list of separators for autocompletion.
        
        @return list of separators (QStringList)
        """
        return QStringList()
    
    def isCommentStyle(self, style):
        """
        Public method to check, if a style is a comment style.
        
        @return flag indicating a comment style (boolean)
        """
        return True
    
    def isStringStyle(self, style):
        """
        Public method to check, if a style is a string style.
        
        @return flag indicating a string style (boolean)
        """
        return True
    
    def keywords(self, kwSet):
        """
        Public method to get the keywords.
        
        @param kwSet number of the keyword set (integer)
        @return string giving the keywords (string) or None
        """
        keywords_ = Preferences.getEditorKeywords(self.language())
        if not keywords_.isEmpty():
            kw = unicode(keywords_[kwSet])
            if kw == "":
                return None
            else:
                return kw
        else:
            return self.defaultKeywords(kwSet)
 def enableFindButton(self,text):
     print type(text),":",len(text)
     print(text)
     t = QString(text)
     self.findButton.setEnabled(not t.isEmpty())
Beispiel #26
0
class notesEditor(QPlainTextEdit):
    def __init__(self, parent=None, fontsize=12):
        super(notesEditor, self).__init__(parent)
        # Do not allow line-wrap; horizontal scrollbar appears when required.
        self.setLineWrapMode(QPlainTextEdit.NoWrap)
        # get same font as main editor uses
        self.setFont(pqMsgs.getMonoFont(12, False))
        self.connect(self.document(), SIGNAL("modificationChanged(bool)"),
                     self.eek)
        self.findText = QString()

    # called from pqEdit.clear()
    def clear(self):
        self.clearing = True
        self.document().clear()
        self.document().setModified(False)
        self.findText = QString()
        self.clearing = False

    # slot to receive the modificationChanged(bool) signal from our document.
    # if it indicates we are modified, set needMetadataSave true if it isn't
    # already. Should the user undo out of all changes, modval will be false
    # and we clear our flag, possibly making the flag 0.
    def eek(self, modval):
        if not self.clearing:
            if modval:
                IMC.needMetadataSave |= IMC.notePanelChanged
            else:
                IMC.needMetadataSave &= (0xff ^ IMC.notePanelChanged)
        IMC.mainWindow.setWinModStatus()

    # Re-implement the parent's keyPressEvent in order to provide zoom:
    # ctrl-plus and ctrl-minus step the font size one point. Other keys:
    # shift-ctl-L inserts the current line number as {nnn}
    # ctl-L looks for a nearby {nnn} (braces required), selects it, and
    # tells the main editor to jump to that line.
    # shift-ctl-P insert the current page (scan) number as [nnn]
    # ctl-P looks for a nearby [nnn] (brackets required), selects it, and
    # tells the main editor to jump to that page position.
    def keyPressEvent(self, event):
        #pqMsgs.printKeyEvent(event)
        kkey = int(int(event.modifiers()) & IMC.keypadDeModifier) | int(
            event.key())
        if kkey in IMC.keysOfInterest:
            # tentatively assume we will process this key
            event.accept()
            if kkey in IMC.zoomKeys:
                n = (-1) if (kkey == IMC.ctl_minus) else 1
                p = self.fontInfo().pointSize() + n
                if (p > 3) and (p < 65):  # don't let's get ridiculous, hmm?
                    f = self.font()  # so get our font,
                    f.setPointSize(p)  # change its point size +/-
                    self.setFont(f)  # and put the font back
            elif (kkey == IMC.ctl_alt_M):  # ctrl/cmd-m with shift
                self.insertLine()
            elif (kkey == IMC.ctl_M):  # ctrl/cmd-m (no shift)
                self.goToLine()
            elif (kkey == IMC.ctl_alt_P):  # ctl/cmd-p
                self.insertPage()
            elif (kkey == IMC.ctl_P):  #ctl/cmd-P
                self.goToPage()
            elif (kkey == IMC.ctl_F) or (kkey == IMC.ctl_G):  # ctl/cmd f/g
                self.doFind(kkey)
            else:  # one of the keys we support but not in this panel
                event.ignore()  # so clear the accepted flag
        else:  # not one of our keys at all
            event.ignore()  # ensure the accepted flag is off
        if not event.isAccepted():  # if we didn't handle it, pass it up
            super(notesEditor, self).keyPressEvent(event)

    # on ctl-alt-l (mac: opt-cmd-l), insert the current edit line number in
    # notes as {nnn}
    def insertLine(self):
        tc = self.textCursor()
        bn = IMC.editWidget.textCursor().blockNumber()  # line num
        tc.insertText(u"{{{0}}}".format(bn))

    # on ctl-l (mac: cmd-l) look for a {nnn} line number "near" our cursor in
    # the notes. Strategy: find-backwards for '{', the forward for regex (\d+)\}
    def goToLine(self):
        tc = self.document().find(QString(u'{'), self.textCursor(),
                                  QTextDocument.FindBackward)
        if not tc.isNull():  # found it, or one. tc now selects the {
            re = QRegExp(QString(u'\{\d+\}'))
            tc.setPosition(tc.selectionStart())  # start looking left of {
            tc = self.document().find(re, tc)
            if not tc.isNull():  # found that.
                self.setTextCursor(tc)  # highlight the found string
                qs = tc.selectedText()  # "{nnn}"
                qs.remove(0, 1)  # "nnn}"
                qs.chop(1)  # "nnn"
                # toInt returns a tuple, (int, flag) where flag is false
                # if the conversion fails. In this case it cannot fail
                # since we found \d+ in the first place. However, the
                # number might be invalid as a line number.
                (bn, flg) = qs.toInt()  # line number as int
                doc = IMC.editWidget.document()  # main document
                tb = doc.findBlockByNumber(bn)  # text block number bn
                if tb.isValid():  # if it exists,
                    tc = IMC.editWidget.textCursor()  # cursor on main doc
                    tc.setPosition(tb.position())  # set it on block
                    IMC.editWidget.setTextCursor(tc)  # make it visible
                    IMC.editWidget.setFocus(Qt.TabFocusReason)
            else:  # no {ddd} seen
                pqMsgs.beep()
        else:  # no { preceding the cursor on same line
            pqMsgs.beep()

    # Insert current page number as [ppp]. Conveniently, pqPngs saves the
    # index of the current page in the page table whenever the cursor moves.
    # (BUG: if there is no pngs folder, that won't happen)
    def insertPage(self):
        tc = self.textCursor()
        if IMC.currentImageNumber is not None:
            tc.insertText("[{0}]".format(unicode(IMC.currentImageNumber)))

    # on ^p, look for [ppp] "near" our cursor in notes, and if found, tell
    # editor to go to that page text. See above for strategy.
    def goToPage(self):
        tc = self.document().find(QString(u'['), self.textCursor(),
                                  QTextDocument.FindBackward)
        if not tc.isNull():  # found it, or one. tc now selects the [
            re = QRegExp(QString(u'\[\d+\]'))
            tc.setPosition(tc.selectionStart())  # start looking left of [
            tc = self.document().find(re, tc)
            if not tc.isNull():  # found that.
                self.setTextCursor(tc)  # highlight the found string
                qs = tc.selectedText()  # "[nnn]"
                qs.remove(0, 1)  # "nnn]"
                qs.chop(1)  # "nnn"
                (pn, flg) = qs.toInt()  # page number as int
                pn -= 1  # index to that page in the page table
                if (pn >= 0) and (pn < IMC.pageTable.size()):
                    etc = IMC.pageTable.getCursor(pn)  # cursor for that page
                    doc = IMC.editWidget.document()  # main document
                    IMC.editWidget.setTextCursor(etc)  # make it visible
                    IMC.editWidget.setFocus(Qt.TabFocusReason)
                else:  # should not occur
                    pqMsgs.beep()
            else:  # no [ppp] seen
                pqMsgs.beep()
        else:  # no [ preceding the cursor on same line
            pqMsgs.beep()

    # Do a simple find. getFindMsg returns (ok,find-text). This is a VERY
    # simple find from the present cursor position downward, case-insensitive.
    # If we get no hit we try once more from the top, thus in effect wrapping.
    def doFind(self, kkey):
        if (kkey == IMC.ctl_F) or (self.findText.isEmpty()):
            # ctl+F, or ctl+G but no previous find done, show the find dialog
            # with a COPY of current selection as pqMsgs might truncate it
            prepText = QString(self.textCursor().selectedText())
            (ok, self.findText) = pqMsgs.getFindMsg(self, prepText)
        # dialog or no dialog, we should have some findText now
        if not self.findText.isEmpty():
            if not self.find(self.findText):  # no hits going down
                self.moveCursor(QTextCursor.Start)  # go to top
                if not self.find(self.findText):  # still no hit
                    pqMsgs.beep()