src/scripttools/debugging/qscriptbreakpointswidget.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtSCriptTools module of the Qt Toolkit.
       
     8 **
       
     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
       
    14 ** this package.
       
    15 **
       
    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.
       
    23 **
       
    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.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qscriptbreakpointswidget_p.h"
       
    43 #include "qscriptbreakpointswidgetinterface_p_p.h"
       
    44 #include "qscriptbreakpointsmodel_p.h"
       
    45 #include "qscriptdebuggerscriptsmodel_p.h"
       
    46 
       
    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>
       
    60 
       
    61 QT_BEGIN_NAMESPACE
       
    62 
       
    63 class QScriptNewBreakpointWidget : public QWidget
       
    64 {
       
    65     Q_OBJECT
       
    66 public:
       
    67     QScriptNewBreakpointWidget(QWidget *parent = 0)
       
    68         : QWidget(parent) {
       
    69 	QString system = QLatin1String("win");
       
    70         QHBoxLayout *hboxLayout = new QHBoxLayout(this);
       
    71 #ifdef Q_OS_MAC
       
    72         system = QLatin1String("mac");
       
    73 #else
       
    74         hboxLayout->setSpacing(6);
       
    75         hboxLayout->setMargin(0);
       
    76 #endif
       
    77 
       
    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(tr("Close"));
       
    82         hboxLayout->addWidget(toolClose);
       
    83 
       
    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);
       
    90 
       
    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);
       
    96 
       
    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()));
       
   103     }
       
   104 
       
   105     void setCompleter(QCompleter *comp)
       
   106         { fileNameEdit->setCompleter(comp); }
       
   107 
       
   108 Q_SIGNALS:
       
   109     void newBreakpointRequest(const QString &fileName, int lineNumber);
       
   110 
       
   111 protected:
       
   112     void keyPressEvent(QKeyEvent *e)
       
   113     {
       
   114         if (e->key() == Qt::Key_Escape)
       
   115             hide();
       
   116         else
       
   117             QWidget::keyPressEvent(e);
       
   118     }
       
   119 
       
   120 private Q_SLOTS:
       
   121     void onOkClicked()
       
   122     {
       
   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);
       
   128     }
       
   129 
       
   130     void onTextChanged()
       
   131     {
       
   132         toolOk->setEnabled(fileNameEdit->hasAcceptableInput());
       
   133     }
       
   134 
       
   135 private:
       
   136     QLineEdit *fileNameEdit;
       
   137     QToolButton *toolClose;
       
   138     QToolButton *toolOk;
       
   139 };
       
   140 
       
   141 
       
   142 
       
   143 class QScriptBreakpointsWidgetPrivate
       
   144     : public QScriptBreakpointsWidgetInterfacePrivate
       
   145 {
       
   146     Q_DECLARE_PUBLIC(QScriptBreakpointsWidget)
       
   147 public:
       
   148     QScriptBreakpointsWidgetPrivate();
       
   149     ~QScriptBreakpointsWidgetPrivate();
       
   150 
       
   151     void _q_newBreakpoint();
       
   152     void _q_deleteBreakpoint();
       
   153     void _q_onCurrentChanged(const QModelIndex &index);
       
   154     void _q_onNewBreakpointRequest(const QString &fileName, int lineNumber);
       
   155 
       
   156     static QPixmap pixmap(const QString &path)
       
   157     {
       
   158         static QString prefix = QString::fromLatin1(":/qt/scripttools/debugging/images/");
       
   159         return QPixmap(prefix + path);
       
   160     }
       
   161 
       
   162     QTreeView *view;
       
   163     QScriptNewBreakpointWidget *newBreakpointWidget;
       
   164     QAction *deleteBreakpointAction;
       
   165     QScriptDebuggerScriptsModel *scriptsModel;
       
   166 };
       
   167 
       
   168 QScriptBreakpointsWidgetPrivate::QScriptBreakpointsWidgetPrivate()
       
   169 {
       
   170 }
       
   171 
       
   172 QScriptBreakpointsWidgetPrivate::~QScriptBreakpointsWidgetPrivate()
       
   173 {
       
   174 }
       
   175 
       
   176 void QScriptBreakpointsWidgetPrivate::_q_newBreakpoint()
       
   177 {
       
   178     newBreakpointWidget->show();
       
   179     newBreakpointWidget->setFocus(Qt::OtherFocusReason);
       
   180 }
       
   181 
       
   182 void QScriptBreakpointsWidgetPrivate::_q_deleteBreakpoint()
       
   183 {
       
   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);
       
   189     }
       
   190 }
       
   191 
       
   192 void QScriptBreakpointsWidgetPrivate::_q_onCurrentChanged(const QModelIndex &index)
       
   193 {
       
   194     deleteBreakpointAction->setEnabled(index.isValid());
       
   195 }
       
   196 
       
   197 void QScriptBreakpointsWidgetPrivate::_q_onNewBreakpointRequest(const QString &fileName, int lineNumber)
       
   198 {
       
   199     QScriptBreakpointData data(fileName, lineNumber);
       
   200     q_func()->breakpointsModel()->setBreakpoint(data);
       
   201 }
       
   202 
       
   203 class QScriptBreakpointsItemDelegate : public QStyledItemDelegate
       
   204 {
       
   205     Q_OBJECT
       
   206 public:
       
   207     QScriptBreakpointsItemDelegate(QObject *parent = 0)
       
   208         : QStyledItemDelegate(parent) {}
       
   209 
       
   210     QWidget *createEditor(QWidget *parent,
       
   211                           const QStyleOptionViewItem &option,
       
   212                           const QModelIndex &index) const
       
   213     {
       
   214         QWidget *editor = QStyledItemDelegate::createEditor(parent, option, index);
       
   215         if (index.column() == 2) {
       
   216             // condition
       
   217             QLineEdit *le = qobject_cast<QLineEdit*>(editor);
       
   218             if (le) {
       
   219                 QObject::connect(le, SIGNAL(textEdited(QString)),
       
   220                                  this, SLOT(validateInput(QString)));
       
   221             }
       
   222         }
       
   223         return editor;
       
   224     }
       
   225 
       
   226     bool eventFilter(QObject *editor, QEvent *event)
       
   227     {
       
   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
       
   234                         return true;
       
   235                     }
       
   236                 }
       
   237             }
       
   238         }
       
   239         return QStyledItemDelegate::eventFilter(editor, event);
       
   240     }
       
   241 
       
   242     void setModelData(QWidget *editor, QAbstractItemModel *model,
       
   243                       const QModelIndex &index) const
       
   244     {
       
   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)
       
   249                 return;
       
   250         }
       
   251         QStyledItemDelegate::setModelData(editor, model, index);
       
   252     }
       
   253 
       
   254 private Q_SLOTS:
       
   255     void validateInput(const QString &text)
       
   256     {
       
   257         QWidget *editor = qobject_cast<QWidget*>(sender());
       
   258         QPalette pal = editor->palette();
       
   259         QColor col;
       
   260         bool ok = (QScriptEngine::checkSyntax(text).state() == QScriptSyntaxCheckResult::Valid);
       
   261         if (ok) {
       
   262             col = Qt::white;
       
   263         } else {
       
   264             QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(
       
   265                 text + QLatin1Char('\n'));
       
   266             if (result.state() == QScriptSyntaxCheckResult::Intermediate)
       
   267                 col = QColor(255, 240, 192);
       
   268             else
       
   269                 col = QColor(255, 102, 102);
       
   270         }
       
   271         pal.setColor(QPalette::Active, QPalette::Base, col);
       
   272         editor->setPalette(pal);
       
   273     }
       
   274 };
       
   275 
       
   276 QScriptBreakpointsWidget::QScriptBreakpointsWidget(QWidget *parent)
       
   277     : QScriptBreakpointsWidgetInterface(*new QScriptBreakpointsWidgetPrivate, parent, 0)
       
   278 {
       
   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));
       
   290 
       
   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)));
       
   295 
       
   296     QIcon newBreakpointIcon;
       
   297     newBreakpointIcon.addPixmap(d->pixmap(QString::fromLatin1("new.png")), QIcon::Normal);
       
   298     QAction *newBreakpointAction = new QAction(newBreakpointIcon, tr("New"), this);
       
   299     QObject::connect(newBreakpointAction, SIGNAL(triggered()),
       
   300                      this, SLOT(_q_newBreakpoint()));
       
   301 
       
   302     QIcon deleteBreakpointIcon;
       
   303     deleteBreakpointIcon.addPixmap(d->pixmap(QString::fromLatin1("delete.png")), QIcon::Normal);
       
   304     d->deleteBreakpointAction = new QAction(deleteBreakpointIcon, tr("Delete"), this);
       
   305     d->deleteBreakpointAction->setEnabled(false);
       
   306     QObject::connect(d->deleteBreakpointAction, SIGNAL(triggered()),
       
   307                      this, SLOT(_q_deleteBreakpoint()));
       
   308 
       
   309 #ifndef QT_NO_TOOLBAR
       
   310     QToolBar *toolBar = new QToolBar();
       
   311     toolBar->addAction(newBreakpointAction);
       
   312     toolBar->addAction(d->deleteBreakpointAction);
       
   313 #endif
       
   314 
       
   315     QVBoxLayout *vbox = new QVBoxLayout(this);
       
   316     vbox->setMargin(0);
       
   317 #ifndef QT_NO_TOOLBAR
       
   318     vbox->addWidget(toolBar);
       
   319 #endif
       
   320     vbox->addWidget(d->newBreakpointWidget);
       
   321     vbox->addWidget(d->view);
       
   322 }
       
   323 
       
   324 QScriptBreakpointsWidget::~QScriptBreakpointsWidget()
       
   325 {
       
   326 }
       
   327 
       
   328 /*!
       
   329   \reimp
       
   330 */
       
   331 QScriptBreakpointsModel *QScriptBreakpointsWidget::breakpointsModel() const
       
   332 {
       
   333     Q_D(const QScriptBreakpointsWidget);
       
   334     return qobject_cast<QScriptBreakpointsModel*>(d->view->model());
       
   335 }
       
   336 
       
   337 /*!
       
   338   \reimp
       
   339 */
       
   340 void QScriptBreakpointsWidget::setBreakpointsModel(QScriptBreakpointsModel *model)
       
   341 {
       
   342     Q_D(QScriptBreakpointsWidget);
       
   343     d->view->setModel(model);
       
   344     d->view->header()->resizeSection(0, 50);
       
   345     QObject::connect(d->view->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
       
   346                      this, SLOT(_q_onCurrentChanged(QModelIndex)));
       
   347 }
       
   348 
       
   349 /*!
       
   350   \reimp
       
   351 */
       
   352 QScriptDebuggerScriptsModel *QScriptBreakpointsWidget::scriptsModel() const
       
   353 {
       
   354     Q_D(const QScriptBreakpointsWidget);
       
   355     return d->scriptsModel;
       
   356 }
       
   357 
       
   358 /*!
       
   359   \reimp
       
   360 */
       
   361 void QScriptBreakpointsWidget::setScriptsModel(QScriptDebuggerScriptsModel *model)
       
   362 {
       
   363     Q_D(QScriptBreakpointsWidget);
       
   364     d->scriptsModel = model;
       
   365     QCompleter *completer = new QCompleter(model, this);
       
   366     completer->setCompletionRole(Qt::DisplayRole);
       
   367     d->newBreakpointWidget->setCompleter(completer);
       
   368 }
       
   369 
       
   370 /*!
       
   371   \reimp
       
   372 */
       
   373 void QScriptBreakpointsWidget::keyPressEvent(QKeyEvent *e)
       
   374 {
       
   375     Q_D(QScriptBreakpointsWidget);
       
   376     if (e->key() == Qt::Key_Delete) {
       
   377         QModelIndex index = d->view->currentIndex();
       
   378         if (!index.isValid())
       
   379             return;
       
   380         int id = breakpointsModel()->breakpointIdAt(index.row());
       
   381         breakpointsModel()->deleteBreakpoint(id);
       
   382     }
       
   383 }
       
   384 
       
   385 QT_END_NAMESPACE
       
   386 
       
   387 #include "qscriptbreakpointswidget.moc"
       
   388 
       
   389 #include "moc_qscriptbreakpointswidget_p.cpp"