Add setting to only show tabs with live channels (#4358)

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
Daniel Sage
2023-06-11 02:34:28 -07:00
committed by GitHub
parent c907f2b170
commit 4361790fbd
13 changed files with 412 additions and 136 deletions
+242 -89
View File
@@ -92,9 +92,7 @@ NotebookTab *Notebook::addPage(QWidget *page, QString title, bool select)
}
this->performLayout();
tab->show();
tab->setVisible(this->shouldShowTab(tab));
return tab;
}
@@ -216,6 +214,7 @@ void Notebook::select(QWidget *page, bool focusPage)
this->selectedPage_ = page;
this->performLayout();
this->updateTabVisibility();
}
bool Notebook::containsPage(QWidget *page)
@@ -262,45 +261,121 @@ void Notebook::selectIndex(int index, bool focusPage)
this->select(this->items_[index].page, focusPage);
}
void Notebook::selectNextTab(bool focusPage)
void Notebook::selectVisibleIndex(int index, bool focusPage)
{
if (this->items_.size() <= 1)
if (!this->tabVisibilityFilter_)
{
this->selectIndex(index, focusPage);
return;
}
auto index =
(this->indexOf(this->selectedPage_) + 1) % this->items_.count();
int i = 0;
for (auto &item : this->items_)
{
if (this->tabVisibilityFilter_(item.tab))
{
if (i == index)
{
// found the index'th visible page
this->select(item.page, focusPage);
return;
}
++i;
}
}
}
this->select(this->items_[index].page, focusPage);
void Notebook::selectNextTab(bool focusPage)
{
const int size = this->items_.size();
if (!this->tabVisibilityFilter_)
{
if (size <= 1)
{
return;
}
auto index = (this->indexOf(this->selectedPage_) + 1) % size;
this->select(this->items_[index].page, focusPage);
return;
}
// find next tab that is permitted by filter
const int startIndex = this->indexOf(this->selectedPage_);
auto index = (startIndex + 1) % size;
while (index != startIndex)
{
if (this->tabVisibilityFilter_(this->items_[index].tab))
{
this->select(this->items_[index].page, focusPage);
return;
}
index = (index + 1) % size;
}
}
void Notebook::selectPreviousTab(bool focusPage)
{
if (this->items_.size() <= 1)
const int size = this->items_.size();
if (!this->tabVisibilityFilter_)
{
if (size <= 1)
{
return;
}
int index = this->indexOf(this->selectedPage_) - 1;
if (index < 0)
{
index += size;
}
this->select(this->items_[index].page, focusPage);
return;
}
int index = this->indexOf(this->selectedPage_) - 1;
// find next previous tab that is permitted by filter
const int startIndex = this->indexOf(this->selectedPage_);
if (index < 0)
auto index = startIndex == 0 ? size - 1 : startIndex - 1;
while (index != startIndex)
{
index += this->items_.count();
}
if (this->tabVisibilityFilter_(this->items_[index].tab))
{
this->select(this->items_[index].page, focusPage);
return;
}
this->select(this->items_[index].page, focusPage);
index = index == 0 ? size - 1 : index - 1;
}
}
void Notebook::selectLastTab(bool focusPage)
{
const auto size = this->items_.size();
if (size <= 1)
if (!this->tabVisibilityFilter_)
{
const auto size = this->items_.size();
if (size <= 1)
{
return;
}
this->select(this->items_[size - 1].page, focusPage);
return;
}
this->select(this->items_[size - 1].page, focusPage);
// find first tab permitted by filter starting from the end
for (auto it = this->items_.rbegin(); it != this->items_.rend(); ++it)
{
if (this->tabVisibilityFilter_(it->tab))
{
this->select(it->page, focusPage);
return;
}
}
}
int Notebook::getPageCount() const
@@ -329,6 +404,12 @@ QWidget *Notebook::tabAt(QPoint point, int &index, int maxWidth)
for (auto &item : this->items_)
{
if (!item.tab->isVisible())
{
i++;
continue;
}
auto rect = item.tab->getDesiredRect();
rect.setHeight(int(this->scale() * 24));
@@ -381,59 +462,73 @@ void Notebook::setShowTabs(bool value)
{
this->showTabs_ = value;
this->performLayout();
for (auto &item : this->items_)
{
item.tab->setHidden(!value);
}
this->setShowAddButton(value);
this->performLayout();
this->updateTabVisibility();
this->updateTabVisibilityMenuAction();
// show a popup upon hiding tabs
if (!value && getSettings()->informOnTabVisibilityToggle.getValue())
{
auto unhideSeq = getApp()->hotkeys->getDisplaySequence(
HotkeyCategory::Window, "setTabVisibility",
{std::vector<QString>()});
if (unhideSeq.isEmpty())
{
unhideSeq = getApp()->hotkeys->getDisplaySequence(
HotkeyCategory::Window, "setTabVisibility", {{"toggle"}});
}
if (unhideSeq.isEmpty())
{
unhideSeq = getApp()->hotkeys->getDisplaySequence(
HotkeyCategory::Window, "setTabVisibility", {{"on"}});
}
QString hotkeyInfo = "(currently unbound)";
if (!unhideSeq.isEmpty())
{
hotkeyInfo =
"(" +
unhideSeq.toString(QKeySequence::SequenceFormat::NativeText) +
")";
}
QMessageBox msgBox(this->window());
msgBox.window()->setWindowTitle("Chatterino - hidden tabs");
msgBox.setText("You've just hidden your tabs.");
msgBox.setInformativeText(
"You can toggle tabs by using the keyboard shortcut " + hotkeyInfo +
" or right-clicking the tab area and selecting \"Toggle "
"visibility of tabs\".");
msgBox.addButton(QMessageBox::Ok);
auto *dsaButton =
msgBox.addButton("Don't show again", QMessageBox::YesRole);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
if (msgBox.clickedButton() == dsaButton)
{
getSettings()->informOnTabVisibilityToggle.setValue(false);
}
this->showTabVisibilityInfoPopup();
}
}
void Notebook::showTabVisibilityInfoPopup()
{
auto unhideSeq = getApp()->hotkeys->getDisplaySequence(
HotkeyCategory::Window, "setTabVisibility", {std::vector<QString>()});
if (unhideSeq.isEmpty())
{
unhideSeq = getApp()->hotkeys->getDisplaySequence(
HotkeyCategory::Window, "setTabVisibility", {{"toggle"}});
}
if (unhideSeq.isEmpty())
{
unhideSeq = getApp()->hotkeys->getDisplaySequence(
HotkeyCategory::Window, "setTabVisibility", {{"on"}});
}
QString hotkeyInfo = "(currently unbound)";
if (!unhideSeq.isEmpty())
{
hotkeyInfo =
"(" + unhideSeq.toString(QKeySequence::SequenceFormat::NativeText) +
")";
}
QMessageBox msgBox(this->window());
msgBox.window()->setWindowTitle("Chatterino - hidden tabs");
msgBox.setText("You've just hidden your tabs.");
msgBox.setInformativeText(
"You can toggle tabs by using the keyboard shortcut " + hotkeyInfo +
" or right-clicking the tab area and selecting \"Toggle "
"visibility of tabs\".");
msgBox.addButton(QMessageBox::Ok);
auto *dsaButton =
msgBox.addButton("Don't show again", QMessageBox::YesRole);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
if (msgBox.clickedButton() == dsaButton)
{
getSettings()->informOnTabVisibilityToggle.setValue(false);
}
}
void Notebook::refresh()
{
this->performLayout();
this->updateTabVisibility();
}
void Notebook::updateTabVisibility()
{
for (auto &item : this->items_)
{
item.tab->setVisible(this->shouldShowTab(item.tab));
}
updateTabVisibilityMenuAction();
}
void Notebook::updateTabVisibilityMenuAction()
@@ -510,6 +605,21 @@ void Notebook::performLayout(bool animated)
const auto buttonWidth = tabHeight;
const auto buttonHeight = tabHeight - 1;
std::vector<Item> filteredItems;
filteredItems.reserve(this->items_.size());
if (this->tabVisibilityFilter_)
{
std::copy_if(this->items_.begin(), this->items_.end(),
std::back_inserter(filteredItems),
[this](const auto &item) {
return this->tabVisibilityFilter_(item.tab);
});
}
else
{
filteredItems.assign(this->items_.begin(), this->items_.end());
}
if (this->tabLocation_ == NotebookTabLocation::Top)
{
auto x = left;
@@ -535,14 +645,14 @@ void Notebook::performLayout(bool animated)
{
// layout tabs
/// Notebook tabs need to know if they are in the last row.
auto firstInBottomRow =
this->items_.size() ? &this->items_.front() : nullptr;
auto *firstInBottomRow =
filteredItems.empty() ? nullptr : &filteredItems.front();
for (auto &item : this->items_)
for (auto &item : filteredItems)
{
/// Break line if element doesn't fit.
auto isFirst = &item == &this->items_.front();
auto isLast = &item == &this->items_.back();
auto isFirst = &item == &filteredItems.front();
auto isLast = &item == &filteredItems.back();
auto fitsInLine = ((isLast ? addButtonWidth : 0) + x +
item.tab->width()) <= width();
@@ -562,7 +672,7 @@ void Notebook::performLayout(bool animated)
/// Update which tabs are in the last row
auto inLastRow = false;
for (const auto &item : this->items_)
for (const auto &item : filteredItems)
{
if (&item == firstInBottomRow)
{
@@ -633,7 +743,7 @@ void Notebook::performLayout(bool animated)
{
return;
}
int count = this->items_.size() + (this->showAddButton_ ? 1 : 0);
int count = filteredItems.size() + (this->showAddButton_ ? 1 : 0);
int columnCount = ceil((float)count / tabsPerColumn);
// only add width of all the tabs if they are not hidden
@@ -644,13 +754,15 @@ void Notebook::performLayout(bool animated)
bool isLastColumn = col == columnCount - 1;
auto largestWidth = 0;
int tabStart = col * tabsPerColumn;
int tabEnd = std::min((col + 1) * tabsPerColumn,
(int)this->items_.size());
int tabEnd =
std::min(static_cast<size_t>((col + 1) * tabsPerColumn),
filteredItems.size());
for (int i = tabStart; i < tabEnd; i++)
{
largestWidth = std::max(
this->items_.at(i).tab->normalTabWidth(), largestWidth);
largestWidth =
std::max(filteredItems.at(i).tab->normalTabWidth(),
largestWidth);
}
if (isLastColumn && this->showAddButton_)
@@ -664,7 +776,7 @@ void Notebook::performLayout(bool animated)
for (int i = tabStart; i < tabEnd; i++)
{
auto item = this->items_.at(i);
auto item = filteredItems.at(i);
/// Layout tab
item.tab->growWidth(largestWidth);
@@ -735,7 +847,7 @@ void Notebook::performLayout(bool animated)
{
return;
}
int count = this->items_.size() + (this->showAddButton_ ? 1 : 0);
int count = filteredItems.size() + (this->showAddButton_ ? 1 : 0);
int columnCount = ceil((float)count / tabsPerColumn);
// only add width of all the tabs if they are not hidden
@@ -746,13 +858,15 @@ void Notebook::performLayout(bool animated)
bool isLastColumn = col == columnCount - 1;
auto largestWidth = 0;
int tabStart = col * tabsPerColumn;
int tabEnd = std::min((col + 1) * tabsPerColumn,
(int)this->items_.size());
int tabEnd =
std::min(static_cast<size_t>((col + 1) * tabsPerColumn),
filteredItems.size());
for (int i = tabStart; i < tabEnd; i++)
{
largestWidth = std::max(
this->items_.at(i).tab->normalTabWidth(), largestWidth);
largestWidth =
std::max(filteredItems.at(i).tab->normalTabWidth(),
largestWidth);
}
if (isLastColumn && this->showAddButton_)
@@ -771,7 +885,7 @@ void Notebook::performLayout(bool animated)
for (int i = tabStart; i < tabEnd; i++)
{
auto item = this->items_.at(i);
auto item = filteredItems.at(i);
/// Layout tab
item.tab->growWidth(largestWidth);
@@ -840,14 +954,14 @@ void Notebook::performLayout(bool animated)
// layout tabs
/// Notebook tabs need to know if they are in the last row.
auto firstInBottomRow =
this->items_.size() ? &this->items_.front() : nullptr;
auto *firstInBottomRow =
filteredItems.empty() ? nullptr : &filteredItems.front();
for (auto &item : this->items_)
for (auto &item : filteredItems)
{
/// Break line if element doesn't fit.
auto isFirst = &item == &this->items_.front();
auto isLast = &item == &this->items_.back();
auto isFirst = &item == &filteredItems.front();
auto isLast = &item == &filteredItems.back();
auto fitsInLine = ((isLast ? addButtonWidth : 0) + x +
item.tab->width()) <= width();
@@ -867,7 +981,7 @@ void Notebook::performLayout(bool animated)
/// Update which tabs are in the last row
auto inLastRow = false;
for (const auto &item : this->items_)
for (const auto &item : filteredItems)
{
if (&item == firstInBottomRow)
{
@@ -1046,6 +1160,28 @@ size_t Notebook::visibleButtonCount() const
return i;
}
void Notebook::setTabVisibilityFilter(TabVisibilityFilter filter)
{
this->tabVisibilityFilter_ = std::move(filter);
this->performLayout();
this->updateTabVisibility();
}
bool Notebook::shouldShowTab(const NotebookTab *tab) const
{
if (!this->showTabs_)
{
return false;
}
if (this->tabVisibilityFilter_)
{
return this->tabVisibilityFilter_(tab);
}
return true;
}
SplitNotebook::SplitNotebook(Window *parent)
: Notebook(parent)
{
@@ -1061,6 +1197,24 @@ SplitNotebook::SplitNotebook(Window *parent)
this->addCustomButtons();
}
getSettings()->tabVisibility.connect(
[this](int val, auto) {
auto visibility = NotebookTabVisibility(val);
switch (visibility)
{
case NotebookTabVisibility::LiveOnly:
this->setTabVisibilityFilter([](const NotebookTab *tab) {
return tab->isLive() || tab->isSelected();
});
break;
case NotebookTabVisibility::AllTabs:
default:
this->setTabVisibilityFilter(nullptr);
break;
}
},
this->signalHolder_, true);
this->signalHolder_.managedConnect(
getApp()->windows->selectSplit, [this](Split *split) {
for (auto &&item : this->items())
@@ -1204,7 +1358,6 @@ SplitContainer *SplitNotebook::addPage(bool select)
auto tab = Notebook::addPage(container, QString(), select);
container->setTab(tab);
tab->setParent(this);
tab->setVisible(this->getShowTabs());
return container;
}