blob: db6b9b9914a40eb2edc873f55552aa66321685f2 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "Editor.h"
#include "JSInterface.h"
#include <QWebView>
#include <QWebFrame>
#include <QFile>
#include <QLayout>
#include <QBoxLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QCoreApplication>
#include <QMouseEvent>
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Cursor //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
Cursor::Cursor(QWidget *parent)
{
}
Cursor::~Cursor()
{
}
void Cursor::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(0,0,size().width(),size().height(),QColor(0,0,255));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// EditorJSCallbacks //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
class EditorJSCallbacks : public JSCallbacks
{
public:
EditorJSCallbacks(Editor *editor) : _editor(editor) {}
void debug(const QString &message);
void addOutlineItem(const QString &itemId, const QString &type, const QString &title);
void updateOutlineItem(const QString &itemId, const QString &title);
void removeOutlineItem(const QString &itemId);
void outlineUpdated();
void setCursor(int x, int y, int width, int height);
void setSelectionHandles(int x1, int y1, int height1, int x2, int y2, int height2);
void setTableSelection(int x, int y, int width, int height);
void setSelectionBounds(int left, int top, int right, int bottom);
void clearSelectionHandlesAndCursor();
void updateAutoCorrect();
void error(const QString &message, const QString &operation);
//private:
Editor *_editor;
};
class EditorJSEvaluator : public JSEvaluator
{
public:
EditorJSEvaluator(QWebView *webView, JSCallbacks *callbacks) : _webView(webView), _callbacks(callbacks) {}
virtual QString evaluate(const QString &script);
virtual JSCallbacks *callbacks() { return _callbacks; }
private:
QWebView *_webView;
JSCallbacks *_callbacks;
};
const char *jsSources[] = {
"first.js",
"ElementTypes.js",
"AutoCorrect.js",
"ChangeTracking.js",
"Clipboard.js",
"Cursor.js",
"DOM.js",
"Editor.js",
"Equations.js",
"Figures.js",
"Formatting.js",
"Hierarchy.js",
"Input.js",
"Lists.js",
"Main.js",
"Metadata.js",
"NodeSet.js",
"Outline.js",
"Position.js",
"PostponedActions.js",
"Preview.js",
"Range.js",
"Scan.js",
"Selection.js",
"StringBuilder.js",
"Styles.js",
"Tables.js",
"Text.js",
"traversal.js",
"types.js",
"UndoManager.js",
"util.js",
"Viewport.js",
NULL,
};
void EditorJSCallbacks::debug(const QString &message)
{
qStdOut() << "CB debug \"" << message << "\"" << endl;
}
void EditorJSCallbacks::addOutlineItem(const QString &itemId, const QString &type, const QString &title)
{
qStdOut() << "CB addOutlineItem " << itemId << " " << type << " \"" << title << "\"" << endl;
}
void EditorJSCallbacks::updateOutlineItem(const QString &itemId, const QString &title)
{
qStdOut() << "CB updateOutlineItem " << itemId << " \"" << title << "\"" << endl;
}
void EditorJSCallbacks::removeOutlineItem(const QString &itemId)
{
qStdOut() << "CB removeOutlineItem " << itemId << endl;
}
void EditorJSCallbacks::outlineUpdated()
{
qStdOut() << "CB outlineUpdated" << endl;
}
void EditorJSCallbacks::setCursor(int x, int y, int width, int height)
{
qStdOut() << "CB setCursor " << x << " " << y << " " << width << " " << height << endl;
_editor->cursor()->setVisible(true);
_editor->cursor()->setGeometry(x,y,width,height);
}
void EditorJSCallbacks::setSelectionHandles(int x1, int y1, int height1, int x2, int y2, int height2)
{
qStdOut() << "CB setSelectionHandles " << x1 << " " << y1 << " " << height1 << " "
<< x2 << " " << y2 << " " << height2 << endl;
_editor->cursor()->setVisible(false);
}
void EditorJSCallbacks::setTableSelection(int x, int y, int width, int height)
{
qStdOut() << "CB setTableSelection" << x << " " << y << " " << width << " " << height << endl;
_editor->cursor()->setVisible(false);
}
void EditorJSCallbacks::setSelectionBounds(int left, int top, int right, int bottom)
{
qStdOut() << "CB setSelectionBounds " << left << " " << top << " " << right << " " << bottom << endl;
}
void EditorJSCallbacks::clearSelectionHandlesAndCursor()
{
qStdOut() << "CB clearSelectionHandlesAndCursor" << endl;
}
void EditorJSCallbacks::updateAutoCorrect()
{
qStdOut() << "CB updateAutoCorrect" << endl;
}
void EditorJSCallbacks::error(const QString &message, const QString &operation)
{
qStdOut() << "CB error \"" << message << "\" \"" << operation << "\"" << endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// EditorJSEvaluator //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
QString EditorJSEvaluator::evaluate(const QString &script)
{
QWebFrame *frame = _webView->page()->mainFrame();
QVariant result = frame->evaluateJavaScript(script);
if (result.userType() != QMetaType::QString)
return QString::null;
else
return result.toString();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Editor //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
Editor::Editor(QWidget *parent, Qt::WindowFlags f) : QWidget(parent,f)
{
_webView = new QWebView(this);
_callbacks = new EditorJSCallbacks(this);
_evaluator = new EditorJSEvaluator(_webView,_callbacks);
_js = new JSInterface(_evaluator);
_selecting = false;
_cursor = new Cursor(this);
_cursor->setHidden(true);
QObject::connect(_webView,SIGNAL(loadFinished(bool)),this,SLOT(webViewloadFinished(bool)));
_webView->installEventFilter(this);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0,0,0,0);
layout->addWidget(_webView);
layout->addWidget(_cursor);
setLayout(layout);
}
Editor::~Editor()
{
delete _webView;
delete _callbacks;
delete _evaluator;
delete _js;
}
void Editor::webViewloadFinished(bool ok)
{
qStdOut() << "webViewloadFinished: ok = " << ok << endl;
if (!ok)
return;
QWebFrame *frame = _webView->page()->mainFrame();
// frame->evaluateJavaScript("alert('This is a test')");
QString appPath = QCoreApplication::applicationDirPath();
QString baseDir = appPath + "/../share/corinthia/js";
baseDir = QUrl::fromLocalFile(baseDir).toLocalFile();
qStdOut() << "js base dir = " << baseDir << endl;
for (int i = 0; jsSources[i] != NULL; i++) {
QString fullPath = baseDir + "/" + QString(jsSources[i]);
QFile file(fullPath);
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
QString content = stream.readAll();
frame->evaluateJavaScript(content);
}
else {
qStdOut() << "Can't open file " << fullPath << endl;
return;
}
}
frame->evaluateJavaScript("Main_init()");
processCallbacks(_evaluator);
}
void Editor::mouseDoubleClickEvent(QMouseEvent *event)
{
}
void Editor::mouseMoveEvent(QMouseEvent *event)
{
if (_selecting) {
js()->selection.dragSelectionUpdate(event->x(),event->y(),false);
}
}
void Editor::mousePressEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
_selecting = true;
js()->selection.dragSelectionBegin(event->x(),event->y(),false);
}
}
void Editor::mouseReleaseEvent(QMouseEvent *event)
{
_selecting = false;
}
void Editor::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
_js->viewport.setViewportWidth(size().width());
}
bool Editor::eventFilter(QObject *obj, QEvent *event)
{
if (obj == _webView) {
switch (event->type()) {
case QEvent::MouseButtonDblClick:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove:
case QEvent::MouseTrackingChange:
this->event(event);
return true;
default:
break;
}
}
return QWidget::eventFilter(obj,event);
}