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();
457 if (!de->mimeData()->hasUrls())
459 QsciScintilla::dragMoveEvent(de);
467 if (!de->mimeData()->hasUrls()) {
468 QsciScintilla::dragEnterEvent(de);
481 return QsciScintilla::fromMimeData(source, rectangular);
489 if (!de->mimeData()->hasUrls()) {
490 QDropEvent localDrop(*de);
492 QsciScintilla::dropEvent(&localDrop);
500 QPrinter printer(QPrinter::HighResolution);
501 auto *print_dlg =
new QPrintDialog(&printer,
this);
502 print_dlg->setWindowTitle(tr(
"Print Script"));
503 if (print_dlg->exec() != QDialog::Accepted) {
506 QTextDocument document(text());
507 document.print(&printer);
525 QsciScintilla::zoomTo(level);
549 if (event->text() ==
"(") {
550 auto *backspEvent =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
551 auto *bracketEvent =
new QKeyEvent(*event);
552 QsciScintilla::keyPressEvent(bracketEvent);
553 QsciScintilla::keyPressEvent(backspEvent);
559 QsciScintilla::keyPressEvent(event);
564#if QSCINTILLA_VERSION < 0x020402
568 if (isListActive()) {
569 QObjectList children = this->children();
570 QListIterator<QObject *> itr(children);
573 while (itr.hasPrevious()) {
574 QObject *child = itr.previous();
575 if (child->inherits(
"QListWidget")) {
576 QWidget *w = qobject_cast<QWidget *>(child);
577 w->setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint);
588 bool matchWords,
bool wrap,
bool forward) {
589 int line(-1),
index(-1), prevLine(-1), prevIndex(-1);
592 this->beginUndoAction();
593 bool found = this->findFirst(searchString, regex, caseSensitive, matchWords, wrap, forward, 0, 0);
596 QMessageBox::information(
this,
"Mantid - Find and Replace",
"No matches found in current document.");
600 this->getCursorPosition(&prevLine, &prevIndex);
601 this->replace(replaceString);
602 found = this->findNext();
603 this->getCursorPosition(&line, &
index);
607 if (line < prevLine || (line == prevLine &&
index <= prevIndex)) {
611 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 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.
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 setLexer(QsciLexer *) override
Set a new code lexer for this object.
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 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.
QString settingsGroup() const
Settings group.
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 zoomTo(int level) override
Override zoomTo slot.
void forwardKeyPressToBase(QKeyEvent *event)
Forward a KeyPress event to QsciScintilla base class.
void readSettings()
Read settings from persistent store.
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.
QString fileName() const
The current filename.
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.
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.