# -*- coding: iso-8859-1 -*- # Copyright (C) 2010-2014 Bastian Kleineidam # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import os import urlparse from PyQt4 import QtGui, QtCore from .linkchecker_ui_editor import Ui_EditorDialog from ..checker.fileurl import get_os_filename try: from .editor_qsci import ContentTypeLexers, Editor except ImportError: from .editor_qt import ContentTypeLexers, Editor class EditorWindow (QtGui.QDialog, Ui_EditorDialog): """Editor window.""" # emitted after successful save saved = QtCore.pyqtSignal(str) # emitted after successful load loaded = QtCore.pyqtSignal(str) def __init__ (self, parent=None): """Initialize the editor widget.""" super(EditorWindow, self).__init__(parent) self.setupUi(self) # filename used for saving self.filename = None # the Scintilla editor widget self.editor = Editor(parent=self.frame) layout = QtGui.QVBoxLayout(self.frame) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.editor) # for debugging #self.setText(("1234567890"*8) + "\n\nx\n\n") #lexer = Qsci.QsciLexerHTML() #lexer.setFont(self.editor.font()) #self.editor.setLexer(lexer) #self.editor.setCursorPosition(1, 1) #self.show() def setContentType (self, content_type): """Choose a lexer according to given content type.""" lexerclass = ContentTypeLexers.get(content_type.lower()) self.editor.highlight(lexerclass) def setText (self, text, line=1, col=1): """Set editor text and jump to given line and column.""" self.editor.setText(text) self.editor.setCursorPosition(line-1, col-1) self.editor.setModified(False) def setUrl (self, url): """If URL is a file:// URL, store the filename of it as base directory for the "save as" dialog.""" self.basedir = "" if url and url.startswith("file://"): urlparts = urlparse.urlsplit(url) path = get_os_filename(urlparts[2]) if os.path.exists(path): self.basedir = path @QtCore.pyqtSlot() def on_actionSave_triggered (self): """Save changed editor contents.""" if self.editor.isModified() or not self.filename: self.save() def closeEvent (self, e=None): """Save settings and remove registered logging handler""" if self.editor.isModified(): # ask if user wants to save if self.wants_save(): if self.save(): e.accept() else: # saving error or user canceled e.ignore() else: # discard changes e.accept() else: # unchanged e.accept() def wants_save (self): """Ask user if he wants to save changes. Return True if user wants to save, else False.""" dialog = QtGui.QMessageBox(parent=self) dialog.setIcon(QtGui.QMessageBox.Question) dialog.setWindowTitle(_("Save file?")) dialog.setText(_("The document has been modified.")) dialog.setInformativeText(_("Do you want to save your changes?")) dialog.setStandardButtons(QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard) dialog.setDefaultButton(QtGui.QMessageBox.Save) return dialog.exec_() == QtGui.QMessageBox.Save def save (self): """Save editor contents to file.""" if not self.filename: title = _("Save File As") res = QtGui.QFileDialog.getSaveFileName(self, title, self.basedir) if not res: # user canceled return self.filename = res self.setWindowTitle(self.filename) else: if not os.path.isfile(self.filename): return if not os.access(self.filename, os.W_OK): return fh = None saved = False try: try: fh = QtCore.QFile(self.filename) if not fh.open(QtCore.QIODevice.WriteOnly): raise IOError(fh.errorString()) stream = QtCore.QTextStream(fh) stream.setCodec("UTF-8") stream << self.editor.text() self.editor.setModified(False) saved = True except (IOError, OSError) as e: err = QtGui.QMessageBox(self) err.setText(str(e)) err.exec_() finally: if fh is not None: fh.close() if saved: self.saved.emit(self.filename) return saved def load (self, filename): """Load editor contents from file.""" if not os.path.isfile(filename): return if not os.access(filename, os.R_OK): return self.filename = filename if not os.access(filename, os.W_OK): title = u"%s (%s)" % (self.filename, _(u"readonly")) else: title = self.filename self.setWindowTitle(title) fh = None loaded = False try: try: fh = QtCore.QFile(self.filename) if not fh.open(QtCore.QIODevice.ReadOnly): raise IOError(fh.errorString()) stream = QtCore.QTextStream(fh) stream.setCodec("UTF-8") self.setText(stream.readAll()) loaded = True except (IOError, OSError) as e: err = QtGui.QMessageBox(self) err.setText(str(e)) err.exec_() finally: if fh is not None: fh.close() if loaded: self.loaded.emit(self.filename)