SUMMARY:    Original plan for split-screen design in Konsole
AUTHOR:     Robert Knight < robertknight@gmail.com >
UPDATED:    Tuesday 26/12/06


Konsole Split-View Design Plan
==============================

The ability to split the view, so that more than one session
can be viewed at once is Konsole's most requested feature.

This document discusses the proposed design which aims to clean
up the code in the main Konsole class, make handling of settings
from all sorts of sources easier and ultimately allow for 
a clean implementation of split view in Konsole.


UI Design
=========
The UI involves two menu items and a splitter widget.  When Konsole starts up,
it will look the same as it does in KDE 3.x

To split the view, the user selects the new 'View -> Split Horizontally' menu option.
To the user, Konsole then appears to duplicate the existing display area (tabs + display
widgets) and put one in the top half of the Konsole window, and one in the bottom half.

A standard splitter appears between the two which the user can drag with the mouse 
(or possibly move using a keyboard shortcut) to alter the relative size of each
display area.

To close one of the views, the user selects the new 'View -> Close Active View' menu option.
The display area which currently has the focus is then removed.

If a user creates a new session whilst there are multiple views, a new tab will be added
to each view in the same window.

Each view can be scrolled independantly, that is, it should be possible to display the 
most recent output from a session in one view area at the bottom of the Konsole window.
and older output from that same session in another view area at the top of the Konsole window.

A view can be detached from the window so that it appears in a new window by right-clicking
on the tab and selecting 'Detach Session'.  In this case the session disappears from
the view containing that tab and reappears in a new Konsole window which contains
just that session.
Other views in the 'old' window are not affected (ie. the session tab will still be visible
in them).
In this way it is possible to display the same session in different windows.


Cleaner Session Management
==========================
As already mentioned in the code, creation and management of new sessions
will be moved into a new class, SessionManager.  There is one SessionManager per
application.

The SessionManager provides a method to set default settings for new sessions that
are created.  These methods will also have a parameter that specifies
where the setting came from.  When a new session is created, for each setting, SessionManager
will pick the one from the most important source.
The idea is that the application will behave consistantly and follow the principle of least
surprise.

eg.  if the following code was executed:

     sessionManager()->addSetting( SessionManager::DefaultFont , SessionManager::CommandLine , fontA );
     sessionManager()->addSetting( SessionManager::DefaultFont , SessionManager::SessionConfig , fontB );
     sessionManager()->addSetting( SessionManager::DefaultFont , SessionManager::GlobalSettings , fontC );

when session manager came to create a new session, it would use
fontA, because that setting came from the source with the highest priority.

It is also possible to have single-shot sources of settings which are only 
considered for the next session which is created and then discarded after that.

eg. 
    sessionManager()->addSetting( SessionManager::InitialDir , SessionManager::KonsoleDefault , getenv("HOME") );
    sessionManager()->addSetting( SessionManager::SingleShot , path );

If two sessions were created after this, the first would start in directory 'path',
and the second would start in the user's home directory.

The code which supplies the setting does not have to check whether there is already
a setting there and whether that setting came from a more important source or not.

The priority given to various sources of settings should be consistant for all settings.

If a setting is added with the same source as an existing setting, it over-writes that 
setting.


Connecting Multiple Views to a Running Session
==============================================

Konsole for KDE 3.x allows one view to be connected to each session.  Extending this 
proved fairly simple since the display widget and the terminal emulation are nicely
decoupled already.

One slightly tricky issue is what to do if there are multiple views of the same session
which are different sizes and visible at the same time - since the terminal
emulation assumes a single screen image and therefore a single size.

My current thought is that the size of the smallest visible display would be used in such 
a case.

For simplicity, the same font settings, colour schemes and keyboard setups should be used
for all views of the same session.

The new API for creating sessions looks like this:

TESession* session = sessionManager()->createSession( configPath );
TEWidget* display = new TEWidget(parent);

session->addView(display);

As with KDE 3.x, the display does not know anything about the emulations to which it is connected
and from whom it receives screen image updates.



View Splitters and Containers
=================================
In the old design there is a single tab widget per Konsole window which holds
all of the terminal displays in that window

In the new design the main window contains a view splitter (ViewSplitter class) derived from QSplitter.
A view splitter widget can contain one or more view containers (ViewContainer interface).  View containers are widgets which hold
one or more terminal displays and provide some means for the user to navigate between them (such as
tabs or a list).  View splitter widgets can also hold view splitter children, allowing for a hierarchy
of view splitters and containers.



                                --> [ Terminal Display ] 
             -->  ViewContainer --> [ Terminal Display ]
                                --> [ Terminal Display ]
                                
                                --> ViewContainer --> [ Terminal Display ]
ViewSplitter -->  ViewSplitter  --> ViewContainer --> [ Terminal Display ] 

The existing tab widget which is used to navigate between displays in a Konsole window will be replaced
with a TabbedViewContainer class.

The reason for allowing different types of view container is that tabs have some shortcomings as a way of viewing
the active terminal displays and switching between them - it would be useful
to have the possibility of introducing a replacement or alternative in the future.

Moving the view management out of the main window should cut down lots of code
related to handling signals and slots for various UI actions in the main Konsole window.


Related Cleanup
===============
The API for color schemes and keyboard setups may be changed as part of this.
I don't plan to touch the internals yet though.

If changes do happen, will be post-KDE 4.x.  As a result,
color schemes and keytab files from Konsole for KDE 3.x should work (at least to some
extent) in KDE 4.0, even though the code in keytab.cpp is responsible for the death
of many cute and fluffy creatures.


