QmlProfiler: relay context menu from trace view to parent widget

As QQuickView is a window with its own event handling, disconnected
from the main window, we need to relay relevant events manually.

Task-number: QTCREATORBUG-11535

Change-Id: If316225ecc01ddc4255c209d7df70a9cee812596
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
Ulf Hermann
2014-02-21 18:34:05 +01:00
parent 676e4f582e
commit 6d8b70ed57
2 changed files with 56 additions and 5 deletions

View File

@@ -51,6 +51,7 @@
#include <QSlider> #include <QSlider>
#include <QMenu> #include <QMenu>
#include <QQuickItem> #include <QQuickItem>
#include <QApplication>
#include <math.h> #include <math.h>
@@ -114,20 +115,20 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerT
groupLayout->setContentsMargins(0, 0, 0, 0); groupLayout->setContentsMargins(0, 0, 0, 0);
groupLayout->setSpacing(0); groupLayout->setSpacing(0);
d->m_mainView = new QQuickView(); d->m_mainView = new QmlProfilerQuickView(this);
d->m_mainView->setResizeMode(QQuickView::SizeRootObjectToView); d->m_mainView->setResizeMode(QQuickView::SizeRootObjectToView);
QWidget *mainViewContainer = QWidget::createWindowContainer(d->m_mainView); QWidget *mainViewContainer = QWidget::createWindowContainer(d->m_mainView);
mainViewContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mainViewContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QHBoxLayout *toolsLayout = new QHBoxLayout; QHBoxLayout *toolsLayout = new QHBoxLayout;
d->m_timebar = new QQuickView(); d->m_timebar = new QmlProfilerQuickView(this);
d->m_timebar->setResizeMode(QQuickView::SizeRootObjectToView); d->m_timebar->setResizeMode(QQuickView::SizeRootObjectToView);
QWidget *timeBarContainer = QWidget::createWindowContainer(d->m_timebar); QWidget *timeBarContainer = QWidget::createWindowContainer(d->m_timebar);
timeBarContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); timeBarContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
timeBarContainer->setFixedHeight(24); timeBarContainer->setFixedHeight(24);
d->m_overview = new QQuickView(); d->m_overview = new QmlProfilerQuickView(this);
d->m_overview->setResizeMode(QQuickView::SizeRootObjectToView); d->m_overview->setResizeMode(QQuickView::SizeRootObjectToView);
QWidget *overviewContainer = QWidget::createWindowContainer(d->m_overview); QWidget *overviewContainer = QWidget::createWindowContainer(d->m_overview);
overviewContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); overviewContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@@ -407,6 +408,11 @@ void QmlProfilerTraceView::resizeEvent(QResizeEvent *event)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Context menu // Context menu
void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev) void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev)
{
showContextMenu(ev->globalPos());
}
void QmlProfilerTraceView::showContextMenu(QPoint position)
{ {
QMenu menu; QMenu menu;
QAction *viewAllAction = 0; QAction *viewAllAction = 0;
@@ -431,7 +437,7 @@ void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev)
viewAllAction = menu.addAction(tr("Reset Zoom")); viewAllAction = menu.addAction(tr("Reset Zoom"));
} }
QAction *selectedAction = menu.exec(ev->globalPos()); QAction *selectedAction = menu.exec(position);
if (selectedAction) { if (selectedAction) {
if (selectedAction == viewAllAction) { if (selectedAction == viewAllAction) {
@@ -509,5 +515,41 @@ void QmlProfilerTraceView::serverRecordingChanged()
setRecording(d->m_profilerState->serverRecording()); setRecording(d->m_profilerState->serverRecording());
} }
bool QmlProfilerQuickView::event(QEvent *ev)
{
// We assume context menus can only be triggered by mouse press, mouse release, or
// pre-synthesized events from the window system.
bool relayed = false;
switch (ev->type()) {
case QEvent::ContextMenu:
// In the case of mouse clicks the active popup gets automatically closed before they show
// up here. That's not necessarily the case with keyboard triggered context menu events, so
// we just ignore them if there is a popup already. Also, the event's pos() and globalPos()
// don't make much sense in this case, so we just put the menu in the upper left corner.
if (QApplication::activePopupWidget() == 0) {
ev->accept();
parent->showContextMenu(parent->mapToGlobal(QPoint(0,0)));
relayed = true;
}
break;
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease: {
QMouseEvent *orig = static_cast<QMouseEvent *>(ev);
QCoreApplication::instance()->postEvent(parent->window()->windowHandle(),
new QMouseEvent(orig->type(), parent->window()->mapFromGlobal(orig->globalPos()),
orig->button(), orig->buttons(), orig->modifiers()));
relayed = true;
break;
}
default:
break;
}
// QQuickView will eat mouse events even if they're not accepted by any QML construct. So we
// ignore the return value of event() above.
return QQuickView::event(ev) || relayed;
}
} // namespace Internal } // namespace Internal
} // namespace QmlProfiler } // namespace QmlProfiler

View File

@@ -75,6 +75,7 @@ public:
bool hasValidSelection() const; bool hasValidSelection() const;
qint64 selectionStart() const; qint64 selectionStart() const;
qint64 selectionEnd() const; qint64 selectionEnd() const;
void showContextMenu(QPoint position);
public slots: public slots:
void clearDisplay(); void clearDisplay();
@@ -95,6 +96,7 @@ private slots:
protected: protected:
virtual void resizeEvent(QResizeEvent *event); virtual void resizeEvent(QResizeEvent *event);
virtual void contextMenuEvent(QContextMenuEvent *event);
private slots: private slots:
void profilerStateChanged(); void profilerStateChanged();
@@ -117,7 +119,6 @@ signals:
void resized(); void resized();
private: private:
void contextMenuEvent(QContextMenuEvent *);
QWidget *createToolbar(); QWidget *createToolbar();
void setRecording(bool recording); void setRecording(bool recording);
@@ -128,6 +129,14 @@ private:
QmlProfilerTraceViewPrivate *d; QmlProfilerTraceViewPrivate *d;
}; };
class QmlProfilerQuickView : public QQuickView {
public:
QmlProfilerQuickView(QmlProfilerTraceView *parent) : parent(parent) {}
protected:
QmlProfilerTraceView *parent;
bool event(QEvent *ev);
};
} // namespace Internal } // namespace Internal
} // namespace QmlProfiler } // namespace QmlProfiler