15#include <QApplication>
26#include <QPrintDialog>
35#include <Qsci/qsciapis.h>
36#include <Qsci/qscicommandset.h>
52QsciLexer *createLexerFromName(
const QString &lexerName,
const QFont &font) {
53 if (lexerName ==
"Python") {
54 return new QsciLexerPython;
55 }
else if (lexerName ==
"AlternateCSPython") {
58 throw std::invalid_argument(
"createLexerFromLanguage: Unsupported "
59 "name. Supported names=Python, AlternateCSPython");
80 :
ScriptEditor(parent, createLexerFromName(lexerName, font)) {}
89 : QsciScintilla(parent), m_filename(
""), m_progressArrowKey(markerDefine(QsciScintilla::RightArrow)),
90 m_currentExecLine(0), m_completer(nullptr), m_previousKey(0), m_findDialog(new
FindReplaceDialog(this)),
91 m_settingsGroup(
std::move(settingsGroup)) {
96 setEolMode(EolWindows);
109 setMarginLineNumbers(1,
true);
113 setFocusPolicy(Qt::StrongFocus);
125 if (QsciLexer *current = lexer()) {
166 if (QsciLexer *current = lexer()) {
169 this->QsciScintilla::setLexer(codelexer);
188 setAutoCompletionSource(source);
189 setAutoCompletionThreshold(2);
190 setCallTipsStyle(QsciScintilla::CallTipsNoAutoCompletionContext);
191 setCallTipsVisible(0);
198 setAutoCompletionSource(QsciScintilla::AcsNone);
199 setAutoCompletionThreshold(-1);
200 setCallTipsVisible(-1);
212 QString selectedFilter;
213 QString filter =
"Scripts (*.py *.PY);;All Files (*)";
214 QString filename = QFileDialog::getSaveFileName(
nullptr,
"Save file...",
"", filter, &selectedFilter);
216 if (filename.isEmpty()) {
219 if (QFileInfo(filename).suffix().isEmpty()) {
220 QString ext = selectedFilter.section(
'(', 1).section(
' ', 0, 0);
231 if (filename.isEmpty()) {
245 QFile file(filename);
246 if (!file.open(QIODevice::WriteOnly)) {
247 QString msg = QString(
"Could not open file \"%1\" for writing.").arg(filename);
248 throw std::runtime_error(qPrintable(msg));
266 int line_length = txt.length();
268 setSelection(lineno,
index, lineno, qMax(line_length, this->text(lineno).length()));
269 removeSelectedText();
270 insertAt(txt, lineno,
index);
271 setCursorPosition(lineno, line_length);
285 if (QApplication::keyboardModifiers() & Qt::ControlModifier &&
286 (event->key() == Qt::Key_Plus || event->key() == Qt::Key_Equal)) {
296 if (QApplication::keyboardModifiers() & Qt::ControlModifier && (event->key() == Qt::Key_Minus)) {
313 if (e->modifiers() == Qt::ControlModifier) {
314 if (e->angleDelta().y() > 0) {
322 QsciScintilla::wheelEvent(e);
330 int keyIdentifier = QKeySequence(keyCombination)[0];
331 if (QsciCommand::validKey(keyIdentifier)) {
332 QsciCommand *cmd = standardCommands()->boundTo(keyIdentifier);
336 throw std::invalid_argument(
"Key combination is not set by Scintilla.");
339 throw std::invalid_argument(
"Key combination is not valid!");
348 const int minWidth = 38;
349 int width = minWidth;
350 int ntens =
static_cast<int>(std::log10(
static_cast<double>(lines())));
354 setMarginWidth(1, width);
379 if (QThread::currentThread() != QApplication::instance()->thread()) {
380 QMetaObject::invokeMethod(
this,
"updateProgressMarker", Qt::AutoConnection, Q_ARG(
int, lineno), Q_ARG(
bool,
error));
403 if (lineno <= 0 || lineno > this->lines())
406 ensureLineVisible(lineno);
421 QStringListIterator iter(keywords);
423 while (iter.hasNext()) {
424 QString item = iter.next();
465 if (!de->mimeData()->hasUrls())
467 QsciScintilla::dragMoveEvent(de);
475 if (!de->mimeData()->hasUrls()) {
476 QsciScintilla::dragEnterEvent(de);
489 return QsciScintilla::fromMimeData(source, rectangular);
497 if (!de->mimeData()->hasUrls()) {
498 QDropEvent localDrop(*de);
500 QsciScintilla::dropEvent(&localDrop);
505 if (fe->gotFocus()) {
507 QsciScintilla::focusInEvent(fe);
515 QPrinter printer(QPrinter::HighResolution);
516 auto *print_dlg =
new QPrintDialog(&printer,
this);
517 print_dlg->setWindowTitle(tr(
"Print Script"));
518 if (print_dlg->exec() != QDialog::Accepted) {
521 QTextDocument document(text());
522 document.print(&printer);
551 if (event->text() ==
"(") {
552 auto *backspEvent =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
553 auto *bracketEvent =
new QKeyEvent(*event);
554 QsciScintilla::keyPressEvent(bracketEvent);
555 QsciScintilla::keyPressEvent(backspEvent);
561 QsciScintilla::keyPressEvent(event);
566#if QSCINTILLA_VERSION < 0x020402
570 if (isListActive()) {
571 QObjectList children = this->children();
572 QListIterator<QObject *> itr(children);
575 while (itr.hasPrevious()) {
576 QObject *child = itr.previous();
577 if (child->inherits(
"QListWidget")) {
578 QWidget *w = qobject_cast<QWidget *>(child);
579 w->setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint);
590 bool matchWords,
bool wrap,
bool forward) {
591 int line(-1),
index(-1), prevLine(-1), prevIndex(-1);
594 this->beginUndoAction();
595 bool found = this->findFirst(searchString, regex, caseSensitive, matchWords, wrap, forward, 0, 0);
598 QMessageBox::information(
this,
"Mantid - Find and Replace",
"No matches found in current document.");
602 this->getCursorPosition(&prevLine, &prevIndex);
603 this->replace(replaceString);
604 found = this->findNext();
605 this->getCursorPosition(&line, &
index);
609 if (line < prevLine || (line == prevLine &&
index <= prevIndex)) {
613 this->endUndoAction();
std::map< DeltaEMode::Type, std::string > index
Defines a Python lexer with a alternative colour scheme to the standard one provided by QsciLexerPyth...
Raises a dialog allowing the user to find/replace text in the editor.
Exception type to indicate that saving was cancelled.
This class provides an area to write scripts.
void saveAs()
Save the script, opening a dialog.
void wheelEvent(QWheelEvent *e) override
Override so that ctrl + mouse wheel will zoom in and out.
void focusInEvent(QFocusEvent *fe) override
void updateProgressMarker(int lineno, bool error=false)
Update the progress marker.
int m_currentExecLine
Hold the line number of the currently executing line.
void setSettingsGroup(const QString &name)
Set the name of the group to save the settings for.
ScriptEditor(const QString &lexerName, const QFont &font=QFont(), QWidget *parent=nullptr)
Construction based on a string defining the langauge used for syntax highlighting.
void keyPressEvent(QKeyEvent *event) override
Capture key presses.
const QString & settingsGroup() const
Settings group.
void dropEvent(QDropEvent *de) override
Accept a drag drop event and process the data appropriately.
void updateProgressMarkerFromThread(int lineno, bool error=false)
Update the progress marker potentially from a separate thread.
virtual void showFindReplaceDialog()
Raise find replace dialog.
void undoAvailable(bool)
Inform observers that undo information is available.
void dragMoveEvent(QDragMoveEvent *de) override
Accept a drag move event and selects whether to accept the action.
void replaceAll(const QString &search, const QString &replace, bool regex, bool caseSensitive, bool matchWords, bool wrap, bool forward=true)
Replace all occurences of a string.
int getZoom() const
Get the current zoom factor.
int m_progressArrowKey
The margin marker.
void editorFocusIn(const QString &filename)
The editor now has focus.
void redoAvailable(bool)
Inform observers that redo information is available.
void setMarkerState(bool enabled)
Set the marker state.
void writeSettings()
Write settings from persistent store.
void padMargin()
Ensure the margin width is big enough to hold everything + padding.
void markFileAsModified()
Mark the file as modified.
void fileNameChanged(const QString &fileName)
Notify that the filename has been modified.
QByteArray fromMimeData(const QMimeData *source, bool &rectangular) const override
If the QMimeData object holds workspaces names then extract text from a QMimeData object and add the ...
void enableAutoCompletion(AutoCompletionSource source=QsciScintilla::AcsAPIs)
Enable the auto complete.
void setFileName(const QString &filename)
Set a new file name.
void disableAutoCompletion()
Disable the auto complete.
void clearKeyBinding(const QString &keyCombination)
Clear keyboard shortcut binding.
void forwardKeyPressToBase(QKeyEvent *event)
Forward a KeyPress event to QsciScintilla base class.
void readSettings()
Read settings from persistent store.
const QString & fileName() const
The current filename.
QsciAPIs * m_completer
A pointer to a QsciAPI object that handles the code completion.
void progressMade(const int progress)
Progress has been made in script execution.
void print()
Print the text within the widget.
~ScriptEditor() override
Destructor.
virtual void writeToDevice(QIODevice &device) const
Write to the given device.
void saveToCurrentFile()
Save to the current filename, opening a dialog if blank.
static QColor g_success_colour
The colour of the marker for a success state.
static QColor g_error_colour
The colour of the marker for an error state.
void setLexer(QsciLexer *) override final
Set a new code lexer for this object.
FindReplaceDialog * m_findDialog
A pointer to the find replace dialog.
QString m_filename
The file name associated with this editor.
QString m_settingsGroup
Name of group that the settings are stored under.
void dragEnterEvent(QDragEnterEvent *de) override
Accept a drag enter event and selects whether to accept the action.
void textZoomedIn()
Emitted when a zoom in is requested.
void textZoomedOut()
Emitted when a zoom out is requested.
void saveScript(const QString &filename)
Save a the text to the given filename.
void setText(int lineno, const QString &text, int index=0)
Set the text on a given line number.
void updateCompletionAPI(const QStringList &keywords)
Refresh the autocomplete information base on a new set of keywords.
void markExecutingLineAsError()
Mark the progress arrow as an error.
QSize sizeHint() const override
Default size hint.
void setAutoMarginResize()
Make the object resize to margin to fit the contents with padding.