Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature to duplicate tabs #5277

Merged
merged 17 commits into from May 25, 2024
Merged

Conversation

KleberPF
Copy link
Contributor

@KleberPF KleberPF commented Mar 30, 2024

Implements tab duplication by creating a descriptor of the tab and applying that descriptor to a new SplitContainer.
The rightmost tab here has a filter to only show messages sent by me.

image

image

Partially implements #5221

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved
src/widgets/splits/SplitContainer.cpp Outdated Show resolved Hide resolved
@KleberPF KleberPF marked this pull request as ready for review March 30, 2024 17:34
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/splits/SplitContainer.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/splits/SplitContainer.cpp Outdated Show resolved Hide resolved
@pajlada pajlada added this to the Post-2.5.0 milestone Mar 30, 2024
@pajlada pajlada self-assigned this May 18, 2024
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved
src/widgets/splits/SplitContainer.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved
src/widgets/splits/SplitContainer.cpp Show resolved Hide resolved
@pajlada
Copy link
Member

pajlada commented May 18, 2024

This currently crashes if you try to duplicate a previously duplicated tab - something with attempting to access the clicked item's highlight state - item->tab seems to be a nullptr/invalid ptr

gdb:

Thread 1 "chatterino" received signal SIGSEGV, Segmentation fault.
chatterino::NotebookTab::highlightState (this=0x0) at /home/pajlada/git/chatterino2/src/widgets/helper/NotebookTab.cpp:380
380         return this->highlightState_;
(gdb) bt
#0  chatterino::NotebookTab::highlightState (this=0x0) at /home/pajlada/git/chatterino2/src/widgets/helper/NotebookTab.cpp:380
#1  0x000055555634d29f in chatterino::Notebook::duplicatePage (this=0x5555569b13a0, page=0x555557bf3eb0) at /home/pajlada/git/chatterino2/src/widgets/Notebook.cpp:201
#2  0x000055555645bdd6 in chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4::operator()() const (this=0x5555583c20a0)
    at /home/pajlada/git/chatterino2/src/widgets/helper/NotebookTab.cpp:103
#3  0x000055555645bd76 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4>::call(chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4&, void**) (f=..., arg=0x7fffffff3ff0) at /usr/include/qt6/QtCore/qobjectdefs_impl.h:137
#4  0x000055555645bd31 in QtPrivate::FunctorCallable<chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4>::call<QtPrivate::List<>, void>(chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4&, void*, void**) (f=..., arg=0x7fffffff3ff0) at /usr/include/qt6/QtCore/qobjectdefs_impl.h:345
#5  0x000055555645bcce in QtPrivate::QCallableObject<chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0x5555583c2090, r=0x5555583c1f30, a=0x7fffffff3ff0, ret=0x0) at /usr/include/qt6/QtCore/qobjectdefs_impl.h:555
#6  0x00007ffff679b57f in ??? () at /usr/lib/libQt6Core.so.6
#7  0x00007ffff7301eda in QAction::activate(QAction::ActionEvent) () at /usr/lib/libQt6Gui.so.6
#8  0x00007ffff7ac5029 in ??? () at /usr/lib/libQt6Widgets.so.6
#9  0x00007ffff7ac6942 in ??? () at /usr/lib/libQt6Widgets.so.6
#10 0x00007ffff7949a99 in QWidget::event(QEvent*) () at /usr/lib/libQt6Widgets.so.6
#11 0x00007ffff78fc44d in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/libQt6Widgets.so.6
#12 0x00007ffff7901548 in QApplication::notify(QObject*, QEvent*) () at /usr/lib/libQt6Widgets.so.6
#13 0x00007ffff673fe18 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/libQt6Core.so.6
#14 0x00007ffff78f457b in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) () at /usr/lib/libQt6Widgets.so.6
#15 0x00007ffff795f484 in ??? () at /usr/lib/libQt6Widgets.so.6
#16 0x00007ffff7960370 in ??? () at /usr/lib/libQt6Widgets.so.6
#17 0x00007ffff78fc44d in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/libQt6Widgets.so.6
#18 0x00007ffff673fe18 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/libQt6Core.so.6
#19 0x00007ffff6f75b20 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) () at /usr/lib/libQt6Gui.so.6
#20 0x00007ffff6fe8dcc in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt6Gui.so.6
#21 0x00007ffff23e6cb7 in ??? () at /usr/lib/qt6/plugins/platforms/../../../libQt6XcbQpa.so.6
#22 0x00007ffff57e4a89 in ??? () at /usr/lib/libglib-2.0.so.0
#23 0x00007ffff58469b7 in ??? () at /usr/lib/libglib-2.0.so.0
#24 0x00007ffff57e3f95 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#25 0x00007ffff6993389 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt6Core.so.6
#26 0x00007ffff6748350 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt6Core.so.6
#27 0x00007ffff6743c1d in QCoreApplication::exec() () at /usr/lib/libQt6Core.so.6
#28 0x0000555555b8e103 in chatterino::Application::run (this=0x7fffffff5310, qtApp=...) at /home/pajlada/git/chatterino2/src/Application.cpp:326
#29 0x0000555555bff0a2 in chatterino::runGui (a=..., paths=..., settings=..., args=..., updates=...) at /home/pajlada/git/chatterino2/src/RunGui.cpp:281
#30 0x0000555555b6d31b in main (argc=1, argv=0x7fffffffe358) at /home/pajlada/git/chatterino2/src/main.cpp:102

valgrind:

==78015== Invalid read of size 8
==78015==    at 0xF01297: chatterino::Notebook::duplicatePage(QWidget*) (src/widgets/Notebook.cpp:201)
==78015==    by 0x100FDD5: chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4::operator()() const (src/widgets/helper/NotebookTab.cpp:103)
==78015==    by 0x100FD75: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4>::call(chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4&, void**) (qobjectdefs_impl.h:137)
==78015==    by 0x100FD30: void QtPrivate::FunctorCallable<chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4>::call<QtPrivate::List<>, void>(chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4&, void*, void**) (qobjectdefs_impl.h:345)
==78015==    by 0x100FCCD: QtPrivate::QCallableObject<chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:555)
==78015==    by 0x5D4057E: UnknownInlinedFun (qobjectdefs_impl.h:469)
==78015==    by 0x5D4057E: void doActivate<false>(QObject*, int, void**) (qobject.cpp:4078)
==78015==    by 0x5506ED9: UnknownInlinedFun (moc_qaction.cpp:480)
==78015==    by 0x5506ED9: QAction::activate(QAction::ActionEvent) (qaction.cpp:1102)
==78015==    by 0x4B5D028: QMenuPrivate::activateCausedStack(QList<QPointer<QWidget> > const&, QAction*, QAction::ActionEvent, bool) (qmenu.cpp:1413)
==78015==    by 0x4B5E941: QMenuPrivate::activateAction(QAction*, QAction::ActionEvent, bool) (qmenu.cpp:1495)
==78015==    by 0x49E1A98: QWidget::event(QEvent*) (qwidget.cpp:9022)
==78015==    by 0x499444C: QApplicationPrivate::notify_helper(QObject*, QEvent*) (qapplication.cpp:3287)
==78015==    by 0x4999547: QApplication::notify(QObject*, QEvent*) (qapplication.cpp:2765)
==78015==  Address 0x14ea3f98 is 88 bytes inside a block of size 112 free'd
==78015==    at 0x4849E00: realloc (vg_replace_malloc.c:1800)
==78015==    by 0x5DEEFC1: QArrayData::reallocateUnaligned(QArrayData*, void*, long long, long long, QArrayData::AllocationOption) (qarraydata.cpp:244)
==78015==    by 0xF122BD: QTypedArrayData<chatterino::Notebook::Item>::reallocateUnaligned(QTypedArrayData<chatterino::Notebook::Item>*, chatterino::Notebook::Item*, long long, QArrayData::AllocationOption) (qarraydata.h:154)
==78015==    by 0xF11C1D: QtPrivate::QMovableArrayOps<chatterino::Notebook::Item>::reallocate(long long, QArrayData::AllocationOption) (qarraydataops.h:867)
==78015==    by 0xF11718: QArrayDataPointer<chatterino::Notebook::Item>::reallocateAndGrow(QArrayData::GrowthPosition, long long, QArrayDataPointer<chatterino::Notebook::Item>*) (qarraydatapointer.h:223)
==78015==    by 0xF112A1: QArrayDataPointer<chatterino::Notebook::Item>::detachAndGrow(QArrayData::GrowthPosition, long long, chatterino::Notebook::Item const**, QArrayDataPointer<chatterino::Notebook::Item>*) (qarraydatapointer.h:209)
==78015==    by 0xF10EC1: void QtPrivate::QMovableArrayOps<chatterino::Notebook::Item>::emplace<chatterino::Notebook::Item const&>(long long, chatterino::Notebook::Item const&) (qarraydataops.h:831)
==78015==    by 0xF12792: QList<chatterino::Notebook::Item>::iterator QList<chatterino::Notebook::Item>::emplace<chatterino::Notebook::Item const&>(long long, chatterino::Notebook::Item const&) (qlist.h:858)
==78015==    by 0xF0C614: QList<chatterino::Notebook::Item>::insert(long long, chatterino::Notebook::Item const&) (qlist.h:475)
==78015==    by 0xEFE59A: chatterino::Notebook::addPageAt(QWidget*, int, QString, bool) (src/widgets/Notebook.cpp:116)
==78015==    by 0xF0122B: chatterino::Notebook::duplicatePage(QWidget*) (src/widgets/Notebook.cpp:198)
==78015==    by 0x100FDD5: chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4::operator()() const (src/widgets/helper/NotebookTab.cpp:103)
==78015==  Block was alloc'd at
==78015==    at 0x4849E00: realloc (vg_replace_malloc.c:1800)
==78015==    by 0x5DEEFC1: QArrayData::reallocateUnaligned(QArrayData*, void*, long long, long long, QArrayData::AllocationOption) (qarraydata.cpp:244)
==78015==    by 0xF122BD: QTypedArrayData<chatterino::Notebook::Item>::reallocateUnaligned(QTypedArrayData<chatterino::Notebook::Item>*, chatterino::Notebook::Item*, long long, QArrayData::AllocationOption) (qarraydata.h:154)
==78015==    by 0xF11C1D: QtPrivate::QMovableArrayOps<chatterino::Notebook::Item>::reallocate(long long, QArrayData::AllocationOption) (qarraydataops.h:867)
==78015==    by 0xF11718: QArrayDataPointer<chatterino::Notebook::Item>::reallocateAndGrow(QArrayData::GrowthPosition, long long, QArrayDataPointer<chatterino::Notebook::Item>*) (qarraydatapointer.h:223)
==78015==    by 0xF112A1: QArrayDataPointer<chatterino::Notebook::Item>::detachAndGrow(QArrayData::GrowthPosition, long long, chatterino::Notebook::Item const**, QArrayDataPointer<chatterino::Notebook::Item>*) (qarraydatapointer.h:209)
==78015==    by 0xF10EC1: void QtPrivate::QMovableArrayOps<chatterino::Notebook::Item>::emplace<chatterino::Notebook::Item const&>(long long, chatterino::Notebook::Item const&) (qarraydataops.h:831)
==78015==    by 0xF10CE7: chatterino::Notebook::Item& QList<chatterino::Notebook::Item>::emplaceBack<chatterino::Notebook::Item const&>(chatterino::Notebook::Item const&) (qlist.h:866)
==78015==    by 0xF10C8C: QList<chatterino::Notebook::Item>::append(chatterino::Notebook::Item const&) (qlist.h:444)
==78015==    by 0xF0C5DC: QList<chatterino::Notebook::Item>::push_back(chatterino::Notebook::Item const&) (qlist.h:661)
==78015==    by 0xEFE563: chatterino::Notebook::addPageAt(QWidget*, int, QString, bool) (src/widgets/Notebook.cpp:112)
==78015==    by 0xEFE401: chatterino::Notebook::addPage(QWidget*, QString, bool) (src/widgets/Notebook.cpp:91)

auto *tab = this->addPageAt(
newContainer, newTabPosition,
item->tab->hasCustomTitle() ? item->tab->getCustomTitle() : "", false);
tab->setHighlightState(item->tab->highlightState());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This currently crashes if you try to duplicate a previously duplicated tab - something with attempting to access the clicked item's highlight state - item->tab seems to be a nullptr/invalid ptr

item is invalid.


This accesses item after it's invalidated due to a resize of items_ by addPageAt (item points to a location inside that list). The following fixes the crash:

diff --git a/src/widgets/Notebook.cpp b/src/widgets/Notebook.cpp
index 0350a1d7..4bbc6148 100644
--- a/src/widgets/Notebook.cpp
+++ b/src/widgets/Notebook.cpp
@@ -195,10 +195,11 @@ void Notebook::duplicatePage(QWidget *page)
     newContainer->applyFromDescriptor(descriptor);
 
     int newTabPosition = this->indexOf(page) + 1;
+    auto highlightState = item->tab->highlightState();
     auto *tab = this->addPageAt(
         newContainer, newTabPosition,
         item->tab->hasCustomTitle() ? item->tab->getCustomTitle() : "", false);
-    tab->setHighlightState(item->tab->highlightState());
+    tab->setHighlightState(highlightState);
 
     newContainer->setTab(tab);
 }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew I would be missing something, thanks.

@8thony
Copy link
Contributor

8thony commented May 18, 2024

issue while duplicate a tab with a watching split
watching: none -> empty split
watching: pajlada -> pajlada

@KleberPF
Copy link
Contributor Author

issue while duplicate a tab with a watching split watching: none -> empty split watching: pajlada -> pajlada

I'll look into it, thanks.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved

SplitNodeDescriptor result;
result.type_ =
channelTypeToString(currentNode->split_->getChannel()->getType());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pajlada @Nerixyz not sure why but there is a Channel::Type inside IndirectChannel and inside Channel, and they are not matching here

image

The reason being that when the watchingChannel is created, it gets passed an empty channel that has type None

watchingChannel(Channel::getEmpty(), Channel::Type::TwitchWatching)

Copy link
Contributor

@Nerixyz Nerixyz May 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type of the IndirectChannel is the type of indirection. It's really only for the watching channel. Its type is only ever TwitchWatching or Direct (don't quote me on that). Maybe there should be another type for the type of indirection, but it's easier for saving/restoring right now, I suppose.

If you use getIndirectChannel().getType() instead if getChannel()->getType() it seems to work.

Copy link
Contributor

@kornes kornes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you force pushed Pajs commits out of existence, can look for them upward from here 44f22f7 :D


SplitNodeDescriptor result;
result.type_ =
channelTypeToString(currentNode->split_->getChannel()->getType());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

descriptor building doesn't handle empty nodes rn, so trying to duplicate empty tab (Node::Type::EmptyRoot) will crash here because split is null. We probably should allow that for ux consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you force pushed Pajs commits out of existence, can look for them upward from here 44f22f7 :D

Oops, my alias did a bit of trolling. Didn't realize someone else pushed to the branch. Not sure if there is an easy way for me to recover it now that the commit is orphan

descriptor building doesn't handle empty nodes rn, so trying to duplicate empty tab (Node::Type::EmptyRoot) will crash here because split is null. We probably should allow that for ux consistency

Makes sense, I'll add a check for that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, my alias did a bit of trolling. Didn't realize someone else pushed to the branch. Not sure if there is an easy way for me to recover it now that the commit is orphan

If you know the SHA, you can append .diff or .patch to the commit's URL on GitHub - for example https://github.com/Chatterino/chatterino2/commit/44f22f732559ab3065d5fcadb33028b3ad5faec8.patch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could get the changes from a patch and make a new commit out of that, is that ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you know the SHA, you can append .diff or .patch to the commit's URL on GitHub

We commented basically at the same time lol. Yeah, I will do that and add a new commit with pajlada's changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

patches are fine, rebasing onto 44f22f7 should also work or cherry picking skipped commits

git cherry-pick 2f4021bfd9c1b5e156942e3bc8b880524fb5e96c
git cherry-pick 75027efb07517b70a1a535de97e1f9c6408b17e3
git cherry-pick bfce89c94d9858b2bf4fc53c63971491d4a842e7
git cherry-pick 470cd2ae33114cbb7e83a9996653500e42b484c2
git cherry-pick 0184bc49446f2f6b5f159c268c7e7973eb2b45f0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to find the commits by fetching (I guess because they aren't on any branch) so cherry-pick wasn't working

 $ git cherry-pick 470cd2ae33114cbb7e83a9996653500e42b484c2       
fatal: bad object 470cd2ae33114cbb7e83a9996653500e42b484c2

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved
src/widgets/splits/SplitContainer.cpp Show resolved Hide resolved
@KleberPF
Copy link
Contributor Author

@8thony it should work now, could you test it again?

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved
src/widgets/splits/SplitContainer.cpp Show resolved Hide resolved
Copy link
Contributor

@8thony 8thony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

works as expected, thanks.

Copy link
Member

@pajlada pajlada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

segfault when trying to dupe an empty tab

Thread 1 "chatterino" received signal SIGSEGV, Segmentation fault.
0x00005555562ee228 in std::__shared_ptr<chatterino::IndirectChannel::Data, (__gnu_cxx::_Lock_policy)2>::__shared_ptr (
    this=0x7fffffff3bf0)
    at /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/shared_ptr_base.h:1523
1523          __shared_ptr(const __shared_ptr&) noexcept = default;
(gdb) bt
#0  0x00005555562ee228 in std::__shared_ptr<chatterino::IndirectChannel::Data, (__gnu_cxx::_Lock_policy)2>::__shared_ptr
    (this=0x7fffffff3bf0)
    at /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/shared_ptr_base.h:1523
#1  0x00005555562ee1fd in std::shared_ptr<chatterino::IndirectChannel::Data>::shared_ptr (this=0x7fffffff3bf0)
    at /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/shared_ptr.h:203
#2  0x00005555562e845d in chatterino::IndirectChannel::IndirectChannel (this=0x7fffffff3bf0)
    at /home/pajlada/git/chatterino2/src/common/Channel.hpp:131
#3  0x000055555652aa97 in chatterino::Split::getIndirectChannel (this=0x0)
    at /home/pajlada/git/chatterino2/src/widgets/splits/Split.cpp:858
#4  0x0000555556557a5e in chatterino::SplitContainer::buildDescriptorRecursively
    (this=0x555558bcb9f0, currentNode=0x555558bcbb90) at /home/pajlada/git/chatterino2/src/widgets/splits/SplitContainer.cpp:820
#5  0x000055555655798a in chatterino::SplitContainer::buildDescriptor (this=0x555558bcb9f0)
    at /home/pajlada/git/chatterino2/src/widgets/splits/SplitContainer.cpp:769
#6  0x000055555634cffe in chatterino::Notebook::duplicatePage (this=0x55555698d7b0, page=0x555558bcb9f0)
    at /home/pajlada/git/chatterino2/src/widgets/Notebook.cpp:192
#7  0x000055555645bc96 in chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4::operator()() const
    (this=0x55555818bdd0) at /home/pajlada/git/chatterino2/src/widgets/helper/NotebookTab.cpp:102
#8  0x000055555645bc36 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4>::call(chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4&, void**)
    (f=..., arg=0x7fffffff3ff0) at /usr/include/qt6/QtCore/qobjectdefs_impl.h:137
#9  0x000055555645bbf1 in QtPrivate::FunctorCallable<chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4>::call<QtPrivate::List<>, void>(chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4&, void*, void**) (f=..., arg=0x7fffffff3ff0)
    at /usr/include/qt6/QtCore/qobjectdefs_impl.h:345
#10 0x000055555645bb8e in QtPrivate::QCallableObject<chatterino::NotebookTab::NotebookTab(chatterino::Notebook*)::$_4, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*)
    (which=1, this_=0x55555818bdc0, r=0x555558112a10, a=0x7fffffff3ff0, ret=0x0)
    at /usr/include/qt6/QtCore/qobjectdefs_impl.h:555
#11 0x00007ffff679b57f in ??? () at /usr/lib/libQt6Core.so.6
#12 0x00007ffff7301eda in QAction::activate(QAction::ActionEvent) () at /usr/lib/libQt6Gui.so.6
#13 0x00007ffff7ac5029 in ??? () at /usr/lib/libQt6Widgets.so.6
#14 0x00007ffff7ac6942 in ??? () at /usr/lib/libQt6Widgets.so.6
#15 0x00007ffff7949a99 in QWidget::event(QEvent*) () at /usr/lib/libQt6Widgets.so.6
#16 0x00007ffff78fc44d in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/libQt6Widgets.so.6
#17 0x00007ffff7901548 in QApplication::notify(QObject*, QEvent*) () at /usr/lib/libQt6Widgets.so.6
#18 0x00007ffff673fe18 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/libQt6Core.so.6
#19 0x00007ffff78f457b in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) () at /usr/lib/libQt6Widgets.so.6
#20 0x00007ffff795f484 in ??? () at /usr/lib/libQt6Widgets.so.6
#21 0x00007ffff7960370 in ??? () at /usr/lib/libQt6Widgets.so.6
#22 0x00007ffff78fc44d in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/libQt6Widgets.so.6
#23 0x00007ffff673fe18 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/libQt6Core.so.6
#24 0x00007ffff6f75b20 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) ()
    at /usr/lib/libQt6Gui.so.6
#25 0x00007ffff6fe8dcc in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
    at /usr/lib/libQt6Gui.so.6
#26 0x00007ffff23e6cb7 in ??? () at /usr/lib/qt6/plugins/platforms/../../../libQt6XcbQpa.so.6
#27 0x00007ffff57e4a89 in ??? () at /usr/lib/libglib-2.0.so.0
#28 0x00007ffff58469b7 in ??? () at /usr/lib/libglib-2.0.so.0
#29 0x00007ffff57e3f95 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#30 0x00007ffff6993389 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
    at /usr/lib/libQt6Core.so.6
#31 0x00007ffff6748350 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt6Core.so.6
#32 0x00007ffff6743c1d in QCoreApplication::exec() () at /usr/lib/libQt6Core.so.6
#33 0x0000555555b8e023 in chatterino::Application::run (this=0x7fffffff5310, qtApp=...)
    at /home/pajlada/git/chatterino2/src/Application.cpp:326
#34 0x0000555555bfefc2 in chatterino::runGui (a=..., paths=..., settings=..., args=..., updates=...)
    at /home/pajlada/git/chatterino2/src/RunGui.cpp:281
#35 0x0000555555b6d23b in main (argc=1, argv=0x7fffffffe358) at /home/pajlada/git/chatterino2/src/main.cpp:102

currentNode->split_ is a nullptr

@KleberPF
Copy link
Contributor Author

currentNode->split_ is a nullptr

I tested duplicating an empty tab, but not duplicating a duplicated empty tab. I added a check now to only try to build and apply from the descriptor if we have a split in the tab.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/Notebook.cpp Show resolved Hide resolved
src/widgets/splits/SplitContainer.cpp Show resolved Hide resolved
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

src/widgets/splits/SplitContainer.cpp Outdated Show resolved Hide resolved
@pajlada pajlada enabled auto-merge (squash) May 25, 2024 12:24
@pajlada pajlada merged commit d161036 into Chatterino:master May 25, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants