[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdevplatform] shell: Fix up assistant popup and port to QtQuick 2
From: Olivier JG <olivier.jg () gmail ! com>
Date: 2015-10-09 8:45:51
Message-ID: E1ZkTJH-0006Za-Ur () scm ! kde ! org
[Download RAW message or body]
Git commit 0f641b67c3fb7ca0e197e7c646be58ddfc3c4877 by Olivier JG.
Committed on 09/10/2015 at 08:47.
Pushed by olivierjg into branch 'master'.
Fix up assistant popup and port to QtQuick 2
M +1 -1 shell/AssistantButton.qml
M +2 -1 shell/CMakeLists.txt
M +37 -71 shell/assistantpopup.cpp
M +9 -12 shell/assistantpopup.h
M +32 -28 shell/assistantpopup.qml
http://commits.kde.org/kdevplatform/0f641b67c3fb7ca0e197e7c646be58ddfc3c4877
diff --git a/shell/AssistantButton.qml b/shell/AssistantButton.qml
index 586c1aa..9500a9e 100644
--- a/shell/AssistantButton.qml
+++ b/shell/AssistantButton.qml
@@ -17,7 +17,7 @@
Boston, MA 02110-1301, USA.
*/
-import QtQuick 1.0
+import QtQuick 2.2
// Component which provides a single button for the assistant widget.
diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt
index d9257da..2ac7691 100644
--- a/shell/CMakeLists.txt
+++ b/shell/CMakeLists.txt
@@ -116,7 +116,8 @@ LINK_PUBLIC
KDev::Debugger
KDev::Interfaces
LINK_PRIVATE
- Qt5::Declarative
+ Qt5::Quick
+ Qt5::QuickWidgets
KF5::GuiAddons
KF5::IconThemes
diff --git a/shell/assistantpopup.cpp b/shell/assistantpopup.cpp
index 4349e95..8aea1e6 100644
--- a/shell/assistantpopup.cpp
+++ b/shell/assistantpopup.cpp
@@ -24,12 +24,14 @@
#include "util/kdevstringhandler.h"
#include <QAction>
-#include <QDeclarativeContext>
+#include <QApplication>
#include <QKeyEvent>
#include <QDebug>
#include <QEvent>
#include <QTimer>
#include <QStandardPaths>
+#include <QQmlContext>
+#include <QQuickItem>
#include <KLocalizedString>
#include <KParts/MainWindow>
@@ -61,7 +63,7 @@ const int ASSISTANT_MOD_KEY =
#ifdef Q_OS_MAC
Qt::Key_Control;
#else
-Qt::Key_Meta;
+Qt::Key_Alt;
#endif
QWidget* findByClassname(const KTextEditor::View* view, const QString& klass)
@@ -101,7 +103,6 @@ QRect textWidgetGeometry(const KTextEditor::View *view)
AssistantPopupConfig::AssistantPopupConfig(QObject *parent)
: QObject(parent)
, m_active(false)
- , m_useVerticalLayout(false)
{
}
@@ -140,14 +141,12 @@ void AssistantPopupConfig::setActive(bool active)
emit activeChanged(m_active);
}
-void AssistantPopupConfig::setUseVerticalLayout(bool vertical)
+void AssistantPopupConfig::setViewSize(const QSize& size)
{
- if (m_useVerticalLayout == vertical) {
- return;
+ if (size != m_viewSize) {
+ m_viewSize = size;
+ emit viewSizeChanged(size);
}
-
- m_useVerticalLayout = vertical;
- emit useVerticalLayoutChanged(m_useVerticalLayout);
}
void AssistantPopupConfig::setTitle(const QString& title)
@@ -173,18 +172,10 @@ void AssistantPopupConfig::setModel(const QList<QObject*>& \
model)
AssistantPopup::AssistantPopup()
// main window as parent to use maximal space available in worst case
- : QDeclarativeView(ICore::self()->uiController()->activeMainWindow())
+ : QQuickWidget(ICore::self()->uiController()->activeMainWindow())
, m_config(new AssistantPopupConfig(this))
- , m_shownAtBottom(false)
- , m_reopening(false)
- , m_updateTimer(new QTimer(this))
+ , m_firstLayoutCompleted(false)
{
- QPalette p = palette();
- p.setColor(QPalette::Window, Qt::transparent);
- setPalette(p);
- setBackgroundRole(QPalette::Window);
- setBackgroundBrush(QBrush(QColor(0, 0, 0, 0)));
- setResizeMode(QDeclarativeView::SizeViewToRootObject);
setAttribute(Qt::WA_ShowWithoutActivating);
rootContext()->setContextProperty("config", m_config);
@@ -192,25 +183,24 @@ AssistantPopup::AssistantPopup()
setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, \
"kdevelop/assistantpopup.qml"))); if (!rootObject()) {
qWarning() << "Failed to load assistant markup! The assistant will not \
work."; + } else {
+ connect(rootObject(), &QQuickItem::widthChanged, this, \
&AssistantPopup::updateLayout); + connect(rootObject(), \
&QQuickItem::heightChanged, this, &AssistantPopup::updateLayout); }
- m_updateTimer->setInterval(UPDATE_STATE_INTERVAL);
- m_updateTimer->setSingleShot(true);
- connect(m_updateTimer, &QTimer::timeout, this, &AssistantPopup::updateState);
-
for (int i = Qt::Key_0; i <= Qt::Key_9; ++i) {
m_shortcuts.append(new QShortcut(ASSISTANT_MODIFIER + i, this));
}
setActive(false);
+
+ connect(qApp, &QApplication::applicationStateChanged, this, [this]{ \
setActive(false); }); }
void AssistantPopup::reset(KTextEditor::View* view, const IAssistant::Ptr& \
assistant) {
setView(view);
setAssistant(assistant);
- updateLayoutType();
-
- m_updateTimer->start();
+ updateState();
}
void AssistantPopup::setView(KTextEditor::View* view)
@@ -227,6 +217,7 @@ void AssistantPopup::setView(KTextEditor::View* view)
this, &AssistantPopup::updatePosition);
}
m_view = view;
+ m_config->setViewSize(m_view ? m_view->size() : QSize());
if (m_view) {
m_view->installEventFilter(this);
connect(m_view.data(), &KTextEditor::View::verticalScrollPositionChanged,
@@ -241,13 +232,13 @@ void AssistantPopup::setAssistant(const IAssistant::Ptr& \
assistant) }
if (m_assistant) {
- disconnect(m_assistant.data(), &IAssistant::actionsChanged, m_updateTimer, \
static_cast<void(QTimer::*)()>(&QTimer::start));
disconnect(m_assistant.data(), &IAssistant::hide, this, \
&AssistantPopup::hideAssistant); }
m_assistant = assistant;
if (m_assistant) {
- connect(m_assistant.data(), &IAssistant::actionsChanged, m_updateTimer, \
static_cast<void(QTimer::*)()>(&QTimer::start));
connect(m_assistant.data(), &IAssistant::hide, this, \
&AssistantPopup::hideAssistant); + } else {
+ hide();
}
}
@@ -259,18 +250,6 @@ void AssistantPopup::setActive(bool active)
}
}
-bool AssistantPopup::viewportEvent(QEvent *event)
-{
- // For some reason, QGraphicsView posts a WindowActivate event
- // when it is shown, even if disabled through setting the WA_ShowWithoutActivate
- // attribute. This causes all focus-driven popups (QuickOpen, tooltips, ...)
- // to hide when the assistant opens. Thus, prevent it from processing the Show \
event here.
- if ( event->type() == QEvent::Show ) {
- return true;
- }
- return QGraphicsView::viewportEvent(event);
-}
-
bool AssistantPopup::eventFilter(QObject* object, QEvent* event)
{
Q_UNUSED(object);
@@ -279,8 +258,7 @@ bool AssistantPopup::eventFilter(QObject* object, QEvent* event)
return false;
if (event->type() == QEvent::Resize) {
- updateLayoutType();
- updatePosition(m_view.data(), KTextEditor::Cursor::invalid());
+ updateLayout();
} else if (event->type() == QEvent::Hide) {
executeHideAction();
} else if (event->type() == QEvent::KeyPress) {
@@ -304,7 +282,7 @@ void AssistantPopup::updatePosition(KTextEditor::View* view, \
const KTextEditor:: {
static const int MARGIN = 12;
- if (newPos.isValid() && newPos.line() == 0 && !m_shownAtBottom) {
+ if (newPos.isValid() && newPos.line() == 0) {
// the position is not going to change; don't waste time
return;
}
@@ -328,15 +306,8 @@ void AssistantPopup::updatePosition(KTextEditor::View* view, \
const KTextEditor:: return;
}
- if ( m_reopening ) {
- // When the assistant is already visible, close to no flickering will occur \
anyways,
- // so we can avoid the full repaint of the window.
- move(targetLocation);
- }
- else {
- Sublime::HoldUpdates \
hold(ICore::self()->uiController()->activeMainWindow());
- move(targetLocation);
- }
+ Sublime::HoldUpdates hold(ICore::self()->uiController()->activeMainWindow());
+ move(targetLocation);
}
IAssistant::Ptr AssistantPopup::assistant() const
@@ -356,23 +327,23 @@ void AssistantPopup::hideAssistant()
reset(nullptr, {}); // indirectly calls hide()
}
-void AssistantPopup::updateLayoutType()
+void AssistantPopup::updateLayout()
{
- if ( !m_assistant || !m_view ) {
+ if ( !m_view ) {
return;
}
- // Make a rough estimate of the width the assistant will need
- // and decide on whether to use vertical layout or not.
- const auto& metrics = fontMetrics();
- auto textWidth = 0;
-
- textWidth += metrics.boundingRect(KDevelop::htmlToPlainText(assistant()->title())).width();
- for ( const auto& action: assistant()->actions() ) {
- textWidth += \
metrics.boundingRect(KDevelop::htmlToPlainText(action->description())).width();
- textWidth += 10;
+
+ m_config->setViewSize(m_view->size());
+ // https://bugreports.qt.io/browse/QTBUG-44876
+ resize(rootObject()->width(), rootObject()->height());
+ updatePosition(m_view, KTextEditor::Cursor::invalid());
+
+ // HACK: QQuickWidget is corrupted due to above resize on the first show
+ if (!m_firstLayoutCompleted) {
+ hide();
+ show();
+ m_firstLayoutCompleted = true;
}
- m_config->setUseVerticalLayout(textWidth > \
textWidgetGeometry(m_view).width()*0.75);
- updateState();
}
void AssistantPopup::updateState()
@@ -395,8 +366,8 @@ void AssistantPopup::updateState()
//For some reason, QAction's setShortcut does nothing, so we manage with \
QShortcut if (++curShortcut != m_shortcuts.constEnd()) {
connect(*curShortcut, &QShortcut::activated, asQAction, \
&QAction::trigger);
- connect(*curShortcut, &QShortcut::activated, hideAction, \
&QAction::trigger); }
+ connect(action.data(), SIGNAL(executed(IAssistantAction*)), hideAction, \
SLOT(trigger())); }
items << hideAction;
@@ -406,11 +377,6 @@ void AssistantPopup::updateState()
m_config->setTitle(m_assistant->title());
setActive(false);
- // both changed title or actions may change the appearance of the popup
- // force recomputing the size hint
- resize(sizeHint());
- updatePosition(m_view, KTextEditor::Cursor::invalid());
-
show();
}
diff --git a/shell/assistantpopup.h b/shell/assistantpopup.h
index bdf3317..44cd167 100644
--- a/shell/assistantpopup.h
+++ b/shell/assistantpopup.h
@@ -22,7 +22,7 @@
#ifndef KDEVPLATFORM_ASSISTANTPOPUP_H
#define KDEVPLATFORM_ASSISTANTPOPUP_H
-#include <QDeclarativeView>
+#include <QQuickWidget>
#include <QShortcut>
#include <interfaces/iassistant.h>
@@ -42,7 +42,7 @@ class AssistantPopupConfig : public QObject
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
Q_PROPERTY(QList<QObject*> model READ model NOTIFY modelChanged)
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
- Q_PROPERTY(bool useVerticalLayout READ useVerticalLayout WRITE \
setUseVerticalLayout NOTIFY useVerticalLayoutChanged) + Q_PROPERTY(QSize viewSize \
READ viewSize WRITE setViewSize NOTIFY viewSizeChanged)
public:
explicit AssistantPopupConfig(QObject *parent = 0);
@@ -51,8 +51,8 @@ public:
QColor background() const { return m_background; }
QColor highlight() const { return m_highlight; }
- bool useVerticalLayout() const { return m_useVerticalLayout; }
- void setUseVerticalLayout(bool vertical);
+ QSize viewSize() const { return m_viewSize; };
+ void setViewSize(const QSize &size);
QString title() const { return m_title; }
void setTitle(const QString& title);
@@ -70,7 +70,7 @@ signals:
void titleChanged(const QString& title);
void modelChanged(const QList<QObject*>& model);
void activeChanged(bool active);
- void useVerticalLayoutChanged(bool useVerticalLayout);
+ void viewSizeChanged(const QSize& size);
private:
QColor m_foreground;
@@ -80,12 +80,12 @@ private:
QString m_title;
QList<QObject*> m_model;
bool m_active;
- bool m_useVerticalLayout;
+ QSize m_viewSize;
};
Q_DECLARE_METATYPE(AssistantPopupConfig*)
-class AssistantPopup : public QDeclarativeView
+class AssistantPopup : public QQuickWidget
{
Q_OBJECT
@@ -111,14 +111,13 @@ public:
private slots:
void updatePosition(KTextEditor::View* view, const KTextEditor::Cursor& newPos);
void updateState();
- void updateLayoutType();
+ void updateLayout();
void executeHideAction();
void hideAssistant();
protected:
virtual bool eventFilter(QObject* object, QEvent* event) override;
- virtual bool viewportEvent(QEvent *event) override;
private:
void setView(KTextEditor::View* view);
@@ -128,10 +127,8 @@ private:
KDevelop::IAssistant::Ptr m_assistant;
QPointer<KTextEditor::View> m_view;
AssistantPopupConfig* m_config;
- bool m_shownAtBottom;
- bool m_reopening;
- QTimer* m_updateTimer;
QList<QShortcut*> m_shortcuts;
+ bool m_firstLayoutCompleted;
};
#endif // KDEVPLATFORM_ASSISTANTPOPUP_H
diff --git a/shell/assistantpopup.qml b/shell/assistantpopup.qml
index cc40a13..63c00e8 100644
--- a/shell/assistantpopup.qml
+++ b/shell/assistantpopup.qml
@@ -19,13 +19,26 @@
// This file provides the whole assistant, including title and buttons.
-import QtQuick 1.0
+import QtQuick 2.2
Rectangle {
id: root
- width: mainFlow.width + 16
- height: mainFlow.height + 10
+ readonly property int vSpacing: 4
+ readonly property int hSpacing: 4
+ readonly property real itemsWidth: {
+ var totalWidth = title.width;
+ for (var i = 0; i < items.count; ++i) {
+ totalWidth += items.itemAt(i).width;
+ }
+ return totalWidth + (items.count + 2) * hSpacing;
+ }
+ readonly property bool useVerticalLayout: config.viewSize.width * 0.90 < \
itemsWidth +
+ // QQuickWidget crashes if either of these is zero
+ // Use ceil to ensure the widget always fits the non-integral content size
+ width: Math.ceil(Math.max(hSpacing, mainFlow.width + hSpacing * 2))
+ height: Math.ceil(Math.max(vSpacing, mainFlow.height + vSpacing * 2))
border.width: 1
border.color: Qt.lighter(config.foreground)
@@ -41,44 +54,35 @@ Rectangle {
centerIn: parent
}
- flow: config.useVerticalLayout ? Flow.TopToBottom : Flow.LeftToRight
- spacing: config.useVerticalLayout ? 4 : 8
+ flow: root.useVerticalLayout ? Flow.TopToBottom : Flow.LeftToRight
+ spacing: root.useVerticalLayout ? root.vSpacing : root.hSpacing
Text {
id: title
- anchors.verticalCenter: parent.flow == Flow.LeftToRight ? \
parent.verticalCenter : undefined
- anchors.verticalCenterOffset: 1
-
color: config.foreground
font.bold: true
text: config.title
}
- // Layout for the buttons
- Flow {
- id: buttonsFlow
-
- spacing: 8
- Repeater {
- id: items
- objectName: "items"
+ Repeater {
+ id: items
+ objectName: "items"
- y: 5
- model: config.model
+ y: 5
+ model: config.model
- AssistantButton {
- text: modelData.text
- highlighted: config.active
- // what is displayed in the hotkey field of the button
- button: index == items.model.length - 1 ? 0 : index + 1
- foreground: config.foreground
- background: config.background
- highlight: config.highlight
+ AssistantButton {
+ text: modelData.text
+ highlighted: config.active
+ // what is displayed in the hotkey field of the button
+ button: index == items.model.length - 1 ? 0 : index + 1
+ foreground: config.foreground
+ background: config.background
+ highlight: config.highlight
- onTriggered: { modelData.trigger() }
- }
+ onTriggered: { modelData.trigger() }
}
}
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic