mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-24 04:32:15 -04:00
Merge pull request #1057 from kiwix/tab_closing
This commit is contained in:
commit
0a6fd10da2
@ -79,10 +79,12 @@ void KiwixApp::init()
|
||||
setDesktopFileName("kiwix.desktop");
|
||||
setStyleSheet(parseStyleFromFile(":/css/style.css"));
|
||||
|
||||
createAction();
|
||||
createActions();
|
||||
mp_mainWindow = new MainWindow;
|
||||
getTabWidget()->setContentManagerView(mp_manager->getView());
|
||||
getTabWidget()->setNewTabButton();
|
||||
const auto newTabAction = getAction(KiwixApp::NewTabAction);
|
||||
getTabWidget()->setNewTabButton(newTabAction);
|
||||
connect(newTabAction, &QAction::triggered, this, &KiwixApp::newTab);
|
||||
postInit();
|
||||
mp_errorDialog = new QErrorMessage(mp_mainWindow);
|
||||
setActivationWindow(mp_mainWindow);
|
||||
@ -128,6 +130,16 @@ KiwixApp::~KiwixApp()
|
||||
}
|
||||
}
|
||||
|
||||
void KiwixApp::newTab()
|
||||
{
|
||||
getTabWidget()->createNewTab(true, false);
|
||||
auto& searchBar = mp_mainWindow->getTopWidget()->getSearchBar();
|
||||
searchBar.setFocus(Qt::MouseFocusReason);
|
||||
searchBar.clear();
|
||||
searchBar.clearSuggestions();
|
||||
searchBar.hideSuggestions();
|
||||
}
|
||||
|
||||
QString KiwixApp::findLibraryDirectory()
|
||||
{
|
||||
// Check for library.xml in the same directory than the executable (portable kiwix-desktop)
|
||||
@ -340,7 +352,7 @@ void KiwixApp::setMonitorDir(const QString &dir) {
|
||||
#define HIDE_ACTION(ID) mpa_actions[ID]->setVisible(false)
|
||||
#define DISABLE_ACTION(ID) mpa_actions[ID]->setDisabled(true)
|
||||
|
||||
void KiwixApp::createAction()
|
||||
void KiwixApp::createActions()
|
||||
{
|
||||
CREATE_ACTION_ICON_SHORTCUT(KiwixServeAction, "share", gt("local-kiwix-server"), QKeySequence(Qt::CTRL | Qt::Key_I));
|
||||
|
||||
@ -370,8 +382,7 @@ void KiwixApp::createAction()
|
||||
|
||||
CREATE_ACTION_ICON_SHORTCUT(NewTabAction,"new-tab-icon", gt("new-tab"), QKeySequence::AddTab);
|
||||
|
||||
CREATE_ACTION_ICON_SHORTCUTS(CloseTabAction, "close", gt("close-tab"), QList<QKeySequence>({QKeySequence(Qt::CTRL | Qt::Key_F4), QKeySequence(Qt::CTRL | Qt::Key_W)}));
|
||||
mpa_actions[CloseTabAction]->setIconVisibleInMenu(false);
|
||||
CREATE_ACTION_SHORTCUTS(CloseCurrentTabAction, gt("close-tab"), QList<QKeySequence>({QKeySequence(Qt::CTRL | Qt::Key_F4), QKeySequence(Qt::CTRL | Qt::Key_W)}));
|
||||
|
||||
CREATE_ACTION_SHORTCUT(ReopenClosedTabAction, gt("reopen-closed-tab"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_T));
|
||||
HIDE_ACTION(ReopenClosedTabAction);
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
OpenHomePageAction,
|
||||
PrintAction,
|
||||
NewTabAction,
|
||||
CloseTabAction,
|
||||
CloseCurrentTabAction,
|
||||
ReopenClosedTabAction,
|
||||
BrowseLibraryAction,
|
||||
OpenFileAction,
|
||||
@ -89,6 +89,7 @@ public:
|
||||
QString parseStyleFromFile(QString filePath);
|
||||
|
||||
public slots:
|
||||
void newTab();
|
||||
void openZimFile(const QString& zimfile="");
|
||||
void openUrl(const QString& url, bool newTab=true);
|
||||
void openUrl(const QUrl& url, bool newTab=true);
|
||||
@ -98,7 +99,7 @@ public slots:
|
||||
void printVersions(std::ostream& out = std::cout);
|
||||
|
||||
protected:
|
||||
void createAction();
|
||||
void createActions();
|
||||
void postInit();
|
||||
|
||||
private:
|
||||
|
@ -19,7 +19,7 @@ MainMenu::MainMenu(QWidget *parent) :
|
||||
|
||||
m_fileMenu.setTitle(gt("file"));
|
||||
m_fileMenu.ADD_ACTION(NewTabAction);
|
||||
m_fileMenu.ADD_ACTION(CloseTabAction);
|
||||
m_fileMenu.ADD_ACTION(CloseCurrentTabAction);
|
||||
m_fileMenu.ADD_ACTION(ReopenClosedTabAction);
|
||||
m_fileMenu.ADD_ACTION(BrowseLibraryAction);
|
||||
m_fileMenu.ADD_ACTION(OpenFileAction);
|
||||
|
178
src/tabbar.cpp
178
src/tabbar.cpp
@ -13,6 +13,15 @@ class QMenu;
|
||||
#define QUITIFNULL(VIEW) if (nullptr==(VIEW)) { return; }
|
||||
#define CURRENTIFNULL(VIEW) if(nullptr==VIEW) { VIEW = currentZimView();}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
QAction* getAction(KiwixApp::Actions action) {
|
||||
return KiwixApp::instance()->getAction(action);
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
TabBar::TabBar(QWidget *parent) :
|
||||
QTabBar(parent)
|
||||
{
|
||||
@ -24,78 +33,31 @@ TabBar::TabBar(QWidget *parent) :
|
||||
setMovable(true);
|
||||
setIconSize(QSize(30, 30));
|
||||
connect(this, &QTabBar::currentChanged, this, &TabBar::onCurrentChanged, Qt::QueuedConnection);
|
||||
auto app = KiwixApp::instance();
|
||||
|
||||
connect(app->getAction(KiwixApp::NextTabAction), &QAction::triggered, this, &TabBar::moveToNextTab);
|
||||
connect(app->getAction(KiwixApp::PreviousTabAction), &QAction::triggered, this, &TabBar::moveToPreviousTab);
|
||||
connect(app->getAction(KiwixApp::NewTabAction), &QAction::triggered,
|
||||
connect(getAction(KiwixApp::NextTabAction), &QAction::triggered, this, &TabBar::moveToNextTab);
|
||||
connect(getAction(KiwixApp::PreviousTabAction), &QAction::triggered, this, &TabBar::moveToPreviousTab);
|
||||
connect(getAction(KiwixApp::CloseCurrentTabAction), &QAction::triggered,
|
||||
this, [=]() {
|
||||
this->createNewTab(true, false);
|
||||
auto topWidget = KiwixApp::instance()->getMainWindow()->getTopWidget();
|
||||
topWidget->getSearchBar().setFocus(Qt::MouseFocusReason);
|
||||
topWidget->getSearchBar().clear();
|
||||
topWidget->getSearchBar().clearSuggestions();
|
||||
topWidget->getSearchBar().hideSuggestions();
|
||||
});
|
||||
connect(app->getAction(KiwixApp::CloseTabAction), &QAction::triggered,
|
||||
this, [=]() {
|
||||
auto index = currentIndex();
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
// library tab cannot be closed
|
||||
QWidget *w = mp_stackedWidget->widget(index);
|
||||
if (qobject_cast<ContentManagerView*>(w)) {
|
||||
return;
|
||||
}
|
||||
this->closeTab(index);
|
||||
this->closeTab(currentIndex());
|
||||
});
|
||||
connect(app->getAction(KiwixApp::OpenHomePageAction), &QAction::triggered,
|
||||
connect(getAction(KiwixApp::OpenHomePageAction), &QAction::triggered,
|
||||
this, [=]() {
|
||||
auto current = this->currentWebView();
|
||||
QUITIFNULL(current);
|
||||
current->setUrl("zim://" + current->zimId() + ".zim/");
|
||||
});
|
||||
connect(app->getAction(KiwixApp::SettingAction), &QAction::triggered,
|
||||
this, [=]() {
|
||||
SettingsView* view = KiwixApp::instance()->getSettingsManager()->getView();
|
||||
for (int i = 0 ; i < mp_stackedWidget->count(); i++) {
|
||||
if (mp_stackedWidget->widget(i) == view) {
|
||||
setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
int index = currentIndex() + 1;
|
||||
mp_stackedWidget->insertWidget(index, view);
|
||||
emit tabDisplayed(TabType::SettingsTab);
|
||||
insertTab(index,QIcon(":/icons/settings.svg"), gt("settings"));
|
||||
QToolButton *tb = new QToolButton(this);
|
||||
tb->setDefaultAction(KiwixApp::instance()->getAction(KiwixApp::CloseTabAction));
|
||||
setTabButton(index, QTabBar::RightSide, tb);
|
||||
setCurrentIndex(index);
|
||||
});
|
||||
connect(getAction(KiwixApp::SettingAction), &QAction::triggered,
|
||||
this, &TabBar::openOrSwitchToSettingsTab);
|
||||
|
||||
for (int i = 0 ; i <= 9 ; i++) {
|
||||
QAction *a = new QAction(this);
|
||||
a->setData(QVariant::fromValue(i));
|
||||
QKeySequence ks(Qt::ALT | (Qt::Key_0 + i));
|
||||
a->setShortcut(ks);
|
||||
a->setShortcut(QKeySequence(Qt::ALT | (Qt::Key_0 + i)));
|
||||
addAction(a);
|
||||
connect(a, &QAction::triggered, this, [=](){
|
||||
QAction *a = qobject_cast<QAction*>(QObject::sender());
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
bool ok;
|
||||
int tab_n = a->data().toInt(&ok);
|
||||
if (tab_n==0)
|
||||
tab_n=10;
|
||||
if (!ok)
|
||||
return;
|
||||
if (tab_n >= count())
|
||||
return;
|
||||
|
||||
setCurrentIndex(tab_n-1);
|
||||
const int tabIndex = i == 0 ? 9 : i - 1;
|
||||
if (tabIndex < realTabCount()) {
|
||||
setCurrentIndex(tabIndex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -104,6 +66,23 @@ TabBar::TabBar(QWidget *parent) :
|
||||
this, SLOT(onTabMoved(int,int)), Qt::DirectConnection);
|
||||
}
|
||||
|
||||
void TabBar::openOrSwitchToSettingsTab()
|
||||
{
|
||||
SettingsView* view = KiwixApp::instance()->getSettingsManager()->getView();
|
||||
for (int i = 0 ; i < mp_stackedWidget->count(); i++) {
|
||||
if (mp_stackedWidget->widget(i) == view) {
|
||||
setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
int index = currentIndex() + 1;
|
||||
mp_stackedWidget->insertWidget(index, view);
|
||||
emit tabDisplayed(TabType::SettingsTab);
|
||||
insertTab(index,QIcon(":/icons/settings.svg"), gt("settings"));
|
||||
setCloseTabButton(index);
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void TabBar::setStackedWidget(QStackedWidget *widget) {
|
||||
mp_stackedWidget = widget;
|
||||
connect(this, &QTabBar::currentChanged,
|
||||
@ -119,10 +98,10 @@ void TabBar::setContentManagerView(ContentManagerView* view)
|
||||
setTabButton(idx, RightSide, nullptr);
|
||||
}
|
||||
|
||||
void TabBar::setNewTabButton()
|
||||
void TabBar::setNewTabButton(QAction* newTabAction)
|
||||
{
|
||||
QToolButton *tb = new QToolButton();
|
||||
tb->setDefaultAction(KiwixApp::instance()->getAction(KiwixApp::NewTabAction));
|
||||
tb->setDefaultAction(newTabAction);
|
||||
tb->setIcon(QIcon(":/icons/new-tab-icon.svg"));
|
||||
int idx = addTab("");
|
||||
setTabEnabled(idx, false);
|
||||
@ -131,12 +110,12 @@ void TabBar::setNewTabButton()
|
||||
setTabButton(idx, QTabBar::RightSide, Q_NULLPTR);
|
||||
}
|
||||
|
||||
// Returns the count of real tabs with content (excluding the last pseudo-tab
|
||||
// that acts as a button for creating new empty tabs; BTW what is the use for
|
||||
// such empty tabs?)
|
||||
int TabBar::realTabCount() const
|
||||
{
|
||||
// The last tab is "+" in TabBar, but that isn't a real tab which displays any content hence the real count is tab count - 1
|
||||
if (count() < 1)
|
||||
return 0;
|
||||
return count() - 1;
|
||||
return count() < 1 ? 0 : count() - 1;
|
||||
}
|
||||
|
||||
void TabBar::moveToNextTab()
|
||||
@ -151,20 +130,32 @@ void TabBar::moveToPreviousTab()
|
||||
setCurrentIndex(index <= 0 ? realTabCount() - 1 : index - 1);
|
||||
}
|
||||
|
||||
ZimView* TabBar::createNewTab(bool setCurrent, bool adjacentToCurrentTab)
|
||||
void TabBar::setCloseTabButton(int index)
|
||||
{
|
||||
Q_ASSERT(index > 0 && index < realTabCount());
|
||||
|
||||
QToolButton *tb = new QToolButton(this);
|
||||
QAction *a = new QAction(QIcon(":/icons/close.svg"), gt("close-tab"), tb);
|
||||
a->setToolTip(getAction(KiwixApp::CloseCurrentTabAction)->toolTip());
|
||||
tb->setDefaultAction(a);
|
||||
setTabButton(index, QTabBar::RightSide, tb);
|
||||
connect(tb, &QToolButton::triggered, this, [=]() {
|
||||
for ( int i = 0; i < realTabCount(); ++i ) {
|
||||
if ( tb == tabButton(i, QTabBar::RightSide) ) {
|
||||
closeTab(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ZimView* TabBar::createNewTab(bool setCurrent, bool nextToCurrentTab)
|
||||
{
|
||||
auto tab = new ZimView(this, this);
|
||||
int index;
|
||||
if(adjacentToCurrentTab) {
|
||||
index = currentIndex() + 1;
|
||||
} else {
|
||||
index = realTabCount(); // for New Tab Button
|
||||
}
|
||||
const int index = nextToCurrentTab ? currentIndex() + 1 : realTabCount();
|
||||
mp_stackedWidget->insertWidget(index, tab);
|
||||
index = insertTab(index, "");
|
||||
QToolButton *tb = new QToolButton(this);
|
||||
tb->setDefaultAction(KiwixApp::instance()->getAction(KiwixApp::CloseTabAction));
|
||||
setTabButton(index, QTabBar::RightSide, tb);
|
||||
insertTab(index, "");
|
||||
setCloseTabButton(index);
|
||||
if (setCurrent) {
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
@ -265,12 +256,13 @@ void TabBar::triggerWebPageAction(QWebEnginePage::WebAction action, ZimView *wid
|
||||
|
||||
void TabBar::closeTabsByZimId(const QString &id)
|
||||
{
|
||||
// the last tab is + button, skip it
|
||||
for (int i = count() - 2 ; i >= 0 ; i--) {
|
||||
// 0th tab is always (unless this comment becomes outdated by the time you
|
||||
// read it) the library tab, so iteration could start from 1, however we
|
||||
// shouldn't try to save CPU cycles at the cost of the code breaking
|
||||
// should this comment indeed become outdated ;)
|
||||
for (int i = 0 ; i < realTabCount() ; ++i ) {
|
||||
auto *zv = qobject_cast<ZimView*>(mp_stackedWidget->widget(i));
|
||||
if (!zv)
|
||||
continue;
|
||||
if (zv->getWebView()->zimId() == id) {
|
||||
if (zv && zv->getWebView()->zimId() == id) {
|
||||
closeTab(i);
|
||||
}
|
||||
}
|
||||
@ -278,19 +270,16 @@ void TabBar::closeTabsByZimId(const QString &id)
|
||||
|
||||
void TabBar::closeTab(int index)
|
||||
{
|
||||
// the last tab is + button, cannot be closed
|
||||
if (index == this->realTabCount())
|
||||
// The first and last tabs (i.e. the library tab and the + (new tab) button)
|
||||
// cannot be closed
|
||||
if (index <= 0 || index >= this->realTabCount())
|
||||
return;
|
||||
|
||||
setSelectionBehaviorOnRemove(index);
|
||||
|
||||
QWidget *view = mp_stackedWidget->widget(index);
|
||||
|
||||
// library tab cannot be closed
|
||||
if (qobject_cast<ContentManagerView*>(view)) {
|
||||
return;
|
||||
if ( index == currentIndex() ) {
|
||||
setCurrentIndex(index + 1 == realTabCount() ? index - 1 : index + 1);
|
||||
}
|
||||
|
||||
QWidget *view = mp_stackedWidget->widget(index);
|
||||
mp_stackedWidget->removeWidget(view);
|
||||
view->setParent(nullptr);
|
||||
removeTab(index);
|
||||
@ -298,15 +287,6 @@ void TabBar::closeTab(int index)
|
||||
view->deleteLater();
|
||||
}
|
||||
|
||||
void TabBar::setSelectionBehaviorOnRemove(int index)
|
||||
{
|
||||
if (index == count() - 2) {
|
||||
setCurrentIndex(index - 1);
|
||||
} else {
|
||||
setCurrentIndex(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void TabBar::onCurrentChanged(int index)
|
||||
{
|
||||
if (index == -1)
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
void setStackedWidget(QStackedWidget* widget);
|
||||
|
||||
void setContentManagerView(ContentManagerView* view);
|
||||
void setNewTabButton();
|
||||
void setNewTabButton(QAction* newTabAction);
|
||||
ZimView* createNewTab(bool setCurrent, bool adjacentToCurrentTab);
|
||||
|
||||
ZimView* currentZimView() {
|
||||
@ -61,20 +61,23 @@ signals:
|
||||
|
||||
public slots:
|
||||
void closeTab(int index);
|
||||
void openOrSwitchToSettingsTab();
|
||||
void fullScreenRequested(QWebEngineFullScreenRequest request);
|
||||
void on_webview_titleChanged(const QString& title);
|
||||
void moveToNextTab();
|
||||
void moveToPreviousTab();
|
||||
|
||||
private:
|
||||
void setCloseTabButton(int index);
|
||||
|
||||
private:
|
||||
QStackedWidget* mp_stackedWidget;
|
||||
QScopedPointer<FullScreenWindow> m_fullScreenWindow;
|
||||
|
||||
void setSelectionBehaviorOnRemove(int index);
|
||||
// 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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user