diff --git a/src/private/multisplitter/Item.cpp b/src/private/multisplitter/Item.cpp index 2cc89df2..5d815f77 100644 --- a/src/private/multisplitter/Item.cpp +++ b/src/private/multisplitter/Item.cpp @@ -43,7 +43,15 @@ QPoint Item::mapToRoot(QPoint p) const if (isRoot()) return p; - return p + parentContainer()->pos(); + return p + parentContainer()->mapToRoot(parentContainer()->pos()); +} + +QPoint Item::mapFromParent(QPoint p) const +{ + if (isRoot()) + return p; + + return p - pos(); } void Item::resize(QSize newSize) @@ -363,7 +371,7 @@ bool Item::isHorizontal() const return m_orientation == Qt::Horizontal; } -int Item::visibleCount() const +int Item::visibleCount_recursive() const { return m_isVisible ? 1 : 0; } @@ -797,16 +805,68 @@ Item *ItemContainer::itemForFrame(const QWidget *w) const return nullptr; } -int ItemContainer::visibleCount() const +int ItemContainer::visibleCount_recursive() const { int count = 0; for (Item *item : m_children) { - count += item->visibleCount(); + count += item->visibleCount_recursive(); } return count; } +int ItemContainer::count_recursive() const +{ + int count = 0; + for (Item *item : m_children) { + if (auto c = item->asContainer()) { + count += c->count_recursive(); + } else { + count++; + } + } + + return count; +} + +Item *ItemContainer::itemAt(QPoint p) const +{ + for (Item *item : m_children) { + if (item->isVisible() && item->geometry().contains(p)) + return item; + } + + return nullptr; +} + +Item *ItemContainer::itemAt_recursive(QPoint p) const +{ + if (Item *item = itemAt(p)) { + if (auto c = item->asContainer()) { + return c->itemAt_recursive(c->mapFromParent(p)); + } else { + return item; + } + } + + return nullptr; +} + +Item::List ItemContainer::items_recursive() const +{ + Item::List items; + items.reserve(30); // sounds like a good upper number to minimize allocations + for (Item *item : m_children) { + if (auto c = item->asContainer()) { + items << c->items_recursive(); + } else { + items << item; + } + } + + return items; +} + void ItemContainer::insertItem(Item *item, int index, bool growItem) { m_children.insert(index, item); diff --git a/src/private/multisplitter/Item_p.h b/src/private/multisplitter/Item_p.h index cc6ce44e..4cf11ea0 100644 --- a/src/private/multisplitter/Item_p.h +++ b/src/private/multisplitter/Item_p.h @@ -178,7 +178,7 @@ public: bool isVertical() const; bool isHorizontal() const; - virtual int visibleCount() const; + virtual int visibleCount_recursive() const; virtual void insertItem(Item *item, Location, SizingOption = SizingOption::Calculate); @@ -234,8 +234,9 @@ public: ItemContainer *root() const; void deserialize() {} void serialize() {} - QRect mapToRoot(QRect local) const; - QPoint mapToRoot(QPoint local) const; + QRect mapToRoot(QRect) const; + QPoint mapToRoot(QPoint) const; + QPoint mapFromParent(QPoint) const; QWidget *frame() const { return m_widget; } // TODO: rename void setFrame(QWidget *w) { m_widget = w; } // TODO rename @@ -325,7 +326,11 @@ public: bool isResizing() const { return m_isResizing; } void clear(); Item* itemForFrame(const QWidget *w) const; // TODO: Rename - int visibleCount() const override; + int visibleCount_recursive() const override; + int count_recursive() const; + Item *itemAt(QPoint p) const; + Item *itemAt_recursive(QPoint p) const; + Item::List items_recursive() const; Q_SIGNALS: void itemsChanged(); diff --git a/src/private/multisplitter/MultiSplitterLayout.cpp b/src/private/multisplitter/MultiSplitterLayout.cpp index 4e8fba6e..391b9622 100644 --- a/src/private/multisplitter/MultiSplitterLayout.cpp +++ b/src/private/multisplitter/MultiSplitterLayout.cpp @@ -182,7 +182,7 @@ void MultiSplitterLayout::addWidget(QWidgetOrQuick *w, Location location, Frame void MultiSplitterLayout::addItems_internal(const ItemList &items, bool updateConstraints, bool emitSignal) { - m_items << items; + if (updateConstraints) updateSizeConstraints(); @@ -195,7 +195,7 @@ void MultiSplitterLayout::addItems_internal(const ItemList &items, bool updateCo } if (emitSignal) - Q_EMIT widgetCountChanged(m_items.size()); + Q_EMIT widgetCountChanged(m_rootItem->count_recursive()); } QString MultiSplitterLayout::affinityName() const @@ -230,7 +230,7 @@ void MultiSplitterLayout::removeItem(Item *item) item->parentContainer()->removeItem(item); Q_EMIT widgetRemoved(item); - Q_EMIT widgetCountChanged(m_items.size()); + Q_EMIT widgetCountChanged(m_rootItem->numVisibleChildren()); } bool MultiSplitterLayout::contains(const Item *item) const @@ -245,12 +245,7 @@ bool MultiSplitterLayout::contains(const Frame *frame) const Item *MultiSplitterLayout::itemAt(QPoint p) const { - for (Layouting::Item *item : m_items) { - if (!item->isPlaceholder() && item->geometry().contains(p)) - return item; - } - - return nullptr; + return m_rootItem->itemAt_recursive(p); } void MultiSplitterLayout::clear() @@ -268,7 +263,7 @@ void MultiSplitterLayout::clear() int MultiSplitterLayout::visibleCount() const { - return m_rootItem->visibleCount(); + return m_rootItem->visibleCount_recursive(); } int MultiSplitterLayout::placeholderCount() const @@ -328,9 +323,12 @@ Frame::List MultiSplitterLayout::framesFrom(QWidgetOrQuick *frameOrMultiSplitter Frame::List MultiSplitterLayout::frames() const { - Frame::List result; + const Item::List items = m_rootItem->items_recursive(); - for (Item *item : m_items) { + Frame::List result; + result.reserve(items.size()); + + for (Item *item : items) { if (auto f = static_cast(item->frame())) result.push_back(f); } @@ -416,7 +414,7 @@ void MultiSplitterLayout::setMinimumSize(QSize sz) const ItemList MultiSplitterLayout::items() const { - return m_items; + return m_rootItem->items_recursive(); } Item *MultiSplitterLayout::rootItem() const @@ -452,51 +450,13 @@ bool MultiSplitterLayout::eventFilter(QObject *o, QEvent *e) return false; } -bool MultiSplitterLayout::deserialize(const LayoutSaver::MultiSplitterLayout &msl) +bool MultiSplitterLayout::deserialize(const LayoutSaver::MultiSplitterLayout &) { - clear(); - - ItemList items; - items.reserve(msl.items.size()); - for (const auto &i : qAsConst(msl.items)) { - Q_UNUSED(i); - //Item *item = deserialize(); TODO - //items.push_back(item); - } - - m_items = items; // Set the items, so Anchor::deserialize() can set the side1 and side2 items - - m_items.clear(); // Now properly set the items, which installs needed event filters, etc. - addItems_internal(items, false, false); // Add the items only after we have the static anchors set - - setSize(msl.size); - setMinimumSize(msl.minSize); - - if (!m_items.isEmpty()) - Q_EMIT widgetCountChanged(m_items.size()); - - - // The main window that we're restoring can have more stuff now (other-toolbars etc), so by - // having restored its geometry it can mean our dockwidget layout is now different, so update - // its content size if needed - Q_EMIT minimumSizeChanged(m_minSize); - - if (size() != multiSplitter()->size()) { - setSize(multiSplitter()->size()); - } - return true; } LayoutSaver::MultiSplitterLayout MultiSplitterLayout::serialize() const { LayoutSaver::MultiSplitterLayout l; - - l.size = size(); - l.minSize = minimumSize(); - - //for (Item *item : m_items) TODO - //l.items.push_back(item->serialize()); - return l; } diff --git a/src/private/multisplitter/MultiSplitterLayout_p.h b/src/private/multisplitter/MultiSplitterLayout_p.h index f54b95e0..66394133 100644 --- a/src/private/multisplitter/MultiSplitterLayout_p.h +++ b/src/private/multisplitter/MultiSplitterLayout_p.h @@ -145,7 +145,7 @@ public: * This includes non-visible (placeholder) Items too. * @sa visibleCount */ - int count() const { return m_items.size(); } + int count() const { return m_rootItem->count_recursive(); } /** * @brief Returns the number of visible Items in this layout. @@ -161,11 +161,6 @@ public: */ int placeholderCount() const; - /** - * @brief Returns true if count is 0. - */ - bool isEmpty() const { return m_items.isEmpty(); } - /** * @brief Returns whether there's non placeholder items. */ @@ -421,7 +416,6 @@ private: MultiSplitter *const m_multiSplitter; Layouting::Anchor::List m_anchors; - ItemList m_items; bool m_inCtor = true; bool m_inDestructor = false; bool m_beingMergedIntoAnotherMultiSplitter = false; // TODO