Commit 29e86dde authored by Lucas Biaggi's avatar Lucas Biaggi Committed by Kurt Hindenburg
Browse files

Add ability to load/save session layouts(split views) and add default layouts

Add three layouts to the toolbar; add --layout <file> to the command line.
The 3 defaults layouts are 2x2, 2x1, 1x2

GUI:
parent 22e7a1aa
add_subdirectory( color-schemes )
add_subdirectory( keyboard-layouts )
add_subdirectory( layouts )
install( FILES konsole.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
{
"Orientation": "Vertical",
"Widgets": [
{
"Orientation": "Horizontal",
"Widgets": [
{
"SessionRestoreId": 0
}
]
},
{
"Orientation": "Horizontal",
"Widgets": [
{
"SessionRestoreId": 0
},
{
"SessionRestoreId": 0
}
]
}
]
}
{
"Orientation": "Vertical",
"Widgets": [
{
"Orientation": "Horizontal",
"Widgets": [
{
"SessionRestoreId": 0
},
{
"SessionRestoreId": 0
}
]
},
{
"Orientation": "Horizontal",
"Widgets": [
{
"SessionRestoreId": 0
}
]
}
]
}
{
"Orientation": "Vertical",
"Widgets": [
{
"Orientation": "Horizontal",
"Widgets": [
{
"SessionRestoreId": 0
},
{
"SessionRestoreId": 0
}
]
},
{
"Orientation": "Horizontal",
"Widgets": [
{
"SessionRestoreId": 0
},
{
"SessionRestoreId": 0
}
]
}
]
}
install (FILES
1x2-terminals.json
2x1-terminals.json
2x2-terminals.json
DESTINATION
${KDE_INSTALL_DATADIR}/konsole)
<?xml version="1.0"?>
<!DOCTYPE gui SYSTEM "kpartgui.dtd">
<gui name="konsole" version="13">
<gui name="konsole" version="14">
<MenuBar>
<Menu name="file"><text>File</text>
<Action name="new-window"/>
......@@ -29,6 +29,8 @@
<Separator/>
<Action name="detach-tab" />
<Action name="detach-view"/>
<Action name="save-layout"/>
<Action name="load-layout"/>
<Separator/>
<DefineGroup name="session-view-operations"/>
</Menu>
......@@ -53,5 +55,8 @@
<Action name="new-tab"/>
<Action name="split-view-left-right"/>
<Action name="split-view-top-bottom"/>
<Action name="load-terminals-layout-2x2"/>
<Action name="load-terminals-layout-2x1"/>
<Action name="load-terminals-layout-1x2"/>
</ToolBar>
</gui>
......@@ -51,7 +51,11 @@ void Application::populateCommandLineParser(QCommandLineParser *parser)
i18nc("@info:shell", "Name of profile to use for new Konsole instance"),
QStringLiteral("name")
},
{ { QStringLiteral("fallback-profile") },
{ { QStringLiteral("layout") },
i18nc("@info:shell", "json layoutfile to be loaded to use for new Konsole instance"),
QStringLiteral("file")
},
{ { QStringLiteral("fallback-profile") },
i18nc("@info:shell", "Use the internal FALLBACK profile")
},
{ { QStringLiteral("workdir") },
......@@ -210,7 +214,6 @@ int Application::newInstance()
return 0;
}
}
// select profile to use
Profile::Ptr baseProfile = processProfileSelectArgs();
......@@ -218,14 +221,20 @@ int Application::newInstance()
// selected profile to be changed
Profile::Ptr newProfile = processProfileChangeArgs(baseProfile);
// create new session
Session *session = window->createSession(newProfile, QString());
// if layout file is enable load it and create session from definitions,
// else create new session
if (m_parser->isSet(QStringLiteral("layout"))) {
window->viewManager()->loadLayout(m_parser->value(QStringLiteral("layout")));
} else {
Session *session = window->createSession(newProfile, QString());
if (m_parser->isSet(QStringLiteral("noclose"))) {
session->setAutoClose(false);
if (m_parser->isSet(QStringLiteral("noclose"))) {
session->setAutoClose(false);
}
}
// if the background-mode argument is supplied, start the background
// if the background-mode argument is supplied, start the background
// session ( or bring to the front if it already exists )
if (m_parser->isSet(QStringLiteral("background-mode"))) {
startBackgroundMode(window);
......
......@@ -377,6 +377,20 @@ void MainWindow::setupActions()
menuAction->setText(i18nc("@item", "Activate Menu"));
collection->setDefaultShortcut(menuAction, Konsole::ACCEL | Qt::SHIFT | Qt::Key_F10);
connect(menuAction, &QAction::triggered, this, &Konsole::MainWindow::activateMenuBar);
auto action = collection->addAction(QStringLiteral("save-layout"));
action->setEnabled(true);
action->setText(i18nc("@action:inmenu", "Save tab layout to file"));
connect(action, &QAction::triggered, this, [this]() {
if (viewManager()) { viewManager()->saveLayoutFile(); }
});
action = collection->addAction(QStringLiteral("load-layout"));
action->setEnabled(true);
action->setText(i18nc("@action:inmenu", "Load tab layout from file"));
connect(action, &QAction::triggered, this, [this]() {
if (viewManager()) { viewManager()->loadLayoutFile(); }
});
}
void MainWindow::viewFullScreen(bool fullScreen)
......
......@@ -12,9 +12,17 @@
// Qt
#include <QStringList>
#include <QTabBar>
#include <QStandardPaths>
#include <QFile>
#include <QFileDialog>
#include <QJsonArray>
#include <QJsonDocument>
// KDE
#include <KLocalizedString>
#include <KMessageBox>
#include <KActionCollection>
#include <KConfigGroup>
......@@ -113,6 +121,30 @@ void ViewManager::setupActions()
collection->setDefaultShortcut(action, Konsole::ACCEL | Qt::Key_ParenRight);
collection->addAction(QStringLiteral("split-view-top-bottom"), action);
action = new QAction(this);
action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")));
action->setText(i18nc("@action:inmenu", "Load a new tab with layout 2x2 terminals"));
connect(action, &QAction::triggered,
this, [this](){
this->loadLayout(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("konsole/2x2-terminals.json"))); });
collection->addAction(QStringLiteral("load-terminals-layout-2x2"), action);
action = new QAction(this);
action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right")));
action->setText(i18nc("@action:inmenu", "Load a new tab with layout 2x1 terminals"));
connect(action, &QAction::triggered,
this, [this](){
this->loadLayout(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("konsole/2x1-terminals.json"))); });
collection->addAction(QStringLiteral("load-terminals-layout-2x1"), action);
action = new QAction(this);
action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")));
action->setText(i18nc("@action:inmenu", "Load a new tab with layout 2x1 terminals"));
connect(action, &QAction::triggered,
this, [this](){
this->loadLayout(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("konsole/1x2-terminals.json"))); });
collection->addAction(QStringLiteral("load-terminals-layout-1x2"), action);
action = new QAction(this);
action->setText(i18nc("@action:inmenu", "Expand View"));
action->setEnabled(false);
......@@ -134,6 +166,7 @@ void ViewManager::setupActions()
action->setIcon(QIcon::fromTheme(QStringLiteral("tab-detach")));
action->setText(i18nc("@action:inmenu", "Detach Current &View"));
connect(action, &QAction::triggered, this, &ViewManager::detachActiveView);
_multiSplitterOnlyActions << action;
......@@ -895,6 +928,23 @@ QJsonObject saveSessionsRecurse(QSplitter *splitter) {
} // namespace
void ViewManager::saveLayoutFile() {
QFile file(QFileDialog::getSaveFileName(this->widget(), i18n("Save File"), QStringLiteral("~/"),
i18n("Konsole View Layout (*.json)")));
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
KMessageBox::sorry(this->widget(), i18n("A problem occurred when saving the Layout.\n%1", file.fileName()));
}
QJsonObject jsonSplit = saveSessionsRecurse(_viewContainer->activeViewSplitter());
if (!jsonSplit.isEmpty()){
file.write(QJsonDocument(jsonSplit).toJson());
qDebug() << "Maybe was saved";
}
}
void ViewManager::saveSessions(KConfigGroup &group)
{
QJsonArray rootArray;
......@@ -909,7 +959,7 @@ void ViewManager::saveSessions(KConfigGroup &group)
namespace {
ViewSplitter *restoreSessionsSplitterRecurse(const QJsonObject& jsonSplitter, ViewManager *manager)
ViewSplitter *restoreSessionsSplitterRecurse(const QJsonObject& jsonSplitter, ViewManager *manager, bool useSessionId)
{
const QJsonArray splitterWidgets = jsonSplitter[QStringLiteral("Widgets")].toArray();
auto orientation = (jsonSplitter[QStringLiteral("Orientation")].toString() == QStringLiteral("Horizontal"))
......@@ -923,11 +973,14 @@ ViewSplitter *restoreSessionsSplitterRecurse(const QJsonObject& jsonSplitter, Vi
const auto sessionIterator = widgetJsonObject.constFind(QStringLiteral("SessionRestoreId"));
if (sessionIterator != widgetJsonObject.constEnd()) {
Session *session = SessionManager::instance()->idToSession(sessionIterator->toInt());
Session *session = useSessionId
? SessionManager::instance()->idToSession(sessionIterator->toInt())
: SessionManager::instance()->createSession();
auto newView = manager->createView(session);
currentSplitter->addWidget(newView);
} else {
auto nextSplitter = restoreSessionsSplitterRecurse(widgetJsonObject, manager);
auto nextSplitter = restoreSessionsSplitterRecurse(widgetJsonObject, manager, useSessionId);
currentSplitter->addWidget(nextSplitter);
}
}
......@@ -935,12 +988,30 @@ ViewSplitter *restoreSessionsSplitterRecurse(const QJsonObject& jsonSplitter, Vi
}
} // namespace
void ViewManager::loadLayout(QString file) {
QFile jsonFile(file);
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
KMessageBox::sorry(this->widget(), i18n("A problem occurred when loading the Layout.\n%1", jsonFile.fileName()));
}
auto json = QJsonDocument::fromJson(jsonFile.readAll());
if (!json.isEmpty()){
auto splitter = restoreSessionsSplitterRecurse(json.object(), this, false);
_viewContainer->addSplitter(splitter, _viewContainer->count());
}
}
void ViewManager::loadLayoutFile() {
loadLayout(QFileDialog::getOpenFileName(this->widget(), i18n("Open File"), QStringLiteral("~/"),
i18n("Konsole View Layout (*.json)")));
}
void ViewManager::restoreSessions(const KConfigGroup &group)
{
const auto tabList = group.readEntry("Tabs", QByteArray("[]"));
const auto jsonTabs = QJsonDocument::fromJson(tabList).array();
for (const auto& jsonSplitter : jsonTabs) {
auto topLevelSplitter = restoreSessionsSplitterRecurse(jsonSplitter.toObject(), this);
auto topLevelSplitter = restoreSessionsSplitterRecurse(jsonSplitter.toObject(), this, true);
_viewContainer->addSplitter(topLevelSplitter, _viewContainer->count());
}
......
......@@ -307,6 +307,11 @@ public Q_SLOTS:
/** DBus slot that sets ALL tabs' width to match their text */
Q_SCRIPTABLE void setTabWidthToText(bool);
// Creates json file with split config
Q_SCRIPTABLE void saveLayoutFile();
Q_SCRIPTABLE void loadLayoutFile();
Q_SCRIPTABLE void loadLayout(QString File);
private Q_SLOTS:
// called when the "Split View Left/Right" menu item is selected
void splitLeftRight();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment