mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-21 02:51:26 -04:00
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:
commit
93ebec0b39
@ -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
|
||||
*/
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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."
|
||||
}
|
||||
|
1
resources/icons/caret-left-solid.svg
Normal file
1
resources/icons/caret-left-solid.svg
Normal 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 |
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -64,6 +64,8 @@ public:
|
||||
ExitAction,
|
||||
ExportReadingListAction,
|
||||
ImportReadingListAction,
|
||||
ScrollPreviousTabAction,
|
||||
ScrollNextTabAction,
|
||||
MAX_ACTION
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -37,6 +37,7 @@ private slots:
|
||||
void readingListToggled(bool state);
|
||||
void hideTabAndTop();
|
||||
void showTabAndTop();
|
||||
void updateTabButtons();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *mp_ui;
|
||||
|
@ -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
|
||||
|
16
src/tabbar.h
16
src/tabbar.h
@ -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);
|
||||
|
150
ui/mainwindow.ui
150
ui/mainwindow.ui
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user