1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtSCriptTools module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qscriptbreakpointswidget_p.h"
43 #include "qscriptbreakpointswidgetinterface_p_p.h"
44 #include "qscriptbreakpointsmodel_p.h"
45 #include "qscriptdebuggerscriptsmodel_p.h"
47 #include <QtCore/qdebug.h>
48 #include <QtGui/qaction.h>
49 #include <QtGui/qcompleter.h>
50 #include <QtGui/qheaderview.h>
51 #include <QtGui/qlineedit.h>
52 #include <QtGui/qmessagebox.h>
53 #include <QtGui/qtoolbar.h>
54 #include <QtGui/qtoolbutton.h>
55 #include <QtGui/qtreeview.h>
56 #include <QtGui/qboxlayout.h>
57 #include <QtGui/qstyleditemdelegate.h>
58 #include <QtGui/qevent.h>
59 #include <QtScript/qscriptengine.h>
63 class QScriptNewBreakpointWidget
: public QWidget
67 QScriptNewBreakpointWidget(QWidget
*parent
= 0)
69 QString system
= QLatin1String("win");
70 QHBoxLayout
*hboxLayout
= new QHBoxLayout(this);
72 system
= QLatin1String("mac");
74 hboxLayout
->setSpacing(6);
75 hboxLayout
->setMargin(0);
78 toolClose
= new QToolButton(this);
79 toolClose
->setIcon(QIcon(QString::fromUtf8(":/qt/scripttools/debugging/images/%1/closetab.png").arg(system
)));
80 toolClose
->setAutoRaise(true);
81 toolClose
->setText(QObject::tr("Close"));
82 hboxLayout
->addWidget(toolClose
);
84 fileNameEdit
= new QLineEdit();
85 setFocusProxy(fileNameEdit
);
86 QRegExp
locationRegExp(QString::fromLatin1(".+:[0-9]+"));
87 QRegExpValidator
*validator
= new QRegExpValidator(locationRegExp
, fileNameEdit
);
88 fileNameEdit
->setValidator(validator
);
89 hboxLayout
->addWidget(fileNameEdit
);
91 toolOk
= new QToolButton(this);
92 toolOk
->setIcon(QIcon(QString::fromUtf8(":/qt/scripttools/debugging/images/%1/plus.png").arg(system
)));
93 toolOk
->setAutoRaise(true);
94 toolOk
->setEnabled(false);
95 hboxLayout
->addWidget(toolOk
);
97 QObject::connect(toolClose
, SIGNAL(clicked()), this, SLOT(hide()));
98 QObject::connect(toolOk
, SIGNAL(clicked()), this, SLOT(onOkClicked()));
99 QObject::connect(fileNameEdit
, SIGNAL(textChanged(QString
)),
100 this, SLOT(onTextChanged()));
101 QObject::connect(fileNameEdit
, SIGNAL(returnPressed()),
102 this, SLOT(onOkClicked()));
105 void setCompleter(QCompleter
*comp
)
106 { fileNameEdit
->setCompleter(comp
); }
109 void newBreakpointRequest(const QString
&fileName
, int lineNumber
);
112 void keyPressEvent(QKeyEvent
*e
)
114 if (e
->key() == Qt::Key_Escape
)
117 QWidget::keyPressEvent(e
);
123 QString location
= fileNameEdit
->text();
124 fileNameEdit
->clear();
125 QString fileName
= location
.left(location
.lastIndexOf(QLatin1Char(':')));
126 int lineNumber
= location
.mid(fileName
.length()+1).toInt();
127 emit
newBreakpointRequest(fileName
, lineNumber
);
132 toolOk
->setEnabled(fileNameEdit
->hasAcceptableInput());
136 QLineEdit
*fileNameEdit
;
137 QToolButton
*toolClose
;
143 class QScriptBreakpointsWidgetPrivate
144 : public QScriptBreakpointsWidgetInterfacePrivate
146 Q_DECLARE_PUBLIC(QScriptBreakpointsWidget
)
148 QScriptBreakpointsWidgetPrivate();
149 ~QScriptBreakpointsWidgetPrivate();
151 void _q_newBreakpoint();
152 void _q_deleteBreakpoint();
153 void _q_onCurrentChanged(const QModelIndex
&index
);
154 void _q_onNewBreakpointRequest(const QString
&fileName
, int lineNumber
);
156 static QPixmap
pixmap(const QString
&path
)
158 static QString prefix
= QString::fromLatin1(":/qt/scripttools/debugging/images/");
159 return QPixmap(prefix
+ path
);
163 QScriptNewBreakpointWidget
*newBreakpointWidget
;
164 QAction
*deleteBreakpointAction
;
165 QScriptDebuggerScriptsModel
*scriptsModel
;
168 QScriptBreakpointsWidgetPrivate::QScriptBreakpointsWidgetPrivate()
172 QScriptBreakpointsWidgetPrivate::~QScriptBreakpointsWidgetPrivate()
176 void QScriptBreakpointsWidgetPrivate::_q_newBreakpoint()
178 newBreakpointWidget
->show();
179 newBreakpointWidget
->setFocus(Qt::OtherFocusReason
);
182 void QScriptBreakpointsWidgetPrivate::_q_deleteBreakpoint()
184 Q_Q(QScriptBreakpointsWidget
);
185 QModelIndex index
= view
->currentIndex();
186 if (index
.isValid()) {
187 int id
= q
->breakpointsModel()->breakpointIdAt(index
.row());
188 q
->breakpointsModel()->deleteBreakpoint(id
);
192 void QScriptBreakpointsWidgetPrivate::_q_onCurrentChanged(const QModelIndex
&index
)
194 deleteBreakpointAction
->setEnabled(index
.isValid());
197 void QScriptBreakpointsWidgetPrivate::_q_onNewBreakpointRequest(const QString
&fileName
, int lineNumber
)
199 QScriptBreakpointData
data(fileName
, lineNumber
);
200 q_func()->breakpointsModel()->setBreakpoint(data
);
203 class QScriptBreakpointsItemDelegate
: public QStyledItemDelegate
207 QScriptBreakpointsItemDelegate(QObject
*parent
= 0)
208 : QStyledItemDelegate(parent
) {}
210 QWidget
*createEditor(QWidget
*parent
,
211 const QStyleOptionViewItem
&option
,
212 const QModelIndex
&index
) const
214 QWidget
*editor
= QStyledItemDelegate::createEditor(parent
, option
, index
);
215 if (index
.column() == 2) {
217 QLineEdit
*le
= qobject_cast
<QLineEdit
*>(editor
);
219 QObject::connect(le
, SIGNAL(textEdited(QString
)),
220 this, SLOT(validateInput(QString
)));
226 bool eventFilter(QObject
*editor
, QEvent
*event
)
228 if (QLineEdit
*le
= qobject_cast
<QLineEdit
*>(editor
)) {
229 if (event
->type() == QEvent::KeyPress
) {
230 int key
= static_cast<QKeyEvent
*>(event
)->key();
231 if ((key
== Qt::Key_Enter
) || (key
== Qt::Key_Return
)) {
232 if (QScriptEngine::checkSyntax(le
->text()).state() != QScriptSyntaxCheckResult::Valid
) {
233 // ignore when script contains syntax error
239 return QStyledItemDelegate::eventFilter(editor
, event
);
242 void setModelData(QWidget
*editor
, QAbstractItemModel
*model
,
243 const QModelIndex
&index
) const
245 if (index
.column() == 2) {
246 // check that the syntax is OK
247 QString condition
= qobject_cast
<QLineEdit
*>(editor
)->text();
248 if (QScriptEngine::checkSyntax(condition
).state() != QScriptSyntaxCheckResult::Valid
)
251 QStyledItemDelegate::setModelData(editor
, model
, index
);
255 void validateInput(const QString
&text
)
257 QWidget
*editor
= qobject_cast
<QWidget
*>(sender());
258 QPalette pal
= editor
->palette();
260 bool ok
= (QScriptEngine::checkSyntax(text
).state() == QScriptSyntaxCheckResult::Valid
);
264 QScriptSyntaxCheckResult result
= QScriptEngine::checkSyntax(
265 text
+ QLatin1Char('\n'));
266 if (result
.state() == QScriptSyntaxCheckResult::Intermediate
)
267 col
= QColor(255, 240, 192);
269 col
= QColor(255, 102, 102);
271 pal
.setColor(QPalette::Active
, QPalette::Base
, col
);
272 editor
->setPalette(pal
);
276 QScriptBreakpointsWidget::QScriptBreakpointsWidget(QWidget
*parent
)
277 : QScriptBreakpointsWidgetInterface(*new QScriptBreakpointsWidgetPrivate
, parent
, 0)
279 Q_D(QScriptBreakpointsWidget
);
280 d
->view
= new QTreeView();
281 // d->view->setEditTriggers(QAbstractItemView::NoEditTriggers);
282 d
->view
->setEditTriggers(QAbstractItemView::AllEditTriggers
);
283 // d->view->setAlternatingRowColors(true);
284 d
->view
->setRootIsDecorated(false);
285 d
->view
->setSelectionBehavior(QAbstractItemView::SelectRows
);
286 // d->view->header()->hide();
287 // d->view->header()->setDefaultAlignment(Qt::AlignLeft);
288 // d->view->header()->setResizeMode(QHeaderView::ResizeToContents);
289 d
->view
->setItemDelegate(new QScriptBreakpointsItemDelegate(this));
291 d
->newBreakpointWidget
= new QScriptNewBreakpointWidget();
292 d
->newBreakpointWidget
->hide();
293 QObject::connect(d
->newBreakpointWidget
, SIGNAL(newBreakpointRequest(QString
,int)),
294 this, SLOT(_q_onNewBreakpointRequest(QString
,int)));
296 QIcon newBreakpointIcon
;
297 newBreakpointIcon
.addPixmap(d
->pixmap(QString::fromLatin1("new.png")), QIcon::Normal
);
298 QAction
*newBreakpointAction
= new QAction(newBreakpointIcon
, QObject::tr("New"), this);
299 QObject::connect(newBreakpointAction
, SIGNAL(triggered()),
300 this, SLOT(_q_newBreakpoint()));
302 QIcon deleteBreakpointIcon
;
303 deleteBreakpointIcon
.addPixmap(d
->pixmap(QString::fromLatin1("delete.png")), QIcon::Normal
);
304 d
->deleteBreakpointAction
= new QAction(deleteBreakpointIcon
, QObject::tr("Delete"), this);
305 d
->deleteBreakpointAction
->setEnabled(false);
306 QObject::connect(d
->deleteBreakpointAction
, SIGNAL(triggered()),
307 this, SLOT(_q_deleteBreakpoint()));
309 QToolBar
*toolBar
= new QToolBar();
310 toolBar
->addAction(newBreakpointAction
);
311 toolBar
->addAction(d
->deleteBreakpointAction
);
313 QVBoxLayout
*vbox
= new QVBoxLayout(this);
315 vbox
->addWidget(toolBar
);
316 vbox
->addWidget(d
->newBreakpointWidget
);
317 vbox
->addWidget(d
->view
);
320 QScriptBreakpointsWidget::~QScriptBreakpointsWidget()
327 QScriptBreakpointsModel
*QScriptBreakpointsWidget::breakpointsModel() const
329 Q_D(const QScriptBreakpointsWidget
);
330 return qobject_cast
<QScriptBreakpointsModel
*>(d
->view
->model());
336 void QScriptBreakpointsWidget::setBreakpointsModel(QScriptBreakpointsModel
*model
)
338 Q_D(QScriptBreakpointsWidget
);
339 d
->view
->setModel(model
);
340 d
->view
->header()->resizeSection(0, 50);
341 QObject::connect(d
->view
->selectionModel(), SIGNAL(currentChanged(QModelIndex
,QModelIndex
)),
342 this, SLOT(_q_onCurrentChanged(QModelIndex
)));
348 QScriptDebuggerScriptsModel
*QScriptBreakpointsWidget::scriptsModel() const
350 Q_D(const QScriptBreakpointsWidget
);
351 return d
->scriptsModel
;
357 void QScriptBreakpointsWidget::setScriptsModel(QScriptDebuggerScriptsModel
*model
)
359 Q_D(QScriptBreakpointsWidget
);
360 d
->scriptsModel
= model
;
361 QCompleter
*completer
= new QCompleter(model
, this);
362 completer
->setCompletionRole(Qt::DisplayRole
);
363 d
->newBreakpointWidget
->setCompleter(completer
);
369 void QScriptBreakpointsWidget::keyPressEvent(QKeyEvent
*e
)
371 Q_D(QScriptBreakpointsWidget
);
372 if (e
->key() == Qt::Key_Delete
) {
373 QModelIndex index
= d
->view
->currentIndex();
374 if (!index
.isValid())
376 int id
= breakpointsModel()->breakpointIdAt(index
.row());
377 breakpointsModel()->deleteBreakpoint(id
);
383 #include "qscriptbreakpointswidget.moc"
385 #include "moc_qscriptbreakpointswidget_p.cpp"