Merge lp:~dpm/ubuntu-terminal-app/merge-plugin into lp:ubuntu-terminal-app
- merge-plugin
- Merge into trunk
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 |
Related bugs: |
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.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
- 68. By David Planella
-
Added rule to copy the plugin to the build directory
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:68
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Pope 🍺🐧🐱 🦄 (popey) wrote : | # |
Tried building this in qtcreator, it built a click package, but that fails the click-reviewers
ERROR: Could not find 'com.ubuntu.
- 69. By David Planella
-
Fixed wrong desktop file in the manifest
David Planella (dpm) wrote : | # |
Sorry, that was a typo in the manifest file. Fixed now.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:69
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Pope 🍺🐧🐱 🦄 (popey) wrote : | # |
Trying to test this but qtc is conspiring against me: bug 1314960
Nicholas Skaggs (nskaggs) wrote : | # |
In order to get this to run, you need the python3-lxml lib added to /home/phablet/
I was able to successfully build and run this on my device.
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
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:70
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nicholas Skaggs (nskaggs) wrote : | # |
could not import package ubuntu_
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.
Dimitri John Ledkov (xnox) wrote : | # |
On 6 May 2014 18:09, Nicholas Skaggs <email address hidden> wrote:
> could not import package ubuntu_
> 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.
Dimitri John Ledkov (xnox) wrote : | # |
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 :-)
Nicholas Skaggs (nskaggs) wrote : | # |
Dimitri John Ledkov (xnox) wrote : | # |
On 6 May 2014 19:39, Nicholas Skaggs <email address hidden> wrote:
> See https:/
> --
> https:/
> Your team Ubuntu Terminal Developers is subscribed to branch lp:ubuntu-terminal-app.
Or see... https:/
which is mid-air colition, slightly older than your branch.
--
Regards,
Dimitri.
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
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:73
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 74. By David Planella
-
Merge Python 3 print() fix from balloons
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:74
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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},
+ python3-autopilot,
Description: Autopilot tests for Terminal Application
- 75. By David Planella
-
Add Python 3 dependency to make Jenkins happy
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) : | # |
Preview Diff
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. |
FAILED: Continuous integration, rev:67 /code.launchpad .net/~dpm/ ubuntu- terminal- app/merge- plugin/ +merge/ 217380/ +edit-commit- message
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:/
http:// 91.189. 93.70:8080/ job/ubuntu- terminal- app-ci/ 49/ 91.189. 93.70:8080/ job/generic- mediumtests- trusty/ 2254 91.189. 93.70:8080/ job/ubuntu- terminal- app-raring- amd64-ci/ 49 91.189. 93.70:8080/ job/ubuntu- terminal- app-saucy- amd64-ci/ 49 91.189. 93.70:8080/ job/ubuntu- terminal- app-trusty- amd64-ci/ 37
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- terminal- app-ci/ 49/rebuild
http://