diff --git a/include/lrglobal.h b/include/lrglobal.h index 13d8851..4829390 100644 --- a/include/lrglobal.h +++ b/include/lrglobal.h @@ -86,14 +86,16 @@ namespace Const{ const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(%1)\\s*\\}"; const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}"; const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*((?:(?:\\\")|(?:))(?:(?:\\$(?:(?:D\\{\\s*\\w*.\\w*\\s*\\})|(?:V\\{\\s*\\w*\\s*\\})|(?:S\\{.+\\})))|(?:\\w*))(?:(?:\\\")|(?:)))(?:(?:\\s*,\\s*(?:\\\"(\\w*)\\\"))|(?:))\\)"; - const int DATASOURCE_INDEX = 3;//4; - const int VALUE_INDEX = 2; //2; - const int EXPRESSION_ARGUMENT_INDEX = 1;//3; + const int DATASOURCE_INDEX = 3; + const int VALUE_INDEX = 2; + const int EXPRESSION_ARGUMENT_INDEX = 1; const QString GROUP_FUNCTION_RX = "(%1\\s*"+GROUP_FUNCTION_PARAM_RX+")"; const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const int SCENE_MARGIN = 50; const QString FUNCTION_MANAGER_NAME = "LimeReport"; + const QString EOW("~!@#$%^&*()+{}|:\"<>?,/;'[]\\-="); + } QString extractClassName(QString className); QString escapeSimbols(const QString& value); diff --git a/limereport/lrglobal.h b/limereport/lrglobal.h index 13d8851..4829390 100644 --- a/limereport/lrglobal.h +++ b/limereport/lrglobal.h @@ -86,14 +86,16 @@ namespace Const{ const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(%1)\\s*\\}"; const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}"; const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*((?:(?:\\\")|(?:))(?:(?:\\$(?:(?:D\\{\\s*\\w*.\\w*\\s*\\})|(?:V\\{\\s*\\w*\\s*\\})|(?:S\\{.+\\})))|(?:\\w*))(?:(?:\\\")|(?:)))(?:(?:\\s*,\\s*(?:\\\"(\\w*)\\\"))|(?:))\\)"; - const int DATASOURCE_INDEX = 3;//4; - const int VALUE_INDEX = 2; //2; - const int EXPRESSION_ARGUMENT_INDEX = 1;//3; + const int DATASOURCE_INDEX = 3; + const int VALUE_INDEX = 2; + const int EXPRESSION_ARGUMENT_INDEX = 1; const QString GROUP_FUNCTION_RX = "(%1\\s*"+GROUP_FUNCTION_PARAM_RX+")"; const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const int SCENE_MARGIN = 50; const QString FUNCTION_MANAGER_NAME = "LimeReport"; + const QString EOW("~!@#$%^&*()+{}|:\"<>?,/;'[]\\-="); + } QString extractClassName(QString className); QString escapeSimbols(const QString& value); diff --git a/limereport/lrreportdesignwindow.cpp b/limereport/lrreportdesignwindow.cpp index a969617..fb2d073 100644 --- a/limereport/lrreportdesignwindow.cpp +++ b/limereport/lrreportdesignwindow.cpp @@ -1100,8 +1100,6 @@ void ReportDesignWindow::slotLoadReport() setWindowTitle(m_reportDesignWidget->report()->reportName() + " - Lime Report Designer"); addRecentFile(fileName); m_editorTabType = ReportDesignWidget::Page; - //showDefaultToolBars(); - //showDefaultEditors(); } } diff --git a/limereport/lrreportengine.cpp b/limereport/lrreportengine.cpp index 977a7e8..9123426 100644 --- a/limereport/lrreportengine.cpp +++ b/limereport/lrreportengine.cpp @@ -71,7 +71,7 @@ ReportEnginePrivate::ReportEnginePrivate(QObject *parent) : m_previewWindowIcon(":/report/images/logo32"), m_previewWindowTitle(tr("Preview")), m_reportRendering(false), m_resultIsEditable(true), m_passPhrase("HjccbzHjlbyfCkjy"), m_fileWatcher( new QFileSystemWatcher( this ) ), m_reportLanguage(QLocale::AnyLanguage), - m_designerFactory(0), m_previewLayoutDirection(Qt::LeftToRight) + m_previewLayoutDirection(Qt::LeftToRight), m_designerFactory(0) { #ifdef HAVE_STATIC_BUILD initResources(); diff --git a/limereport/lrscriptenginemanager.cpp b/limereport/lrscriptenginemanager.cpp index 0e3c2b4..2bc89a5 100644 --- a/limereport/lrscriptenginemanager.cpp +++ b/limereport/lrscriptenginemanager.cpp @@ -1275,9 +1275,11 @@ void ScriptEngineContext::baseDesignIntfToScript(const QString& pageName, BaseDe #ifdef USE_QJSENGINE ScriptValueType sItem = getCppOwnedJSValue(*engine, item); - engine->globalObject().setProperty(pageName+"_"+item->patternName(), sItem); + QString on = item->patternName().compare(pageName) == 0 ? pageName : pageName+"_"+item->patternName(); + engine->globalObject().setProperty(on, sItem); #else - ScriptValueType sItem = engine->globalObject().property(pageName+"_"+item->patternName()); + QString on = item->patternName().compare(pageName) == 0 ? pageName : pageName+"_"+item->patternName(); + ScriptValueType sItem = engine->globalObject().property(on); if (sItem.isValid()){ engine->newQObject(sItem, item); } else { diff --git a/limereport/scripteditor/lrcodeeditor.cpp b/limereport/scripteditor/lrcodeeditor.cpp index 75a86bc..0b7af1a 100644 --- a/limereport/scripteditor/lrcodeeditor.cpp +++ b/limereport/scripteditor/lrcodeeditor.cpp @@ -10,6 +10,7 @@ #include #include "lrscripthighlighter.h" +#include "lrglobal.h" namespace LimeReport{ @@ -92,6 +93,10 @@ void CodeEditor::keyPressEvent(QKeyEvent *e) case Qt::Key_Escape: case Qt::Key_Tab: case Qt::Key_Backtab: + case Qt::Key_Right: + case Qt::Key_Left: + case Qt::Key_Up: + case Qt::Key_Down: e->ignore(); return; default: @@ -106,13 +111,14 @@ void CodeEditor::keyPressEvent(QKeyEvent *e) if (!m_compleater || (ctrlOrShift && e->text().isEmpty())) return; - static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift; QString completionPrefix = textUnderCursor(); if (!isShortcut && (hasModifier || e->text().isEmpty()|| completionPrefix.length() < 3 - || eow.contains(e->text().right(1)))) { + || Const::EOW.contains(e->text().right(1))) + ) + { m_compleater->popup()->hide(); return; } @@ -122,11 +128,22 @@ void CodeEditor::keyPressEvent(QKeyEvent *e) m_compleater->popup()->setCurrentIndex(m_compleater->completionModel()->index(0, 0)); } + QModelIndex ci = m_compleater->completionModel()->index(0,0); + if (ci.isValid() && m_compleater->completionModel()->data(ci).toString().compare(completionPrefix) == 0){ + m_compleater->popup()->hide(); + return; + } + QRect cr = cursorRect(); cr.setWidth(m_compleater->popup()->sizeHintForColumn(0) + m_compleater->popup()->verticalScrollBar()->sizeHint().width()); m_compleater->complete(cr); + if (!completionPrefix.isEmpty() && + completionPrefix.at(completionPrefix.length()-1) == '.') + { + m_compleater->popup(); + } } void CodeEditor::focusInEvent(QFocusEvent *e) @@ -145,8 +162,15 @@ void CodeEditor::resizeEvent(QResizeEvent* event) QString CodeEditor::textUnderCursor() const { QTextCursor tc = textCursor(); - tc.select(QTextCursor::WordUnderCursor); - return tc.selectedText(); + QString currentText; + tc.movePosition(QTextCursor::StartOfBlock,QTextCursor::KeepAnchor); + QString blockText = tc.selectedText(); + for(int i = blockText.length(); i>0; --i){ + if (!Const::EOW.contains(blockText.at(i-1))) + currentText = blockText.at(i-1) + currentText; + else break; + } + return currentText; } bool CodeEditor::matchLeftParenthesis(QTextBlock currentBlock, QChar parenthesisType, int i, int numLeftParentheses) diff --git a/limereport/scripteditor/lrscripteditor.cpp b/limereport/scripteditor/lrscripteditor.cpp index a661e1c..1b84f25 100644 --- a/limereport/scripteditor/lrscripteditor.cpp +++ b/limereport/scripteditor/lrscripteditor.cpp @@ -18,7 +18,7 @@ ScriptEditor::ScriptEditor(QWidget *parent) : { ui->setupUi(this); setFocusProxy(ui->textEdit); - m_completer = new QCompleter(this); + m_completer = new ReportStructureCompleater(this); ui->textEdit->setCompleter(m_completer); connect(ui->splitter, SIGNAL(splitterMoved(int,int)), this, SIGNAL(splitterMoved(int,int))); } @@ -81,47 +81,60 @@ void ScriptEditor::setPageBand(BandDesignIntf* band) void ScriptEditor::initCompleter() { - QStringList dataWords; +// QStringList dataWords; - DataSourceManager* dm = 0; +// DataSourceManager* dm = 0; +// if (m_reportEngine) +// dm = m_reportEngine->dataManager(); +// if (m_page) +// dm = m_page->datasourceManager(); + +//#ifdef USE_QJSENGINE +// ScriptEngineManager& se = LimeReport::ScriptEngineManager::instance(); +// QJSValue globalObject = se.scriptEngine()->globalObject(); +// QJSValueIterator it(globalObject); +// while (it.hasNext()){ +// it.next(); +// if (it.value().isCallable() ){ +// dataWords << it.name(); +// } +// } +//#endif +// foreach(const QString &dsName,dm->dataSourceNames()){ +// dataWords << dsName; +// foreach(const QString &field, dm->fieldNames(dsName)){ +// dataWords<variableNames()) { +// dataWords << varName.remove("#"); +// } + +// if (m_reportEngine){ +// for ( int i = 0; i < m_reportEngine->pageCount(); ++i){ +// PageDesignIntf* page = m_reportEngine->pageAt(i); +// dataWords << page->pageItem()->objectName(); +// QMetaObject const * mo = page->pageItem()->metaObject(); +// for(int i = mo->methodOffset(); i < mo->methodCount(); ++i) +// { +// if (mo->method(i).methodType() == QMetaMethod::Signal) { +// dataWords << page->pageItem()->objectName() +"."+QString::fromLatin1(mo->method(i).name()); +// } +// } +// dataWords << page->pageItem()->objectName()+".beforeRender"; +// dataWords << page->pageItem()->objectName()+".afterRender"; +// foreach (BaseDesignIntf* item, page->pageItem()->childBaseItems()){ +// addItemToCompleater(page->pageItem()->objectName(), item, dataWords); +// } +// } +// } + +// dataWords.sort(); if (m_reportEngine) - dm = m_reportEngine->dataManager(); - if (m_page) - dm = m_page->datasourceManager(); - -#ifdef USE_QJSENGINE - ScriptEngineManager& se = LimeReport::ScriptEngineManager::instance(); - QJSValue globalObject = se.scriptEngine()->globalObject(); - QJSValueIterator it(globalObject); - while (it.hasNext()){ - it.next(); - if (it.value().isCallable() ){ - dataWords << it.name(); - } - } -#endif - foreach(const QString &dsName,dm->dataSourceNames()){ - dataWords << dsName; - foreach(const QString &field, dm->fieldNames(dsName)){ - dataWords<variableNames()) { - dataWords << varName.remove("#"); - } - - if (m_reportEngine){ - for ( int i = 0; i < m_reportEngine->pageCount(); ++i){ - PageDesignIntf* page = m_reportEngine->pageAt(i); - dataWords << page->pageItem()->objectName(); - foreach (BaseDesignIntf* item, page->pageItem()->childBaseItems()){ - addItemToCompleater(page->pageItem()->objectName(), item, dataWords); - } - } - } - - m_completer->setModel(new QStringListModel(dataWords,m_completer)); + m_completer->updateCompleaterModel(m_reportEngine); + else + m_completer->updateCompleaterModel(m_page->datasourceManager()); } QByteArray ScriptEditor::saveState() @@ -206,6 +219,129 @@ void ScriptEditor::slotOnCurrentChanged(const QModelIndex &to, const QModelIndex } } + + +QString ReportStructureCompleater::pathFromIndex(const QModelIndex &index) const +{ + QStringList dataList; + for (QModelIndex i = index; i.isValid(); i = i.parent()) { + dataList.prepend(model()->data(i, Qt::DisplayRole).toString()); + } + return dataList.join("."); +} + +QStringList ReportStructureCompleater::splitPath(const QString &path) const +{ + return path.split("."); +} + +void ReportStructureCompleater::addAdditionalDatawords(DataSourceManager* dataManager){ + + foreach(const QString &dsName,dataManager->dataSourceNames()){ + QStandardItem* dsNode = new QStandardItem; + dsNode->setText(dsName); + foreach(const QString &field, dataManager->fieldNames(dsName)){ + QStandardItem* fieldNode = new QStandardItem; + fieldNode->setText(field); + dsNode->appendRow(fieldNode); + } + m_model.invisibleRootItem()->appendRow(dsNode); + } + + foreach (QString varName, dataManager->variableNames()) { + QStandardItem* varNode = new QStandardItem; + varNode->setText(varName.remove("#")); + m_model.invisibleRootItem()->appendRow(varNode); + } + +#ifdef USE_QJSENGINE + ScriptEngineManager& se = LimeReport::ScriptEngineManager::instance(); + QJSValue globalObject = se.scriptEngine()->globalObject(); + QJSValueIterator it(globalObject); + while (it.hasNext()){ + it.next(); + if (it.value().isCallable() ){ + QStandardItem* itemNode = new QStandardItem; + itemNode->setText(it.name()); + m_model.invisibleRootItem()->appendRow(itemNode); + } + } +#endif + +} + +void ReportStructureCompleater::updateCompleaterModel(ReportEnginePrivateInterface* report) +{ + if (report){ + m_model.clear(); + + addAdditionalDatawords(report->dataManager()); + + for ( int i = 0; i < report->pageCount(); ++i){ + PageDesignIntf* page = report->pageAt(i); + + QStandardItem* itemNode = new QStandardItem; + itemNode->setText(page->pageItem()->objectName()); + m_model.invisibleRootItem()->appendRow(itemNode); + + QStringList slotsNames = extractSlotNames(page->pageItem()); + foreach(QString slotName, slotsNames){ + QStandardItem* slotItem = new QStandardItem; + slotItem->setText(slotName); + itemNode->appendRow(slotItem); + } + foreach (BaseDesignIntf* item, page->pageItem()->childBaseItems()){ + addChildItem(item, itemNode->text(), m_model.invisibleRootItem()); + } + } + } +} + +void ReportStructureCompleater::updateCompleaterModel(DataSourceManager *dataManager) +{ + m_model.clear(); + addAdditionalDatawords(dataManager); +} + +QStringList ReportStructureCompleater::extractSlotNames(BaseDesignIntf *item) +{ + QStringList result; + if (!item) return result; + QMetaObject const * mo = item->metaObject(); + while (mo){ + for(int i = mo->methodOffset(); i < mo->methodCount(); ++i) + { + if (mo->method(i).methodType() == QMetaMethod::Signal) { + result.append(QString::fromLatin1(mo->method(i).name())); + } + } + mo = mo->superClass(); + } + result.sort(); + return result; +} + +void ReportStructureCompleater::addChildItem(BaseDesignIntf *item, const QString &pageName, QStandardItem *parent) +{ + if (!item) return; + + QStandardItem* itemNode = new QStandardItem; + itemNode->setText(pageName+"_"+item->objectName()); + parent->appendRow(itemNode); + QStringList slotNames = extractSlotNames(item); + foreach(QString slotName, slotNames){ + QStandardItem* slotItem = new QStandardItem; + slotItem->setText(slotName); + itemNode->appendRow(slotItem); + } + //BandDesignIntf* band = dynamic_cast(item); + //if (band){ + foreach (BaseDesignIntf* child, item->childBaseItems()){ + addChildItem(child, pageName, parent); + } + //} +} + } // namespace LimeReport diff --git a/limereport/scripteditor/lrscripteditor.h b/limereport/scripteditor/lrscripteditor.h index f9b8db7..666dbc9 100644 --- a/limereport/scripteditor/lrscripteditor.h +++ b/limereport/scripteditor/lrscripteditor.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace LimeReport{ @@ -19,6 +20,26 @@ namespace Ui { class ScriptEditor; } +class ReportStructureCompleater : public QCompleter{ + Q_OBJECT +public: + explicit ReportStructureCompleater(QObject* parent = 0): QCompleter(parent){ setModel(&m_model);} + explicit ReportStructureCompleater(QAbstractItemModel* model, QObject* parent = 0) + :QCompleter(model, parent){ setModel(&m_model);} +public: + // QCompleter interface + QString pathFromIndex(const QModelIndex& index) const; + QStringList splitPath(const QString& path) const; + void updateCompleaterModel(ReportEnginePrivateInterface* report); + void updateCompleaterModel(DataSourceManager* dataManager); +protected: + QStringList extractSlotNames(BaseDesignIntf* item); + void addChildItem(BaseDesignIntf *item, const QString &pageName, QStandardItem *parent); + void addAdditionalDatawords(DataSourceManager *dataManager); +private: + QStandardItemModel m_model; +}; + class ScriptEditor : public QWidget { Q_OBJECT @@ -50,8 +71,7 @@ private: Ui::ScriptEditor *ui; ReportEnginePrivateInterface* m_reportEngine; PageDesignIntf* m_page; - QCompleter* m_completer; - + ReportStructureCompleater* m_completer; }; } // namespace LimeReport