Skip to content

Commit

Permalink
Implement closeTab action
Browse files Browse the repository at this point in the history
  • Loading branch information
Yaraslaut committed Sep 29, 2024
1 parent 3d6940c commit 530f1cb
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 42 deletions.
98 changes: 60 additions & 38 deletions src/contour/TerminalSessionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,16 @@ TerminalSession* TerminalSessionManager::createSession()
QQmlEngine::setObjectOwnership(session, QQmlEngine::CppOwnership);

_activeSession = session;
_lastTabChange = std::chrono::steady_clock::now();
return session;
}

void TerminalSessionManager::setSession(size_t index)
{

// QML for some reason sends multiple switch requests in a row, so we need to ignore them.
auto now = std::chrono::steady_clock::now();
if (now - _lastTabSwitch < _timeBetweenTabSwitches)
{
std::cout << "Ignoring switch request due to too frequent switch requests." << std::endl;
managerLog()(fmt::format("SET SESSION: index: {}, _sessions.size(): {}", index, _sessions.size()));
if (!isAllowedToChangeTabs())
return;
}
_lastTabSwitch = now;

std::cout << "Switching to session " << index << std::endl;

auto imageSize = display->pixelSize();
auto pageSize = display->calculatePageSize();
Expand All @@ -85,20 +79,8 @@ void TerminalSessionManager::setSession(size_t index)
}
display->setSession(_activeSession);
display->resizeWindow(imageSize.width, imageSize.height);

_activeSession->terminal().setGuiTabInfoForStatusLine([&]() {
std::string tabInfo;
for (size_t i = 0; i < _sessions.size(); ++i)
{
if (i == index)
tabInfo += "[";
tabInfo += std::to_string(i + 1);
if (i == index)
tabInfo += "]";
tabInfo += " ";
}
return tabInfo;
}());
updateStatusLine();
_lastTabChange = std::chrono::steady_clock::now();
}

void TerminalSessionManager::addSession()
Expand All @@ -108,13 +90,10 @@ void TerminalSessionManager::addSession()

void TerminalSessionManager::previousTab()
{
auto currentSessionIndex = [](auto const& sessions, auto const& activeSession) {
auto i = std::find_if(sessions.begin(), sessions.end(), [&](auto p) { return p == activeSession; });
return i != sessions.end() ? i - sessions.begin() : -1;
}(_sessions, _activeSession);
std::cout << "PREVIOUS: ";
std::cout << "currentSessionIndex: " << currentSessionIndex << ", _sessions.size(): " << _sessions.size()
<< std::endl;
const auto currentSessionIndex = getCurrentSessionIndex();
managerLog()(fmt::format("PREVIOUS TAB: currentSessionIndex: {}, _sessions.size(): {}",
currentSessionIndex,
_sessions.size()));

if (currentSessionIndex > 0)
{
Expand All @@ -124,22 +103,63 @@ void TerminalSessionManager::previousTab()

void TerminalSessionManager::nextTab()
{
auto currentSessionIndex = [](auto const& sessions, auto const& activeSession) {
auto i = std::find_if(sessions.begin(), sessions.end(), [&](auto p) { return p == activeSession; });
return i != sessions.end() ? i - sessions.begin() : -1;
}(_sessions, _activeSession);

std::cout << "NEXT TAB: ";
std::cout << "currentSessionIndex: " << currentSessionIndex << ", _sessions.size(): " << _sessions.size()
<< std::endl;
const auto currentSessionIndex = getCurrentSessionIndex();

managerLog()(fmt::format(
"NEXT TAB: currentSessionIndex: {}, _sessions.size(): {}", currentSessionIndex, _sessions.size()));
if (currentSessionIndex < _sessions.size() - 1)
{
setSession(currentSessionIndex + 1);
}
}

void TerminalSessionManager::closeTab()
{
const auto currentSessionIndex = getCurrentSessionIndex();
managerLog()(fmt::format(
"CLOSE TAB: currentSessionIndex: {}, _sessions.size(): {}", currentSessionIndex, _sessions.size()));

// Session was removed outside of terminal session manager, we need to switch to another tab.
if (currentSessionIndex == -1 && !_sessions.empty())
{
// We need to switch to another tab, so we permit consequent tab changes.
// TODO: This is a bit hacky.
_lastTabChange = std::chrono::steady_clock::now() - std::chrono::seconds(1);
setSession(0);
return;
}

if (_sessions.size() > 1)
{

if (!isAllowedToChangeTabs())
return;

removeSession(*_activeSession);

// We need to switch to another tab, so we permit consequent tab changes.
// TODO: This is a bit hacky.
_lastTabChange = std::chrono::steady_clock::now() - std::chrono::seconds(1);

if (currentSessionIndex <= _sessions.size() - 1)
{
setSession(currentSessionIndex + 1);
}
else
{
setSession(currentSessionIndex - 1);
}
}
}

void TerminalSessionManager::removeSession(TerminalSession& thatSession)
{
managerLog()(fmt::format(
"REMOVE SESSION: session: {}, _sessions.size(): {}", (void*) &thatSession, _sessions.size()));

if (!isAllowedToChangeTabs())
return;

_app.onExit(thatSession); // TODO: the logic behind that impl could probably be moved here.

auto i = std::find_if(_sessions.begin(), _sessions.end(), [&](auto p) { return p == &thatSession; });
Expand All @@ -148,6 +168,8 @@ void TerminalSessionManager::removeSession(TerminalSession& thatSession)
_sessions.erase(i);
}

updateStatusLine();
_lastTabChange = std::chrono::steady_clock::now();
// Notify app if all sessions have been killed to trigger app termination.
}

Expand Down
41 changes: 40 additions & 1 deletion src/contour/TerminalSessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class TerminalSessionManager: public QAbstractListModel

Q_INVOKABLE void previousTab();
Q_INVOKABLE void nextTab();
Q_INVOKABLE void closeTab();
Q_INVOKABLE void setSession(size_t index);

void removeSession(TerminalSession&);
Expand All @@ -48,12 +49,50 @@ class TerminalSessionManager: public QAbstractListModel

private:
std::unique_ptr<vtpty::Pty> createPty();
[[nodiscard]] auto getCurrentSessionIndex() const
{
return [](auto const& sessions, auto const& activeSession) {
auto i =
std::find_if(sessions.begin(), sessions.end(), [&](auto p) { return p == activeSession; });
return i != sessions.end() ? i - sessions.begin() : -1;
}(_sessions, _activeSession);
}

void updateStatusLine()
{
const auto currentSessionIndex = getCurrentSessionIndex();
_activeSession->terminal().setGuiTabInfoForStatusLine([&]() {
std::string tabInfo;
for (size_t i = 0; i < _sessions.size(); ++i)
{
if (i == currentSessionIndex)
tabInfo += "[";
tabInfo += std::to_string(i + 1);
if (i == currentSessionIndex)
tabInfo += "]";
tabInfo += " ";
}
return tabInfo;
}());
}

bool isAllowedToChangeTabs()
{
// QML for some reason sends multiple signals requests in a row, so we need to ignore them.
auto now = std::chrono::steady_clock::now();
if (abs(now - _lastTabChange) < _timeBetweenTabSwitches)
{
managerLog()("Ignoring change request due to too frequent change requests.");
return false;
}
return true;
}

ContourGuiApp& _app;
std::chrono::seconds _earlyExitThreshold;
TerminalSession* _activeSession = nullptr;
std::vector<TerminalSession*> _sessions;
std::chrono::time_point<std::chrono::steady_clock> _lastTabSwitch;
std::chrono::time_point<std::chrono::steady_clock> _lastTabChange;
std::chrono::milliseconds _timeBetweenTabSwitches { 300 };
};

Expand Down
2 changes: 1 addition & 1 deletion src/contour/display/TerminalDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ TerminalDisplay::~TerminalDisplay()

void TerminalDisplay::setSession(TerminalSession* newSession)
{
fmt::print("TerminalDisplay::setSession: {} -> {}\n", (void*) _session, (void*) newSession);
displayLog()("TerminalDisplay::setSession: {} -> {}\n", (void*) _session, (void*) newSession);
if (_session == newSession)
return;

Expand Down
2 changes: 1 addition & 1 deletion src/contour/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ auto inline const displayLog =
auto inline const inputLog =
logstore::category("gui.input", "Logs input driver details (e.g. GUI input events).");
auto inline const sessionLog = logstore::category("gui.session", "VT terminal session logs");

auto inline const managerLog = logstore::category("gui.session_manager", "Sessions manager logs");
namespace detail
{
template <typename F>
Expand Down
6 changes: 5 additions & 1 deletion src/contour/ui.template/Terminal.qml.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ContourTerminal

onPreviousTab: terminalSessions.previousTab()
onNextTab: terminalSessions.nextTab()
onCloseTab: terminalSessions.closeTab()

Rectangle {
id : backgroundColor
Expand Down Expand Up @@ -186,7 +187,10 @@ ContourTerminal

onTerminated: {
console.log("Client process terminated. Closing the window.");
Window.window.close(); // https://stackoverflow.com/a/53829662/386670
if (terminalSessions.count == 0)
Window.window.close(); // https://stackoverflow.com/a/53829662/386670
else
terminalSessions.closeTab();
}

function playBell(volume) {
Expand Down

0 comments on commit 530f1cb

Please sign in to comment.