Newer
Older
Gigg, Martyn Anthony
committed
//-------------------------------------------
// Includes
//-------------------------------------------
#include "ScriptingWindow.h"
#include "ScriptManagerWidget.h"
#include "ScriptingEnv.h"
#include "pixmaps.h"
Gigg, Martyn Anthony
committed
// Mantid
#include "MantidKernel/ConfigService.h"
Gigg, Martyn Anthony
committed
#include "ApplicationWindow.h"
Gigg, Martyn Anthony
committed
//Qt
#include <QTextEdit>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QSettings>
#include <QPrintDialog>
#include <QPrinter>
Gigg, Martyn Anthony
committed
#include <QDateTime>
Gigg, Martyn Anthony
committed
#include <QFileDialog>
#include <QMessageBox>
#include <QApplication>
#include <QTextStream>
Gigg, Martyn Anthony
committed
//***************************************************************************
//
// ScriptOutputDock class
//
//***************************************************************************
/**
* Constructor
Janik Zikovsky
committed
* @param title :: The title
* @param parent :: The parent widget
* @param flags :: Window flags
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
ScriptOutputDock::ScriptOutputDock(const QString & title, ScriptManagerWidget* manager,
QWidget * parent, Qt::WindowFlags flags ) :
Gigg, Martyn Anthony
committed
QDockWidget(title, parent, flags), m_manager(manager)
Gigg, Martyn Anthony
committed
{
setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
// The text display
m_text_display = new QTextEdit(this);
m_text_display->setReadOnly(true);
m_text_display->setLineWrapMode(QTextEdit::FixedColumnWidth);
m_text_display->setLineWrapColumnOrWidth(105);
m_text_display->setAutoFormatting(QTextEdit::AutoNone);
// Change to fix width font so that table formatting isn't screwed up
Gigg, Martyn Anthony
committed
resetFont();
Gigg, Martyn Anthony
committed
m_text_display->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_text_display, SIGNAL(customContextMenuRequested(const QPoint&)), this,
SLOT(showContextMenu(const QPoint&)));
initActions();
Gigg, Martyn Anthony
committed
setWidget(m_text_display);
}
/**
* Is there anything here
*/
bool ScriptOutputDock::isEmpty() const
{
return m_text_display->document()->isEmpty();
}
Gigg, Martyn Anthony
committed
/**
* Clear the text area
*/
void ScriptOutputDock::clear()
{
m_text_display->clear();
}
/**
* Change the title based on the script's execution state
Janik Zikovsky
committed
* @param running :: The current state of the script environment
Gigg, Martyn Anthony
committed
*/
void ScriptOutputDock::setScriptIsRunning(bool running)
{
QString title("Script Output - Status: ");
if( running )
{
title += "Running ...";
}
else
{
title += "Stopped";
}
setWindowTitle(title);
}
//-------------------------------------------
// Private slot member functions
//-------------------------------------------
/**
* Display an output message in the output dock
Janik Zikovsky
committed
* @param msg :: The msg
* @param error :: Indicate that this is an error
* @param timestamp :: Indicates if the message has a timestamp attached to it. In this case the
Gigg, Martyn Anthony
committed
* message will appear on a new line regardless of the last cursor position
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
void ScriptOutputDock::displayOutputMessage(const QString &msg, bool error, bool timestamp)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
// Ensure the cursor is in the correct position. This affects the font unfortunately
m_text_display->moveCursor(QTextCursor::End);
resetFont();
Gigg, Martyn Anthony
committed
if( error )
{
m_text_display->setTextColor(Qt::red);
}
else
{
m_text_display->setTextColor(Qt::black);
}
Gigg, Martyn Anthony
committed
QString msg_to_print = msg;
if( error || timestamp )
{
if( timestamp )
{
QString separator(75, '-');
msg_to_print = separator + "\n" + QDateTime::currentDateTime().toString()
+ ": " + msg.trimmed() + "\n" + separator + '\n';
}
// Check for last character being a new line character unless we are at the start of the
// scroll area
if( !m_text_display->text().endsWith('\n') && m_text_display->textCursor().position() != 0 )
{
m_text_display->textCursor().insertText("\n");
}
}
m_text_display->textCursor().insertText(msg_to_print);
Gigg, Martyn Anthony
committed
m_text_display->moveCursor(QTextCursor::End);
}
/**
* Display a context menu
*/
void ScriptOutputDock::showContextMenu(const QPoint & pos)
{
QMenu menu(this);
QAction* clear = new QAction("Clear", this);
connect(clear, SIGNAL(activated()), this, SLOT(clear()));
menu.addAction(clear);
//Copy action
menu.addAction(m_copy);
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
//Save to file
QAction* save_to_file = new QAction("Save to file", this);
connect(save_to_file, SIGNAL(activated()), this, SLOT(saveToFile()));
menu.addAction(save_to_file);
Gigg, Martyn Anthony
committed
if( !m_text_display->document()->isEmpty() )
{
Janik Zikovsky
committed
QAction* print = new QAction(getQPixmap("fileprint_xpm"), "&Print", this);
connect(print, SIGNAL(activated()), this, SLOT(print()));
menu.addAction(print);
Gigg, Martyn Anthony
committed
}
menu.exec(m_text_display->mapToGlobal(pos));
}
Gigg, Martyn Anthony
committed
/**
* Print the window output
*/
void ScriptOutputDock::print()
{
QPrinter printer;
QPrintDialog *print_dlg = new QPrintDialog(&printer, this);
print_dlg->setWindowTitle(tr("Print Output"));
if (print_dlg->exec() != QDialog::Accepted)
return;
QTextDocument document(m_text_display->text());
document.print(&printer);
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/**
* Save script output to a file
*/
void ScriptOutputDock::saveToFile()
{
QString filter = tr("Text") + " (*.txt *.TXT);;";
filter += tr("All Files")+" (*)";
QString selected_filter;
QString filename = QFileDialog::getSaveFileName(this, tr("MantidPlot - Save script"),
m_manager->m_last_dir, filter, &selected_filter);
if( filename.isEmpty() ) return;
if( QFileInfo(filename).suffix().isEmpty() )
{
QString ext = selected_filter.section('(',1).section(' ', 0, 0);
ext.remove(0,1);
if( ext != ")" ) filename += ext;
}
QFile file(filename);
if( !file.open(QIODevice::WriteOnly) )
{
QMessageBox::critical(this, tr("MantidPlot - File error"),
tr("Could not open file \"%1\" for writing.").arg(filename));
return;
}
QTextStream writer(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
writer << m_text_display->toPlainText();
QApplication::restoreOverrideCursor();
file.close();
}
//-------------------------------------------
// Private non-slot member functions
//-------------------------------------------
/**
* Create the actions associated with this widget
*/
void ScriptOutputDock::initActions()
{
// Copy action
Janik Zikovsky
committed
m_copy = new QAction(getQPixmap("copy_xpm"), "Copy", this);
m_copy->setShortcut(tr("Ctrl+C"));
connect(m_copy, SIGNAL(activated()), m_text_display, SLOT(copy()));
}
Gigg, Martyn Anthony
committed
/**
* Rest the font to default
*/
void ScriptOutputDock::resetFont()
{
QFont f("Andale Mono");
f.setFixedPitch(true);
f.setPointSize(8);
m_text_display->setCurrentFont(f);
m_text_display->setMinimumWidth(5);
m_text_display->setMinimumHeight(5);
}
Gigg, Martyn Anthony
committed
//***************************************************************************
//
// ScriptingWindow class
//
//***************************************************************************
//-------------------------------------------
// Public member functions
//-------------------------------------------
/**
* Constructor
Janik Zikovsky
committed
* @param env :: The scripting environment
* @param parent :: The parent widget
* @param flags :: Window flags passed to the base class
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
ScriptingWindow::ScriptingWindow(ScriptingEnv *env,QWidget *parent, Qt::WindowFlags flags) :
Gigg, Martyn Anthony
committed
QMainWindow(parent, flags)
{
setObjectName("MantidScriptWindow");
// Sub-widgets
Gigg, Martyn Anthony
committed
m_manager = new ScriptManagerWidget(env, this);
Gigg, Martyn Anthony
committed
setCentralWidget(m_manager);
Gigg, Martyn Anthony
committed
m_output_dock = new ScriptOutputDock(QString(), m_manager, this);
Gigg, Martyn Anthony
committed
m_output_dock->setScriptIsRunning(false);
//Set the height to 10% of the height of the window
addDockWidget(Qt::BottomDockWidgetArea, m_output_dock);
int dock_width = m_output_dock->geometry().width();
m_output_dock->resize(dock_width, this->geometry().height() * 0.01);
Gigg, Martyn Anthony
committed
connect(m_manager, SIGNAL(MessageToPrint(const QString&,bool,bool)), m_output_dock,
SLOT(displayOutputMessage(const QString&, bool,bool)));
Gigg, Martyn Anthony
committed
connect(m_manager, SIGNAL(ScriptIsActive(bool)), m_output_dock, SLOT(setScriptIsRunning(bool)));
Gigg, Martyn Anthony
committed
QSettings settings;
settings.beginGroup("/ScriptWindow");
QString lastdir = settings.value("LastDirectoryVisited", "").toString();
Gigg, Martyn Anthony
committed
// If nothgin, set the last directory to the Mantid scripts directory (if present)
if( lastdir.isEmpty() )
Gigg, Martyn Anthony
committed
{
lastdir = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("pythonscripts.directory"));
Gigg, Martyn Anthony
committed
}
m_manager->m_last_dir = lastdir;
if( env->supportsProgressReporting() )
{
m_manager->m_toggle_progress->setChecked(settings.value("ProgressArrow", true).toBool());
}
else
{
m_manager->m_toggle_progress->setChecked(false);
}
Sofia Antony
committed
//get the recent scripts values from registry
m_manager->setRecentScripts(settings.value("/RecentScripts").toStringList());
Gigg, Martyn Anthony
committed
settings.endGroup();
Sofia Antony
committed
// Create menus and actions
initMenus();
fileAboutToShow();
editAboutToShow();
// This connection must occur after the objects have been created and initialized
connect(m_manager, SIGNAL(currentChanged(int)), this, SLOT(tabSelectionChanged()));
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
setWindowIcon(QIcon(":/MantidPlot_Icon_32offset.png"));
setWindowTitle("MantidPlot: " + env->scriptingLanguage() + " Window");
setFocusPolicy(Qt::StrongFocus);
setFocusProxy(m_manager);
}
/**
* Destructor
*/
ScriptingWindow::~ScriptingWindow()
{
delete m_manager;
delete m_output_dock;
}
/**
* Is a script executing?
* @returns A flag indicating the current state
*/
bool ScriptingWindow::isScriptRunning() const
{
return m_manager->isScriptRunning();
}
/**
* Save the settings on the window
*/
void ScriptingWindow::saveSettings()
{
QSettings settings;
settings.beginGroup("/ScriptWindow");
settings.setValue("/AlwaysOnTop", m_always_on_top->isChecked());
Gigg, Martyn Anthony
committed
settings.setValue("/ProgressArrow", m_manager->m_toggle_progress->isChecked());
settings.setValue("/LastDirectoryVisited", m_manager->m_last_dir);
Sofia Antony
committed
settings.setValue("/RecentScripts",m_manager->recentScripts());
Gigg, Martyn Anthony
committed
settings.endGroup();
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
/**
* Override the closeEvent
* @param event :: A pointer to the event object
*/
void ScriptingWindow::closeEvent(QCloseEvent *event)
{
emit closeMe();
// This will ensure each is saved correctly
Gigg, Martyn Anthony
committed
m_manager->closeAllTabs();
Gigg, Martyn Anthony
committed
event->accept();
}
/**
* Override the showEvent function
* @param event :: A pointer to the event object
*/
void ScriptingWindow::showEvent(QShowEvent *event)
{
if( m_manager->count() == 0 )
{
m_manager->newTab();
}
event->accept();
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
/**
* Open a script directly. This is here for backwards compatability with the old ScriptWindow
* class
Janik Zikovsky
committed
* @param filename :: The file name
* @param newtab :: Do we want a new tab
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
void ScriptingWindow::open(const QString & filename, bool newtab)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
m_manager->open(newtab, filename);
Gigg, Martyn Anthony
committed
}
void ScriptingWindow::executeAll()
{
m_manager->executeAll();
}
//-------------------------------------------
// Private non-slot member functions
//-------------------------------------------
/**
* Accept a custom event and in this case test if it is a ScriptingChangeEvent
Janik Zikovsky
committed
* @param event :: The custom event
Gigg, Martyn Anthony
committed
*/
void ScriptingWindow::customEvent(QEvent *event)
{
if( !m_manager->isScriptRunning() && event->type() == SCRIPTING_CHANGE_EVENT )
{
ScriptingChangeEvent *sce = static_cast<ScriptingChangeEvent*>(event);
setWindowTitle("MantidPlot: " + sce->scriptingEnv()->scriptingLanguage() + " Window");
}
}
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
/**
* Construct the file menu
*/
void ScriptingWindow::fileAboutToShow()
{
m_file_menu->clear();
// New tab
m_file_menu->addAction(m_manager->m_new_tab);
// Open a file in current tab
m_file_menu->addAction(m_manager->m_open_curtab);
//Open in new tab
m_file_menu->addAction(m_manager->m_open_newtab);
// Save a script
m_file_menu->insertSeparator();
m_file_menu->addAction(m_manager->m_save);
// Save a script under a new file name
m_file_menu->addAction(m_manager->m_saveas);
//Print
if( m_manager->count() > 0 )
{
m_file_menu->addAction(m_manager->printAction());
}
if( !m_output_dock->isEmpty() )
{
m_file_menu->addAction(m_print_output);
}
Gigg, Martyn Anthony
committed
// Scripting language
//m_file_menu->insertSeparator();
//m_file_menu->addAction(m_scripting_lang);
Gigg, Martyn Anthony
committed
Sofia Antony
committed
m_file_menu->insertSeparator();
m_file_menu->addMenu(m_manager->m_recent_scripts);
m_manager->updateRecentScriptList();
Gigg, Martyn Anthony
committed
// Close current tab
m_file_menu->insertSeparator();
m_file_menu->addAction(m_manager->m_close_tab);
}
Gigg, Martyn Anthony
committed
/**
* Construct the edit menu
*/
void ScriptingWindow::editAboutToShow()
{
m_edit_menu->clear();
if( m_manager->count() > 0 )
{
// Undo
m_edit_menu->addAction(m_manager->undoAction());
//Redo
m_edit_menu->addAction(m_manager->redoAction());
//Cut
m_edit_menu->addAction(m_manager->cutAction());
//Copy
m_edit_menu->addAction(m_manager->copyAction());
//Paste
m_edit_menu->addAction(m_manager->pasteAction());
//Find and replace
m_edit_menu->insertSeparator();
m_edit_menu->addAction(m_manager->m_find);
m_edit_menu->insertSeparator();
Gigg, Martyn Anthony
committed
//Clear output
m_edit_menu->addAction(m_clear_output);
Gigg, Martyn Anthony
committed
}
/**
*
*/
Gigg, Martyn Anthony
committed
void ScriptingWindow::updateWindowFlags()
{
Qt::WindowFlags flags = Qt::Window;
if( m_always_on_top->isChecked() )
{
flags |= Qt::WindowStaysOnTopHint;
}
setWindowFlags(flags);
//This is necessary due to the setWindowFlags function reparenting the window and causing is
//to hide itself
show();
}
void ScriptingWindow::tabSelectionChanged()
{
// Ensure that the shortcuts are active
fileAboutToShow();
editAboutToShow();
}
Gigg, Martyn Anthony
committed
//-------------------------------------------
// Private non-slot member functions
//-------------------------------------------
/**
* Initialize the menus and actions
*/
void ScriptingWindow::initMenus()
{
//************* File menu *************
m_file_menu = menuBar()->addMenu(tr("&File"));
Gigg, Martyn Anthony
committed
#ifdef SCRIPTING_DIALOG
m_scripting_lang = new QAction(tr("Scripting &language"), this);
connect(m_scripting_lang, SIGNAL(activated()), this, SIGNAL(chooseScriptingLanguage()));
#endif
connect(m_file_menu, SIGNAL(aboutToShow()), this, SLOT(fileAboutToShow()));
m_print_output = new QAction(tr("Print &Output"), this);
connect(m_print_output, SIGNAL(activated()), m_output_dock, SLOT(print()));
Gigg, Martyn Anthony
committed
//************* Edit menu *************
m_edit_menu = menuBar()->addMenu(tr("&Edit"));
connect(m_edit_menu, SIGNAL(aboutToShow()), this, SLOT(editAboutToShow()));
// Clear output
m_clear_output = new QAction(tr("&Clear Output"), this);
Gigg, Martyn Anthony
committed
connect(m_clear_output, SIGNAL(activated()), m_output_dock, SLOT(clear()));
Gigg, Martyn Anthony
committed
//************* Run menu *************
m_run_menu = menuBar()->addMenu(tr("E&xecute"));
// Execute script
m_run_menu->addAction(m_manager->m_exec);
// Execute everything from a script
m_run_menu->addAction(m_manager->m_exec_all);
//Evaluate function for those environments that support one
// m_run_menu->addAction(m_manager->m_eval);
Gigg, Martyn Anthony
committed
//************* Window menu *************
Gigg, Martyn Anthony
committed
m_window_menu = menuBar()->addMenu(tr("&Window"));
//Always on top
m_always_on_top = new QAction(tr("Always on &Top"), this);
m_always_on_top->setCheckable(true);
connect(m_always_on_top, SIGNAL(toggled(bool)), this, SLOT(updateWindowFlags()));
m_window_menu->addAction(m_always_on_top);
//Hide
m_hide = new QAction(tr("&Hide"), this);
Gigg, Martyn Anthony
committed
m_hide->setShortcut(tr("F3"));
// Note that we channel the hide through the parent so that we can save the geometry state
connect(m_hide, SIGNAL(activated()), this, SIGNAL(hideMe()));
Gigg, Martyn Anthony
committed
m_window_menu->addAction(m_hide);
Gigg, Martyn Anthony
committed
m_window_menu->insertSeparator();
Gigg, Martyn Anthony
committed
//Toggle output dock
m_toggle_output = m_output_dock->toggleViewAction();
m_toggle_output->setText("&Show Output");
m_toggle_output->setChecked(true);
m_window_menu->addAction(m_toggle_output);
Gigg, Martyn Anthony
committed
//Toggle progress
m_window_menu->addAction(m_manager->m_toggle_progress);
Gigg, Martyn Anthony
committed
m_window_menu->insertSeparator();
//Toggle folding
m_window_menu->addAction(m_manager->m_toggle_folding);
//Toggle code completion
m_window_menu->addAction(m_manager->m_toggle_completion);
//Toggle call tips
m_window_menu->addAction(m_manager->m_toggle_calltips);
Gigg, Martyn Anthony
committed
}
Sofia Antony
committed
/**
* calls ScriptManagerWidget saveToString and
* saves the currently opened script file names to a string
*/
QString ScriptingWindow::saveToString()
{
Gigg, Martyn Anthony
committed
return m_manager->saveToString();