Example #1
0
 def __init__(self):
     QObject.__init__(self)
     self._createdActions = []
     self._createdMenus = []
     self._currentDocument = core.workspace().currentDocument()  # probably None
     model = core.actionManager()
     
     for menu in _MENUS:
         if menu[2]:
             menuObj = model.addMenu(menu[0], menu[1], QIcon(':/enkiicons/' + menu[2]))
         else:
             menuObj = model.addMenu(menu[0], menu[1])
         menuObj.setEnabled(False)
         self._createdMenus.append(menuObj)
     
     for command, path, text, shortcut, icon in _ACTIONS:
         actObject = QAction(text, self)
         if shortcut:
             actObject.setShortcut(shortcut)
         if icon:
             actObject.setIcon(QIcon(':/enkiicons/' + icon))
         actObject.setData(command)
         actObject.setEnabled(False)
         actObject.triggered.connect(self.onAction)
         model.addAction(path, actObject)
         self._createdActions.append(actObject)
     
     core.workspace().currentDocumentChanged.connect(self.onCurrentDocumentChanged)
Example #2
0
 def hide(self):
     """Reimplemented function.
     Sends signal, returns focus to workspace
     """
     super(SearchWidget, self).hide()
     core.workspace().focusCurrentDocument()
     self.visibilityChanged.emit(self.isVisible())
Example #3
0
 def test_logWindowSplitter4(self):
     """User actively hide log window, Enki should be able to remember this.
     """
     document1 = self.createFile('file1.rst', '.. file1::')
     document2 = self.createFile('file2.rst', '')
     document3 = self.createFile('file3.rst', '.. file3::')
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document1))
     # Wait for events to process. See qWait comment above.
     QTest.qWait(100)
     # User manually change error state splitter size such that log window
     # is hidden.
     self._widget().splitter.setSizes([1, 0])
     self._widget().splitter.splitterMoved.emit(1, 1)
     # Switch to document 2. Log window is hidden now.
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document2))
     # Wait for events to process. See qWait comment above.
     QTest.qWait(100)
     self.assertFalse(self._widget().splitter.sizes()[1])
     # Switch to document 3. Log window should keep hidden.
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document3))
     # Wait for events to process. See qWait comment above.
     QTest.qWait(100)
     self.assertFalse(self._widget().splitter.sizes()[1])
Example #4
0
    def test_previewCheck2b(self):
        """Check for double builds.
        """
        self._doBasicSphinxConfig()
        webViewContent, logContent = self._doBasicSphinxTest('rst')
        # After the inital ``_clear`` then a build with text, we expect to
        # see two builds.
        self.assertEqual(self._dock()._sphinxConverter._SphinxInvocationCount,
                         2)

        # Inserting a character when auto-save is enabled can cause a double
        # build: the save made in preparation for the first build also invokes
        # the second build.
        qp = core.workspace().currentDocument().qutepart
        core.config()['Sphinx']['BuildOnSave'] = False
        with self._WaitForHtmlReady(timeout=10000, numEmittedExpected=1):
            qp.lines[0] += ' '
        self.assertEqual(self._dock()._sphinxConverter._SphinxInvocationCount,
                         3)

        # Inserting a space at the end of the line can cause a double build,
        # since the StripTrailingWhitespace option deletes the space, then
        # the auto-save and build code restores it.
        #
        # However, double builds still only produce a single ``loadFinished``
        # signal.
        core.config()["Qutepart"]["StripTrailingWhitespace"] = True
        qp = core.workspace().currentDocument().qutepart
        with self._WaitForHtmlReady(timeout=10000, numEmittedExpected=1):
            qp.appendPlainText('\nTesting...')
        self.assertEqual(self._dock()._sphinxConverter._SphinxInvocationCount,
                         4)
Example #5
0
 def test_logWindowSplitter2(self):
     """Feature 2. All build-with-error files' splitter size are connected.
     """
     document1 = self.createFile('file1.rst', '.. file1::')
     document2 = self.createFile('file2.rst', '.. file2::')
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document2))
     # Change splitter location of document 2.
     newSplitterSize = [124, 123]
     self._widget().splitter.setSizes(newSplitterSize)
     # Calling setSizes directly will not trigger splitter's ``splitterMoved``
     # signal. We need to manually emit this signal with two arguments (not
     # important here.)
     self._widget().splitter.splitterMoved.emit(newSplitterSize[0], 1)
     # Assert preview window and log window are visible and are of almost equal size
     self.assertNotIn(0, self._widget().splitter.sizes())
     self.assertAlmostEqual(self._widget().splitter.sizes()[0],
                            self._widget().splitter.sizes()[1],
                            delta=10)
     # Switch to document 1, make sure its splitter size is changed, too.
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document1))
     self.assertNotIn(0, self._widget().splitter.sizes())
     self.assertAlmostEqual(self._widget().splitter.sizes()[0],
                            self._widget().splitter.sizes()[1],
                            delta=10)
Example #6
0
 def test_logWindowSplitter3a(self):
     """Feature 1,2,3. A combination of the above test cases.
     """
     document1 = self.createFile('file1.rst', '.. file1::')
     document2 = self.createFile('file2.rst', '')
     document3 = self.createFile('file3.rst', '.. file3::')
     self._assertHtmlReady(lambda: None)
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document1))
     # Wait for events to process. See qWait comment above.
     QTest.qWait(100)
     # Change splitter setting of document 1.
     newSplitterSize = [125, 124]
     self._widget().splitter.setSizes(newSplitterSize)
     self._widget().splitter.splitterMoved.emit(newSplitterSize[0], 1)
     # Assert log window and preview window are visible and are of almost
     # equal size.
     self.assertNotIn(0, self._widget().splitter.sizes())
     self.assertAlmostEqual(self._widget().splitter.sizes()[0],
                            self._widget().splitter.sizes()[1],
                            delta=10)
     # Switch to an error-free document, assert log window hidden.
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document2))
     # Wait for events to process. See qWait comment above.
     QTest.qWait(100)
     self.assertFalse(self._widget().splitter.sizes()[1])
     # Switch to file3 which will cause build error, check splitter size.
     self._assertHtmlReady(
         lambda: core.workspace().setCurrentDocument(document3))
     self.assertNotIn(0, self._widget().splitter.sizes())
     self.assertAlmostEqual(self._widget().splitter.sizes()[0],
                            self._widget().splitter.sizes()[1],
                            delta=10)
Example #7
0
    def _searchWord(self, forward=True):
        """Do search in file operation. Will select next found item
        if updateWidget is True, search widget line edit will color will be set according to result
        """
        document = core.workspace().currentDocument()

        word, wordStartAbsPos, wordEndAbsPos = document.wordUnderCursor()
        if word is None:
            return
        
        regExp = re.compile('\\b%s\\b' % re.escape(word))
        text = document.text()

        # avoid matching word under cursor
        if forward:
            startPoint = wordEndAbsPos
        else:
            startPoint = wordStartAbsPos
        
        match, matches = self._searchInText(regExp, document.text(), startPoint, forward)
        if match is not None:
            document.goTo(absPos = match.start(), selectionLength = len(match.group(0)))
            core.mainWindow().statusBar().showMessage('Match %d of %d' % \
                                                      (matches.index(match) + 1, len(matches)), 3000)
        else:
            self._resetSelection(core.workspace().currentDocument())
Example #8
0
    def test_4(self):
        # dock remembers its Enabled/Disabled state
        ruby = self.createFile('source.rb', RUBY_SOURCE)
        txt = self.createFile('file.txt', "asdf")

        dock = self.findDock('&Navigator')

        core.workspace().setCurrentDocument(ruby)

        self.retryUntilPassed(200, lambda: self.assertTrue(dock.isVisible()))

        self.keyClicks('N', Qt.AltModifier)
        self.keyClick(Qt.Key_Escape)
        self.assertFalse(dock.isVisible())
        self.assertFalse(core.config()['Navigator']['Enabled'])

        core.workspace().setCurrentDocument(txt)
        core.workspace().setCurrentDocument(ruby)
        self.assertFalse(dock.isVisible())

        self.keyClicks('N', Qt.AltModifier)
        self.assertTrue(dock.isVisible())
        self.assertTrue(core.config()['Navigator']['Enabled'])

        core.workspace().setCurrentDocument(txt)
        core.workspace().setCurrentDocument(ruby)
        self.assertTrue(dock.isVisible())
Example #9
0
 def execute(self):
     path = self._clickedPath
     fullPath = os.path.join(core.project().path(), path)
     if self._line is None:
         core.workspace().goTo(fullPath)
     else:
         core.workspace().goTo(fullPath, line=self._line - 1)
Example #10
0
    def _saveSession(self, showWarnings=True):
        """Enki is going to be terminated.
        Save session
        """
        fileList = [
            document.filePath() for document in core.workspace().documents()
            if document.filePath() is not None and os.path.exists(
                document.filePath()) and not '/.git/' in document.filePath()
            and not (document.fileName().startswith('svn-commit')
                     and document.fileName().endswith('.tmp'))
        ]

        if not fileList:
            return

        currentPath = None
        if core.workspace().currentDocument() is not None:
            currentPath = core.workspace().currentDocument().filePath()

        session = {
            'current': currentPath,
            'opened': fileList,
            'project': core.project().path()
        }

        enki.core.json_wrapper.dump(_SESSION_FILE_PATH, 'session', session,
                                    showWarnings)
Example #11
0
    def execute(self):
        """Execute the command
        """
        if self._isGlob(self._path):
            expandedPathes = []
            for path in glob.iglob(os.path.expanduser(self._path)):
                try:
                    path = os.path.abspath(path)
                except OSError:
                    pass
                expandedPathes.append(path)

            # 2 loops, because we should open absolute pathes. When opening files, enki changes its current directory
            for path in expandedPathes:
                if self._line is None:
                    core.workspace().goTo(path)
                else:
                    core.workspace().goTo(path, line=self._line - 1)

        else:  # file may be not existing
            path = os.path.expanduser(self._path)
            if os.path.isfile(path):
                path = os.path.abspath(path)
                if self._line is None:
                    core.workspace().goTo(path)
                else:
                    core.workspace().goTo(path, line=self._line - 1)
            else:
                core.workspace().createEmptyNotSavedDocument(path)
Example #12
0
    def setData(self, index, value, role=Qt.EditRole):
        document = self.document(index)
        newPath = value

        if newPath == document.filePath():
            return False

        if newPath == '/dev/null':
            try:
                os.remove(document.filePath())
            except (OSError, IOError) as ex:
                QMessageBox.critical(core.mainWindow(), 'Not this time',
                                     'The OS thinks it needs the file')
                return False
            core.workspace().closeDocument(document)
        else:
            try:
                os.rename(document.filePath(), newPath)
            except (OSError, IOError) as ex:
                QMessageBox.critical(core.mainWindow(),
                                     'Failed to rename file', str(ex))
                return False
            else:
                document.setFilePath(newPath)
                document.saveFile()
                self.dataChanged.emit(index, index)

        return True
Example #13
0
    def __init__(self, plugin):
        QFrame.__init__(self, core.workspace())
        self._mode = None
        self.plugin = plugin
        from PyQt4 import uic  # lazy import for better startup performance

        uic.loadUi(os.path.join(os.path.dirname(__file__), "SearchWidget.ui"), self)

        self.cbSearch.setCompleter(None)
        self.cbReplace.setCompleter(None)
        self.cbMask.setCompleter(None)

        self.fsModel = QDirModel(self.cbPath.lineEdit())
        self.fsModel.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        self.cbPath.lineEdit().setCompleter(QCompleter(self.fsModel, self.cbPath.lineEdit()))
        # TODO QDirModel is deprecated but QCompleter does not yet handle
        # QFileSystemodel - please update when possible."""
        self.cbSearch.setCompleter(None)
        self.pbSearchStop.setVisible(False)
        self.pbReplaceCheckedStop.setVisible(False)

        self._progress = QProgressBar(self)
        self._progress.setAlignment(Qt.AlignCenter)
        self._progress.setToolTip(self.tr("Search in progress..."))
        self._progress.setMaximumSize(QSize(80, 16))
        core.mainWindow().statusBar().insertPermanentWidget(1, self._progress)
        self._progress.setVisible(False)

        # cd up action
        self.tbCdUp = QToolButton(self.cbPath.lineEdit())
        self.tbCdUp.setIcon(QIcon(":/enkiicons/go-up.png"))
        self.tbCdUp.setCursor(Qt.ArrowCursor)
        self.tbCdUp.installEventFilter(self)  # for drawing button

        self.cbSearch.installEventFilter(self)  # for catching Tab and Shift+Tab
        self.cbReplace.installEventFilter(self)  # for catching Tab and Shift+Tab
        self.cbPath.installEventFilter(self)  # for catching Tab and Shift+Tab
        self.cbMask.installEventFilter(self)  # for catching Tab and Shift+Tab

        self._closeShortcut = QShortcut(QKeySequence("Esc"), self)
        self._closeShortcut.setContext(Qt.WidgetWithChildrenShortcut)
        self._closeShortcut.activated.connect(self.hide)

        # connections
        self.cbSearch.lineEdit().textChanged.connect(self._onSearchRegExpChanged)

        self.cbSearch.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbReplace.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbPath.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbMask.lineEdit().returnPressed.connect(self._onReturnPressed)

        self.cbRegularExpression.stateChanged.connect(self._onSearchRegExpChanged)
        self.cbCaseSensitive.stateChanged.connect(self._onSearchRegExpChanged)

        self.tbCdUp.clicked.connect(self._onCdUpPressed)

        core.mainWindow().hideAllWindows.connect(self.hide)
        core.workspace().currentDocumentChanged.connect(
            lambda old, new: self.setVisible(self.isVisible() and new is not None)
        )
Example #14
0
 def terminate(self):
     """Explicitly called destructor
     """
     self._cleanupActions()
     core.workspace().documentClosed.disconnect(self._onDocumentClosed)
     core.actionManager().removeAction(self._undoClose)
     enki.core.json_wrapper.dump(_FILE_PATH, 'recent file', self._recent)
Example #15
0
    def terminate(self):
        """Uninstall the plugin
        """
        core.actionManager().removeAction('mTools/aSetSphinxPath')

        if self._dockInstalled:
            self._removeDock()

        if self._dock is not None:
            self._dock.terminate()

        core.workspace().currentDocumentChanged.disconnect(
            self._onDocumentChanged)
        core.workspace().languageChanged.disconnect(self._onDocumentChanged)
        core.uiSettingsManager().aboutToExecute.disconnect(
            self._onSettingsDialogAboutToExecute)
        core.uiSettingsManager().dialogAccepted.disconnect(
            self._onDocumentChanged)
        core.uiSettingsManager().dialogAccepted.disconnect(
            self._setSphinxActionVisibility)
        core.project().changed.disconnect(self.onFileBrowserPathChanged)

        if self._dock:
            self._dock.closed.disconnect(self._onDockClosed)
            self._dock.shown.disconnect(self._onDockShown)
            if haveWebkit:
                self._saveAction.triggered.disconnect(self._dock.onPreviewSave)
Example #16
0
    def _onRestoreSession(self):
        """Enki initialisation finished.
        Now restore session
        """
        # if have documents except 'untitled' new doc, don't restore session
        if core.workspace().currentDocument() is not None:
            return

        if not os.path.exists(_SESSION_FILE_PATH):
            return

        session = enki.core.json_wrapper.load(_SESSION_FILE_PATH, 'session',
                                              None)

        if session is not None:
            for filePath in session['opened']:
                if os.path.exists(filePath):
                    core.workspace().openFile(filePath)

            if session['current'] is not None:
                document = self._documentForPath(session['current'])
                if document is not None:  # document might be already deleted
                    core.workspace().setCurrentDocument(document)

            if 'project' in session:
                path = session['project']
                if path is not None and os.path.isdir(path):
                    core.project().open(path)
Example #17
0
    def _onRestoreSession(self):
        """Enki initialisation finished.
        Now restore session
        """
        # if have documents except 'untitled' new doc, don't restore session
        if core.workspace().currentDocument() is not None:
            return

        if not os.path.exists(_SESSION_FILE_PATH):
            return

        session = enki.core.json_wrapper.load(_SESSION_FILE_PATH, 'session', None)

        if session is not None:
            for filePath in session['opened']:
                if os.path.exists(filePath):
                    core.workspace().openFile(filePath)

            if session['current'] is not None:
                document = self._documentForPath(session['current'])
                if document is not None:  # document might be already deleted
                    core.workspace().setCurrentDocument(document)

            if 'project' in session:
                path = session['project']
                if path is not None and os.path.isdir(path):
                    core.project().open(path)
Example #18
0
    def setData(self, index, value, role=Qt.EditRole):
        document = self.document(index)
        newPath = value

        if newPath == document.filePath():
            return False

        if newPath == '/dev/null':
            try:
                os.remove(document.filePath())
            except (OSError, IOError) as ex:
                QMessageBox.critical(core.mainWindow(), 'Not this time', 'The OS thinks it needs the file')
                return False
            core.workspace().closeDocument(document)
        else:
            try:
                os.rename(document.filePath(), newPath)
            except (OSError, IOError) as ex:
                QMessageBox.critical(core.mainWindow(), 'Failed to rename file', str(ex))
                return False
            else:
                document.setFilePath(newPath)
                document.saveFile()
                self.dataChanged.emit(index, index)

        return True
Example #19
0
    def __init__(self):
        DockWidget.__init__(self, core.mainWindow(), "&Preview", QIcon(':/enkiicons/internet.png'), "Alt+P")

        from PyQt4.QtWebKit import QWebView  # delayed import, startup performance optimization
        self._view = QWebView(self)
        self._view.page().mainFrame().titleChanged.connect(self._updateTitle)
        self.setWidget(self._view)
        self.setFocusProxy(self._view)
        
        core.workspace().currentDocumentChanged.connect(self._onDocumentChanged)
        core.workspace().textChanged.connect(self._onTextChanged)
        
        self._scrollPos = {}
        self._vAtEnd = {}
        self._hAtEnd = {}
        
        self._thread = ConverterThread()
        self._thread.htmlReady.connect(self._setHtml)

        self._visiblePath = None
        
        # If we update Preview on every key pressing, freezes are sensible (GUI thread draws preview too slowly
        # This timer is used for drawing Preview 300 ms After user has stopped typing text
        self._typingTimer = QTimer()
        self._typingTimer.setInterval(300)
        self._typingTimer.timeout.connect(self._scheduleDocumentProcessing)

        self._scheduleDocumentProcessing()
Example #20
0
 def terminate(self):
     """Explicitly called destructor
     """
     self._cleanupActions()
     core.workspace().documentClosed.disconnect(self._onDocumentClosed)
     core.actionManager().removeAction(self._undoClose)
     enki.core.json_wrapper.dump(_FILE_PATH, 'recent file', self._recent)
Example #21
0
    def test_previewCheck23(self):
        """If the document is modified externally, then build on save will be
        automatically enabled. Calling scheduledocumentprocessing will not
        trigger a rebuild.
        """
        self._doBasicSphinxConfig()
        core.config()['Sphinx']['BuildOnSave'] = False
        core.config().flush()
        self.codeText = """****
head
****

"""
        self.masterText = """.. toctree::

   code.rst"""
        codeDoc = self.createFile('code.rst', self.testText)
        masterDoc = self.createFile('index.rst', self.testText)
        self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(codeDoc), timeout=10000)
        # Modify this file externally.
        with open("code.rst", 'a') as f:
            f.write(".. mytag::")
        self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(masterDoc), timeout=10000)
        core.workspace().setCurrentDocument(codeDoc)

        # Modify this file internally, then wait for the typing timer to expire.
        qp = core.workspace().currentDocument().qutepart
        self.assertEmits(lambda: qp.appendPlainText('xxx'),
                         self._dock()._typingTimer.timeout, timeoutMs=1000)
        # The typing timer invokes _scheduleDocumentProcessing. Make sure
        # it completes by waiting until all events are processed.
        base._processPendingEvents()
        # Make sure the file wasn't saved.
        self.assertTrue(qp.document().isModified())
Example #22
0
    def test_4(self):
        # dock remembers its Enabled/Disabled state
        ruby = self.createFile('source.rb', RUBY_SOURCE)
        txt = self.createFile('file.txt', "asdf")

        dock = self.findDock('&Navigator')

        core.workspace().setCurrentDocument(ruby)

        self.retryUntilPassed(200,
                              lambda: self.assertTrue(dock.isVisible()))

        self.keyClicks('N', Qt.AltModifier)
        self.keyClick(Qt.Key_Escape)
        self.assertFalse(dock.isVisible())
        self.assertFalse(core.config()['Navigator']['Enabled'])

        core.workspace().setCurrentDocument(txt)
        core.workspace().setCurrentDocument(ruby)
        self.assertFalse(dock.isVisible())

        self.keyClicks('N', Qt.AltModifier)
        self.assertTrue(dock.isVisible())
        self.assertTrue(core.config()['Navigator']['Enabled'])

        core.workspace().setCurrentDocument(txt)
        core.workspace().setCurrentDocument(ruby)
        self.assertTrue(dock.isVisible())
Example #23
0
 def __init__(self):
     """Create and install the plugin
     """
     QObject.__init__(self)
     self._action = None
     core.workspace().currentDocumentChanged.connect(self._updateAction)
     core.workspace().languageChanged.connect(self._updateAction)
Example #24
0
    def test_previewCheck18(self):
        """Switching between different files should update the log
        window accordingly.
        """
        core.config()['CodeChat']['Enabled'] = True
        # First create a warning only test case,
        document1 = self.createFile('file1.py', '# `<>_')
        # then an error only case,
        document2 = self.createFile('file2.py', '# .. h::')
        # then an error free case. Wait for the HTML to be generated before
        # continuing, so that the next assertHtmlReady won't accidentally catch
        # the HTML ready generated here.
        with self._WaitForHtmlReady():
            document3 = self.createFile('file3.py', '# <>_')
        base.waitForSignal(lambda: None, self._widget().webView.page().mainFrame().loadFinished, 200)

        # switch to document 1
        self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(document1))
        base.waitForSignal(lambda: None, self._widget().webView.page().mainFrame().loadFinished, 200)
        ps = self._widget().prgStatus
        self.assertIn('#FF9955', ps.styleSheet())
        self.assertIn('Error(s): 0, warning(s): 1', ps.text())
        # switch to document 2
        self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(document2))
        base.waitForSignal(lambda: None, self._widget().webView.page().mainFrame().loadFinished, 200)
        self.assertIn('red', ps.styleSheet())
        self.assertIn('Error(s): 1, warning(s): 0', ps.text())
        # switch to document 3
        self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(document3))
        base.waitForSignal(lambda: None, self._widget().webView.page().mainFrame().loadFinished, 200)
        self.assertEqual(self._widget().prgStatus.styleSheet(), 'QLabel {}')
        self.assertEqual(self._logText(), '')
Example #25
0
    def __init__(self, *args):
        DockWidget.__init__(self, *args)

        self.setObjectName("PreviewDock")
        self.setWindowTitle(self.tr( "&Preview" ))
        self.setWindowIcon(QIcon(':/enkiicons/internet.png'))
        self.showAction().setShortcut("Alt+P")

        from PyQt4.QtWebKit import QWebView  # delayed import, startup performance optimization
        self._view = QWebView(self)
        self._view.page().mainFrame().titleChanged.connect(self._updateTitle)
        self.setWidget(self._view)
        self.setFocusProxy(self._view)
        
        core.workspace().currentDocumentChanged.connect(self._onDocumentChanged)
        core.workspace().textChanged.connect(self._onTextChanged)
        
        self._scrollPos = {}
        self._vAtEnd = {}
        self._hAtEnd = {}
        
        self._thread = ConverterThread()
        self._thread.htmlReady.connect(self._setHtml)

        self._visiblePath = None
        self._onDocumentChanged(None, core.workspace().currentDocument())
Example #26
0
    def test_previewCheck2b(self):
        """Check for double builds.
        """
        self._doBasicSphinxConfig()
        webViewContent, logContent = self._doBasicSphinxTest('rst')
        # After the inital ``_clear`` then a build with text, we expect to
        # see two builds.
        self.assertEqual(self._dock()._sphinxConverter._SphinxInvocationCount, 2)

        # Inserting a character when auto-save is enabled can cause a double
        # build: the save made in preparation for the first build also invokes
        # the second build.
        qp = core.workspace().currentDocument().qutepart
        core.config()['Sphinx']['BuildOnSave'] = False
        with self._WaitForHtmlReady(timeout=10000, numEmittedExpected=1):
            qp.lines[0] += ' '
        self.assertEqual(self._dock()._sphinxConverter._SphinxInvocationCount, 3)

        # Inserting a space at the end of the line can cause a double build,
        # since the StripTrailingWhitespace option deletes the space, then
        # the auto-save and build code restores it.
        #
        # However, double builds still only produce a single ``loadFinished``
        # signal.
        core.config()["Qutepart"]["StripTrailingWhitespace"] = True
        qp = core.workspace().currentDocument().qutepart
        with self._WaitForHtmlReady(timeout=10000, numEmittedExpected=1):
            qp.appendPlainText('\nTesting...')
        self.assertEqual(self._dock()._sphinxConverter._SphinxInvocationCount, 4)
Example #27
0
    def _searchWord(self, forward):
        """Do search in file operation. Will select next found item
        if updateWidget is True, search widget line edit will color will be set according to result
        """
        document = core.workspace().currentDocument()

        cursor = document.qutepart.textCursor()
        if not cursor.hasSelection():
            cursor.select(cursor.WordUnderCursor)
        word = cursor.selectedText()
        wordStartAbsPos = cursor.anchor()
        wordEndAbsPos = cursor.position()

        if not word:
            return

        regExp = re.compile('\\b%s\\b' % re.escape(word))
        text = document.qutepart.text

        # avoid matching word under cursor
        if forward:
            startPoint = wordEndAbsPos
        else:
            startPoint = wordStartAbsPos

        self._updateFoundItemsHighlighting(regExp)

        match, matches = self._searchInText(regExp, document.qutepart.text, startPoint, forward)
        if match is not None:
            document.qutepart.absSelectedPosition = (match.start(), match.start() + len(match.group(0)))
            core.mainWindow().statusBar().showMessage('Match %d of %d' % \
                                                      (matches.index(match) + 1, len(matches)), 3000)
        else:
            core.workspace().currentDocument().qutepart.resetSelection()
Example #28
0
    def _onRename(self):
        """Handler for File->File System->Rename"""
        document = core.workspace().currentDocument()
        if document.qutepart.document().isModified() or \
           document.isExternallyModified() or \
           document.isExternallyRemoved() or \
           document.isNeverSaved():
            QMessageBox.warning(core.mainWindow(), 'Rename file', 'Save the file before renaming')
            return

        newPath, ok = QInputDialog.getText(core.mainWindow(), 'Rename file', 'New file name', text=document.filePath())
        if not ok:
            return

        if newPath == document.filePath():
            return

        if newPath == '/dev/null':
            try:
                os.remove(document.filePath())
            except (OSError, IOError) as ex:
                QMessageBox.critical(core.mainWindow(), 'Not this time', 'The OS thinks it needs the file')
            else:
                core.workspace().closeDocument(document)
        else:
            try:
                os.rename(document.filePath(), newPath)
            except (OSError, IOError) as ex:
                QMessageBox.critical(core.mainWindow(), 'Failed to rename file', str(ex))
            else:
                document.setFilePath(newPath)
                document.saveFile()
Example #29
0
    def execute(self):
        """Execute the command
        """
        if self._isGlob(self._path):
            expandedPathes = []
            for path in glob.iglob(os.path.expanduser(self._path)):
                try:
                    path = os.path.abspath(path)
                except OSError:
                    pass
                expandedPathes.append(path)
        
            # 2 loops, because we should open absolute pathes. When opening files, enki changes its current directory
            for path in expandedPathes:
                if self._line is None:
                    core.workspace().goTo(path)
                else:
                    core.workspace().goTo(path, line = self._line - 1)

        else:  # file may be not existing
            path = os.path.expanduser(self._path)
            if os.path.isfile(path):
                path = os.path.abspath(path)
                if self._line is None:
                    core.workspace().goTo(path)
                else:
                    core.workspace().goTo(path, line = self._line - 1)
            else:
                core.workspace().createEmptyNotSavedDocument(path)
Example #30
0
    def _createSearchWidget(self):
        """ Create search widget. Called only when user requested it first time
        """
        from . import searchwidget
        self._widget = searchwidget.SearchWidget(self)
        self._widget.searchInDirectoryStartPressed.connect(self._onSearchInDirectoryStartPressed)
        self._widget.searchInDirectoryStopPressed.connect(self._onSearchInDirectoryStopPressed)
        self._widget.replaceCheckedStartPressed.connect(self._onReplaceCheckedStartPressed)
        self._widget.replaceCheckedStopPressed.connect(self._onReplaceCheckedStopPressed)
        self._widget.visibilityChanged.connect(self._updateSearchWidgetFoundItemsHighlighting)

        self._widget.searchRegExpChanged.connect(self._updateFileActionsState)
        self._widget.searchRegExpChanged.connect(self._onRegExpChanged)
        self._widget.searchRegExpChanged.connect(self._updateSearchWidgetFoundItemsHighlighting)

        self._widget.searchNext.connect(self._onSearchNext)
        self._widget.searchPrevious.connect(self._onSearchPrevious)

        self._widget.replaceFileOne.connect(self._onReplaceFileOne)
        self._widget.replaceFileAll.connect(self._onReplaceFileAll)

        core.workspace().currentDocumentChanged.connect(self._updateFileActionsState)  # always disabled, if no widget
        core.workspace().textChanged.connect(self._updateSearchWidgetFoundItemsHighlighting)

        core.mainWindow().centralLayout().addWidget(self._widget)
        self._widget.setVisible(False)
        self._updateFileActionsState()
Example #31
0
 def __init__(self):
     QObject.__init__(self)
     self._createdActions = []
     self._createdSeparators = []
     self._createdMenus = []
     self._currentDocument = core.workspace().currentDocument()  # probably None
     
     for menu in _MENUS:
         if menu[2]:
             menuObj = core.actionManager().addMenu(menu[0], menu[1], QIcon(':/enkiicons/' + menu[2]))
         else:
             menuObj = core.actionManager().addMenu(menu[0], menu[1])
         menuObj.setEnabled(False)
         self._createdMenus.append(menuObj)
     
     for item in _ACTIONS:
         if isinstance(item, tuple):  # action
             command, path, text, shortcut, icon = item
             actObject = QAction(text, self)
             if shortcut:
                 actObject.setShortcut(shortcut)
             if icon:
                 actObject.setIcon(QIcon(':/enkiicons/' + icon))
             actObject.setData(command)
             actObject.setEnabled(False)
             actObject.triggered.connect(self.onAction)
             core.actionManager().addAction(path, actObject)
             self._createdActions.append(actObject)
         else:  # separator
             menuPath = item
             menu = core.actionManager().menu(menuPath)
             self._createdSeparators.append(menu.addSeparator())
     
     core.workspace().currentDocumentChanged.connect(self.onCurrentDocumentChanged)
Example #32
0
 def test_logWindowSplitter3a(self):
     """Feature 1,2,3. A combination of the above test cases.
     """
     document1 = self.createFile('file1.rst', '.. file1::')
     document2 = self.createFile('file2.rst', '')
     document3 = self.createFile('file3.rst', '.. file3::')
     self._assertHtmlReady(lambda: None)
     self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(document1))
     # Wait for events to process. See qWait comment above.
     QTest.qWait(100)
     # Change splitter setting of document 1.
     newSplitterSize = [125, 124]
     self._widget().splitter.setSizes(newSplitterSize)
     self._widget().splitter.splitterMoved.emit(newSplitterSize[0], 1)
     # Assert log window and preview window are visible and are of almost
     # equal size.
     self.assertNotIn(0, self._widget().splitter.sizes())
     self.assertAlmostEqual(self._widget().splitter.sizes()[0], self._widget().splitter.sizes()[1], delta=10)
     # Switch to an error-free document, assert log window hidden.
     self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(document2))
     # Wait for events to process. See qWait comment above.
     QTest.qWait(100)
     self.assertFalse(self._widget().splitter.sizes()[1])
     # Switch to file3 which will cause build error, check splitter size.
     self._assertHtmlReady(lambda: core.workspace().setCurrentDocument(document3))
     self.assertNotIn(0, self._widget().splitter.sizes())
     self.assertAlmostEqual(self._widget().splitter.sizes()[0], self._widget().splitter.sizes()[1], delta=10)
Example #33
0
    def __init__(self, *args):
        QLabel.__init__(self, *args)

        self.setMinimumWidth(QFontMetrics(self.font()).width("Xreplace charX"))
        self.setAlignment(Qt.AlignCenter)

        core.workspace().currentDocumentChanged.connect(self._onCurrentDocumentChanged)
Example #34
0
 def __init__(self):
     """Create and install the plugin
     """
     QObject.__init__(self)
     self._action = None
     core.workspace().currentDocumentChanged.connect(self._updateAction)
     core.workspace().languageChanged.connect(self._updateAction)
Example #35
0
def main():
    cmdLine = _parseCommandLine()

    profiler = _StartProfiler(cmdLine["profiling"])

    try:
        _checkDependencies(profiler)
    except ImportError:
        sys.exit(-1)

    # Imports only here. Hack for ability to get help and version info even on system without PyQt.
    import PyQt5.QtGui
    import qutepart

    logging.basicConfig(level=logging.ERROR)
    logging.getLogger('qutepart').removeHandler(qutepart.consoleHandler)

    sys.excepthook = excepthook

    app = PyQt5.QtWidgets.QApplication(sys.argv)
    app.setApplicationName(enki.core.defines.PACKAGE_NAME)
    app.setOrganizationName(enki.core.defines.PACKAGE_ORGANISATION)
    app.setOrganizationDomain(enki.core.defines.PACKAGE_URL)
    app.lastWindowClosed.connect(app.quit)

    profiler.stepDone('Construct application')

    # init the core
    from enki.core.core import core
    core.init(profiler, cmdLine)

    _openFiles(core, cmdLine, profiler)

    profiler.stepDone('Open files')

    if core.workspace().currentDocument():
        core.workspace().currentDocument().setFocus()

    core.mainWindow().loadState()
    profiler.stepDone('Load state')

    core.mainWindow().show()

    profiler.stepDone('Show main window')

    # execute application
    if profiler.enabled:
        core.workspace().forceCloseAllDocuments()
        result = 0
    else:
        result = app.exec_()

    core.term()

    profiler.printInfo()

    profiler.stepDone('Terminate core')

    return result
Example #36
0
def main():
    cmdLine = _parseCommandLine()

    profiler = _StartProfiler(cmdLine["profiling"])

    try:
        _checkDependencies(profiler)
    except ImportError:
        sys.exit(-1)

    # Imports only here. Hack for ability to get help and version info even on system without PyQt.
    import PyQt5.QtGui
    import qutepart

    logging.basicConfig(level=logging.ERROR)
    logging.getLogger('qutepart').removeHandler(qutepart.consoleHandler)

    sys.excepthook = excepthook

    app = PyQt5.QtWidgets.QApplication(sys.argv)
    app.setApplicationName(enki.core.defines.PACKAGE_NAME)
    app.setOrganizationName(enki.core.defines.PACKAGE_ORGANISATION)
    app.setOrganizationDomain(enki.core.defines.PACKAGE_URL)
    app.lastWindowClosed.connect(app.quit)

    profiler.stepDone('Construct application')

    # init the core
    from enki.core.core import core
    core.init(profiler, cmdLine)

    _openFiles(core, cmdLine, profiler)

    profiler.stepDone('Open files')

    if core.workspace().currentDocument():
        core.workspace().currentDocument().setFocus()

    core.mainWindow().loadState()
    profiler.stepDone('Load state')

    core.mainWindow().show()

    profiler.stepDone('Show main window')

    # execute application
    if profiler.enabled:
        core.workspace().forceCloseAllDocuments()
        result = 0
    else:
        result = app.exec_()

    core.term()

    profiler.printInfo()

    profiler.stepDone('Terminate core')

    return result
Example #37
0
    def __init__(self, *args):
        QLabel.__init__(self, *args)

        self.setMinimumWidth(QFontMetrics(self.font()).width("Xreplace charX"))
        self.setAlignment(Qt.AlignCenter)

        core.workspace().currentDocumentChanged.connect(
            self._onCurrentDocumentChanged)
Example #38
0
 def _deactivate(self):
     """Destroy the dialog, remove actions from the main menu."""
     self._fileswitcher = None
     self._removeActions()
     core.workspace().documentOpened.disconnect(
         self._onDocumentOpenedOrClosed)
     core.workspace().documentClosed.disconnect(
         self._onDocumentOpenedOrClosed)
Example #39
0
    def terminate(self):
        if self._timer.isActive():
            self._timer.stop()

        core.workspace().currentDocumentChanged.disconnect(
            self._onCurrentDocumentChanged)
        core.workspace().cursorPositionChanged.disconnect(
            self._onCursorPositionChanged)
Example #40
0
 def _onFileOpenTriggered(self):
     """Handler of File->Open
     """
     fileNames = QFileDialog.getOpenFileNames( core.mainWindow(),
                                               self.tr( "Classic open dialog. Main menu -> Navigation -> Locator is better" ))
             
     for path in fileNames:
         core.workspace().openFile(path)
Example #41
0
 def del_(self):
     """Uninstall the plugin
     """
     core.workspace().currentDocumentChanged.disconnect(self._updateAction)
     core.workspace().languageChanged.disconnect(self._updateAction)
     if self._action is not None:
         core.actionManager().removeAction(self._action)
         del self._action
    def test_same_path(self):
        core.workspace().openFile(self.EXISTING_FILE)

        _startEditCurrentFilePath()
        self.keyClicks(self.EXISTING_FILE)
        self.keyClick(Qt.Key_Return)

        self.assertEqual(QApplication.instance().activeWindow(), core.mainWindow())  # not messagebox with error
Example #43
0
    def _onFileOpenTriggered(self):
        """Handler of File->Open
        """
        fileNames = QFileDialog.getOpenFileNames( core.mainWindow(),
                                                  self.tr( "Classic open dialog. Main menu -> Navigation -> Locator is better" ))

        for path in fileNames:
            core.workspace().openFile(path)
Example #44
0
    def __init__(self):
        QObject.__init__(self)
        core.workspace().currentDocumentChanged.connect(
            self._onCurrentDocumentChanged)

        document = core.workspace().currentDocument()
        if document:
            document.qutepart.installEventFilter(self)
Example #45
0
 def terminate(self):
     """Uninstall the plugin
     """
     core.workspace().currentDocumentChanged.disconnect(self._updateAction)
     core.workspace().languageChanged.disconnect(self._updateAction)
     if self._action is not None:
         core.actionManager().removeAction(self._action)
         del self._action
Example #46
0
 def _applySettings(self):
     if core.config()['Lint']['Python']['Enabled']:
         self._install()
         if self._isSupported(core.workspace().currentDocument()):
             self._processDocument(core.workspace().currentDocument())
     else:
         self._uninstall()
         for document in core.workspace().documents():
             document.qutepart.lintMarks = {}
Example #47
0
 def execute(self):
     """Execute the command
     """
     for path in glob.iglob(os.path.expanduser(self._path)):
         path = os.path.abspath(path)
         if self._line is None:
             core.workspace().goTo(path)
         else:
             core.workspace().goTo(path, line = self._line - 1)
Example #48
0
 def _onRegExpChanged(self, regExp):
     """Search regExp changed. Do incremental search
     """
     if self._mode in (MODE_SEARCH, MODE_REPLACE) and \
        core.workspace().currentDocument() is not None:
         if regExp.pattern:
             self._searchFile(forward=True, incremental=True )
         else:  # Clear selection
             core.workspace().currentDocument().qutepart.resetSelection()
Example #49
0
 def __init__(self, parent):
     QToolButton.__init__(self, parent)
     self.setToolTip(self.tr("Cursor position"))
     self.setEnabled(False)
     self._setCursorPosition(-1, -1)
     minWidth = QFontMetrics(self.font()).width("Line: xxxxx Column: xxx")
     minWidth += 30  # for the button borders
     self.setMinimumWidth(minWidth)  # Avoid flickering when text width changed
     core.workspace().currentDocumentChanged.connect(self._onCurrentDocumentChanged)
Example #50
0
 def _onRegExpChanged(self, regExp):
     """Search regExp changed. Do incremental search
     """
     if self._mode in (MODE_SEARCH, MODE_REPLACE) and \
        core.workspace().currentDocument() is not None:
         if regExp.pattern:
             self._searchFile(forward=True, incremental=True)
         else:  # Clear selection
             core.workspace().currentDocument().qutepart.resetSelection()
Example #51
0
 def _applySettings(self):
     if core.config()['Lint']['Python']['Enabled']:
         self._install()
         if core.workspace().currentDocument() is not None:
             self._processDocument(core.workspace().currentDocument())
     else:
         self._uninstall()
         for document in core.workspace().documents():
             document.qutepart.lintMarks = {}
Example #52
0
    def tearDown(self):
        self._finished = True

        for document in core.workspace().documents():
            document.qutepart.text = ''  # clear modified flag, avoid Save Files dialog

        core.workspace().closeAllDocuments()
        core.term()
        _processPendingEvents()
        self._cleanUpFs()
Example #53
0
 def blockingFunc():
     try:
         core.workspace().forceCloseAllDocuments()
         core.term()
     finally:
         try:
             QApplication.instance().processEvents()
         except:
             pass
         QApplication.instance().quit()
Example #54
0
    def execute(self):
        """Execute command
        """
        try:
            path = os.path.abspath(os.path.expanduser(self._path))
        except OSError:  # directory deleted
            return

        core.workspace().currentDocument().setFilePath(path)
        core.workspace().currentDocument().saveFile()
Example #55
0
    def test_6(self):
        """Test _firstLetterShortcut."""
        # To access this function, create a dummy document so we can pull
        # up its containing dialog.
        self.createFile('file1.rb', 'asdf\nfdsa')
        uis = _UISaveFiles(core.workspace(), core.workspace().documents())
        # Label one of the dialog buttons.
        s = uis._firstLetterShortcut(uis.buttonBox.Discard, 'Does &This work')

        self.assertEquals(s.key(), QKeySequence("T"))
Example #56
0
    def __init__(self):
        QMessageBox.information(core.mainWindow(), "Hello, world", "Plugin loaded")
        self._addAction()
        self._createDock()
        self._readSettings()

        core.workspace().currentDocumentChanged.connect(self._onDocumentChanged)

        core.uiSettingsManager().dialogAccepted.connect(self._applySettings)
        core.uiSettingsManager().aboutToExecute.connect(self._onSettingsDialogAboutToExecute)
Example #57
0
def _openFiles(core, cmdLine, profiler):
    existingFiles = []
    notExistingFiles = []
    dirs = []
    for filePath in cmdLine["files"]:
        if os.path.exists(filePath):
            if os.path.isdir(filePath):
                dirs.append(filePath)
            else:
                existingFiles.append(filePath)
        else:
            notExistingFiles.append(filePath)

    # open file by path and line number
    if "firstFileLineToGo" in cmdLine and \
       len(existingFiles) == 1:
        line = cmdLine["firstFileLineToGo"] - 1  # convert from users to internal indexing
        core.workspace().goTo(existingFiles[0], line=line)
    elif existingFiles or notExistingFiles:
        core.workspace().openFiles(existingFiles)
        for filePath in notExistingFiles:
            core.workspace().createEmptyNotSavedDocument(filePath)
    elif dirs:
        try:
            os.chdir(dirs[0])
        except:
            pass
    else:
        if not cmdLine["no-session"]:
            core.restoreSession.emit()
        profiler.stepDone('Restore session')

        if core.workspace().currentDocument() is None:
            core.workspace().createEmptyNotSavedDocument()
Example #58
0
 def __init__(self):
     QObject.__init__(self)
     self._recentFileActions = []
     self._recent = enki.core.json_wrapper.load(_FILE_PATH, 'recent file list', [])
     self._undoClose = core.actionManager().addAction("mFile/mUndoClose/aUndoClose",
                                                      "Undo close",
                                                      shortcut = 'Shift+Ctrl+U')
     core.workspace().documentClosed.connect(self._onDocumentClosed)
     self._undoClose.triggered.connect(self._onUndoClose)
     menu = core.actionManager().action("mFile/mUndoClose").menu()
     menu.aboutToShow.connect(self._onMenuAboutToShow)
Example #59
0
    def _onActivated(self, idx):
        """File or directory doubleClicked
        """
        index = self._filteredModel.mapToSource(idx)
        path = self._dirsModel.filePath(index)

        if os.path.isdir(path):
            self._fileBrowser.setCurrentPath(path)
        else:
            self._fileActivated.emit()
            core.workspace().openFile(path)