# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) import time from qtpy.QtCore import Qt from qtpy.QtGui import QColor, QIntValidator from qtpy.QtPrintSupport import QPrinter from qtpy.QtWidgets import (QDialog, QLabel, QLineEdit, QGridLayout, QDialogButtonBox, QVBoxLayout, QHBoxLayout) from spyder.config.base import _ # ============================================================================= # CodeEditor's Printer # ============================================================================= # TODO: Implement the header and footer support class Printer(QPrinter): def __init__(self, mode=QPrinter.ScreenResolution, header_font=None): QPrinter.__init__(self, mode) self.setColorMode(QPrinter.Color) self.setPageOrder(QPrinter.FirstPageFirst) self.date = time.ctime() if header_font is not None: self.header_font = header_font # The following method is simply ignored by QPlainTextEdit # (this is a copy from QsciEditor's Printer) def formatPage(self, painter, drawing, area, pagenr): header = '%s - %s - Page %s' % (self.docName(), self.date, pagenr) painter.save() painter.setFont(self.header_font) painter.setPen(QColor(Qt.black)) if drawing: painter.drawText(area.right()-painter.fontMetrics().width(header), area.top()+painter.fontMetrics().ascent(), header) area.setTop(area.top()+painter.fontMetrics().height()+5) painter.restore() # ============================================================================= # Go to line dialog box # ============================================================================= class GoToLineDialog(QDialog): def __init__(self, editor): QDialog.__init__(self, editor, Qt.WindowTitleHint | Qt.WindowCloseButtonHint) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.lineno = None self.editor = editor self.setWindowTitle(_("Editor")) self.setModal(True) label = QLabel(_("Go to line:")) self.lineedit = QLineEdit() validator = QIntValidator(self.lineedit) validator.setRange(1, editor.get_line_count()) self.lineedit.setValidator(validator) self.lineedit.textChanged.connect(self.text_has_changed) cl_label = QLabel(_("Current line:")) cl_label_v = QLabel("%d" % editor.get_cursor_line_number()) last_label = QLabel(_("Line count:")) last_label_v = QLabel("%d" % editor.get_line_count()) glayout = QGridLayout() glayout.addWidget(label, 0, 0, Qt.AlignVCenter | Qt.AlignRight) glayout.addWidget(self.lineedit, 0, 1, Qt.AlignVCenter) glayout.addWidget(cl_label, 1, 0, Qt.AlignVCenter | Qt.AlignRight) glayout.addWidget(cl_label_v, 1, 1, Qt.AlignVCenter) glayout.addWidget(last_label, 2, 0, Qt.AlignVCenter | Qt.AlignRight) glayout.addWidget(last_label_v, 2, 1, Qt.AlignVCenter) bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Vertical, self) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) btnlayout = QVBoxLayout() btnlayout.addWidget(bbox) btnlayout.addStretch(1) ok_button = bbox.button(QDialogButtonBox.Ok) ok_button.setEnabled(False) self.lineedit.textChanged.connect( lambda text: ok_button.setEnabled(len(text) > 0)) layout = QHBoxLayout() layout.addLayout(glayout) layout.addLayout(btnlayout) self.setLayout(layout) self.lineedit.setFocus() def text_has_changed(self, text): """Line edit's text has changed.""" text = str(text) if text: self.lineno = int(text) else: self.lineno = None def get_line_number(self): """Return line number.""" # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute return self.lineno