Actual QML port, moved from QWidget to QQuickPaintedItem. Setup of the project, added sample test-app.

This commit is contained in:
Filippo Scognamiglio
2014-11-06 01:45:17 +01:00
parent 92a5e5d37d
commit e9ee4c9091
13 changed files with 890 additions and 119 deletions
+57
View File
@@ -0,0 +1,57 @@
HEADERS += $$PWD/lib/BlockArray.h \
$$PWD/lib/CharacterColor.h \
$$PWD/lib/Character.h \
$$PWD/lib/ColorScheme.h \
$$PWD/lib/ColorTables.h \
$$PWD/lib/DefaultTranslatorText.h \
$$PWD/lib/Emulation.h \
$$PWD/lib/ExtendedDefaultTranslator.h \
$$PWD/lib/Filter.h \
$$PWD/lib/History.h \
$$PWD/lib/HistorySearch.h \
$$PWD/lib/KeyboardTranslator.h \
$$PWD/lib/konsole_wcwidth.h \
$$PWD/lib/kprocess.h \
$$PWD/lib/kptydevice.h \
$$PWD/lib/kpty.h \
$$PWD/lib/kpty_p.h \
$$PWD/lib/kptyprocess.h \
$$PWD/lib/LineFont.h \
$$PWD/lib/Pty.h \
$$PWD/lib/Screen.h \
$$PWD/lib/ScreenWindow.h \
#$$PWD/lib/SearchBar.h \
$$PWD/lib/Session.h \
$$PWD/lib/ShellCommand.h \
$$PWD/lib/TerminalCharacterDecoder.h \
$$PWD/lib/TerminalDisplay.h \
$$PWD/lib/tools.h \
$$PWD/lib/Vt102Emulation.h \
#$$PWD/lib/qtermwidget.h
SOURCES += $$PWD/lib/BlockArray.cpp \
$$PWD/lib/ColorScheme.cpp \
$$PWD/lib/Emulation.cpp \
$$PWD/lib/Filter.cpp \
$$PWD/lib/History.cpp \
$$PWD/lib/HistorySearch.cpp \
$$PWD/lib/KeyboardTranslator.cpp \
$$PWD/lib/konsole_wcwidth.cpp \
$$PWD/lib/kprocess.cpp \
$$PWD/lib/kpty.cpp \
$$PWD/lib/kptydevice.cpp \
$$PWD/lib/kptyprocess.cpp \
$$PWD/lib/Pty.cpp \
#$$PWD/lib/qtermwidget.cpp \
$$PWD/lib/Screen.cpp \
$$PWD/lib/ScreenWindow.cpp \
#$$PWD/lib/SearchBar.cpp \
$$PWD/lib/Session.cpp \
$$PWD/lib/ShellCommand.cpp \
$$PWD/lib/TerminalCharacterDecoder.cpp \
$$PWD/lib/TerminalDisplay.cpp \
$$PWD/lib/tools.cpp \
$$PWD/lib/Vt102Emulation.cpp
#FORMS = $$PWD/lib/SearchBar.ui
+1 -1
View File
@@ -69,7 +69,7 @@ Character* ScreenWindow::getImage()
if (!_bufferNeedsUpdate)
return _windowBuffer;
_screen->getImage(_windowBuffer,size,
currentLine(),endWindowLine());
+6 -10
View File
@@ -45,6 +45,9 @@
#include "ShellCommand.h"
#include "Vt102Emulation.h"
// QMLTermWidget
#include <QQuickWindow>
using namespace Konsole;
int Session::lastSessionId = 0;
@@ -133,15 +136,8 @@ WId Session::windowId() const
if ( _views.count() == 0 ) {
return 0;
} else {
QWidget * window = _views.first();
Q_ASSERT( window );
while ( window->parentWidget() != 0 ) {
window = window->parentWidget();
}
return window->winId();
QQuickWindow * window = _views.first()->window();
return (window ? window->winId() : 0);
}
}
@@ -510,7 +506,7 @@ void Session::updateTerminalSize()
//select largest number of lines and columns that will fit in all visible views
while ( viewIter.hasNext() ) {
TerminalDisplay * view = viewIter.next();
if ( view->isHidden() == false &&
if ( !view->isVisible() == false &&
view->lines() >= VIEW_LINES_THRESHOLD &&
view->columns() >= VIEW_COLUMNS_THRESHOLD ) {
minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() );
+263 -101
View File
@@ -100,7 +100,7 @@ const ColorEntry Konsole::base_color_table[TABLE_COLORS] =
// static
bool TerminalDisplay::_antialiasText = true;
bool TerminalDisplay::HAVE_TRANSPARENCY = true;
bool TerminalDisplay::HAVE_TRANSPARENCY = false;
// we use this to force QPainter to display text in LTR mode
// more information can be found in: http://unicode.org/reports/tr9/
@@ -138,11 +138,12 @@ void TerminalDisplay::setScreenWindow(ScreenWindow* window)
{
// TODO: Determine if this is an issue.
// TODO: Those two connections caused an additional painting. Determine if this is an issue.
//#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?"
connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) );
connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) );
connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateFilters()) );
connect( _screenWindow , SIGNAL(scrolled(int)) , this , SLOT(updateFilters()) );
//connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateFilters()) );
//connect( _screenWindow , SIGNAL(scrolled(int)) , this , SLOT(updateFilters()) );
window->setWindowLines(_lines);
}
}
@@ -263,8 +264,10 @@ void TerminalDisplay::setVTFont(const QFont& f)
qDebug() << "Using an unsupported variable-width font in the terminal. This may produce display errors.";
}
if ( metrics.height() < height() && metrics.maxWidth() < width() )
{
//TODO This if has been removed it would be better to understand if this is useful.
//if(font.pixelSize() > 0) {
// if ( metrics.height() < height() && metrics.maxWidth() < width() )
// {
// hint that text should be drawn without anti-aliasing.
// depending on the user's font configuration, this may not be respected
if (!_antialiasText)
@@ -275,13 +278,14 @@ void TerminalDisplay::setVTFont(const QFont& f)
// Disabling kerning saves some computation when rendering text.
font.setKerning(false);
QWidget::setFont(font);
m_font = font;
fontChange(font);
}
//}
}
void TerminalDisplay::setFont(const QFont &)
void TerminalDisplay::setFont(const QFont &f)
{
Q_UNUSED(f);
// ignore font change request if not coming from konsole itself
}
@@ -291,8 +295,8 @@ void TerminalDisplay::setFont(const QFont &)
/* */
/* ------------------------------------------------------------------------- */
TerminalDisplay::TerminalDisplay(QWidget *parent)
:QWidget(parent)
TerminalDisplay::TerminalDisplay(QQuickItem *parent)
:QQuickPaintedItem(parent)
,_screenWindow(0)
,_allowBell(true)
,_gridLayout(0)
@@ -339,10 +343,12 @@ TerminalDisplay::TerminalDisplay(QWidget *parent)
,_filterChain(new TerminalImageFilterChain())
,_cursorShape(BlockCursor)
,mMotionAfterPasting(NoMoveScreenWindow)
,m_font("Monospace", 12)
,m_color_role(QPalette::Background)
{
// terminal applications are not designed with Right-To-Left in mind,
// so the layout is forced to Left-To-Right
setLayoutDirection(Qt::LeftToRight);
//setLayoutDirection(Qt::LeftToRight);
// The offsets are not yet calculated.
// Do not calculate these too often to be more smoothly when resizing
@@ -350,9 +356,13 @@ TerminalDisplay::TerminalDisplay(QWidget *parent)
_topMargin = DEFAULT_TOP_MARGIN;
_leftMargin = DEFAULT_LEFT_MARGIN;
m_palette = qApp->palette();
setVTFont(m_font);
// create scroll bar for scrolling output up and down
// set the scroll bar's slider to occupy the whole area of the scroll bar initially
_scrollBar = new QScrollBar(this);
_scrollBar = new QScrollBar();
setScroll(0,0);
_scrollBar->setCursor( Qt::ArrowCursor );
connect(_scrollBar, SIGNAL(valueChanged(int)), this,
@@ -371,27 +381,31 @@ TerminalDisplay::TerminalDisplay(QWidget *parent)
setUsesMouse(true);
setColorTable(base_color_table);
setMouseTracking(true);
//setMouseTracking(true);
setAcceptedMouseButtons(Qt::LeftButton);
setFlags(ItemHasContents | ItemAcceptsInputMethod);
// Enable drag and drop
setAcceptDrops(true); // attempt
dragInfo.state = diNone;
// setAcceptDrops(true); // attempt
// dragInfo.state = diNone;
setFocusPolicy( Qt::WheelFocus );
// setFocusPolicy( Qt::WheelFocus );
// enable input method support
setAttribute(Qt::WA_InputMethodEnabled, true);
// setAttribute(Qt::WA_InputMethodEnabled, true);
// this is an important optimization, it tells Qt
// that TerminalDisplay will handle repainting its entire area.
setAttribute(Qt::WA_OpaquePaintEvent);
// setAttribute(Qt::WA_OpaquePaintEvent);
_gridLayout = new QGridLayout(this);
_gridLayout->setContentsMargins(0, 0, 0, 0);
// _gridLayout = new QGridLayout(this);
// _gridLayout->setContentsMargins(0, 0, 0, 0);
setLayout( _gridLayout );
// setLayout( _gridLayout );
new AutoScrollHandler(this);
// new AutoScrollHandler(this);
}
TerminalDisplay::~TerminalDisplay()
@@ -687,7 +701,7 @@ void TerminalDisplay::drawCharacters(QPainter& painter,
// don't draw text which is currently blinking
if ( _blinking && (style->rendition & RE_BLINK) )
return;
// setup bold and underline
bool useBold;
ColorEntry::FontWeight weight = style->fontWeight(_colorTable);
@@ -697,6 +711,8 @@ void TerminalDisplay::drawCharacters(QPainter& painter,
useBold = (weight == ColorEntry::Bold) ? true : false;
bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();
painter.setFont(font());
QFont font = painter.font();
if ( font.bold() != useBold
|| font.underline() != useUnderline )
@@ -890,7 +906,7 @@ void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion)
Q_ASSERT(scrollRect.isValid() && !scrollRect.isEmpty());
//scroll the display vertically to match internal _image
scroll( 0 , _fontHeight * (-lines) , scrollRect );
//scroll( 0 , _fontHeight * (-lines) , scrollRect );
}
QRegion TerminalDisplay::hotSpotRegion() const
@@ -951,7 +967,7 @@ void TerminalDisplay::processFilters()
update( preUpdateHotSpots | postUpdateHotSpots );
}
void TerminalDisplay::updateImage()
void TerminalDisplay::updateImage()
{
if ( !_screenWindow )
return;
@@ -1015,7 +1031,7 @@ void TerminalDisplay::updateImage()
for( x = 0 ; x < columnsToUpdate ; ++x)
{
if ( newLine[x] != currentLine[x] )
if ( newLine[x] != currentLine[x] )
{
dirtyMask[x] = true;
}
@@ -1140,32 +1156,32 @@ void TerminalDisplay::updateImage()
void TerminalDisplay::showResizeNotification()
{
if (_terminalSizeHint && isVisible())
{
if (_terminalSizeStartup) {
_terminalSizeStartup=false;
return;
}
if (!_resizeWidget)
{
_resizeWidget = new QLabel("Size: XXX x XXX", this);
_resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width("Size: XXX x XXX"));
_resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());
_resizeWidget->setAlignment(Qt::AlignCenter);
// if (_terminalSizeHint && isVisible())
// {
// if (_terminalSizeStartup) {
// _terminalSizeStartup=false;
// return;
// }
// if (!_resizeWidget)
// {
// _resizeWidget = new QLabel("Size: XXX x XXX", this);
// _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width("Size: XXX x XXX"));
// _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());
// _resizeWidget->setAlignment(Qt::AlignCenter);
_resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)");
// _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)");
_resizeTimer = new QTimer(this);
_resizeTimer->setSingleShot(true);
connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));
}
QString sizeStr = QString("Size: %1 x %2").arg(_columns).arg(_lines);
_resizeWidget->setText(sizeStr);
_resizeWidget->move((width()-_resizeWidget->width())/2,
(height()-_resizeWidget->height())/2+20);
_resizeWidget->show();
_resizeTimer->start(1000);
}
// _resizeTimer = new QTimer(this);
// _resizeTimer->setSingleShot(true);
// connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));
// }
// QString sizeStr = QString("Size: %1 x %2").arg(_columns).arg(_lines);
// _resizeWidget->setText(sizeStr);
// _resizeWidget->move((width()-_resizeWidget->width())/2,
// (height()-_resizeWidget->height())/2+20);
// _resizeWidget->show();
// _resizeTimer->start(1000);
// }
}
void TerminalDisplay::setBlinkingCursor(bool blink)
@@ -1227,20 +1243,32 @@ void TerminalDisplay::focusInEvent(QFocusEvent*)
_blinkTimer->start();
}
void TerminalDisplay::paintEvent( QPaintEvent* pe )
void TerminalDisplay::paint(QPainter *painter)
{
QPainter paint(this);
//contentsBoundingRect()
// TODO This function might be optimized.
QRect rect = contentsRect();
drawBackground(*painter, rect, m_palette.background().color(), false /* use opacity setting */);
drawContents(*painter, rect);
foreach (const QRect &rect, (pe->region() & contentsRect()).rects())
{
drawBackground(paint,rect,palette().background().color(),
true /* use opacity setting */);
drawContents(paint, rect);
}
drawInputMethodPreeditString(paint,preeditRect());
paintFilters(paint);
//drawInputMethodPreeditString(*painter, preeditRect());
//paintFilters(painter);
}
//void TerminalDisplay::paintEvent( QPaintEvent* pe )
//{
// QPainter paint(this);
// foreach (const QRect &rect, (pe->region() & contentsRect()).rects())
// {
// drawBackground(paint,rect,palette().background().color(),
// true /* use opacity setting */);
// drawContents(paint, rect);
// }
// drawInputMethodPreeditString(paint,preeditRect());
// paintFilters(paint);
//}
QPoint TerminalDisplay::cursorPosition() const
{
if (_screenWindow)
@@ -1290,7 +1318,7 @@ void TerminalDisplay::paintFilters(QPainter& painter)
{
// get color of character under mouse and use it to draw
// lines for filters
QPoint cursorPos = mapFromGlobal(QCursor::pos());
QPoint cursorPos = mapFromScene(QCursor::pos()).toPoint();
int cursorLine;
int cursorColumn;
int scrollBarWidth = (_scrollbarLocation == ScrollBarLeft) ? _scrollBar->width() : 0;
@@ -1383,7 +1411,7 @@ void TerminalDisplay::paintFilters(QPainter& painter)
int baseline = r.bottom() - metrics.descent();
// find the position of the underline below that
int underlinePos = baseline + metrics.underlinePos();
if ( region.contains( mapFromGlobal(QCursor::pos()) ) ){
if ( region.contains( mapFromScene(QCursor::pos()).toPoint() ) ){
painter.drawLine( r.left() , underlinePos ,
r.right() , underlinePos );
}
@@ -1409,6 +1437,9 @@ void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect)
int rlx = qMin(_usedColumns-1, qMax(0,(rect.right() - tLx - _leftMargin ) / _fontWidth));
int rly = qMin(_usedLines-1, qMax(0,(rect.bottom() - tLy - _topMargin ) / _fontHeight));
if(!_image)
return;
const int bufferSize = _usedColumns;
QString unistr;
unistr.reserve(bufferSize);
@@ -1587,9 +1618,9 @@ void TerminalDisplay::propagateSize()
if (_isFixedSize)
{
setSize(_columns, _lines);
QWidget::setFixedSize(sizeHint());
parentWidget()->adjustSize();
parentWidget()->setFixedSize(parentWidget()->sizeHint());
//QWidget::setFixedSize(sizeHint());
//parentWidget()->adjustSize();
//parentWidget()->setFixedSize(parentWidget()->sizeHint());
return;
}
if (_image)
@@ -1610,7 +1641,7 @@ void TerminalDisplay::updateImageSize()
if (oldimg)
{
for (int line = 0; line < lines; line++)
for (int line = 0; line < lines; line++)
{
memcpy((void*)&_image[_columns*line],
(void*)&oldimg[oldcol*line],columns*sizeof(Character));
@@ -1853,7 +1884,7 @@ void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev)
const QString& tooltip = spot->tooltip();
if ( !tooltip.isEmpty() )
{
QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea.boundingRect() );
//QToolTip::showText( mapToScene(ev->pos()).toPoint() , tooltip , this , _mouseOverHotspotArea.boundingRect() );
}
update( _mouseOverHotspotArea | previousHotspotArea );
@@ -2429,7 +2460,8 @@ bool TerminalDisplay::focusNextPrevChild( bool next )
if (next)
return false; // This disables changing the active part in konqueror
// when pressing Tab
return QWidget::focusNextPrevChild( next );
return false;
//return QWidget::focusNextPrevChild( next );
}
@@ -2738,7 +2770,7 @@ bool TerminalDisplay::event(QEvent* event)
default:
break;
}
return eventHandled ? true : QWidget::event(event);
return eventHandled ? true : QQuickItem::event(event);
}
void TerminalDisplay::setBellMode(int mode)
@@ -2874,7 +2906,9 @@ void TerminalDisplay::setSize(int columns, int lines)
if ( newSize != size() )
{
_size = newSize;
updateGeometry();
//updateGeometry();
//TODO Manage geometry change
}
}
@@ -2894,7 +2928,7 @@ void TerminalDisplay::setFixedSize(int cols, int lins)
makeImage();
}
setSize(cols, lins);
QWidget::setFixedSize(_size);
//QWidget::setFixedSize(_size);
}
QSize TerminalDisplay::sizeHint() const
@@ -2971,39 +3005,39 @@ void TerminalDisplay::doDrag()
void TerminalDisplay::outputSuspended(bool suspended)
{
//create the label when this function is first called
if (!_outputSuspendedLabel)
{
//This label includes a link to an English language website
//describing the 'flow control' (Xon/Xoff) feature found in almost
//all terminal emulators.
//If there isn't a suitable article available in the target language the link
//can simply be removed.
_outputSuspendedLabel = new QLabel( tr("<qt>Output has been "
"<a href=\"http://en.wikipedia.org/wiki/Flow_control\">suspended</a>"
" by pressing Ctrl+S."
" Press <b>Ctrl+Q</b> to resume.</qt>"),
this );
// if (!_outputSuspendedLabel)
// {
// //This label includes a link to an English language website
// //describing the 'flow control' (Xon/Xoff) feature found in almost
// //all terminal emulators.
// //If there isn't a suitable article available in the target language the link
// //can simply be removed.
// _outputSuspendedLabel = new QLabel( tr("<qt>Output has been "
// "<a href=\"http://en.wikipedia.org/wiki/Flow_control\">suspended</a>"
// " by pressing Ctrl+S."
// " Press <b>Ctrl+Q</b> to resume.</qt>"),
// this );
QPalette palette(_outputSuspendedLabel->palette());
//KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground);
_outputSuspendedLabel->setPalette(palette);
_outputSuspendedLabel->setAutoFillBackground(true);
_outputSuspendedLabel->setBackgroundRole(QPalette::Base);
_outputSuspendedLabel->setFont(QApplication::font());
_outputSuspendedLabel->setContentsMargins(5, 5, 5, 5);
// QPalette palette(_outputSuspendedLabel->palette());
// //KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground);
// _outputSuspendedLabel->setPalette(palette);
// _outputSuspendedLabel->setAutoFillBackground(true);
// _outputSuspendedLabel->setBackgroundRole(QPalette::Base);
// _outputSuspendedLabel->setFont(QApplication::font());
// _outputSuspendedLabel->setContentsMargins(5, 5, 5, 5);
//enable activation of "Xon/Xoff" link in label
_outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse |
Qt::LinksAccessibleByKeyboard);
_outputSuspendedLabel->setOpenExternalLinks(true);
_outputSuspendedLabel->setVisible(false);
// //enable activation of "Xon/Xoff" link in label
// _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse |
// Qt::LinksAccessibleByKeyboard);
// _outputSuspendedLabel->setOpenExternalLinks(true);
// _outputSuspendedLabel->setVisible(false);
_gridLayout->addWidget(_outputSuspendedLabel);
_gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding,
QSizePolicy::Expanding),
1,0);
// _gridLayout->addWidget(_outputSuspendedLabel);
// _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding,
// QSizePolicy::Expanding),
// 1,0);
}
// }
_outputSuspendedLabel->setVisible(suspended);
}
@@ -3036,7 +3070,7 @@ void AutoScrollHandler::timerEvent(QTimerEvent* event)
Qt::LeftButton,
Qt::NoModifier);
QApplication::sendEvent(widget(),&mouseEvent);
QApplication::sendEvent(widget(),&mouseEvent);
}
bool AutoScrollHandler::eventFilter(QObject* watched,QEvent* event)
{
@@ -3077,4 +3111,132 @@ bool AutoScrollHandler::eventFilter(QObject* watched,QEvent* event)
return false;
}
// QMLTermWidget specific functions ///////////////////////////////////////////
void TerminalDisplay::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
if (newGeometry != oldGeometry) {
resizeEvent(NULL);
update();
}
QQuickPaintedItem::geometryChanged(newGeometry,oldGeometry);
}
void TerminalDisplay::update(const QRegion &region)
{
Q_UNUSED(region);
// TODO this function might be optimized
// foreach (QRect rect, region.rects()) {
// QQuickPaintedItem::update(rect);
// }
QQuickPaintedItem::update();
}
void TerminalDisplay::update()
{
QQuickPaintedItem::update();
}
QRect TerminalDisplay::contentsRect() const
{
return QRect(0, 0, this->width(), this->height());
}
QSize TerminalDisplay::size() const
{
return QSize(this->width(), this->height());
}
void TerminalDisplay::setSession(KSession * session)
{
if (m_session != session) {
qDebug() << "SetSession called";
session->removeView(this);
m_session = session;
connect(this, SIGNAL(copyAvailable(bool)),
m_session, SLOT(selectionChanged(bool)));
connect(this, SIGNAL(termGetFocus()),
m_session, SIGNAL(termGetFocus()));
connect(this, SIGNAL(termLostFocus()),
m_session, SIGNAL(termLostFocus()));
connect(this, SIGNAL(keyPressedSignal(QKeyEvent *)),
m_session, SIGNAL(termKeyPressed(QKeyEvent *)));
m_session->addView(this);
setRandomSeed(m_session->getRandomSeed());
update();
emit sessionChanged();
}
}
KSession* TerminalDisplay::getSession()
{
return m_session;
}
QStringList TerminalDisplay::availableColorSchemes()
{
QStringList ret;
foreach (const ColorScheme* cs, ColorSchemeManager::instance()->allColorSchemes())
ret.append(cs->name());
return ret;
}
void TerminalDisplay::setColorScheme(const QString &name)
{
const ColorScheme *cs;
// avoid legacy (int) solution
if (!availableColorSchemes().contains(name))
cs = ColorSchemeManager::instance()->defaultColorScheme();
else
cs = ColorSchemeManager::instance()->findColorScheme(name);
if (! cs)
{
qDebug() << "Cannot load color scheme: " << name;
return;
}
ColorEntry table[TABLE_COLORS];
cs->getColorTable(table);
setColorTable(table);
}
void TerminalDisplay::simulateKeyPress(int key, int modifiers, bool pressed, quint32 nativeScanCode, const QString &text)
{
Q_UNUSED(nativeScanCode);
QEvent::Type type = pressed ? QEvent::KeyPress : QEvent::KeyRelease;
QKeyEvent event = QKeyEvent(type, key, (Qt::KeyboardModifier) modifiers, text);
keyPressedSignal(&event);
}
void TerminalDisplay::simulateWheel(int x, int y, int buttons, int modifiers, QPointF angleDelta){
QWheelEvent event(QPointF(x,y), angleDelta.y(), (Qt::MouseButton) buttons, (Qt::KeyboardModifier) modifiers);
wheelEvent(&event);
}
void TerminalDisplay::simulateMouseMove(int x, int y, int button, int buttons, int modifiers){
QMouseEvent event(QEvent::MouseMove, QPointF(x, y),(Qt::MouseButton) button, (Qt::MouseButtons) buttons, (Qt::KeyboardModifiers) modifiers);
mouseMoveEvent(&event);
}
void TerminalDisplay::simulateMousePress(int x, int y, int button, int buttons, int modifiers){
QMouseEvent event(QEvent::MouseButtonPress, QPointF(x, y),(Qt::MouseButton) button, (Qt::MouseButtons) buttons, (Qt::KeyboardModifiers) modifiers);
mousePressEvent(&event);
}
void TerminalDisplay::simulateMouseRelease(int x, int y, int button, int buttons, int modifiers){
QMouseEvent event(QEvent::MouseButtonRelease, QPointF(x, y),(Qt::MouseButton) button, (Qt::MouseButtons) buttons, (Qt::KeyboardModifiers) modifiers);
mouseReleaseEvent(&event);
}
void TerminalDisplay::simulateMouseDoubleClick(int x, int y, int button, int buttons, int modifiers){
QMouseEvent event(QEvent::MouseButtonDblClick, QPointF(x, y),(Qt::MouseButton) button, (Qt::MouseButtons) buttons, (Qt::KeyboardModifiers) modifiers);
mouseDoubleClickEvent(&event);
}
//#include "TerminalDisplay.moc"
+55 -5
View File
@@ -24,7 +24,8 @@
// Qt
#include <QColor>
#include <QPointer>
#include <QWidget>
//#include <QWidget>
#include <QQuickPaintedItem>
// Konsole
#include "Filter.h"
@@ -32,6 +33,10 @@
//#include "konsole_export.h"
#define KONSOLEPRIVATE_EXPORT
// QMLTermWidget
#include "ksession.h"
#include "ColorScheme.h"
class QDrag;
class QDragEnterEvent;
class QDropEvent;
@@ -75,13 +80,17 @@ class ScreenWindow;
*
* TODO More documentation
*/
class KONSOLEPRIVATE_EXPORT TerminalDisplay : public QWidget
class KONSOLEPRIVATE_EXPORT TerminalDisplay : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(KSession* session READ getSession WRITE setSession NOTIFY sessionChanged)
Q_PROPERTY(QFont font READ getVTFont WRITE setVTFont )
Q_PROPERTY(QString colorScheme WRITE setColorScheme )
public:
/** Constructs a new terminal display widget with the specified parent. */
TerminalDisplay(QWidget *parent=0);
TerminalDisplay(QQuickItem *parent=0);
virtual ~TerminalDisplay();
/** Returns the terminal color palette used by the display. */
@@ -431,7 +440,7 @@ public:
// maps a point on the widget to the position ( ie. line and column )
// of the character at that point.
void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const;
void getCharacterPosition(const QPoint &widgetPoint, int& line, int& column) const;
public slots:
@@ -525,6 +534,17 @@ public slots:
void selectionChanged();
// QMLTermWidget
void setColorScheme(const QString &name);
QStringList availableColorSchemes();
void simulateKeyPress(int key, int modifiers, bool pressed, quint32 nativeScanCode, const QString &text);
void simulateWheel(int x, int y, int buttons, int modifiers, QPointF angleDelta);
void simulateMouseMove(int x, int y, int button, int buttons, int modifiers);
void simulateMousePress(int x, int y, int button, int buttons, int modifiers);
void simulateMouseRelease(int x, int y, int button, int buttons, int modifiers);
void simulateMouseDoubleClick(int x, int y, int button, int buttons, int modifiers);
signals:
/**
@@ -572,10 +592,13 @@ signals:
void notifyBell(const QString&);
// QMLTermWidget
void sessionChanged();
protected:
virtual bool event( QEvent * );
virtual void paintEvent( QPaintEvent * );
//virtual void paintEvent( QPaintEvent * );
virtual void showEvent(QShowEvent*);
virtual void hideEvent(QHideEvent*);
@@ -622,6 +645,10 @@ protected:
virtual void inputMethodEvent ( QInputMethodEvent* event );
virtual QVariant inputMethodQuery( Qt::InputMethodQuery query ) const;
// QMLTermWidget
void paint(QPainter * painter);
virtual void geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry);
protected slots:
void scrollBarPositionChanged(int value);
@@ -831,6 +858,29 @@ private:
static const int DEFAULT_LEFT_MARGIN = 1;
static const int DEFAULT_TOP_MARGIN = 1;
// QMLTermWidget port functions
QFont m_font;
QPalette m_palette;
QPalette::ColorRole m_color_role;
KSession *m_session;
QFont font() const { return m_font; }
const QPalette palette() { return m_palette; }
void setPalette(const QPalette &p){ m_palette = p; }
QPalette::ColorRole backgroundRole() { return m_color_role; }
void setBackgroundRole(QPalette::ColorRole role) { m_color_role = role; }
void update(const QRegion &region);
void update();
QRect contentsRect() const;
QSize size() const;
void setSession(KSession *session);
KSession* getSession();
public:
static void setTransparencyEnabled(bool enable)
{
+2 -2
View File
@@ -17,7 +17,7 @@ QString get_kb_layout_dir()
// qDebug() << __FILE__ << __FUNCTION__;
QString rval = "";
QString k(KB_LAYOUT_DIR);
QString k(qgetenv("KB_LAYOUT_DIR"));
QDir d(k);
qDebug() << "default KB_LAYOUT_DIR: " << k;
@@ -55,7 +55,7 @@ QString get_color_schemes_dir()
// qDebug() << __FILE__ << __FUNCTION__;
QString rval = "";
QString k(COLORSCHEMES_DIR);
QString k(qgetenv("COLORSCHEMES_DIR"));
QDir d(k);
// qDebug() << "default COLORSCHEMES_DIR: " << k;
+26
View File
@@ -0,0 +1,26 @@
TEMPLATE = lib
TARGET = qmltermwidget
QT += qml quick widgets
CONFIG += qt plugin
include(lib.pri)
DESTDIR = $$OUT_PWD/QMLTermWidget
DEFINES += HAVE_POSIX_OPENPT HAVE_SYS_TIME_H
!macx:DEFINES += HAVE_UPDWTMPX
INCLUDEPATH += $$PWD/lib
DEPENDPATH += $$PWD/lib
INCLUDEPATH += $$PWD/src
HEADERS += $$PWD/src/qmltermwidget_plugin.h \
$$PWD/src/ksession.h
SOURCES += $$PWD/src/qmltermwidget_plugin.cpp \
$$PWD/src/ksession.cpp
# Copy the files useful to the plugin in DESTDIR
QMAKE_POST_LINK = $(COPY_DIR) $$PWD/lib/color-schemes $$DESTDIR && \
$(COPY_DIR) $$PWD/lib/kb-layouts $$DESTDIR && \
$$QMAKE_COPY $$PWD/src/qmldir $$DESTDIR
+248
View File
@@ -0,0 +1,248 @@
/*
This file is part of Konsole QML plugin,
which is a terminal emulator from KDE.
Copyright 2013 by Dmitry Zagnoyko <hiroshidi@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.
*/
// Own
#include "ksession.h"
// Qt
#include <QTextCodec>
// Konsole
#include "KeyboardTranslator.h"
KSession::KSession(QObject *parent) :
QObject(parent), m_session(createSession(""))
{
connect(m_session, SIGNAL(finished()), this, SLOT(sessionFinished()));
connect(m_session, SIGNAL(titleChanged()), this, SIGNAL(titleChanged()));
}
KSession::~KSession()
{
if (m_session) {
m_session->close();
m_session->disconnect();
delete m_session;
}
}
void KSession::setTitle(QString name)
{
m_session->setTitle(Session::NameRole, name);
}
Session *KSession::createSession(QString name)
{
Session *session = new Session();
session->setTitle(Session::NameRole, name);
/* Thats a freaking bad idea!!!!
* /bin/bash is not there on every system
* better set it to the current $SHELL
* Maybe you can also make a list available and then let the widget-owner decide what to use.
* By setting it to $SHELL right away we actually make the first filecheck obsolete.
* But as iam not sure if you want to do anything else ill just let both checks in and set this to $SHELL anyway.
*/
//cool-old-term: There is another check in the code. Not sure if useful.
QString envshell = getenv("SHELL");
QString shellProg = envshell != NULL ? envshell : "/bin/bash";
session->setProgram(shellProg);
setenv("TERM", "xterm", 1);
//session->setProgram();
QStringList args("");
session->setArguments(args);
session->setAutoClose(true);
session->setCodec(QTextCodec::codecForName("UTF-8"));
session->setFlowControlEnabled(true);
session->setHistoryType(HistoryTypeBuffer(1000));
session->setDarkBackground(true);
session->setKeyBindings("");
return session;
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
int KSession::getRandomSeed()
{
return m_session->sessionId() * 31;
}
void KSession::addView(TerminalDisplay *display)
{
m_session->addView(display);
}
void KSession::removeView(TerminalDisplay *display)
{
m_session->removeView(display);
}
void KSession::sessionFinished()
{
emit finished();
}
void KSession::selectionChanged(bool textSelected)
{
Q_UNUSED(textSelected)
}
void KSession::startShellProgram()
{
if ( m_session->isRunning() ) {
return;
}
m_session->run();
}
int KSession::getShellPID()
{
return m_session->processId();
}
void KSession::changeDir(const QString &dir)
{
/*
this is a very hackish way of trying to determine if the shell is in
the foreground before attempting to change the directory. It may not
be portable to anything other than Linux.
*/
QString strCmd;
strCmd.setNum(getShellPID());
strCmd.prepend("ps -j ");
strCmd.append(" | tail -1 | awk '{ print $5 }' | grep -q \\+");
int retval = system(strCmd.toStdString().c_str());
if (!retval) {
QString cmd = "cd " + dir + "\n";
sendText(cmd);
}
}
void KSession::setEnvironment(const QStringList &environment)
{
m_session->setEnvironment(environment);
}
void KSession::setShellProgram(const QString &progname)
{
m_session->setProgram(progname);
}
void KSession::setInitialWorkingDirectory(const QString &dir)
{
_initialWorkingDirectory = dir;
m_session->setInitialWorkingDirectory(dir);
}
QString KSession::getInitialWorkingDirectory()
{
return _initialWorkingDirectory;
}
void KSession::setArgs(QStringList &args)
{
m_session->setArguments(args);
}
void KSession::setTextCodec(QTextCodec *codec)
{
m_session->setCodec(codec);
}
void KSession::setHistorySize(int lines)
{
if (lines < 0)
m_session->setHistoryType(HistoryTypeFile());
else
m_session->setHistoryType(HistoryTypeBuffer(lines));
}
void KSession::sendText(QString text)
{
m_session->sendText(text);
}
void KSession::sendKey(int rep, int key, int mod) const
{
//TODO implement or remove this function.
// Qt::KeyboardModifier kbm = Qt::KeyboardModifier(mod);
// QKeyEvent qkey(QEvent::KeyPress, key, kbm);
// while (rep > 0){
// m_session->sendKey(&qkey);
// --rep;
// }
}
void KSession::setFlowControlEnabled(bool enabled)
{
m_session->setFlowControlEnabled(enabled);
}
bool KSession::flowControlEnabled()
{
return m_session->flowControlEnabled();
}
void KSession::setKeyBindings(const QString &kb)
{
m_session->setKeyBindings(kb);
emit changedKeyBindings(kb);
}
QString KSession::getKeyBindings()
{
return m_session->keyBindings();
}
QStringList KSession::availableKeyBindings()
{
return KeyboardTranslatorManager::instance()->allTranslators();
}
QString KSession::keyBindings()
{
return m_session->keyBindings();
}
QString KSession::getTitle()
{
return m_session->userTitle();
}
+142
View File
@@ -0,0 +1,142 @@
/*
This file is part of Konsole QML plugin,
which is a terminal emulator from KDE.
Copyright 2013 by Dmitry Zagnoyko <hiroshidi@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 KSESSION_H
#define KSESSION_H
#include <QObject>
// Konsole
#include "Session.h"
//#include "TerminalDisplay.h"
using namespace Konsole;
class KSession : public QObject
{
Q_OBJECT
Q_PROPERTY(QString kbScheme READ getKeyBindings WRITE setKeyBindings NOTIFY changedKeyBindings)
Q_PROPERTY(QString initialWorkingDirectory READ getInitialWorkingDirectory WRITE setInitialWorkingDirectory)
Q_PROPERTY(QString title READ getTitle NOTIFY titleChanged)
Q_PROPERTY(QString shellProgram WRITE setShellProgram)
public:
KSession(QObject *parent = 0);
~KSession();
public:
//bool setup();
void addView(TerminalDisplay *display);
void removeView(TerminalDisplay *display);
int getRandomSeed();
QString getKeyBindings();
//look-n-feel, if you don`t like defaults
//environment
void setEnvironment(const QStringList & environment);
//Initial working directory
void setInitialWorkingDirectory(const QString & dir);
QString getInitialWorkingDirectory();
// Shell program args, default is none
void setArgs(QStringList & args);
//Text codec, default is UTF-8
void setTextCodec(QTextCodec * codec);
// History size for scrolling
void setHistorySize(int lines); //infinite if lines < 0
// Sets whether flow control is enabled
void setFlowControlEnabled(bool enabled);
// Returns whether flow control is enabled
bool flowControlEnabled(void);
/**
* Sets whether the flow control warning box should be shown
* when the flow control stop key (Ctrl+S) is pressed.
*/
//void setFlowControlWarningEnabled(bool enabled);
/*! Get all available keyboard bindings
*/
static QStringList availableKeyBindings();
//! Return current key bindings
QString keyBindings();
QString getTitle();
signals:
void finished();
void copyAvailable(bool);
void termGetFocus();
void termLostFocus();
void termKeyPressed(QKeyEvent *);
void changedKeyBindings(QString kb);
void titleChanged();
public slots:
/*! Set named key binding for given widget
*/
void setKeyBindings(const QString & kb);
void setTitle(QString name);
void startShellProgram();
// Shell program, default is /bin/bash
void setShellProgram(const QString & progname);
int getShellPID();
void changeDir(const QString & dir);
// Send some text to terminal
void sendText(QString text);
// Send some text to terminal
void sendKey(int rep, int key, int mod) const;
protected slots:
void sessionFinished();
void selectionChanged(bool textSelected);
private slots:
Session* createSession(QString name);
//Konsole::KTerminalDisplay* createTerminalDisplay(Konsole::Session *session, QQuickItem* parent);
private:
//Konsole::KTerminalDisplay *m_terminalDisplay;
QString _initialWorkingDirectory;
Session *m_session;
};
#endif // KSESSION_H
+3
View File
@@ -0,0 +1,3 @@
module QMLTermWidget
plugin qmltermwidget
+38
View File
@@ -0,0 +1,38 @@
#include "qmltermwidget_plugin.h"
#include "TerminalDisplay.h"
#include "ksession.h"
#include <qqml.h>
#include <QQmlEngine>
#include <QDir>
using namespace Konsole;
void QmltermwidgetPlugin::registerTypes(const char *uri)
{
// @uri org.qterminal.qmlterminal
qmlRegisterType<TerminalDisplay>(uri, 1, 0, "QMLTermWidget");
qmlRegisterType<KSession>(uri, 1, 0, "QMLTermSession");
}
void QmltermwidgetPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
{
QQmlExtensionPlugin::initializeEngine(engine, uri);
QStringList pwds = engine->importPathList();
if (!pwds.empty()){
QString cs, kbl;
foreach (QString pwd, pwds) {
cs = pwd + "/QMLTermWidget/color-schemes";
kbl = pwd + "/QMLTermWidget/kb-layouts";
if (QDir(cs).exists()) break;
}
setenv("KB_LAYOUT_DIR",kbl.toUtf8().constData(),1);
setenv("COLORSCHEMES_DIR",cs.toUtf8().constData(),1);
}
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef QMLTERMWIDGET_PLUGIN_H
#define QMLTERMWIDGET_PLUGIN_H
#include <QQmlExtensionPlugin>
class QmltermwidgetPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qterminal.qmlterminal.QMLTermWidget")
public:
void registerTypes(const char *uri);
void initializeEngine(QQmlEngine *engine, const char *uri);
};
#endif // QMLTERMWIDGET_PLUGIN_H
+32
View File
@@ -0,0 +1,32 @@
import QtQuick 2.0
import QMLTermWidget 1.0
import QtQuick.Controls 1.2
Rectangle {
width: 640
height: 480
Action{
onTriggered: terminal.copyClipboard();
shortcut: "Ctrl+Shift+C"
}
Action{
onTriggered: terminal.pasteClipboard();
shortcut: "Ctrl+Shift+V"
}
QMLTermWidget {
id: terminal
anchors.fill: parent
font.family: "Monospace"
font.pointSize: 12
colorScheme: "DarkPastels"
session: QMLTermSession{
id: mainsession
initialWorkingDirectory: "$HOME"
}
Component.onCompleted: mainsession.startShellProgram();
}
Component.onCompleted: terminal.forceActiveFocus();
}