Conflicts:
	src/main.cpp
This commit is contained in:
Petr Vanek
2013-01-15 17:11:13 +01:00
10 changed files with 556 additions and 9 deletions
+9 -3
View File
@@ -43,6 +43,7 @@ set ( SRCS
Emulation.cpp
Filter.cpp
History.cpp
HistorySearch.cpp
KeyboardTranslator.cpp
konsole_wcwidth.cpp
kprocess.cpp
@@ -53,6 +54,7 @@ set ( SRCS
qtermwidget.cpp
Screen.cpp
ScreenWindow.cpp
SearchBar.cpp
Session.cpp
ShellCommand.cpp
TerminalCharacterDecoder.cpp
@@ -66,13 +68,15 @@ set ( SRCS
set ( HDRS
Emulation.h
Filter.h
HistorySearch.h
kprocess.h
kptydevice.h
kptyprocess.h
Pty.h
qtermwidget.h
ScreenWindow.h
Session.h
SearchBar.h
Session.h
TerminalDisplay.h
Vt102Emulation.h
)
@@ -88,8 +92,10 @@ include ( ${QT_USE_FILE} ) # Includes Qt4 headers and libraries (the above comma
QT4_WRAP_CPP ( MOC_SRCS ${HDRS} ) # Moc's the headers
#include ( ${CMAKE_BINARY_DIR} ) # For including the heades generated by ui files
QT4_WRAP_UI(UI_SRCS SearchBar.ui)
#| qtermwidget specific
include_directories ( ${PROJECT_SOURCE_DIR} ) # You mark some of the headers as global, so I just add the source directory to the includes
include_directories ( ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) # You mark some of the headers as global, so I just add the source directory to the includes
# dirs
@@ -119,7 +125,7 @@ endif (HAVE_UPDWTMPX)
#| Create the Library
#add_library( qtermwidget STATIC ${SRCS} ${MOC_SRCS} )
add_library ( qtermwidget SHARED ${SRCS} ${MOC_SRCS} )
add_library ( qtermwidget SHARED ${SRCS} ${MOC_SRCS} ${UI_SRCS})
if (APPLE)
# this is a must to load the lib correctly
+156
View File
@@ -0,0 +1,156 @@
/*
Copyright 2013 Christian Surlykke
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.
*/
#include <QApplication>
#include <QTextStream>
#include <QDebug>
#include "TerminalCharacterDecoder.h"
#include "Emulation.h"
#include "HistorySearch.h"
HistorySearch::HistorySearch(EmulationPtr emulation, QRegExp regExp,
bool forwards, int startColumn, int startLine,
QObject* parent) :
QObject(parent),
m_emulation(emulation),
m_regExp(regExp),
m_forwards(forwards),
m_startColumn(startColumn),
m_startLine(startLine) {
}
HistorySearch::~HistorySearch() {
}
void HistorySearch::search() {
bool found = false;
if (! m_regExp.isEmpty())
{
if (m_forwards) {
found = search(m_startColumn, m_startLine, -1, m_emulation->lineCount()) || search(0, 0, m_startColumn, m_startLine);
} else {
found = search(0, 0, m_startColumn, m_startLine) || search(m_startColumn, m_startLine, -1, m_emulation->lineCount());
}
}
if (found) {
emit matchFound(m_foundStartColumn, m_foundStartLine, m_foundEndColumn, m_foundEndLine);
} else {
emit noMatchFound();
}
deleteLater();
}
bool HistorySearch::search(int startColumn, int startLine, int endColumn, int endLine) {
qDebug() << "search from" << startColumn << "," << startLine
<< "to" << endColumn << "," << endLine;
int linesRead = 0;
int linesToRead = endLine - startLine + 1;
qDebug() << "linesToRead:" << linesToRead;
// We read process history from (and including) startLine to (and including) endLine in
// blocks of at most 10K lines so that we do not use unhealthy amounts of memory
int blockSize;
while ((blockSize = qMin(10000, linesToRead - linesRead)) > 0) {
QString string;
QTextStream searchStream(&string);
PlainTextDecoder decoder;
decoder.begin(&searchStream);
decoder.setRecordLinePositions(true);
// Calculate lines to read and read them
int blockStartLine = m_forwards ? startLine + linesRead : endLine - linesRead - blockSize + 1;
int chunkEndLine = blockStartLine + blockSize - 1;
m_emulation->writeToStream(&decoder, blockStartLine, chunkEndLine);
// We search between startColumn in the first line of the string and endColumn in the last
// line of the string. First we calculate the position (in the string) of endColumn in the
// last line of the string
int endPosition;
// The String that Emulator.writeToStream produces has a newline at the end, and so ends with an
// empty line - we ignore that.
int numberOfLinesInString = decoder.linePositions().size() - 1;
if (numberOfLinesInString > 0 && endColumn > -1 )
{
endPosition = decoder.linePositions().at(numberOfLinesInString - 1) + endColumn;
}
else
{
endPosition = string.size();
}
// So now we can log for m_regExp in the string between startColumn and endPosition
int matchStart;
if (m_forwards)
{
matchStart = string.indexOf(m_regExp, startColumn);
if (matchStart >= endPosition)
matchStart = -1;
}
else
{
matchStart = string.lastIndexOf(m_regExp, endPosition - 1);
if (matchStart < startColumn)
matchStart = -1;
}
if (matchStart > -1)
{
int matchEnd = matchStart + m_regExp.matchedLength() - 1;
qDebug() << "Found in string from" << matchStart << "to" << matchEnd;
// Translate startPos and endPos to startColum, startLine, endColumn and endLine in history.
int startLineNumberInString = findLineNumberInString(decoder.linePositions(), matchStart);
m_foundStartColumn = matchStart - decoder.linePositions().at(startLineNumberInString);
m_foundStartLine = startLineNumberInString + startLine + linesRead;
int endLineNumberInString = findLineNumberInString(decoder.linePositions(), matchEnd);
m_foundEndColumn = matchEnd - decoder.linePositions().at(endLineNumberInString);
m_foundEndLine = endLineNumberInString + startLine + linesRead;
qDebug() << "m_foundStartColumn" << m_foundStartColumn
<< "m_foundStartLine" << m_foundEndLine
<< "m_foundEndColumn" << m_foundEndColumn
<< "m_foundEndLine" << m_foundEndLine;
return true;
}
linesRead += blockSize;
}
qDebug() << "Not found";
return false;
}
int HistorySearch::findLineNumberInString(QList<int> linePositions, int position) {
int lineNum = 0;
while (lineNum + 1 < linePositions.size() && linePositions[lineNum + 1] <= position)
lineNum++;
return lineNum;
}
+70
View File
@@ -0,0 +1,70 @@
/*
Copyright 2013 Christian Surlykke
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 TASK_H
#define TASK_H
#include <QObject>
#include <QPointer>
#include <QMap>
#include <Session.h>
#include <ScreenWindow.h>
#include "Emulation.h"
#include "TerminalCharacterDecoder.h"
using namespace Konsole;
typedef QPointer<Emulation> EmulationPtr;
class HistorySearch : public QObject
{
Q_OBJECT
public:
explicit HistorySearch(EmulationPtr emulation, QRegExp regExp, bool forwards,
int startColumn, int startLine, QObject* parent);
~HistorySearch();
void search();
signals:
void matchFound(int startColumn, int startLine, int endColumn, int endLine);
void noMatchFound();
private:
bool search(int startColumn, int startLine, int endColumn, int endLine);
int findLineNumberInString(QList<int> linePositions, int position);
EmulationPtr m_emulation;
QRegExp m_regExp;
bool m_forwards;
int m_startColumn;
int m_startLine;
int m_foundStartColumn;
int m_foundStartLine;
int m_foundEndColumn;
int m_foundEndLine;
};
#endif /* TASK_H */
+92
View File
@@ -0,0 +1,92 @@
/*
Copyright 2013 Christian Surlykke
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.
*/
#include <QMenu>
#include <QAction>
#include <QRegExp>
#include <QDebug>
#include "SearchBar.h"
SearchBar::SearchBar(QWidget *parent) :
QWidget(parent),
m_regExp("")
{
widget.setupUi(this);
connect(widget.closeButton, SIGNAL(clicked()), this, SLOT(hide()));
connect(widget.searchTextEdit, SIGNAL(textChanged(QString)), this, SLOT(searchTextChanged()));
connect(widget.findPreviousButton, SIGNAL(clicked()), this, SLOT(findPrevious()));
connect(widget.findNextButton, SIGNAL(clicked()), this, SLOT(findNext()));
QMenu *optionsMenu = new QMenu(widget.optionsButton);
widget.optionsButton->setMenu(optionsMenu);
m_matchCaseMenuEntry = optionsMenu->addAction(tr("Match case"));
m_matchCaseMenuEntry->setCheckable(true);
m_matchCaseMenuEntry->setChecked(true);
m_useRegularExpressionMenuEntry = optionsMenu->addAction(tr("Regular expression"));
m_useRegularExpressionMenuEntry->setCheckable(true);
m_highlightMatchesMenuEntry = optionsMenu->addAction(tr("Higlight all matches"));
m_highlightMatchesMenuEntry->setCheckable(true);
m_highlightMatchesMenuEntry->setChecked(true);
}
SearchBar::~SearchBar() {
}
void SearchBar::show()
{
QWidget::show();
widget.searchTextEdit->setFocus();
}
void SearchBar::hide()
{
QWidget::hide();
}
void SearchBar::toggleShown()
{
isHidden() ? show() : hide();
}
void SearchBar::searchTextChanged()
{
m_regExp = QRegExp(widget.searchTextEdit->text());
if (! m_useRegularExpressionMenuEntry->isChecked()) {
m_regExp.setPatternSyntax(QRegExp::FixedString);
}
if (! m_matchCaseMenuEntry->isChecked()) {
m_regExp.setCaseSensitivity(Qt::CaseInsensitive);
}
emit search(m_regExp, true, false);
}
void SearchBar::findNext()
{
emit search(m_regExp, true, true);
}
void SearchBar::findPrevious()
{
emit search(m_regExp, false, false);
}
+55
View File
@@ -0,0 +1,55 @@
/*
Copyright 2013 Christian Surlykke
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 _SEARCHBAR_H
#define _SEARCHBAR_H
#include <QRegExp>
#include "ui_SearchBar.h"
#include "HistorySearch.h"
class SearchBar : public QWidget {
Q_OBJECT
public:
SearchBar(QWidget* parent = 0);
virtual ~SearchBar();
virtual void show();
virtual void hide();
public slots:
void toggleShown();
signals:
void search(QRegExp regexp, bool forwards, bool skip);
private slots:
void searchTextChanged();
void findNext();
void findPrevious();
private:
QRegExp m_regExp;
Ui::SearchBar widget;
QAction *m_matchCaseMenuEntry;
QAction *m_useRegularExpressionMenuEntry;
QAction *m_highlightMatchesMenuEntry;
};
#endif /* _SEARCHBAR_H */
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SearchBar</class>
<widget class="QWidget" name="SearchBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>40</height>
</rect>
</property>
<property name="windowTitle">
<string>SearchBar</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="closeButton">
<property name="text">
<string>X</string>
</property>
<property name="icon">
<iconset theme="dialog-close">
<normaloff/>
</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="findLabel">
<property name="text">
<string>Find:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="searchTextEdit"/>
</item>
<item>
<widget class="QToolButton" name="findPreviousButton">
<property name="text">
<string>&lt;</string>
</property>
<property name="icon">
<iconset theme="go-previous">
<normaloff/>
</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="findNextButton">
<property name="text">
<string>&gt;</string>
</property>
<property name="icon">
<iconset theme="go-next">
<normaloff/>
</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="optionsButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normaloff/>
</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
<property name="arrowType">
<enum>Qt::DownArrow</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+66 -1
View File
@@ -16,7 +16,11 @@
Boston, MA 02110-1301, USA.
*/
#include <QLayout>
#include <QtGui/qboxlayout.h>
#include <QtGui/qlayoutitem.h>
#include <QtGui/qsizepolicy.h>
#include "SearchBar.h"
#include "qtermwidget.h"
#include "ColorTables.h"
@@ -27,6 +31,7 @@
#include "TerminalDisplay.h"
#include "KeyboardTranslator.h"
#include "ColorScheme.h"
#include "SearchBar.h"
#define STEP_ZOOM 3
@@ -121,6 +126,47 @@ void QTermWidget::selectionChanged(bool textSelected)
emit copyAvailable(textSelected);
}
void QTermWidget::search(QRegExp regexp, bool forwards, bool next)
{
int startColumn, startLine;
if (next) // search from end of current selection
{
m_impl->m_terminalDisplay->screenWindow()->screen()->getSelectionEnd(startColumn, startLine);
}
else // search from start of current selection
{
m_impl->m_terminalDisplay->screenWindow()->screen()->getSelectionStart(startColumn, startLine);
}
qDebug() << "current selection starts at: " << startColumn << startLine;
qDebug() << "current cursor position: " << m_impl->m_terminalDisplay->screenWindow()->cursorPosition();
HistorySearch *historySearch =
new HistorySearch(m_impl->m_session->emulation(), regexp, forwards, startColumn, startLine, this);
connect(historySearch, SIGNAL(matchFound(int, int, int, int)), this, SLOT(matchFound(int, int, int, int)));
connect(historySearch, SIGNAL(noMatchFound()), this, SLOT(noMatchFound()));
historySearch->search();
}
void QTermWidget::matchFound(int startColumn, int startLine, int endColumn, int endLine)
{
ScreenWindow* sw = m_impl->m_terminalDisplay->screenWindow();
qDebug() << "Scroll to" << startLine;
sw->scrollTo(startLine);
sw->setTrackOutput(false);
sw->notifyOutputChanged();
sw->setSelectionStart(startColumn, startLine - sw->currentLine(), false);
sw->setSelectionEnd(endColumn, endLine - sw->currentLine());
}
void QTermWidget::noMatchFound()
{
m_impl->m_terminalDisplay->screenWindow()->clearSelection();
}
int QTermWidget::getShellPID()
{
return m_impl->m_session->processId();
@@ -163,7 +209,19 @@ void QTermWidget::startShellProgram()
void QTermWidget::init(int startnow)
{
m_layout = new QVBoxLayout();
m_layout->setMargin(0);
setLayout(m_layout);
m_impl = new TermWidgetImpl(this);
m_impl->m_terminalDisplay->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
m_layout->addWidget(m_impl->m_terminalDisplay);
m_searchBar = new SearchBar(this);
m_searchBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
connect(m_searchBar, SIGNAL(search(QRegExp, bool, bool)), this, SLOT(search(QRegExp, bool, bool)));
m_layout->addWidget(m_searchBar);
m_searchBar->hide();
if (startnow && m_impl->m_session) {
m_impl->m_session->run();
@@ -188,6 +246,8 @@ void QTermWidget::init(int startnow)
font.setPointSize(10);
font.setStyleHint(QFont::TypeWriter);
setTerminalFont(font);
m_searchBar->setFont(font);
setScrollBarPosition(NoScrollBar);
m_impl->m_session->addView(m_impl->m_terminalDisplay);
@@ -386,6 +446,11 @@ QString QTermWidget::keyBindings()
return m_impl->m_session->keyBindings();
}
void QTermWidget::toggleShowSearchBar()
{
m_searchBar->toggleShown();
}
bool QTermWidget::flowControlEnabled(void)
{
return m_impl->m_session->flowControlEnabled();
+10
View File
@@ -23,6 +23,7 @@
#include <QtGui>
struct TermWidgetImpl;
class SearchBar;
class QTermWidget : public QWidget {
@@ -149,6 +150,8 @@ public slots:
*/
void clear();
void toggleShowSearchBar();
protected:
virtual void resizeEvent(QResizeEvent *);
@@ -156,10 +159,17 @@ protected slots:
void sessionFinished();
void selectionChanged(bool textSelected);
private slots:
void search(QRegExp, bool forwards, bool skip);
void matchFound(int startColumn, int startLine, int endColumn, int endLine);
void noMatchFound();
private:
void setZoom(int step);
void init(int startnow);
TermWidgetImpl * m_impl;
SearchBar* m_searchBar;
QVBoxLayout *m_layout;
};
+1
View File
@@ -14,6 +14,7 @@ set ( SRCS
#| qtermwidget Library
include_directories (
${PROJECT_SOURCE_DIR}/../lib
${CMAKE_CURRENT_BINARY_DIR}/../lib
)
set(QTERMWIDGET_LIB qtermwidget)
+12 -5
View File
@@ -21,17 +21,25 @@
#include <QtGui>
#include <QApplication>
#include <QtDebug>
#include <cstdlib>
#include <QIcon>
#include <QtGui/qicon.h>
#include "qtermwidget.h"
int main(int argc, char *argv[])
{
setenv("TERM", "xterm", 1);
QApplication app(argc, argv);
QApplication app(argc, argv);
QIcon::setThemeName("oxygen");
QMainWindow *mainWindow = new QMainWindow();
QTermWidget *console = new QTermWidget();
QMenuBar *menuBar = new QMenuBar(mainWindow);
QMenu *actionsMenu = new QMenu("Actions", menuBar);
menuBar->addMenu(actionsMenu);
actionsMenu->addAction("Find..", console, SLOT(toggleShowSearchBar()), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_F));
mainWindow->setMenuBar(menuBar);
QFont font = QApplication::font();
#ifdef Q_WS_MAC
@@ -71,4 +79,3 @@ int main(int argc, char *argv[])
return app.exec();
}