+ unify DLL export defines to namespace names
git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5000 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
This commit is contained in:
595
src/Gui/EditorView.cpp
Normal file
595
src/Gui/EditorView.cpp
Normal file
@@ -0,0 +1,595 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2007 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QAbstractTextDocumentLayout>
|
||||
# include <QApplication>
|
||||
# include <QClipboard>
|
||||
# include <QDateTime>
|
||||
# include <QHBoxLayout>
|
||||
# include <QMessageBox>
|
||||
# include <QPainter>
|
||||
# include <QPrinter>
|
||||
# include <QPrintDialog>
|
||||
# include <QScrollBar>
|
||||
# include <QPlainTextEdit>
|
||||
# include <QPrintPreviewDialog>
|
||||
# include <QTextBlock>
|
||||
# include <QTextCodec>
|
||||
# include <QTextStream>
|
||||
# include <QTimer>
|
||||
#endif
|
||||
|
||||
#include "EditorView.h"
|
||||
#include "Application.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "FileDialog.h"
|
||||
#include "Macro.h"
|
||||
#include "PythonDebugger.h"
|
||||
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Parameter.h>
|
||||
|
||||
using namespace Gui;
|
||||
namespace Gui {
|
||||
class EditorViewP {
|
||||
public:
|
||||
QPlainTextEdit* textEdit;
|
||||
QString fileName;
|
||||
QTimer* activityTimer;
|
||||
uint timeStamp;
|
||||
bool lock;
|
||||
QStringList undos;
|
||||
QStringList redos;
|
||||
};
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR Gui::EditorView */
|
||||
|
||||
/**
|
||||
* Constructs a EditorView which is a child of 'parent', with the
|
||||
* name 'name'.
|
||||
*/
|
||||
EditorView::EditorView(QPlainTextEdit* editor, QWidget* parent)
|
||||
: MDIView(0,parent,0), WindowParameter( "Editor" )
|
||||
{
|
||||
d = new EditorViewP;
|
||||
d->lock = false;
|
||||
|
||||
// create the editor first
|
||||
d->textEdit = editor;
|
||||
d->textEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
|
||||
|
||||
// Create the layout containing the workspace and a tab bar
|
||||
QFrame* hbox = new QFrame(this);
|
||||
hbox->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
|
||||
QHBoxLayout* layout = new QHBoxLayout();
|
||||
layout->setMargin(1);
|
||||
layout->addWidget(d->textEdit);
|
||||
d->textEdit->setParent(hbox);
|
||||
hbox->setLayout(layout);
|
||||
setCentralWidget(hbox);
|
||||
|
||||
setCurrentFileName(QString());
|
||||
d->textEdit->setFocus();
|
||||
|
||||
setWindowIcon(d->textEdit->windowIcon());
|
||||
|
||||
ParameterGrp::handle hPrefGrp = getWindowParameter();
|
||||
hPrefGrp->Attach( this );
|
||||
hPrefGrp->NotifyAll();
|
||||
|
||||
d->activityTimer = new QTimer(this);
|
||||
connect(d->activityTimer, SIGNAL(timeout()),
|
||||
this, SLOT(checkTimestamp()) );
|
||||
connect(d->textEdit->document(), SIGNAL(modificationChanged(bool)),
|
||||
this, SLOT(setWindowModified(bool)));
|
||||
connect(d->textEdit->document(), SIGNAL(undoAvailable(bool)),
|
||||
this, SLOT(undoAvailable(bool)));
|
||||
connect(d->textEdit->document(), SIGNAL(redoAvailable(bool)),
|
||||
this, SLOT(redoAvailable(bool)));
|
||||
connect(d->textEdit->document(), SIGNAL(contentsChange(int, int, int)),
|
||||
this, SLOT(contentsChange(int, int, int)));
|
||||
}
|
||||
|
||||
/** Destroys the object and frees any allocated resources */
|
||||
EditorView::~EditorView()
|
||||
{
|
||||
d->activityTimer->stop();
|
||||
delete d->activityTimer;
|
||||
delete d;
|
||||
getWindowParameter()->Detach( this );
|
||||
}
|
||||
|
||||
void EditorView::drawMarker(int line, int x, int y, QPainter*)
|
||||
{
|
||||
}
|
||||
|
||||
QPlainTextEdit* EditorView::getEditor() const
|
||||
{
|
||||
return d->textEdit;
|
||||
}
|
||||
|
||||
void EditorView::OnChange(Base::Subject<const char*> &rCaller,const char* rcReason)
|
||||
{
|
||||
ParameterGrp::handle hPrefGrp = getWindowParameter();
|
||||
if (strcmp(rcReason, "EnableLineNumber") == 0) {
|
||||
//bool show = hPrefGrp->GetBool( "EnableLineNumber", true );
|
||||
}
|
||||
}
|
||||
|
||||
void EditorView::checkTimestamp()
|
||||
{
|
||||
QFileInfo fi(d->fileName);
|
||||
uint timeStamp = fi.lastModified().toTime_t();
|
||||
if (timeStamp != d->timeStamp) {
|
||||
switch( QMessageBox::question( this, tr("Modified file"),
|
||||
tr("%1.\n\nThis has been modified outside of the source editor. Do you want to reload it?").arg(d->fileName),
|
||||
QMessageBox::Yes|QMessageBox::Default, QMessageBox::No|QMessageBox::Escape) )
|
||||
{
|
||||
case QMessageBox::Yes:
|
||||
// updates time stamp and timer
|
||||
open( d->fileName );
|
||||
return;
|
||||
case QMessageBox::No:
|
||||
d->timeStamp = timeStamp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d->activityTimer->setSingleShot(true);
|
||||
d->activityTimer->start(3000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the action specified by \a pMsg.
|
||||
*/
|
||||
bool EditorView::onMsg(const char* pMsg,const char** ppReturn)
|
||||
{
|
||||
if (strcmp(pMsg,"Save")==0){
|
||||
saveFile();
|
||||
return true;
|
||||
} else if (strcmp(pMsg,"SaveAs")==0){
|
||||
saveAs();
|
||||
return true;
|
||||
} else if (strcmp(pMsg,"Cut")==0){
|
||||
cut();
|
||||
return true;
|
||||
} else if (strcmp(pMsg,"Copy")==0){
|
||||
copy();
|
||||
return true;
|
||||
} else if (strcmp(pMsg,"Paste")==0){
|
||||
paste();
|
||||
return true;
|
||||
} else if (strcmp(pMsg,"Undo")==0){
|
||||
undo();
|
||||
return true;
|
||||
} else if (strcmp(pMsg,"Redo")==0){
|
||||
redo();
|
||||
return true;
|
||||
} else if (strcmp(pMsg,"ViewFit")==0){
|
||||
// just ignore this
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the action \a pMsg is available. This is for enabling/disabling
|
||||
* the corresponding buttons or menu items for this action.
|
||||
*/
|
||||
bool EditorView::onHasMsg(const char* pMsg) const
|
||||
{
|
||||
if (strcmp(pMsg,"Run")==0) return true;
|
||||
if (strcmp(pMsg,"DebugStart")==0) return true;
|
||||
if (strcmp(pMsg,"DebugStop")==0) return true;
|
||||
if (strcmp(pMsg,"SaveAs")==0) return true;
|
||||
if (strcmp(pMsg,"Print")==0) return true;
|
||||
if (strcmp(pMsg,"PrintPreview")==0) return true;
|
||||
if (strcmp(pMsg,"PrintPdf")==0) return true;
|
||||
if (strcmp(pMsg,"Save")==0) {
|
||||
return d->textEdit->document()->isModified();
|
||||
} else if (strcmp(pMsg,"Cut")==0) {
|
||||
bool canWrite = !d->textEdit->isReadOnly();
|
||||
return (canWrite && (d->textEdit->textCursor().hasSelection()));
|
||||
} else if (strcmp(pMsg,"Copy")==0) {
|
||||
return ( d->textEdit->textCursor().hasSelection() );
|
||||
} else if (strcmp(pMsg,"Paste")==0) {
|
||||
QClipboard *cb = QApplication::clipboard();
|
||||
QString text;
|
||||
|
||||
// Copy text from the clipboard (paste)
|
||||
text = cb->text();
|
||||
|
||||
bool canWrite = !d->textEdit->isReadOnly();
|
||||
return ( !text.isEmpty() && canWrite );
|
||||
} else if (strcmp(pMsg,"Undo")==0) {
|
||||
return d->textEdit->document()->isUndoAvailable ();
|
||||
} else if (strcmp(pMsg,"Redo")==0) {
|
||||
return d->textEdit->document()->isRedoAvailable ();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Checking on close state. */
|
||||
bool EditorView::canClose(void)
|
||||
{
|
||||
if ( !d->textEdit->document()->isModified() )
|
||||
return true;
|
||||
this->setFocus(); // raises the view to front
|
||||
switch( QMessageBox::question(this, tr("Unsaved document"),
|
||||
tr("The document has been modified.\n"
|
||||
"Do you want to save your changes?"),
|
||||
QMessageBox::Yes|QMessageBox::Default, QMessageBox::No,
|
||||
QMessageBox::Cancel|QMessageBox::Escape))
|
||||
{
|
||||
case QMessageBox::Yes:
|
||||
return saveFile();
|
||||
case QMessageBox::No:
|
||||
return true;
|
||||
case QMessageBox::Cancel:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the content of the editor to a file specified by the appearing file dialog.
|
||||
*/
|
||||
bool EditorView::saveAs(void)
|
||||
{
|
||||
QString fn = FileDialog::getSaveFileName(this, QObject::tr("Save Macro"),
|
||||
QString::null, tr("FreeCAD macro (*.FCMacro);;Python (*.py)"));
|
||||
if (fn.isEmpty())
|
||||
return false;
|
||||
setCurrentFileName(fn);
|
||||
return saveFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the file \a fileName.
|
||||
*/
|
||||
bool EditorView::open(const QString& fileName)
|
||||
{
|
||||
if (!QFile::exists(fileName))
|
||||
return false;
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
return false;
|
||||
|
||||
d->lock = true;
|
||||
d->textEdit->setPlainText(QString::fromUtf8(file.readAll()));
|
||||
d->lock = false;
|
||||
d->undos.clear();
|
||||
d->redos.clear();
|
||||
file.close();
|
||||
|
||||
QFileInfo fi(fileName);
|
||||
d->timeStamp = fi.lastModified().toTime_t();
|
||||
d->activityTimer->setSingleShot(true);
|
||||
d->activityTimer->start(3000);
|
||||
|
||||
setCurrentFileName(fileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the selected text to the clipboard and deletes it from the text edit.
|
||||
* If there is no selected text nothing happens.
|
||||
*/
|
||||
void EditorView::cut(void)
|
||||
{
|
||||
d->textEdit->cut();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies any selected text to the clipboard.
|
||||
*/
|
||||
void EditorView::copy(void)
|
||||
{
|
||||
d->textEdit->copy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pastes the text from the clipboard into the text edit at the current cursor position.
|
||||
* If there is no text in the clipboard nothing happens.
|
||||
*/
|
||||
void EditorView::paste(void)
|
||||
{
|
||||
d->textEdit->paste();
|
||||
}
|
||||
|
||||
/**
|
||||
* Undoes the last operation.
|
||||
* If there is no operation to undo, i.e. there is no undo step in the undo/redo history, nothing happens.
|
||||
*/
|
||||
void EditorView::undo(void)
|
||||
{
|
||||
d->lock = true;
|
||||
if (!d->undos.isEmpty()) {
|
||||
d->redos << d->undos.back();
|
||||
d->undos.pop_back();
|
||||
}
|
||||
d->textEdit->document()->undo();
|
||||
d->lock = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redoes the last operation.
|
||||
* If there is no operation to undo, i.e. there is no undo step in the undo/redo history, nothing happens.
|
||||
*/
|
||||
void EditorView::redo(void)
|
||||
{
|
||||
d->lock = true;
|
||||
if (!d->redos.isEmpty()) {
|
||||
d->undos << d->redos.back();
|
||||
d->redos.pop_back();
|
||||
}
|
||||
d->textEdit->document()->redo();
|
||||
d->lock = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the printer dialog.
|
||||
*/
|
||||
void EditorView::print()
|
||||
{
|
||||
QPrinter printer(QPrinter::HighResolution);
|
||||
printer.setFullPage(true);
|
||||
QPrintDialog dlg(&printer, this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
d->textEdit->document()->print(&printer);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorView::printPreview()
|
||||
{
|
||||
QPrinter printer(QPrinter::HighResolution);
|
||||
QPrintPreviewDialog dlg(&printer, this);
|
||||
connect(&dlg, SIGNAL(paintRequested (QPrinter *)),
|
||||
this, SLOT(print(QPrinter *)));
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void EditorView::print(QPrinter* printer)
|
||||
{
|
||||
d->textEdit->document()->print(printer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the document into a Pdf file.
|
||||
*/
|
||||
void EditorView::printPdf()
|
||||
{
|
||||
QString filename = FileDialog::getSaveFileName(this, tr("Export PDF"), QString(), tr("PDF file (*.pdf)"));
|
||||
if (!filename.isEmpty()) {
|
||||
QPrinter printer(QPrinter::HighResolution);
|
||||
printer.setOutputFormat(QPrinter::PdfFormat);
|
||||
printer.setOutputFileName(filename);
|
||||
d->textEdit->document()->print(&printer);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorView::setCurrentFileName(const QString &fileName)
|
||||
{
|
||||
d->fileName = fileName;
|
||||
d->textEdit->document()->setModified(false);
|
||||
|
||||
QString shownName;
|
||||
if (fileName.isEmpty())
|
||||
shownName = tr("untitled[*]");
|
||||
else
|
||||
shownName = QString::fromAscii("%1[*]").arg(fileName);
|
||||
shownName += tr(" - Editor");
|
||||
setWindowTitle(shownName);
|
||||
setWindowModified(false);
|
||||
}
|
||||
|
||||
QString EditorView::fileName() const
|
||||
{
|
||||
return d->fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the contents to a file.
|
||||
*/
|
||||
bool EditorView::saveFile()
|
||||
{
|
||||
if (d->fileName.isEmpty())
|
||||
return saveAs();
|
||||
|
||||
QFile file(d->fileName);
|
||||
if (!file.open(QFile::WriteOnly))
|
||||
return false;
|
||||
QTextStream ts(&file);
|
||||
ts.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
ts << d->textEdit->document()->toPlainText();
|
||||
file.close();
|
||||
d->textEdit->document()->setModified(false);
|
||||
|
||||
QFileInfo fi(d->fileName);
|
||||
d->timeStamp = fi.lastModified().toTime_t();
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditorView::undoAvailable(bool undo)
|
||||
{
|
||||
if (!undo)
|
||||
d->undos.clear();
|
||||
}
|
||||
|
||||
void EditorView::redoAvailable(bool redo)
|
||||
{
|
||||
if (!redo)
|
||||
d->redos.clear();
|
||||
}
|
||||
|
||||
void EditorView::contentsChange(int position, int charsRemoved, int charsAdded)
|
||||
{
|
||||
if (d->lock)
|
||||
return;
|
||||
if (charsRemoved > 0 && charsAdded > 0)
|
||||
return; // syntax highlighting
|
||||
else if (charsRemoved > 0)
|
||||
d->undos << tr("%1 chars removed").arg(charsRemoved);
|
||||
else if (charsAdded > 0)
|
||||
d->undos << tr("%1 chars added").arg(charsAdded);
|
||||
else
|
||||
d->undos << tr("Formatted");
|
||||
d->redos.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the undo history.
|
||||
*/
|
||||
QStringList EditorView::undoActions() const
|
||||
{
|
||||
return d->undos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the redo history.
|
||||
*/
|
||||
QStringList EditorView::redoActions() const
|
||||
{
|
||||
return d->redos;;
|
||||
}
|
||||
|
||||
void EditorView::focusInEvent (QFocusEvent * e)
|
||||
{
|
||||
d->textEdit->setFocus();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
PythonEditorView::PythonEditorView(QPlainTextEdit* editor, QWidget* parent)
|
||||
: EditorView(editor, parent), m_debugLine(-1),
|
||||
breakpoint(QLatin1String(":/icons/breakpoint.png")),
|
||||
debugMarker(QLatin1String(":/icons/debug-marker.png"))
|
||||
{
|
||||
_dbg = Application::Instance->macroManager()->debugger();
|
||||
}
|
||||
|
||||
PythonEditorView::~PythonEditorView()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the action specified by \a pMsg.
|
||||
*/
|
||||
bool PythonEditorView::onMsg(const char* pMsg,const char** ppReturn)
|
||||
{
|
||||
if (strcmp(pMsg,"Run")==0) {
|
||||
executeScript();
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(pMsg,"StartDebug")==0) {
|
||||
startDebug();
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(pMsg,"ToggleBreakpoint")==0) {
|
||||
toggleBreakpoint();
|
||||
return true;
|
||||
}
|
||||
return EditorView::onMsg(pMsg, ppReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the action \a pMsg is available. This is for enabling/disabling
|
||||
* the corresponding buttons or menu items for this action.
|
||||
*/
|
||||
bool PythonEditorView::onHasMsg(const char* pMsg) const
|
||||
{
|
||||
if (strcmp(pMsg,"Run")==0) return true;
|
||||
if (strcmp(pMsg,"StartDebug")==0) return true;
|
||||
if (strcmp(pMsg,"ToggleBreakpoint")==0) return true;
|
||||
return EditorView::onHasMsg(pMsg);
|
||||
}
|
||||
|
||||
void PythonEditorView::drawMarker(int line, int x, int y, QPainter* p)
|
||||
{
|
||||
Breakpoint bp = _dbg->getBreakpoint(fileName());
|
||||
if (bp.checkLine(line)) {
|
||||
p->drawPixmap(x, y, breakpoint);
|
||||
}
|
||||
if (m_debugLine == line) {
|
||||
p->drawPixmap(x, y+2, debugMarker);
|
||||
debugRect = QRect(x, y+2, debugMarker.width(), debugMarker.height());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the opened script in the macro manager.
|
||||
*/
|
||||
void PythonEditorView::executeScript()
|
||||
{
|
||||
Application::Instance->macroManager()->run(Gui::MacroManager::File,fileName().toUtf8());
|
||||
}
|
||||
|
||||
void PythonEditorView::startDebug()
|
||||
{
|
||||
if (_dbg->start()) {
|
||||
_dbg->runFile(fileName());
|
||||
_dbg->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void PythonEditorView::toggleBreakpoint()
|
||||
{
|
||||
QTextCursor cursor = getEditor()->textCursor();
|
||||
int line = cursor.blockNumber() + 1;
|
||||
_dbg->toggleBreakpoint(line, fileName());
|
||||
// getMarker()->update();
|
||||
}
|
||||
|
||||
void PythonEditorView::showDebugMarker(int line)
|
||||
{
|
||||
m_debugLine = line;
|
||||
// getMarker()->update();
|
||||
QTextCursor cursor = getEditor()->textCursor();
|
||||
cursor.movePosition(QTextCursor::StartOfBlock);
|
||||
int cur = cursor.blockNumber() + 1;
|
||||
if (cur > line) {
|
||||
for (int i=line; i<cur; i++)
|
||||
cursor.movePosition(QTextCursor::Up);
|
||||
}
|
||||
else if (cur < line) {
|
||||
for (int i=cur; i<line; i++)
|
||||
cursor.movePosition(QTextCursor::Down);
|
||||
}
|
||||
getEditor()->setTextCursor(cursor);
|
||||
}
|
||||
|
||||
void PythonEditorView::hideDebugMarker()
|
||||
{
|
||||
m_debugLine = -1;
|
||||
// getMarker()->update();
|
||||
}
|
||||
|
||||
#include "moc_EditorView.cpp"
|
||||
Reference in New Issue
Block a user