3 Copyright (c) 2012 Jakob Leben & Tim Blechmann
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "lookup_dialog.hpp"
22 #include "main_window.hpp"
23 #include "../core/sc_introspection.hpp"
24 #include "../core/main.hpp"
26 #include <QVBoxLayout>
27 #include <QHeaderView>
29 #include <QDesktopWidget>
30 #include <QApplication>
33 #include "yaml-cpp/node.h"
34 #include "yaml-cpp/parser.h"
38 GenericLookupDialog::GenericLookupDialog( QWidget
* parent
):
39 QDialog(parent
, Qt::Popup
| Qt::FramelessWindowHint
)
41 mQueryEdit
= new QLineEdit(this);
43 mResult
= new QTreeView(this);
44 mResult
->setRootIsDecorated(false);
45 mResult
->setAllColumnsShowFocus(true);
46 mResult
->setHeaderHidden(true);
47 mResult
->header()->setStretchLastSection(false);
49 QVBoxLayout
*layout
= new QVBoxLayout
;
50 layout
->setContentsMargins(4,4,4,4);
51 layout
->setSpacing(1);
52 layout
->addWidget(mQueryEdit
);
53 layout
->addWidget(mResult
);
56 connect(mQueryEdit
, SIGNAL(returnPressed()), this, SLOT(performQuery()));
57 connect(mResult
, SIGNAL(doubleClicked(QModelIndex
)), this, SLOT(onAccepted(QModelIndex
)));
58 connect(mResult
, SIGNAL(activated(QModelIndex
)), this, SLOT(onAccepted(QModelIndex
)));
60 mResult
->installEventFilter(this);
62 QRect
bounds(0,0,600,300);
64 QRect parentRect
= parent
->rect();
65 bounds
.moveCenter( parent
->mapToGlobal( parentRect
.center() ) );
67 QRect availableBounds
= QApplication::desktop()->availableGeometry(this);
68 bounds
.moveCenter( availableBounds
.center() );
73 mQueryEdit
->setFocus( Qt::OtherFocusReason
);
76 void GenericLookupDialog::onAccepted(QModelIndex currentIndex
)
78 QStandardItemModel
* model
= qobject_cast
<QStandardItemModel
*>(mResult
->model());
79 currentIndex
= currentIndex
.sibling(currentIndex
.row(), 0);
80 QStandardItem
*currentItem
= model
->itemFromIndex(currentIndex
);
86 QString path
= currentItem
->data( PathRole
).toString();
87 int pos
= currentItem
->data( CharPosRole
).toInt();
89 Main::documentManager()->open(path
, pos
);
93 bool GenericLookupDialog::eventFilter( QObject
*object
, QEvent
*event
)
95 if (object
== mResult
&& event
->type() == QEvent::KeyPress
) {
96 QKeyEvent
*ke
= static_cast<QKeyEvent
*>(event
);
100 onAccepted(mResult
->currentIndex());
106 return QDialog::eventFilter(object
,event
);
109 void GenericLookupDialog::paintEvent( QPaintEvent
* )
111 QPainter
painter(this);
112 painter
.setBrush(Qt::NoBrush
);
113 painter
.setPen(palette().color(QPalette::Dark
));
114 painter
.drawRect(rect().adjusted(0,0,-1,-1));
117 void GenericLookupDialog::focusResults()
119 mResult
->header()->resizeSections(QHeaderView::ResizeToContents
);
120 mResult
->setFocus(Qt::OtherFocusReason
);
122 QStandardItemModel
* model
= qobject_cast
<QStandardItemModel
*>(mResult
->model());
123 QStandardItem
* firstItem
= model
->item(0, 0);
125 QModelIndex firstIndex
= model
->indexFromItem(firstItem
);
126 mResult
->setCurrentIndex(firstIndex
);
130 using namespace ScLanguage
;
134 LookupDialog::LookupDialog( QWidget
* parent
):
135 GenericLookupDialog(parent
), mIsPartialQuery(false)
137 setWindowTitle(tr("Look Up Class or Method Definition"));
139 mQueryEdit
->setText(tr("Enter symbol to look up"));
140 mQueryEdit
->selectAll();
143 void LookupDialog::performQuery()
145 QString queryString
= mQueryEdit
->text();
147 if (queryString
.isEmpty()) {
148 mResult
->setModel(NULL
);
152 const Introspection
& introspection
= Main::scProcess()->introspection();
153 if (!introspection
.introspectionAvailable()) {
154 MainWindow::instance()->showStatusMessage("Introspection data not yet available");
158 mIsPartialQuery
= false;
159 if (queryString
[0].isUpper()) {
160 bool success
= performClassQuery(queryString
);
166 bool success
= performMethodQuery(queryString
);
173 bool success
= performPartialQuery(queryString
);
178 void LookupDialog::onAccepted(QModelIndex currentIndex
)
180 if (!mIsPartialQuery
) {
181 GenericLookupDialog::onAccepted(currentIndex
);
185 QStandardItemModel
* model
= qobject_cast
<QStandardItemModel
*>(mResult
->model());
186 currentIndex
= currentIndex
.sibling(currentIndex
.row(), 0);
187 QStandardItem
*currentItem
= model
->itemFromIndex(currentIndex
);
194 bool isClass
= currentItem
->data(IsClassRole
).toBool();
196 GenericLookupDialog::onAccepted(currentIndex
);
200 QString className
= currentItem
->text();
201 mQueryEdit
->setText(className
);
205 QList
<QStandardItem
*> GenericLookupDialog::makeDialogItem( QString
const & name
, QString
const & displayPath
,
206 QString
const & path
, int position
, bool isClassItem
)
208 QStandardItem
* item
= new QStandardItem( name
);
209 item
->setData( path
, PathRole
);
210 item
->setData( position
, CharPosRole
);
211 item
->setData( isClassItem
, IsClassRole
);
212 QStandardItem
* pathItem
= new QStandardItem(displayPath
);
214 QList
<QStandardItem
*> ret
;
215 ret
<< item
<< pathItem
;
220 QStandardItemModel
* LookupDialog::modelForClass(const QString
&className
)
222 const Introspection
& introspection
= Main::scProcess()->introspection();
223 const Class
*klass
= introspection
.findClass(className
);
228 QStandardItemModel
* model
= new QStandardItemModel(this);
229 QStandardItem
*parentItem
= model
->invisibleRootItem();
232 Class
*metaClass
= klass
->metaClass
;
234 QString displayPath
= introspection
.compactLibraryPath(klass
->definition
.path
);
236 parentItem
->appendRow(makeDialogItem(klass
->name
.get(), displayPath
,
237 klass
->definition
.path
.get(),
238 klass
->definition
.position
, true ));
240 foreach (const Method
* method
, metaClass
->methods
) {
241 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
242 QString displayPath
= introspection
.compactLibraryPath(method
->definition
.path
);
244 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
245 method
->definition
.path
.get(),
246 method
->definition
.position
, false ));
249 foreach (const Method
* method
, klass
->methods
) {
250 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
251 QString displayPath
= introspection
.compactLibraryPath(method
->definition
.path
);
253 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
254 method
->definition
.path
.get(),
255 method
->definition
.position
, false ));
258 klass
= klass
->superClass
;
264 QStandardItemModel
* LookupDialog::modelForMethod(const QString
& methodName
)
266 const Introspection
& introspection
= Main::scProcess()->introspection();
268 const MethodMap
& methods
= introspection
.methodMap();
269 pair
<MethodMap::const_iterator
, MethodMap::const_iterator
> matchingMethods
= methods
.equal_range(methodName
);
271 if (matchingMethods
.first
== matchingMethods
.second
)
274 QStandardItemModel
* model
= new QStandardItemModel(this);
275 QStandardItem
*parentItem
= model
->invisibleRootItem();
277 for (MethodMap::const_iterator it
= matchingMethods
.first
; it
!= matchingMethods
.second
; ++it
) {
278 Method
*method
= it
->second
.data();
279 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
281 const QString
& path
= method
->definition
.path
;
282 QString displayPath
= introspection
.compactLibraryPath(path
);
284 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
285 method
->definition
.path
.get(),
286 method
->definition
.position
, false ));
293 QStandardItemModel
* LookupDialog::modelForPartialQuery(const QString
& queryString
)
295 const Introspection
& introspection
= Main::scProcess()->introspection();
296 vector
<const Class
*> classes
= introspection
.findClassPartial(queryString
);
297 vector
<const Method
*> methods
= introspection
.findMethodPartial(queryString
);
298 typedef vector
<const Method
*>::const_iterator MethodIterator
;
299 typedef vector
<const Class
*>::const_iterator ClassIterator
;
301 if (classes
.empty() && methods
.empty()) {
302 MainWindow::instance()->showStatusMessage("No result for query");
306 mIsPartialQuery
= true;
307 QStandardItemModel
* model
= new QStandardItemModel(this);
308 QStandardItem
*parentItem
= model
->invisibleRootItem();
310 for (MethodIterator it
= methods
.begin(); it
!= methods
.end(); ++it
) {
311 const Method
*method
= *it
;
312 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
314 const QString
& path
= method
->definition
.path
;
315 QString displayPath
= introspection
.compactLibraryPath(path
);
317 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
318 method
->definition
.path
.get(),
319 method
->definition
.position
, false ));
322 for (ClassIterator it
= classes
.begin(); it
!= classes
.end(); ++it
) {
323 const Class
* klass
= *it
;
324 QString displayPath
= introspection
.compactLibraryPath(klass
->definition
.path
);
326 parentItem
->appendRow(makeDialogItem(klass
->name
.get(), displayPath
,
327 klass
->definition
.path
.get(),
328 klass
->definition
.position
, true ));
335 bool LookupDialog::performClassQuery(const QString
& className
)
337 QStandardItemModel
* model
= modelForClass(className
);
338 mResult
->setModel(model
);
342 bool LookupDialog::performMethodQuery(const QString
& methodName
)
344 QStandardItemModel
* model
= modelForMethod(methodName
);
345 mResult
->setModel(model
);
349 bool LookupDialog::performPartialQuery(const QString
& queryString
)
351 QStandardItemModel
* model
= modelForPartialQuery(queryString
);
352 mResult
->setModel(model
);
357 ReferencesDialog::ReferencesDialog(QWidget
* parent
):
360 setWindowTitle(tr("Look Up References"));
362 mQueryEdit
->setText(tr("Enter symbol to find references"));
363 mQueryEdit
->selectAll();
366 void ReferencesDialog::performQuery()
368 QString queryString
= mQueryEdit
->text();
370 if (queryString
.isEmpty()) {
371 mResult
->setModel(NULL
);
375 SymbolReferenceRequest
* request
= new SymbolReferenceRequest(Main::scProcess(), this);
376 connect(request
, SIGNAL(response(QString
,QString
)), this, SLOT(onResposeFromLanguage(QString
,QString
)));
377 connect(request
, SIGNAL(requestCanceled()), this, SLOT(requestCanceled()));
378 request
->sendRequest(queryString
);
381 void ReferencesDialog::requestCanceled()
383 mResult
->setModel(NULL
);
386 void ReferencesDialog::onResposeFromLanguage(const QString
&, const QString
&responseData
)
388 QStandardItemModel
* model
= parse(responseData
);
389 mResult
->setModel(model
);
395 QStandardItemModel
* ReferencesDialog::parse(const QString
&responseData
)
397 using namespace ScLanguage
;
398 const Introspection
& introspection
= Main::scProcess()->introspection();
400 if (!introspection
.introspectionAvailable()) { // just required for short path name
401 MainWindow::instance()->showStatusMessage("Introspection data not yet available");
405 std::stringstream stream
;
406 stream
<< responseData
.toStdString();
407 YAML::Parser
parser(stream
);
410 if(!parser
.GetNextDocument(doc
)) {
411 qWarning("no YAML document");
415 assert (doc
.Type() == YAML::NodeType::Sequence
);
417 QString symbol
= doc
[0].to
<std::string
>().c_str();
419 QStandardItemModel
* model
= new QStandardItemModel(this);
420 QStandardItem
*parentItem
= model
->invisibleRootItem();
422 YAML::Node
const & references
= doc
[1];
424 for (YAML::Iterator refIt
= references
.begin(); refIt
!= references
.end(); ++refIt
) {
425 YAML::Node
const & reference
= *refIt
;
426 QString className
= reference
[0].to
<std::string
>().c_str();
427 QString methodName
= reference
[1].to
<std::string
>().c_str();
428 QString path
= reference
[2].to
<std::string
>().c_str();
429 int charPos
= reference
[3].to
<int>();
431 QString displayPath
= introspection
.compactLibraryPath(path
);
432 QString fullName
= ScLanguage::makeFullMethodName(className
, methodName
);
434 parentItem
->appendRow(makeDialogItem(fullName
, displayPath
, path
, charPos
, false));