Skip to content

Commit

Permalink
Add Improved GuiTabline
Browse files Browse the repository at this point in the history
Uses new Neovim API:
neovim/neovim#12481

Adds QTabBars for both vim-tabs and vim-buffers.

Also includes general UI improvements:
 - Tab close buttons
 - Tab filetype icons
  • Loading branch information
jgehrig committed Aug 10, 2021
1 parent d6e8c18 commit 4212ee1
Show file tree
Hide file tree
Showing 10 changed files with 614 additions and 211 deletions.
1 change: 1 addition & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ add_library(neovim-qt-gui
popupmenumodel.cpp
scrollbar.cpp
shell.cpp
tabline.cpp
treeview.cpp
${SRCS_PLATFORM}
${NEOVIM_RCC_SOURCES})
Expand Down
133 changes: 10 additions & 123 deletions src/gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ static QString DefaultWindowTitle() noexcept
return "Neovim";
}

MainWindow::MainWindow(NeovimConnector* c, QWidget* parent)
: QMainWindow(parent)
MainWindow::MainWindow(NeovimConnector* c, QWidget* parent) noexcept
: QMainWindow{ parent }
, m_tabline{ *c, this }
, m_defaultFont{ font() }
, m_defaultPalette{ palette() }
{
Expand Down Expand Up @@ -42,24 +43,7 @@ void MainWindow::init(NeovimConnector *c)

m_shell = new Shell(c);

m_tabline_bar = addToolBar("tabline");
m_tabline_bar->setObjectName("tabline");
m_tabline_bar->setAllowedAreas(Qt::TopToolBarArea);
m_tabline_bar->setMovable(false);
m_tabline_bar->setFloatable(false);
// Avoid margins around the tabbar
m_tabline_bar->layout()->setContentsMargins(0, 0, 0, 0);

m_tabline = new QTabBar(m_tabline_bar);
m_tabline->setDrawBase(false);
m_tabline->setExpanding(false);
m_tabline->setDocumentMode(true);
m_tabline->setFocusPolicy(Qt::NoFocus);
connect(m_tabline, &QTabBar::currentChanged,
this, &MainWindow::changeTab);

m_tabline_bar->addWidget(m_tabline);
m_tabline_bar->setVisible(m_shell->GetShellOptions().IsTablineEnabled());
addToolBar(&m_tabline);

// Context menu and actions for right-click
m_contextMenu = new QMenu();
Expand Down Expand Up @@ -123,12 +107,6 @@ void MainWindow::init(NeovimConnector *c)
this, &MainWindow::neovimError);
connect(m_shell, &Shell::neovimIsUnsupported,
this, &MainWindow::neovimIsUnsupported);
connect(m_shell, &Shell::neovimExtTablineSet,
this, &MainWindow::extTablineSet);
connect(m_shell, &Shell::neovimTablineUpdate,
this, &MainWindow::neovimTablineUpdate);
connect(m_shell, &Shell::neovimShowtablineSet,
this, &MainWindow::neovimShowtablineSet);
connect(m_shell, &Shell::neovimShowContextMenu,
this, &MainWindow::neovimShowContextMenu);
connect(m_actCut, &QAction::triggered,
Expand Down Expand Up @@ -331,95 +309,18 @@ void MainWindow::handleNeovimAttachment(bool attached)
{
emit neovimAttachmentChanged(attached);

if (attached) {
if (isWindow() && m_shell != NULL) {
m_shell->updateGuiWindowState(windowState());
}
} else {
m_tabline->deleteLater();
m_tabline_bar->deleteLater();
}
}

Shell* MainWindow::shell()
{
return m_shell;
}

void MainWindow::extTablineSet(bool val)
{
ShellOptions& shellOptions{ m_shell->GetShellOptions() };

// We can ignore events where the value does not change.
if (val == shellOptions.IsTablineEnabled()) {
if (!attached) {
return;
}

shellOptions.SetIsTablineEnabled(val);
m_nvim->api0()->vim_command("silent! redraw!");
m_tabline_bar->setVisible(val);
}

void MainWindow::neovimShowtablineSet(int val)
{
m_shell->GetShellOptions().SetOptionShowTabline(val);
if (m_shell && isWindow()) {
m_shell->updateGuiWindowState(windowState());
}
}

void MainWindow::neovimTablineUpdate(int64_t curtab, QList<Tab> tabs)
Shell* MainWindow::shell()
{
if (!m_shell->GetShellOptions().IsTablineEnabled()) {
return;
}

// remove extra tabs
for (int index=tabs.size(); index<m_tabline->count(); index++) {
m_tabline->removeTab(index);
}

for (int index=0; index<tabs.size(); index++) {
// Escape & in tab name otherwise it will be interpreted as
// a keyboard shortcut (#357) - escaping is done using &&
QString text = tabs[index].name;
text.replace("&", "&&");

if (m_tabline->count() <= index) {
m_tabline->addTab(text);
} else {
m_tabline->setTabText(index, text);
}

m_tabline->setTabToolTip(index, text);
m_tabline->setTabData(index, QVariant::fromValue(tabs[index].tab));

if (curtab == tabs[index].tab) {
m_tabline->setCurrentIndex(index);
}
}

Q_ASSERT(tabs.size() == m_tabline->count());

switch(m_shell->GetShellOptions().GetOptionShowTabline())
{
// Never show tabline
case 0:
m_tabline_bar->setVisible(false);
break;

// Show tabline for two or more tabs.
case 1:
m_tabline_bar->setVisible(tabs.size() >= 2);
break;

// Always show tabline
case 2:
m_tabline_bar->setVisible(true);
break;

// Fallback: show tabline for two or more tabs
default:
m_tabline_bar->setVisible(tabs.size() >= 2);
break;
}
return m_shell;
}

void MainWindow::neovimShowContextMenu()
Expand Down Expand Up @@ -447,20 +348,6 @@ void MainWindow::neovimSendSelectAll()
m_nvim->api0()->vim_command("normal! ggVG");
}

void MainWindow::changeTab(int index)
{
if (!m_shell->GetShellOptions().IsTablineEnabled()) {
return;
}

if (m_nvim->api2() == NULL) {
return;
}

int64_t tab = m_tabline->tabData(index).toInt();
m_nvim->api2()->nvim_set_current_tabpage(tab);
}

void MainWindow::saveWindowGeometry()
{
QSettings settings{ "window-geometry" };
Expand Down
18 changes: 5 additions & 13 deletions src/gui/mainwindow.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
#ifndef NEOVIM_QT_MAINWINDOW
#define NEOVIM_QT_MAINWINDOW
#pragma once

#include <QMainWindow>
#include <QPalette>
#include <QSplitter>
#include <QCloseEvent>
#include <QStackedWidget>
#include <QTabBar>

#include "errorwidget.h"
#include "neovimconnector.h"
#include "scrollbar.h"
#include "shell.h"
#include "tabline.h"
#include "treeview.h"

namespace NeovimQt {
Expand All @@ -27,7 +26,7 @@ class MainWindow: public QMainWindow
FullScreen,
};

MainWindow(NeovimConnector *, QWidget *parent=0);
MainWindow(NeovimConnector* c, QWidget* parent = nullptr) noexcept;

bool isNeovimAttached() const noexcept { return m_shell && m_shell->isNeovimAttached(); }

Expand Down Expand Up @@ -60,15 +59,11 @@ private slots:
void showIfDelayed();
void handleNeovimAttachment(bool);
void neovimIsUnsupported();
void neovimShowtablineSet(int);
void neovimTablineUpdate(int64_t curtab, QList<NeovimQt::Tab> tabs);
void neovimShowContextMenu();
void neovimSendCut();
void neovimSendCopy();
void neovimSendPaste();
void neovimSendSelectAll();
void extTablineSet(bool);
void changeTab(int index);
void saveWindowGeometry();

// GuiAdaptive Color/Font/Style Slots
Expand All @@ -87,8 +82,6 @@ private slots:
Shell* m_shell{ nullptr };
DelayedShow m_delayedShow{ DelayedShow::Disabled };
QStackedWidget m_stack;
QTabBar* m_tabline{ nullptr };
QToolBar* m_tabline_bar{ nullptr };

bool m_neovim_requested_close{ false };
QMenu* m_contextMenu{ nullptr };
Expand All @@ -97,6 +90,7 @@ private slots:
QAction* m_actPaste{ nullptr };
QAction* m_actSelectAll{ nullptr };
ScrollBar* m_scrollbar{ nullptr };
Tabline m_tabline;
int m_exitStatus{ 0 };

// GuiAdaptive Color/Font/Style
Expand All @@ -111,6 +105,4 @@ private slots:
void updateAdaptiveFont() noexcept;
};

} // Namespace

#endif
} // namespace NeovimQt
38 changes: 10 additions & 28 deletions src/gui/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,30 +562,8 @@ void Shell::handleRedraw(const QByteArray& name, const QVariantList& opargs)
handleBusy(true);
} else if (name == "busy_stop"){
handleBusy(false);
} else if (name == "tabline_update") {
if (opargs.size() < 2 || !opargs.at(0).canConvert<int64_t>()) {
qWarning() << "Unexpected argument for tabline_update:" << opargs;
return;
}
int64_t curtab = opargs.at(0).toInt();
QList<Tab> tabs;
foreach(const QVariant& tabv, opargs.at(1).toList()) {
QVariantMap tab = tabv.toMap();

if (!tab.contains("tab") || !tab.contains("name")) {
qWarning() << "Unexpected tab value in tabline_update:" << tab;
}

int64_t num = tab.value("tab").toInt();
QString name = tab.value("name").toString();
tabs.append(Tab(num, name));
}

emit neovimTablineUpdate(curtab, tabs);
} else if (name == "option_set") {
if (2 <= opargs.size()) {
handleSetOption(opargs.at(0).toString(), opargs.at(1));
}
handleSetOption(opargs);
} else if (name == "suspend") {
if (isWindow()) {
setWindowState(windowState() | Qt::WindowMinimized);
Expand Down Expand Up @@ -942,18 +920,22 @@ void Shell::handleExtGuiOption(const QString& name, const QVariant& value)
}
}

void Shell::handleSetOption(const QString& name, const QVariant& value)
void Shell::handleSetOption(const QVariantList& opargs)
{
if (opargs.size() < 2 || !opargs.at(0).canConvert<QString>()) {
qWarning() << "Unexpected arguments for option_set:" << opargs;
return;
}

const QString name{ opargs.at(0).toString() };
const QVariant& value{ opargs.at(1) };

if (name == "guifont") {
setGuiFont(value.toString(), false /*force*/);
} else if (name == "guifontwide") {
handleGuiFontWide(value);
} else if (name == "linespace") {
handleLineSpace(value);
} else if (name == "showtabline") {
emit neovimShowtablineSet(value.toString().toInt());
} else if (name == "ext_tabline") {
emit neovimExtTablineSet(value.toBool());
} else {
// Uncomment for writing new event handling code.
// qDebug() << "Received unknown option" << name << value;
Expand Down
36 changes: 9 additions & 27 deletions src/gui/shell.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#ifndef NEOVIM_QT_SHELL
#define NEOVIM_QT_SHELL

#include <QWidget>
#include <QVariantList>
#include <QFont>
#pragma once
#include <QBackingStore>
#include <QFont>
#include <QLabel>
#include <QTimer>
#include <QUrl>
#include <QList>
#include <QMap>
#include <QMenu>
#include <QTimer>
#include <QUrl>
#include <QVariantList>
#include <QWidget>

#include "neovimconnector.h"
#include "popupmenu.h"
Expand All @@ -19,20 +17,10 @@
#include "shellwidget/cursor.h"
#include "shellwidget/highlight.h"
#include "shellwidget/shellwidget.h"
#include "tab.h"

namespace NeovimQt {

class Tab {
public:
Tab(int64_t id, QString name) {
this->tab = id;
this->name = name;
}
/// The tab handle, a unique tab identifier
int64_t tab;
QString name;
};

class Shell: public ShellWidget
{
Q_OBJECT
Expand Down Expand Up @@ -95,11 +83,6 @@ class Shell: public ShellWidget
void neovimGuiCloseRequest(int status = 0);
/// This signal is emmited if the running neovim version is unsupported by the GUI
void neovimIsUnsupported();
void neovimExtTablineSet(bool);
/// The tabline needs updating. curtab is the handle of the current tab (not its index)
/// as seen in Tab::tab.
void neovimTablineUpdate(int64_t curtab, QList<NeovimQt::Tab> tabs);
void neovimShowtablineSet(int);
void neovimShowContextMenu();
void colorsChanged();

Expand Down Expand Up @@ -159,7 +142,7 @@ protected slots:
virtual void handleSetTitle(const QVariantList& opargs);
virtual void handleSetScrollRegion(const QVariantList& opargs);
virtual void handleBusy(bool);
virtual void handleSetOption(const QString& name, const QVariant& value);
virtual void handleSetOption(const QVariantList& opargs);
void handleExtGuiOption(const QString& name, const QVariant& value);
virtual void handlePopupMenuShow(const QVariantList& opargs);
virtual void handlePopupMenuSelect(const QVariantList& opargs);
Expand Down Expand Up @@ -288,5 +271,4 @@ template <class T>
}
}

} // Namespace
#endif
} // namespace NeovimQtj
Loading

0 comments on commit 4212ee1

Please # to comment.