mirror of
https://github.com/KDE/konsole.git
synced 2026-05-02 03:36:34 -04:00
467 lines
14 KiB
C++
467 lines
14 KiB
C++
/*
|
|
Copyright 2006-2008 by Robert Knight <robertknight@gmail.com>
|
|
Copyright 2009 by Thomas Dreibholz <dreibh@iem.uni-due.de>
|
|
|
|
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 SESSIONCONTROLLER_H
|
|
#define SESSIONCONTROLLER_H
|
|
|
|
// Qt
|
|
#include <QtGui/QIcon>
|
|
#include <QtCore/QList>
|
|
#include <QtCore/QSet>
|
|
#include <QtCore/QPointer>
|
|
#include <QtCore/QString>
|
|
#include <QtCore/QThread>
|
|
#include <QtCore/QHash>
|
|
|
|
// KDE
|
|
#include <KActionCollection>
|
|
#include <KActionMenu>
|
|
#include <KIcon>
|
|
#include <KXMLGUIClient>
|
|
|
|
// Konsole
|
|
#include "HistorySizeDialog.h"
|
|
#include "ViewProperties.h"
|
|
#include "Profile.h"
|
|
|
|
namespace KIO
|
|
{
|
|
class Job;
|
|
}
|
|
|
|
class QAction;
|
|
class QTextCodec;
|
|
class KCodecAction;
|
|
class KUrl;
|
|
class KJob;
|
|
|
|
namespace Konsole
|
|
{
|
|
|
|
class Session;
|
|
class SessionGroup;
|
|
class ScreenWindow;
|
|
class TerminalDisplay;
|
|
class IncrementalSearchBar;
|
|
class ProfileList;
|
|
class UrlFilter;
|
|
class RegExpFilter;
|
|
|
|
// SaveHistoryTask
|
|
class TerminalCharacterDecoder;
|
|
|
|
|
|
typedef QPointer<Session> SessionPtr;
|
|
|
|
/**
|
|
* Provides the menu actions to manipulate a single terminal session and view pair.
|
|
* The actions provided by this class are defined in the sessionui.rc XML file.
|
|
*
|
|
* SessionController monitors the session and provides access to basic information
|
|
* about the session such as title(), icon() and currentDir(). SessionController
|
|
* provides notifications of activity in the session via the activity() signal.
|
|
*
|
|
* When the controlled view receives the focus, the focused() signal is emitted
|
|
* with a pointer to the controller. This can be used by main application window
|
|
* which contains the view to plug the controller's actions into the menu when
|
|
* the view is focused.
|
|
*/
|
|
class KONSOLEPRIVATE_EXPORT SessionController : public ViewProperties , public KXMLGUIClient
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/**
|
|
* Constructs a new SessionController which operates on @p session and @p view.
|
|
*/
|
|
SessionController(Session* session , TerminalDisplay* view, QObject* parent);
|
|
~SessionController();
|
|
|
|
/** Returns the session associated with this controller */
|
|
QPointer<Session> session() { return _session; }
|
|
/** Returns the view associated with this controller */
|
|
QPointer<TerminalDisplay> view() { return _view; }
|
|
|
|
/**
|
|
* Returns true if the controller is valid.
|
|
* A valid controller is one which has a non-null session() and view().
|
|
*
|
|
* Equivalent to "!session().isNull() && !view().isNull()"
|
|
*/
|
|
bool isValid() const;
|
|
|
|
/**
|
|
* Sets the widget used for searches through the session's output.
|
|
*
|
|
* When the user clicks on the "Search Output" menu action the @p searchBar 's
|
|
* show() method will be called. The SessionController will then connect to the search
|
|
* bar's signals to update the search when the widget's controls are pressed.
|
|
*/
|
|
void setSearchBar( IncrementalSearchBar* searchBar );
|
|
/**
|
|
* see setSearchBar()
|
|
*/
|
|
IncrementalSearchBar* searchBar() const;
|
|
|
|
/**
|
|
* Sets the action displayed in the session's context menu to hide or
|
|
* show the menu bar.
|
|
*/
|
|
void setShowMenuAction(QAction* action);
|
|
|
|
// reimplemented
|
|
virtual KUrl url() const;
|
|
virtual QString currentDir() const;
|
|
virtual void rename();
|
|
virtual bool confirmClose() const;
|
|
|
|
// Reimplemented to watch for events happening to the view
|
|
virtual bool eventFilter(QObject* watched , QEvent* event);
|
|
|
|
/** Returns the set of all controllers that exist. */
|
|
static QSet<SessionController*> allControllers()
|
|
{ return _allControllers; }
|
|
|
|
signals:
|
|
/**
|
|
* Emitted when the view associated with the controller is focused.
|
|
* This can be used by other classes to plug the controller's actions into a window's
|
|
* menus.
|
|
*/
|
|
void focused( SessionController* controller );
|
|
|
|
public slots:
|
|
/**
|
|
* Issues a command to the session to navigate to the specified URL.
|
|
* This may not succeed if the foreground program does not understand
|
|
* the command sent to it ( 'cd path' for local URLs ) or is not
|
|
* responding to input.
|
|
*
|
|
* openUrl() currently supports urls for local paths and those
|
|
* using the 'ssh' protocol ( eg. "ssh://joebloggs@hostname" )
|
|
*/
|
|
void openUrl( const KUrl& url );
|
|
|
|
/**
|
|
* update actions which are meaningful only when rimary screen is in use.
|
|
*/
|
|
void setupPrimaryScreenSpecificActions( bool use);
|
|
|
|
/**
|
|
* enable or disable the copy action
|
|
*/
|
|
void updateCopyAction( const QString & text );
|
|
|
|
|
|
|
|
private slots:
|
|
// menu item handlers
|
|
void openBrowser();
|
|
void copy();
|
|
void paste();
|
|
void pasteSelection(); // shortcut only
|
|
void copyInputToAllTabs();
|
|
void copyInputToSelectedTabs();
|
|
void copyInputToNone();
|
|
void editCurrentProfile();
|
|
void changeCodec(QTextCodec* codec);
|
|
void searchHistory(bool showSearchBar);
|
|
void findNextInHistory();
|
|
void findPreviousInHistory();
|
|
void changeSearchMatch();
|
|
void saveHistory();
|
|
void showHistoryOptions();
|
|
void clearHistory();
|
|
void clearHistoryAndReset();
|
|
void closeSession();
|
|
void monitorActivity(bool monitor);
|
|
void monitorSilence(bool monitor);
|
|
void increaseTextSize();
|
|
void decreaseTextSize();
|
|
void renameSession();
|
|
void saveSession();
|
|
void changeProfile(Profile::Ptr profile);
|
|
|
|
// other
|
|
void prepareChangeProfileMenu();
|
|
void updateCodecAction();
|
|
void showDisplayContextMenu(const QPoint& position);
|
|
void sessionStateChanged(int state);
|
|
void sessionTitleChanged();
|
|
void searchTextChanged(const QString& text);
|
|
void searchCompleted(bool success);
|
|
void searchClosed(); // called when the user clicks on the
|
|
// history search bar's close button
|
|
|
|
void snapshot(); // called periodically as the user types
|
|
// to take a snapshot of the state of the
|
|
// foreground process in the terminal
|
|
|
|
void requireUrlFilterUpdate();
|
|
void highlightMatches(bool highlight);
|
|
void scrollBackOptionsChanged(int mode , int lines, bool saveToCurrentProfile);
|
|
void sessionResizeRequest(const QSize& size);
|
|
void trackOutput(QKeyEvent* event); // move view to end of current output
|
|
// when a key press occurs in the
|
|
// display area
|
|
|
|
void updateSearchFilter();
|
|
|
|
void zmodemDownload();
|
|
void zmodemUpload();
|
|
|
|
/* Returns true if called within a KPart; false if called within Konsole. */
|
|
bool isKonsolePart() const;
|
|
|
|
private:
|
|
// begins the search
|
|
// text - pattern to search for
|
|
// direction - value from SearchHistoryTask::SearchDirection enum to specify
|
|
// the search direction
|
|
void beginSearch(const QString& text , int direction);
|
|
void setupActions();
|
|
void removeSearchFilter(); // remove and delete the current search filter if set
|
|
void setFindNextPrevEnabled(bool enabled);
|
|
void listenForScreenWindowUpdates();
|
|
|
|
private:
|
|
void updateSessionIcon();
|
|
|
|
QPointer<Session> _session;
|
|
QPointer<TerminalDisplay> _view;
|
|
SessionGroup* _copyToGroup;
|
|
|
|
ProfileList* _profileList;
|
|
|
|
KIcon _sessionIcon;
|
|
QString _sessionIconName;
|
|
int _previousState;
|
|
|
|
UrlFilter* _viewUrlFilter;
|
|
RegExpFilter* _searchFilter;
|
|
|
|
KAction* _copyToAllTabsAction;
|
|
KAction* _copyToSelectedAction;
|
|
KAction* _copyToNoneAction;
|
|
|
|
KAction* _searchToggleAction;
|
|
KAction* _findNextAction;
|
|
KAction* _findPreviousAction;
|
|
|
|
|
|
bool _urlFilterUpdateRequired;
|
|
|
|
QPointer<IncrementalSearchBar> _searchBar;
|
|
|
|
KCodecAction* _codecAction;
|
|
|
|
KActionMenu* _changeProfileMenu;
|
|
|
|
bool _listenForScreenWindowUpdates;
|
|
bool _preventClose;
|
|
|
|
static QSet<SessionController*> _allControllers;
|
|
static int _lastControllerId;
|
|
static KIcon _activityIcon;
|
|
static KIcon _silenceIcon;
|
|
};
|
|
inline bool SessionController::isValid() const
|
|
{
|
|
return !_session.isNull() && !_view.isNull();
|
|
}
|
|
|
|
/**
|
|
* Abstract class representing a task which can be performed on a group of sessions.
|
|
*
|
|
* Create a new instance of the appropriate sub-class for the task you want to perform and
|
|
* call the addSession() method to add each session which needs to be processed.
|
|
*
|
|
* Finally, call the execute() method to perform the sub-class specific action on each
|
|
* of the sessions.
|
|
*/
|
|
class SessionTask : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
SessionTask(QObject* parent = 0);
|
|
|
|
/**
|
|
* Sets whether the task automatically deletes itself when the task has been finished.
|
|
* Depending on whether the task operates synchronously or asynchronously, the deletion
|
|
* may be scheduled immediately after execute() returns or it may happen some time later.
|
|
*/
|
|
void setAutoDelete(bool enable);
|
|
/** Returns true if the task automatically deletes itself. See setAutoDelete() */
|
|
bool autoDelete() const;
|
|
|
|
/** Adds a new session to the group */
|
|
void addSession(Session* session);
|
|
|
|
/**
|
|
* Executes the task on each of the sessions in the group.
|
|
* The completed() signal is emitted when the task is finished, depending on the specific sub-class
|
|
* execute() may be synchronous or asynchronous
|
|
*/
|
|
virtual void execute() = 0;
|
|
|
|
signals:
|
|
/**
|
|
* Emitted when the task has completed.
|
|
* Depending on the task this may occur just before execute() returns, or it
|
|
* may occur later
|
|
*
|
|
* @param success Indicates whether the task completed successfully or not
|
|
*/
|
|
void completed(bool success);
|
|
|
|
protected:
|
|
|
|
/** Returns a list of sessions in the group */
|
|
QList< SessionPtr > sessions() const;
|
|
|
|
private:
|
|
|
|
bool _autoDelete;
|
|
QList< SessionPtr > _sessions;
|
|
};
|
|
|
|
/**
|
|
* A task which prompts for a URL for each session and saves that session's output
|
|
* to the given URL
|
|
*/
|
|
class SaveHistoryTask : public SessionTask
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/** Constructs a new task to save session output to URLs */
|
|
SaveHistoryTask(QObject* parent = 0);
|
|
virtual ~SaveHistoryTask();
|
|
|
|
/**
|
|
* Opens a save file dialog for each session in the group and begins saving
|
|
* each session's history to the given URL.
|
|
*
|
|
* The data transfer is performed asynchronously and will continue after execute() returns.
|
|
*/
|
|
virtual void execute();
|
|
|
|
private slots:
|
|
void jobDataRequested(KIO::Job* job , QByteArray& data);
|
|
void jobResult(KJob* job);
|
|
|
|
private:
|
|
class SaveJob // structure to keep information needed to process
|
|
// incoming data requests from jobs
|
|
{
|
|
public:
|
|
SessionPtr session; // the session associated with a history save job
|
|
int lastLineFetched; // the last line processed in the previous data request
|
|
// set this to -1 at the start of the save job
|
|
|
|
TerminalCharacterDecoder* decoder; // decoder used to convert terminal characters
|
|
// into output
|
|
|
|
};
|
|
|
|
QHash<KJob*,SaveJob> _jobSession;
|
|
};
|
|
|
|
class SearchHistoryThread;
|
|
/**
|
|
* A task which searches through the output of sessions for matches for a given regular expression.
|
|
* SearchHistoryTask operates on ScreenWindow instances rather than sessions added by addSession().
|
|
* A screen window can be added to the list to search using addScreenWindow()
|
|
*
|
|
* When execute() is called, the search begins in the direction specified by searchDirection(),
|
|
* starting at the position of the current selection.
|
|
*
|
|
* FIXME - This is not a proper implementation of SessionTask, in that it ignores sessions specified
|
|
* with addSession()
|
|
*
|
|
* TODO - Implementation requirements:
|
|
* May provide progress feedback to the user when searching very large output logs.
|
|
*/
|
|
class SearchHistoryTask : public SessionTask
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/**
|
|
* This enum describes the strategies available for searching through the
|
|
* session's output.
|
|
*/
|
|
enum SearchDirection
|
|
{
|
|
/** Searches forwards through the output, starting at the current selection. */
|
|
ForwardsSearch,
|
|
/** Searches backwars through the output, starting at the current selection. */
|
|
BackwardsSearch
|
|
};
|
|
|
|
/**
|
|
* Constructs a new search task.
|
|
*/
|
|
explicit SearchHistoryTask(QObject* parent = 0);
|
|
|
|
/** Adds a screen window to the list to search when execute() is called. */
|
|
void addScreenWindow( Session* session , ScreenWindow* searchWindow);
|
|
|
|
/** Sets the regular expression which is searched for when execute() is called */
|
|
void setRegExp(const QRegExp& regExp);
|
|
/** Returns the regular expression which is searched for when execute() is called */
|
|
QRegExp regExp() const;
|
|
|
|
/** Specifies the direction to search in when execute() is called. */
|
|
void setSearchDirection( SearchDirection direction );
|
|
/** Returns the current search direction. See setSearchDirection(). */
|
|
SearchDirection searchDirection() const;
|
|
|
|
/**
|
|
* Performs a search through the session's history, starting at the position
|
|
* of the current selection, in the direction specified by setSearchDirection().
|
|
*
|
|
* If it finds a match, the ScreenWindow specified in the constructor is
|
|
* scrolled to the position where the match occurred and the selection
|
|
* is set to the matching text. execute() then returns immediately.
|
|
*
|
|
* To continue the search looking for further matches, call execute() again.
|
|
*/
|
|
virtual void execute();
|
|
|
|
private:
|
|
typedef QPointer<ScreenWindow> ScreenWindowPtr;
|
|
|
|
void executeOnScreenWindow( SessionPtr session , ScreenWindowPtr window );
|
|
void highlightResult( ScreenWindowPtr window , int position);
|
|
|
|
QMap< SessionPtr , ScreenWindowPtr > _windows;
|
|
QRegExp _regExp;
|
|
SearchDirection _direction;
|
|
|
|
static QPointer<SearchHistoryThread> _thread;
|
|
};
|
|
|
|
}
|
|
|
|
#endif //SESSIONCONTROLLER_H
|
|
|