Newer
Older
#include "qmlcontextpane.h"
#include <contextpanewidget.h>
#include <qmldesignerplugin.h>
#include <utils/changeset.h>
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljspropertyreader.h>
#include <qmljs/qmljsrewriter.h>
#include <qmljs/qmljsindenter.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/tabsettings.h>
#include <colorwidget.h>
#include <QDebug>
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using namespace QmlJS;
using namespace AST;
namespace QmlDesigner {
static inline QString textAt(const Document* doc,
const SourceLocation &from,
const SourceLocation &to)
{
return doc->source().mid(from.offset, to.end() - from.begin());
}
QmlContextPane::QmlContextPane(QObject *parent) : ::QmlJS::IContextPane(parent), m_blockWriting(false)
{
m_node = 0;
ContextPaneWidget();
m_propertyOrder
<< QLatin1String("id")
<< QLatin1String("name")
<< QLatin1String("target")
<< QLatin1String("property")
<< QLatin1String("x")
<< QLatin1String("y")
<< QLatin1String("width")
<< QLatin1String("height")
<< QLatin1String("position")
<< QLatin1String("color")
<< QLatin1String("radius")
<< QLatin1String("text")
<< QLatin1String("font.family")
<< QLatin1String("font.bold")
<< QLatin1String("font.italic")
<< QLatin1String("font.underline")
<< QLatin1String("font.strikeout")
<< QString::null
<< QLatin1String("states")
<< QLatin1String("transitions")
;
}
QmlContextPane::~QmlContextPane()
{
//if the pane was never activated the widget is not in a widget tree
if (!m_widget.isNull())
delete m_widget.data();
m_widget.clear();
}
void QmlContextPane::apply(TextEditor::BaseTextEditorEditable *editor, Document::Ptr doc, Node *node, bool update)
{
if (!Internal::BauhausPlugin::pluginInstance()->settings().enableContextPane)
return;
if (doc.isNull())
return;
if (update && editor != m_editor)
return; //do not update for different editor
setEnabled(doc->isParsedCorrectly());
m_editor = editor;
contextWidget()->setParent(editor->widget()->parentWidget());
contextWidget()->colorDialog()->setParent(editor->widget()->parentWidget());
if (cast<UiObjectDefinition*>(node) || cast<UiObjectBinding*>(node)) {
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition*>(node);
UiObjectBinding *objectBinding = cast<UiObjectBinding*>(node);
QString name;
quint32 offset;
quint32 end;
UiObjectInitializer *initializer;
if (objectDefinition) {
name = objectDefinition->qualifiedTypeNameId->name->asString();
initializer = objectDefinition->initializer;
offset = objectDefinition->firstSourceLocation().offset;
end = objectDefinition->lastSourceLocation().end();
} else if (objectBinding) {
name = objectBinding->qualifiedTypeNameId->name->asString();
initializer = objectBinding->initializer;
offset = objectBinding->firstSourceLocation().offset;
end = objectBinding->lastSourceLocation().end();
}
if (name.contains("Text")) {
m_node = 0;
PropertyReader propertyReader(doc.data(), initializer);
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
QTextCursor tc(editor->editor()->document());
tc.setPosition(offset);
QPoint p1 = editor->editor()->mapToParent(editor->editor()->viewport()->mapToParent(editor->editor()->cursorRect(tc).topLeft()) - QPoint(0, contextWidget()->height() + 10));
tc.setPosition(end);
QPoint p2 = editor->editor()->mapToParent(editor->editor()->viewport()->mapToParent(editor->editor()->cursorRect(tc).bottomLeft()) + QPoint(0, 10));
p2.setX(p1.x());
if (!update)
contextWidget()->activate(p1 , p2);
else
contextWidget()->rePosition(p1 , p2);
m_blockWriting = true;
contextWidget()->setType(name);
contextWidget()->setProperties(&propertyReader);
m_blockWriting = false;
m_doc = doc;
m_node = node;
} else {
contextWidget()->setParent(0);
contextWidget()->hide();
contextWidget()->colorDialog()->hide();
}
} else {
contextWidget()->setParent(0);
contextWidget()->hide();
contextWidget()->colorDialog()->hide();
}
}
void QmlContextPane::setProperty(const QString &propertyName, const QVariant &value)
{
QString stringValue = value.toString();
if (value.type() == QVariant::Color)
stringValue = QChar('\"') + value.toString() + QChar('\"');
if (cast<UiObjectDefinition*>(m_node) || cast<UiObjectBinding*>(m_node)) {
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition*>(m_node);
UiObjectBinding *objectBinding = cast<UiObjectBinding*>(m_node);
UiObjectInitializer *initializer;
if (objectDefinition)
initializer = objectDefinition->initializer;
else if (objectBinding)
initializer = objectBinding->initializer;
Utils::ChangeSet changeSet;
Rewriter rewriter(m_doc->source(), &changeSet, m_propertyOrder);
int line = 1;
PropertyReader propertyReader(m_doc.data(), initializer);
if (propertyReader.hasProperty(propertyName)) {
rewriter.changeProperty(initializer, propertyName, stringValue, Rewriter::ScriptBinding);
rewriter.addBinding(initializer, propertyName, stringValue, Rewriter::ScriptBinding);
int column;
m_editor->convertPosition(changeSet.operationList().first().pos1, &line, &column); //get line
}
QTextCursor tc(m_editor->editor()->document());
tc.beginEditBlock();
int cursorPostion = tc.position();
tc.beginEditBlock();
changeSet.apply(&tc);
if (line > 0) {
TextEditor::TabSettings ts = m_editor->editor()->tabSettings();
QmlJSIndenter indenter;
indenter.setTabSize(ts.m_tabSize);
indenter.setIndentSize(ts.m_indentSize);
QTextBlock start = m_editor->editor()->document()->findBlockByLineNumber(line);
QTextBlock end = m_editor->editor()->document()->findBlockByLineNumber(line);
const int indent = indenter.indentForBottomLine(m_editor->editor()->document()->begin(), end.next(), QChar::Null);
ts.indentLine(start, indent);
}
tc.endEditBlock();
tc.setPosition(cursorPostion);
tc.endEditBlock();
tc.setPosition(cursorPostion);
}
}
void QmlContextPane::removeProperty(const QString &propertyName)
{
if (cast<UiObjectDefinition*>(m_node) || cast<UiObjectBinding*>(m_node)) {
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition*>(m_node);
UiObjectBinding *objectBinding = cast<UiObjectBinding*>(m_node);
UiObjectInitializer *initializer;
if (objectDefinition)
initializer = objectDefinition->initializer;
else if (objectBinding)
initializer = objectBinding->initializer;
PropertyReader propertyReader(m_doc.data(), initializer);
if (propertyReader.hasProperty(propertyName)) {
Utils::ChangeSet changeSet;
Rewriter rewriter(m_doc->source(), &changeSet, m_propertyOrder);
rewriter.removeProperty(initializer, propertyName);
QTextCursor tc(m_editor->editor()->document());
changeSet.apply(&tc);
}
}
}
void QmlContextPane::setEnabled(bool b)
{
if (m_widget)
m_widget->currentWidget()->setEnabled(b);
}
void QmlContextPane::onPropertyChanged(const QString &name, const QVariant &value)
{
if (m_blockWriting)
return;
if (!m_doc)
return;
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
setProperty(name, value);
m_doc.clear(); //the document is outdated
}
void QmlContextPane::onPropertyRemovedAndChange(const QString &remove, const QString &change, const QVariant &value)
{
if (m_blockWriting)
return;
if (!m_doc)
return;
setProperty(change, value);
removeProperty(remove);
m_doc.clear(); //the document is outdated
}
ContextPaneWidget* QmlContextPane::contextWidget()
{
if (m_widget.isNull()) { //lazily recreate widget
m_widget = new ContextPaneWidget;
connect(m_widget.data(), SIGNAL(propertyChanged(QString,QVariant)), this, SLOT(onPropertyChanged(QString,QVariant)));
connect(m_widget.data(), SIGNAL(removeProperty(QString)), this, SLOT(onPropertyRemoved(QString)));
connect(m_widget.data(), SIGNAL(removeAndChangeProperty(QString,QString,QVariant)), this, SLOT(onPropertyRemovedAndChange(QString,QString,QVariant)));
}
return m_widget.data();
}
void QmlContextPane::onPropertyRemoved(const QString &propertyName)
{
if (m_blockWriting)
return;
if (!m_doc)
return;
removeProperty(propertyName);
m_doc.clear(); //the document is outdated
}
} //QmlDesigner