Cherry-picked upstream version 0.8.0.

ubuntu/cosmic
Alf Gaida 7 years ago
parent ccc166214d
commit e7d4039a1b

@ -1,7 +1,53 @@
qtermwidget-0.7.1 / 2016-12-21 qtermwidget-0.8.0 / 2017-10-21
============================== ==============================
* FIX: #46 fix vertical font truncation
* bump versions
* Really fallback to /bin/sh when $SHELL is missing or invalid
* README: don't recommend building from source
* Improve README
* Don't export github templates
* Support REP escape sequence defined in ECMA-48, section 8.3.103
* Fix build issue related to utmpx in Mac OSX Sierra
* Remove the deprecation notice
* Handle DECSCUSR signals
* Copied issue template
* Update building instructions
* Require Qt 5.6+
* This commit allows the consumer of qtermwidget to capture the (#111)
* Allow the terminal display to be smaller than the size hint (#123)
* Backport Vt102 emulation fixes (#113)
* Backport the default.keytab from Konsole
* Fixes (#122)
* Updated README, Added support for PyQT 5.7
* Fix memory leak in hotspot (URLs & emails) detection
* Adds superbuild support
* Use target_compile_definitions() instead of add_definitions()
* Update find_package() documentation
* Use the lxqt_create_pkgconfig_file
* Improve lxqt_translate_ts() use
* Adds COMPONENT to the install files
* Renames test app to example. Make it work
* Drop include_directories() for in tree dirs
* Use the CMake Targets way
* Pack Utf8Proc stuff
* Adds export header
* Use LXQtCompilerSettings
* Packs compile definitions
* Adds package version file
* Removes Qt4 stuff
* Add translation mechanism
* Use const iterators when possible.
* Enable strict iterators for debug builds
* TerminalDisplay: Make resizing "Size" translatable
* Exposes receivedData signal to users of QTermWidget
* Exposes sessions autoClose property to QTermWidget
0.7.1 / 2016-12-21
==================
* Release 0.7.1: Update changelog
* Bump patch version (#105) * Bump patch version (#105)
* Added a modified Breeze color scheme (#104) * Added a modified Breeze color scheme (#104)
* Accept hex color strings as well (#101) * Accept hex color strings as well (#101)

@ -3,54 +3,44 @@ cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
project(qtermwidget) project(qtermwidget)
include(GNUInstallDirs) include(GNUInstallDirs)
include(GenerateExportHeader)
include(CMakePackageConfigHelpers)
include(CheckFunctionExists) include(CheckFunctionExists)
option(BUILD_TEST "Build test application. Default OFF." OFF) set(REQUIRED_QT_VERSION "5.6")
set(LXQTBT_MINIMUM_VERSION "0.4.0")
option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF)
option(BUILD_EXAMPLE "Build example application. Default OFF." OFF)
# just change version for releases # just change version for releases
set(QTERMWIDGET_VERSION_MAJOR "0") set(QTERMWIDGET_VERSION_MAJOR "0")
set(QTERMWIDGET_VERSION_MINOR "7") set(QTERMWIDGET_VERSION_MINOR "8")
set(QTERMWIDGET_VERSION_PATCH "1") set(QTERMWIDGET_VERSION_PATCH "0")
set(QTERMWIDGET_VERSION "${QTERMWIDGET_VERSION_MAJOR}.${QTERMWIDGET_VERSION_MINOR}.${QTERMWIDGET_VERSION_PATCH}") set(QTERMWIDGET_VERSION "${QTERMWIDGET_VERSION_MAJOR}.${QTERMWIDGET_VERSION_MINOR}.${QTERMWIDGET_VERSION_PATCH}")
# additional cmake files # additional cmake files
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release) set(CMAKE_BUILD_TYPE Release)
endif() endif()
include(CheckCXXCompilerFlag) set(CMAKE_INCLUDE_CURRENT_DIR ON)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(FATAL "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. C++11 support is required")
endif()
include_directories(
"${CMAKE_SOURCE_DIR}/lib"
"${CMAKE_BINARY_DIR}/lib"
"${CMAKE_BINARY_DIR}"
)
add_definitions(-Wall)
find_package(Qt5Widgets "${REQUIRED_QT_VERSION}" REQUIRED)
find_package(Qt5LinguistTools "${REQUIRED_QT_VERSION}" REQUIRED)
find_package(lxqt-build-tools ${LXQTBT_MINIMUM_VERSION} REQUIRED)
include(LXQtTranslateTs)
include(LXQtCompilerSettings NO_POLICY_SCOPE)
include(LXQtCreatePkgConfigFile)
set(QTERMWIDGET_LIBRARY_NAME qtermwidget5) set(QTERMWIDGET_LIBRARY_NAME qtermwidget5)
include(qtermwidget5_use)
option(USE_UTF8PROC "Use libutf8proc for better Unicode support. Default OFF" OFF) option(USE_UTF8PROC "Use libutf8proc for better Unicode support. Default OFF" OFF)
if(USE_UTF8PROC) if(USE_UTF8PROC)
find_package(Utf8Proc) find_package(Utf8Proc REQUIRED)
endif()
if (UTF8PROC_FOUND)
add_definitions(-DHAVE_UTF8PROC)
include_directories("${UTF8PROC_INCLUDE_DIRS}")
endif() endif()
# main library # main library
@ -105,86 +95,200 @@ set(UI
# for distribution # for distribution
set(HDRS_DISTRIB set(HDRS_DISTRIB
lib/qtermwidget.h lib/qtermwidget.h
lib/Emulation.h
lib/Filter.h lib/Filter.h
) )
# dirs # dirs
set(KB_LAYOUT_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${QTERMWIDGET_LIBRARY_NAME}/kb-layouts") set(KB_LAYOUT_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${QTERMWIDGET_LIBRARY_NAME}/kb-layouts")
message(STATUS "Keyboard layouts will be installed in: ${KB_LAYOUT_DIR}") message(STATUS "Keyboard layouts will be installed in: ${KB_LAYOUT_DIR}")
add_definitions(-DKB_LAYOUT_DIR="${KB_LAYOUT_DIR}")
set(COLORSCHEMES_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${QTERMWIDGET_LIBRARY_NAME}/color-schemes") set(COLORSCHEMES_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${QTERMWIDGET_LIBRARY_NAME}/color-schemes")
message(STATUS "Color schemes will be installed in: ${COLORSCHEMES_DIR}" ) message(STATUS "Color schemes will be installed in: ${COLORSCHEMES_DIR}" )
add_definitions(-DCOLORSCHEMES_DIR="${COLORSCHEMES_DIR}")
set(TRANSLATIONS_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${QTERMWIDGET_LIBRARY_NAME}/translations")
message(STATUS "Translations will be installed in: ${TRANSLATIONS_DIR}")
set(QTERMWIDGET_INCLUDE_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/${QTERMWIDGET_LIBRARY_NAME}") set(QTERMWIDGET_INCLUDE_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/${QTERMWIDGET_LIBRARY_NAME}")
#| Defines
add_definitions(-DHAVE_POSIX_OPENPT -DHAVE_SYS_TIME_H)
if(APPLE)
add_definitions(-DHAVE_UTMPX -D_UTMPX_COMPAT)
endif()
CHECK_FUNCTION_EXISTS(updwtmpx HAVE_UPDWTMPX) CHECK_FUNCTION_EXISTS(updwtmpx HAVE_UPDWTMPX)
if(HAVE_UPDWTMPX)
add_definitions(-DHAVE_UPDWTMPX)
endif()
qt5_wrap_cpp(MOCS ${HDRS}) qt5_wrap_cpp(MOCS ${HDRS})
qt5_wrap_ui(UI_SRCS ${UI}) qt5_wrap_ui(UI_SRCS ${UI})
set(PKG_CONFIG_REQ "Qt5Core, Qt5Xml, Qt5Widgets") set(PKG_CONFIG_REQ "Qt5Widgets")
add_library(${QTERMWIDGET_LIBRARY_NAME} SHARED ${SRCS} ${MOCS} ${UI_SRCS}) lxqt_translate_ts(QTERMWIDGET_QM
target_link_libraries(${QTERMWIDGET_LIBRARY_NAME} ${QTERMWIDGET_QT_LIBRARIES}) TRANSLATION_DIR "lib/translations"
UPDATE_TRANSLATIONS
${UPDATE_TRANSLATIONS}
SOURCES
${SRCS} ${HDRS} ${UI}
PULL_TRANSLATIONS
${PULL_TRANSLATIONS}
CLEAN_TRANSLATIONS
${CLEAN_TRANSLATIONS}
TRANSLATIONS_REPO
${TRANSLATIONS_REPO}
TRANSLATIONS_REFSPEC
${TRANSLATIONS_REFSPEC}
INSTALL_DIR
${TRANSLATIONS_DIR}
COMPONENT
Runtime
)
add_library(${QTERMWIDGET_LIBRARY_NAME} SHARED ${SRCS} ${MOCS} ${UI_SRCS} ${QTERMWIDGET_QM})
target_link_libraries(${QTERMWIDGET_LIBRARY_NAME} Qt5::Widgets)
set_target_properties( ${QTERMWIDGET_LIBRARY_NAME} PROPERTIES set_target_properties( ${QTERMWIDGET_LIBRARY_NAME} PROPERTIES
SOVERSION ${QTERMWIDGET_VERSION_MAJOR} SOVERSION ${QTERMWIDGET_VERSION_MAJOR}
VERSION ${QTERMWIDGET_VERSION} VERSION ${QTERMWIDGET_VERSION}
) )
if(APPLE)
target_compile_definitions(${QTERMWIDGET_LIBRARY_NAME}
PRIVATE
"HAVE_UTMPX"
"UTMPX_COMPAT"
)
endif()
if(HAVE_UPDWTMPX)
target_compile_definitions(${QTERMWIDGET_LIBRARY_NAME}
PRIVATE
"HAVE_UPDWTMPX"
)
endif()
if (UTF8PROC_FOUND) if (UTF8PROC_FOUND)
target_link_libraries(${QTERMWIDGET_LIBRARY_NAME} ${UTF8PROC_LIBRARIES}) target_compile_definitions(${QTERMWIDGET_LIBRARY_NAME}
PRIVATE
"HAVE_UTF8PROC"
)
target_include_directories(${QTERMWIDGET_LIBRARY_NAME}
INTERFACE
${UTF8PROC_INCLUDE_DIRS}
)
target_link_libraries(${QTERMWIDGET_LIBRARY_NAME}
${UTF8PROC_LIBRARIES}
)
string(APPEND PKG_CONFIG_REQ ", libutf8proc")
endif() endif()
if(APPLE) if(APPLE)
set (CMAKE_SKIP_RPATH 1) set (CMAKE_SKIP_RPATH 1)
# this is a must to load the lib correctly # this is a must to load the lib correctly
set_target_properties(${QTERMWIDGET_LIBRARY_NAME} PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR}) set_target_properties(${QTERMWIDGET_LIBRARY_NAME} PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
endif() endif()
install(TARGETS ${QTERMWIDGET_LIBRARY_NAME} DESTINATION "${CMAKE_INSTALL_LIBDIR}") target_compile_definitions(${QTERMWIDGET_LIBRARY_NAME}
install(FILES ${HDRS_DISTRIB} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTERMWIDGET_LIBRARY_NAME}") PRIVATE
"KB_LAYOUT_DIR=\"${KB_LAYOUT_DIR}\""
"COLORSCHEMES_DIR=\"${COLORSCHEMES_DIR}\""
"TRANSLATIONS_DIR=\"${TRANSLATIONS_DIR}\""
"HAVE_POSIX_OPENPT"
"HAVE_SYS_TIME_H"
)
generate_export_header(${QTERMWIDGET_LIBRARY_NAME}
EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/lib/qtermwidget_export.h"
EXPORT_MACRO_NAME QTERMWIDGET_EXPORT
)
target_include_directories(${QTERMWIDGET_LIBRARY_NAME}
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/lib>"
INTERFACE
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${QTERMWIDGET_LIBRARY_NAME}>"
)
write_basic_package_version_file(
"${CMAKE_BINARY_DIR}/${QTERMWIDGET_LIBRARY_NAME}-config-version.cmake"
VERSION ${QTERMWIDGET_VERSION}
COMPATIBILITY AnyNewerVersion
)
install(FILES
"${CMAKE_BINARY_DIR}/${QTERMWIDGET_LIBRARY_NAME}-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTERMWIDGET_LIBRARY_NAME}"
COMPONENT Devel
)
install(EXPORT
"${QTERMWIDGET_LIBRARY_NAME}-targets"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTERMWIDGET_LIBRARY_NAME}"
COMPONENT Devel
)
install(FILES
${HDRS_DISTRIB} "${CMAKE_CURRENT_BINARY_DIR}/lib/qtermwidget_export.h"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTERMWIDGET_LIBRARY_NAME}"
COMPONENT Devel
)
# keyboard layouts # keyboard layouts
install(DIRECTORY lib/kb-layouts/ DESTINATION "${KB_LAYOUT_DIR}" FILES_MATCHING PATTERN "*.keytab" ) install(DIRECTORY
lib/kb-layouts/
DESTINATION "${KB_LAYOUT_DIR}"
COMPONENT Runtime
FILES_MATCHING PATTERN "*.keytab"
)
# color schemes # color schemes
install(DIRECTORY lib/color-schemes/ DESTINATION "${COLORSCHEMES_DIR}" FILES_MATCHING PATTERN "*.*schem*") install(DIRECTORY
lib/color-schemes/
DESTINATION "${COLORSCHEMES_DIR}"
COMPONENT Runtime
FILES_MATCHING PATTERN "*.*schem*"
)
include(create_pkgconfig_file) lxqt_create_pkgconfig_file(
create_pkgconfig_file(${QTERMWIDGET_LIBRARY_NAME} PACKAGE_NAME ${QTERMWIDGET_LIBRARY_NAME}
"QTermWidget library for Qt ${QTERMWIDGET_VERSION_MAJOR}.x" DESCRIPTIVE_NAME ${QTERMWIDGET_LIBRARY_NAME}
${PKG_CONFIG_REQ} DESCRIPTION "QTermWidget library for Qt ${QTERMWIDGET_VERSION_MAJOR}.x"
${QTERMWIDGET_LIBRARY_NAME} INCLUDEDIRS ${QTERMWIDGET_LIBRARY_NAME}
${QTERMWIDGET_VERSION} LIBS ${QTERMWIDGET_LIBRARY_NAME}
REQUIRES ${PKG_CONFIG_REQ}
VERSION ${QTERMWIDGET_VERSION}
INSTALL
COMPONENT Devel
) )
configure_file( configure_file(
"${CMAKE_SOURCE_DIR}/cmake/${QTERMWIDGET_LIBRARY_NAME}-config.cmake.in" "${PROJECT_SOURCE_DIR}/cmake/${QTERMWIDGET_LIBRARY_NAME}-config.cmake.in"
"${CMAKE_BINARY_DIR}/${QTERMWIDGET_LIBRARY_NAME}-config.cmake" "${CMAKE_BINARY_DIR}/${QTERMWIDGET_LIBRARY_NAME}-config.cmake"
@ONLY @ONLY
) )
install(FILES install(FILES
"${CMAKE_BINARY_DIR}/${QTERMWIDGET_LIBRARY_NAME}-config.cmake" "${CMAKE_BINARY_DIR}/${QTERMWIDGET_LIBRARY_NAME}-config.cmake"
"${CMAKE_SOURCE_DIR}/cmake/${QTERMWIDGET_LIBRARY_NAME}_use.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTERMWIDGET_LIBRARY_NAME}" DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTERMWIDGET_LIBRARY_NAME}"
COMPONENT Devel
)
install(TARGETS ${QTERMWIDGET_LIBRARY_NAME}
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
EXPORT "${QTERMWIDGET_LIBRARY_NAME}-targets"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
PUBLIC_HEADER
COMPONENT Runtime
)
export(TARGETS ${QTERMWIDGET_LIBRARY_NAME}
FILE "${CMAKE_BINARY_DIR}/${QTERMWIDGET_LIBRARY_NAME}-targets.cmake"
EXPORT_LINK_INTERFACE_LIBRARIES
) )
# end of main library # end of main library
# test application # example application
if(BUILD_TEST) if(BUILD_EXAMPLE)
set(TEST_SRC src/main.cpp) set(EXAMPLE_SRC example/main.cpp)
add_executable(test ${TEST_SRC}) add_executable(example ${EXAMPLE_SRC})
add_dependencies(test ${QTERMWIDGET_LIBRARY_NAME}) target_link_libraries(example ${QTERMWIDGET_LIBRARY_NAME})
link_directories(${CMAKE_BINARY_DIR}) endif()
target_link_libraries(test ${QTERMWIDGET_QT_LIBRARIES} ${QTERMWIDGET_LIBRARY_NAME} util) # end of example application
endif (BUILD_TEST)
# end of test application
CONFIGURE_FILE( CONFIGURE_FILE(

@ -2,27 +2,27 @@
## Overview ## Overview
A terminal emulator widget for Qt 5. A terminal emulator widget for Qt 5.
QTermWidget is an open-source project originally based on KDE4 Konsole application, but it took its own direction later. QTermWidget is an open-source project originally based on the KDE4 Konsole application, but it took its own direction later on.
The main goal of this project is to provide a unicode-enabled, embeddable Qt widget for using as a built-in console (or terminal emulation widget). The main goal of this project is to provide a unicode-enabled, embeddable Qt widget for using as a built-in console (or terminal emulation widget).
It is compatible with BSD, Linux and OS X. It is compatible with BSD, Linux and OS X.
This project is licensed under the terms of the [GPLv2](https://www.gnu.org/licenses/gpl-2.0.en.html) or any later version. See the LICENSE file for the full text of the license. This project is licensed under the terms of the [GPLv2](https://www.gnu.org/licenses/gpl-2.0.en.html) or any later version. See the LICENSE file for the full text of the license.
## Installation ## Installation
### Compiling sources ### Compiling sources
The only runtime dependency is qtbase ≥ 5.4. The only runtime dependency is qtbase ≥ 5.6.
In order to build CMake ≥ 3.0 is needed as well as optionally Git to pull latest VCS checkouts. In order to build CMake ≥ 3.0.2 and [lxqt-build-tools](https://github.com/lxde/lxqt-build-tools/) >= 0.3 are needed as well as Git to pull translations and optionally latest VCS checkouts.
Code configuration is handled by CMake. Building out of source is strongly recommended. CMake variable `CMAKE_INSTALL_PREFIX` will normally have to be set to `/usr`, depending on the way library paths are dealt with on 64bit systems variables like `CMAKE_INSTALL_LIBDIR` may have to be set as well. Code configuration is handled by CMake. CMake variable `CMAKE_INSTALL_PREFIX` will normally have to be set to `/usr`, depending on the way library paths are dealt with on 64bit systems variables like `CMAKE_INSTALL_LIBDIR` may have to be set as well.
To build run `make`, to install `make install` which accepts variable `DESTDIR` as usual. To build run `make`, to install `make install` which accepts variable `DESTDIR` as usual.
### Binary packages ### Binary packages
The library is provided by all major Linux distributions like Arch Linux, Debian, Fedora and openSUSE. The library is provided by all major Linux distributions like Arch Linux, Debian, Fedora and openSUSE.
Just use the distributions' package managers to search for string `qtermwidget`. Just use the distributions' package managers to search for string `qtermwidget`.

@ -1,29 +0,0 @@
#
# Write a pkg-config pc file for given "name" with "decription"
# Arguments:
# name: a library name (withoud "lib" prefix and "so" suffixes
# desc: a desription string
# requires: required libraries
# include_rel_dir: include directory, relative to includedir
# version: package version
#
macro (create_pkgconfig_file name desc requires include_rel_dir version)
set(_pkgfname "${CMAKE_CURRENT_BINARY_DIR}/${name}.pc")
message(STATUS "${name}: writing pkgconfig file ${_pkgfname}")
file(WRITE "${_pkgfname}"
"prefix=${CMAKE_INSTALL_PREFIX}\n"
"libdir=\${prefix}/${CMAKE_INSTALL_LIBDIR}\n"
"includedir=\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}\n"
"\n"
"Name: ${name}\n"
"Description: ${desc}\n"
"Version: ${version}\n"
"Requires: ${requires}\n"
"Libs: -L\${libdir} -l${name}\n"
"Cflags: -I\${includedir} -I\${includedir}/${include_rel_dir}\n"
"\n"
)
install(FILES ${_pkgfname} DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endmacro()

@ -1,8 +0,0 @@
find_package(Qt4 REQUIRED QUIET)
include(${QT_USE_FILE})
set(QTERMWIDGET_QT_LIBRARIES ${QT_LIBRARIES})
include_directories(${QTERMWIDGET_INCLUDE_DIRS})

@ -1,41 +1,20 @@
# - Find the QTermWidget include and library dirs and define a some macros # - Find the QTermWidget include and library
#
# The module defines the following variables
# QTERMWIDGET_FOUND - Set to TRUE if all of the above has been found
#
# QTERMWIDGET_INCLUDE_DIR - The QTermWidget include directory
#
# QTERMWIDGET_INCLUDE_DIRS - The QTermWidget include directory
#
# QTERMWIDGET_LIBRARIES - The libraries needed to use QTermWidget
#
# QTERMWIDGET_USE_FILE - The variable QTERMWIDGET_USE_FILE is set which is the path
# to a CMake file that can be included to compile qtermwidget
# applications and libraries. It sets up the compilation
# environment for include directories and populates a
# QTERMWIDGET_LIBRARIES variable.
#
# QTERMWIDGET_QT_LIBRARIES - The Qt libraries needed by QTermWidget
# #
# Typical usage: # Typical usage:
# find_package(QTERMWIDGET5) # find_package(QTermWidget5 REQUIRED)
# #
# include(${QTERMWIDGET_USE_FILE})
# add_executable(foo main.cpp) # add_executable(foo main.cpp)
# target_link_libraries(foo ${QTERMWIDGET_QT_LIBRARIES} ${QTERMWIDGET_LIBRARIES}) # target_link_libraries(foo qtermwidget5)
set(QTERMWIDGET_INCLUDE_DIR @QTERMWIDGET_INCLUDE_DIR@)
set(QTERMWIDGET_LIBRARY @QTERMWIDGET_LIBRARY_NAME@)
set(QTERMWIDGET_LIBRARIES ${QTERMWIDGET_LIBRARY})
set(QTERMWIDGET_INCLUDE_DIRS "${QTERMWIDGET_INCLUDE_DIR}")
set(QTERMWIDGET_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/qtermwidget5_use.cmake") @PACKAGE_INIT@
set(QTERMWIDGET_FOUND 1)
set(QTERMWIDGET_VERSION_MAJOR @QTERMWIDGET_VERSION_MAJOR@) if (CMAKE_VERSION VERSION_LESS 3.0.2)
set(QTERMWIDGET_VERSION_MINOR @QTERMWIDGET_VERSION_MINOR@) message(FATAL_ERROR \"qtermwidget requires at least CMake version 3.0.2\")
set(QTERMWIDGET_VERSION_PATCH @QTERMWIDGET_VERSION_PATCH@) endif()
set(QTERMWIDGET_VERSION @QTERMWIDGET_VERSION@)
mark_as_advanced(QTERMWIDGET_LIBRARY QTERMWIDGET_INCLUDE_DIR) if (NOT TARGET @QTERMWIDGET_LIBRARY_NAME@)
if (POLICY CMP0024)
cmake_policy(SET CMP0024 NEW)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@QTERMWIDGET_LIBRARY_NAME@-targets.cmake")
endif()

@ -1,9 +0,0 @@
find_package(Qt5Widgets REQUIRED)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_definitions(${Qt5Core_DEFINITIONS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
set(QTERMWIDGET_QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
include_directories(${QTERMWIDGET_INCLUDE_DIRS})

@ -48,6 +48,10 @@ static const int LINE_DOUBLEHEIGHT = (1 << 2);
#define RE_ITALIC (1 << 4) #define RE_ITALIC (1 << 4)
#define RE_CURSOR (1 << 5) #define RE_CURSOR (1 << 5)
#define RE_EXTENDED_CHAR (1 << 6) #define RE_EXTENDED_CHAR (1 << 6)
#define RE_FAINT (1 << 7)
#define RE_STRIKEOUT (1 << 8)
#define RE_CONCEAL (1 << 9)
#define RE_OVERLINE (1 << 10)
/** /**
* A single character in the terminal which consists of a unicode character * A single character in the terminal which consists of a unicode character

@ -70,6 +70,11 @@ Emulation::Emulation() :
SLOT(usesMouseChanged(bool))); SLOT(usesMouseChanged(bool)));
connect(this , SIGNAL(programBracketedPasteModeChanged(bool)) , connect(this , SIGNAL(programBracketedPasteModeChanged(bool)) ,
SLOT(bracketedPasteModeChanged(bool))); SLOT(bracketedPasteModeChanged(bool)));
connect(this, &Emulation::cursorChanged, [this] (KeyboardCursorShape cursorShape, bool blinkingCursorEnabled) {
emit titleChanged( 50, QString("CursorShape=%1;BlinkingCursorEnabled=%2")
.arg(static_cast<int>(cursorShape)).arg(blinkingCursorEnabled) );
});
} }
bool Emulation::programUsesMouse() const bool Emulation::programUsesMouse() const

@ -126,6 +126,26 @@ Q_OBJECT
public: public:
/**
* This enum describes the available shapes for the keyboard cursor.
* See setKeyboardCursorShape()
*/
enum class KeyboardCursorShape {
/** A rectangular block which covers the entire area of the cursor character. */
BlockCursor = 0,
/**
* A single flat line which occupies the space at the bottom of the cursor
* character's area.
*/
UnderlineCursor = 1,
/**
* An cursor shaped like the capital letter 'I', similar to the IBeam
* cursor used in Qt/KDE text editors.
*/
IBeamCursor = 2
};
/** Constructs a new terminal emulation */ /** Constructs a new terminal emulation */
Emulation(); Emulation();
~Emulation(); ~Emulation();
@ -415,6 +435,15 @@ signals:
*/ */
void flowControlKeyPressed(bool suspendKeyPressed); void flowControlKeyPressed(bool suspendKeyPressed);
/**
* Emitted when the cursor shape or its blinking state is changed via
* DECSCUSR sequences.
*
* @param cursorShape One of 3 possible values in KeyboardCursorShape enum
* @param blinkingCursorEnabled Whether to enable blinking or not
*/
void cursorChanged(KeyboardCursorShape cursorShape, bool blinkingCursorEnabled);
protected: protected:
virtual void setMode(int mode) = 0; virtual void setMode(int mode) = 0;
virtual void resetMode(int mode) = 0; virtual void resetMode(int mode) = 0;

@ -26,6 +26,7 @@
// Qt // Qt
#include <QAction> #include <QAction>
#include <QApplication> #include <QApplication>
#include <QtAlgorithms>
#include <QClipboard> #include <QClipboard>
#include <QString> #include <QString>
#include <QTextStream> #include <QTextStream>
@ -194,6 +195,7 @@ Filter::~Filter()
} }
void Filter::reset() void Filter::reset()
{ {
qDeleteAll(_hotspotList);
_hotspots.clear(); _hotspots.clear();
_hotspotList.clear(); _hotspotList.clear();
} }
@ -416,7 +418,7 @@ UrlFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endCol
UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const
{ {
QString url = capturedTexts().first(); QString url = capturedTexts().constFirst();
if ( FullUrlRegExp.exactMatch(url) ) if ( FullUrlRegExp.exactMatch(url) )
return StandardUrl; return StandardUrl;
@ -428,7 +430,7 @@ UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const
void UrlFilter::HotSpot::activate(const QString& actionName) void UrlFilter::HotSpot::activate(const QString& actionName)
{ {
QString url = capturedTexts().first(); QString url = capturedTexts().constFirst();
const UrlType kind = urlType(); const UrlType kind = urlType();

@ -321,6 +321,10 @@ bool KeyboardTranslatorReader::parseAsCommand(const QString& text,KeyboardTransl
command = KeyboardTranslator::ScrollLineDownCommand; command = KeyboardTranslator::ScrollLineDownCommand;
else if ( text.compare("scrolllock",Qt::CaseInsensitive) == 0 ) else if ( text.compare("scrolllock",Qt::CaseInsensitive) == 0 )
command = KeyboardTranslator::ScrollLockCommand; command = KeyboardTranslator::ScrollLockCommand;
else if ( text.compare("scrolluptotop",Qt::CaseInsensitive) == 0)
command = KeyboardTranslator::ScrollUpToTopCommand;
else if ( text.compare("scrolldowntobottom",Qt::CaseInsensitive) == 0)
command = KeyboardTranslator::ScrollDownToBottomCommand;
else else
return false; return false;
@ -543,27 +547,27 @@ QList<KeyboardTranslatorReader::Token> KeyboardTranslatorReader::tokenize(const
if ( title.exactMatch(text) ) if ( title.exactMatch(text) )
{ {
Token titleToken = { Token::TitleKeyword , QString() }; Token titleToken = { Token::TitleKeyword , QString() };
Token textToken = { Token::TitleText , title.capturedTexts()[1] }; Token textToken = { Token::TitleText , title.capturedTexts().at(1) };
list << titleToken << textToken; list << titleToken << textToken;
} }
else if ( key.exactMatch(text) ) else if ( key.exactMatch(text) )
{ {
Token keyToken = { Token::KeyKeyword , QString() }; Token keyToken = { Token::KeyKeyword , QString() };
Token sequenceToken = { Token::KeySequence , key.capturedTexts()[1].remove(' ') }; Token sequenceToken = { Token::KeySequence , key.capturedTexts().value(1).remove(' ') };
list << keyToken << sequenceToken; list << keyToken << sequenceToken;
if ( key.capturedTexts()[3].isEmpty() ) if ( key.capturedTexts().at(3).isEmpty() )
{ {
// capturedTexts()[2] is a command // capturedTexts()[2] is a command
Token commandToken = { Token::Command , key.capturedTexts()[2] }; Token commandToken = { Token::Command , key.capturedTexts().at(2) };
list << commandToken; list << commandToken;
} }
else else
{ {
// capturedTexts()[3] is the output string // capturedTexts()[3] is the output string
Token outputToken = { Token::OutputText , key.capturedTexts()[3] }; Token outputToken = { Token::OutputText , key.capturedTexts().at(3) };
list << outputToken; list << outputToken;
} }
} }
@ -785,6 +789,10 @@ QString KeyboardTranslator::Entry::resultToString(bool expandWildCards,Qt::Keybo
return "ScrollLineDown"; return "ScrollLineDown";
else if ( _command == ScrollLockCommand ) else if ( _command == ScrollLockCommand )
return "ScrollLock"; return "ScrollLock";
else if (_command == ScrollUpToTopCommand)
return "ScrollUpToTop";
else if (_command == ScrollDownToBottomCommand)
return "ScrollDownToBottom";
return QString(); return QString();
} }
@ -852,10 +860,11 @@ void KeyboardTranslator::removeEntry(const Entry& entry)
} }
KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state) const KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state) const
{ {
foreach(const Entry& entry, _entries.values(keyCode)) for (auto it = _entries.cbegin(), end = _entries.cend(); it != end; ++it)
{ {
if ( entry.matches(keyCode,modifiers,state) ) if (it.key() == keyCode)
return entry; if ( it.value().matches(keyCode,modifiers,state) )
return *it;
} }
return Entry(); // entry not found return Entry(); // entry not found
} }

@ -111,8 +111,12 @@ public:
ScrollLineDownCommand = 16, ScrollLineDownCommand = 16,
/** Toggles scroll lock mode */ /** Toggles scroll lock mode */
ScrollLockCommand = 32, ScrollLockCommand = 32,
/** Scroll the terminal display up to the start of history */
ScrollUpToTopCommand = 64,
/** Scroll the terminal display down to the end of history */
ScrollDownToBottomCommand = 128,
/** Echos the operating system specific erase character. */ /** Echos the operating system specific erase character. */
EraseCommand = 64 EraseCommand = 256
}; };
Q_DECLARE_FLAGS(Commands,Command) Q_DECLARE_FLAGS(Commands,Command)

@ -226,6 +226,28 @@ void Screen::insertChars(int n)
screenLines[cuY].resize(columns); screenLines[cuY].resize(columns);
} }
void Screen::repeatChars(int count)
//=REP
{
if (count == 0)
{
count = 1;
}
/**
* From ECMA-48 version 5, section 8.3.103
* If the character preceding REP is a control function or part of a
* control function, the effect of REP is not defined by this Standard.
*
* So, a "normal" program should always use REP immediately after a visible
* character (those other than escape sequences). So, lastDrawnChar can be
* safely used.
*/
for (int i = 0; i < count; i++)
{
displayCharacter(lastDrawnChar);
}
}
void Screen::deleteLines(int n) void Screen::deleteLines(int n)
{ {
if (n == 0) n = 1; // Default if (n == 0) n = 1; // Default
@ -663,6 +685,8 @@ void Screen::displayCharacter(unsigned short c)
currentChar.backgroundColor = effectiveBackground; currentChar.backgroundColor = effectiveBackground;
currentChar.rendition = effectiveRendition; currentChar.rendition = effectiveRendition;
lastDrawnChar = c;
int i = 0; int i = 0;
int newCursorX = cuX + w--; int newCursorX = cuX + w--;
while(w) while(w)

@ -197,6 +197,11 @@ public:
* If @p n is 0 then one character is inserted. * If @p n is 0 then one character is inserted.
*/ */
void insertChars(int n); void insertChars(int n);
/**
* Repeat the preceeding graphic character @count times, including SPACE.
* If @count is 0 then the character is repeated once.
*/
void repeatChars(int count);
/** /**
* Removes @p n lines beginning from the current cursor position. * Removes @p n lines beginning from the current cursor position.
* The position of the cursor is not altered. * The position of the cursor is not altered.
@ -667,6 +672,9 @@ private:
// last position where we added a character // last position where we added a character
int lastPos; int lastPos;
// used in REP (repeating char)
unsigned short lastDrawnChar;
static Character defaultChar; static Character defaultChar;
}; };

@ -99,6 +99,8 @@ Session::Session(QObject* parent) :
this, SLOT(onEmulationSizeChange(QSize))); this, SLOT(onEmulationSizeChange(QSize)));
connect(_emulation, SIGNAL(imageSizeChanged(int, int)), connect(_emulation, SIGNAL(imageSizeChanged(int, int)),
this, SLOT(onViewSizeChange(int, int))); this, SLOT(onViewSizeChange(int, int)));
connect(_emulation, &Vt102Emulation::cursorChanged,
this, &Session::cursorChanged);
//connect teletype to emulation backend //connect teletype to emulation backend
_shellProcess->setUtf8Mode(_emulation->utf8()); _shellProcess->setUtf8Mode(_emulation->utf8());
@ -256,8 +258,10 @@ void Session::run()
// here we expect full path. If there is no fullpath let's expect it's // here we expect full path. If there is no fullpath let's expect it's
// a custom shell (eg. python, etc.) available in the PATH. // a custom shell (eg. python, etc.) available in the PATH.
if (exec.startsWith("/")) if (exec.startsWith("/") || exec.isEmpty())
{ {
const QString defaultShell{"/bin/sh"};
QFile excheck(exec); QFile excheck(exec);
if ( exec.isEmpty() || !excheck.exists() ) { if ( exec.isEmpty() || !excheck.exists() ) {
exec = getenv("SHELL"); exec = getenv("SHELL");
@ -265,7 +269,8 @@ void Session::run()
excheck.setFileName(exec); excheck.setFileName(exec);
if ( exec.isEmpty() || !excheck.exists() ) { if ( exec.isEmpty() || !excheck.exists() ) {
exec = "/bin/sh"; qWarning() << "Neither default shell nor $SHELL is set to a correct path. Fallback to" << defaultShell;
exec = defaultShell;
} }
} }

@ -28,6 +28,7 @@
#include <QStringList> #include <QStringList>
#include <QWidget> #include <QWidget>
#include "Emulation.h"
#include "History.h" #include "History.h"
class KProcess; class KProcess;
@ -477,6 +478,11 @@ signals:
*/ */
void flowControlEnabledChanged(bool enabled); void flowControlEnabledChanged(bool enabled);
/**
* Broker for Emulation::cursorChanged() signal
*/
void cursorChanged(Emulation::KeyboardCursorShape cursorShape, bool blinkingCursorEnabled);
void silence(); void silence();
void activity(); void activity();

@ -96,8 +96,9 @@ QStringList ShellCommand::expand(const QStringList & items)
{ {
QStringList result; QStringList result;
foreach( QString item , items ) foreach(const QString &item, items ) {
result << expand(item); result << expand(item);
}
return result; return result;
} }

@ -241,9 +241,32 @@ void TerminalDisplay::fontChange(const QFont&)
emit changedFontMetricSignal( _fontHeight, _fontWidth ); emit changedFontMetricSignal( _fontHeight, _fontWidth );
propagateSize(); propagateSize();
// We will run paint event testing procedure.
// Although this operation will destory the orignal content,
// the content will be drawn again after the test.
_drawTextTestFlag = true;
update(); update();
} }
void TerminalDisplay::calDrawTextAdditionHeight(QPainter& painter)
{
QRect test_rect, feedback_rect;
test_rect.setRect(1, 1, _fontWidth * 4, _fontHeight);
painter.drawText(test_rect, Qt::AlignBottom, LTR_OVERRIDE_CHAR + QString("Mq"), &feedback_rect);
//qDebug() << "test_rect:" << test_rect << "feeback_rect:" << feedback_rect;
_drawTextAdditionHeight = (feedback_rect.height() - _fontHeight) / 2;
if(_drawTextAdditionHeight < 0) {
_drawTextAdditionHeight = 0;
}
// update the original content
_drawTextTestFlag = false;
update();
}
void TerminalDisplay::setVTFont(const QFont& f) void TerminalDisplay::setVTFont(const QFont& f)
{ {
QFont font = f; QFont font = f;
@ -334,9 +357,13 @@ TerminalDisplay::TerminalDisplay(QWidget *parent)
,_colorsInverted(false) ,_colorsInverted(false)
,_blendColor(qRgba(0,0,0,0xff)) ,_blendColor(qRgba(0,0,0,0xff))
,_filterChain(new TerminalImageFilterChain()) ,_filterChain(new TerminalImageFilterChain())
,_cursorShape(QTermWidget::BlockCursor) ,_cursorShape(Emulation::KeyboardCursorShape::BlockCursor)
,mMotionAfterPasting(NoMoveScreenWindow) ,mMotionAfterPasting(NoMoveScreenWindow)
{ {
// variables for draw text
_drawTextAdditionHeight = 0;
_drawTextTestFlag = false;
// terminal applications are not designed with Right-To-Left in mind, // terminal applications are not designed with Right-To-Left in mind,
// so the layout is forced to Left-To-Right // so the layout is forced to Left-To-Right
setLayoutDirection(Qt::LeftToRight); setLayoutDirection(Qt::LeftToRight);
@ -739,7 +766,7 @@ void TerminalDisplay::drawCursor(QPainter& painter,
else else
painter.setPen(foregroundColor); painter.setPen(foregroundColor);
if ( _cursorShape == QTermWidget::BlockCursor ) if ( _cursorShape == Emulation::KeyboardCursorShape::BlockCursor )
{ {
// draw the cursor outline, adjusting the area so that // draw the cursor outline, adjusting the area so that
// it is draw entirely inside 'rect' // it is draw entirely inside 'rect'
@ -761,12 +788,12 @@ void TerminalDisplay::drawCursor(QPainter& painter,
} }
} }
} }
else if ( _cursorShape == QTermWidget::UnderlineCursor ) else if ( _cursorShape == Emulation::KeyboardCursorShape::UnderlineCursor )
painter.drawLine(cursorRect.left(), painter.drawLine(cursorRect.left(),
cursorRect.bottom(), cursorRect.bottom(),
cursorRect.right(), cursorRect.right(),
cursorRect.bottom()); cursorRect.bottom());
else if ( _cursorShape == QTermWidget::IBeamCursor ) else if ( _cursorShape == Emulation::KeyboardCursorShape::IBeamCursor )
painter.drawLine(cursorRect.left(), painter.drawLine(cursorRect.left(),
cursorRect.top(), cursorRect.top(),
cursorRect.left(), cursorRect.left(),
@ -783,23 +810,30 @@ void TerminalDisplay::drawCharacters(QPainter& painter,
{ {
// don't draw text which is currently blinking // don't draw text which is currently blinking
if ( _blinking && (style->rendition & RE_BLINK) ) if ( _blinking && (style->rendition & RE_BLINK) )
return;
// don't draw concealed characters
if (style->rendition & RE_CONCEAL)
return; return;
// setup bold and underline // setup bold and underline
bool useBold; bool useBold = ((style->rendition & RE_BOLD) && _boldIntense) || font().bold();
ColorEntry::FontWeight weight = style->fontWeight(_colorTable); const bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();
if (weight == ColorEntry::UseCurrentFormat) const bool useItalic = style->rendition & RE_ITALIC || font().italic();
useBold = ((style->rendition & RE_BOLD) && _boldIntense) || font().bold(); const bool useStrikeOut = style->rendition & RE_STRIKEOUT || font().strikeOut();
else const bool useOverline = style->rendition & RE_OVERLINE || font().overline();
useBold = (weight == ColorEntry::Bold) ? true : false;
bool useUnderline = style->rendition & RE_UNDERLINE || font().underline();
QFont font = painter.font(); QFont font = painter.font();
if ( font.bold() != useBold if ( font.bold() != useBold
|| font.underline() != useUnderline ) || font.underline() != useUnderline
{ || font.italic() != useItalic
|| font.strikeOut() != useStrikeOut
|| font.overline() != useOverline) {
font.setBold(useBold); font.setBold(useBold);
font.setUnderline(useUnderline); font.setUnderline(useUnderline);
font.setItalic(useItalic);
font.setStrikeOut(useStrikeOut);
font.setOverline(useOverline);
painter.setFont(font); painter.setFont(font);
} }
@ -818,16 +852,21 @@ void TerminalDisplay::drawCharacters(QPainter& painter,
drawLineCharString(painter,rect.x(),rect.y(),text,style); drawLineCharString(painter,rect.x(),rect.y(),text,style);
else else
{ {
// the drawText(rect,flags,string) overload is used here with null flags // Force using LTR as the document layout for the terminal area, because
// instead of drawText(rect,string) because the (rect,string) overload causes // there is no use cases for RTL emulator and RTL terminal application.
// the application's default layout direction to be used instead of //
// the widget-specific layout direction, which should always be // This still allows RTL characters to be rendered in the RTL way.
// Qt::LeftToRight for this widget painter.setLayoutDirection(Qt::LeftToRight);
// This was discussed in: http://lists.kde.org/?t=120552223600002&r=1&w=2
if (_bidiEnabled) if (_bidiEnabled) {
painter.drawText(rect,0,text); painter.drawText(rect.x(), rect.y() + _fontAscent + _lineSpacing, text);
else } else {
painter.drawText(rect, Qt::AlignBottom, LTR_OVERRIDE_CHAR + text); {
QRect drawRect(rect.topLeft(), rect.size());
drawRect.setHeight(rect.height() + _drawTextAdditionHeight);
painter.drawText(drawRect, Qt::AlignBottom, LTR_OVERRIDE_CHAR + text);
}
}
} }
} }
@ -1241,8 +1280,9 @@ void TerminalDisplay::showResizeNotification()
} }
if (!_resizeWidget) if (!_resizeWidget)
{ {
_resizeWidget = new QLabel("Size: XXX x XXX", this); const QString label = tr("Size: XXX x XXX");
_resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width("Size: XXX x XXX")); _resizeWidget = new QLabel(label, this);
_resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(label));
_resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height()); _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height());
_resizeWidget->setAlignment(Qt::AlignCenter); _resizeWidget->setAlignment(Qt::AlignCenter);
@ -1252,8 +1292,7 @@ void TerminalDisplay::showResizeNotification()
_resizeTimer->setSingleShot(true); _resizeTimer->setSingleShot(true);
connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide())); connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide()));
} }
QString sizeStr = QString("Size: %1 x %2").arg(_columns).arg(_lines); _resizeWidget->setText(tr("Size: %1 x %2").arg(_columns).arg(_lines));
_resizeWidget->setText(sizeStr);
_resizeWidget->move((width()-_resizeWidget->width())/2, _resizeWidget->move((width()-_resizeWidget->width())/2,
(height()-_resizeWidget->height())/2+20); (height()-_resizeWidget->height())/2+20);
_resizeWidget->show(); _resizeWidget->show();
@ -1332,14 +1371,21 @@ void TerminalDisplay::paintEvent( QPaintEvent* pe )
paint.fillRect(contentsRect(), background); paint.fillRect(contentsRect(), background);
} }
foreach (const QRect &rect, (pe->region() & contentsRect()).rects()) if(_drawTextTestFlag)
{
calDrawTextAdditionHeight(paint);
}
else
{ {
drawBackground(paint,rect,palette().background().color(), foreach (const QRect &rect, (pe->region() & contentsRect()).rects())
true /* use opacity setting */); {
drawContents(paint, rect); drawBackground(paint,rect,palette().background().color(),
true /* use opacity setting */);
drawContents(paint, rect);
}
drawInputMethodPreeditString(paint,preeditRect());
paintFilters(paint);
} }
drawInputMethodPreeditString(paint,preeditRect());
paintFilters(paint);
} }
QPoint TerminalDisplay::cursorPosition() const QPoint TerminalDisplay::cursorPosition() const

@ -677,6 +677,8 @@ private:
void paintFilters(QPainter& painter); void paintFilters(QPainter& painter);
void calDrawTextAdditionHeight(QPainter& painter);
// returns a region covering all of the areas of the widget which contain // returns a region covering all of the areas of the widget which contain
// a hotspot // a hotspot
QRegion hotSpotRegion() const; QRegion hotSpotRegion() const;
@ -702,6 +704,8 @@ private:
int _fontWidth; // width int _fontWidth; // width
int _fontAscent; // ascend int _fontAscent; // ascend
bool _boldIntense; // Whether intense colors should be rendered with bold font bool _boldIntense; // Whether intense colors should be rendered with bold font
int _drawTextAdditionHeight; // additional height to prevent font trancation
bool _drawTextTestFlag; // indicate it is a testing or not
int _leftMargin; // offset int _leftMargin; // offset
int _topMargin; // offset int _topMargin; // offset

@ -133,6 +133,7 @@ void Vt102Emulation::reset()
- ESC_DE - Escape codes of the form <ESC><any of `()+*#%'> C - ESC_DE - Escape codes of the form <ESC><any of `()+*#%'> C
- CSI_PN - Escape codes of the form <ESC>'[' {Pn} ';' {Pn} C - CSI_PN - Escape codes of the form <ESC>'[' {Pn} ';' {Pn} C
- CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C - CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C
- CSI_PS_SP - Escape codes of the form <ESC>'[' {Pn} ';' ... {Space} C
- CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C - CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C
- CSI_PE - Escape codes of the form <ESC>'[' '!' {Pn} ';' ... C - CSI_PE - Escape codes of the form <ESC>'[' '!' {Pn} ';' ... C
- VT52 - VT52 escape codes - VT52 - VT52 escape codes
@ -160,6 +161,7 @@ void Vt102Emulation::reset()
#define TY_CSI_PS(A,N) TY_CONSTRUCT(5,A,N) #define TY_CSI_PS(A,N) TY_CONSTRUCT(5,A,N)
#define TY_CSI_PN(A ) TY_CONSTRUCT(6,A,0) #define TY_CSI_PN(A ) TY_CONSTRUCT(6,A,0)
#define TY_CSI_PR(A,N) TY_CONSTRUCT(7,A,N) #define TY_CSI_PR(A,N) TY_CONSTRUCT(7,A,N)
#define TY_CSI_PS_SP(A,N) TY_CONSTRUCT(11,A,N)
#define TY_VT52(A) TY_CONSTRUCT(8,A,0) #define TY_VT52(A) TY_CONSTRUCT(8,A,0)
#define TY_CSI_PG(A) TY_CONSTRUCT(9,A,0) #define TY_CSI_PG(A) TY_CONSTRUCT(9,A,0)
@ -203,7 +205,6 @@ void Vt102Emulation::addToCurrentToken(int cc)
} }
// Character Class flags used while decoding // Character Class flags used while decoding
#define CTL 1 // Control character #define CTL 1 // Control character
#define CHR 2 // Printable character #define CHR 2 // Printable character
#define CPN 4 // TODO: Document me #define CPN 4 // TODO: Document me
@ -223,7 +224,7 @@ void Vt102Emulation::initTokenizer()
charClass[i] |= CTL; charClass[i] |= CTL;
for(i = 32;i < 256; ++i) for(i = 32;i < 256; ++i)
charClass[i] |= CHR; charClass[i] |= CHR;
for(s = (quint8*)"@ABCDGHILMPSTXZcdfry"; *s; ++s) for(s = (quint8*)"@ABCDGHILMPSTXZbcdfry"; *s; ++s)
charClass[*s] |= CPN; charClass[*s] |= CPN;
// resize = \e[8;<row>;<col>t // resize = \e[8;<row>;<col>t
for(s = (quint8*)"t"; *s; ++s) for(s = (quint8*)"t"; *s; ++s)
@ -266,17 +267,19 @@ void Vt102Emulation::initTokenizer()
#define epp( ) (p >= 3 && s[2] == '?') #define epp( ) (p >= 3 && s[2] == '?')
#define epe( ) (p >= 3 && s[2] == '!') #define epe( ) (p >= 3 && s[2] == '!')
#define egt( ) (p >= 3 && s[2] == '>') #define egt( ) (p >= 3 && s[2] == '>')
#define esp( ) (p == 4 && s[3] == ' ')
#define Xpe (tokenBufferPos >= 2 && tokenBuffer[1] == ']') #define Xpe (tokenBufferPos >= 2 && tokenBuffer[1] == ']')
#define Xte (Xpe && cc == 7 ) #define Xte (Xpe && (cc == 7 || cc == 33))
#define ces(C) (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte) #define ces(C) (cc < 256 && (charClass[cc] & (C)) == (C) && !Xte)
#define ESC 27
#define CNTL(c) ((c)-'@') #define CNTL(c) ((c)-'@')
#define ESC 27
#define DEL 127
// process an incoming unicode character // process an incoming unicode character
void Vt102Emulation::receiveChar(int cc) void Vt102Emulation::receiveChar(int cc)
{ {
if (cc == 127) if (cc == DEL)
return; //VT100: ignore. return; //VT100: ignore.
if (ces(CTL)) if (ces(CTL))
@ -314,6 +317,12 @@ void Vt102Emulation::receiveChar(int cc)
if (les(3,1,SCS)) { processToken( TY_ESC_CS(s[1],s[2]), 0, 0); resetTokenizer(); return; } if (les(3,1,SCS)) { processToken( TY_ESC_CS(s[1],s[2]), 0, 0); resetTokenizer(); return; }
if (lec(3,1,'#')) { processToken( TY_ESC_DE(s[2]), 0, 0); resetTokenizer(); return; } if (lec(3,1,'#')) { processToken( TY_ESC_DE(s[2]), 0, 0); resetTokenizer(); return; }
if (eps( CPN)) { processToken( TY_CSI_PN(cc), argv[0],argv[1]); resetTokenizer(); return; } if (eps( CPN)) { processToken( TY_CSI_PN(cc), argv[0],argv[1]); resetTokenizer(); return; }
if (esp( )) { return; }
if (lec(5, 4, 'q') && s[3] == ' ') {
processToken( TY_CSI_PS_SP(cc, argv[0]), argv[0], 0);
resetTokenizer();
return;
}
// resize = \e[8;<row>;<col>t // resize = \e[8;<row>;<col>t
if (eps(CPS)) if (eps(CPS))
@ -531,7 +540,7 @@ void Vt102Emulation::processToken(int token, int p, int q)
case TY_ESC_DE('8' ) : _currentScreen->helpAlign ( ); break; case TY_ESC_DE('8' ) : _currentScreen->helpAlign ( ); break;
// resize = \e[8;<row>;<col>t // resize = \e[8;<row>;<col>t
case TY_CSI_PS('t', 8) : setImageSize( q /* columns */, p /* lines */ ); case TY_CSI_PS('t', 8) : setImageSize( p /*lines */, q /* columns */ );
emit imageResizeRequest(QSize(q, p)); emit imageResizeRequest(QSize(q, p));
break; break;
@ -557,18 +566,27 @@ void Vt102Emulation::processToken(int token, int p, int q)
case TY_CSI_PS('m', 0) : _currentScreen->setDefaultRendition ( ); break; case TY_CSI_PS('m', 0) : _currentScreen->setDefaultRendition ( ); break;
case TY_CSI_PS('m', 1) : _currentScreen-> setRendition (RE_BOLD ); break; //VT100 case TY_CSI_PS('m', 1) : _currentScreen-> setRendition (RE_BOLD ); break; //VT100
case TY_CSI_PS('m', 2) : _currentScreen-> setRendition (RE_FAINT ); break;
case TY_CSI_PS('m', 3) : _currentScreen-> setRendition (RE_ITALIC ); break; //VT100 case TY_CSI_PS('m', 3) : _currentScreen-> setRendition (RE_ITALIC ); break; //VT100
case TY_CSI_PS('m', 4) : _currentScreen-> setRendition (RE_UNDERLINE); break; //VT100 case TY_CSI_PS('m', 4) : _currentScreen-> setRendition (RE_UNDERLINE); break; //VT100
case TY_CSI_PS('m', 5) : _currentScreen-> setRendition (RE_BLINK ); break; //VT100 case TY_CSI_PS('m', 5) : _currentScreen-> setRendition (RE_BLINK ); break; //VT100
case TY_CSI_PS('m', 7) : _currentScreen-> setRendition (RE_REVERSE ); break; case TY_CSI_PS('m', 7) : _currentScreen-> setRendition (RE_REVERSE ); break;
case TY_CSI_PS('m', 8) : _currentScreen-> setRendition (RE_CONCEAL ); break;
case TY_CSI_PS('m', 9) : _currentScreen-> setRendition (RE_STRIKEOUT); break;
case TY_CSI_PS('m', 53) : _currentScreen-> setRendition (RE_OVERLINE ); break;
case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX
case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX
case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX
case TY_CSI_PS('m', 22) : _currentScreen->resetRendition (RE_BOLD ); break; case TY_CSI_PS('m', 21) : _currentScreen->resetRendition (RE_BOLD ); break;
case TY_CSI_PS('m', 22) : _currentScreen->resetRendition (RE_BOLD );
_currentScreen->resetRendition (RE_FAINT ); break;
case TY_CSI_PS('m', 23) : _currentScreen->resetRendition (RE_ITALIC ); break; //VT100 case TY_CSI_PS('m', 23) : _currentScreen->resetRendition (RE_ITALIC ); break; //VT100
case TY_CSI_PS('m', 24) : _currentScreen->resetRendition (RE_UNDERLINE); break; case TY_CSI_PS('m', 24) : _currentScreen->resetRendition (RE_UNDERLINE); break;
case TY_CSI_PS('m', 25) : _currentScreen->resetRendition (RE_BLINK ); break; case TY_CSI_PS('m', 25) : _currentScreen->resetRendition (RE_BLINK ); break;
case TY_CSI_PS('m', 27) : _currentScreen->resetRendition (RE_REVERSE ); break; case TY_CSI_PS('m', 27) : _currentScreen->resetRendition (RE_REVERSE ); break;
case TY_CSI_PS('m', 28) : _currentScreen->resetRendition (RE_CONCEAL ); break;
case TY_CSI_PS('m', 29) : _currentScreen->resetRendition (RE_STRIKEOUT); break;
case TY_CSI_PS('m', 55) : _currentScreen->resetRendition (RE_OVERLINE ); break;
case TY_CSI_PS('m', 30) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 0); break; case TY_CSI_PS('m', 30) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 0); break;
case TY_CSI_PS('m', 31) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 1); break; case TY_CSI_PS('m', 31) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 1); break;
@ -624,6 +642,14 @@ void Vt102Emulation::processToken(int token, int p, int q)
case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100 case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100
case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100 case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100
case TY_CSI_PS_SP('q', 0) : /* fall through */
case TY_CSI_PS_SP('q', 1) : emit cursorChanged(KeyboardCursorShape::BlockCursor, true ); break;
case TY_CSI_PS_SP('q', 2) : emit cursorChanged(KeyboardCursorShape::BlockCursor, false); break;
case TY_CSI_PS_SP('q', 3) : emit cursorChanged(KeyboardCursorShape::UnderlineCursor, true ); break;
case TY_CSI_PS_SP('q', 4) : emit cursorChanged(KeyboardCursorShape::UnderlineCursor, false); break;
case TY_CSI_PS_SP('q', 5) : emit cursorChanged(KeyboardCursorShape::IBeamCursor, true ); break;
case TY_CSI_PS_SP('q', 6) : emit cursorChanged(KeyboardCursorShape::IBeamCursor, false); break;
case TY_CSI_PN('@' ) : _currentScreen->insertChars (p ); break; case TY_CSI_PN('@' ) : _currentScreen->insertChars (p ); break;
case TY_CSI_PN('A' ) : _currentScreen->cursorUp (p ); break; //VT100 case TY_CSI_PN('A' ) : _currentScreen->cursorUp (p ); break; //VT100
case TY_CSI_PN('B' ) : _currentScreen->cursorDown (p ); break; //VT100 case TY_CSI_PN('B' ) : _currentScreen->cursorDown (p ); break; //VT100
@ -641,6 +667,7 @@ void Vt102Emulation::processToken(int token, int p, int q)
case TY_CSI_PN('T' ) : _currentScreen->scrollDown (p ); break; case TY_CSI_PN('T' ) : _currentScreen->scrollDown (p ); break;
case TY_CSI_PN('X' ) : _currentScreen->eraseChars (p ); break; case TY_CSI_PN('X' ) : _currentScreen->eraseChars (p ); break;
case TY_CSI_PN('Z' ) : _currentScreen->backtab (p ); break; case TY_CSI_PN('Z' ) : _currentScreen->backtab (p ); break;
case TY_CSI_PN('b' ) : _currentScreen->repeatChars (p ); break;
case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100 case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100
case TY_CSI_PN('d' ) : _currentScreen->setCursorY (p ); break; //LINUX case TY_CSI_PN('d' ) : _currentScreen->setCursorY (p ); break; //LINUX
case TY_CSI_PN('f' ) : _currentScreen->setCursorYX (p, q); break; //VT100 case TY_CSI_PN('f' ) : _currentScreen->setCursorYX (p, q); break; //VT100
@ -885,12 +912,12 @@ void Vt102Emulation::reportAnswerBack()
/*! /*!
`cx',`cy' are 1-based. `cx',`cy' are 1-based.
`eventType' indicates the button pressed (0-2) `cb' indicates the button pressed or released (0-2) or scroll event (4-5).
or a general mouse release (3).
eventType represents the kind of mouse action that occurred: eventType represents the kind of mouse action that occurred:
0 = Mouse button press or release 0 = Mouse button press
1 = Mouse drag 1 = Mouse drag
2 = Mouse button release
*/ */
void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType ) void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType )
@ -905,10 +932,31 @@ void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType )
//Mouse motion handling //Mouse motion handling
if ((getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1) if ((getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1)
cb += 0x20; //add 32 to signify motion event cb += 0x20; //add 32 to signify motion event
char command[32];
command[0] = '\0';
// Check the extensions in decreasing order of preference. Encoding the release event above assumes that 1006 comes first.
if (getMode(MODE_Mouse1006)) {
snprintf(command, sizeof(command), "\033[<%d;%d;%d%c", cb, cx, cy, eventType == 2 ? 'm' : 'M');
} else if (getMode(MODE_Mouse1015)) {
snprintf(command, sizeof(command), "\033[%d;%d;%dM", cb + 0x20, cx, cy);
} else if (getMode(MODE_Mouse1005)) {
if (cx <= 2015 && cy <= 2015) {
// The xterm extension uses UTF-8 (up to 2 bytes) to encode
// coordinate+32, no matter what the locale is. We could easily
// convert manually, but QString can also do it for us.
QChar coords[2];
coords[0] = cx + 0x20;
coords[1] = cy + 0x20;
QString coordsStr = QString(coords, 2);
QByteArray utf8 = coordsStr.toUtf8();
snprintf(command, sizeof(command), "\033[M%c%s", cb + 0x20, utf8.constData());
}
} else if (cx <= 223 && cy <= 223) {
snprintf(command, sizeof(command), "\033[M%c%c%c", cb + 0x20, cx + 0x20, cy + 0x20);
}
char command[20];
sprintf(command,"\033[M%c%c%c",cb+0x20,cx+0x20,cy+0x20);
sendString(command); sendString(command);
} }
@ -965,10 +1013,15 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event )
// check flow control state // check flow control state
if (modifiers & Qt::ControlModifier) if (modifiers & Qt::ControlModifier)
{ {
if (event->key() == Qt::Key_S) switch (event->key()) {
case Qt::Key_S:
emit flowControlKeyPressed(true); emit flowControlKeyPressed(true);
else if (event->key() == Qt::Key_Q) break;
case Qt::Key_Q:
case Qt::Key_C: // cancel flow control
emit flowControlKeyPressed(false); emit flowControlKeyPressed(false);
break;
}
} }
// lookup key binding // lookup key binding
@ -987,6 +1040,7 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event )
// (unless there is an entry defined for this particular combination // (unless there is an entry defined for this particular combination
// in the keyboard modifier) // in the keyboard modifier)
bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier; bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier;
bool wantsMetaModifier = entry.modifiers() & entry.modifierMask() & Qt::MetaModifier;
bool wantsAnyModifier = entry.state() & bool wantsAnyModifier = entry.state() &
entry.stateMask() & KeyboardTranslator::AnyModifierState; entry.stateMask() & KeyboardTranslator::AnyModifierState;
@ -995,6 +1049,11 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event )
{ {
textToSend.prepend("\033"); textToSend.prepend("\033");
} }
if ( modifiers & Qt::MetaModifier && !(wantsMetaModifier || wantsAnyModifier)
&& !event->text().isEmpty() )
{
textToSend.prepend("\030@s");
}
if ( entry.command() != KeyboardTranslator::NoCommand ) if ( entry.command() != KeyboardTranslator::NoCommand )
{ {
@ -1169,6 +1228,9 @@ void Vt102Emulation::resetModes()
resetMode(MODE_Mouse1001); saveMode(MODE_Mouse1001); resetMode(MODE_Mouse1001); saveMode(MODE_Mouse1001);
resetMode(MODE_Mouse1002); saveMode(MODE_Mouse1002); resetMode(MODE_Mouse1002); saveMode(MODE_Mouse1002);
resetMode(MODE_Mouse1003); saveMode(MODE_Mouse1003); resetMode(MODE_Mouse1003); saveMode(MODE_Mouse1003);
resetMode(MODE_Mouse1005); saveMode(MODE_Mouse1005);
resetMode(MODE_Mouse1006); saveMode(MODE_Mouse1006);
resetMode(MODE_Mouse1015); saveMode(MODE_Mouse1015);
resetMode(MODE_BracketedPaste); saveMode(MODE_BracketedPaste); resetMode(MODE_BracketedPaste); saveMode(MODE_BracketedPaste);
resetMode(MODE_AppScreen); saveMode(MODE_AppScreen); resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);
@ -1268,7 +1330,7 @@ char Vt102Emulation::eraseChar() const
0, 0,
0); 0);
if ( entry.text().count() > 0 ) if ( entry.text().count() > 0 )
return entry.text()[0]; return entry.text().at(0);
else else
return '\b'; return '\b';
} }

@ -133,7 +133,7 @@ private:
void resetModes(); void resetModes();
void resetTokenizer(); void resetTokenizer();
#define MAX_TOKEN_LENGTH 80 #define MAX_TOKEN_LENGTH 256 // Max length of tokens (e.g. window title)
void addToCurrentToken(int cc); void addToCurrentToken(int cc);
int tokenBuffer[MAX_TOKEN_LENGTH]; //FIXME: overflow? int tokenBuffer[MAX_TOKEN_LENGTH]; //FIXME: overflow?
int tokenBufferPos; int tokenBufferPos;
@ -153,6 +153,7 @@ private:
void processToken(int code, int p, int q); void processToken(int code, int p, int q);
void processWindowAttributeChange(); void processWindowAttributeChange();
void requestWindowAttribute(int);
void reportTerminalType(); void reportTerminalType();
void reportSecondaryAttributes(); void reportSecondaryAttributes();

@ -62,6 +62,11 @@ key Down -Shift+AnyMod+Ansi : "\E[1;*B"
key Right -Shift+AnyMod+Ansi : "\E[1;*C" key Right -Shift+AnyMod+Ansi : "\E[1;*C"
key Left -Shift+AnyMod+Ansi : "\E[1;*D" key Left -Shift+AnyMod+Ansi : "\E[1;*D"
key Up +Shift+AppScreen : "\E[1;*A"
key Down +Shift+AppScreen : "\E[1;*B"
key Left +Shift+AppScreen : "\E[1;*D"
key Right +Shift+AppScreen : "\E[1;*C"
# Keypad keys with NumLock ON # Keypad keys with NumLock ON
# (see "Numeric Keypad" section at http://www.nw.com/nw/WWW/products/wizcon/vt100.html ) # (see "Numeric Keypad" section at http://www.nw.com/nw/WWW/products/wizcon/vt100.html )
# #
@ -99,10 +104,10 @@ key End +AppCuKeys+KeyPad : "\EOF"
key Home -AppCuKeys+KeyPad : "\E[H" key Home -AppCuKeys+KeyPad : "\E[H"
key End -AppCuKeys+KeyPad : "\E[F" key End -AppCuKeys+KeyPad : "\E[F"
key Insert +KeyPad : "\E[2~" key Insert +KeyPad : "\E[2~"
key Delete +KeyPad : "\E[3~" key Delete +KeyPad : "\E[3~"
key Prior -Shift+KeyPad : "\E[5~" key PgUp -Shift+KeyPad : "\E[5~"
key Next -Shift+KeyPad : "\E[6~" key PgDown -Shift+KeyPad : "\E[6~"
# other grey PC keys # other grey PC keys
@ -121,10 +126,10 @@ key Delete -AnyMod : "\E[3~"
key Insert +AnyMod : "\E[2;*~" key Insert +AnyMod : "\E[2;*~"
key Delete +AnyMod : "\E[3;*~" key Delete +AnyMod : "\E[3;*~"
key Prior -Shift-AnyMod : "\E[5~" key PgUp -Shift-AnyMod : "\E[5~"
key Next -Shift-AnyMod : "\E[6~" key PgDown -Shift-AnyMod : "\E[6~"
key Prior -Shift+AnyMod : "\E[5;*~" key PgUp -Shift+AnyMod : "\E[5;*~"
key Next -Shift+AnyMod : "\E[6;*~" key PgDown -Shift+AnyMod : "\E[6;*~"
# Function keys # Function keys
key F1 -AnyMod : "\EOP" key F1 -AnyMod : "\EOP"
@ -160,10 +165,12 @@ key Space +Control : "\x00"
# Some keys are used by konsole to cause operations. # Some keys are used by konsole to cause operations.
# The scroll* operations refer to the history buffer. # The scroll* operations refer to the history buffer.
key Up +Shift-AppScreen : scrollLineUp key Up +Shift-AppScreen : scrollLineUp
key Prior +Shift-AppScreen : scrollPageUp key PgUp +Shift-AppScreen : scrollPageUp
key Down +Shift-AppScreen : scrollLineDown key Home +Shift-AppScreen : scrollUpToTop
key Next +Shift-AppScreen : scrollPageDown key Down +Shift-AppScreen : scrollLineDown
key PgDown +Shift-AppScreen : scrollPageDown
key End +Shift-AppScreen : scrollDownToBottom
key ScrollLock : scrollLock key ScrollLock : scrollLock

@ -102,9 +102,9 @@ key F12 : "\E[24~"
key Home : "\E[H" key Home : "\E[H"
key End : "\E[F" key End : "\E[F"
key Prior -Shift : "\E[5~" key PgUp -Shift : "\E[5~"
key Next -Shift : "\E[6~" key PgDown -Shift : "\E[6~"
key Insert-Shift : "\E[2~" key Insert -Shift : "\E[2~"
# Keypad-Enter. See comment on Return above. # Keypad-Enter. See comment on Return above.
@ -115,10 +115,10 @@ key Space +Control : "\x00"
# some of keys are used by konsole. # some of keys are used by konsole.
key Up +Shift : scrollLineUp key Up +Shift : scrollLineUp
key Prior +Shift : scrollPageUp key PgUp +Shift : scrollPageUp
key Down +Shift : scrollLineDown key Down +Shift : scrollLineDown
key Next +Shift : scrollPageDown key PgDown +Shift : scrollPageDown
key ScrollLock : scrollLock key ScrollLock : scrollLock

@ -36,8 +36,8 @@ key Home : "\E[1~"
key Insert-Shift : "\E[2~" key Insert-Shift : "\E[2~"
key Delete : "\E[3~" key Delete : "\E[3~"
key End : "\E[4~" key End : "\E[4~"
key Prior -Shift : "\E[5~" key PgUp -Shift : "\E[5~"
key Next -Shift : "\E[6~" key PgDown -Shift : "\E[6~"
# function keys # function keys
@ -61,10 +61,10 @@ key Space +Control : "\x00"
# Some keys are used by konsole to cause operations. # Some keys are used by konsole to cause operations.
# The scroll* operations refer to the history buffer. # The scroll* operations refer to the history buffer.
key Up +Shift : scrollLineUp key Up +Shift : scrollLineUp
key Prior +Shift : scrollPageUp key PgUp +Shift : scrollPageUp
key Down +Shift : scrollLineDown key Down +Shift : scrollLineDown
key Next +Shift : scrollPageDown key PgDown +Shift : scrollPageDown
key ScrollLock : scrollLock key ScrollLock : scrollLock

@ -108,9 +108,9 @@ key F12 : "\E[24~"
key Home : "\E[1~" key Home : "\E[1~"
key End : "\E[4~" key End : "\E[4~"
key Prior -Shift : "\E[5~" key PgUp -Shift : "\E[5~"
key Next -Shift : "\E[6~" key PgDown -Shift : "\E[6~"
key Insert-Shift : "\E[2~" key Insert -Shift : "\E[2~"
# Keypad-Enter. See comment on Return above. # Keypad-Enter. See comment on Return above.
@ -121,10 +121,10 @@ key Space +Control : "\x00"
# some of keys are used by konsole. # some of keys are used by konsole.
key Up +Shift : scrollLineUp key Up +Shift : scrollLineUp
key Prior +Shift : scrollPageUp key PgUp +Shift : scrollPageUp
key Down +Shift : scrollLineDown key Down +Shift : scrollLineDown
key Next +Shift : scrollPageDown key PgDown +Shift : scrollPageDown
key ScrollLock : scrollLock key ScrollLock : scrollLock

@ -99,10 +99,10 @@ key Delete -AnyMod : "\E[3~"
key Insert +AnyMod : "\E[2;*~" key Insert +AnyMod : "\E[2;*~"
key Delete +AnyMod : "\E[3;*~" key Delete +AnyMod : "\E[3;*~"
key Prior -Shift-AnyMod : "\E[5~" key PgUp -Shift-AnyMod : "\E[5~"
key Next -Shift-AnyMod : "\E[6~" key PgDown -Shift-AnyMod : "\E[6~"
key Prior -Shift+AnyMod : "\E[5;*~" key PgUp -Shift+AnyMod : "\E[5;*~"
key Next -Shift+AnyMod : "\E[6;*~" key PgDown -Shift+AnyMod : "\E[6;*~"
# Function keys # Function keys
#key F1 -AnyMod : "\EOP" #key F1 -AnyMod : "\EOP"
@ -160,10 +160,10 @@ key Space +Control : "\x00"
# Some keys are used by konsole to cause operations. # Some keys are used by konsole to cause operations.
# The scroll* operations refer to the history buffer. # The scroll* operations refer to the history buffer.
key Up +Shift-AppScreen : scrollLineUp key Up +Shift-AppScreen : scrollLineUp
key Prior +Shift-AppScreen : scrollPageUp key PgUp +Shift-AppScreen : scrollPageUp
key Down +Shift-AppScreen : scrollLineDown key Down +Shift-AppScreen : scrollLineDown
key Next +Shift-AppScreen : scrollPageDown key PgDown +Shift-AppScreen : scrollPageDown
#key Up +Shift : scrollLineUp #key Up +Shift : scrollLineUp
#key Prior +Shift : scrollPageUp #key Prior +Shift : scrollPageUp

@ -72,8 +72,8 @@ key Home : "\E[1~"
key Insert-Shift : "\E[2~" key Insert-Shift : "\E[2~"
key Delete : "\E[3~" key Delete : "\E[3~"
key End : "\E[4~" key End : "\E[4~"
key Prior -Shift : "\E[5~" key PgUp -Shift : "\E[5~"
key Next -Shift : "\E[6~" key PgDown -Shift : "\E[6~"
# function keys # function keys
@ -99,10 +99,10 @@ key Space +Control : "\x00"
#key Left +Shift : prevSession #key Left +Shift : prevSession
#key Right +Shift : nextSession #key Right +Shift : nextSession
key Up +Shift : scrollLineUp key Up +Shift : scrollLineUp
key Prior +Shift : scrollPageUp key PgUp +Shift : scrollPageUp
key Down +Shift : scrollLineDown key Down +Shift : scrollLineDown
key Next +Shift : scrollPageDown key PgDown +Shift : scrollPageDown
#key Insert+Shift : emitSelection #key Insert+Shift : emitSelection
# keypad characters are not offered differently by Qt. # keypad characters are not offered differently by Qt.

@ -138,9 +138,9 @@ key F12+Shift : "\E[24;2~"
key Home : "\E[H" key Home : "\E[H"
key End : "\E[F" key End : "\E[F"
key Prior -Shift : "\E[5~" key PgUp -Shift : "\E[5~"
key Next -Shift : "\E[6~" key PgDown -Shift : "\E[6~"
key Insert-Shift : "\E[2~" key Insert -Shift : "\E[2~"
# Keypad-Enter. See comment on Return above. # Keypad-Enter. See comment on Return above.
@ -151,10 +151,10 @@ key Space +Control : "\x00"
# some of keys are used by konsole. # some of keys are used by konsole.
key Up +Shift : scrollLineUp key Up +Shift : scrollLineUp
key Prior +Shift : scrollPageUp key PgUp +Shift : scrollPageUp
key Down +Shift : scrollLineDown key Down +Shift : scrollLineDown
key Next +Shift : scrollPageDown key PgDown +Shift : scrollPageDown
key ScrollLock : scrollLock key ScrollLock : scrollLock

@ -503,7 +503,11 @@ void KPty::login(const char * user, const char * remotehost)
// note: strncpy without terminators _is_ correct here. man 4 utmp // note: strncpy without terminators _is_ correct here. man 4 utmp
if (user) { if (user) {
# ifdef HAVE_UTMPX
strncpy(l_struct.ut_user, user, sizeof(l_struct.ut_user));
# else
strncpy(l_struct.ut_name, user, sizeof(l_struct.ut_name)); strncpy(l_struct.ut_name, user, sizeof(l_struct.ut_name));
# endif
} }
if (remotehost) { if (remotehost) {
@ -614,7 +618,11 @@ void KPty::logout()
setutent(); setutent();
if ((ut = getutline(&l_struct))) { if ((ut = getutline(&l_struct))) {
# endif # endif
# ifdef HAVE_UTMPX
memset(ut->ut_user, 0, sizeof(*ut->ut_user));
# else
memset(ut->ut_name, 0, sizeof(*ut->ut_name)); memset(ut->ut_name, 0, sizeof(*ut->ut_name));
# endif
memset(ut->ut_host, 0, sizeof(*ut->ut_host)); memset(ut->ut_host, 0, sizeof(*ut->ut_host));
# ifdef HAVE_STRUCT_UTMP_UT_SYSLEN # ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
ut->ut_syslen = 0; ut->ut_syslen = 0;

@ -278,7 +278,7 @@ public:
{ {
int index = 0; int index = 0;
int start = head; int start = head;
QLinkedList<QByteArray>::ConstIterator it = buffers.begin(); QLinkedList<QByteArray>::ConstIterator it = buffers.constBegin();
forever { forever {
if (!maxLength) if (!maxLength)
return index; return index;

@ -246,8 +246,28 @@ void QTermWidget::init(int startnow)
m_layout->setMargin(0); m_layout->setMargin(0);
setLayout(m_layout); setLayout(m_layout);
// translations
// First check $XDG_DATA_DIRS. This follows the implementation in libqtxdg
QString d = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
QStringList dirs = d.split(QLatin1Char(':'), QString::SkipEmptyParts);
if (dirs.isEmpty()) {
dirs.append(QString::fromLatin1("/usr/local/share"));
dirs.append(QString::fromLatin1("/usr/share"));
}
dirs.append(QFile::decodeName(TRANSLATIONS_DIR));
m_translator = new QTranslator(this);
for (const QString& dir : dirs) {
qDebug() << "Trying to load translation file from dir" << dir;
if (m_translator->load(QLocale::system(), "qtermwidget", "_", dir)) {
qApp->installTranslator(m_translator);
qDebug() << "Translations found in" << dir;
break;
}
}
m_impl = new TermWidgetImpl(this); m_impl = new TermWidgetImpl(this);
m_impl->m_terminalDisplay->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
m_layout->addWidget(m_impl->m_terminalDisplay); m_layout->addWidget(m_impl->m_terminalDisplay);
connect(m_impl->m_session, SIGNAL(bellRequest(QString)), m_impl->m_terminalDisplay, SLOT(bell(QString))); connect(m_impl->m_session, SIGNAL(bellRequest(QString)), m_impl->m_terminalDisplay, SLOT(bell(QString)));
@ -255,6 +275,8 @@ void QTermWidget::init(int startnow)
connect(m_impl->m_session, SIGNAL(activity()), this, SIGNAL(activity())); connect(m_impl->m_session, SIGNAL(activity()), this, SIGNAL(activity()));
connect(m_impl->m_session, SIGNAL(silence()), this, SIGNAL(silence())); connect(m_impl->m_session, SIGNAL(silence()), this, SIGNAL(silence()));
connect(m_impl->m_session, &Session::profileChangeCommandReceived, this, &QTermWidget::profileChanged);
connect(m_impl->m_session, &Session::receivedData, this, &QTermWidget::receivedData);
// That's OK, FilterChain's dtor takes care of UrlFilter. // That's OK, FilterChain's dtor takes care of UrlFilter.
UrlFilter *urlFilter = new UrlFilter(); UrlFilter *urlFilter = new UrlFilter();
@ -296,13 +318,14 @@ void QTermWidget::init(int startnow)
m_searchBar->setFont(font); m_searchBar->setFont(font);
setScrollBarPosition(NoScrollBar); setScrollBarPosition(NoScrollBar);
setKeyboardCursorShape(BlockCursor); setKeyboardCursorShape(Emulation::KeyboardCursorShape::BlockCursor);
m_impl->m_session->addView(m_impl->m_terminalDisplay); m_impl->m_session->addView(m_impl->m_terminalDisplay);
connect(m_impl->m_session, SIGNAL(resizeRequest(QSize)), this, SLOT(setSize(QSize))); connect(m_impl->m_session, SIGNAL(resizeRequest(QSize)), this, SLOT(setSize(QSize)));
connect(m_impl->m_session, SIGNAL(finished()), this, SLOT(sessionFinished())); connect(m_impl->m_session, SIGNAL(finished()), this, SLOT(sessionFinished()));
connect(m_impl->m_session, &Session::titleChanged, this, &QTermWidget::titleChanged); connect(m_impl->m_session, &Session::titleChanged, this, &QTermWidget::titleChanged);
connect(m_impl->m_session, &Session::cursorChanged, this, &QTermWidget::cursorChanged);
} }
@ -668,6 +691,13 @@ void QTermWidget::setKeyboardCursorShape(KeyboardCursorShape shape)
m_impl->m_terminalDisplay->setKeyboardCursorShape(shape); m_impl->m_terminalDisplay->setKeyboardCursorShape(shape);
} }
void QTermWidget::setBlinkingCursor(bool blink)
{
if (!m_impl->m_terminalDisplay)
return;
m_impl->m_terminalDisplay->setBlinkingCursor(blink);
}
QString QTermWidget::title() const QString QTermWidget::title() const
{ {
QString title = m_impl->m_session->userTitle(); QString title = m_impl->m_session->userTitle();
@ -688,3 +718,15 @@ bool QTermWidget::isTitleChanged() const
{ {
return m_impl->m_session->isTitleChanged(); return m_impl->m_session->isTitleChanged();
} }
void QTermWidget::setAutoClose(bool autoClose)
{
m_impl->m_session->setAutoClose(autoClose);
}
void QTermWidget::cursorChanged(Konsole::Emulation::KeyboardCursorShape cursorShape, bool blinkingCursorEnabled)
{
// TODO: A switch to enable/disable DECSCUSR?
setKeyboardCursorShape(cursorShape);
setBlinkingCursor(blinkingCursorEnabled);
}

@ -20,15 +20,18 @@
#ifndef _Q_TERM_WIDGET #ifndef _Q_TERM_WIDGET
#define _Q_TERM_WIDGET #define _Q_TERM_WIDGET
#include <QTranslator>
#include <QWidget> #include <QWidget>
#include "Emulation.h"
#include "Filter.h" #include "Filter.h"
#include "qtermwidget_export.h"
class QVBoxLayout; class QVBoxLayout;
struct TermWidgetImpl; struct TermWidgetImpl;
class SearchBar; class SearchBar;
class QUrl; class QUrl;
class QTermWidget : public QWidget { class QTERMWIDGET_EXPORT QTermWidget : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
@ -44,24 +47,7 @@ public:
ScrollBarRight = 2 ScrollBarRight = 2
}; };
/** using KeyboardCursorShape = Konsole::Emulation::KeyboardCursorShape;
* This enum describes the available shapes for the keyboard cursor.
* See setKeyboardCursorShape()
*/
enum KeyboardCursorShape {
/** A rectangular block which covers the entire area of the cursor character. */
BlockCursor = 0,
/**
* A single flat line which occupies the space at the bottom of the cursor
* character's area.
*/
UnderlineCursor = 1,
/**
* An cursor shaped like the capital letter 'I', similar to the IBeam
* cursor used in Qt/KDE text editors.
*/
IBeamCursor = 2
};
//Creation of widget //Creation of widget
QTermWidget(int startnow, // 1 = start shell programm immediatelly QTermWidget(int startnow, // 1 = start shell programm immediatelly
@ -211,6 +197,15 @@ public:
*/ */
void setKeyboardCursorShape(KeyboardCursorShape shape); void setKeyboardCursorShape(KeyboardCursorShape shape);
void setBlinkingCursor(bool blink);
/**
* Automatically close the terminal session after the shell process exits or
* keep it running.
*/
void setAutoClose(bool);
QString title() const; QString title() const;
QString icon() const; QString icon() const;
@ -240,8 +235,16 @@ signals:
*/ */
void sendData(const char *,int); void sendData(const char *,int);
void profileChanged(const QString & profile);
void titleChanged(); void titleChanged();
/**
* Signals that we received new data from the process running in the
* terminal emulator
*/
void receivedData(const QString &text);
public slots: public slots:
// Copy selection to clipboard // Copy selection to clipboard
void copyClipboard(); void copyClipboard();
@ -282,6 +285,11 @@ private slots:
void findPrevious(); void findPrevious();
void matchFound(int startColumn, int startLine, int endColumn, int endLine); void matchFound(int startColumn, int startLine, int endColumn, int endLine);
void noMatchFound(); void noMatchFound();
/**
* Emulation::cursorChanged() signal propogates to here and QTermWidget
* sends the specified cursor states to the terminal display
*/
void cursorChanged(Konsole::Emulation::KeyboardCursorShape cursorShape, bool blinkingCursorEnabled);
private: private:
void search(bool forwards, bool next); void search(bool forwards, bool next);
@ -290,6 +298,7 @@ private:
TermWidgetImpl * m_impl; TermWidgetImpl * m_impl;
SearchBar* m_searchBar; SearchBar* m_searchBar;
QVBoxLayout *m_layout; QVBoxLayout *m_layout;
QTranslator *m_translator;
}; };

@ -92,7 +92,7 @@ const QStringList get_color_schemes_dirs()
rval << (QCoreApplication::applicationDirPath() + "/../Resources/color-schemes/"); rval << (QCoreApplication::applicationDirPath() + "/../Resources/color-schemes/");
} }
#endif #endif
for (const QString& custom_dir : custom_color_schemes_dirs) for (const QString& custom_dir : const_cast<const QStringList&>(custom_color_schemes_dirs))
{ {
d.setPath(custom_dir); d.setPath(custom_dir);
if (d.exists()) if (d.exists())

@ -4,31 +4,33 @@ PyQt5 Bindings for QTermWidget
INSTALL: INSTALL:
------------ ------------
####1. Download QTermWidget -> https://github.com/lxde/qtermwidget
####2. Compile and install it: ####1. Download, compile and install QTermWidget:
$ mkdir build && cd build $ git clone https://github.com/lxde/qtermwidget.git
$ cd qtermwidget && mkdir build && cd build
$ cmake .. $ cmake ..
$ make $ make
$ sudo make install $ sudo make install
If `make install` command will not work just copy the `qtermwidget.so*` files to /usr/lib directory. If `make install` command will not work just copy the `qtermwidget.so*` files to /usr/lib directory.
####3. Install PyQt5 and PyQt5-devel if not yet installed. ####2. Install PyQt5 and PyQt5-devel if not yet installed.
####4. Configure, compile and install bindings. Execute in terminal in the qtermwidget bindings folder: ####3. Configure, compile and install Python bindings. Execute in terminal in the qtermwidget bindings folder:
$ cd pyqt/
$ python config.py $ QT_SELECT=5 python config.py
$ make $ make
$ sudo make install $ sudo make install
####5. You can run ./test.py to test the installed module. ####4. You can run ./test.py to test the installed module.
ABOUT: ABOUT:
--------- ---------
Curently maintained by:
- Pawel Koston <pawelkoston@gmail.com>
Based on previous PyQt4 bindings by: Based on previous PyQt4 bindings by:
- Piotr "Riklaunim" Maliński <riklaunim@gmail.com>, - Piotr "Riklaunim" Maliński <riklaunim@gmail.com>,
- Alexander Slesarev <alex.slesarev@gmail.com> - Alexander Slesarev <alex.slesarev@gmail.com>
PyQt5 QTermWidget Bindings PyQt5 QTermWidget Bindings
License: GPL3 License: GPL3

@ -5,66 +5,74 @@ import os
import site import site
import pprint import pprint
from distutils import sysconfig from distutils import sysconfig
import pyqtconfig
from PyQt5 import QtCore from PyQt5 import QtCore
import PyQt5 import PyQt5
class Configuration(sipconfig.Configuration): class Configuration(sipconfig.Configuration):
"""The class that represents PyQt configuration values. """The class that represents PyQt configuration values.
""" """
def getEnv(self,name, default):
return os.environ.get(name) or default def getEnv(self, name, default):
return os.environ.get(name) or default
def __init__(self):
qtconfig = subprocess.check_output(["/usr/lib64/qt5/bin/qmake", "-query"], universal_newlines=True) def __init__(self):
qtconfig = dict(x.split(":", 1) for x in qtconfig.splitlines()) qmake_bin = subprocess.check_output(
["which", "qmake"], universal_newlines=True).strip(' \t\n\r')
self.pyQtIncludePath = self.getEnv('PYQT_INCLUDE_PATH','/usr/share/sip/PyQt5' ) qtconfig = subprocess.check_output(
[qmake_bin, "-query"], universal_newlines=True)
pyqtconfig = { qtconfig = dict(x.split(":", 1) for x in qtconfig.splitlines())
"pyqt_config_args": "--confirm-license -v "+str(self.pyQtIncludePath)+" --qsci-api -q /usr/lib64/qt5/bin/qmake",
"pyqt_version": QtCore.PYQT_VERSION, self.pyQtIncludePath = self.getEnv(
"pyqt_version_str": QtCore.PYQT_VERSION_STR, 'PYQT_INCLUDE_PATH', '/usr/share/sip/PyQt5')
"pyqt_bin_dir": PyQt5.__path__[0],
"pyqt_mod_dir": PyQt5.__path__[0], pyqtconfig = {
"pyqt_sip_dir": str(self.pyQtIncludePath), "pyqt_config_args": "--confirm-license -v " + str(self.pyQtIncludePath) + " --qsci-api -q " + qmake_bin,
"pyqt_modules": "QtCore QtGui QtWidgets", #... and many more "pyqt_version": QtCore.PYQT_VERSION,
"pyqt_sip_flags": QtCore.PYQT_CONFIGURATION['sip_flags'], "pyqt_version_str": QtCore.PYQT_VERSION_STR,
"qt_version": QtCore.QT_VERSION, "pyqt_bin_dir": PyQt5.__path__[0],
"qt_edition": "free", "pyqt_mod_dir": PyQt5.__path__[0],
"qt_winconfig": "shared", "pyqt_sip_dir": str(self.pyQtIncludePath),
"qt_framework": 0, "pyqt_modules": "QtCore QtGui QtWidgets", # ... and many more
"qt_threaded": 1, "pyqt_sip_flags": QtCore.PYQT_CONFIGURATION['sip_flags'],
"qt_dir": qtconfig['QT_INSTALL_PREFIX'], "qt_version": QtCore.QT_VERSION,
"qt_data_dir": qtconfig['QT_INSTALL_DATA'], "qt_edition": "free",
"qt_archdata_dir": qtconfig['QT_INSTALL_DATA'], "qt_winconfig": "shared",
"qt_inc_dir": qtconfig['QT_INSTALL_HEADERS'], "qt_framework": 0,
"qt_lib_dir": qtconfig['QT_INSTALL_LIBS'] "qt_threaded": 1,
} "qt_dir": qtconfig['QT_INSTALL_PREFIX'],
"qt_data_dir": qtconfig['QT_INSTALL_DATA'],
macros = sipconfig._default_macros.copy() "qt_archdata_dir": qtconfig['QT_INSTALL_DATA'],
macros['INCDIR_QT'] = qtconfig['QT_INSTALL_HEADERS'] "qt_inc_dir": qtconfig['QT_INSTALL_HEADERS'],
macros['LIBDIR_QT'] = qtconfig['QT_INSTALL_LIBS'] "qt_lib_dir": qtconfig['QT_INSTALL_LIBS']
macros['MOC'] = os.path.join(qtconfig['QT_INSTALL_BINS'], 'moc') }
sipconfig.Configuration.__init__(self, [pyqtconfig]) macros = sipconfig._default_macros.copy()
self.set_build_macros(macros) macros['INCDIR_QT'] = qtconfig['QT_INSTALL_HEADERS']
macros['LIBDIR_QT'] = qtconfig['QT_INSTALL_LIBS']
macros['MOC'] = os.path.join(qtconfig['QT_INSTALL_BINS'], 'moc')
## The name of the SIP build file generated by SIP and used by the build system.
sipconfig.Configuration.__init__(self, [pyqtconfig])
self.set_build_macros(macros)
# The name of the SIP build file generated by SIP and used by the build system.
build_file = "qtermwidget.sbf" build_file = "qtermwidget.sbf"
# Get the SIP configuration information. # Get the SIP configuration information.
config = Configuration() config = Configuration()
# Run SIP to generate the build_file # Run SIP to generate the build_file
os.system(" ".join([config.sip_bin, '-I' , str(config.pyQtIncludePath), str(config.pyqt_sip_flags), "-b", build_file,"-o", "-c", ". " " qtermwidget.sip"])) os.system(" ".join([config.sip_bin, '-I', str(config.pyQtIncludePath), str(
config.pyqt_sip_flags), "-b", build_file, "-o", "-c", ". " " qtermwidget.sip"]))
installs = [] installs = []
installs.append(["qtermwidget.sip", os.path.join(config.pyqt_sip_dir,"qtermwidget")]) installs.append(["qtermwidget.sip", os.path.join(
config.pyqt_sip_dir, "qtermwidget")])
installs.append(["qtermwidgetconfig.py", config.pyqt_mod_dir]) installs.append(["qtermwidgetconfig.py", config.pyqt_mod_dir])
makefile = sipconfig.SIPModuleMakefile( configuration = config, build_file = build_file, installs = installs, qt=["QtCore" ,"QtGui", "QtWidgets"] ) makefile = sipconfig.SIPModuleMakefile(
configuration=config, build_file=build_file, installs=installs, qt=["QtCore", "QtGui", "QtWidgets"])
# Add the library we are wrapping. The name doesn't include any platform # Add the library we are wrapping. The name doesn't include any platform
# specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the # specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the
@ -73,20 +81,23 @@ makefile.extra_lib_dirs.append("../lib/")
makefile.extra_lib_dirs.append("..") makefile.extra_lib_dirs.append("..")
makefile.extra_libs = ["qtermwidget5"] makefile.extra_libs = ["qtermwidget5"]
# Support for C++11
makefile.extra_cxxflags.append('-std=c++11')
# Generate the Makefile itself. # Generate the Makefile itself.
makefile.generate() makefile.generate()
content = { content = {
# Publish where the SIP specifications for this module will be # Publish where the SIP specifications for this module will be
# installed. # installed.
"qtermwidget_sip_dir": config.pyqt_sip_dir, "qtermwidget_sip_dir": config.pyqt_sip_dir,
# Publish the set of SIP flags needed by this module. As these are the # Publish the set of SIP flags needed by this module. As these are the
# same flags needed by the qt module we could leave it out, but this # same flags needed by the qt module we could leave it out, but this
# allows us to change the flags at a later date without breaking # allows us to change the flags at a later date without breaking
# scripts that import the configuration module. # scripts that import the configuration module.
"qtermwidget_sip_flags": config.pyqt_sip_flags "qtermwidget_sip_flags": config.pyqt_sip_flags
} }
# This creates the qtermwidgetconfig.py module from the qtermwidgetconfig.py.in # This creates the qtermwidgetconfig.py module from the qtermwidgetconfig.py.in
# template and the dictionary. # template and the dictionary.

@ -1,8 +1,6 @@
%Module QTermWidget %Module QTermWidget
%Import QtGui/QtGuimod.sip %Import QtGui/QtGuimod.sip
%Import QtCore/QtCoremod.sip %Import QtCore/QtCoremod.sip
%Import QtWidgets/QtWidgetsmod.sip %Import QtWidgets/QtWidgetsmod.sip
@ -21,9 +19,16 @@ public:
ScrollBarRight=2 ScrollBarRight=2
}; };
enum KeyboardCursorShape
{
BlockCursor=0,
UnderlineCursor=1,
IBeamCursor=2
};
QTermWidget(int startnow = 1, QWidget *parent = 0); QTermWidget(int startnow = 1, QWidget *parent = 0);
~QTermWidget(); ~QTermWidget();
void startTerminalTeletype();
QSize sizeHint() const; QSize sizeHint() const;
void startShellProgram(); void startShellProgram();
int getShellPID(); int getShellPID();
@ -35,10 +40,11 @@ public:
void setShellProgram(const QString & progname); void setShellProgram(const QString & progname);
void setWorkingDirectory(const QString & dir); void setWorkingDirectory(const QString & dir);
QString workingDirectory(); QString workingDirectory();
void setArgs(QStringList &args); void setArgs(QStringList & args);
void setTextCodec(QTextCodec *codec); void setTextCodec(QTextCodec *codec);
void setColorScheme(const QString & name); void setColorScheme(const QString & name);
static QStringList availableColorSchemes(); static QStringList availableColorSchemes();
static void addCustomColorSchemeDir(const QString& custom_dir);
void setHistorySize(int lines); void setHistorySize(int lines);
void setScrollBarPosition(ScrollBarPosition); void setScrollBarPosition(ScrollBarPosition);
void scrollToEnd(); void scrollToEnd();
@ -59,28 +65,48 @@ public:
void setMonitorActivity(bool); void setMonitorActivity(bool);
void setMonitorSilence(bool); void setMonitorSilence(bool);
void setSilenceTimeout(int seconds); void setSilenceTimeout(int seconds);
int getPtySlaveFd() const;
void setKeyboardCursorShape(KeyboardCursorShape shape);
void setAutoClose(bool);
QString title() const;
QString icon() const;
signals: signals:
void finished(); void finished();
void copyAvailable(bool); void copyAvailable(bool);
void termGetFocus(); void termGetFocus();
void termLostFocus(); void termLostFocus();
void termKeyPressed(QKeyEvent *); void termKeyPressed(QKeyEvent *);
void urlActivated(const QUrl&); void urlActivated(const QUrl&, bool fromContextMenu);
void bell(const QString& message); void bell(const QString& message);
void activity(); void activity();
void silence(); void silence();
void sendData(const char *,int);
void titleChanged();
void receivedData(const QString &text);
void profileChanged(const QString & profile);
public slots: public slots:
void copyClipboard(); void copyClipboard();
void pasteClipboard(); void pasteClipboard();
void pasteSelection(); void pasteSelection();
void zoomIn(); void zoomIn();
void zoomOut(); void zoomOut();
void setSize(const QSize &);
void setKeyBindings(const QString & kb); void setKeyBindings(const QString & kb);
void clear(); void clear();
void toggleShowSearchBar(); void toggleShowSearchBar();
void setSize(const QSize&);
protected: protected:
void resizeEvent(QResizeEvent *e); virtual void resizeEvent(QResizeEvent *);
protected slots:
void sessionFinished();
void selectionChanged(bool textSelected);
private: private:
void *createTermWidget(int startnow, void *parent); void search(bool forwards, bool next);
void setZoom(int step);
void init(int startnow);
private slots:
void find();
void findNext();
void findPrevious();
void matchFound(int startColumn, int startLine, int endColumn, int endLine);
void noMatchFound();
}; };

Loading…
Cancel
Save