diff --git a/ReText/editor.py b/ReText/editor.py index c1b3aadd..263a1bac 100644 --- a/ReText/editor.py +++ b/ReText/editor.py @@ -378,7 +378,7 @@ def findNextImageName(self, filenames): highestNumber = max(number, highestNumber) return 'image%04d.png' % (highestNumber + 1) - def getImageFilenameAndLink(self): + def getImageFilename(self): if self.tab.fileName: saveDir = os.path.dirname(self.tab.fileName) else: @@ -386,40 +386,47 @@ def getImageFilenameAndLink(self): imageFileName = self.findNextImageName(os.listdir(saveDir)) - chosenFileName = QFileDialog.getSaveFileName(self, + return QFileDialog.getSaveFileName(self, self.tr('Save image'), os.path.join(saveDir, imageFileName), self.tr('Images (*.png *.jpg)'))[0] - if chosenFileName: - # Use relative links for named documents - if self.tab.fileName: - try: - link = os.path.relpath(chosenFileName, saveDir) - except ValueError: # different roots - link = chosenFileName - else: - link = chosenFileName - else: - link = None - - return chosenFileName, link + def makeFileNameRelative(self, fileName): + """Tries to make the given fileName relative. If the document is + not saved, or the fileName is on a different root, returns the + original fileName. + """ + if self.tab.fileName: + currentDir = os.path.dirname(self.tab.fileName) + try: + return os.path.relpath(fileName, currentDir) + except ValueError: # different roots + return fileName + return fileName + + def getImageMarkup(self, fileName): + """Returns markup for image in the current markup language. + + This method is also accessed in ReTextWindow.insertImage. + """ + link = self.makeFileNameRelative(fileName) + markupClass = self.tab.getActiveMarkupClass() + if markupClass == MarkdownMarkup: + return '![%s](%s)' % (QFileInfo(link).baseName(), link) + elif markupClass == ReStructuredTextMarkup: + return '.. image:: %s' % link + elif markupClass == TextileMarkup: + return '!%s!' % link def pasteImage(self): mimeData = QApplication.instance().clipboard().mimeData() - fileName, link = self.getImageFilenameAndLink() + fileName = self.getImageFilename() if not fileName or not mimeData.hasImage(): return image = QImage(mimeData.imageData()) image.save(fileName) - markupClass = self.tab.getActiveMarkupClass() - if markupClass == MarkdownMarkup: - imageText = '![%s](%s)' % (QFileInfo(link).baseName(), link) - elif markupClass == ReStructuredTextMarkup: - imageText = '.. image:: %s' % link - elif markupClass == TextileMarkup: - imageText = '!%s!' % link + imageText = self.getImageMarkup(fileName) self.textCursor().insertText(imageText) diff --git a/ReText/window.py b/ReText/window.py index 6ee91c4c..1110c83c 100644 --- a/ReText/window.py +++ b/ReText/window.py @@ -146,6 +146,8 @@ def __init__(self, parent=None): self.actionTableMode = self.act(self.tr('Table editing mode'), shct=Qt.CTRL+Qt.Key_T, trigbool=lambda x: self.currentTab.editBox.enableTableMode(x)) + self.actionInsertImages = self.act(self.tr('Insert images by file path'), + trig=lambda: self.insertImages()) if ReTextFakeVimHandler: self.actionFakeVimMode = self.act(self.tr('FakeVim mode'), shct=Qt.CTRL+Qt.ALT+Qt.Key_V, trigbool=self.enableFakeVimMode) @@ -326,6 +328,7 @@ def __init__(self, parent=None): menuEdit.addAction(self.actionPreview) menuEdit.addAction(self.actionInsertTable) menuEdit.addAction(self.actionTableMode) + menuEdit.addAction(self.actionInsertImages) if ReTextFakeVimHandler: menuEdit.addAction(self.actionFakeVimMode) menuEdit.addSeparator() @@ -1239,6 +1242,23 @@ def viewHtml(self): htmlDlg.raise_() htmlDlg.activateWindow() + def insertImages(self): + supportedExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp'] + fileFilter = ' (%s);;' % ' '.join('*' + ext for ext in supportedExtensions) + fileNames, _selectedFilter = QFileDialog.getOpenFileNames(self, + self.tr("Select one or several images to open"), QDir.currentPath(), + self.tr("Supported files") + fileFilter + self.tr("All files (*)")) + + cursor = self.currentTab.editBox.textCursor() + + imagesMarkup = '\n'.join( + self.currentTab.editBox.getImageMarkup(fileName) + for fileName in fileNames) + cursor.insertText(imagesMarkup) + + self.formattingBox.setCurrentIndex(0) + self.currentTab.editBox.setFocus(Qt.OtherFocusReason) + def openHelp(self): QDesktopServices.openUrl(QUrl('https://github.com/retext-project/retext/wiki')) diff --git a/tests/test_editor.py b/tests/test_editor.py index 2de33ebc..ba5e953f 100644 --- a/tests/test_editor.py +++ b/tests/test_editor.py @@ -111,24 +111,26 @@ def test_pasteText(self): self.editor.insertFromMimeData(mimeData) self.assertTrue('pasted text' in self.editor.toPlainText()) - @patch.object(ReTextEdit, 'getImageFilenameAndLink', return_value=('/tmp/myimage.jpg', 'myimage.jpg')) + @patch.object(ReTextEdit, 'getImageFilename', return_value='/tmp/myimage.jpg') @patch.object(QImage, 'save') def test_pasteImage_Markdown(self, _mock_image, _mock_editor): mimeData = QMimeData() mimeData.setImageData(self._create_image()) app.clipboard().setMimeData(mimeData) self.dummytab.markupClass = MarkdownMarkup + self.dummytab.fileName = '/tmp/foo.md' self.editor.pasteImage() self.assertTrue('![myimage](myimage.jpg)' in self.editor.toPlainText()) - @patch.object(ReTextEdit, 'getImageFilenameAndLink', return_value=('/tmp/myimage.jpg', 'myimage.jpg')) + @patch.object(ReTextEdit, 'getImageFilename', return_value='/tmp/myimage.jpg') @patch.object(QImage, 'save') def test_pasteImage_RestructuredText(self, _mock_image, _mock_editor): mimeData = QMimeData() mimeData.setImageData(self._create_image()) app.clipboard().setMimeData(mimeData) self.dummytab.markupClass = ReStructuredTextMarkup + self.dummytab.fileName = '/tmp/foo.rst' self.editor.pasteImage() self.assertTrue('.. image:: myimage.jpg' in self.editor.toPlainText())