Commit 242e18a9 authored by Robert Knight's avatar Robert Knight
Browse files

Work done during my short holiday:

New User-Visible Features:
    * 'Merge Windows' feature.  This merges all of the existing Konsole windows into a single
      window.  (The opposite of detach view in a sense).  Only merges the views from the active 
      tab widget in each window at the moment. 
    * Split-view feature.  Splits existing view top/bottom.

New Front-end Progress:  
    * Make creating a new tab and window work in the new front-end
    * Add detach-view in new front-end
    * Added ViewManager class which manges views and view containers in a main window as well
      as creating new views and session controllers for terminal sessions.
    * Added SessionController class which provides the actions associated with an individual session and view.
      (including the Edit and History menus)
    * Menu items now working: Copy,Paste,Clear,Clear & Reset,Clear History,Configure Konsole
    * Wrote a widget for incremental searches in documents ( IncrementalSearchBar ).  The widget
      is closely modelled on the incremental search bar found in Firefox. 
    * SessionList class to provide the actions used to create new sessions in menus

Fixes:
    * Fix crashes with multiple views caused by trying to change the size of the 
      terminal image ( via setSize() ) after the user manually resizes the display
    * Update terminal size associated with pty when resizing display
    * Fix broken signal-slot connection in TabbedViewContainer
    * Check for a minimum terminal size of 1 line x 1 column when updating the terminal image
    * Ensure that internal array used by display widget to store terminal characters is always non-zero
      in size.  Also ensure that 'lines' and 'columns' internal properties are always > 0.
      Fixes crashes when display widget has a very small height or width.
    * Fixed crash with small display widget caused by TEWidget's count of used lines and used columns
      (usedLines,usedColumn fields) not being updated when the terminal image was made smaller.

Refactoring:
    * Further file renaming for consistancy between file name and class name
    * Make ViewContainer subclasses take a QObject* parent argument in their constructors
    

svn path=/branches/work/konsole-split-view/; revision=618089
parent 6ae99927
......@@ -6,19 +6,37 @@
<Action name="new-tab" />
<Action name="new-window" />
<Separator/>
<DefineGroup name="new-session-operations"/>
<ActionList name="new-session-types"/>
<Separator/>
<Action name="close-session"/>
<Action name="exit" />
</Menu>
<Menu name="edit"><text>Edit</text>
<DefineGroup name="edit-operations"/>
<Action name="copy"/>
<Action name="paste"/>
<Separator/>
<Action name="zmodem-upload"/>
<Separator/>
<Action name="clear"/>
<Action name="clear-and-reset"/>
</Menu>
<Menu name="view"><text>View</text>
<DefineGroup name="view-operations"/>
<Menu name="history"><text>History</text>
<Action name="search-history"/>
<Action name="find-next"/>
<Action name="find-previous"/>
<Action name="save-history"/>
<Separator/>
<Action name="clear-history"/>
</Menu>
<Action name="bookmark">
<Menu name="view"><text>View</text>
<Action name="monitor-activity"/>
<Action name="monitor-silence" />
<Separator/>
<Action name="split-view"/>
<Action name="detach-view"/>
<Action name="merge-windows"/>
</Menu>
<Action name="bookmark"/>
<Menu name="settings"><text>Settings</text>
<DefineGroup name="session-settings"/>
<Separator/>
......
......@@ -53,6 +53,8 @@ set(konsole_KDEINIT_SRCS
start.cpp
KonsoleApp.cpp
KonsoleMainWindow.cpp
SessionController.cpp
SessionList.cpp
SessionManager.cpp
TESession.cpp
TEPty.cpp
......@@ -64,11 +66,12 @@ set(konsole_KDEINIT_SRCS
ViewContainer.cpp
ViewManager.cpp
ViewSplitter.cpp
konsolebookmarkhandler.cpp
zmodem_dialog.cpp
keytrans.cpp
KonsoleBookmarkHandler.cpp
ZModemDialog.cpp
KeyTrans.cpp
BlockArray.cpp
TerminalCharacterDecoder.cpp
IncrementalSearchBar.cpp
schema.cpp
konsole_wcwidth.cpp
)
......@@ -103,14 +106,14 @@ set(konsolepart_PART_SRCS
konsole_part.cpp
schema.cpp
TESession.cpp
zmodem_dialog.cpp
ZModemDialog.cpp
TEWidget.cpp
TEmuVt102.cpp
TEScreen.cpp
konsole_wcwidth.cpp
TEmulation.cpp
TEHistory.cpp
keytrans.cpp
KeyTrans.cpp
TerminalCharacterDecoder.cpp
SessionManager.cpp )
......
/*
Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
*/
// Qt
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QProgressBar>
#include <QToolButton>
// KDE
#include <KLocale>
#include <KIcon>
// Konsole
#include "IncrementalSearchBar.h"
IncrementalSearchBar::IncrementalSearchBar(Features features , QWidget* parent)
: QWidget(parent)
, _foundMatch(false)
, _matchCase(false)
, _matchRegExp(false)
, _highlightMatches(false)
, _searchEdit(0)
, _continueLabel(0)
{
QHBoxLayout* layout = new QHBoxLayout(parent);
QToolButton* close = new QToolButton(this);
close->setAutoRaise(true);
close->setIcon(KIcon("fileclose"));
connect( close , SIGNAL(clicked()) , this , SIGNAL(closeClicked()) );
QLabel* findLabel = new QLabel(i18n("Find"),this);
_searchEdit = new QLineEdit(this);
// text box may be a minimum of 3 characters wide and a maximum of 10 characters wide
// (since the maxWidth metric is used here, more characters probably will fit in than 3
// and 10)
QFontMetrics metrics(_searchEdit->font());
int maxWidth = metrics.maxWidth();
_searchEdit->setMinimumWidth(maxWidth*3);
_searchEdit->setMaximumWidth(maxWidth*10);
connect( _searchEdit , SIGNAL(textChanged(const QString&)) , this , SIGNAL(searchChanged(const QString&)));
QToolButton* findNext = new QToolButton(this);
findNext->setText(i18n("Next"));
findNext->setAutoRaise(true);
findNext->setIcon( KIcon("next") );
findNext->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
connect( findNext , SIGNAL(clicked()) , this , SIGNAL(findNextClicked()) );
QToolButton* findPrev = new QToolButton(this);
findPrev->setText(i18n("Previous"));
findPrev->setAutoRaise(true);
findPrev->setIcon( KIcon("previous") );
findPrev->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
connect( findPrev , SIGNAL(clicked()) , this , SIGNAL(findPreviousClicked()) );
QCheckBox* highlightMatches = 0;
if ( features & HighlightMatches )
{
highlightMatches = new QCheckBox( i18n("Highlight Matches") , this );
connect( highlightMatches , SIGNAL(toggled(bool)) , this ,
SIGNAL(highlightMatchesToggled(bool)) );
}
QCheckBox* matchCase = 0;
if ( features & MatchCase )
{
matchCase = new QCheckBox( i18n("Match Case") , this );
connect( matchCase , SIGNAL(toggled(bool)) , this , SIGNAL(matchCaseToggled(bool)) );
}
QCheckBox* matchRegExp = 0;
if ( features & RegExp )
{
matchRegExp = new QCheckBox( i18n("Match Regular Expression") , this );
connect( matchRegExp , SIGNAL(toggled(bool)) , this , SIGNAL(matchRegExpToggled(bool)) );
}
QProgressBar* _progress = new QProgressBar(this);
_progress->setMinimum(0);
_progress->setMaximum(0);
_progress->setVisible(false);
QLabel* _continueLabel = new QLabel(this);
_continueLabel->setVisible(false);
layout->addWidget(close);
layout->addWidget(findLabel);
layout->addWidget(_searchEdit);
layout->addWidget(findNext);
layout->addWidget(findPrev);
// optional features
if ( features & HighlightMatches ) layout->addWidget(highlightMatches);
if ( features & MatchCase ) layout->addWidget(matchCase);
if ( features & RegExp ) layout->addWidget(matchRegExp);
layout->addWidget(_progress);
layout->addWidget(_continueLabel);
layout->addStretch();
layout->setMargin(4);
setLayout(layout);
}
QString IncrementalSearchBar::searchText()
{
return _searchEdit->text();
}
bool IncrementalSearchBar::highlightMatches()
{
return _highlightMatches;
}
bool IncrementalSearchBar::matchCase()
{
return _matchCase;
}
bool IncrementalSearchBar::matchRegExp()
{
return _matchRegExp;
}
void IncrementalSearchBar::setFoundMatch( bool match )
{
//FIXME - Hard coded colour used here - is there a better alternative?
if ( !match )
{
_searchEdit->setStyleSheet( "QLineEdit{ background-color: #FF7777 }" );
}
else
{
_searchEdit->setStyleSheet( QString() );
}
}
void IncrementalSearchBar::setContinueFlag( Continue flag )
{
if ( flag == ContinueFromTop )
{
_continueLabel->setText( i18n("Search reached bottom, continued from top.") );
_continueLabel->show();
}
else if ( flag == ContinueFromBottom )
{
_continueLabel->setText( i18n("Search reached top, continued from bottom.") );
_continueLabel->show();
}
else if ( flag == ClearContinue )
{
_continueLabel->hide();
}
}
#include "IncrementalSearchBar.moc"
/*
Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
*/
#ifndef INCREMENTALSEARCHBAR_H
#define INCREMENTALSEARCHBAR_H
// Qt
#include <QWidget>
class QLineEdit;
class QProgressBar;
/**
* A widget which allows users to search incrementally through a document for a
* a text string or regular expression.
*
* The widget consists of a text box into which the user can enter their search text and
* buttons to trigger a search for the next and previous matches for the search text.
*
* When the search text is changed, the searchChanged() signal is emitted. A search through
* the document for the new text should begin immediately and the active view of the document
* should jump to display any matches if found. setFoundMatch() should be called whenever the
* search text changes to indicate whether a match for the text was found in the document.
*
* findNextClicked() and findPreviousClicked() signals are emitted when the user presses buttons
* to find next and previous matches respectively.
*
* The search bar has a number of optional features which can be enabled or disabled by passing
* a set of Features flags to the constructor.
*
* An optional checkbox can be displayed to indicate whether all matches in the document
* for searchText() should be highlighted.
* The highlightMatchesToggled() signal is emitted when this checkbox is toggled.
*
* The two further optional checkboxes allow the user to control the matching process.
* The first indicates whether searches are case sensitive.
* The matchCaseToggled() signal is emitted when this is changed.
* The second indicates whether the search text should be treated as a plain string or
* as a regular expression.
* The matchRegExpToggled() signal is emitted when this is changed.
*/
class IncrementalSearchBar : public QWidget
{
Q_OBJECT
public:
enum Continue
{
/**
* Indicates that the search has reached the bottom of the document and has been continued from
* the top
*/
ContinueFromTop,
/**
* Indicates that the search has reached the top of the document and has been continued from
* the bottom
*/
ContinueFromBottom,
/** Clears the Continue flag */
ClearContinue
};
/**
* This enum defines the features which can be supported by an implementation of
* an incremental search bar
*/
enum Features
{
/** search facility supports highlighting of all matches */
HighlightMatches = 1,
/** search facility supports case-sensitive and case-insensitive search */
MatchCase = 2,
/** search facility supports regular expressions */
RegExp = 4,
/** search facility supports all features */
AllFeatures = HighlightMatches | MatchCase | RegExp
};
/**
* Constructs a new incremental search bar with the given parent widget
* @p features specifies the features which should be made available to the user.
*/
IncrementalSearchBar(Features features , QWidget* parent);
/**
* Sets an indicator for the user as to whether or not a match for the
* current search text was found in the document.
*/
void setFoundMatch( bool match );
/**
* Sets a flag to indicate that the current search for matches has reached the top or bottom of
* the document and has been continued again from the other end of the document.
*
* This flag will be cleared when the user presses the buttons to find a next or previous match.
*/
void setContinueFlag( Continue flag );
/** Returns the current search text */
QString searchText();
/** Returns whether matches for the current search text should be highlighted in the document */
bool highlightMatches();
/** Returns whether matching for the current search text should be case sensitive */
bool matchCase();
/** Returns whether the current search text should be treated as plain text or a regular expression */
bool matchRegExp();
signals:
/** Emitted when the text entered in the search box is altered */
void searchChanged( const QString& text );
/** Emitted when the user clicks the button to find the next match */
void findNextClicked();
/** Emitted when the user clicks the button to find the previous match */
void findPreviousClicked();
/**
* Emitted when the user toggles the checkbox to indicate whether
* matches for the search text should be highlighted
*/
void highlightMatchesToggled(bool);
/**
* Emitted when the user toggles the checkbox to indicate whether
* matching for the search text should be case sensitive
*/
void matchCaseToggled(bool);
/**
* Emitted when the user toggles the checkbox to indicate whether
* the search text should be treated as a plain string or a regular expression
*/
void matchRegExpToggled(bool);
/** Emitted when the close button is clicked */
void closeClicked();
private:
bool _foundMatch;
bool _matchCase;
bool _matchRegExp;
bool _highlightMatches;
QLineEdit* _searchEdit;
QLabel* _continueLabel;
QProgressBar* _progress;
};
#endif // INCREMENTALSEARCHBAR_H
......@@ -25,7 +25,7 @@
FIXME: some bug crept in, disallowing '\0' to be emitted.
*/
#include "keytrans.h"
#include "KeyTrans.h"
#include <QBuffer>
#include <QObject>
#include <q3intdict.h>
......
/*
Copyright (C) 2006 by Robert Knight <robertknight@gmail.com>
Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -17,16 +17,25 @@
02110-1301 USA.
*/
#include "kdebug.h"
#include "SessionList.h"
#include "SessionManager.h"
#include "keytrans.h"
#include "KeyTrans.h"
#include "KonsoleApp.h"
#include "KonsoleMainWindow.h"
#include "TESession.h"
#include "ViewManager.h"
// temporary - testing history feature
#include "TEHistory.h"
// global variable to determine whether or not true transparency should be used
// this should be made into a static class variable of KonsoleApp
int true_transparency = true;
KonsoleApp::KonsoleApp()
: _sessionList(0)
{
// create session manager
_sessionManager = new SessionManager();
......@@ -40,10 +49,23 @@ KonsoleApp* KonsoleApp::self()
return (KonsoleApp*)KApp;
}
int KonsoleApp::newInstance()
KonsoleMainWindow* KonsoleApp::newMainWindow()
{
KonsoleMainWindow* window = new KonsoleMainWindow();
window->setSessionList( new SessionList(sessionManager(),window) );
connect( window , SIGNAL(requestSession(const QString&,ViewManager*)),
this , SLOT(createSession(const QString&,ViewManager*)));
connect( window->viewManager() , SIGNAL(viewDetached(TESession*)) , this , SLOT(detachView(TESession*)) );
return window;
}
int KonsoleApp::newInstance()
{
KonsoleMainWindow* window = newMainWindow();
createSession( QString() , window->viewManager() );
window->show();
return 0;
......@@ -54,4 +76,23 @@ SessionManager* KonsoleApp::sessionManager()
return _sessionManager;
}
void KonsoleApp::detachView(TESession* session)
{
KonsoleMainWindow* window = newMainWindow();
window->viewManager()->createView(session);
window->show();
}
void KonsoleApp::createSession(const QString& key , ViewManager* view)
{
TESession* session = _sessionManager->createSession(key);
session->setConnect(true);
//temporary - test history feature
//session->setHistory( HistoryTypeBuffer(1000) );
session->run();
view->createView(session);
}
#include "KonsoleApp.moc"
/*
Copyright (C) 2006 by Robert Knight <robertknight@gmail.com>
Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -24,10 +24,22 @@
#include <KUniqueApplication>
class KCmdLineArgs;
class SessionList;
class SessionManager;
class ViewManager;
class KonsoleMainWindow;
class TESession;
/**
* The Konsole Application
* The Konsole Application.
*
* The application consists of one or more main windows and a set of factories to create
* new sessions and views.
*
* To create a new main window with a default terminal session, call the newInstance() method.
* Empty main windows can be created using newMainWindow().
*
* The factory used to create new terminal sessions can be retrieved using the sessionManager() accessor.
*/
class KonsoleApp : public KUniqueApplication
{
......@@ -40,16 +52,30 @@ public:
/** Creates a new main window and opens a default terminal session */
virtual int newInstance();
/**
* Creates a new, empty main window and returns a pointer to the created window
*
* DESIGN ISSUE: This is the only way that new main windows should be created because
* KonsoleApp needs to connect up certain signals from the window to itself
* perhaps it would be better if KonsoleMainWindow hooked itself up to KonsoleApp
* rather than the other way round?
*/
KonsoleMainWindow* newMainWindow();
/** Returns the KonsoleApp instance */
static KonsoleApp* self();
/** Returns the session manager */
SessionManager* sessionManager();
private slots:
void createSession(const QString& key, ViewManager* view);
void detachView(TESession* session);
private:
KCmdLineArgs* _arguments;
SessionManager* _sessionManager;
SessionList* _sessionList;
};
#endif //KONSOLEAPP_H
......@@ -33,7 +33,7 @@
#include <KBookmarkMenu>
// Konsole
#include "konsolebookmarkhandler.h"
#include "KonsoleBookmarkHandler.h"
KonsoleBookmarkHandler::KonsoleBookmarkHandler( KMainWindow* konsole, KMenu* menu, bool toplevel )
: QObject( konsole ),
......@@ -116,4 +116,4 @@ QString KonsoleBookmarkHandler::currentTitle() const
return u.prettyUrl();
}
#include "konsolebookmarkhandler.moc"
#include "KonsoleBookmarkHandler.moc"
/*
Copyright (C) 2006 by Robert Knight <robertknight@gmail.com>
Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -21,15 +21,18 @@
#include <KAction>
#include <KActionCollection>
#include <KActionMenu>
#include <KKeyDialog>
#include <KLocale>
#include <KMenu>
#include <KService>
#include <KToolInvocation>
#include <kstandardaction.h>
// Konsole
#include "konsolebookmarkhandler.h"
#include "KonsoleApp.h"
#include "KonsoleBookmarkHandler.h"
#include "KonsoleMainWindow.h"
#include "SessionList.h"
#include "ViewManager.h"
#include "ViewSplitter.h"
......@@ -44,17 +47,26 @@ KonsoleMainWindow::KonsoleMainWindow()