qtquick: Don't assume in the C++ that the tab bar has a list view

Getting the tab index by QPoint is now done in QML, so it can
be overridden by the user.
This commit is contained in:
Sergio Martins
2022-07-18 10:05:16 +01:00
parent dd1363de6c
commit 82ad2242dd
4 changed files with 54 additions and 58 deletions

View File

@@ -40,33 +40,6 @@ void TabBar_qtquick::init()
});
}
QHash<int, QQuickItem *> TabBar_qtquick::qmlTabs() const
{
if (!m_tabBarQmlItem) {
qWarning() << Q_FUNC_INFO << "No visual tab bar item yet" << this;
return {};
}
/// Returns the list of QtQuickControls tabs in our tab bar
QHash<int, QQuickItem *> tabs;
if (QQuickItem *internalListView = listView()) {
const auto childItems = internalListView->childItems();
if (!childItems.isEmpty()) {
for (QQuickItem *item : childItems.first()->childItems()) {
bool ok = false;
const int index = item->property("tabIndex").toInt(&ok);
if (ok)
tabs.insert(index, item);
}
}
} else {
qWarning() << Q_FUNC_INFO << "Couldn't find the internal ListView";
}
return tabs;
}
int TabBar_qtquick::tabAt(QPoint localPt) const
{
// QtQuick's TabBar doesn't provide any API for this.
@@ -79,14 +52,13 @@ int TabBar_qtquick::tabAt(QPoint localPt) const
const QPointF globalPos = m_tabBarQmlItem->mapToGlobal(localPt);
const QHash<int, QQuickItem *> tabs = qmlTabs();
for (auto it = tabs.keyValueBegin(); it != tabs.keyValueEnd(); ++it) {
QQuickItem *tab = it->second;
if (tab->contains(tab->mapFromGlobal(globalPos))) {
const int index = it->first;
return index;
}
}
QVariant index;
const bool res = QMetaObject::invokeMethod(m_tabBarQmlItem, "getTabIndexAtPosition",
Q_RETURN_ARG(QVariant, index),
Q_ARG(QVariant, globalPos));
if (res)
return index.toInt();
return -1;
}
@@ -154,27 +126,6 @@ QQuickItem *TabBar_qtquick::tabAt(int index) const
return nullptr;
}
QQuickItem *TabBar_qtquick::listView() const
{
// Returns the internal ListView of the TabBar
if (!m_tabBarQmlItem) {
qWarning() << Q_FUNC_INFO << "No visual tab bar item yet";
return nullptr;
}
const QList<QQuickItem *> children = m_tabBarQmlItem->childItems();
if (children.size() != 1) {
return nullptr;
}
for (QQuickItem *child : children.constFirst()->childItems()) {
if (qstrcmp(child->metaObject()->className(), "QQuickListView") == 0)
return child;
}
return nullptr;
}
void TabBar_qtquick::moveTabTo(int from, int to)
{
Q_UNUSED(from);

View File

@@ -72,9 +72,7 @@ protected:
void init() override;
private:
QHash<int, QQuickItem *> qmlTabs() const;
QQuickItem *tabAt(int index) const;
QQuickItem *listView() const;
QPointer<QQuickItem> m_tabBarQmlItem;
KDBindings::ScopedConnection m_tabBarAutoHideChanged;
};

View File

@@ -16,23 +16,62 @@ import QtQuick.Controls 2.9
TabBarBase {
id: root
// Helper, only applies if you're using the TabBar from QQControls.
// Returns the internal ListView
function getInternalListView() {
for(var i = 0; i < tabBar.children.length; ++i) {
if (tabBar.children[i].toString().startsWith("QQuickListView"))
return tabBar.children[i];
}
console.warn("Couldn't find the internal ListView");
return null;
}
function getTabAtIndex(index) {
var listView = getInternalListView();
var content = listView.children[0];
var curr = 0;
for (var i = 0; i < content.children.length; ++i) {
var candidate = content.children[i];
if (typeof candidate.tabIndex == "undefined") {
// All tabs need to have "tabIndex" property.
continue;
}
if (curr == index)
return candidate;
curr++;
}
if (index < listView.children.length)
return listView.children[0].children[index];
return null;
}
function getTabIndexAtPosition(globalPoint) {
var listView = getInternalListView();
var content = listView.children[0];
for (var i = 0; i < content.children.length; ++i) {
var candidate = content.children[i];
if (typeof candidate.tabIndex == "undefined") {
// All tabs need to have "tabIndex" property.
continue;
}
var localPt = candidate.mapFromGlobal(globalPoint.x, globalPoint.y);
if (candidate.contains(localPt)) {
return i;
}
}
return -1;
}
implicitHeight: tabBar.implicitHeight
onCurrentTabIndexChanged: {

View File

@@ -67,4 +67,12 @@ Item {
function getTabAtIndex(index) {
console.warn("Override this function in the actual derived tab bar!");
}
/// Returns the index of the tab that's at localPoint
/// Returns -1 if no tab there.
/// This is called by C++ and needs to be implemented in the derived class.
/// See TabBar.qml for an example.
function getTabIndexAtPosition(localPoint) {
console.warn("Override this function in the actual derived tab bar!");
}
}