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
)
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 if (queryString
[0].isUpper()) {
159 bool success
= performClassQuery(queryString
);
165 bool success
= performMethodQuery(queryString
);
172 bool success
= performPartialQuery(queryString
);
177 QList
<QStandardItem
*> GenericLookupDialog::makeDialogItem( QString
const & name
, QString
const & displayPath
,
178 QString
const & path
, int position
, bool isClassItem
)
180 QStandardItem
* item
= new QStandardItem( name
);
181 item
->setData( path
, PathRole
);
182 item
->setData( position
, CharPosRole
);
183 item
->setData( isClassItem
, IsClassRole
);
184 QStandardItem
* pathItem
= new QStandardItem(displayPath
);
186 QList
<QStandardItem
*> ret
;
187 ret
<< item
<< pathItem
;
192 QStandardItemModel
* LookupDialog::modelForClass(const QString
&className
)
194 const Introspection
& introspection
= Main::scProcess()->introspection();
195 const Class
*klass
= introspection
.findClass(className
);
200 QStandardItemModel
* model
= new QStandardItemModel(this);
201 QStandardItem
*parentItem
= model
->invisibleRootItem();
204 Class
*metaClass
= klass
->metaClass
;
206 QString displayPath
= introspection
.compactLibraryPath(klass
->definition
.path
);
208 parentItem
->appendRow(makeDialogItem(klass
->name
.get(), displayPath
,
209 klass
->definition
.path
.get(),
210 klass
->definition
.position
, true ));
212 foreach (const Method
* method
, metaClass
->methods
) {
213 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
214 QString displayPath
= introspection
.compactLibraryPath(method
->definition
.path
);
216 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
217 method
->definition
.path
.get(),
218 method
->definition
.position
, false ));
221 foreach (const Method
* method
, klass
->methods
) {
222 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
223 QString displayPath
= introspection
.compactLibraryPath(method
->definition
.path
);
225 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
226 method
->definition
.path
.get(),
227 method
->definition
.position
, false ));
230 klass
= klass
->superClass
;
236 QStandardItemModel
* LookupDialog::modelForMethod(const QString
& methodName
)
238 const Introspection
& introspection
= Main::scProcess()->introspection();
240 const MethodMap
& methods
= introspection
.methodMap();
241 pair
<MethodMap::const_iterator
, MethodMap::const_iterator
> matchingMethods
= methods
.equal_range(methodName
);
243 if (matchingMethods
.first
== matchingMethods
.second
)
246 QStandardItemModel
* model
= new QStandardItemModel(this);
247 QStandardItem
*parentItem
= model
->invisibleRootItem();
249 for (MethodMap::const_iterator it
= matchingMethods
.first
; it
!= matchingMethods
.second
; ++it
) {
250 Method
*method
= it
->second
.data();
251 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
253 const QString
& path
= method
->definition
.path
;
254 QString displayPath
= introspection
.compactLibraryPath(path
);
256 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
257 method
->definition
.path
.get(),
258 method
->definition
.position
, false ));
265 QStandardItemModel
* LookupDialog::modelForPartialQuery(const QString
& queryString
)
267 const Introspection
& introspection
= Main::scProcess()->introspection();
268 vector
<const Class
*> classes
= introspection
.findClassPartial(queryString
);
269 vector
<const Method
*> methods
= introspection
.findMethodPartial(queryString
);
270 typedef vector
<const Method
*>::const_iterator MethodIterator
;
271 typedef vector
<const Class
*>::const_iterator ClassIterator
;
273 if (classes
.empty() && methods
.empty()) {
274 MainWindow::instance()->showStatusMessage("No result for query");
278 QStandardItemModel
* model
= new QStandardItemModel(this);
279 QStandardItem
*parentItem
= model
->invisibleRootItem();
281 for (MethodIterator it
= methods
.begin(); it
!= methods
.end(); ++it
) {
282 const Method
*method
= *it
;
283 QString signature
= method
->signature( Method::SignatureWithoutArguments
);
285 const QString
& path
= method
->definition
.path
;
286 QString displayPath
= introspection
.compactLibraryPath(path
);
288 parentItem
->appendRow(makeDialogItem( signature
, displayPath
,
289 method
->definition
.path
.get(),
290 method
->definition
.position
, false ));
293 for (ClassIterator it
= classes
.begin(); it
!= classes
.end(); ++it
) {
294 const Class
* klass
= *it
;
295 QString displayPath
= introspection
.compactLibraryPath(klass
->definition
.path
);
297 parentItem
->appendRow(makeDialogItem(klass
->name
.get(), displayPath
,
298 klass
->definition
.path
.get(),
299 klass
->definition
.position
, true ));
306 bool LookupDialog::performClassQuery(const QString
& className
)
308 QStandardItemModel
* model
= modelForClass(className
);
309 mResult
->setModel(model
);
313 bool LookupDialog::performMethodQuery(const QString
& methodName
)
315 QStandardItemModel
* model
= modelForMethod(methodName
);
316 mResult
->setModel(model
);
320 bool LookupDialog::performPartialQuery(const QString
& queryString
)
322 QStandardItemModel
* model
= modelForPartialQuery(queryString
);
323 mResult
->setModel(model
);
328 ReferencesDialog::ReferencesDialog(QWidget
* parent
):
331 setWindowTitle(tr("Look Up References"));
333 mQueryEdit
->setText(tr("Enter symbol to find references"));
334 mQueryEdit
->selectAll();
337 void ReferencesDialog::performQuery()
339 QString queryString
= mQueryEdit
->text();
341 if (queryString
.isEmpty()) {
342 mResult
->setModel(NULL
);
346 SymbolReferenceRequest
* request
= new SymbolReferenceRequest(Main::scProcess(), this);
347 connect(request
, SIGNAL(response(QString
,QString
)), this, SLOT(onResposeFromLanguage(QString
,QString
)));
348 connect(request
, SIGNAL(requestCanceled()), this, SLOT(requestCanceled()));
349 request
->sendRequest(queryString
);
352 void ReferencesDialog::requestCanceled()
354 mResult
->setModel(NULL
);
357 void ReferencesDialog::onResposeFromLanguage(const QString
&, const QString
&responseData
)
359 QStandardItemModel
* model
= parse(responseData
);
360 mResult
->setModel(model
);
366 QStandardItemModel
* ReferencesDialog::parse(const QString
&responseData
)
368 using namespace ScLanguage
;
369 const Introspection
& introspection
= Main::scProcess()->introspection();
371 if (!introspection
.introspectionAvailable()) { // just required for short path name
372 MainWindow::instance()->showStatusMessage("Introspection data not yet available");
376 std::stringstream stream
;
377 stream
<< responseData
.toStdString();
378 YAML::Parser
parser(stream
);
381 if(!parser
.GetNextDocument(doc
)) {
382 qWarning("no YAML document");
386 assert (doc
.Type() == YAML::NodeType::Sequence
);
388 QString symbol
= doc
[0].to
<std::string
>().c_str();
390 QStandardItemModel
* model
= new QStandardItemModel(this);
391 QStandardItem
*parentItem
= model
->invisibleRootItem();
393 YAML::Node
const & references
= doc
[1];
395 for (YAML::Iterator refIt
= references
.begin(); refIt
!= references
.end(); ++refIt
) {
396 YAML::Node
const & reference
= *refIt
;
397 QString className
= reference
[0].to
<std::string
>().c_str();
398 QString methodName
= reference
[1].to
<std::string
>().c_str();
399 QString path
= reference
[2].to
<std::string
>().c_str();
400 int charPos
= reference
[3].to
<int>();
402 QString displayPath
= introspection
.compactLibraryPath(path
);
403 QString fullName
= ScLanguage::makeFullMethodName(className
, methodName
);
405 parentItem
->appendRow(makeDialogItem(fullName
, displayPath
, path
, charPos
, false));