Merge pull request #1198 from kiwix/Issue#157-scroll-tab-buttons

Introduce Scroll Buttons to Replace Ones from Qt's Built-in TabBar.
This commit is contained in:
Kelson 2024-09-17 10:53:09 +02:00 committed by GitHub
commit 93ebec0b39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 232 additions and 54 deletions

View File

@ -167,7 +167,9 @@ QTabBar {
}
QTabBar::tear {
background-color: blue;
width: 0px;
height: 0px;
border: none;
}
QTabWidget::pane {
@ -194,19 +196,33 @@ QTabBar::tab:first {
padding-left: 5px;
}
QTabBar::tab:last QToolButton {
#closeTabButton, #newTabButton {
font-size: 30px;
width: 30px; min-width: 30px; max-width: 30px;
height: 30px; min-height:30px; max-height:30px;
border-radius: 3px;
}
QTabBar::tab:last QToolButton::hover {
#nextTabButton, #prevTabButton, #newTabSideButton {
border: 1px solid #ccc;
}
#closeTabButton:hover, #newTabButton:hover,
#nextTabButton:hover, #prevTabButton:hover,
#newTabSideButton:hover {
border: 1px solid #3366CC;
background-color: #D9E9FF;
border-radius: 3px;
}
QTabBar::scroller {
width: 0px;
height: 0px;
/* Last tab size is off by 1 if border not set. */
border: 1px solid transparent;
}
/* -----------------------------------------
TabWidget
*/

View File

@ -165,5 +165,7 @@
"import-reading-list": "Import reading list",
"import-reading-list-error": "An error has occured during import of the reading list.",
"disable-sandbox": "Application was launched from a network drive. This is known to cause compatibility issues due to the sandbox. Do you want to take the risks and disable it?",
"save-page-as": "Save As..."
"save-page-as": "Save As...",
"scroll-next-tab": "Scroll to next tab",
"scroll-previous-tab": "Scroll to previous tab"
}

View File

@ -172,5 +172,7 @@
"export-reading-list-error": "Error description text for when exporting the reading list to a file failed.",
"import-reading-list": "Represents the action of importing a reading list from a file.",
"import-reading-list-error": "Error description text for when importing a reading list from a file failed.",
"save-page-as": "Represents the action of saving the current tab content to a file chosen by the user."
"save-page-as": "Represents the action of saving the current tab content to a file chosen by the user.",
"scroll-next-tab": "Represents the action of scrolling to the next tab of the current tab which toward the end of the tab bar.",
"scroll-previous-tab": "Represents the action of scrolling to the previous tab of the current tab which toward the start of the tab bar."
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M9.4 278.6c-12.5-12.5-12.5-32.8 0-45.3l128-128c9.2-9.2 22.9-11.9 34.9-6.9s19.8 16.6 19.8 29.6l0 256c0 12.9-7.8 24.6-19.8 29.6s-25.7 2.2-34.9-6.9l-128-128z"/></svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@ -65,5 +65,6 @@
<file>icons/xmark-solid.svg</file>
<file>icons/home-button.svg</file>
<file>icons/more-vertical.svg</file>
<file>icons/caret-left-solid.svg</file>
</qresource>
</RCC>

View File

@ -385,16 +385,16 @@ void KiwixApp::createActions()
if (QGuiApplication::isLeftToRight()) {
CREATE_ACTION_ICON_SHORTCUT(HistoryBackAction, "history-left", gt("back"), QKeySequence(Qt::ALT | Qt::Key_Left));
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-right", gt("forward"), QKeySequence(Qt::ALT | Qt::Key_Right));
CREATE_ACTION_ICON(ScrollNextTabAction, "caret-right-solid", gt("scroll-next-tab"));
CREATE_ACTION_ICON(ScrollPreviousTabAction, "caret-left-solid", gt("scroll-previous-tab"));
} else {
CREATE_ACTION_ICON_SHORTCUT(HistoryBackAction, "history-right", gt("back"), QKeySequence(Qt::ALT | Qt::Key_Right));
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-left", gt("forward"), QKeySequence(Qt::ALT | Qt::Key_Left));
CREATE_ACTION_ICON(ScrollNextTabAction, "caret-left-solid", gt("scroll-next-tab"));
CREATE_ACTION_ICON(ScrollPreviousTabAction, "caret-right-solid", gt("scroll-previous-tab"));
}
DISABLE_ACTION(HistoryBackAction);
if (QGuiApplication::isLeftToRight()) {
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-right", gt("forward"), QKeySequence(Qt::ALT | Qt::Key_Right));
} else {
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-left", gt("forward"), QKeySequence(Qt::ALT | Qt::Key_Left));
}
DISABLE_ACTION(HistoryForwardAction);
CREATE_ACTION_ICON_SHORTCUT(PrintAction, "print", gt("print"), QKeySequence::Print);

View File

@ -64,6 +64,8 @@ public:
ExitAction,
ExportReadingListAction,
ImportReadingListAction,
ScrollPreviousTabAction,
ScrollNextTabAction,
MAX_ACTION
};

View File

@ -27,6 +27,18 @@ MainWindow::MainWindow(QWidget *parent) :
addAction(app->getAction(KiwixApp::NextTabAction));
addAction(app->getAction(KiwixApp::PreviousTabAction));
mp_ui->newTabSideButton->setDefaultAction(app->getAction(KiwixApp::NewTabAction));
mp_ui->nextTabButton->setDefaultAction(app->getAction(KiwixApp::ScrollNextTabAction));
mp_ui->prevTabButton->setDefaultAction(app->getAction(KiwixApp::ScrollPreviousTabAction));
connect(mp_ui->tabBar, &TabBar::sizeChanged, this, &MainWindow::updateTabButtons);
connect(mp_ui->tabBar, &QTabBar::currentChanged, this, &MainWindow::updateTabButtons);
connect(mp_ui->tabBar, &TabBar::tabRemovedSignal, this, &MainWindow::updateTabButtons);
connect(mp_ui->tabBar, &TabBar::tabInsertedSignal, this, &MainWindow::updateTabButtons);
connect(mp_ui->nextTabButton, &QToolButton::triggered, mp_ui->tabBar, &TabBar::scrollNextTab);
connect(mp_ui->prevTabButton, &QToolButton::triggered, mp_ui->tabBar, &TabBar::scrollPreviousTab);
connect(app->getAction(KiwixApp::ExitAction), &QAction::triggered,
this, &QMainWindow::close);
connect(app->getAction(KiwixApp::ToggleFullscreenAction), &QAction::triggered,
@ -102,6 +114,32 @@ void MainWindow::showTabAndTop() {
getTopWidget()->show();
}
void MainWindow::updateTabButtons()
{
auto tabBar = getTabBar();
QRect tabBarRect = getTabBar()->rect();
QRect newTabButtonRect = tabBar->tabRect(tabBar->count() - 1);
/* Decision is made at half way of the new button tab for smoothness */
newTabButtonRect.setWidth(newTabButtonRect.width() / 2);
bool newTabButtonVisible = tabBarRect.contains(newTabButtonRect);
mp_ui->newTabSideButton->setHidden(newTabButtonVisible);
int lastTabIndex = tabBar->realTabCount() - 1;
QRect firstTabRect = tabBar->tabRect(0);
QRect lastTabRect = tabBar->tabRect(lastTabIndex);
bool firstVisible = tabBarRect.contains(firstTabRect);
bool lastVisible = tabBarRect.contains(lastTabRect);
bool noOverFlow = firstVisible && lastVisible;
mp_ui->prevTabButton->setHidden(noOverFlow);
mp_ui->nextTabButton->setHidden(noOverFlow);
mp_ui->prevTabButton->setDisabled(tabBar->currentIndex() == 0);
mp_ui->nextTabButton->setDisabled(tabBar->currentIndex() == lastTabIndex);
}
bool MainWindow::eventFilter(QObject* /*object*/, QEvent* event)
{
if (event->type() == QEvent::MouseMove && isFullScreen())
@ -129,6 +167,7 @@ void MainWindow::resizeEvent(QResizeEvent *event)
{
QMainWindow::resizeEvent(event);
KiwixApp::instance()->getContentManager()->getView()->updateSizeHint();
updateTabButtons();
}
void MainWindow::readingListToggled(bool state)

View File

@ -37,6 +37,7 @@ private slots:
void readingListToggled(bool state);
void hideTabAndTop();
void showTabAndTop();
void updateTabButtons();
private:
Ui::MainWindow *mp_ui;

View File

@ -104,6 +104,7 @@ void TabBar::setContentManagerView(ContentManagerView* view)
void TabBar::setNewTabButton(QAction* newTabAction)
{
QToolButton *tb = new QToolButton();
tb->setObjectName("newTabButton");
tb->setDefaultAction(newTabAction);
tb->setIcon(QIcon(":/icons/new-tab-icon.svg"));
int idx = addTab("");
@ -133,11 +134,24 @@ void TabBar::moveToPreviousTab()
setCurrentIndex(index <= 0 ? realTabCount() - 1 : index - 1);
}
void TabBar::scrollNextTab()
{
const int index = currentIndex();
setCurrentIndex(index == realTabCount() - 1 ? index : index + 1);
}
void TabBar::scrollPreviousTab()
{
const int index = currentIndex();
setCurrentIndex(index <= 0 ? index : index - 1);
}
void TabBar::setCloseTabButton(int index)
{
Q_ASSERT(index > 0 && index < realTabCount());
QToolButton *tb = new QToolButton(this);
tb->setObjectName("closeTabButton");
QAction *a = new QAction(QIcon(":/icons/close.svg"), gt("close-tab"), tb);
a->setToolTip(getAction(KiwixApp::CloseCurrentTabAction)->toolTip());
tb->setDefaultAction(a);
@ -238,7 +252,7 @@ QSize TabBar::tabSizeHint(int index) const
{
QWidget *w = mp_stackedWidget->widget(index);
if (w && qobject_cast<ContentManagerView*>(w))
if ((w && qobject_cast<ContentManagerView*>(w)) || index >= count() - 1)
return QSize(40, 40); // the "Library" tab is only icon
return QSize(205, 40); // "Settings" and content tabs have text
@ -491,6 +505,24 @@ void TabBar::paintEvent(QPaintEvent *e)
}
}
void TabBar::tabRemoved(int index)
{
QTabBar::tabRemoved(index);
emit tabRemovedSignal(index);
}
void TabBar::tabInserted(int index)
{
QTabBar::tabInserted(index);
emit tabInsertedSignal(index);
}
void TabBar::resizeEvent(QResizeEvent *event)
{
QTabBar::resizeEvent(event);
emit sizeChanged();
}
void TabBar::onTabMoved(int from, int to)
{
// avoid infinitive recursion

View File

@ -52,14 +52,24 @@ public:
QStringList getTabUrls() const;
QStringList getTabZimIds() const;
// The "+" (new tab) button is implemented as a tab (that is always placed at the end).
// This function returns the count of real tabs.
int realTabCount() const;
protected:
void mousePressEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *);
void tabRemoved(int index) override;
void tabInserted(int index) override;
void resizeEvent(QResizeEvent *) override;
signals:
void webActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled);
void tabDisplayed(TabType tabType);
void currentTitleChanged(const QString& title);
void tabRemovedSignal(int index);
void tabInsertedSignal(int index);
void sizeChanged();
public slots:
void closeTab(int index);
@ -69,6 +79,8 @@ public slots:
void on_webview_titleChanged(const QString& title);
void moveToNextTab();
void moveToPreviousTab();
void scrollNextTab();
void scrollPreviousTab();
private:
void setCloseTabButton(int index);
@ -77,10 +89,6 @@ private:
QStackedWidget* mp_stackedWidget;
QScopedPointer<FullScreenWindow> m_fullScreenWindow;
// The "+" (new tab) button is implemented as a tab (that is always placed at the end).
// This function returns the count of real tabs.
int realTabCount() const;
private slots:
void onTabMoved(int from, int to);
void onCurrentChanged(int index);

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>1024</width>
<width>968</width>
<height>576</height>
</rect>
</property>
@ -40,50 +40,122 @@
<number>0</number>
</property>
<item>
<widget class="TabBar" name="tabBar" native="true"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QStackedWidget" name="sideBar">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<layout class="QHBoxLayout" name="tabBarLayout">
<property name="spacing">
<number>0</number>
</property>
<widget class="ContentManagerSide" name="contentmanagerside">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<widget class="ReadingListBar" name="readinglistbar"/>
</widget>
<item>
<widget class="QToolButton" name="prevTabButton">
<property name="maximumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="TabBar" name="tabBar" native="true"/>
</item>
<item>
<widget class="QToolButton" name="newTabSideButton">
<property name="maximumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/kiwix.qrc">
<normaloff>:/icons/new-tab-icon.svg</normaloff>:/icons/new-tab-icon.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="nextTabButton">
<property name="maximumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QStackedWidget" name="mainView">
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QStackedWidget" name="sideBar">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<widget class="ContentManagerSide" name="contentmanagerside">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<widget class="ReadingListBar" name="readinglistbar"/>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="mainView">
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
@ -130,6 +202,8 @@
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="../resources/kiwix.qrc"/>
</resources>
<connections/>
</ui>