Merge lp:~dpm/ubuntu-terminal-app/merge-plugin into lp:ubuntu-terminal-app

Proposed by David Planella
Status: Merged
Approved by: Nicholas Skaggs
Approved revision: 75
Merged at revision: 57
Proposed branch: lp:~dpm/ubuntu-terminal-app/merge-plugin
Merge into: lp:ubuntu-terminal-app
Diff against target: 25271 lines (+24506/-71)
106 files modified
.bzrignore (+0/-6)
CMakeLists.txt (+33/-18)
README (+0/-1)
README.md (+152/-0)
apparmor.json (+3/-2)
click/CMakeLists.txt (+0/-8)
debian/changelog (+6/-2)
debian/control (+29/-8)
debian/qtdeclarative5-konsole-qml-plugin.install (+1/-0)
manifest.json (+6/-6)
plugins.json (+0/-6)
src/CMakeLists.txt (+2/-0)
src/app/CMakeLists.txt (+24/-0)
src/app/main.cpp (+120/-0)
src/plugin/CMakeLists.txt (+7/-0)
src/plugin/konsole/BlockArray.cpp (+377/-0)
src/plugin/konsole/BlockArray.h (+126/-0)
src/plugin/konsole/CMakeLists.txt (+93/-0)
src/plugin/konsole/Character.h (+221/-0)
src/plugin/konsole/CharacterColor.h (+294/-0)
src/plugin/konsole/ColorScheme.cpp (+774/-0)
src/plugin/konsole/ColorScheme.h (+342/-0)
src/plugin/konsole/ColorTables.h (+55/-0)
src/plugin/konsole/DefaultTranslatorText.h (+2/-0)
src/plugin/konsole/Emulation.cpp (+458/-0)
src/plugin/konsole/Emulation.h (+467/-0)
src/plugin/konsole/ExtendedDefaultTranslator.h (+74/-0)
src/plugin/konsole/Filter.cpp (+542/-0)
src/plugin/konsole/Filter.h (+380/-0)
src/plugin/konsole/History.cpp (+986/-0)
src/plugin/konsole/History.h (+490/-0)
src/plugin/konsole/KeyboardTranslator.cpp (+892/-0)
src/plugin/konsole/KeyboardTranslator.h (+584/-0)
src/plugin/konsole/LineFont.h (+21/-0)
src/plugin/konsole/LineFont.src (+786/-0)
src/plugin/konsole/Pty.cpp (+310/-0)
src/plugin/konsole/Pty.h (+206/-0)
src/plugin/konsole/Screen.cpp (+1360/-0)
src/plugin/konsole/Screen.h (+672/-0)
src/plugin/konsole/ScreenWindow.cpp (+292/-0)
src/plugin/konsole/ScreenWindow.h (+257/-0)
src/plugin/konsole/Session.cpp (+1064/-0)
src/plugin/konsole/Session.h (+626/-0)
src/plugin/konsole/ShellCommand.cpp (+167/-0)
src/plugin/konsole/ShellCommand.h (+90/-0)
src/plugin/konsole/TerminalCharacterDecoder.cpp (+251/-0)
src/plugin/konsole/TerminalCharacterDecoder.h (+148/-0)
src/plugin/konsole/TerminalDisplay.cpp (+2170/-0)
src/plugin/konsole/TerminalDisplay.h (+715/-0)
src/plugin/konsole/Vt102Emulation.cpp (+1221/-0)
src/plugin/konsole/Vt102Emulation.h (+188/-0)
src/plugin/konsole/assets/color-schemes/BlackOnLightYellow.schema (+42/-0)
src/plugin/konsole/assets/color-schemes/BlackOnRandomLight.colorscheme (+104/-0)
src/plugin/konsole/assets/color-schemes/BlackOnWhite.schema (+42/-0)
src/plugin/konsole/assets/color-schemes/DarkPastels.colorscheme (+103/-0)
src/plugin/konsole/assets/color-schemes/GreenOnBlack.colorscheme (+104/-0)
src/plugin/konsole/assets/color-schemes/Linux.colorscheme (+100/-0)
src/plugin/konsole/assets/color-schemes/WhiteOnBlack.schema (+42/-0)
src/plugin/konsole/assets/color-schemes/historic/BlackOnLightColor.schema (+42/-0)
src/plugin/konsole/assets/color-schemes/historic/DarkPicture.schema (+44/-0)
src/plugin/konsole/assets/color-schemes/historic/Example.Schema (+47/-0)
src/plugin/konsole/assets/color-schemes/historic/GreenOnBlack.schema (+42/-0)
src/plugin/konsole/assets/color-schemes/historic/GreenTint.schema (+49/-0)
src/plugin/konsole/assets/color-schemes/historic/GreenTint_MC.schema (+49/-0)
src/plugin/konsole/assets/color-schemes/historic/LightPicture.schema (+44/-0)
src/plugin/konsole/assets/color-schemes/historic/Linux.schema (+47/-0)
src/plugin/konsole/assets/color-schemes/historic/README.Schema (+132/-0)
src/plugin/konsole/assets/color-schemes/historic/README.default.Schema (+44/-0)
src/plugin/konsole/assets/color-schemes/historic/Transparent.schema (+49/-0)
src/plugin/konsole/assets/color-schemes/historic/Transparent_MC.schema (+51/-0)
src/plugin/konsole/assets/color-schemes/historic/Transparent_darkbg.schema (+42/-0)
src/plugin/konsole/assets/color-schemes/historic/Transparent_lightbg.schema (+51/-0)
src/plugin/konsole/assets/color-schemes/historic/XTerm.schema (+46/-0)
src/plugin/konsole/assets/color-schemes/historic/syscolor.schema (+44/-0)
src/plugin/konsole/assets/color-schemes/historic/vim.schema (+40/-0)
src/plugin/konsole/assets/kb-layouts/README (+72/-0)
src/plugin/konsole/assets/kb-layouts/default.keytab (+169/-0)
src/plugin/konsole/assets/kb-layouts/historic/vt100.keytab (+133/-0)
src/plugin/konsole/assets/kb-layouts/historic/x11r5.keytab (+71/-0)
src/plugin/konsole/assets/kb-layouts/linux.keytab (+164/-0)
src/plugin/konsole/assets/kb-layouts/macbook.keytab (+175/-0)
src/plugin/konsole/assets/kb-layouts/solaris.keytab (+108/-0)
src/plugin/konsole/assets/kb-layouts/vt420pc.keytab (+168/-0)
src/plugin/konsole/default.keytab (+128/-0)
src/plugin/konsole/konsole_wcwidth.cpp (+224/-0)
src/plugin/konsole/konsole_wcwidth.h (+24/-0)
src/plugin/konsole/kprocess.cpp (+412/-0)
src/plugin/konsole/kprocess.h (+372/-0)
src/plugin/konsole/kpty.cpp (+701/-0)
src/plugin/konsole/kpty.h (+191/-0)
src/plugin/konsole/kpty_p.h (+50/-0)
src/plugin/konsole/kptydevice.cpp (+422/-0)
src/plugin/konsole/kptydevice.h (+360/-0)
src/plugin/konsole/kptyprocess.cpp (+129/-0)
src/plugin/konsole/kptyprocess.h (+178/-0)
src/plugin/konsole/ksession.cpp (+242/-0)
src/plugin/konsole/ksession.h (+132/-0)
src/plugin/konsole/plugin.cpp (+63/-0)
src/plugin/konsole/plugin.h (+46/-0)
src/plugin/konsole/plugins.qmltypes (+169/-0)
src/plugin/konsole/qmldir (+3/-0)
src/plugin/konsole/tools.cpp (+80/-0)
src/plugin/konsole/tools.h (+10/-0)
tests/autopilot/CMakeLists.txt (+1/-1)
tests/autopilot/ubuntu_terminal_app/tests/__init__.py (+25/-10)
ubuntu-terminal-app.in (+0/-3)
To merge this branch: bzr merge lp:~dpm/ubuntu-terminal-app/merge-plugin
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Nicholas Skaggs Pending
Review via email: mp+217380@code.launchpad.net

Commit message

Merge the terminal app's plugin into the app's repository

Description of the change

This branch merges the terminal app's plugin into the app's repository, enabling shipping the plugin into the same .click package. Separate .deb packages for the app and the plugin are still generated.

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :

FAILED: Continuous integration, rev:67
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~dpm/ubuntu-terminal-app/merge-plugin/+merge/217380/+edit-commit-message

http://91.189.93.70:8080/job/ubuntu-terminal-app-ci/49/
Executed test runs:
    SUCCESS: http://91.189.93.70:8080/job/generic-mediumtests-trusty/2254
    SUCCESS: http://91.189.93.70:8080/job/ubuntu-terminal-app-raring-amd64-ci/49
    SUCCESS: http://91.189.93.70:8080/job/ubuntu-terminal-app-saucy-amd64-ci/49
    SUCCESS: http://91.189.93.70:8080/job/ubuntu-terminal-app-trusty-amd64-ci/37

Click here to trigger a rebuild:
http://91.189.93.70:8080/job/ubuntu-terminal-app-ci/49/rebuild

review: Needs Fixing (continuous-integration)
68. By David Planella

Added rule to copy the plugin to the build directory

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Pope 🍺🐧🐱 🦄 (popey) wrote :

Tried building this in qtcreator, it built a click package, but that fails the click-reviewers-tools..

ERROR: Could not find 'com.ubuntu.terminal.desktop.in'

69. By David Planella

Fixed wrong desktop file in the manifest

Revision history for this message
David Planella (dpm) wrote :

Sorry, that was a typo in the manifest file. Fixed now.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Pope 🍺🐧🐱 🦄 (popey) wrote :

Trying to test this but qtc is conspiring against me: bug 1314960

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

In order to get this to run, you need the python3-lxml lib added to /home/phablet/autopilot -- and you need the armhf version as it's a compiled module ;-) I would recommend adding this info to the readme.

I was able to successfully build and run this on my device.

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

I would also change the dependency to python3-lxml from python-lxml.

70. By David Planella

Updated python-lxml dependency to Python 3, added note about manual set up for running tests on device

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

could not import package ubuntu_terminal_app: No module named 'ubuntu_terminal_app'
Loading tests from:

Did not find any tests

We had this same issue with shorts; py3 meant jenkins couldn't find the tests. If you change back to python-lxml I assume it will work.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

On 6 May 2014 18:09, Nicholas Skaggs <email address hidden> wrote:
> could not import package ubuntu_terminal_app: No module named 'ubuntu_terminal_app'
> Loading tests from:
>
> Did not find any tests
>
> We had this same issue with shorts; py3 meant jenkins couldn't find the tests. If you change back to python-lxml I assume it will work.

Both Python2 & Python3 comes with an xml module in the standard
library is that not sufficient?

--
Regards,

Dimitri.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :
Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Dimitri, yes in this case I think we simply drop the lxml dependency.

In regards to what I was saying about jenkins missing tests, I finally figured out why jenkins wasn't finding the tests. It requires the core app to depend on python3, and for the cmakelists file for autopilot tests to copy the module to the python3 path, instead of python2 :-)

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

On 6 May 2014 19:39, Nicholas Skaggs <email address hidden> wrote:
> See https://code.launchpad.net/~nskaggs/ubuntu-terminal-app/working-py3-jenkins/+merge/218488 for the fix
> --
> https://code.launchpad.net/~dpm/ubuntu-terminal-app/merge-plugin/+merge/217380
> Your team Ubuntu Terminal Developers is subscribed to branch lp:ubuntu-terminal-app.

Or see... https://code.launchpad.net/~xnox/ubuntu-terminal-app/merge-plugin+lxml+py3
which is mid-air colition, slightly older than your branch.

--
Regards,

Dimitri.

Revision history for this message
David Planella (dpm) wrote :

As far as I can tell, the standard module is not a drop-in replacement for lxml, so just replacing the import won't work.

In any case, as discussed on IRC, I'll split this MP to separate the change that introduced the lxml dependency.

71. By David Planella

Reverted the feature of autodetecting Qt Creator's build dir. Will submit it in a separate MP

72. By David Planella

Updated README too

73. By David Planella

Merged nskagg's Jenkins Python 3 fixes

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
74. By David Planella

Merge Python 3 print() fix from balloons

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Specify python3-autopilot so jenkins runs with it.

=== modified file 'debian/control'
--- debian/control 2014-05-06 19:04:04 +0000
+++ debian/control 2014-05-06 21:41:01 +0000
@@ -45,6 +45,7 @@
 Depends: ${misc:Depends},
          libautopilot-qt,
          libqt5test5,
+ python3-autopilot,
          ubuntu-terminal-app (>= ${source:Version}),
          ubuntu-ui-toolkit-autopilot,
 Description: Autopilot tests for Terminal Application

75. By David Planella

Add Python 3 dependency to make Jenkins happy

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2014-05-06 21:50:22 +0000
4@@ -0,0 +1,16 @@
5+Makefile
6+src/*.so
7+*user
8+
9+.moc/
10+.obj/
11+
12+debian/files
13+debian/qtdeclarative5-konsole-qml-plugin/
14+debian/*.debhelper.log
15+debian/*.substvars
16+.excludes
17+obj-x86_64-linux-gnu
18+debian/tmp
19+debian/ubuntu-terminal-app
20+debian/ubuntu-terminal-app-autopilot
21
22=== removed file '.bzrignore'
23--- .bzrignore 2013-04-23 20:42:10 +0000
24+++ .bzrignore 1970-01-01 00:00:00 +0000
25@@ -1,6 +0,0 @@
26-*.qmlproject.user
27-
28-debian/files
29-debian/ubuntu-terminal-app/
30-debian/*.debhelper.log
31-debian/*.substvars
32
33=== modified file 'CMakeLists.txt'
34--- CMakeLists.txt 2014-04-15 18:00:53 +0000
35+++ CMakeLists.txt 2014-05-06 21:50:22 +0000
36@@ -1,6 +1,9 @@
37-project(com.ubuntu.terminal)
38+project(com.ubuntu.terminal C CXX)
39 cmake_minimum_required(VERSION 2.8.9)
40
41+set(CMAKE_AUTOMOC ON)
42+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra -fPIC")
43+
44 # Standard install paths
45 include(GNUInstallDirs)
46
47@@ -8,49 +11,61 @@
48 option(CLICK_MODE "Installs to a contained location" off)
49
50 set(APP_NAME terminal)
51-set(DESKTOP_FILE "${PROJECT_NAME}_${APP_NAME}.desktop")
52-set(URLS_FILE "${PROJECT_NAME}_${APP_NAME}.url-dispatcher")
53+set(DESKTOP_FILE "${PROJECT_NAME}.desktop")
54+set(URLS_FILE "${PROJECT_NAME}.url-dispatcher")
55 set(APP_HARDCODE ubuntu-terminal-app)
56 set(MAIN_QML ubuntu-terminal-app.qml)
57 set(ICON_FILE terminal64.png)
58 set(AUTOPILOT_DIR ubuntu_terminal_app)
59+set(EXEC "${APP_NAME}")
60
61 if(CLICK_MODE)
62 if(NOT DEFINED BZR_SOURCE)
63 set(BZR_SOURCE "lp:${APP_HARDCODE}")
64 message("-- Setting BZR_SOURCE to ${BZR_SOURCE}")
65 endif(NOT DEFINED BZR_SOURCE)
66+ # Find out the architecture for package building
67+ # to determine the plugin's installation path
68+ execute_process(
69+ COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
70+ OUTPUT_VARIABLE ARCH_TRIPLET
71+ OUTPUT_STRIP_TRAILING_WHITESPACE
72+ )
73 set(CMAKE_INSTALL_PREFIX /)
74 set(CMAKE_INSTALL_BINDIR /)
75 set(DATA_DIR /)
76- set(EXEC "qmlscene ${MAIN_QML}")
77 set(DESKTOP_DIR ${DATA_DIR})
78 set(URLS_DIR ${DATA_DIR})
79- set(ICON ${ICON_FILE})
80+ set(ICON ${ICON_FILE})
81+ set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}")
82+ set(BIN_DIR /lib/${ARCH_TRIPLET}/bin)
83+ if(NOT BZR_REVNO)
84+ set(BZR_REVNO "latest")
85+ endif(NOT BZR_REVNO)
86+ configure_file(manifest.json ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)
87+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json apparmor.json DESTINATION ${CMAKE_INSTALL_PREFIX})
88 else(CLICK_MODE)
89- set(DATA_DIR ${CMAKE_INSTALL_DATADIR}/${APP_HARDCODE})
90- set(EXEC ${APP_HARDCODE})
91- set(ICON ${CMAKE_INSTALL_PREFIX}/${DATA_DIR}/${ICON_FILE})
92- configure_file(${APP_HARDCODE}.in
93- ${CMAKE_CURRENT_BINARY_DIR}/${APP_HARDCODE})
94- install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${APP_HARDCODE}
95- DESTINATION ${CMAKE_INSTALL_BINDIR})
96+ execute_process(
97+ COMMAND qmake -query QT_INSTALL_QML
98+ OUTPUT_VARIABLE QT_IMPORTS_DIR
99+ OUTPUT_STRIP_TRAILING_WHITESPACE
100+ )
101+ set(DATA_DIR ${CMAKE_INSTALL_DATADIR}/${APP_NAME})
102+ set(ICON ${CMAKE_INSTALL_PREFIX}/${DATA_DIR}/${ICON_FILE})
103 set(DESKTOP_DIR ${CMAKE_INSTALL_DATADIR}/applications)
104 set(URLS_DIR ${CMAKE_INSTALL_DATADIR}/url-dispatcher/urls)
105 endif(CLICK_MODE)
106
107 file(GLOB_RECURSE I18N_SRC_FILES
108 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
109- rc/**.qml desktop/**.desktop.in)
110+ src/app/**.qml *.desktop.in)
111 list(SORT I18N_SRC_FILES)
112
113-
114 file(GLOB SRC_FILES
115 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
116 *.qml *.js *.png *.js)
117-install(DIRECTORY config extraPanel DESTINATION ${DATA_DIR})
118-install(FILES Terminal.qml Configs.qml settings.png avatar@8.png
119- ${MAIN_QML} ${ICON_FILE} DESTINATION ${DATA_DIR})
120+install(FILES ${SRC_FILES}
121+ DESTINATION ${DATA_DIR})
122
123 configure_file(${DESKTOP_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE})
124 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE}
125@@ -61,6 +76,6 @@
126 # Tests
127 enable_testing()
128
129-add_subdirectory(click)
130 add_subdirectory(po)
131 add_subdirectory(tests)
132+add_subdirectory(src)
133
134=== removed file 'README'
135--- README 2013-02-12 16:18:48 +0000
136+++ README 1970-01-01 00:00:00 +0000
137@@ -1,1 +0,0 @@
138-this is an example README file.
139
140=== added file 'README.md'
141--- README.md 1970-01-01 00:00:00 +0000
142+++ README.md 2014-05-06 21:50:22 +0000
143@@ -0,0 +1,152 @@
144+# Ubuntu Terminal
145+
146+A terminal app for desktop and mobile devices. It provides access to terminal
147+sessions and is based on KDE's Konsole plugin.
148+
149+The current plugin consists of:
150+- KTerminal: offers access to terminal session from qml
151+- KSessions: offers access to pty(s) from C++ layer
152+
153+## Building the app
154+
155+### For the desktop
156+
157+Install the following build dependencies:
158+
159+(none required at the moment)
160+
161+Then open the CMakeLists.txt file in Qt Creator, and ensure that the kit
162+selected on the left sidebar (just above the green "Run" button) is "Desktop"
163+
164+### For a device
165+
166+If you don't have one already, you'll need to create an armhf chroot to
167+cross-compile the app. Here's how:
168+
169+1. In Qt Creator, open the CMakeLists.txt file
170+2. Go to Tools > Options > Ubuntu > Click
171+2. Click on Create Click Target
172+3. Follow the prompts to generate the chroot. You will be asked for your sudo
173+ password
174+4. Once created, you'll need to add the build dependencies for the app:
175+ - At this time, none are required, but the steps are shown for the sake of
176+ completion
177+ - Click on the Maintain button on your chroot
178+ - On the terminal prompt that is started, type
179+ apt-get install $DEPENDENCY_NAME:armhf'
180+ - Close the terminal when the installation finishes
181+5. Now you can either do a clean checkout and wait to be prompted by Qt Creator
182+ to add the armhf kit, or alternatively:
183+6. Go to the Projects tab > Add kit and then select the UbuntuSDK armhf kit
184+
185+Additionally, you'll have to tell Qt Creator that you are doing a build for a
186+device to ultimately create a click package for installation:
187+
188+1. In Qt Creator, go to the Projects tab on the sidebar
189+2. Click on the "Build" subtab of the "UbuntuSDK for armhf..." tab
190+3. Then go to the "CMake arguments" text field and add "-DCLICK_MODE=on"
191+ without the quotes
192+
193+Before starting the build make sure to select the "UbuntuSDK" kit on Qt
194+Creator's left sidebar (just above the green "Run" button).
195+
196+### Doing the build
197+
198+Ensure you've selected the kit you want for your build and press the build
199+button on Qt Creator's left sidebar (or alternatively Ctrl+B).
200+
201+## Running the app
202+
203+### On the desktop
204+
205+No additional steps are required before running the app on the desktop.
206+
207+### On a device
208+
209+Due to Qt Creator's bug #1312094 in launchpad.net, there needs to be a manual
210+workaround done before the app can run on the device:
211+
212+1. Modify the desktop.in file: change the Exec line to read:
213+ Exec=lib/arm-linux-gnueabihf/bin/@EXEC@
214+
215+Remember to revert this temporary change if you are building a click package or
216+if you're making other changes to be committed to the code!
217+
218+### Starting the app
219+
220+Ensure you've selected the kit you want for your build and press the run
221+button on Qt Creator's left sidebar (or alternatively Ctrl+R).
222+
223+If the app hasn't been built yet, or if there are pending changes that require
224+a build, the app will automatically be built first before running.
225+
226+If you're starting the app on a device, the build will be copied over and the
227+code will run unconfined.
228+
229+## Building a click package
230+
231+There are two alternative ways of building a click package.
232+
233+### Using Qt Creator
234+
235+1. Ensure you've selected the UbuntuSDK for armhf kit on Qt Creator's sidebar
236+2. Click on Publish on the sidebar
237+3. Click on "Create package"
238+4. If all goes well, you'll find the final click package in the build directory
239+
240+Notes:
241+- You can see the output of the click build if you click on Edit on the sidebar
242+ and then "Application Output" at the bottom. This is useful to identify any
243+ failures during the build
244+- Run `sudo apt-get install click-reviewers-tools` to enable click package
245+ validation in Qt Creator. You might need to restart Qt Creator after you've
246+ installed them for it to detect them
247+
248+### Using click-buddy
249+
250+1. Install phablet-tools: `sudo apt-get install phablet-tools`
251+2. Run click-buddy in your source tree:
252+ click-buddy --dir . --arch armhf --framework ubuntu-sdk-14.04
253+3. Once finished, click-buddy will tell you the location of your source package
254+
255+## Installing a click package
256+
257+First of all, ensure you've got a working Ubuntu device attached over USB to
258+your host computer
259+
260+### Manually
261+
262+Run the following commands to manually install the click package (replace 0.1
263+with the version of your package):
264+
265+ adb push /home/phablet com.ubuntu.terminal_0.1_armhf.click
266+ adb shell
267+ sudo -H -u phablet pkcon install-local /home/phablet/com.ubuntu.terminal_0.1_armhf.click
268+
269+### Using click-buddy
270+
271+You can add the --provision argument to the previous command to install the
272+click package on the device.
273+
274+### Starting the app
275+
276+1. Either kill unity8 with `pkill unity8` or restart the system for the Apps
277+ (click) scope to pick up your newly installed click package
278+2. Search for Reminders in the Apps scope and tap on its icon to start it
279+3. You'll find the runtime logs at ~/.cache/upstart/application-click/
280+
281+## Uninstalling a click package
282+
283+Run the following commands, replacing the version of the click package you want
284+to uninstall:
285+
286+ adb shell
287+ sudo -iu phablet
288+ sudo click unregister com.ubuntu.terminal 0.1
289+
290+## Run the autopilot tests
291+
292+Once the app has been built, you can go to the build directory and run:
293+
294+ cd tests/autopilot
295+ autopilot run ubuntu_terminal_app
296
297=== renamed file 'click/apparmor.json' => 'apparmor.json'
298--- click/apparmor.json 2014-03-14 18:33:50 +0000
299+++ apparmor.json 2014-05-06 21:50:22 +0000
300@@ -1,4 +1,5 @@
301 {
302- "policy_version": 1.1,
303+ "policy_groups": [],
304+ "policy_version": 1.1,
305 "template": "unconfined"
306-}
307+}
308\ No newline at end of file
309
310=== removed directory 'click'
311=== removed file 'click/CMakeLists.txt'
312--- click/CMakeLists.txt 2014-01-31 21:52:08 +0000
313+++ click/CMakeLists.txt 1970-01-01 00:00:00 +0000
314@@ -1,8 +0,0 @@
315-if(CLICK_MODE)
316- if(NOT BZR_REVNO)
317- set(BZR_REVNO "latest")
318- endif(NOT BZR_REVNO)
319- configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)
320- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json apparmor.json
321- DESTINATION ${CMAKE_INSTALL_PREFIX})
322-endif(CLICK_MODE)
323
324=== renamed file 'com.ubuntu.terminal_terminal.desktop.in' => 'com.ubuntu.terminal.desktop.in'
325=== renamed file 'com.ubuntu.terminal_terminal.url-dispatcher' => 'com.ubuntu.terminal.url-dispatcher'
326=== modified file 'debian/changelog'
327--- debian/changelog 2014-03-10 10:19:53 +0000
328+++ debian/changelog 2014-05-06 21:50:22 +0000
329@@ -1,8 +1,12 @@
330-ubuntu-terminal-app (0.5ubuntu1) UNRELEASED; urgency=medium
331+ubuntu-terminal-app (0.5ubuntu2) trusty; urgency=medium
332
333+ [ Alan Pope ]
334 * Add -qt5 command line option (LP: #1288885)
335
336- -- Alan Pope <popey@ubuntu.com> Mon, 10 Mar 2014 10:19:27 +0000
337+ [ David Planella ]
338+ * Merge konsole plugin into the app's repo.
339+
340+ -- David Planella <david.planella@ubuntu.com> Sun, 27 Apr 2014 12:08:04 +0200
341
342 ubuntu-terminal-app (0.5) raring; urgency=low
343
344
345=== modified file 'debian/control'
346--- debian/control 2014-03-07 21:06:44 +0000
347+++ debian/control 2014-05-06 21:50:22 +0000
348@@ -3,29 +3,50 @@
349 Maintainer: Ubuntu App Cats <ubuntu-touch-coreapps@lists.launchpad.net>
350 Build-Depends: cmake,
351 debhelper (>= 9),
352- python,
353-Standards-Version: 3.9.4
354+ python3-all,
355+ gettext,
356+ qtbase5-dev,
357+ qtdeclarative5-dev,
358+ qt5-default,
359+Standards-Version: 3.9.5
360 Section: misc
361 Homepage: https://launchpad.net/ubuntu-terminal-app
362 Vcs-Bzr: https://code.launchpad.net/~ubuntu-terminal-dev/ubuntu-terminal-app/trunk
363
364 Package: ubuntu-terminal-app
365 Section: misc
366-Architecture: all
367-Depends: qmlscene,
368+Architecture: any
369+Depends: ${misc:Depends},
370+ ${shlibs:Depends},
371 qtdeclarative5-konsole-qml-plugin (>= 0.1.1),
372 qtdeclarative5-localstorage-plugin,
373 qtdeclarative5-qtquick2-plugin,
374- qtdeclarative5-ubuntu-ui-toolkit-plugin | qt-components-ubuntu,
375- ${misc:Depends},
376+ qtdeclarative5-ubuntu-ui-toolkit-plugin,
377 Description: Terminal application
378 Core Terminal application
379
380+Package: qtdeclarative5-konsole-qml-plugin
381+Architecture: any
382+Multi-Arch: same
383+Depends: ${misc:Depends},
384+ ${shlibs:Depends},
385+ ${misc:Pre-Depends},
386+Description: KDE Konsole QML plugin - qml terminal plugin
387+ Konsole is a terminal emulator from KDE. This is a ported
388+ version for the Ubuntu Terminal app and does not require KDE.
389+ .
390+ This package contains the Konsole terminal emulator plugin
391+ for Qt Qml, which offers access to terminal by KTerminal and
392+ KSession elements. KTerminal is used for displaying information
393+ given by KSession.
394+
395 Package: ubuntu-terminal-app-autopilot
396 Architecture: all
397-Depends: libautopilot-qt,
398+Depends: ${misc:Depends},
399+ libautopilot-qt,
400 libqt5test5,
401- ubuntu-terminal-app (= ${source:Version}),
402+ python3-autopilot,
403+ ubuntu-terminal-app (>= ${source:Version}),
404 ubuntu-ui-toolkit-autopilot,
405 Description: Autopilot tests for Terminal Application
406 This package contains the autopilot tests for the Terminal
407
408=== added file 'debian/qtdeclarative5-konsole-qml-plugin.install'
409--- debian/qtdeclarative5-konsole-qml-plugin.install 1970-01-01 00:00:00 +0000
410+++ debian/qtdeclarative5-konsole-qml-plugin.install 2014-05-06 21:50:22 +0000
411@@ -0,0 +1,1 @@
412+usr/lib/*/qt5/qml/org/kde/konsole/
413
414=== renamed file 'click/manifest.json.in' => 'manifest.json'
415--- click/manifest.json.in 2014-04-11 22:59:46 +0000
416+++ manifest.json 2014-05-06 21:50:22 +0000
417@@ -3,15 +3,15 @@
418 "framework": "ubuntu-sdk-14.04-dev1",
419 "architecture": "armhf",
420 "hooks": {
421- "@APP_NAME@": {
422+ "terminal": {
423 "apparmor": "apparmor.json",
424- "desktop": "@DESKTOP_FILE@",
425- "urls": "@URLS_FILE@"
426+ "desktop": "com.ubuntu.terminal.desktop",
427+ "urls": "com.ubuntu.terminal.url-dispatcher"
428 }
429 },
430- "icon": "@ICON@",
431+ "icon": "terminal64.png",
432 "maintainer": "Ubuntu App Cats <ubuntu-touch-coreapps@lists.launchpad.net>",
433- "name": "@PROJECT_NAME@",
434+ "name": "com.ubuntu.terminal",
435 "title": "Terminal",
436 "version": "0.5.@BZR_REVNO@",
437 "x-source": {
438@@ -21,4 +21,4 @@
439 "x-test": {
440 "autopilot": "@AUTOPILOT_DIR@"
441 }
442-}
443+}
444\ No newline at end of file
445
446=== removed file 'plugins.json'
447--- plugins.json 2013-10-11 14:30:09 +0000
448+++ plugins.json 1970-01-01 00:00:00 +0000
449@@ -1,6 +0,0 @@
450-[
451-{
452- "package": "qtdeclarative5-konsole-qml-plugin",
453- "ppa": "ppa:ubuntu-touch-coreapps-drivers/daily"
454-}
455-]
456
457=== added directory 'src'
458=== added file 'src/CMakeLists.txt'
459--- src/CMakeLists.txt 1970-01-01 00:00:00 +0000
460+++ src/CMakeLists.txt 2014-05-06 21:50:22 +0000
461@@ -0,0 +1,2 @@
462+add_subdirectory(plugin)
463+add_subdirectory(app)
464
465=== added directory 'src/app'
466=== added file 'src/app/CMakeLists.txt'
467--- src/app/CMakeLists.txt 1970-01-01 00:00:00 +0000
468+++ src/app/CMakeLists.txt 2014-05-06 21:50:22 +0000
469@@ -0,0 +1,24 @@
470+file(GLOB_RECURSE QML_SRCS *.qml *.js)
471+
472+set(terminal_SRCS
473+ main.cpp
474+ ${QML_SRCS}
475+)
476+
477+add_executable(terminal ${terminal_SRCS})
478+
479+qt5_use_modules(terminal Gui Qml Quick)
480+
481+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
482+add_custom_target(terminal-qmlfiles ALL
483+ COMMAND cp -r ${CMAKE_CURRENT_SOURCE_DIR}/qml ${CMAKE_CURRENT_BINARY_DIR}
484+ DEPENDS ${QMLFILES}
485+)
486+endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
487+
488+install(DIRECTORY qml DESTINATION ${DATA_DIR})
489+if(CLICK_MODE)
490+ install(TARGETS terminal DESTINATION ${BIN_DIR})
491+else()
492+ install(TARGETS terminal RUNTIME DESTINATION bin)
493+endif()
494
495=== added file 'src/app/main.cpp'
496--- src/app/main.cpp 1970-01-01 00:00:00 +0000
497+++ src/app/main.cpp 2014-05-06 21:50:22 +0000
498@@ -0,0 +1,120 @@
499+/*
500+ * Copyright: 2013 - 2014 Canonical, Ltd
501+ *
502+ * This file is part of ubuntu-terminal-app
503+ *
504+ * ubuntu-terminal-app is free software: you can redistribute it and/or modify
505+ * it under the terms of the GNU General Public License as published by
506+ * the Free Software Foundation, either version 3 of the License, or
507+ * (at your option) any later version.
508+ *
509+ * ubuntu-terminal-app is distributed in the hope that it will be useful,
510+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
511+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
512+ * GNU General Public License for more details.
513+ *
514+ * You should have received a copy of the GNU General Public License
515+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
516+ *
517+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
518+ * Riccardo Padovani <rpadovani@ubuntu.com>
519+ * David Planella <david.planella@ubuntu.com>
520+ */
521+
522+#include <QtGui/QGuiApplication>
523+#include <QtQuick/QQuickView>
524+#include <QtQml/QtQml>
525+#include <QLibrary>
526+#include <QDir>
527+
528+#include <QDebug>
529+
530+int main(int argc, char *argv[])
531+{
532+ QGuiApplication a(argc, argv);
533+ QQuickView view;
534+ view.setResizeMode(QQuickView::SizeRootObjectToView);
535+
536+ // Set up import paths
537+ QStringList importPathList = view.engine()->importPathList();
538+ // Prepend the location of the plugin in the build dir,
539+ // so that Qt Creator finds it there, thus overriding the one installed
540+ // in the sistem if there is one
541+ importPathList.prepend(QCoreApplication::applicationDirPath() + "/../plugin/");
542+
543+ QStringList args = a.arguments();
544+ if (args.contains("-h") || args.contains("--help")) {
545+ qDebug() << "usage: " + args.at(0) + " [-p|--phone] [-t|--tablet] [-h|--help] [-I <path>]";
546+ qDebug() << " -p|--phone If running on Desktop, start in a phone sized window.";
547+ qDebug() << " -t|--tablet If running on Desktop, start in a tablet sized window.";
548+ qDebug() << " -h|--help Print this help.";
549+ qDebug() << " -I <path> Give a path for an additional QML import directory. May be used multiple times.";
550+ qDebug() << " -q <qmlfile> Give an alternative location for the main qml file.";
551+ return 0;
552+ }
553+
554+ QString qmlfile;
555+ for (int i = 0; i < args.count(); i++) {
556+ if (args.at(i) == "-I" && args.count() > i + 1) {
557+ QString addedPath = args.at(i+1);
558+ if (addedPath.startsWith('.')) {
559+ addedPath = addedPath.right(addedPath.length() - 1);
560+ addedPath.prepend(QDir::currentPath());
561+ }
562+ importPathList.append(addedPath);
563+ } else if (args.at(i) == "-q" && args.count() > i + 1) {
564+ qmlfile = args.at(i+1);
565+ }
566+ }
567+
568+ if (args.contains(QLatin1String("-testability")) || getenv("QT_LOAD_TESTABILITY")) {
569+ QLibrary testLib(QLatin1String("qttestability"));
570+ if (testLib.load()) {
571+ typedef void (*TasInitialize)(void);
572+ TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
573+ if (initFunction) {
574+ initFunction();
575+ } else {
576+ qCritical("Library qttestability resolve failed!");
577+ }
578+ } else {
579+ qCritical("Library qttestability load failed!");
580+ }
581+ }
582+
583+ view.engine()->rootContext()->setContextProperty("tablet", QVariant(false));
584+ view.engine()->rootContext()->setContextProperty("phone", QVariant(false));
585+ if (args.contains("-t") || args.contains("--tablet")) {
586+ qDebug() << "running in tablet mode";
587+ view.engine()->rootContext()->setContextProperty("tablet", QVariant(true));
588+ } else if (args.contains("-p") || args.contains("--phone")){
589+ qDebug() << "running in phone mode";
590+ view.engine()->rootContext()->setContextProperty("phone", QVariant(true));
591+ } else if (qgetenv("QT_QPA_PLATFORM") != "ubuntumirclient") {
592+ // Default to tablet size on X11
593+ view.engine()->rootContext()->setContextProperty("tablet", QVariant(true));
594+ }
595+
596+ view.engine()->setImportPathList(importPathList);
597+
598+ // load the qml file
599+ if (qmlfile.isEmpty()) {
600+ QStringList paths = QStandardPaths::standardLocations(QStandardPaths::DataLocation);
601+ paths.prepend(QDir::currentPath());
602+ paths.prepend(QCoreApplication::applicationDirPath());
603+
604+ foreach (const QString &path, paths) {
605+ QFileInfo fi(path + "/qml/ubuntu-terminal-app.qml");
606+ qDebug() << "Trying to load QML from:" << path + "/qml/ubuntu-terminal-app.qml";
607+ if (fi.exists()) {
608+ qmlfile = path + "/qml/ubuntu-terminal-app.qml";
609+ break;
610+ }
611+ }
612+ }
613+ qDebug() << "using main qml file from:" << qmlfile;
614+ view.setSource(QUrl::fromLocalFile(qmlfile));
615+ view.show();
616+
617+ return a.exec();
618+}
619
620=== added directory 'src/app/qml'
621=== renamed file 'Configs.qml' => 'src/app/qml/Configs.qml'
622=== renamed file 'Terminal.qml' => 'src/app/qml/Terminal.qml'
623=== renamed file 'avatar@8.png' => 'src/app/qml/avatar@8.png'
624=== renamed directory 'config' => 'src/app/qml/config'
625=== renamed directory 'extraPanel' => 'src/app/qml/extraPanel'
626=== renamed file 'settings.png' => 'src/app/qml/settings.png'
627=== renamed file 'terminal.qmlproject' => 'src/app/qml/terminal.qmlproject'
628=== renamed file 'ubuntu-terminal-app.qml' => 'src/app/qml/ubuntu-terminal-app.qml'
629=== added directory 'src/plugin'
630=== added file 'src/plugin/CMakeLists.txt'
631--- src/plugin/CMakeLists.txt 1970-01-01 00:00:00 +0000
632+++ src/plugin/CMakeLists.txt 2014-05-06 21:50:22 +0000
633@@ -0,0 +1,7 @@
634+include(FindPkgConfig)
635+find_package(Qt5Core)
636+find_package(Qt5Qml)
637+find_package(Qt5Quick)
638+find_package(Qt5Widgets)
639+
640+add_subdirectory(konsole)
641
642=== added directory 'src/plugin/konsole'
643=== added file 'src/plugin/konsole/BlockArray.cpp'
644--- src/plugin/konsole/BlockArray.cpp 1970-01-01 00:00:00 +0000
645+++ src/plugin/konsole/BlockArray.cpp 2014-05-06 21:50:22 +0000
646@@ -0,0 +1,377 @@
647+/*
648+ This file is part of Konsole, an X terminal.
649+ Copyright (C) 2000 by Stephan Kulow <coolo@kde.org>
650+
651+ Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
652+
653+ This program is free software; you can redistribute it and/or modify
654+ it under the terms of the GNU General Public License as published by
655+ the Free Software Foundation; either version 2 of the License, or
656+ (at your option) any later version.
657+
658+ This program is distributed in the hope that it will be useful,
659+ but WITHOUT ANY WARRANTY; without even the implied warranty of
660+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
661+ GNU General Public License for more details.
662+
663+ You should have received a copy of the GNU General Public License
664+ along with this program; if not, write to the Free Software
665+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
666+ 02110-1301 USA.
667+
668+*/
669+
670+// Own
671+#include "BlockArray.h"
672+
673+#include <QtCore>
674+
675+// System
676+#include <assert.h>
677+#include <sys/mman.h>
678+#include <sys/param.h>
679+#include <unistd.h>
680+#include <stdio.h>
681+
682+
683+static int blocksize = 0;
684+
685+BlockArray::BlockArray()
686+ : size(0),
687+ current(size_t(-1)),
688+ index(size_t(-1)),
689+ lastmap(0),
690+ lastmap_index(size_t(-1)),
691+ lastblock(0), ion(-1),
692+ length(0)
693+{
694+ // lastmap_index = index = current = size_t(-1);
695+ if (blocksize == 0) {
696+ blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();
697+ }
698+
699+}
700+
701+BlockArray::~BlockArray()
702+{
703+ setHistorySize(0);
704+ assert(!lastblock);
705+}
706+
707+size_t BlockArray::append(Block * block)
708+{
709+ if (!size) {
710+ return size_t(-1);
711+ }
712+
713+ ++current;
714+ if (current >= size) {
715+ current = 0;
716+ }
717+
718+ int rc;
719+ rc = lseek(ion, current * blocksize, SEEK_SET);
720+ if (rc < 0) {
721+ perror("HistoryBuffer::add.seek");
722+ setHistorySize(0);
723+ return size_t(-1);
724+ }
725+ rc = write(ion, block, blocksize);
726+ if (rc < 0) {
727+ perror("HistoryBuffer::add.write");
728+ setHistorySize(0);
729+ return size_t(-1);
730+ }
731+
732+ length++;
733+ if (length > size) {
734+ length = size;
735+ }
736+
737+ ++index;
738+
739+ delete block;
740+ return current;
741+}
742+
743+size_t BlockArray::newBlock()
744+{
745+ if (!size) {
746+ return size_t(-1);
747+ }
748+ append(lastblock);
749+
750+ lastblock = new Block();
751+ return index + 1;
752+}
753+
754+Block * BlockArray::lastBlock() const
755+{
756+ return lastblock;
757+}
758+
759+bool BlockArray::has(size_t i) const
760+{
761+ if (i == index + 1) {
762+ return true;
763+ }
764+
765+ if (i > index) {
766+ return false;
767+ }
768+ if (index - i >= length) {
769+ return false;
770+ }
771+ return true;
772+}
773+
774+const Block * BlockArray::at(size_t i)
775+{
776+ if (i == index + 1) {
777+ return lastblock;
778+ }
779+
780+ if (i == lastmap_index) {
781+ return lastmap;
782+ }
783+
784+ if (i > index) {
785+ qDebug() << "BlockArray::at() i > index\n";
786+ return 0;
787+ }
788+
789+// if (index - i >= length) {
790+// kDebug(1211) << "BlockArray::at() index - i >= length\n";
791+// return 0;
792+// }
793+
794+ size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
795+
796+ assert(j < size);
797+ unmap();
798+
799+ Block * block = (Block *)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
800+
801+ if (block == (Block *)-1) {
802+ perror("mmap");
803+ return 0;
804+ }
805+
806+ lastmap = block;
807+ lastmap_index = i;
808+
809+ return block;
810+}
811+
812+void BlockArray::unmap()
813+{
814+ if (lastmap) {
815+ int res = munmap((char *)lastmap, blocksize);
816+ if (res < 0) {
817+ perror("munmap");
818+ }
819+ }
820+ lastmap = 0;
821+ lastmap_index = size_t(-1);
822+}
823+
824+bool BlockArray::setSize(size_t newsize)
825+{
826+ return setHistorySize(newsize * 1024 / blocksize);
827+}
828+
829+bool BlockArray::setHistorySize(size_t newsize)
830+{
831+// kDebug(1211) << "setHistorySize " << size << " " << newsize;
832+
833+ if (size == newsize) {
834+ return false;
835+ }
836+
837+ unmap();
838+
839+ if (!newsize) {
840+ delete lastblock;
841+ lastblock = 0;
842+ if (ion >= 0) {
843+ close(ion);
844+ }
845+ ion = -1;
846+ current = size_t(-1);
847+ return true;
848+ }
849+
850+ if (!size) {
851+ FILE * tmp = tmpfile();
852+ if (!tmp) {
853+ perror("konsole: cannot open temp file.\n");
854+ } else {
855+ ion = dup(fileno(tmp));
856+ if (ion<0) {
857+ perror("konsole: cannot dup temp file.\n");
858+ fclose(tmp);
859+ }
860+ }
861+ if (ion < 0) {
862+ return false;
863+ }
864+
865+ assert(!lastblock);
866+
867+ lastblock = new Block();
868+ size = newsize;
869+ return false;
870+ }
871+
872+ if (newsize > size) {
873+ increaseBuffer();
874+ size = newsize;
875+ return false;
876+ } else {
877+ decreaseBuffer(newsize);
878+ ftruncate(ion, length*blocksize);
879+ size = newsize;
880+
881+ return true;
882+ }
883+}
884+
885+void moveBlock(FILE * fion, int cursor, int newpos, char * buffer2)
886+{
887+ int res = fseek(fion, cursor * blocksize, SEEK_SET);
888+ if (res) {
889+ perror("fseek");
890+ }
891+ res = fread(buffer2, blocksize, 1, fion);
892+ if (res != 1) {
893+ perror("fread");
894+ }
895+
896+ res = fseek(fion, newpos * blocksize, SEEK_SET);
897+ if (res) {
898+ perror("fseek");
899+ }
900+ res = fwrite(buffer2, blocksize, 1, fion);
901+ if (res != 1) {
902+ perror("fwrite");
903+ }
904+ // printf("moving block %d to %d\n", cursor, newpos);
905+}
906+
907+void BlockArray::decreaseBuffer(size_t newsize)
908+{
909+ if (index < newsize) { // still fits in whole
910+ return;
911+ }
912+
913+ int offset = (current - (newsize - 1) + size) % size;
914+
915+ if (!offset) {
916+ return;
917+ }
918+
919+ // The Block constructor could do somthing in future...
920+ char * buffer1 = new char[blocksize];
921+
922+ FILE * fion = fdopen(dup(ion), "w+b");
923+ if (!fion) {
924+ delete [] buffer1;
925+ perror("fdopen/dup");
926+ return;
927+ }
928+
929+ int firstblock;
930+ if (current <= newsize) {
931+ firstblock = current + 1;
932+ } else {
933+ firstblock = 0;
934+ }
935+
936+ size_t oldpos;
937+ for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
938+ oldpos = (size + cursor + offset) % size;
939+ moveBlock(fion, oldpos, cursor, buffer1);
940+ if (oldpos < newsize) {
941+ cursor = oldpos;
942+ } else {
943+ cursor++;
944+ }
945+ }
946+
947+ current = newsize - 1;
948+ length = newsize;
949+
950+ delete [] buffer1;
951+
952+ fclose(fion);
953+
954+}
955+
956+void BlockArray::increaseBuffer()
957+{
958+ if (index < size) { // not even wrapped once
959+ return;
960+ }
961+
962+ int offset = (current + size + 1) % size;
963+ if (!offset) { // no moving needed
964+ return;
965+ }
966+
967+ // The Block constructor could do somthing in future...
968+ char * buffer1 = new char[blocksize];
969+ char * buffer2 = new char[blocksize];
970+
971+ int runs = 1;
972+ int bpr = size; // blocks per run
973+
974+ if (size % offset == 0) {
975+ bpr = size / offset;
976+ runs = offset;
977+ }
978+
979+ FILE * fion = fdopen(dup(ion), "w+b");
980+ if (!fion) {
981+ perror("fdopen/dup");
982+ delete [] buffer1;
983+ delete [] buffer2;
984+ return;
985+ }
986+
987+ int res;
988+ for (int i = 0; i < runs; i++) {
989+ // free one block in chain
990+ int firstblock = (offset + i) % size;
991+ res = fseek(fion, firstblock * blocksize, SEEK_SET);
992+ if (res) {
993+ perror("fseek");
994+ }
995+ res = fread(buffer1, blocksize, 1, fion);
996+ if (res != 1) {
997+ perror("fread");
998+ }
999+ int newpos = 0;
1000+ for (int j = 1, cursor=firstblock; j < bpr; j++) {
1001+ cursor = (cursor + offset) % size;
1002+ newpos = (cursor - offset + size) % size;
1003+ moveBlock(fion, cursor, newpos, buffer2);
1004+ }
1005+ res = fseek(fion, i * blocksize, SEEK_SET);
1006+ if (res) {
1007+ perror("fseek");
1008+ }
1009+ res = fwrite(buffer1, blocksize, 1, fion);
1010+ if (res != 1) {
1011+ perror("fwrite");
1012+ }
1013+ }
1014+ current = size - 1;
1015+ length = size;
1016+
1017+ delete [] buffer1;
1018+ delete [] buffer2;
1019+
1020+ fclose(fion);
1021+
1022+}
1023+
1024
1025=== added file 'src/plugin/konsole/BlockArray.h'
1026--- src/plugin/konsole/BlockArray.h 1970-01-01 00:00:00 +0000
1027+++ src/plugin/konsole/BlockArray.h 2014-05-06 21:50:22 +0000
1028@@ -0,0 +1,126 @@
1029+/*
1030+ This file is part of Konsole, an X terminal.
1031+ Copyright (C) 2000 by Stephan Kulow <coolo@kde.org>
1032+
1033+ Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
1034+
1035+ This program is free software; you can redistribute it and/or modify
1036+ it under the terms of the GNU General Public License as published by
1037+ the Free Software Foundation; either version 2 of the License, or
1038+ (at your option) any later version.
1039+
1040+ This program is distributed in the hope that it will be useful,
1041+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1042+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1043+ GNU General Public License for more details.
1044+
1045+ You should have received a copy of the GNU General Public License
1046+ along with this program; if not, write to the Free Software
1047+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1048+ 02110-1301 USA.
1049+*/
1050+
1051+#ifndef BLOCKARRAY_H
1052+#define BLOCKARRAY_H
1053+
1054+#include <unistd.h>
1055+
1056+//#error Do not use in KDE 2.1
1057+
1058+#define BlockSize (1 << 12)
1059+#define ENTRIES ((BlockSize - sizeof(size_t) ) / sizeof(unsigned char))
1060+
1061+struct Block {
1062+ Block() {
1063+ size = 0;
1064+ }
1065+ unsigned char data[ENTRIES];
1066+ size_t size;
1067+};
1068+
1069+// ///////////////////////////////////////////////////////
1070+
1071+class BlockArray {
1072+public:
1073+ /**
1074+ * Creates a history file for holding
1075+ * maximal size blocks. If more blocks
1076+ * are requested, then it drops earlier
1077+ * added ones.
1078+ */
1079+ BlockArray();
1080+
1081+ /// destructor
1082+ ~BlockArray();
1083+
1084+ /**
1085+ * adds the Block at the end of history.
1086+ * This may drop other blocks.
1087+ *
1088+ * The ownership on the block is transfered.
1089+ * An unique index number is returned for accessing
1090+ * it later (if not yet dropped then)
1091+ *
1092+ * Note, that the block may be dropped completely
1093+ * if history is turned off.
1094+ */
1095+ size_t append(Block * block);
1096+
1097+ /**
1098+ * gets the block at the index. Function may return
1099+ * 0 if the block isn't available any more.
1100+ *
1101+ * The returned block is strictly readonly as only
1102+ * maped in memory - and will be invalid on the next
1103+ * operation on this class.
1104+ */
1105+ const Block * at(size_t index);
1106+
1107+ /**
1108+ * reorders blocks as needed. If newsize is null,
1109+ * the history is emptied completely. The indices
1110+ * returned on append won't change their semantic,
1111+ * but they may not be valid after this call.
1112+ */
1113+ bool setHistorySize(size_t newsize);
1114+
1115+ size_t newBlock();
1116+
1117+ Block * lastBlock() const;
1118+
1119+ /**
1120+ * Convenient function to set the size in KBytes
1121+ * instead of blocks
1122+ */
1123+ bool setSize(size_t newsize);
1124+
1125+ size_t len() const {
1126+ return length;
1127+ }
1128+
1129+ bool has(size_t index) const;
1130+
1131+ size_t getCurrent() const {
1132+ return current;
1133+ }
1134+
1135+private:
1136+ void unmap();
1137+ void increaseBuffer();
1138+ void decreaseBuffer(size_t newsize);
1139+
1140+ size_t size;
1141+ // current always shows to the last inserted block
1142+ size_t current;
1143+ size_t index;
1144+
1145+ Block * lastmap;
1146+ size_t lastmap_index;
1147+ Block * lastblock;
1148+
1149+ int ion;
1150+ size_t length;
1151+
1152+};
1153+
1154+#endif
1155
1156=== added file 'src/plugin/konsole/CMakeLists.txt'
1157--- src/plugin/konsole/CMakeLists.txt 1970-01-01 00:00:00 +0000
1158+++ src/plugin/konsole/CMakeLists.txt 2014-05-06 21:50:22 +0000
1159@@ -0,0 +1,93 @@
1160+include_directories(
1161+ ${CMAKE_CURRENT_SOURCE_DIR}
1162+)
1163+
1164+set(PLUGIN_DIR org/kde/konsole)
1165+add_definitions(-DHAVE_POSIX_OPENPT -DHAVE_SYS_TIME_H -DHAVE_UPDWTMPX)
1166+add_definitions(-DQ_WS_UBUNTU)
1167+
1168+set(konsole_SRCS
1169+ BlockArray.cpp
1170+ BlockArray.h
1171+ CharacterColor.h
1172+ Character.h
1173+ ColorScheme.cpp
1174+ ColorScheme.h
1175+ ColorTables.h
1176+ DefaultTranslatorText.h
1177+ Emulation.cpp
1178+ Emulation.h
1179+ ExtendedDefaultTranslator.h
1180+ Filter.cpp
1181+ Filter.h
1182+ History.cpp
1183+ History.h
1184+ KeyboardTranslator.cpp
1185+ KeyboardTranslator.h
1186+ konsole_wcwidth.cpp
1187+ konsole_wcwidth.h
1188+ kprocess.cpp
1189+ kprocess.h
1190+ kpty.cpp
1191+ kptydevice.cpp
1192+ kptydevice.h
1193+ kpty.h
1194+ kpty_p.h
1195+ kptyprocess.cpp
1196+ kptyprocess.h
1197+ ksession.cpp
1198+ ksession.h
1199+ LineFont.h
1200+ plugin.cpp
1201+ plugin.h
1202+ Pty.cpp
1203+ Pty.h
1204+ Screen.cpp
1205+ Screen.h
1206+ ScreenWindow.cpp
1207+ ScreenWindow.h
1208+ Session.cpp
1209+ Session.h
1210+ ShellCommand.cpp
1211+ ShellCommand.h
1212+ TerminalCharacterDecoder.cpp
1213+ TerminalCharacterDecoder.h
1214+ TerminalDisplay.cpp
1215+ TerminalDisplay.h
1216+ tools.cpp
1217+ tools.h
1218+ Vt102Emulation.cpp
1219+ Vt102Emulation.h
1220+)
1221+
1222+add_library(kdekonsole MODULE
1223+ ${konsole_SRCS}
1224+)
1225+
1226+qt5_use_modules(kdekonsole Gui Qml Quick Widgets)
1227+
1228+# Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator
1229+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
1230+ add_custom_target(konsole-qmldir ALL
1231+ COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
1232+ DEPENDS ${QMLFILES}
1233+ )
1234+ add_custom_target(konsole-layouts-schemes ALL
1235+ COMMAND cp -a ${CMAKE_CURRENT_SOURCE_DIR}/assets/color-schemes ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
1236+ COMMAND cp -a ${CMAKE_CURRENT_SOURCE_DIR}/assets/kb-layouts ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
1237+ DEPENDS ${QMLFILES}
1238+ )
1239+ add_custom_command(TARGET kdekonsole POST_BUILD
1240+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
1241+ COMMENT "Creating plugin directory layout in the build dir"
1242+ COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:kdekonsole> ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
1243+ COMMENT "Copying to output directory"
1244+ )
1245+endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
1246+
1247+
1248+install(TARGETS kdekonsole DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
1249+install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
1250+install(DIRECTORY assets/color-schemes DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
1251+install(DIRECTORY assets/kb-layouts DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
1252+
1253
1254=== added file 'src/plugin/konsole/Character.h'
1255--- src/plugin/konsole/Character.h 1970-01-01 00:00:00 +0000
1256+++ src/plugin/konsole/Character.h 2014-05-06 21:50:22 +0000
1257@@ -0,0 +1,221 @@
1258+/*
1259+ This file is part of Konsole, KDE's terminal.
1260+
1261+ Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
1262+ Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
1263+
1264+ This program is free software; you can redistribute it and/or modify
1265+ it under the terms of the GNU General Public License as published by
1266+ the Free Software Foundation; either version 2 of the License, or
1267+ (at your option) any later version.
1268+
1269+ This program is distributed in the hope that it will be useful,
1270+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1271+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1272+ GNU General Public License for more details.
1273+
1274+ You should have received a copy of the GNU General Public License
1275+ along with this program; if not, write to the Free Software
1276+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1277+ 02110-1301 USA.
1278+*/
1279+
1280+#ifndef CHARACTER_H
1281+#define CHARACTER_H
1282+
1283+// Qt
1284+#include <QtCore/QHash>
1285+
1286+// Local
1287+#include "CharacterColor.h"
1288+
1289+typedef unsigned char LineProperty;
1290+
1291+static const int LINE_DEFAULT = 0;
1292+static const int LINE_WRAPPED = (1 << 0);
1293+static const int LINE_DOUBLEWIDTH = (1 << 1);
1294+static const int LINE_DOUBLEHEIGHT = (1 << 2);
1295+
1296+#define DEFAULT_RENDITION 0
1297+#define RE_BOLD (1 << 0)
1298+#define RE_BLINK (1 << 1)
1299+#define RE_UNDERLINE (1 << 2)
1300+#define RE_REVERSE (1 << 3) // Screen only
1301+#define RE_INTENSIVE (1 << 3) // Widget only
1302+#define RE_CURSOR (1 << 4)
1303+#define RE_EXTENDED_CHAR (1 << 5)
1304+
1305+/**
1306+ * A single character in the terminal which consists of a unicode character
1307+ * value, foreground and background colors and a set of rendition attributes
1308+ * which specify how it should be drawn.
1309+ */
1310+class Character
1311+{
1312+public:
1313+ /**
1314+ * Constructs a new character.
1315+ *
1316+ * @param _c The unicode character value of this character.
1317+ * @param _f The foreground color used to draw the character.
1318+ * @param _b The color used to draw the character's background.
1319+ * @param _r A set of rendition flags which specify how this character is to be drawn.
1320+ */
1321+ inline Character(quint16 _c = ' ',
1322+ CharacterColor _f = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR),
1323+ CharacterColor _b = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR),
1324+ quint8 _r = DEFAULT_RENDITION)
1325+ : character(_c), rendition(_r), foregroundColor(_f), backgroundColor(_b) {}
1326+
1327+ union
1328+ {
1329+ /** The unicode character value for this character. */
1330+ quint16 character;
1331+ /**
1332+ * Experimental addition which allows a single Character instance to contain more than
1333+ * one unicode character.
1334+ *
1335+ * charSequence is a hash code which can be used to look up the unicode
1336+ * character sequence in the ExtendedCharTable used to create the sequence.
1337+ */
1338+ quint16 charSequence;
1339+ };
1340+
1341+ /** A combination of RENDITION flags which specify options for drawing the character. */
1342+ quint8 rendition;
1343+
1344+ /** The foreground color used to draw this character. */
1345+ CharacterColor foregroundColor;
1346+ /** The color used to draw this character's background. */
1347+ CharacterColor backgroundColor;
1348+
1349+ /**
1350+ * Returns true if this character has a transparent background when
1351+ * it is drawn with the specified @p palette.
1352+ */
1353+ bool isTransparent(const ColorEntry* palette) const;
1354+ /**
1355+ * Returns true if this character should always be drawn in bold when
1356+ * it is drawn with the specified @p palette, independent of whether
1357+ * or not the character has the RE_BOLD rendition flag.
1358+ */
1359+ ColorEntry::FontWeight fontWeight(const ColorEntry* base) const;
1360+
1361+ /**
1362+ * returns true if the format (color, rendition flag) of the compared characters is equal
1363+ */
1364+ bool equalsFormat(const Character &other) const;
1365+
1366+ /**
1367+ * Compares two characters and returns true if they have the same unicode character value,
1368+ * rendition and colors.
1369+ */
1370+ friend bool operator == (const Character& a, const Character& b);
1371+ /**
1372+ * Compares two characters and returns true if they have different unicode character values,
1373+ * renditions or colors.
1374+ */
1375+ friend bool operator != (const Character& a, const Character& b);
1376+};
1377+
1378+inline bool operator == (const Character& a, const Character& b)
1379+{
1380+ return a.character == b.character &&
1381+ a.rendition == b.rendition &&
1382+ a.foregroundColor == b.foregroundColor &&
1383+ a.backgroundColor == b.backgroundColor;
1384+}
1385+
1386+inline bool operator != (const Character& a, const Character& b)
1387+{
1388+ return a.character != b.character ||
1389+ a.rendition != b.rendition ||
1390+ a.foregroundColor != b.foregroundColor ||
1391+ a.backgroundColor != b.backgroundColor;
1392+}
1393+
1394+inline bool Character::isTransparent(const ColorEntry* base) const
1395+{
1396+ return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) &&
1397+ base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].transparent)
1398+ || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) &&
1399+ base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].transparent);
1400+}
1401+
1402+inline bool Character::equalsFormat(const Character& other) const
1403+{
1404+ return
1405+ backgroundColor==other.backgroundColor &&
1406+ foregroundColor==other.foregroundColor &&
1407+ rendition==other.rendition;
1408+}
1409+
1410+inline ColorEntry::FontWeight Character::fontWeight(const ColorEntry* base) const
1411+{
1412+ if (backgroundColor._colorSpace == COLOR_SPACE_DEFAULT)
1413+ return base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].fontWeight;
1414+ else if (backgroundColor._colorSpace == COLOR_SPACE_SYSTEM)
1415+ return base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].fontWeight;
1416+ else
1417+ return ColorEntry::UseCurrentFormat;
1418+}
1419+
1420+extern unsigned short vt100_graphics[32];
1421+
1422+
1423+/**
1424+ * A table which stores sequences of unicode characters, referenced
1425+ * by hash keys. The hash key itself is the same size as a unicode
1426+ * character ( ushort ) so that it can occupy the same space in
1427+ * a structure.
1428+ */
1429+class ExtendedCharTable
1430+{
1431+public:
1432+ /** Constructs a new character table. */
1433+ ExtendedCharTable();
1434+ ~ExtendedCharTable();
1435+
1436+ /**
1437+ * Adds a sequences of unicode characters to the table and returns
1438+ * a hash code which can be used later to look up the sequence
1439+ * using lookupExtendedChar()
1440+ *
1441+ * If the same sequence already exists in the table, the hash
1442+ * of the existing sequence will be returned.
1443+ *
1444+ * @param unicodePoints An array of unicode character points
1445+ * @param length Length of @p unicodePoints
1446+ */
1447+ ushort createExtendedChar(ushort* unicodePoints , ushort length);
1448+ /**
1449+ * Looks up and returns a pointer to a sequence of unicode characters
1450+ * which was added to the table using createExtendedChar().
1451+ *
1452+ * @param hash The hash key returned by createExtendedChar()
1453+ * @param length This variable is set to the length of the
1454+ * character sequence.
1455+ *
1456+ * @return A unicode character sequence of size @p length.
1457+ */
1458+ ushort* lookupExtendedChar(ushort hash , ushort& length) const;
1459+
1460+ /** The global ExtendedCharTable instance. */
1461+ static ExtendedCharTable instance;
1462+private:
1463+ // calculates the hash key of a sequence of unicode points of size 'length'
1464+ ushort extendedCharHash(ushort* unicodePoints , ushort length) const;
1465+ // tests whether the entry in the table specified by 'hash' matches the
1466+ // character sequence 'unicodePoints' of size 'length'
1467+ bool extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const;
1468+ // internal, maps hash keys to character sequence buffers. The first ushort
1469+ // in each value is the length of the buffer, followed by the ushorts in the buffer
1470+ // themselves.
1471+ QHash<ushort,ushort*> extendedCharTable;
1472+};
1473+
1474+
1475+Q_DECLARE_TYPEINFO(Character, Q_MOVABLE_TYPE);
1476+
1477+#endif // CHARACTER_H
1478+
1479
1480=== added file 'src/plugin/konsole/CharacterColor.h'
1481--- src/plugin/konsole/CharacterColor.h 1970-01-01 00:00:00 +0000
1482+++ src/plugin/konsole/CharacterColor.h 2014-05-06 21:50:22 +0000
1483@@ -0,0 +1,294 @@
1484+/*
1485+ This file is part of Konsole, KDE's terminal.
1486+
1487+ Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
1488+ Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
1489+
1490+ This program is free software; you can redistribute it and/or modify
1491+ it under the terms of the GNU General Public License as published by
1492+ the Free Software Foundation; either version 2 of the License, or
1493+ (at your option) any later version.
1494+
1495+ This program is distributed in the hope that it will be useful,
1496+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1497+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1498+ GNU General Public License for more details.
1499+
1500+ You should have received a copy of the GNU General Public License
1501+ along with this program; if not, write to the Free Software
1502+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1503+ 02110-1301 USA.
1504+*/
1505+
1506+#ifndef CHARACTERCOLOR_H
1507+#define CHARACTERCOLOR_H
1508+
1509+// Qt
1510+#include <QtGui/QColor>
1511+
1512+//#include <kdemacros.h>
1513+#define KDE_NO_EXPORT
1514+
1515+/**
1516+ * An entry in a terminal display's color palette.
1517+ *
1518+ * A color palette is an array of 16 ColorEntry instances which map
1519+ * system color indexes (from 0 to 15) into actual colors.
1520+ *
1521+ * Each entry can be set as bold, in which case any text
1522+ * drawn using the color should be drawn in bold.
1523+ *
1524+ * Each entry can also be transparent, in which case the terminal
1525+ * display should avoid drawing the background for any characters
1526+ * using the entry as a background.
1527+ */
1528+class ColorEntry
1529+{
1530+public:
1531+ /** Specifies the weight to use when drawing text with this color. */
1532+ enum FontWeight
1533+ {
1534+ /** Always draw text in this color with a bold weight. */
1535+ Bold,
1536+ /** Always draw text in this color with a normal weight. */
1537+ Normal,
1538+ /**
1539+ * Use the current font weight set by the terminal application.
1540+ * This is the default behavior.
1541+ */
1542+ UseCurrentFormat
1543+ };
1544+
1545+ /**
1546+ * Constructs a new color palette entry.
1547+ *
1548+ * @param c The color value for this entry.
1549+ * @param tr Specifies that the color should be transparent when used as a background color.
1550+ * @param weight Specifies the font weight to use when drawing text with this color.
1551+ */
1552+ ColorEntry(QColor c, bool tr, FontWeight weight = UseCurrentFormat)
1553+ : color(c), transparent(tr), fontWeight(weight) {}
1554+
1555+ /**
1556+ * Constructs a new color palette entry with an undefined color, and
1557+ * with the transparent and bold flags set to false.
1558+ */
1559+ ColorEntry() : transparent(false), fontWeight(UseCurrentFormat) {}
1560+
1561+ /**
1562+ * Sets the color, transparency and boldness of this color to those of @p rhs.
1563+ */
1564+ void operator=(const ColorEntry& rhs)
1565+ {
1566+ color = rhs.color;
1567+ transparent = rhs.transparent;
1568+ fontWeight = rhs.fontWeight;
1569+ }
1570+
1571+ /** The color value of this entry for display. */
1572+ QColor color;
1573+
1574+ /**
1575+ * If true character backgrounds using this color should be transparent.
1576+ * This is not applicable when the color is used to render text.
1577+ */
1578+ bool transparent;
1579+ /**
1580+ * Specifies the font weight to use when drawing text with this color.
1581+ * This is not applicable when the color is used to draw a character's background.
1582+ */
1583+ FontWeight fontWeight;
1584+};
1585+
1586+
1587+// Attributed Character Representations ///////////////////////////////
1588+
1589+// Colors
1590+
1591+#define BASE_COLORS (2+8)
1592+#define INTENSITIES 2
1593+#define TABLE_COLORS (INTENSITIES*BASE_COLORS)
1594+
1595+#define DEFAULT_FORE_COLOR 0
1596+#define DEFAULT_BACK_COLOR 1
1597+
1598+//a standard set of colors using black text on a white background.
1599+//defined in TerminalDisplay.cpp
1600+
1601+extern const ColorEntry base_color_table[TABLE_COLORS] KDE_NO_EXPORT;
1602+
1603+/* CharacterColor is a union of the various color spaces.
1604+
1605+ Assignment is as follows:
1606+
1607+ Type - Space - Values
1608+
1609+ 0 - Undefined - u: 0, v:0 w:0
1610+ 1 - Default - u: 0..1 v:intense w:0
1611+ 2 - System - u: 0..7 v:intense w:0
1612+ 3 - Index(256) - u: 16..255 v:0 w:0
1613+ 4 - RGB - u: 0..255 v:0..256 w:0..256
1614+
1615+ Default colour space has two separate colours, namely
1616+ default foreground and default background colour.
1617+*/
1618+
1619+#define COLOR_SPACE_UNDEFINED 0
1620+#define COLOR_SPACE_DEFAULT 1
1621+#define COLOR_SPACE_SYSTEM 2
1622+#define COLOR_SPACE_256 3
1623+#define COLOR_SPACE_RGB 4
1624+
1625+/**
1626+ * Describes the color of a single character in the terminal.
1627+ */
1628+class CharacterColor
1629+{
1630+ friend class Character;
1631+
1632+public:
1633+ /** Constructs a new CharacterColor whoose color and color space are undefined. */
1634+ CharacterColor()
1635+ : _colorSpace(COLOR_SPACE_UNDEFINED),
1636+ _u(0),
1637+ _v(0),
1638+ _w(0)
1639+ {}
1640+
1641+ /**
1642+ * Constructs a new CharacterColor using the specified @p colorSpace and with
1643+ * color value @p co
1644+ *
1645+ * The meaning of @p co depends on the @p colorSpace used.
1646+ *
1647+ * TODO : Document how @p co relates to @p colorSpace
1648+ *
1649+ * TODO : Add documentation about available color spaces.
1650+ */
1651+ CharacterColor(quint8 colorSpace, int co)
1652+ : _colorSpace(colorSpace),
1653+ _u(0),
1654+ _v(0),
1655+ _w(0)
1656+ {
1657+ switch (colorSpace)
1658+ {
1659+ case COLOR_SPACE_DEFAULT:
1660+ _u = co & 1;
1661+ break;
1662+ case COLOR_SPACE_SYSTEM:
1663+ _u = co & 7;
1664+ _v = (co >> 3) & 1;
1665+ break;
1666+ case COLOR_SPACE_256:
1667+ _u = co & 255;
1668+ break;
1669+ case COLOR_SPACE_RGB:
1670+ _u = co >> 16;
1671+ _v = co >> 8;
1672+ _w = co;
1673+ break;
1674+ default:
1675+ _colorSpace = COLOR_SPACE_UNDEFINED;
1676+ }
1677+ }
1678+
1679+ /**
1680+ * Returns true if this character color entry is valid.
1681+ */
1682+ bool isValid()
1683+ {
1684+ return _colorSpace != COLOR_SPACE_UNDEFINED;
1685+ }
1686+
1687+ /**
1688+ * Toggles the value of this color between a normal system color and the corresponding intensive
1689+ * system color.
1690+ *
1691+ * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
1692+ * color spaces.
1693+ */
1694+ void toggleIntensive();
1695+
1696+ /**
1697+ * Returns the color within the specified color @p palette
1698+ *
1699+ * The @p palette is only used if this color is one of the 16 system colors, otherwise
1700+ * it is ignored.
1701+ */
1702+ QColor color(const ColorEntry* palette) const;
1703+
1704+ /**
1705+ * Compares two colors and returns true if they represent the same color value and
1706+ * use the same color space.
1707+ */
1708+ friend bool operator == (const CharacterColor& a, const CharacterColor& b);
1709+ /**
1710+ * Compares two colors and returns true if they represent different color values
1711+ * or use different color spaces.
1712+ */
1713+ friend bool operator != (const CharacterColor& a, const CharacterColor& b);
1714+
1715+private:
1716+ quint8 _colorSpace;
1717+
1718+ // bytes storing the character color
1719+ quint8 _u;
1720+ quint8 _v;
1721+ quint8 _w;
1722+};
1723+
1724+inline bool operator == (const CharacterColor& a, const CharacterColor& b)
1725+{
1726+ return a._colorSpace == b._colorSpace &&
1727+ a._u == b._u &&
1728+ a._v == b._v &&
1729+ a._w == b._w;
1730+}
1731+inline bool operator != (const CharacterColor& a, const CharacterColor& b)
1732+{
1733+ return !operator==(a,b);
1734+}
1735+
1736+inline const QColor color256(quint8 u, const ColorEntry* base)
1737+{
1738+ // 0.. 16: system colors
1739+ if (u < 8) return base[u+2 ].color; u -= 8;
1740+ if (u < 8) return base[u+2+BASE_COLORS].color; u -= 8;
1741+
1742+ // 16..231: 6x6x6 rgb color cube
1743+ if (u < 216) return QColor(((u/36)%6) ? (40*((u/36)%6)+55) : 0,
1744+ ((u/ 6)%6) ? (40*((u/ 6)%6)+55) : 0,
1745+ ((u/ 1)%6) ? (40*((u/ 1)%6)+55) : 0); u -= 216;
1746+
1747+ // 232..255: gray, leaving out black and white
1748+ int gray = u*10+8; return QColor(gray,gray,gray);
1749+}
1750+
1751+inline QColor CharacterColor::color(const ColorEntry* base) const
1752+{
1753+ switch (_colorSpace)
1754+ {
1755+ case COLOR_SPACE_DEFAULT: return base[_u+0+(_v?BASE_COLORS:0)].color;
1756+ case COLOR_SPACE_SYSTEM: return base[_u+2+(_v?BASE_COLORS:0)].color;
1757+ case COLOR_SPACE_256: return color256(_u,base);
1758+ case COLOR_SPACE_RGB: return QColor(_u,_v,_w);
1759+ case COLOR_SPACE_UNDEFINED: return QColor();
1760+ }
1761+
1762+ Q_ASSERT(false); // invalid color space
1763+
1764+ return QColor();
1765+}
1766+
1767+inline void CharacterColor::toggleIntensive()
1768+{
1769+ if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT)
1770+ {
1771+ _v = !_v;
1772+ }
1773+}
1774+
1775+
1776+#endif // CHARACTERCOLOR_H
1777+
1778
1779=== added file 'src/plugin/konsole/ColorScheme.cpp'
1780--- src/plugin/konsole/ColorScheme.cpp 1970-01-01 00:00:00 +0000
1781+++ src/plugin/konsole/ColorScheme.cpp 2014-05-06 21:50:22 +0000
1782@@ -0,0 +1,774 @@
1783+/*
1784+ This source file is part of Konsole, a terminal emulator.
1785+
1786+ Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
1787+
1788+ This program is free software; you can redistribute it and/or modify
1789+ it under the terms of the GNU General Public License as published by
1790+ the Free Software Foundation; either version 2 of the License, or
1791+ (at your option) any later version.
1792+
1793+ This program is distributed in the hope that it will be useful,
1794+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1795+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1796+ GNU General Public License for more details.
1797+
1798+ You should have received a copy of the GNU General Public License
1799+ along with this program; if not, write to the Free Software
1800+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1801+ 02110-1301 USA.
1802+*/
1803+
1804+// Own
1805+#include "ColorScheme.h"
1806+#include "tools.h"
1807+
1808+// Qt
1809+#include <QtGui/QBrush>
1810+#include <QtCore/QFile>
1811+#include <QtCore/QFileInfo>
1812+#include <QtDebug>
1813+#include <QSettings>
1814+#include <QDir>
1815+
1816+
1817+// KDE
1818+//#include <KColorScheme>
1819+//#include <KConfig>
1820+//#include <KLocale>
1821+//#include <KDebug>
1822+//#include <KConfigGroup>
1823+//#include <KStandardDirs>
1824+
1825+
1826+const ColorEntry ColorScheme::defaultTable[TABLE_COLORS] =
1827+ // The following are almost IBM standard color codes, with some slight
1828+ // gamma correction for the dim colors to compensate for bright X screens.
1829+ // It contains the 8 ansiterm/xterm colors in 2 intensities.
1830+{
1831+ ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
1832+QColor(0xFF,0xFF,0xFF), 1), // Dfore, Dback
1833+ ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
1834+QColor(0xB2,0x18,0x18), 0), // Black, Red
1835+ ColorEntry( QColor(0x18,0xB2,0x18), 0), ColorEntry(
1836+QColor(0xB2,0x68,0x18), 0), // Green, Yellow
1837+ ColorEntry( QColor(0x18,0x18,0xB2), 0), ColorEntry(
1838+QColor(0xB2,0x18,0xB2), 0), // Blue, Magenta
1839+ ColorEntry( QColor(0x18,0xB2,0xB2), 0), ColorEntry(
1840+QColor(0xB2,0xB2,0xB2), 0), // Cyan, White
1841+ // intensive
1842+ ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
1843+QColor(0xFF,0xFF,0xFF), 1),
1844+ ColorEntry( QColor(0x68,0x68,0x68), 0), ColorEntry(
1845+QColor(0xFF,0x54,0x54), 0),
1846+ ColorEntry( QColor(0x54,0xFF,0x54), 0), ColorEntry(
1847+QColor(0xFF,0xFF,0x54), 0),
1848+ ColorEntry( QColor(0x54,0x54,0xFF), 0), ColorEntry(
1849+QColor(0xFF,0x54,0xFF), 0),
1850+ ColorEntry( QColor(0x54,0xFF,0xFF), 0), ColorEntry(
1851+QColor(0xFF,0xFF,0xFF), 0)
1852+};
1853+
1854+const char* const ColorScheme::colorNames[TABLE_COLORS] =
1855+{
1856+ "Foreground",
1857+ "Background",
1858+ "Color0",
1859+ "Color1",
1860+ "Color2",
1861+ "Color3",
1862+ "Color4",
1863+ "Color5",
1864+ "Color6",
1865+ "Color7",
1866+ "ForegroundIntense",
1867+ "BackgroundIntense",
1868+ "Color0Intense",
1869+ "Color1Intense",
1870+ "Color2Intense",
1871+ "Color3Intense",
1872+ "Color4Intense",
1873+ "Color5Intense",
1874+ "Color6Intense",
1875+ "Color7Intense"
1876+};
1877+// dummy silently comment out the tr_NOOP
1878+#define tr_NOOP
1879+const char* const ColorScheme::translatedColorNames[TABLE_COLORS] =
1880+{
1881+ tr_NOOP("Foreground"),
1882+ tr_NOOP("Background"),
1883+ tr_NOOP("Color 1"),
1884+ tr_NOOP("Color 2"),
1885+ tr_NOOP("Color 3"),
1886+ tr_NOOP("Color 4"),
1887+ tr_NOOP("Color 5"),
1888+ tr_NOOP("Color 6"),
1889+ tr_NOOP("Color 7"),
1890+ tr_NOOP("Color 8"),
1891+ tr_NOOP("Foreground (Intense)"),
1892+ tr_NOOP("Background (Intense)"),
1893+ tr_NOOP("Color 1 (Intense)"),
1894+ tr_NOOP("Color 2 (Intense)"),
1895+ tr_NOOP("Color 3 (Intense)"),
1896+ tr_NOOP("Color 4 (Intense)"),
1897+ tr_NOOP("Color 5 (Intense)"),
1898+ tr_NOOP("Color 6 (Intense)"),
1899+ tr_NOOP("Color 7 (Intense)"),
1900+ tr_NOOP("Color 8 (Intense)")
1901+};
1902+
1903+ColorScheme::ColorScheme()
1904+{
1905+ _table = 0;
1906+ _randomTable = 0;
1907+ _opacity = 1.0;
1908+}
1909+ColorScheme::ColorScheme(const ColorScheme& other)
1910+ : _opacity(other._opacity)
1911+ ,_table(0)
1912+ ,_randomTable(0)
1913+{
1914+ setName(other.name());
1915+ setDescription(other.description());
1916+
1917+ if ( other._table != 0 )
1918+ {
1919+ for ( int i = 0 ; i < TABLE_COLORS ; i++ )
1920+ setColorTableEntry(i,other._table[i]);
1921+ }
1922+
1923+ if ( other._randomTable != 0 )
1924+ {
1925+ for ( int i = 0 ; i < TABLE_COLORS ; i++ )
1926+ {
1927+ const RandomizationRange& range = other._randomTable[i];
1928+ setRandomizationRange(i,range.hue,range.saturation,range.value);
1929+ }
1930+ }
1931+}
1932+ColorScheme::~ColorScheme()
1933+{
1934+ delete[] _table;
1935+ delete[] _randomTable;
1936+}
1937+
1938+void ColorScheme::setDescription(const QString& description) { _description = description; }
1939+QString ColorScheme::description() const { return _description; }
1940+
1941+void ColorScheme::setName(const QString& name) { _name = name; }
1942+QString ColorScheme::name() const { return _name; }
1943+
1944+void ColorScheme::setColorTableEntry(int index , const ColorEntry& entry)
1945+{
1946+ Q_ASSERT( index >= 0 && index < TABLE_COLORS );
1947+
1948+ if ( !_table )
1949+ {
1950+ _table = new ColorEntry[TABLE_COLORS];
1951+
1952+ for (int i=0;i<TABLE_COLORS;i++)
1953+ _table[i] = defaultTable[i];
1954+ }
1955+
1956+ _table[index] = entry;
1957+}
1958+ColorEntry ColorScheme::colorEntry(int index , uint randomSeed) const
1959+{
1960+ Q_ASSERT( index >= 0 && index < TABLE_COLORS );
1961+
1962+ if ( randomSeed != 0 )
1963+ qsrand(randomSeed);
1964+
1965+ ColorEntry entry = colorTable()[index];
1966+
1967+ if ( randomSeed != 0 &&
1968+ _randomTable != 0 &&
1969+ !_randomTable[index].isNull() )
1970+ {
1971+ const RandomizationRange& range = _randomTable[index];
1972+
1973+
1974+ int hueDifference = range.hue ? (qrand() % range.hue) - range.hue/2 : 0;
1975+ int saturationDifference = range.saturation ? (qrand() % range.saturation) - range.saturation/2 : 0;
1976+ int valueDifference = range.value ? (qrand() % range.value) - range.value/2 : 0;
1977+
1978+ QColor& color = entry.color;
1979+
1980+ int newHue = qAbs( (color.hue() + hueDifference) % MAX_HUE );
1981+ int newValue = qMin( qAbs(color.value() + valueDifference) , 255 );
1982+ int newSaturation = qMin( qAbs(color.saturation() + saturationDifference) , 255 );
1983+
1984+ color.setHsv(newHue,newSaturation,newValue);
1985+ }
1986+
1987+ return entry;
1988+}
1989+void ColorScheme::getColorTable(ColorEntry* table , uint randomSeed) const
1990+{
1991+ for ( int i = 0 ; i < TABLE_COLORS ; i++ )
1992+ table[i] = colorEntry(i,randomSeed);
1993+}
1994+bool ColorScheme::randomizedBackgroundColor() const
1995+{
1996+ return _randomTable == 0 ? false : !_randomTable[1].isNull();
1997+}
1998+void ColorScheme::setRandomizedBackgroundColor(bool randomize)
1999+{
2000+ // the hue of the background colour is allowed to be randomly
2001+ // adjusted as much as possible.
2002+ //
2003+ // the value and saturation are left alone to maintain read-ability
2004+ if ( randomize )
2005+ {
2006+ setRandomizationRange( 1 /* background color index */ , MAX_HUE , 255 , 0 );
2007+ }
2008+ else
2009+ {
2010+ if ( _randomTable )
2011+ setRandomizationRange( 1 /* background color index */ , 0 , 0 , 0 );
2012+ }
2013+}
2014+
2015+void ColorScheme::setRandomizationRange( int index , quint16 hue , quint8 saturation ,
2016+ quint8 value )
2017+{
2018+ Q_ASSERT( hue <= MAX_HUE );
2019+ Q_ASSERT( index >= 0 && index < TABLE_COLORS );
2020+
2021+ if ( _randomTable == 0 )
2022+ _randomTable = new RandomizationRange[TABLE_COLORS];
2023+
2024+ _randomTable[index].hue = hue;
2025+ _randomTable[index].value = value;
2026+ _randomTable[index].saturation = saturation;
2027+}
2028+
2029+const ColorEntry* ColorScheme::colorTable() const
2030+{
2031+ if ( _table )
2032+ return _table;
2033+ else
2034+ return defaultTable;
2035+}
2036+QColor ColorScheme::foregroundColor() const
2037+{
2038+ return colorTable()[0].color;
2039+}
2040+QColor ColorScheme::backgroundColor() const
2041+{
2042+ return colorTable()[1].color;
2043+}
2044+bool ColorScheme::hasDarkBackground() const
2045+{
2046+ // value can range from 0 - 255, with larger values indicating higher brightness.
2047+ // so 127 is in the middle, anything less is deemed 'dark'
2048+ return backgroundColor().value() < 127;
2049+}
2050+void ColorScheme::setOpacity(qreal opacity) { _opacity = opacity; }
2051+qreal ColorScheme::opacity() const { return _opacity; }
2052+
2053+void ColorScheme::read(const QString & fileName)
2054+{
2055+ QSettings s(fileName, QSettings::IniFormat);
2056+ s.beginGroup("General");
2057+
2058+ _description = s.value("Description", QObject::tr("Un-named Color Scheme")).toString();
2059+ _opacity = s.value("Opacity",qreal(1.0)).toDouble();
2060+ s.endGroup();
2061+
2062+ for (int i=0 ; i < TABLE_COLORS ; i++)
2063+ {
2064+ readColorEntry(&s, i);
2065+ }
2066+}
2067+#if 0
2068+// implemented upstream - user apps
2069+void ColorScheme::read(KConfig& config)
2070+{
2071+ KConfigGroup configGroup = config.group("General");
2072+
2073+ QString description = configGroup.readEntry("Description", QObject::tr("Un-named Color Scheme"));
2074+
2075+ _description = tr(description.toUtf8());
2076+ _opacity = configGroup.readEntry("Opacity",qreal(1.0));
2077+
2078+ for (int i=0 ; i < TABLE_COLORS ; i++)
2079+ {
2080+ readColorEntry(config,i);
2081+ }
2082+}
2083+void ColorScheme::write(KConfig& config) const
2084+{
2085+ KConfigGroup configGroup = config.group("General");
2086+
2087+ configGroup.writeEntry("Description",_description);
2088+ configGroup.writeEntry("Opacity",_opacity);
2089+
2090+ for (int i=0 ; i < TABLE_COLORS ; i++)
2091+ {
2092+ RandomizationRange random = _randomTable != 0 ? _randomTable[i] : RandomizationRange();
2093+ writeColorEntry(config,colorNameForIndex(i),colorTable()[i],random);
2094+ }
2095+}
2096+#endif
2097+
2098+QString ColorScheme::colorNameForIndex(int index)
2099+{
2100+ Q_ASSERT( index >= 0 && index < TABLE_COLORS );
2101+
2102+ return QString(colorNames[index]);
2103+}
2104+QString ColorScheme::translatedColorNameForIndex(int index)
2105+{
2106+ Q_ASSERT( index >= 0 && index < TABLE_COLORS );
2107+
2108+ return translatedColorNames[index];
2109+}
2110+
2111+void ColorScheme::readColorEntry(QSettings * s , int index)
2112+{
2113+ s->beginGroup(colorNameForIndex(index));
2114+
2115+ ColorEntry entry;
2116+
2117+ QStringList rgbList = s->value("Color", QStringList()).toStringList();
2118+ if (rgbList.count() != 3)
2119+ {
2120+ Q_ASSERT(0);
2121+ }
2122+ int r, g, b;
2123+ r = rgbList[0].toInt();
2124+ g = rgbList[1].toInt();
2125+ b = rgbList[2].toInt();
2126+ entry.color = QColor(r, g, b);
2127+
2128+ entry.transparent = s->value("Transparent",false).toBool();
2129+
2130+ // Deprecated key from KDE 4.0 which set 'Bold' to true to force
2131+ // a color to be bold or false to use the current format
2132+ //
2133+ // TODO - Add a new tri-state key which allows for bold, normal or
2134+ // current format
2135+ if (s->contains("Bold"))
2136+ entry.fontWeight = s->value("Bold",false).toBool() ? ColorEntry::Bold :
2137+ ColorEntry::UseCurrentFormat;
2138+
2139+ quint16 hue = s->value("MaxRandomHue",0).toInt();
2140+ quint8 value = s->value("MaxRandomValue",0).toInt();
2141+ quint8 saturation = s->value("MaxRandomSaturation",0).toInt();
2142+
2143+ setColorTableEntry( index , entry );
2144+
2145+ if ( hue != 0 || value != 0 || saturation != 0 )
2146+ setRandomizationRange( index , hue , saturation , value );
2147+
2148+ s->endGroup();
2149+}
2150+#if 0
2151+// implemented upstream - user apps
2152+void ColorScheme::writeColorEntry(KConfig& config , const QString& colorName, const ColorEntry& entry , const RandomizationRange& random) const
2153+{
2154+ KConfigGroup configGroup(&config,colorName);
2155+
2156+ configGroup.writeEntry("Color",entry.color);
2157+ configGroup.writeEntry("Transparency",(bool)entry.transparent);
2158+ if (entry.fontWeight != ColorEntry::UseCurrentFormat)
2159+ {
2160+ configGroup.writeEntry("Bold",entry.fontWeight == ColorEntry::Bold);
2161+ }
2162+
2163+ // record randomization if this color has randomization or
2164+ // if one of the keys already exists
2165+ if ( !random.isNull() || configGroup.hasKey("MaxRandomHue") )
2166+ {
2167+ configGroup.writeEntry("MaxRandomHue",(int)random.hue);
2168+ configGroup.writeEntry("MaxRandomValue",(int)random.value);
2169+ configGroup.writeEntry("MaxRandomSaturation",(int)random.saturation);
2170+ }
2171+}
2172+#endif
2173+
2174+//
2175+// Work In Progress - A color scheme for use on KDE setups for users
2176+// with visual disabilities which means that they may have trouble
2177+// reading text with the supplied color schemes.
2178+//
2179+// This color scheme uses only the 'safe' colors defined by the
2180+// KColorScheme class.
2181+//
2182+// A complication this introduces is that each color provided by
2183+// KColorScheme is defined as a 'background' or 'foreground' color.
2184+// Only foreground colors are allowed to be used to render text and
2185+// only background colors are allowed to be used for backgrounds.
2186+//
2187+// The ColorEntry and TerminalDisplay classes do not currently
2188+// support this restriction.
2189+//
2190+// Requirements:
2191+// - A color scheme which uses only colors from the KColorScheme class
2192+// - Ability to restrict which colors the TerminalDisplay widget
2193+// uses as foreground and background color
2194+// - Make use of KGlobalSettings::allowDefaultBackgroundImages() as
2195+// a hint to determine whether this accessible color scheme should
2196+// be used by default.
2197+//
2198+//
2199+// -- Robert Knight <robertknight@gmail.com> 21/07/2007
2200+//
2201+AccessibleColorScheme::AccessibleColorScheme()
2202+ : ColorScheme()
2203+{
2204+#if 0
2205+// It's not finished in konsole and it breaks Qt4 compilation as well
2206+ // basic attributes
2207+ setName("accessible");
2208+ setDescription(QObject::tr("Accessible Color Scheme"));
2209+
2210+ // setup colors
2211+ const int ColorRoleCount = 8;
2212+
2213+ const KColorScheme colorScheme(QPalette::Active);
2214+
2215+ QBrush colors[ColorRoleCount] =
2216+ {
2217+ colorScheme.foreground( colorScheme.NormalText ),
2218+ colorScheme.background( colorScheme.NormalBackground ),
2219+
2220+ colorScheme.foreground( colorScheme.InactiveText ),
2221+ colorScheme.foreground( colorScheme.ActiveText ),
2222+ colorScheme.foreground( colorScheme.LinkText ),
2223+ colorScheme.foreground( colorScheme.VisitedText ),
2224+ colorScheme.foreground( colorScheme.NegativeText ),
2225+ colorScheme.foreground( colorScheme.NeutralText )
2226+ };
2227+
2228+ for ( int i = 0 ; i < TABLE_COLORS ; i++ )
2229+ {
2230+ ColorEntry entry;
2231+ entry.color = colors[ i % ColorRoleCount ].color();
2232+
2233+ setColorTableEntry( i , entry );
2234+ }
2235+#endif
2236+}
2237+
2238+KDE3ColorSchemeReader::KDE3ColorSchemeReader( QIODevice* device ) :
2239+ _device(device)
2240+{
2241+}
2242+ColorScheme* KDE3ColorSchemeReader::read()
2243+{
2244+ Q_ASSERT( _device->openMode() == QIODevice::ReadOnly ||
2245+ _device->openMode() == QIODevice::ReadWrite );
2246+
2247+ ColorScheme* scheme = new ColorScheme();
2248+
2249+ QRegExp comment("#.*$");
2250+ while ( !_device->atEnd() )
2251+ {
2252+ QString line(_device->readLine());
2253+ line.remove(comment);
2254+ line = line.simplified();
2255+
2256+ if ( line.isEmpty() )
2257+ continue;
2258+
2259+ if ( line.startsWith(QLatin1String("color")) )
2260+ {
2261+ if (!readColorLine(line,scheme))
2262+ qDebug() << "Failed to read KDE 3 color scheme line" << line;
2263+ }
2264+ else if ( line.startsWith(QLatin1String("title")) )
2265+ {
2266+ if (!readTitleLine(line,scheme))
2267+ qDebug() << "Failed to read KDE 3 color scheme title line" << line;
2268+ }
2269+ else
2270+ {
2271+ qDebug() << "KDE 3 color scheme contains an unsupported feature, '" <<
2272+ line << "'";
2273+ }
2274+ }
2275+
2276+ return scheme;
2277+}
2278+bool KDE3ColorSchemeReader::readColorLine(const QString& line,ColorScheme* scheme)
2279+{
2280+ QStringList list = line.split(QChar(' '));
2281+
2282+ if (list.count() != 7)
2283+ return false;
2284+ if (list.first() != "color")
2285+ return false;
2286+
2287+ int index = list[1].toInt();
2288+ int red = list[2].toInt();
2289+ int green = list[3].toInt();
2290+ int blue = list[4].toInt();
2291+ int transparent = list[5].toInt();
2292+ int bold = list[6].toInt();
2293+
2294+ const int MAX_COLOR_VALUE = 255;
2295+
2296+ if( (index < 0 || index >= TABLE_COLORS )
2297+ || (red < 0 || red > MAX_COLOR_VALUE )
2298+ || (blue < 0 || blue > MAX_COLOR_VALUE )
2299+ || (green < 0 || green > MAX_COLOR_VALUE )
2300+ || (transparent != 0 && transparent != 1 )
2301+ || (bold != 0 && bold != 1) )
2302+ return false;
2303+
2304+ ColorEntry entry;
2305+ entry.color = QColor(red,green,blue);
2306+ entry.transparent = ( transparent != 0 );
2307+ entry.fontWeight = ( bold != 0 ) ? ColorEntry::Bold : ColorEntry::UseCurrentFormat;
2308+
2309+ scheme->setColorTableEntry(index,entry);
2310+ return true;
2311+}
2312+bool KDE3ColorSchemeReader::readTitleLine(const QString& line,ColorScheme* scheme)
2313+{
2314+ if( !line.startsWith(QLatin1String("title")) )
2315+ return false;
2316+
2317+ int spacePos = line.indexOf(' ');
2318+ if( spacePos == -1 )
2319+ return false;
2320+
2321+ QString description = line.mid(spacePos+1);
2322+
2323+ scheme->setDescription(description.toUtf8());
2324+ return true;
2325+}
2326+ColorSchemeManager::ColorSchemeManager()
2327+ : _haveLoadedAll(false)
2328+{
2329+}
2330+ColorSchemeManager::~ColorSchemeManager()
2331+{
2332+ QHashIterator<QString,const ColorScheme*> iter(_colorSchemes);
2333+ while (iter.hasNext())
2334+ {
2335+ iter.next();
2336+ delete iter.value();
2337+ }
2338+}
2339+void ColorSchemeManager::loadAllColorSchemes()
2340+{
2341+ qDebug() << "loadAllColorSchemes";
2342+ int success = 0;
2343+ int failed = 0;
2344+
2345+ QList<QString> nativeColorSchemes = listColorSchemes();
2346+
2347+ QListIterator<QString> nativeIter(nativeColorSchemes);
2348+ while ( nativeIter.hasNext() )
2349+ {
2350+ if ( loadColorScheme( nativeIter.next() ) )
2351+ success++;
2352+ else
2353+ failed++;
2354+ }
2355+
2356+ QList<QString> kde3ColorSchemes = listKDE3ColorSchemes();
2357+ QListIterator<QString> kde3Iter(kde3ColorSchemes);
2358+ while ( kde3Iter.hasNext() )
2359+ {
2360+ if ( loadKDE3ColorScheme( kde3Iter.next() ) )
2361+ success++;
2362+ else
2363+ failed++;
2364+ }
2365+
2366+ if ( failed > 0 )
2367+ qDebug() << "failed to load " << failed << " color schemes.";
2368+
2369+ _haveLoadedAll = true;
2370+}
2371+QList<const ColorScheme*> ColorSchemeManager::allColorSchemes()
2372+{
2373+ if ( !_haveLoadedAll )
2374+ {
2375+ loadAllColorSchemes();
2376+ }
2377+
2378+ return _colorSchemes.values();
2379+}
2380+bool ColorSchemeManager::loadKDE3ColorScheme(const QString& filePath)
2381+{
2382+ QFile file(filePath);
2383+ if (!filePath.endsWith(QLatin1String(".schema")) || !file.open(QIODevice::ReadOnly))
2384+ return false;
2385+
2386+ KDE3ColorSchemeReader reader(&file);
2387+ ColorScheme* scheme = reader.read();
2388+ scheme->setName(QFileInfo(file).baseName());
2389+ file.close();
2390+
2391+ if (scheme->name().isEmpty())
2392+ {
2393+ qDebug() << "color scheme name is not valid.";
2394+ delete scheme;
2395+ return false;
2396+ }
2397+
2398+ QFileInfo info(filePath);
2399+
2400+ if ( !_colorSchemes.contains(info.baseName()) )
2401+ _colorSchemes.insert(scheme->name(),scheme);
2402+ else
2403+ {
2404+ qDebug() << "color scheme with name" << scheme->name() << "has already been" <<
2405+ "found, ignoring.";
2406+ delete scheme;
2407+ }
2408+
2409+ return true;
2410+}
2411+#if 0
2412+void ColorSchemeManager::addColorScheme(ColorScheme* scheme)
2413+{
2414+ _colorSchemes.insert(scheme->name(),scheme);
2415+
2416+ // save changes to disk
2417+ QString path = KGlobal::dirs()->saveLocation("data","konsole/") + scheme->name() + ".colorscheme";
2418+ KConfig config(path , KConfig::NoGlobals);
2419+
2420+ scheme->write(config);
2421+}
2422+#endif
2423+bool ColorSchemeManager::loadColorScheme(const QString& filePath)
2424+{
2425+ if ( !filePath.endsWith(QLatin1String(".colorscheme")) || !QFile::exists(filePath) )
2426+ return false;
2427+
2428+ QFileInfo info(filePath);
2429+
2430+ ColorScheme* scheme = new ColorScheme();
2431+ scheme->setName(info.baseName());
2432+ scheme->read(filePath);
2433+
2434+ if (scheme->name().isEmpty())
2435+ {
2436+ qDebug() << "Color scheme in" << filePath << "does not have a valid name and was not loaded.";
2437+ delete scheme;
2438+ return false;
2439+ }
2440+
2441+ if ( !_colorSchemes.contains(info.baseName()) )
2442+ {
2443+ _colorSchemes.insert(scheme->name(),scheme);
2444+ }
2445+ else
2446+ {
2447+ qDebug() << "color scheme with name" << scheme->name() << "has already been" <<
2448+ "found, ignoring.";
2449+
2450+ delete scheme;
2451+ }
2452+
2453+ return true;
2454+}
2455+QList<QString> ColorSchemeManager::listKDE3ColorSchemes()
2456+{
2457+ QString dname(get_color_schemes_dir());
2458+ QDir dir(dname);
2459+ QStringList filters;
2460+ filters << "*.schema";
2461+ dir.setNameFilters(filters);
2462+ QStringList list = dir.entryList(filters);
2463+ QStringList ret;
2464+ foreach(QString i, list)
2465+ ret << dname + "/" + i;
2466+ return ret;
2467+ //return KGlobal::dirs()->findAllResources("data",
2468+ // "konsole/*.schema",
2469+ // KStandardDirs::NoDuplicates);
2470+ //
2471+}
2472+QList<QString> ColorSchemeManager::listColorSchemes()
2473+{
2474+ QString dname(get_color_schemes_dir());
2475+ QDir dir(dname);
2476+ QStringList filters;
2477+ filters << "*.colorscheme";
2478+ dir.setNameFilters(filters);
2479+ QStringList list = dir.entryList(filters);
2480+ QStringList ret;
2481+ foreach(QString i, list)
2482+ ret << dname + "/" + i;
2483+ return ret;
2484+// return KGlobal::dirs()->findAllResources("data",
2485+// "konsole/*.colorscheme",
2486+// KStandardDirs::NoDuplicates);
2487+}
2488+const ColorScheme ColorSchemeManager::_defaultColorScheme;
2489+const ColorScheme* ColorSchemeManager::defaultColorScheme() const
2490+{
2491+ return &_defaultColorScheme;
2492+}
2493+bool ColorSchemeManager::deleteColorScheme(const QString& name)
2494+{
2495+ Q_ASSERT( _colorSchemes.contains(name) );
2496+
2497+ // lookup the path and delete
2498+ QString path = findColorSchemePath(name);
2499+ if ( QFile::remove(path) )
2500+ {
2501+ _colorSchemes.remove(name);
2502+ return true;
2503+ }
2504+ else
2505+ {
2506+ qDebug() << "Failed to remove color scheme -" << path;
2507+ return false;
2508+ }
2509+}
2510+QString ColorSchemeManager::findColorSchemePath(const QString& name) const
2511+{
2512+// QString path = KStandardDirs::locate("data","konsole/"+name+".colorscheme");
2513+ QString path(get_color_schemes_dir() + "/"+ name + ".colorscheme");
2514+ if ( !path.isEmpty() )
2515+ return path;
2516+
2517+ //path = KStandardDirs::locate("data","konsole/"+name+".schema");
2518+ path = get_color_schemes_dir() + "/"+ name + ".schema";
2519+
2520+ return path;
2521+}
2522+const ColorScheme* ColorSchemeManager::findColorScheme(const QString& name)
2523+{
2524+ if ( name.isEmpty() )
2525+ return defaultColorScheme();
2526+
2527+ if ( _colorSchemes.contains(name) )
2528+ return _colorSchemes[name];
2529+ else
2530+ {
2531+ // look for this color scheme
2532+ QString path = findColorSchemePath(name);
2533+ if ( !path.isEmpty() && loadColorScheme(path) )
2534+ {
2535+ return findColorScheme(name);
2536+ }
2537+ else
2538+ {
2539+ if (!path.isEmpty() && loadKDE3ColorScheme(path))
2540+ return findColorScheme(name);
2541+ }
2542+
2543+ qDebug() << "Could not find color scheme - " << name;
2544+
2545+ return 0;
2546+ }
2547+}
2548+
2549+ColorSchemeManager* ColorSchemeManager::theColorSchemeManager = 0;
2550+//K_GLOBAL_STATIC( ColorSchemeManager , theColorSchemeManager )
2551+ColorSchemeManager* ColorSchemeManager::instance()
2552+{
2553+ if (! theColorSchemeManager)
2554+ theColorSchemeManager = new ColorSchemeManager();
2555+ return theColorSchemeManager;
2556+}
2557
2558=== added file 'src/plugin/konsole/ColorScheme.h'
2559--- src/plugin/konsole/ColorScheme.h 1970-01-01 00:00:00 +0000
2560+++ src/plugin/konsole/ColorScheme.h 2014-05-06 21:50:22 +0000
2561@@ -0,0 +1,342 @@
2562+/*
2563+ This source file is part of Konsole, a terminal emulator.
2564+
2565+ Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
2566+
2567+ This program is free software; you can redistribute it and/or modify
2568+ it under the terms of the GNU General Public License as published by
2569+ the Free Software Foundation; either version 2 of the License, or
2570+ (at your option) any later version.
2571+
2572+ This program is distributed in the hope that it will be useful,
2573+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2574+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2575+ GNU General Public License for more details.
2576+
2577+ You should have received a copy of the GNU General Public License
2578+ along with this program; if not, write to the Free Software
2579+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2580+ 02110-1301 USA.
2581+*/
2582+
2583+#ifndef COLORSCHEME_H
2584+#define COLORSCHEME_H
2585+
2586+// Qt
2587+#include <QtCore/QHash>
2588+#include <QtCore/QList>
2589+#include <QtCore/QMetaType>
2590+#include <QtCore/QIODevice>
2591+#include <QtCore/QSet>
2592+#include <QSettings>
2593+
2594+// Konsole
2595+#include "CharacterColor.h"
2596+
2597+class QIODevice;
2598+//class KConfig;
2599+
2600+
2601+/**
2602+ * Represents a color scheme for a terminal display.
2603+ *
2604+ * The color scheme includes the palette of colors used to draw the text and character backgrounds
2605+ * in the display and the opacity level of the display background.
2606+ */
2607+class ColorScheme
2608+{
2609+public:
2610+ /**
2611+ * Constructs a new color scheme which is initialised to the default color set
2612+ * for Konsole.
2613+ */
2614+ ColorScheme();
2615+ ColorScheme(const ColorScheme& other);
2616+ ~ColorScheme();
2617+
2618+ /** Sets the descriptive name of the color scheme. */
2619+ void setDescription(const QString& description);
2620+ /** Returns the descriptive name of the color scheme. */
2621+ QString description() const;
2622+
2623+ /** Sets the name of the color scheme */
2624+ void setName(const QString& name);
2625+ /** Returns the name of the color scheme */
2626+ QString name() const;
2627+
2628+#if 0
2629+// Implemented upstream - in user apps
2630+ /** Reads the color scheme from the specified configuration source */
2631+ void read(KConfig& config);
2632+ /** Writes the color scheme to the specified configuration source */
2633+ void write(KConfig& config) const;
2634+#endif
2635+ void read(const QString & filename);
2636+
2637+ /** Sets a single entry within the color palette. */
2638+ void setColorTableEntry(int index , const ColorEntry& entry);
2639+
2640+ /**
2641+ * Copies the color entries which form the palette for this color scheme
2642+ * into @p table. @p table should be an array with TABLE_COLORS entries.
2643+ *
2644+ * @param table Array into which the color entries for this color scheme
2645+ * are copied.
2646+ * @param randomSeed Color schemes may allow certain colors in their
2647+ * palette to be randomized. The seed is used to pick the random color.
2648+ */
2649+ void getColorTable(ColorEntry* table, uint randomSeed = 0) const;
2650+
2651+ /**
2652+ * Retrieves a single color entry from the table.
2653+ *
2654+ * See getColorTable()
2655+ */
2656+ ColorEntry colorEntry(int index , uint randomSeed = 0) const;
2657+
2658+ /**
2659+ * Convenience method. Returns the
2660+ * foreground color for this scheme,
2661+ * this is the primary color used to draw the
2662+ * text in this scheme.
2663+ */
2664+ QColor foregroundColor() const;
2665+ /**
2666+ * Convenience method. Returns the background color for
2667+ * this scheme, this is the primary color used to
2668+ * draw the terminal background in this scheme.
2669+ */
2670+ QColor backgroundColor() const;
2671+
2672+ /**
2673+ * Returns true if this color scheme has a dark background.
2674+ * The background color is said to be dark if it has a value of less than 127
2675+ * in the HSV color space.
2676+ */
2677+ bool hasDarkBackground() const;
2678+
2679+ /**
2680+ * Sets the opacity level of the display background. @p opacity ranges
2681+ * between 0 (completely transparent background) and 1 (completely
2682+ * opaque background).
2683+ *
2684+ * Defaults to 1.
2685+ *
2686+ * TODO: More documentation
2687+ */
2688+ void setOpacity(qreal opacity);
2689+ /**
2690+ * Returns the opacity level for this color scheme, see setOpacity()
2691+ * TODO: More documentation
2692+ */
2693+ qreal opacity() const;
2694+
2695+ /**
2696+ * Enables randomization of the background color. This will cause
2697+ * the palette returned by getColorTable() and colorEntry() to
2698+ * be adjusted depending on the value of the random seed argument
2699+ * to them.
2700+ */
2701+ void setRandomizedBackgroundColor(bool randomize);
2702+
2703+ /** Returns true if the background color is randomized. */
2704+ bool randomizedBackgroundColor() const;
2705+
2706+ static QString colorNameForIndex(int index);
2707+ static QString translatedColorNameForIndex(int index);
2708+
2709+private:
2710+ // specifies how much a particular color can be randomized by
2711+ class RandomizationRange
2712+ {
2713+ public:
2714+ RandomizationRange() : hue(0) , saturation(0) , value(0) {}
2715+
2716+ bool isNull() const
2717+ {
2718+ return ( hue == 0 && saturation == 0 && value == 0 );
2719+ }
2720+
2721+ quint16 hue;
2722+ quint8 saturation;
2723+ quint8 value;
2724+ };
2725+
2726+ // returns the active color table. if none has been set specifically,
2727+ // this is the default color table.
2728+ const ColorEntry* colorTable() const;
2729+
2730+#if 0
2731+// implemented upstream - user apps
2732+ // reads a single colour entry from a KConfig source
2733+ // and sets the palette entry at 'index' to the entry read.
2734+ void readColorEntry(KConfig& config , int index);
2735+ // writes a single colour entry to a KConfig source
2736+ void writeColorEntry(KConfig& config , const QString& colorName, const ColorEntry& entry,const RandomizationRange& range) const;
2737+#endif
2738+ void readColorEntry(QSettings *s, int index);
2739+
2740+ // sets the amount of randomization allowed for a particular color
2741+ // in the palette. creates the randomization table if
2742+ // it does not already exist
2743+ void setRandomizationRange( int index , quint16 hue , quint8 saturation , quint8 value );
2744+
2745+ QString _description;
2746+ QString _name;
2747+ qreal _opacity;
2748+ ColorEntry* _table; // pointer to custom color table or 0 if the default
2749+ // color scheme is being used
2750+
2751+
2752+ static const quint16 MAX_HUE = 340;
2753+
2754+ RandomizationRange* _randomTable; // pointer to randomization table or 0
2755+ // if no colors in the color scheme support
2756+ // randomization
2757+
2758+ static const char* const colorNames[TABLE_COLORS];
2759+ static const char* const translatedColorNames[TABLE_COLORS];
2760+
2761+ static const ColorEntry defaultTable[]; // table of default color entries
2762+};
2763+
2764+/**
2765+ * A color scheme which uses colors from the standard KDE color palette.
2766+ *
2767+ * This is designed primarily for the benefit of users who are using specially
2768+ * designed colors.
2769+ *
2770+ * TODO Implement and make it the default on systems with specialized KDE
2771+ * color schemes.
2772+ */
2773+class AccessibleColorScheme : public ColorScheme
2774+{
2775+public:
2776+ AccessibleColorScheme();
2777+};
2778+
2779+/**
2780+ * Reads a color scheme stored in the .schema format used in the KDE 3 incarnation
2781+ * of Konsole
2782+ *
2783+ * Only the basic essentials ( title and color palette entries ) are currently
2784+ * supported. Additional options such as background image and background
2785+ * blend colors are ignored.
2786+ */
2787+class KDE3ColorSchemeReader
2788+{
2789+public:
2790+ /**
2791+ * Constructs a new reader which reads from the specified device.
2792+ * The device should be open in read-only mode.
2793+ */
2794+ KDE3ColorSchemeReader( QIODevice* device );
2795+
2796+ /**
2797+ * Reads and parses the contents of the .schema file from the input
2798+ * device and returns the ColorScheme defined within it.
2799+ *
2800+ * Returns a null pointer if an error occurs whilst parsing
2801+ * the contents of the file.
2802+ */
2803+ ColorScheme* read();
2804+
2805+private:
2806+ // reads a line from the file specifying a colour palette entry
2807+ // format is: color [index] [red] [green] [blue] [transparent] [bold]
2808+ bool readColorLine(const QString& line , ColorScheme* scheme);
2809+ bool readTitleLine(const QString& line , ColorScheme* scheme);
2810+
2811+ QIODevice* _device;
2812+};
2813+
2814+/**
2815+ * Manages the color schemes available for use by terminal displays.
2816+ * See ColorScheme
2817+ */
2818+class ColorSchemeManager
2819+{
2820+public:
2821+
2822+ /**
2823+ * Constructs a new ColorSchemeManager and loads the list
2824+ * of available color schemes.
2825+ *
2826+ * The color schemes themselves are not loaded until they are first
2827+ * requested via a call to findColorScheme()
2828+ */
2829+ ColorSchemeManager();
2830+ /**
2831+ * Destroys the ColorSchemeManager and saves any modified color schemes to disk.
2832+ */
2833+ ~ColorSchemeManager();
2834+
2835+ /**
2836+ * Returns the default color scheme for Konsole
2837+ */
2838+ const ColorScheme* defaultColorScheme() const;
2839+
2840+ /**
2841+ * Returns the color scheme with the given name or 0 if no
2842+ * scheme with that name exists. If @p name is empty, the
2843+ * default color scheme is returned.
2844+ *
2845+ * The first time that a color scheme with a particular name is
2846+ * requested, the configuration information is loaded from disk.
2847+ */
2848+ const ColorScheme* findColorScheme(const QString& name);
2849+
2850+#if 0
2851+ /**
2852+ * Adds a new color scheme to the manager. If @p scheme has the same name as
2853+ * an existing color scheme, it replaces the existing scheme.
2854+ *
2855+ * TODO - Ensure the old color scheme gets deleted
2856+ */
2857+ void addColorScheme(ColorScheme* scheme);
2858+#endif
2859+ /**
2860+ * Deletes a color scheme. Returns true on successful deletion or false otherwise.
2861+ */
2862+ bool deleteColorScheme(const QString& name);
2863+
2864+ /**
2865+ * Returns a list of the all the available color schemes.
2866+ * This may be slow when first called because all of the color
2867+ * scheme resources on disk must be located, read and parsed.
2868+ *
2869+ * Subsequent calls will be inexpensive.
2870+ */
2871+ QList<const ColorScheme*> allColorSchemes();
2872+
2873+ /** Returns the global color scheme manager instance. */
2874+ static ColorSchemeManager* instance();
2875+
2876+private:
2877+ // loads a color scheme from a KDE 4+ .colorscheme file
2878+ bool loadColorScheme(const QString& path);
2879+ // loads a color scheme from a KDE 3 .schema file
2880+ bool loadKDE3ColorScheme(const QString& path);
2881+ // returns a list of paths of color schemes in the KDE 4+ .colorscheme file format
2882+ QList<QString> listColorSchemes();
2883+ // returns a list of paths of color schemes in the .schema file format
2884+ // used in KDE 3
2885+ QList<QString> listKDE3ColorSchemes();
2886+ // loads all of the color schemes
2887+ void loadAllColorSchemes();
2888+ // finds the path of a color scheme
2889+ QString findColorSchemePath(const QString& name) const;
2890+
2891+ QHash<QString,const ColorScheme*> _colorSchemes;
2892+ QSet<ColorScheme*> _modifiedSchemes;
2893+
2894+ bool _haveLoadedAll;
2895+
2896+ static const ColorScheme _defaultColorScheme;
2897+
2898+ static ColorSchemeManager * theColorSchemeManager;
2899+};
2900+
2901+Q_DECLARE_METATYPE(const ColorScheme*)
2902+
2903+#endif //COLORSCHEME_H
2904
2905=== added file 'src/plugin/konsole/ColorTables.h'
2906--- src/plugin/konsole/ColorTables.h 1970-01-01 00:00:00 +0000
2907+++ src/plugin/konsole/ColorTables.h 2014-05-06 21:50:22 +0000
2908@@ -0,0 +1,55 @@
2909+#ifndef _COLOR_TABLE_H
2910+#define _COLOR_TABLE_H
2911+
2912+#include "CharacterColor.h"
2913+
2914+//using namespace Konsole;
2915+#if 0
2916+static const ColorEntry whiteonblack_color_table[TABLE_COLORS] = {
2917+ // normal
2918+ ColorEntry(QColor(0xFF,0xFF,0xFF), false ), ColorEntry( QColor(0x00,0x00,0x00), true ), // Dfore, Dback
2919+ ColorEntry(QColor(0x00,0x00,0x00), false ), ColorEntry( QColor(0xB2,0x18,0x18), false ), // Black, Red
2920+ ColorEntry(QColor(0x18,0xB2,0x18), false ), ColorEntry( QColor(0xB2,0x68,0x18), false ), // Green, Yellow
2921+ ColorEntry(QColor(0x18,0x18,0xB2), false ), ColorEntry( QColor(0xB2,0x18,0xB2), false ), // Blue, Magenta
2922+ ColorEntry(QColor(0x18,0xB2,0xB2), false ), ColorEntry( QColor(0xB2,0xB2,0xB2), false ), // Cyan, White
2923+ // intensiv
2924+ ColorEntry(QColor(0x00,0x00,0x00), false ), ColorEntry( QColor(0xFF,0xFF,0xFF), true ),
2925+ ColorEntry(QColor(0x68,0x68,0x68), false ), ColorEntry( QColor(0xFF,0x54,0x54), false ),
2926+ ColorEntry(QColor(0x54,0xFF,0x54), false ), ColorEntry( QColor(0xFF,0xFF,0x54), false ),
2927+ ColorEntry(QColor(0x54,0x54,0xFF), false ), ColorEntry( QColor(0xFF,0x54,0xFF), false ),
2928+ ColorEntry(QColor(0x54,0xFF,0xFF), false ), ColorEntry( QColor(0xFF,0xFF,0xFF), false )
2929+};
2930+
2931+static const ColorEntry greenonblack_color_table[TABLE_COLORS] = {
2932+ ColorEntry(QColor( 24, 240, 24), false), ColorEntry(QColor( 0, 0, 0), true),
2933+ ColorEntry(QColor( 0, 0, 0), false), ColorEntry(QColor( 178, 24, 24), false),
2934+ ColorEntry(QColor( 24, 178, 24), false), ColorEntry(QColor( 178, 104, 24), false),
2935+ ColorEntry(QColor( 24, 24, 178), false), ColorEntry(QColor( 178, 24, 178), false),
2936+ ColorEntry(QColor( 24, 178, 178), false), ColorEntry(QColor( 178, 178, 178), false),
2937+ // intensive colors
2938+ ColorEntry(QColor( 24, 240, 24), false ), ColorEntry(QColor( 0, 0, 0), true ),
2939+ ColorEntry(QColor( 104, 104, 104), false ), ColorEntry(QColor( 255, 84, 84), false ),
2940+ ColorEntry(QColor( 84, 255, 84), false ), ColorEntry(QColor( 255, 255, 84), false ),
2941+ ColorEntry(QColor( 84, 84, 255), false ), ColorEntry(QColor( 255, 84, 255), false ),
2942+ ColorEntry(QColor( 84, 255, 255), false ), ColorEntry(QColor( 255, 255, 255), false )
2943+};
2944+
2945+static const ColorEntry blackonlightyellow_color_table[TABLE_COLORS] = {
2946+ ColorEntry(QColor( 0, 0, 0), false), ColorEntry(QColor( 255, 255, 221), true),
2947+ ColorEntry(QColor( 0, 0, 0), false), ColorEntry(QColor( 178, 24, 24), false),
2948+ ColorEntry(QColor( 24, 178, 24), false), ColorEntry(QColor( 178, 104, 24), false),
2949+ ColorEntry(QColor( 24, 24, 178), false), ColorEntry(QColor( 178, 24, 178), false),
2950+ ColorEntry(QColor( 24, 178, 178), false), ColorEntry(QColor( 178, 178, 178), false),
2951+ ColorEntry(QColor( 0, 0, 0), false), ColorEntry(QColor( 255, 255, 221), true),
2952+ ColorEntry(QColor(104, 104, 104), false), ColorEntry(QColor( 255, 84, 84), false),
2953+ ColorEntry(QColor( 84, 255, 84), false), ColorEntry(QColor( 255, 255, 84), false),
2954+ ColorEntry(QColor( 84, 84, 255), false), ColorEntry(QColor( 255, 84, 255), false),
2955+ ColorEntry(QColor( 84, 255, 255), false), ColorEntry(QColor( 255, 255, 255), false)
2956+};
2957+
2958+
2959+#endif
2960+
2961+
2962+#endif
2963+
2964
2965=== added file 'src/plugin/konsole/DefaultTranslatorText.h'
2966--- src/plugin/konsole/DefaultTranslatorText.h 1970-01-01 00:00:00 +0000
2967+++ src/plugin/konsole/DefaultTranslatorText.h 2014-05-06 21:50:22 +0000
2968@@ -0,0 +1,2 @@
2969+"keyboard \"Fallback Key Translator\"\n"
2970+"key Tab : \"\\t\" \0"
2971
2972=== added file 'src/plugin/konsole/Emulation.cpp'
2973--- src/plugin/konsole/Emulation.cpp 1970-01-01 00:00:00 +0000
2974+++ src/plugin/konsole/Emulation.cpp 2014-05-06 21:50:22 +0000
2975@@ -0,0 +1,458 @@
2976+/*
2977+ Copyright 2007-2008 Robert Knight <robertknight@gmail.com>
2978+ Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
2979+ Copyright 1996 by Matthias Ettrich <ettrich@kde.org>
2980+
2981+ This program is free software; you can redistribute it and/or modify
2982+ it under the terms of the GNU General Public License as published by
2983+ the Free Software Foundation; either version 2 of the License, or
2984+ (at your option) any later version.
2985+
2986+ This program is distributed in the hope that it will be useful,
2987+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2988+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2989+ GNU General Public License for more details.
2990+
2991+ You should have received a copy of the GNU General Public License
2992+ along with this program; if not, write to the Free Software
2993+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2994+ 02110-1301 USA.
2995+*/
2996+
2997+// Own
2998+#include "Emulation.h"
2999+
3000+// System
3001+#include <assert.h>
3002+#include <stdio.h>
3003+#include <stdlib.h>
3004+#include <unistd.h>
3005+
3006+// Qt
3007+#include <QGuiApplication>
3008+#include <QtGui/QClipboard>
3009+#include <QtCore/QHash>
3010+#include <QtGui/QKeyEvent>
3011+#include <QtCore/QRegExp>
3012+#include <QtCore/QTextStream>
3013+#include <QtCore/QThread>
3014+
3015+#include <QtCore/QTime>
3016+
3017+// KDE
3018+//#include <kdebug.h>
3019+
3020+// Konsole
3021+#include "KeyboardTranslator.h"
3022+#include "Screen.h"
3023+#include "TerminalCharacterDecoder.h"
3024+#include "ScreenWindow.h"
3025+
3026+Emulation::Emulation() :
3027+ _currentScreen(0),
3028+ _codec(0),
3029+ _decoder(0),
3030+ _keyTranslator(0),
3031+ _usesMouse(false)
3032+{
3033+ // create screens with a default size
3034+ _screen[0] = new Screen(40,80);
3035+ _screen[1] = new Screen(40,80);
3036+ _currentScreen = _screen[0];
3037+
3038+ QObject::connect(&_bulkTimer1, SIGNAL(timeout()), this, SLOT(showBulk()) );
3039+ QObject::connect(&_bulkTimer2, SIGNAL(timeout()), this, SLOT(showBulk()) );
3040+
3041+ // listen for mouse status changes
3042+ connect( this , SIGNAL(programUsesMouseChanged(bool)) ,
3043+ SLOT(usesMouseChanged(bool)) );
3044+}
3045+
3046+bool Emulation::programUsesMouse() const
3047+{
3048+ return _usesMouse;
3049+}
3050+
3051+void Emulation::usesMouseChanged(bool usesMouse)
3052+{
3053+ _usesMouse = usesMouse;
3054+}
3055+
3056+ScreenWindow* Emulation::createWindow()
3057+{
3058+ ScreenWindow* window = new ScreenWindow();
3059+ window->setScreen(_currentScreen);
3060+ _windows << window;
3061+
3062+ connect(window , SIGNAL(selectionChanged()),
3063+ this , SLOT(bufferedUpdate()));
3064+
3065+ connect(this , SIGNAL(outputChanged()),
3066+ window , SLOT(notifyOutputChanged()) );
3067+ return window;
3068+}
3069+
3070+Emulation::~Emulation()
3071+{
3072+ QListIterator<ScreenWindow*> windowIter(_windows);
3073+
3074+ while (windowIter.hasNext())
3075+ {
3076+ delete windowIter.next();
3077+ }
3078+
3079+ delete _screen[0];
3080+ delete _screen[1];
3081+ delete _decoder;
3082+}
3083+
3084+void Emulation::setScreen(int n)
3085+{
3086+ Screen *old = _currentScreen;
3087+ _currentScreen = _screen[n & 1];
3088+ if (_currentScreen != old)
3089+ {
3090+ // tell all windows onto this emulation to switch to the newly active screen
3091+ foreach(ScreenWindow* window,_windows)
3092+ window->setScreen(_currentScreen);
3093+ }
3094+}
3095+
3096+void Emulation::clearHistory()
3097+{
3098+ _screen[0]->setScroll( _screen[0]->getScroll() , false );
3099+}
3100+void Emulation::setHistory(const HistoryType& t)
3101+{
3102+ _screen[0]->setScroll(t);
3103+
3104+ showBulk();
3105+}
3106+
3107+const HistoryType& Emulation::history() const
3108+{
3109+ return _screen[0]->getScroll();
3110+}
3111+
3112+void Emulation::setCodec(const QTextCodec * qtc)
3113+{
3114+ if (qtc)
3115+ _codec = qtc;
3116+ else
3117+ setCodec(LocaleCodec);
3118+
3119+ delete _decoder;
3120+ _decoder = _codec->makeDecoder();
3121+
3122+ emit useUtf8Request(utf8());
3123+}
3124+
3125+void Emulation::setCodec(EmulationCodec codec)
3126+{
3127+ if ( codec == Utf8Codec )
3128+ setCodec( QTextCodec::codecForName("utf8") );
3129+ else if ( codec == LocaleCodec )
3130+ setCodec( QTextCodec::codecForLocale() );
3131+}
3132+
3133+void Emulation::setKeyBindings(const QString& name)
3134+{
3135+ _keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name);
3136+ if (!_keyTranslator)
3137+ {
3138+ _keyTranslator = KeyboardTranslatorManager::instance()->defaultTranslator();
3139+ }
3140+}
3141+
3142+QString Emulation::keyBindings() const
3143+{
3144+ return _keyTranslator->name();
3145+}
3146+
3147+void Emulation::receiveChar(int c)
3148+// process application unicode input to terminal
3149+// this is a trivial scanner
3150+{
3151+ c &= 0xff;
3152+ switch (c)
3153+ {
3154+ case '\b' : _currentScreen->backspace(); break;
3155+ case '\t' : _currentScreen->tab(); break;
3156+ case '\n' : _currentScreen->newLine(); break;
3157+ case '\r' : _currentScreen->toStartOfLine(); break;
3158+ case 0x07 : emit stateSet(NOTIFYBELL);
3159+ break;
3160+ default : _currentScreen->displayCharacter(c); break;
3161+ };
3162+}
3163+
3164+void Emulation::sendKeyEvent( QKeyEvent* ev )
3165+{
3166+ emit stateSet(NOTIFYNORMAL);
3167+
3168+ if (!ev->text().isEmpty())
3169+ { // A block of text
3170+ // Note that the text is proper unicode.
3171+ // We should do a conversion here
3172+ emit sendData(ev->text().toUtf8(),ev->text().length());
3173+ }
3174+}
3175+
3176+void Emulation::sendString(const char*,int)
3177+{
3178+ // default implementation does nothing
3179+}
3180+
3181+void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int /*eventType*/)
3182+{
3183+ // default implementation does nothing
3184+}
3185+
3186+/*
3187+ We are doing code conversion from locale to unicode first.
3188+TODO: Character composition from the old code. See #96536
3189+*/
3190+
3191+void Emulation::receiveData(const char* text, int length)
3192+{
3193+ emit stateSet(NOTIFYACTIVITY);
3194+
3195+ bufferedUpdate();
3196+
3197+ QString unicodeText = _decoder->toUnicode(text,length);
3198+
3199+ //send characters to terminal emulator
3200+ for (int i=0;i<unicodeText.length();i++)
3201+ receiveChar(unicodeText[i].unicode());
3202+
3203+ //look for z-modem indicator
3204+ //-- someone who understands more about z-modems that I do may be able to move
3205+ //this check into the above for loop?
3206+ for (int i=0;i<length;i++)
3207+ {
3208+ if (text[i] == '\030')
3209+ {
3210+ if ((length-i-1 > 3) && (strncmp(text+i+1, "B00", 3) == 0))
3211+ emit zmodemDetected();
3212+ }
3213+ }
3214+}
3215+
3216+//OLDER VERSION
3217+//This version of onRcvBlock was commented out because
3218+// a) It decoded incoming characters one-by-one, which is slow in the current version of Qt (4.2 tech preview)
3219+// b) It messed up decoding of non-ASCII characters, with the result that (for example) chinese characters
3220+// were not printed properly.
3221+//
3222+//There is something about stopping the _decoder if "we get a control code halfway a multi-byte sequence" (see below)
3223+//which hasn't been ported into the newer function (above). Hopefully someone who understands this better
3224+//can find an alternative way of handling the check.
3225+
3226+
3227+/*void Emulation::onRcvBlock(const char *s, int len)
3228+{
3229+ emit notifySessionState(NOTIFYACTIVITY);
3230+
3231+ bufferedUpdate();
3232+ for (int i = 0; i < len; i++)
3233+ {
3234+
3235+ QString result = _decoder->toUnicode(&s[i],1);
3236+ int reslen = result.length();
3237+
3238+ // If we get a control code halfway a multi-byte sequence
3239+ // we flush the _decoder and continue with the control code.
3240+ if ((s[i] < 32) && (s[i] > 0))
3241+ {
3242+ // Flush _decoder
3243+ while(!result.length())
3244+ result = _decoder->toUnicode(&s[i],1);
3245+ reslen = 1;
3246+ result.resize(reslen);
3247+ result[0] = QChar(s[i]);
3248+ }
3249+
3250+ for (int j = 0; j < reslen; j++)
3251+ {
3252+ if (result[j].characterategory() == QChar::Mark_NonSpacing)
3253+ _currentScreen->compose(result.mid(j,1));
3254+ else
3255+ onRcvChar(result[j].unicode());
3256+ }
3257+ if (s[i] == '\030')
3258+ {
3259+ if ((len-i-1 > 3) && (strncmp(s+i+1, "B00", 3) == 0))
3260+ emit zmodemDetected();
3261+ }
3262+ }
3263+}*/
3264+
3265+void Emulation::writeToStream( TerminalCharacterDecoder* _decoder ,
3266+ int startLine ,
3267+ int endLine)
3268+{
3269+ _currentScreen->writeLinesToStream(_decoder,startLine,endLine);
3270+}
3271+
3272+int Emulation::lineCount() const
3273+{
3274+ // sum number of lines currently on _screen plus number of lines in history
3275+ return _currentScreen->getLines() + _currentScreen->getHistLines();
3276+}
3277+
3278+#define BULK_TIMEOUT1 10
3279+#define BULK_TIMEOUT2 40
3280+
3281+void Emulation::showBulk()
3282+{
3283+ _bulkTimer1.stop();
3284+ _bulkTimer2.stop();
3285+
3286+ emit outputChanged();
3287+
3288+ _currentScreen->resetScrolledLines();
3289+ _currentScreen->resetDroppedLines();
3290+}
3291+
3292+void Emulation::bufferedUpdate()
3293+{
3294+ _bulkTimer1.setSingleShot(true);
3295+ _bulkTimer1.start(BULK_TIMEOUT1);
3296+ if (!_bulkTimer2.isActive())
3297+ {
3298+ _bulkTimer2.setSingleShot(true);
3299+ _bulkTimer2.start(BULK_TIMEOUT2);
3300+ }
3301+}
3302+
3303+char Emulation::eraseChar() const
3304+{
3305+ return '\b';
3306+}
3307+
3308+void Emulation::setImageSize(int lines, int columns)
3309+{
3310+ if ((lines < 1) || (columns < 1))
3311+ return;
3312+
3313+ QSize screenSize[2] = { QSize(_screen[0]->getColumns(),
3314+ _screen[0]->getLines()),
3315+ QSize(_screen[1]->getColumns(),
3316+ _screen[1]->getLines()) };
3317+ QSize newSize(columns,lines);
3318+
3319+ if (newSize == screenSize[0] && newSize == screenSize[1])
3320+ return;
3321+
3322+ _screen[0]->resizeImage(lines,columns);
3323+ _screen[1]->resizeImage(lines,columns);
3324+
3325+ emit imageSizeChanged(lines,columns);
3326+
3327+ bufferedUpdate();
3328+}
3329+
3330+QSize Emulation::imageSize() const
3331+{
3332+ return QSize(_currentScreen->getColumns(), _currentScreen->getLines());
3333+}
3334+
3335+ushort ExtendedCharTable::extendedCharHash(ushort* unicodePoints , ushort length) const
3336+{
3337+ ushort hash = 0;
3338+ for ( ushort i = 0 ; i < length ; i++ )
3339+ {
3340+ hash = 31*hash + unicodePoints[i];
3341+ }
3342+ return hash;
3343+}
3344+bool ExtendedCharTable::extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const
3345+{
3346+ ushort* entry = extendedCharTable[hash];
3347+
3348+ // compare given length with stored sequence length ( given as the first ushort in the
3349+ // stored buffer )
3350+ if ( entry == 0 || entry[0] != length )
3351+ return false;
3352+ // if the lengths match, each character must be checked. the stored buffer starts at
3353+ // entry[1]
3354+ for ( int i = 0 ; i < length ; i++ )
3355+ {
3356+ if ( entry[i+1] != unicodePoints[i] )
3357+ return false;
3358+ }
3359+ return true;
3360+}
3361+ushort ExtendedCharTable::createExtendedChar(ushort* unicodePoints , ushort length)
3362+{
3363+ // look for this sequence of points in the table
3364+ ushort hash = extendedCharHash(unicodePoints,length);
3365+
3366+ // check existing entry for match
3367+ while ( extendedCharTable.contains(hash) )
3368+ {
3369+ if ( extendedCharMatch(hash,unicodePoints,length) )
3370+ {
3371+ // this sequence already has an entry in the table,
3372+ // return its hash
3373+ return hash;
3374+ }
3375+ else
3376+ {
3377+ // if hash is already used by another, different sequence of unicode character
3378+ // points then try next hash
3379+ hash++;
3380+ }
3381+ }
3382+
3383+
3384+ // add the new sequence to the table and
3385+ // return that index
3386+ ushort* buffer = new ushort[length+1];
3387+ buffer[0] = length;
3388+ for ( int i = 0 ; i < length ; i++ )
3389+ buffer[i+1] = unicodePoints[i];
3390+
3391+ extendedCharTable.insert(hash,buffer);
3392+
3393+ return hash;
3394+}
3395+
3396+ushort* ExtendedCharTable::lookupExtendedChar(ushort hash , ushort& length) const
3397+{
3398+ // lookup index in table and if found, set the length
3399+ // argument and return a pointer to the character sequence
3400+
3401+ ushort* buffer = extendedCharTable[hash];
3402+ if ( buffer )
3403+ {
3404+ length = buffer[0];
3405+ return buffer+1;
3406+ }
3407+ else
3408+ {
3409+ length = 0;
3410+ return 0;
3411+ }
3412+}
3413+
3414+ExtendedCharTable::ExtendedCharTable()
3415+{
3416+}
3417+ExtendedCharTable::~ExtendedCharTable()
3418+{
3419+ // free all allocated character buffers
3420+ QHashIterator<ushort,ushort*> iter(extendedCharTable);
3421+ while ( iter.hasNext() )
3422+ {
3423+ iter.next();
3424+ delete[] iter.value();
3425+ }
3426+}
3427+
3428+// global instance
3429+ExtendedCharTable ExtendedCharTable::instance;
3430+
3431+
3432+//#include "Emulation.moc"
3433+
3434
3435=== added file 'src/plugin/konsole/Emulation.h'
3436--- src/plugin/konsole/Emulation.h 1970-01-01 00:00:00 +0000
3437+++ src/plugin/konsole/Emulation.h 2014-05-06 21:50:22 +0000
3438@@ -0,0 +1,467 @@
3439+/*
3440+ This file is part of Konsole, an X terminal.
3441+
3442+ Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
3443+ Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
3444+
3445+ This program is free software; you can redistribute it and/or modify
3446+ it under the terms of the GNU General Public License as published by
3447+ the Free Software Foundation; either version 2 of the License, or
3448+ (at your option) any later version.
3449+
3450+ This program is distributed in the hope that it will be useful,
3451+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3452+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3453+ GNU General Public License for more details.
3454+
3455+ You should have received a copy of the GNU General Public License
3456+ along with this program; if not, write to the Free Software
3457+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
3458+ 02110-1301 USA.
3459+*/
3460+
3461+#ifndef EMULATION_H
3462+#define EMULATION_H
3463+
3464+// System
3465+#include <stdio.h>
3466+
3467+// Qt
3468+#include <QtGui/QKeyEvent>
3469+//#include <QPointer>
3470+#include <QtCore/QTextCodec>
3471+#include <QtCore/QTextStream>
3472+#include <QtCore/QTimer>
3473+
3474+// Konsole
3475+//#include "konsole_export.h"
3476+#define KONSOLEPRIVATE_EXPORT
3477+
3478+class KeyboardTranslator;
3479+class HistoryType;
3480+class Screen;
3481+class ScreenWindow;
3482+class TerminalCharacterDecoder;
3483+
3484+/**
3485+ * This enum describes the available states which
3486+ * the terminal emulation may be set to.
3487+ *
3488+ * These are the values used by Emulation::stateChanged()
3489+ */
3490+enum
3491+{
3492+ /** The emulation is currently receiving user input. */
3493+ NOTIFYNORMAL=0,
3494+ /**
3495+ * The terminal program has triggered a bell event
3496+ * to get the user's attention.
3497+ */
3498+ NOTIFYBELL=1,
3499+ /**
3500+ * The emulation is currently receiving data from its
3501+ * terminal input.
3502+ */
3503+ NOTIFYACTIVITY=2,
3504+
3505+ // unused here?
3506+ NOTIFYSILENCE=3
3507+};
3508+
3509+/**
3510+ * Base class for terminal emulation back-ends.
3511+ *
3512+ * The back-end is responsible for decoding an incoming character stream and
3513+ * producing an output image of characters.
3514+ *
3515+ * When input from the terminal is received, the receiveData() slot should be called with
3516+ * the data which has arrived. The emulation will process the data and update the
3517+ * screen image accordingly. The codec used to decode the incoming character stream
3518+ * into the unicode characters used internally can be specified using setCodec()
3519+ *
3520+ * The size of the screen image can be specified by calling setImageSize() with the
3521+ * desired number of lines and columns. When new lines are added, old content
3522+ * is moved into a history store, which can be set by calling setHistory().
3523+ *
3524+ * The screen image can be accessed by creating a ScreenWindow onto this emulation
3525+ * by calling createWindow(). Screen windows provide access to a section of the
3526+ * output. Each screen window covers the same number of lines and columns as the
3527+ * image size returned by imageSize(). The screen window can be moved up and down
3528+ * and provides transparent access to both the current on-screen image and the
3529+ * previous output. The screen windows emit an outputChanged signal
3530+ * when the section of the image they are looking at changes.
3531+ * Graphical views can then render the contents of a screen window, listening for notifications
3532+ * of output changes from the screen window which they are associated with and updating
3533+ * accordingly.
3534+ *
3535+ * The emulation also is also responsible for converting input from the connected views such
3536+ * as keypresses and mouse activity into a character string which can be sent
3537+ * to the terminal program. Key presses can be processed by calling the sendKeyEvent() slot,
3538+ * while mouse events can be processed using the sendMouseEvent() slot. When the character
3539+ * stream has been produced, the emulation will emit a sendData() signal with a pointer
3540+ * to the character buffer. This data should be fed to the standard input of the terminal
3541+ * process. The translation of key presses into an output character stream is performed
3542+ * using a lookup in a set of key bindings which map key sequences to output
3543+ * character sequences. The name of the key bindings set used can be specified using
3544+ * setKeyBindings()
3545+ *
3546+ * The emulation maintains certain state information which changes depending on the
3547+ * input received. The emulation can be reset back to its starting state by calling
3548+ * reset().
3549+ *
3550+ * The emulation also maintains an activity state, which specifies whether
3551+ * terminal is currently active ( when data is received ), normal
3552+ * ( when the terminal is idle or receiving user input ) or trying
3553+ * to alert the user ( also known as a "Bell" event ). The stateSet() signal
3554+ * is emitted whenever the activity state is set. This can be used to determine
3555+ * how long the emulation has been active/idle for and also respond to
3556+ * a 'bell' event in different ways.
3557+ */
3558+class KONSOLEPRIVATE_EXPORT Emulation : public QObject
3559+{
3560+Q_OBJECT
3561+
3562+public:
3563+
3564+ /** Constructs a new terminal emulation */
3565+ Emulation();
3566+ ~Emulation();
3567+
3568+ /**
3569+ * Creates a new window onto the output from this emulation. The contents
3570+ * of the window are then rendered by views which are set to use this window using the
3571+ * TerminalDisplay::setScreenWindow() method.
3572+ */
3573+ ScreenWindow* createWindow();
3574+
3575+ /** Returns the size of the screen image which the emulation produces */
3576+ QSize imageSize() const;
3577+
3578+ /**
3579+ * Returns the total number of lines, including those stored in the history.
3580+ */
3581+ int lineCount() const;
3582+
3583+ /**
3584+ * Sets the history store used by this emulation. When new lines
3585+ * are added to the output, older lines at the top of the screen are transferred to a history
3586+ * store.
3587+ *
3588+ * The number of lines which are kept and the storage location depend on the
3589+ * type of store.
3590+ */
3591+ void setHistory(const HistoryType&);
3592+ /** Returns the history store used by this emulation. See setHistory() */
3593+ const HistoryType& history() const;
3594+ /** Clears the history scroll. */
3595+ void clearHistory();
3596+
3597+ /**
3598+ * Copies the output history from @p startLine to @p endLine
3599+ * into @p stream, using @p decoder to convert the terminal
3600+ * characters into text.
3601+ *
3602+ * @param decoder A decoder which converts lines of terminal characters with
3603+ * appearance attributes into output text. PlainTextDecoder is the most commonly
3604+ * used decoder.
3605+ * @param startLine Index of first line to copy
3606+ * @param endLine Index of last line to copy
3607+ */
3608+ virtual void writeToStream(TerminalCharacterDecoder* decoder,int startLine,int endLine);
3609+
3610+ /** Returns the codec used to decode incoming characters. See setCodec() */
3611+ const QTextCodec* codec() const { return _codec; }
3612+ /** Sets the codec used to decode incoming characters. */
3613+ void setCodec(const QTextCodec*);
3614+
3615+ /**
3616+ * Convenience method.
3617+ * Returns true if the current codec used to decode incoming
3618+ * characters is UTF-8
3619+ */
3620+ bool utf8() const
3621+ { Q_ASSERT(_codec); return _codec->mibEnum() == 106; }
3622+
3623+
3624+ /** TODO Document me */
3625+ virtual char eraseChar() const;
3626+
3627+ /**
3628+ * Sets the key bindings used to key events
3629+ * ( received through sendKeyEvent() ) into character
3630+ * streams to send to the terminal.
3631+ */
3632+ void setKeyBindings(const QString& name);
3633+ /**
3634+ * Returns the name of the emulation's current key bindings.
3635+ * See setKeyBindings()
3636+ */
3637+ QString keyBindings() const;
3638+
3639+ /**
3640+ * Copies the current image into the history and clears the screen.
3641+ */
3642+ virtual void clearEntireScreen() =0;
3643+
3644+ /** Resets the state of the terminal. */
3645+ virtual void reset() =0;
3646+
3647+ /**
3648+ * Returns true if the active terminal program wants
3649+ * mouse input events.
3650+ *
3651+ * The programUsesMouseChanged() signal is emitted when this
3652+ * changes.
3653+ */
3654+ bool programUsesMouse() const;
3655+
3656+public slots:
3657+
3658+ /** Change the size of the emulation's image */
3659+ virtual void setImageSize(int lines, int columns);
3660+
3661+ /**
3662+ * Interprets a sequence of characters and sends the result to the terminal.
3663+ * This is equivalent to calling sendKeyEvent() for each character in @p text in succession.
3664+ */
3665+ virtual void sendText(const QString& text) = 0;
3666+
3667+ /**
3668+ * Interprets a key press event and emits the sendData() signal with
3669+ * the resulting character stream.
3670+ */
3671+ virtual void sendKeyEvent(QKeyEvent*);
3672+
3673+ /**
3674+ * Converts information about a mouse event into an xterm-compatible escape
3675+ * sequence and emits the character sequence via sendData()
3676+ */
3677+ virtual void sendMouseEvent(int buttons, int column, int line, int eventType);
3678+
3679+ /**
3680+ * Sends a string of characters to the foreground terminal process.
3681+ *
3682+ * @param string The characters to send.
3683+ * @param length Length of @p string or if set to a negative value, @p string will
3684+ * be treated as a null-terminated string and its length will be determined automatically.
3685+ */
3686+ virtual void sendString(const char* string, int length = -1) = 0;
3687+
3688+ /**
3689+ * Processes an incoming stream of characters. receiveData() decodes the incoming
3690+ * character buffer using the current codec(), and then calls receiveChar() for
3691+ * each unicode character in the resulting buffer.
3692+ *
3693+ * receiveData() also starts a timer which causes the outputChanged() signal
3694+ * to be emitted when it expires. The timer allows multiple updates in quick
3695+ * succession to be buffered into a single outputChanged() signal emission.
3696+ *
3697+ * @param buffer A string of characters received from the terminal program.
3698+ * @param len The length of @p buffer
3699+ */
3700+ void receiveData(const char* buffer,int len);
3701+
3702+signals:
3703+
3704+ /**
3705+ * Emitted when a buffer of data is ready to send to the
3706+ * standard input of the terminal.
3707+ *
3708+ * @param data The buffer of data ready to be sent
3709+ * @param len The length of @p data in bytes
3710+ */
3711+ void sendData(const char* data,int len);
3712+
3713+ /**
3714+ * Requests that sending of input to the emulation
3715+ * from the terminal process be suspended or resumed.
3716+ *
3717+ * @param suspend If true, requests that sending of
3718+ * input from the terminal process' stdout be
3719+ * suspended. Otherwise requests that sending of
3720+ * input be resumed.
3721+ */
3722+ void lockPtyRequest(bool suspend);
3723+
3724+ /**
3725+ * Requests that the pty used by the terminal process
3726+ * be set to UTF 8 mode.
3727+ *
3728+ * TODO: More documentation
3729+ */
3730+ void useUtf8Request(bool);
3731+
3732+ /**
3733+ * Emitted when the activity state of the emulation is set.
3734+ *
3735+ * @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY
3736+ * or NOTIFYBELL
3737+ */
3738+ void stateSet(int state);
3739+
3740+ /** TODO Document me */
3741+ void zmodemDetected();
3742+
3743+
3744+ /**
3745+ * Requests that the color of the text used
3746+ * to represent the tabs associated with this
3747+ * emulation be changed. This is a Konsole-specific
3748+ * extension from pre-KDE 4 times.
3749+ *
3750+ * TODO: Document how the parameter works.
3751+ */
3752+ void changeTabTextColorRequest(int color);
3753+
3754+ /**
3755+ * This is emitted when the program running in the shell indicates whether or
3756+ * not it is interested in mouse events.
3757+ *
3758+ * @param usesMouse This will be true if the program wants to be informed about
3759+ * mouse events or false otherwise.
3760+ */
3761+ void programUsesMouseChanged(bool usesMouse);
3762+
3763+ /**
3764+ * Emitted when the contents of the screen image change.
3765+ * The emulation buffers the updates from successive image changes,
3766+ * and only emits outputChanged() at sensible intervals when
3767+ * there is a lot of terminal activity.
3768+ *
3769+ * Normally there is no need for objects other than the screen windows
3770+ * created with createWindow() to listen for this signal.
3771+ *
3772+ * ScreenWindow objects created using createWindow() will emit their
3773+ * own outputChanged() signal in response to this signal.
3774+ */
3775+ void outputChanged();
3776+
3777+ /**
3778+ * Emitted when the program running in the terminal wishes to update the
3779+ * session's title. This also allows terminal programs to customize other
3780+ * aspects of the terminal emulation display.
3781+ *
3782+ * This signal is emitted when the escape sequence "\033]ARG;VALUE\007"
3783+ * is received in the input string, where ARG is a number specifying what
3784+ * should change and VALUE is a string specifying the new value.
3785+ *
3786+ * TODO: The name of this method is not very accurate since this method
3787+ * is used to perform a whole range of tasks besides just setting
3788+ * the user-title of the session.
3789+ *
3790+ * @param title Specifies what to change.
3791+ * <ul>
3792+ * <li>0 - Set window icon text and session title to @p newTitle</li>
3793+ * <li>1 - Set window icon text to @p newTitle</li>
3794+ * <li>2 - Set session title to @p newTitle</li>
3795+ * <li>11 - Set the session's default background color to @p newTitle,
3796+ * where @p newTitle can be an HTML-style string ("#RRGGBB") or a named
3797+ * color (eg 'red', 'blue').
3798+ * See http://doc.trolltech.com/4.2/qcolor.html#setNamedColor for more
3799+ * details.
3800+ * </li>
3801+ * <li>31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)</li>
3802+ * <li>32 - Sets the icon associated with the session. @p newTitle is the name
3803+ * of the icon to use, which can be the name of any icon in the current KDE icon
3804+ * theme (eg: 'konsole', 'kate', 'folder_home')</li>
3805+ * </ul>
3806+ * @param newTitle Specifies the new title
3807+ */
3808+
3809+ void titleChanged(int title,const QString& newTitle);
3810+
3811+ /**
3812+ * Emitted when the program running in the terminal changes the
3813+ * screen size.
3814+ */
3815+ void imageSizeChanged(int lineCount , int columnCount);
3816+
3817+ /**
3818+ * Emitted when the terminal program requests to change various properties
3819+ * of the terminal display.
3820+ *
3821+ * A profile change command occurs when a special escape sequence, followed
3822+ * by a string containing a series of name and value pairs is received.
3823+ * This string can be parsed using a ProfileCommandParser instance.
3824+ *
3825+ * @param text A string expected to contain a series of key and value pairs in
3826+ * the form: name=value;name2=value2 ...
3827+ */
3828+ void profileChangeCommandReceived(const QString& text);
3829+
3830+ /**
3831+ * Emitted when a flow control key combination ( Ctrl+S or Ctrl+Q ) is pressed.
3832+ * @param suspendKeyPressed True if Ctrl+S was pressed to suspend output or Ctrl+Q to
3833+ * resume output.
3834+ */
3835+ void flowControlKeyPressed(bool suspendKeyPressed);
3836+
3837+protected:
3838+ virtual void setMode(int mode) = 0;
3839+ virtual void resetMode(int mode) = 0;
3840+
3841+ /**
3842+ * Processes an incoming character. See receiveData()
3843+ * @p ch A unicode character code.
3844+ */
3845+ virtual void receiveChar(int ch);
3846+
3847+ /**
3848+ * Sets the active screen. The terminal has two screens, primary and alternate.
3849+ * The primary screen is used by default. When certain interactive programs such
3850+ * as Vim are run, they trigger a switch to the alternate screen.
3851+ *
3852+ * @param index 0 to switch to the primary screen, or 1 to switch to the alternate screen
3853+ */
3854+ void setScreen(int index);
3855+
3856+ enum EmulationCodec
3857+ {
3858+ LocaleCodec = 0,
3859+ Utf8Codec = 1
3860+ };
3861+ void setCodec(EmulationCodec codec); // codec number, 0 = locale, 1=utf8
3862+
3863+
3864+ QList<ScreenWindow*> _windows;
3865+
3866+ Screen* _currentScreen; // pointer to the screen which is currently active,
3867+ // this is one of the elements in the screen[] array
3868+
3869+ Screen* _screen[2]; // 0 = primary screen ( used by most programs, including the shell
3870+ // scrollbars are enabled in this mode )
3871+ // 1 = alternate ( used by vi , emacs etc.
3872+ // scrollbars are not enabled in this mode )
3873+
3874+
3875+ //decodes an incoming C-style character stream into a unicode QString using
3876+ //the current text codec. (this allows for rendering of non-ASCII characters in text files etc.)
3877+ const QTextCodec* _codec;
3878+ QTextDecoder* _decoder;
3879+ const KeyboardTranslator* _keyTranslator; // the keyboard layout
3880+
3881+protected slots:
3882+ /**
3883+ * Schedules an update of attached views.
3884+ * Repeated calls to bufferedUpdate() in close succession will result in only a single update,
3885+ * much like the Qt buffered update of widgets.
3886+ */
3887+ void bufferedUpdate();
3888+
3889+private slots:
3890+
3891+ // triggered by timer, causes the emulation to send an updated screen image to each
3892+ // view
3893+ void showBulk();
3894+
3895+ void usesMouseChanged(bool usesMouse);
3896+
3897+private:
3898+ bool _usesMouse;
3899+ QTimer _bulkTimer1;
3900+ QTimer _bulkTimer2;
3901+
3902+};
3903+
3904+
3905+#endif // ifndef EMULATION_H
3906
3907=== added file 'src/plugin/konsole/ExtendedDefaultTranslator.h'
3908--- src/plugin/konsole/ExtendedDefaultTranslator.h 1970-01-01 00:00:00 +0000
3909+++ src/plugin/konsole/ExtendedDefaultTranslator.h 2014-05-06 21:50:22 +0000
3910@@ -0,0 +1,74 @@
3911+"keyboard \"Default (XFree 4)\""
3912+"key Escape : \"\\E\""
3913+"key Tab -Shift : \"\\t\"\n"
3914+"key Tab +Shift+Ansi : \"\\E[Z\"\n"
3915+"key Tab +Shift-Ansi : \"\\t\"\n"
3916+"key Backtab +Ansi : \"\\E[Z\"\n"
3917+"key Backtab -Ansi : \"\\t\"\n"
3918+"key Return-Shift-NewLine : \"\\r\"\n"
3919+"key Return-Shift+NewLine : \"\\r\\n\"\n"
3920+"key Return+Shift : \"\\EOM\"\n"
3921+"key Backspace : \"\\x7f\"\n"
3922+"key Up -Shift-Ansi : \"\\EA\"\n"
3923+"key Down -Shift-Ansi : \"\\EB\"\n"
3924+"key Right-Shift-Ansi : \"\\EC\"\n"
3925+"key Left -Shift-Ansi : \"\\ED\"\n"
3926+"key Up -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOA\"\n"
3927+"key Down -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOB\"\n"
3928+"key Right -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOC\"\n"
3929+"key Left -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOD\"\n"
3930+"key Up -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[A\"\n"
3931+"key Down -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[B\"\n"
3932+"key Right -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[C\"\n"
3933+"key Left -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[D\"\n"
3934+"key Up -Shift+AnyMod+Ansi : \"\\E[1;*A\"\n"
3935+"key Down -Shift+AnyMod+Ansi : \"\\E[1;*B\"\n"
3936+"key Right -Shift+AnyMod+Ansi : \"\\E[1;*C\"\n"
3937+"key Left -Shift+AnyMod+Ansi : \"\\E[1;*D\"\n"
3938+"key Enter+NewLine : \"\\r\\n\"\n"
3939+"key Enter-NewLine : \"\\r\"\n"
3940+"key Home -AnyMod -AppCuKeys : \"\\E[H\" \n"
3941+"key End -AnyMod -AppCuKeys : \"\\E[F\" \n"
3942+"key Home -AnyMod +AppCuKeys : \"\\EOH\" \n"
3943+"key End -AnyMod +AppCuKeys : \"\\EOF\" \n"
3944+"key Home +AnyMod : \"\\E[1;*H\"\n"
3945+"key End +AnyMod : \"\\E[1;*F\"\n"
3946+"key Insert -AnyMod : \"\\E[2~\"\n"
3947+"key Delete -AnyMod : \"\\E[3~\"\n"
3948+"key Insert +AnyMod : \"\\E[2;*~\"\n"
3949+"key Delete +AnyMod : \"\\E[3;*~\"\n"
3950+"key Prior -Shift-AnyMod : \"\\E[5~\"\n"
3951+"key Next -Shift-AnyMod : \"\\E[6~\"\n"
3952+"key Prior -Shift+AnyMod : \"\\E[5;*~\"\n"
3953+"key Next -Shift+AnyMod : \"\\E[6;*~\"\n"
3954+"key F1 -AnyMod : \"\\EOP\"\n"
3955+"key F2 -AnyMod : \"\\EOQ\"\n"
3956+"key F3 -AnyMod : \"\\EOR\"\n"
3957+"key F4 -AnyMod : \"\\EOS\"\n"
3958+"key F5 -AnyMod : \"\\E[15~\"\n"
3959+"key F6 -AnyMod : \"\\E[17~\"\n"
3960+"key F7 -AnyMod : \"\\E[18~\"\n"
3961+"key F8 -AnyMod : \"\\E[19~\"\n"
3962+"key F9 -AnyMod : \"\\E[20~\"\n"
3963+"key F10 -AnyMod : \"\\E[21~\"\n"
3964+"key F11 -AnyMod : \"\\E[23~\"\n"
3965+"key F12 -AnyMod : \"\\E[24~\"\n"
3966+"key F1 +AnyMod : \"\\EO*P\"\n"
3967+"key F2 +AnyMod : \"\\EO*Q\"\n"
3968+"key F3 +AnyMod : \"\\EO*R\"\n"
3969+"key F4 +AnyMod : \"\\EO*S\"\n"
3970+"key F5 +AnyMod : \"\\E[15;*~\"\n"
3971+"key F6 +AnyMod : \"\\E[17;*~\"\n"
3972+"key F7 +AnyMod : \"\\E[18;*~\"\n"
3973+"key F8 +AnyMod : \"\\E[19;*~\"\n"
3974+"key F9 +AnyMod : \"\\E[20;*~\"\n"
3975+"key F10 +AnyMod : \"\\E[21;*~\"\n"
3976+"key F11 +AnyMod : \"\\E[23;*~\"\n"
3977+"key F12 +AnyMod : \"\\E[24;*~\"\n"
3978+"key Space +Control : \"\\x00\"\n"
3979+"key Up +Shift-AppScreen : scrollLineUp\n"
3980+"key Prior +Shift-AppScreen : scrollPageUp\n"
3981+"key Down +Shift-AppScreen : scrollLineDown\n"
3982+"key Next +Shift-AppScreen : scrollPageDown\n"
3983+"key ScrollLock : scrollLock\n"
3984+"\0"
3985
3986=== added file 'src/plugin/konsole/Filter.cpp'
3987--- src/plugin/konsole/Filter.cpp 1970-01-01 00:00:00 +0000
3988+++ src/plugin/konsole/Filter.cpp 2014-05-06 21:50:22 +0000
3989@@ -0,0 +1,542 @@
3990+/*
3991+ Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
3992+
3993+ This program is free software; you can redistribute it and/or modify
3994+ it under the terms of the GNU General Public License as published by
3995+ the Free Software Foundation; either version 2 of the License, or
3996+ (at your option) any later version.
3997+
3998+ This program is distributed in the hope that it will be useful,
3999+ but WITHOUT ANY WARRANTY; without even the implied warranty of
4000+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4001+ GNU General Public License for more details.
4002+
4003+ You should have received a copy of the GNU General Public License
4004+ along with this program; if not, write to the Free Software
4005+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4006+ 02110-1301 USA.
4007+*/
4008+
4009+// Own
4010+#include "Filter.h"
4011+
4012+// System
4013+#include <iostream>
4014+
4015+// Qt
4016+#include <QtWidgets/QAction>
4017+#include <QtWidgets/QApplication>
4018+#include <QtGui/QClipboard>
4019+#include <QtCore/QString>
4020+#include <QtCore/QTextStream>
4021+#include <QtCore/QSharedData>
4022+#include <QtCore/QFile>
4023+#include <QDesktopServices>
4024+#include <QUrl>
4025+
4026+// KDE
4027+//#include <KLocale>
4028+//#include <KRun>
4029+
4030+// Konsole
4031+#include "TerminalCharacterDecoder.h"
4032+#include "konsole_wcwidth.h"
4033+
4034+
4035+FilterChain::~FilterChain()
4036+{
4037+ QMutableListIterator<Filter*> iter(*this);
4038+
4039+ while ( iter.hasNext() )
4040+ {
4041+ Filter* filter = iter.next();
4042+ iter.remove();
4043+ delete filter;
4044+ }
4045+}
4046+
4047+void FilterChain::addFilter(Filter* filter)
4048+{
4049+ append(filter);
4050+}
4051+void FilterChain::removeFilter(Filter* filter)
4052+{
4053+ removeAll(filter);
4054+}
4055+bool FilterChain::containsFilter(Filter* filter)
4056+{
4057+ return contains(filter);
4058+}
4059+void FilterChain::reset()
4060+{
4061+ QListIterator<Filter*> iter(*this);
4062+ while (iter.hasNext())
4063+ iter.next()->reset();
4064+}
4065+void FilterChain::setBuffer(const QString* buffer , const QList<int>* linePositions)
4066+{
4067+ QListIterator<Filter*> iter(*this);
4068+ while (iter.hasNext())
4069+ iter.next()->setBuffer(buffer,linePositions);
4070+}
4071+void FilterChain::process()
4072+{
4073+ QListIterator<Filter*> iter(*this);
4074+ while (iter.hasNext())
4075+ iter.next()->process();
4076+}
4077+void FilterChain::clear()
4078+{
4079+ QList<Filter*>::clear();
4080+}
4081+Filter::HotSpot* FilterChain::hotSpotAt(int line , int column) const
4082+{
4083+ QListIterator<Filter*> iter(*this);
4084+ while (iter.hasNext())
4085+ {
4086+ Filter* filter = iter.next();
4087+ Filter::HotSpot* spot = filter->hotSpotAt(line,column);
4088+ if ( spot != 0 )
4089+ {
4090+ return spot;
4091+ }
4092+ }
4093+
4094+ return 0;
4095+}
4096+
4097+QList<Filter::HotSpot*> FilterChain::hotSpots() const
4098+{
4099+ QList<Filter::HotSpot*> list;
4100+ QListIterator<Filter*> iter(*this);
4101+ while (iter.hasNext())
4102+ {
4103+ Filter* filter = iter.next();
4104+ list << filter->hotSpots();
4105+ }
4106+ return list;
4107+}
4108+//QList<Filter::HotSpot*> FilterChain::hotSpotsAtLine(int line) const;
4109+
4110+TerminalImageFilterChain::TerminalImageFilterChain()
4111+: _buffer(0)
4112+, _linePositions(0)
4113+{
4114+}
4115+
4116+TerminalImageFilterChain::~TerminalImageFilterChain()
4117+{
4118+ delete _buffer;
4119+ delete _linePositions;
4120+}
4121+
4122+void TerminalImageFilterChain::setImage(const Character* const image , int lines , int columns, const QVector<LineProperty>& lineProperties)
4123+{
4124+ if (empty())
4125+ return;
4126+
4127+ // reset all filters and hotspots
4128+ reset();
4129+
4130+ PlainTextDecoder decoder;
4131+ decoder.setTrailingWhitespace(false);
4132+
4133+ // setup new shared buffers for the filters to process on
4134+ QString* newBuffer = new QString();
4135+ QList<int>* newLinePositions = new QList<int>();
4136+ setBuffer( newBuffer , newLinePositions );
4137+
4138+ // free the old buffers
4139+ delete _buffer;
4140+ delete _linePositions;
4141+
4142+ _buffer = newBuffer;
4143+ _linePositions = newLinePositions;
4144+
4145+ QTextStream lineStream(_buffer);
4146+ decoder.begin(&lineStream);
4147+
4148+ for (int i=0 ; i < lines ; i++)
4149+ {
4150+ _linePositions->append(_buffer->length());
4151+ decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT);
4152+
4153+ // pretend that each line ends with a newline character.
4154+ // this prevents a link that occurs at the end of one line
4155+ // being treated as part of a link that occurs at the start of the next line
4156+ //
4157+ // the downside is that links which are spread over more than one line are not
4158+ // highlighted.
4159+ //
4160+ // TODO - Use the "line wrapped" attribute associated with lines in a
4161+ // terminal image to avoid adding this imaginary character for wrapped
4162+ // lines
4163+ if ( !(lineProperties.value(i,LINE_DEFAULT) & LINE_WRAPPED) )
4164+ lineStream << QChar('\n');
4165+ }
4166+ decoder.end();
4167+}
4168+
4169+Filter::Filter() :
4170+_linePositions(0),
4171+_buffer(0)
4172+{
4173+}
4174+
4175+Filter::~Filter()
4176+{
4177+ QListIterator<HotSpot*> iter(_hotspotList);
4178+ while (iter.hasNext())
4179+ {
4180+ delete iter.next();
4181+ }
4182+}
4183+void Filter::reset()
4184+{
4185+ _hotspots.clear();
4186+ _hotspotList.clear();
4187+}
4188+
4189+void Filter::setBuffer(const QString* buffer , const QList<int>* linePositions)
4190+{
4191+ _buffer = buffer;
4192+ _linePositions = linePositions;
4193+}
4194+
4195+void Filter::getLineColumn(int position , int& startLine , int& startColumn)
4196+{
4197+ Q_ASSERT( _linePositions );
4198+ Q_ASSERT( _buffer );
4199+
4200+
4201+ for (int i = 0 ; i < _linePositions->count() ; i++)
4202+ {
4203+ int nextLine = 0;
4204+
4205+ if ( i == _linePositions->count()-1 )
4206+ nextLine = _buffer->length() + 1;
4207+ else
4208+ nextLine = _linePositions->value(i+1);
4209+
4210+ if ( _linePositions->value(i) <= position && position < nextLine )
4211+ {
4212+ startLine = i;
4213+ startColumn = string_width(buffer()->mid(_linePositions->value(i),position - _linePositions->value(i)));
4214+ return;
4215+ }
4216+ }
4217+}
4218+
4219+
4220+/*void Filter::addLine(const QString& text)
4221+{
4222+ _linePositions << _buffer.length();
4223+ _buffer.append(text);
4224+}*/
4225+
4226+const QString* Filter::buffer()
4227+{
4228+ return _buffer;
4229+}
4230+Filter::HotSpot::~HotSpot()
4231+{
4232+}
4233+void Filter::addHotSpot(HotSpot* spot)
4234+{
4235+ _hotspotList << spot;
4236+
4237+ for (int line = spot->startLine() ; line <= spot->endLine() ; line++)
4238+ {
4239+ _hotspots.insert(line,spot);
4240+ }
4241+}
4242+QList<Filter::HotSpot*> Filter::hotSpots() const
4243+{
4244+ return _hotspotList;
4245+}
4246+QList<Filter::HotSpot*> Filter::hotSpotsAtLine(int line) const
4247+{
4248+ return _hotspots.values(line);
4249+}
4250+
4251+Filter::HotSpot* Filter::hotSpotAt(int line , int column) const
4252+{
4253+ QListIterator<HotSpot*> spotIter(_hotspots.values(line));
4254+
4255+ while (spotIter.hasNext())
4256+ {
4257+ HotSpot* spot = spotIter.next();
4258+
4259+ if ( spot->startLine() == line && spot->startColumn() > column )
4260+ continue;
4261+ if ( spot->endLine() == line && spot->endColumn() < column )
4262+ continue;
4263+
4264+ return spot;
4265+ }
4266+
4267+ return 0;
4268+}
4269+
4270+Filter::HotSpot::HotSpot(int startLine , int startColumn , int endLine , int endColumn)
4271+ : _startLine(startLine)
4272+ , _startColumn(startColumn)
4273+ , _endLine(endLine)
4274+ , _endColumn(endColumn)
4275+ , _type(NotSpecified)
4276+{
4277+}
4278+QString Filter::HotSpot::tooltip() const
4279+{
4280+ return QString();
4281+}
4282+QList<QAction*> Filter::HotSpot::actions()
4283+{
4284+ return QList<QAction*>();
4285+}
4286+int Filter::HotSpot::startLine() const
4287+{
4288+ return _startLine;
4289+}
4290+int Filter::HotSpot::endLine() const
4291+{
4292+ return _endLine;
4293+}
4294+int Filter::HotSpot::startColumn() const
4295+{
4296+ return _startColumn;
4297+}
4298+int Filter::HotSpot::endColumn() const
4299+{
4300+ return _endColumn;
4301+}
4302+Filter::HotSpot::Type Filter::HotSpot::type() const
4303+{
4304+ return _type;
4305+}
4306+void Filter::HotSpot::setType(Type type)
4307+{
4308+ _type = type;
4309+}
4310+
4311+RegExpFilter::RegExpFilter()
4312+{
4313+}
4314+
4315+RegExpFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
4316+ : Filter::HotSpot(startLine,startColumn,endLine,endColumn)
4317+{
4318+ setType(Marker);
4319+}
4320+
4321+void RegExpFilter::HotSpot::activate(QObject*)
4322+{
4323+}
4324+
4325+void RegExpFilter::HotSpot::setCapturedTexts(const QStringList& texts)
4326+{
4327+ _capturedTexts = texts;
4328+}
4329+QStringList RegExpFilter::HotSpot::capturedTexts() const
4330+{
4331+ return _capturedTexts;
4332+}
4333+
4334+void RegExpFilter::setRegExp(const QRegExp& regExp)
4335+{
4336+ _searchText = regExp;
4337+}
4338+QRegExp RegExpFilter::regExp() const
4339+{
4340+ return _searchText;
4341+}
4342+/*void RegExpFilter::reset(int)
4343+{
4344+ _buffer = QString();
4345+}*/
4346+void RegExpFilter::process()
4347+{
4348+ int pos = 0;
4349+ const QString* text = buffer();
4350+
4351+ Q_ASSERT( text );
4352+
4353+ // ignore any regular expressions which match an empty string.
4354+ // otherwise the while loop below will run indefinitely
4355+ static const QString emptyString("");
4356+ if ( _searchText.exactMatch(emptyString) )
4357+ return;
4358+
4359+ while(pos >= 0)
4360+ {
4361+ pos = _searchText.indexIn(*text,pos);
4362+
4363+ if ( pos >= 0 )
4364+ {
4365+ int startLine = 0;
4366+ int endLine = 0;
4367+ int startColumn = 0;
4368+ int endColumn = 0;
4369+
4370+ getLineColumn(pos,startLine,startColumn);
4371+ getLineColumn(pos + _searchText.matchedLength(),endLine,endColumn);
4372+
4373+ RegExpFilter::HotSpot* spot = newHotSpot(startLine,startColumn,
4374+ endLine,endColumn);
4375+ spot->setCapturedTexts(_searchText.capturedTexts());
4376+
4377+ addHotSpot( spot );
4378+ pos += _searchText.matchedLength();
4379+
4380+ // if matchedLength == 0, the program will get stuck in an infinite loop
4381+ if ( _searchText.matchedLength() == 0 )
4382+ pos = -1;
4383+ }
4384+ }
4385+}
4386+
4387+RegExpFilter::HotSpot* RegExpFilter::newHotSpot(int startLine,int startColumn,
4388+ int endLine,int endColumn)
4389+{
4390+ return new RegExpFilter::HotSpot(startLine,startColumn,
4391+ endLine,endColumn);
4392+}
4393+RegExpFilter::HotSpot* UrlFilter::newHotSpot(int startLine,int startColumn,int endLine,
4394+ int endColumn)
4395+{
4396+ return new UrlFilter::HotSpot(startLine,startColumn,
4397+ endLine,endColumn);
4398+}
4399+UrlFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
4400+: RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn)
4401+, _urlObject(new FilterObject(this))
4402+{
4403+ setType(Link);
4404+}
4405+QString UrlFilter::HotSpot::tooltip() const
4406+{
4407+ QString url = capturedTexts().first();
4408+
4409+ const UrlType kind = urlType();
4410+
4411+ if ( kind == StandardUrl )
4412+ return QString();
4413+ else if ( kind == Email )
4414+ return QString();
4415+ else
4416+ return QString();
4417+}
4418+UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const
4419+{
4420+ QString url = capturedTexts().first();
4421+
4422+ if ( FullUrlRegExp.exactMatch(url) )
4423+ return StandardUrl;
4424+ else if ( EmailAddressRegExp.exactMatch(url) )
4425+ return Email;
4426+ else
4427+ return Unknown;
4428+}
4429+
4430+void UrlFilter::HotSpot::activate(QObject* object)
4431+{
4432+ QString url = capturedTexts().first();
4433+
4434+ const UrlType kind = urlType();
4435+
4436+ const QString& actionName = object ? object->objectName() : QString();
4437+
4438+ if ( actionName == "copy-action" )
4439+ {
4440+ QApplication::clipboard()->setText(url);
4441+ return;
4442+ }
4443+
4444+ if ( !object || actionName == "open-action" )
4445+ {
4446+ if ( kind == StandardUrl )
4447+ {
4448+ // if the URL path does not include the protocol ( eg. "www.kde.org" ) then
4449+ // prepend http:// ( eg. "www.kde.org" --> "http://www.kde.org" )
4450+ if (!url.contains("://"))
4451+ {
4452+ url.prepend("http://");
4453+ }
4454+ }
4455+ else if ( kind == Email )
4456+ {
4457+ url.prepend("mailto:");
4458+ }
4459+
4460+ QDesktopServices::openUrl(QUrl(url));
4461+ //new KRun(url,QApplication::activeWindow());
4462+ }
4463+}
4464+
4465+// Note: Altering these regular expressions can have a major effect on the performance of the filters
4466+// used for finding URLs in the text, especially if they are very general and could match very long
4467+// pieces of text.
4468+// Please be careful when altering them.
4469+
4470+//regexp matches:
4471+// full url:
4472+// protocolname:// or www. followed by anything other than whitespaces, <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, comma and dot
4473+const QRegExp UrlFilter::FullUrlRegExp("(www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]]");
4474+// email address:
4475+// [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
4476+const QRegExp UrlFilter::EmailAddressRegExp("\\b(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+\\b");
4477+
4478+// matches full url or email address
4479+const QRegExp UrlFilter::CompleteUrlRegExp('('+FullUrlRegExp.pattern()+'|'+
4480+ EmailAddressRegExp.pattern()+')');
4481+
4482+UrlFilter::UrlFilter()
4483+{
4484+ setRegExp( CompleteUrlRegExp );
4485+}
4486+UrlFilter::HotSpot::~HotSpot()
4487+{
4488+ delete _urlObject;
4489+}
4490+void FilterObject::activated()
4491+{
4492+ _filter->activate(sender());
4493+}
4494+QList<QAction*> UrlFilter::HotSpot::actions()
4495+{
4496+ QList<QAction*> list;
4497+
4498+ const UrlType kind = urlType();
4499+
4500+ QAction* openAction = new QAction(_urlObject);
4501+ QAction* copyAction = new QAction(_urlObject);;
4502+
4503+ Q_ASSERT( kind == StandardUrl || kind == Email );
4504+
4505+ if ( kind == StandardUrl )
4506+ {
4507+ openAction->setText(QObject::tr("Open Link"));
4508+ copyAction->setText(QObject::tr("Copy Link Address"));
4509+ }
4510+ else if ( kind == Email )
4511+ {
4512+ openAction->setText(QObject::tr("Send Email To..."));
4513+ copyAction->setText(QObject::tr("Copy Email Address"));
4514+ }
4515+
4516+ // object names are set here so that the hotspot performs the
4517+ // correct action when activated() is called with the triggered
4518+ // action passed as a parameter.
4519+ openAction->setObjectName( QLatin1String("open-action" ));
4520+ copyAction->setObjectName( QLatin1String("copy-action" ));
4521+
4522+ QObject::connect( openAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
4523+ QObject::connect( copyAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
4524+
4525+ list << openAction;
4526+ list << copyAction;
4527+
4528+ return list;
4529+}
4530+
4531+//#include "Filter.moc"
4532
4533=== added file 'src/plugin/konsole/Filter.h'
4534--- src/plugin/konsole/Filter.h 1970-01-01 00:00:00 +0000
4535+++ src/plugin/konsole/Filter.h 2014-05-06 21:50:22 +0000
4536@@ -0,0 +1,380 @@
4537+/*
4538+ Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
4539+
4540+ This program is free software; you can redistribute it and/or modify
4541+ it under the terms of the GNU General Public License as published by
4542+ the Free Software Foundation; either version 2 of the License, or
4543+ (at your option) any later version.
4544+
4545+ This program is distributed in the hope that it will be useful,
4546+ but WITHOUT ANY WARRANTY; without even the implied warranty of
4547+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4548+ GNU General Public License for more details.
4549+
4550+ You should have received a copy of the GNU General Public License
4551+ along with this program; if not, write to the Free Software
4552+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4553+ 02110-1301 USA.
4554+*/
4555+
4556+#ifndef FILTER_H
4557+#define FILTER_H
4558+
4559+// Qt
4560+#include <QtWidgets/QAction>
4561+#include <QtCore/QList>
4562+#include <QtCore/QObject>
4563+#include <QtCore/QStringList>
4564+#include <QtCore/QHash>
4565+#include <QtCore/QRegExp>
4566+
4567+// Local
4568+#include "Character.h"
4569+
4570+
4571+/**
4572+ * A filter processes blocks of text looking for certain patterns (such as URLs or keywords from a list)
4573+ * and marks the areas which match the filter's patterns as 'hotspots'.
4574+ *
4575+ * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
4576+ * and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact
4577+ * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
4578+ * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response.
4579+ *
4580+ * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.
4581+ * Hotspots may have more than one action, in which case the list of actions can be obtained using the
4582+ * actions() method.
4583+ *
4584+ * Different subclasses of filter will return different types of hotspot.
4585+ * Subclasses must reimplement the process() method to examine a block of text and identify sections of interest.
4586+ * When processing the text they should create instances of Filter::HotSpot subclasses for sections of interest
4587+ * and add them to the filter's list of hotspots using addHotSpot()
4588+ */
4589+class Filter
4590+{
4591+public:
4592+ /**
4593+ * Represents an area of text which matched the pattern a particular filter has been looking for.
4594+ *
4595+ * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
4596+ * and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact
4597+ * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
4598+ * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response.
4599+ *
4600+ * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.
4601+ * Hotspots may have more than one action, in which case the list of actions can be obtained using the
4602+ * actions() method. These actions may then be displayed in a popup menu or toolbar for example.
4603+ */
4604+ class HotSpot
4605+ {
4606+ public:
4607+ /**
4608+ * Constructs a new hotspot which covers the area from (@p startLine,@p startColumn) to (@p endLine,@p endColumn)
4609+ * in a block of text.
4610+ */
4611+ HotSpot(int startLine , int startColumn , int endLine , int endColumn);
4612+ virtual ~HotSpot();
4613+
4614+ enum Type
4615+ {
4616+ // the type of the hotspot is not specified
4617+ NotSpecified,
4618+ // this hotspot represents a clickable link
4619+ Link,
4620+ // this hotspot represents a marker
4621+ Marker
4622+ };
4623+
4624+ /** Returns the line when the hotspot area starts */
4625+ int startLine() const;
4626+ /** Returns the line where the hotspot area ends */
4627+ int endLine() const;
4628+ /** Returns the column on startLine() where the hotspot area starts */
4629+ int startColumn() const;
4630+ /** Returns the column on endLine() where the hotspot area ends */
4631+ int endColumn() const;
4632+ /**
4633+ * Returns the type of the hotspot. This is usually used as a hint for views on how to represent
4634+ * the hotspot graphically. eg. Link hotspots are typically underlined when the user mouses over them
4635+ */
4636+ Type type() const;
4637+ /**
4638+ * Causes the an action associated with a hotspot to be triggered.
4639+ *
4640+ * @param object The object which caused the hotspot to be triggered. This is
4641+ * typically null ( in which case the default action should be performed ) or
4642+ * one of the objects from the actions() list. In which case the associated
4643+ * action should be performed.
4644+ */
4645+ virtual void activate(QObject* object = 0) = 0;
4646+ /**
4647+ * Returns a list of actions associated with the hotspot which can be used in a
4648+ * menu or toolbar
4649+ */
4650+ virtual QList<QAction*> actions();
4651+
4652+ /**
4653+ * Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or
4654+ * an empty string if there is no tooltip associated with this hotspot.
4655+ *
4656+ * The default implementation returns an empty string.
4657+ */
4658+ virtual QString tooltip() const;
4659+
4660+ protected:
4661+ /** Sets the type of a hotspot. This should only be set once */
4662+ void setType(Type type);
4663+
4664+ private:
4665+ int _startLine;
4666+ int _startColumn;
4667+ int _endLine;
4668+ int _endColumn;
4669+ Type _type;
4670+
4671+ };
4672+
4673+ /** Constructs a new filter. */
4674+ Filter();
4675+ virtual ~Filter();
4676+
4677+ /** Causes the filter to process the block of text currently in its internal buffer */
4678+ virtual void process() = 0;
4679+
4680+ /**
4681+ * Empties the filters internal buffer and resets the line count back to 0.
4682+ * All hotspots are deleted.
4683+ */
4684+ void reset();
4685+
4686+ /** Adds a new line of text to the filter and increments the line count */
4687+ //void addLine(const QString& string);
4688+
4689+ /** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */
4690+ HotSpot* hotSpotAt(int line , int column) const;
4691+
4692+ /** Returns the list of hotspots identified by the filter */
4693+ QList<HotSpot*> hotSpots() const;
4694+
4695+ /** Returns the list of hotspots identified by the filter which occur on a given line */
4696+ QList<HotSpot*> hotSpotsAtLine(int line) const;
4697+
4698+ /**
4699+ * TODO: Document me
4700+ */
4701+ void setBuffer(const QString* buffer , const QList<int>* linePositions);
4702+
4703+protected:
4704+ /** Adds a new hotspot to the list */
4705+ void addHotSpot(HotSpot*);
4706+ /** Returns the internal buffer */
4707+ const QString* buffer();
4708+ /** Converts a character position within buffer() to a line and column */
4709+ void getLineColumn(int position , int& startLine , int& startColumn);
4710+
4711+private:
4712+ QMultiHash<int,HotSpot*> _hotspots;
4713+ QList<HotSpot*> _hotspotList;
4714+
4715+ const QList<int>* _linePositions;
4716+ const QString* _buffer;
4717+};
4718+
4719+/**
4720+ * A filter which searches for sections of text matching a regular expression and creates a new RegExpFilter::HotSpot
4721+ * instance for them.
4722+ *
4723+ * Subclasses can reimplement newHotSpot() to return custom hotspot types when matches for the regular expression
4724+ * are found.
4725+ */
4726+class RegExpFilter : public Filter
4727+{
4728+public:
4729+ /**
4730+ * Type of hotspot created by RegExpFilter. The capturedTexts() method can be used to find the text
4731+ * matched by the filter's regular expression.
4732+ */
4733+ class HotSpot : public Filter::HotSpot
4734+ {
4735+ public:
4736+ HotSpot(int startLine, int startColumn, int endLine , int endColumn);
4737+ virtual void activate(QObject* object = 0);
4738+
4739+ /** Sets the captured texts associated with this hotspot */
4740+ void setCapturedTexts(const QStringList& texts);
4741+ /** Returns the texts found by the filter when matching the filter's regular expression */
4742+ QStringList capturedTexts() const;
4743+ private:
4744+ QStringList _capturedTexts;
4745+ };
4746+
4747+ /** Constructs a new regular expression filter */
4748+ RegExpFilter();
4749+
4750+ /**
4751+ * Sets the regular expression which the filter searches for in blocks of text.
4752+ *
4753+ * Regular expressions which match the empty string are treated as not matching
4754+ * anything.
4755+ */
4756+ void setRegExp(const QRegExp& text);
4757+ /** Returns the regular expression which the filter searches for in blocks of text */
4758+ QRegExp regExp() const;
4759+
4760+ /**
4761+ * Reimplemented to search the filter's text buffer for text matching regExp()
4762+ *
4763+ * If regexp matches the empty string, then process() will return immediately
4764+ * without finding results.
4765+ */
4766+ virtual void process();
4767+
4768+protected:
4769+ /**
4770+ * Called when a match for the regular expression is encountered. Subclasses should reimplement this
4771+ * to return custom hotspot types
4772+ */
4773+ virtual RegExpFilter::HotSpot* newHotSpot(int startLine,int startColumn,
4774+ int endLine,int endColumn);
4775+
4776+private:
4777+ QRegExp _searchText;
4778+};
4779+
4780+class FilterObject;
4781+
4782+/** A filter which matches URLs in blocks of text */
4783+class UrlFilter : public RegExpFilter
4784+{
4785+public:
4786+ /**
4787+ * Hotspot type created by UrlFilter instances. The activate() method opens a web browser
4788+ * at the given URL when called.
4789+ */
4790+ class HotSpot : public RegExpFilter::HotSpot
4791+ {
4792+ public:
4793+ HotSpot(int startLine,int startColumn,int endLine,int endColumn);
4794+ virtual ~HotSpot();
4795+
4796+ virtual QList<QAction*> actions();
4797+
4798+ /**
4799+ * Open a web browser at the current URL. The url itself can be determined using
4800+ * the capturedTexts() method.
4801+ */
4802+ virtual void activate(QObject* object = 0);
4803+
4804+ virtual QString tooltip() const;
4805+ private:
4806+ enum UrlType
4807+ {
4808+ StandardUrl,
4809+ Email,
4810+ Unknown
4811+ };
4812+ UrlType urlType() const;
4813+
4814+ FilterObject* _urlObject;
4815+ };
4816+
4817+ UrlFilter();
4818+
4819+protected:
4820+ virtual RegExpFilter::HotSpot* newHotSpot(int,int,int,int);
4821+
4822+private:
4823+
4824+ static const QRegExp FullUrlRegExp;
4825+ static const QRegExp EmailAddressRegExp;
4826+
4827+ // combined OR of FullUrlRegExp and EmailAddressRegExp
4828+ static const QRegExp CompleteUrlRegExp;
4829+};
4830+
4831+class FilterObject : public QObject
4832+{
4833+Q_OBJECT
4834+public:
4835+ FilterObject(Filter::HotSpot* filter) : _filter(filter) {}
4836+private slots:
4837+ void activated();
4838+private:
4839+ Filter::HotSpot* _filter;
4840+};
4841+
4842+/**
4843+ * A chain which allows a group of filters to be processed as one.
4844+ * The chain owns the filters added to it and deletes them when the chain itself is destroyed.
4845+ *
4846+ * Use addFilter() to add a new filter to the chain.
4847+ * When new text to be filtered arrives, use addLine() to add each additional
4848+ * line of text which needs to be processed and then after adding the last line, use
4849+ * process() to cause each filter in the chain to process the text.
4850+ *
4851+ * After processing a block of text, the reset() method can be used to set the filter chain's
4852+ * internal cursor back to the first line.
4853+ *
4854+ * The hotSpotAt() method will return the first hotspot which covers a given position.
4855+ *
4856+ * The hotSpots() and hotSpotsAtLine() method return all of the hotspots in the text and on
4857+ * a given line respectively.
4858+ */
4859+class FilterChain : protected QList<Filter*>
4860+{
4861+public:
4862+ virtual ~FilterChain();
4863+
4864+ /** Adds a new filter to the chain. The chain will delete this filter when it is destroyed */
4865+ void addFilter(Filter* filter);
4866+ /** Removes a filter from the chain. The chain will no longer delete the filter when destroyed */
4867+ void removeFilter(Filter* filter);
4868+ /** Returns true if the chain contains @p filter */
4869+ bool containsFilter(Filter* filter);
4870+ /** Removes all filters from the chain */
4871+ void clear();
4872+
4873+ /** Resets each filter in the chain */
4874+ void reset();
4875+ /**
4876+ * Processes each filter in the chain
4877+ */
4878+ void process();
4879+
4880+ /** Sets the buffer for each filter in the chain to process. */
4881+ void setBuffer(const QString* buffer , const QList<int>* linePositions);
4882+
4883+ /** Returns the first hotspot which occurs at @p line, @p column or 0 if no hotspot was found */
4884+ Filter::HotSpot* hotSpotAt(int line , int column) const;
4885+ /** Returns a list of all the hotspots in all the chain's filters */
4886+ QList<Filter::HotSpot*> hotSpots() const;
4887+ /** Returns a list of all hotspots at the given line in all the chain's filters */
4888+ QList<Filter::HotSpot> hotSpotsAtLine(int line) const;
4889+
4890+};
4891+
4892+/** A filter chain which processes character images from terminal displays */
4893+class TerminalImageFilterChain : public FilterChain
4894+{
4895+public:
4896+ TerminalImageFilterChain();
4897+ virtual ~TerminalImageFilterChain();
4898+
4899+ /**
4900+ * Set the current terminal image to @p image.
4901+ *
4902+ * @param image The terminal image
4903+ * @param lines The number of lines in the terminal image
4904+ * @param columns The number of columns in the terminal image
4905+ * @param lineProperties The line properties to set for image
4906+ */
4907+ void setImage(const Character* const image , int lines , int columns,
4908+ const QVector<LineProperty>& lineProperties);
4909+
4910+private:
4911+ QString* _buffer;
4912+ QList<int>* _linePositions;
4913+};
4914+
4915+
4916+#endif //FILTER_H
4917
4918=== added file 'src/plugin/konsole/History.cpp'
4919--- src/plugin/konsole/History.cpp 1970-01-01 00:00:00 +0000
4920+++ src/plugin/konsole/History.cpp 2014-05-06 21:50:22 +0000
4921@@ -0,0 +1,986 @@
4922+/*
4923+ This file is part of Konsole, an X terminal.
4924+ Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
4925+
4926+ This program is free software; you can redistribute it and/or modify
4927+ it under the terms of the GNU General Public License as published by
4928+ the Free Software Foundation; either version 2 of the License, or
4929+ (at your option) any later version.
4930+
4931+ This program is distributed in the hope that it will be useful,
4932+ but WITHOUT ANY WARRANTY; without even the implied warranty of
4933+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4934+ GNU General Public License for more details.
4935+
4936+ You should have received a copy of the GNU General Public License
4937+ along with this program; if not, write to the Free Software
4938+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4939+ 02110-1301 USA.
4940+*/
4941+
4942+// Own
4943+#include "History.h"
4944+
4945+// System
4946+#include <iostream>
4947+#include <stdlib.h>
4948+#include <assert.h>
4949+#include <stdio.h>
4950+#include <sys/types.h>
4951+#include <sys/mman.h>
4952+#include <unistd.h>
4953+#include <errno.h>
4954+
4955+#include <QtDebug>
4956+
4957+// KDE
4958+//#include <kde_file.h>
4959+//#include <kdebug.h>
4960+
4961+// Reasonable line size
4962+#define LINE_SIZE 1024
4963+#define KDE_lseek lseek
4964+
4965+
4966+/*
4967+ An arbitrary long scroll.
4968+
4969+ One can modify the scroll only by adding either cells
4970+ or newlines, but access it randomly.
4971+
4972+ The model is that of an arbitrary wide typewriter scroll
4973+ in that the scroll is a serie of lines and each line is
4974+ a serie of cells with no overwriting permitted.
4975+
4976+ The implementation provides arbitrary length and numbers
4977+ of cells and line/column indexed read access to the scroll
4978+ at constant costs.
4979+
4980+KDE4: Can we use QTemporaryFile here, instead of KTempFile?
4981+
4982+FIXME: some complain about the history buffer comsuming the
4983+ memory of their machines. This problem is critical
4984+ since the history does not behave gracefully in cases
4985+ where the memory is used up completely.
4986+
4987+ I put in a workaround that should handle it problem
4988+ now gracefully. I'm not satisfied with the solution.
4989+
4990+FIXME: Terminating the history is not properly indicated
4991+ in the menu. We should throw a signal.
4992+
4993+FIXME: There is noticeable decrease in speed, also. Perhaps,
4994+ there whole feature needs to be revisited therefore.
4995+ Disadvantage of a more elaborated, say block-oriented
4996+ scheme with wrap around would be it's complexity.
4997+*/
4998+
4999+//FIXME: tempory replacement for tmpfile
5000+// this is here one for debugging purpose.
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches