Commit 47d2f314 authored by Robert Knight's avatar Robert Knight

Experiment with a new view container which uses a list-view (like Kate) to...

Experiment with a new view container which uses a list-view (like Kate) to display the sessions instead of tabs.  Document a number of crashes and other bugs which need to be fixed before continuing further.

svn path=/branches/work/konsole-split-view/; revision=621029
parent ab076394
......@@ -117,7 +117,8 @@ set(konsolepart_PART_SRCS
TEHistory.cpp
KeyTrans.cpp
TerminalCharacterDecoder.cpp
SessionManager.cpp )
SessionManager.cpp
Filter.cpp )
kde4_automoc(${konsolepart_PART_SRCS})
......
Monday - 8th Jan 07
===================
- More reliable syncing of menus when selected view changes.
Currently the _pluggedController in ViewManager is only changed if the newly
selected view gets the focus, and that might not happen automatically in some circumstances.
Add a signal to ViewContainer which is emitted when the selected view changes.
- Calling viewRemoved() in ViewContainer::viewDestroyed() causes crashes at exit.
Start Konsole, create several shells then click X button on main window to close --> crash.
Debug this.
- Midnight Commander not always set to the right size when creating a new view
- Using ListViewContainer as view container:
1. Create a new shell
2. Split the view
3. Detach the view
4. In the newly created main window, select View -> Merge Windows
5. The new main window now has two list view items for the same terminal display (as expected)
6. Trying to activate the second entry in the list causes a crash
- Using ListViewContainer as view container:
1. Create a new shell
2. Split the view
3. Unsplit the view using View -> Remove split. Causes a crash
- Cannot create a selection when the view is split.
1. Create a new shell
2. Split the view
3. Try to select a block of text with the mouse in one of the views
4. The selection will disappear instantly
== NOTE: This TODO refers to the old Konsole code, before the start of a new front-end
using KonsoleApp and KonsoleMainWindow. Some parts do not apply to the new
front-end
......
......@@ -29,6 +29,10 @@ SessionController::SessionController(TESession* session , TEWidget* view, QObjec
view->installEventFilter(this);
// destroy session controller if either the view or the session are destroyed
connect( _session , SIGNAL(destroyed()) , this , SLOT(deleteLater()) );
connect( _view , SIGNAL(destroyed()) , this , SLOT(deleteLater()) );
// listen to activity / silence notifications from session
connect( _session , SIGNAL(notifySessionState(TESession*,int)) , this ,
SLOT(sessionStateChanged(TESession*,int) ));
......
......@@ -22,6 +22,10 @@ class UrlFilter;
* and exposes information such as the title and icon associated with the session to view containers.
*
* Each view should have one SessionController associated with it
*
* The SessionController will delete itself if either the view or the session is destroyed, for
* this reason it is recommended that other classes which need a pointer to a SessionController
* use QPointer<SessionController> rather than SessionController*
*/
class SessionController : public ViewProperties , public KXMLGUIClient
{
......
......@@ -214,6 +214,11 @@ TEWidget* TESession::primaryView()
return 0;
}
QList<TEWidget*> TESession::views() const
{
return _views;
}
void TESession::addView(TEWidget* widget)
{
Q_ASSERT( !_views.contains(widget) );
......
......@@ -89,6 +89,11 @@ public:
*/
void removeView(TEWidget* widget);
/**
* Returns the views connected to this session
*/
QList<TEWidget*> views() const;
/**
* Returns the primary view for this session.
*
......
......@@ -22,6 +22,8 @@
// Qt
#include <QHash>
#include <QLineEdit>
#include <QListWidget>
#include <QSplitter>
#include <QStackedWidget>
#include <QToolButton>
#include <QWidgetAction>
......@@ -54,6 +56,8 @@ void ViewContainer::viewDestroyed(QObject* object)
_views.removeAll(widget);
_navigation.remove(widget);
viewRemoved(widget);
if (_views.count() == 0)
emit empty(this);
}
......@@ -107,6 +111,7 @@ TabbedViewContainer::TabbedViewContainer(QObject* parent) :
QToolButton* closeButton = new QToolButton(_tabWidget);
closeButton->setIcon( KIcon("tab_remove") );
closeButton->setAutoRaise(true);
connect( closeButton , SIGNAL(clicked()) , this , SLOT(closeTabClicked()) );
_tabWidget->setCornerWidget(_newSessionButton,Qt::TopLeftCorner);
_tabWidget->setCornerWidget(closeButton,Qt::TopRightCorner);
......@@ -161,6 +166,11 @@ TabbedViewContainer::TabbedViewContainer(QObject* parent) :
SLOT(showContextMenu(QWidget*,const QPoint&)));
}
void TabbedViewContainer::closeTabClicked()
{
emit closeRequest(_tabWidget->currentWidget());
}
TabbedViewContainer::~TabbedViewContainer()
{
delete _tabContextMenu;
......@@ -309,4 +319,95 @@ void StackedViewContainer::viewRemoved( QWidget* view )
_stackWidget->removeWidget(view);
}
ListViewContainer::ListViewContainer(QObject* parent)
: ViewContainer(parent)
{
_splitter = new QSplitter;
_stackWidget = new QStackedWidget;
_listWidget = new QListWidget;
_listWidget->setTextElideMode( Qt::ElideLeft );
_listWidget->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
_splitter->addWidget(_listWidget);
_splitter->addWidget(_stackWidget);
connect( _listWidget , SIGNAL(currentRowChanged(int)) , this , SLOT(rowChanged(int)) );
}
ListViewContainer::~ListViewContainer()
{
delete _listWidget;
delete _stackWidget;
delete _splitter;
}
QWidget* ListViewContainer::containerWidget() const
{
return _splitter;
}
QWidget* ListViewContainer::activeView() const
{
return _stackWidget->currentWidget();
}
void ListViewContainer::viewAdded( QWidget* view )
{
_stackWidget->addWidget(view);
ViewProperties* properties = viewProperties(view);
QListWidgetItem* item = new QListWidgetItem(_listWidget);
item->setText( properties->title() );
item->setIcon( properties->icon() );
connect( properties , SIGNAL(titleChanged(ViewProperties*)) , this , SLOT(updateTitle(ViewProperties*)));
connect( properties , SIGNAL(iconChanged(ViewProperties*)) , this , SLOT(updateIcon(ViewProperties*)));
}
void ListViewContainer::viewRemoved( QWidget* view )
{
int index = _stackWidget->indexOf(view);
_stackWidget->removeWidget(view);
delete _listWidget->takeItem( index );
}
void ListViewContainer::setActiveView( QWidget* view )
{
_stackWidget->setCurrentWidget(view);
_listWidget->setCurrentRow(_stackWidget->indexOf(view));
}
void ListViewContainer::rowChanged( int row )
{
_stackWidget->setCurrentIndex( row );
emit activeViewChanged( _stackWidget->currentWidget() );
}
void ListViewContainer::updateTitle( ViewProperties* properties )
{
QList<QWidget*> items = widgetsForItem(properties);
QListIterator<QWidget*> itemIter(items);
while ( itemIter.hasNext() )
{
int index = _stackWidget->indexOf( itemIter.next() );
_listWidget->item( index )->setText( properties->title() );
}
}
void ListViewContainer::updateIcon( ViewProperties* properties )
{
QList<QWidget*> items = widgetsForItem(properties);
QListIterator<QWidget*> itemIter(items);
while ( itemIter.hasNext() )
{
int index = _stackWidget->indexOf( itemIter.next() );
_listWidget->item( index )->setIcon( properties->icon() );
}
}
#include "ViewContainer.moc"
......@@ -45,6 +45,10 @@ class ViewProperties;
class KColorCells;
class KMenu;
// ListViewContainer
class QSplitter;
class QListWidget;
/**
* An interface for container widgets which can hold one or more views.
*
......@@ -97,6 +101,12 @@ signals:
/** Emitted when the container has no more children */
void empty(ViewContainer* container);
/** Emitted when the user requests to close the a view */
void closeRequest(QWidget* activeView);
/** Emitted when the active view changes */
void activeViewChanged( QWidget* view );
protected:
/**
* Performs the task of adding the view widget
......@@ -137,7 +147,7 @@ public:
virtual void setActiveView(QWidget* view);
void setNewSessionMenu(QMenu* menu);
protected:
virtual void viewAdded( QWidget* view );
virtual void viewRemoved( QWidget* view );
......@@ -145,7 +155,7 @@ protected:
private slots:
void updateTitle(ViewProperties* item);
void updateIcon(ViewProperties* item);
void closeTabClicked();
void selectTabColor();
void prepareColorCells();
void showContextMenu(QWidget* widget , const QPoint& position);
......@@ -186,5 +196,35 @@ private:
QStackedWidget* _stackWidget;
};
/**
* A view container which uses a list instead of tabs to provide navigation
* between sessions.
*/
class ListViewContainer : public ViewContainer
{
Q_OBJECT
public:
ListViewContainer(QObject* parent);
virtual ~ListViewContainer();
virtual QWidget* containerWidget() const;
virtual QWidget* activeView() const;
virtual void setActiveView(QWidget* view);
protected:
virtual void viewAdded( QWidget* view );
virtual void viewRemoved( QWidget* view );
private slots:
void rowChanged( int row );
void updateTitle( ViewProperties* );
void updateIcon( ViewProperties* );
private:
QStackedWidget* _stackWidget;
QSplitter* _splitter;
QListWidget* _listWidget;
};
#endif //VIEWCONTAINER_H
......@@ -241,8 +241,8 @@ void ViewManager::createView(TESession* session)
ViewContainer* ViewManager::createContainer()
{
TabbedViewContainer* container = new TabbedViewContainer(_viewSplitter);
/*TabbedViewContainer* container = new TabbedViewContainer(_viewSplitter);
if ( _mainWindow->factory() )
{
QMenu* menu = (QMenu*)_mainWindow->factory()->container("new-session-popup",_mainWindow);
......@@ -252,13 +252,37 @@ ViewContainer* ViewManager::createContainer()
}
else
{
kDebug() << __FILE__ << __LINE__ << ": ViewManager attempted to create a view before" <<
kDebug() << __FILE__ << __LINE__ << ": ViewManager attempted to create a view before" <<
" the main window GUI was created - unable to create popup menus for container." << endl;
}
// connect signals and slots
connect( container , SIGNAL(closeRequest(QWidget*)) , this , SLOT(viewCloseRequest(QWidget*)) );
*/
ViewContainer* container = new ListViewContainer(_viewSplitter);
return container;
}
void ViewManager::viewCloseRequest(QWidget* view)
{
// 1. detach view from session
// 2. if the session has no views left, close it
TEWidget* display = (TEWidget*)view;
TESession* session = _sessionMap[ display ];
if ( session )
{
delete display;
if ( session->views().count() == 0 )
session->closeSession();
}
else
{
kDebug() << __FILE__ << __LINE__ << ": received close request from unknown view." << endl;
}
}
void ViewManager::merge(ViewManager* otherManager)
{
ViewSplitter* otherSplitter = otherManager->_viewSplitter;
......
......@@ -23,6 +23,7 @@
// Qt
#include <QHash>
#include <QObject>
#include <QPointer>
class KToggleAction;
......@@ -79,6 +80,8 @@ private slots:
// called when a session terminates - the view manager will delete any
// views associated with the session
void sessionFinished( TESession* session );
// called when the container requests to close a particular view
void viewCloseRequest(QWidget* widget);
void viewFocused( SessionController* controller );
......@@ -100,7 +103,7 @@ private:
KonsoleMainWindow* _mainWindow;
KToggleAction* _splitViewAction;
ViewSplitter* _viewSplitter;
SessionController* _pluggedController;
QPointer<SessionController> _pluggedController;
QHash<TEWidget*,TESession*> _sessionMap;
};
......
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