Changeset View
Changeset View
Standalone View
Standalone View
krusader/KViewer/lister.cpp
Context not available. | |||||
35 | #include <QRect> | 35 | #include <QRect> | ||
---|---|---|---|---|---|
36 | #include <QDate> | 36 | #include <QDate> | ||
37 | #include <QTemporaryFile> | 37 | #include <QTemporaryFile> | ||
38 | #include <QTextCodec> | | |||
39 | #include <QTextStream> | 38 | #include <QTextStream> | ||
40 | // QtGui | 39 | // QtGui | ||
41 | #include <QPainter> | 40 | #include <QPainter> | ||
Context not available. | |||||
77 | #define SEARCH_CACHE_CHARS 100000 | 76 | #define SEARCH_CACHE_CHARS 100000 | ||
78 | #define SEARCH_MAX_ROW_LEN 4000 | 77 | #define SEARCH_MAX_ROW_LEN 4000 | ||
79 | #define CONTROL_CHAR 752 | 78 | #define CONTROL_CHAR 752 | ||
80 | #define CACHE_SIZE 100000 | 79 | #define CACHE_SIZE 5242880 // cache size set to 5MiB | ||
80 | | ||||
81 | 81 | | |||
82 | ListerTextArea::ListerTextArea(Lister *lister, QWidget *parent) : KTextEdit(parent), _lister(lister), | 82 | ListerTextArea::ListerTextArea(Lister *lister, QWidget *parent) : KTextEdit(parent), _lister(lister), | ||
83 | _sizeX(-1), _sizeY(-1), _cursorAnchorPos(-1), _inSliderOp(false), _inCursorUpdate(false), _hexMode(false) | 83 | _sizeX(-1), _sizeY(-1), _cursorAnchorPos(-1), _inSliderOp(false), _hexMode(false) | ||
84 | { | 84 | { | ||
85 | connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(slotCursorPositionChanged())); | 85 | connect(this, &QTextEdit::cursorPositionChanged, this, &ListerTextArea::slotCursorPositionChanged); | ||
86 | _tabWidth = 4; | 86 | _tabWidth = 4; | ||
87 | setWordWrapMode(QTextOption::NoWrap); | 87 | setWordWrapMode(QTextOption::NoWrap); | ||
88 | setLineWrapMode(QTextEdit::NoWrap); | 88 | setLineWrapMode(QTextEdit::NoWrap); | ||
Context not available. | |||||
92 | connect(new QShortcut(QKeySequence("Ctrl+-"), this), SIGNAL(activated()), this, SLOT(zoomOut())); | 92 | connect(new QShortcut(QKeySequence("Ctrl+-"), this), SIGNAL(activated()), this, SLOT(zoomOut())); | ||
93 | 93 | | |||
94 | // start cursor blinking | 94 | // start cursor blinking | ||
95 | QTimer *blinkTimer = new QTimer(this); | 95 | _blinkTimer = new QTimer(this); | ||
96 | connect(blinkTimer, SIGNAL(timeout()), this, SLOT(blinkCursor())); | 96 | connect(_blinkTimer, &QTimer::timeout, this, [=] { | ||
97 | blinkTimer->start(500); | 97 | if (!_cursorBlinkMutex.tryLock()) { | ||
98 | } | 98 | return; | ||
99 | 99 | } | |||
100 | void ListerTextArea::blinkCursor() | 100 | setCursorWidth(cursorWidth() == 0 ? 2 : 0); | ||
101 | { | 101 | _cursorBlinkMutex.unlock(); | ||
102 | if (_inCursorUpdate) { | 102 | }); | ||
103 | return; | 103 | _blinkTimer->start(500); | ||
104 | } | | |||
105 | _cursorState = !_cursorState; | | |||
106 | setCursorWidth(_cursorState ? 2 : 0); | | |||
107 | } | 104 | } | ||
108 | 105 | | |||
109 | void ListerTextArea::reset() | 106 | void ListerTextArea::reset() | ||
Context not available. | |||||
131 | redrawTextArea(); | 128 | redrawTextArea(); | ||
132 | } | 129 | } | ||
133 | 130 | | |||
134 | void ListerTextArea::calculateText(bool forcedUpdate) | 131 | void ListerTextArea::calculateText(const bool forcedUpdate) | ||
135 | { | 132 | { | ||
136 | QFontMetrics fm(font()); | 133 | const QFontMetrics fm(font()); | ||
137 | 134 | | |||
138 | int fontHeight = fm.height(); | 135 | const int fontHeight = std::max(fm.height(), 1); | ||
139 | if (fontHeight < 1) | | |||
140 | fontHeight = 1; | | |||
141 | 136 | | |||
142 | QRect crect = viewport()->contentsRect(); | 137 | const QRect crect = viewport()->contentsRect(); | ||
143 | int windowHeight = crect.height(); | 138 | const int windowHeight = crect.height(); | ||
144 | 139 | | |||
145 | int sizeY = windowHeight / fontHeight; | 140 | const int sizeY = windowHeight / fontHeight; | ||
146 | _pageSize = sizeY; | 141 | _pageSize = sizeY; | ||
147 | 142 | | |||
148 | QList<qint64> rowStarts; | 143 | const int fontWidth = std::max(fm.width("W"), 1); | ||
149 | 144 | const int windowWidth = std::max(crect.width() - fontWidth / 2, 0); | |||
150 | int fontWidth = fm.width("W"); | | |||
151 | if (fontWidth < 1) | | |||
152 | fontWidth = 1; | | |||
153 | int windowWidth = crect.width() - fontWidth / 2; | | |||
154 | if (windowWidth < 1) | | |||
155 | windowWidth = 0; | | |||
156 | 145 | | |||
157 | setTabStopWidth(fontWidth * _tabWidth); | 146 | setTabStopWidth(fontWidth * _tabWidth); | ||
158 | 147 | | |||
159 | int sizeX = windowWidth / fontWidth; | 148 | const int sizeX = windowWidth / fontWidth; | ||
160 | 149 | | |||
161 | _sizeChanged = (_sizeY != sizeY) || (_sizeX != sizeX) || forcedUpdate; | 150 | _sizeChanged = (_sizeY != sizeY) || (_sizeX != sizeX) || forcedUpdate; | ||
162 | _sizeY = sizeY; | 151 | _sizeY = sizeY; | ||
163 | _sizeX = sizeX; | 152 | _sizeX = sizeX; | ||
164 | 153 | | |||
154 | QList<qint64> rowStarts; | ||||
155 | | ||||
165 | QStringList list = readLines(_screenStartPos, _screenEndPos, _sizeY, &rowStarts); | 156 | QStringList list = readLines(_screenStartPos, _screenEndPos, _sizeY, &rowStarts); | ||
166 | 157 | | |||
167 | if (_sizeChanged) { | 158 | if (_sizeChanged) { | ||
Context not available. | |||||
169 | setUpScrollBar(); | 160 | setUpScrollBar(); | ||
170 | } | 161 | } | ||
171 | 162 | | |||
172 | rowStarts << _screenEndPos; | 163 | const QStringList listRemn = readLines(_screenEndPos, _screenEndPos, 1); | ||
173 | | ||||
174 | QStringList listRemn = readLines(_screenEndPos, _screenEndPos, 1); | | |||
175 | list << listRemn; | 164 | list << listRemn; | ||
176 | 165 | | |||
177 | if (list != _rowContent) { | 166 | if (list != _rowContent) { | ||
167 | | ||||
168 | _cursorBlinkMutex.lock(); | ||||
169 | _blinkTimer->stop(); | ||||
170 | setCursorWidth(0); | ||||
171 | | ||||
178 | setPlainText(list.join("\n")); | 172 | setPlainText(list.join("\n")); | ||
173 | | ||||
174 | if (_cursorAnchorPos == -1 || _cursorAnchorPos == _cursorPos) { | ||||
175 | clearSelection(); | ||||
176 | _blinkTimer->start(500); | ||||
177 | } | ||||
178 | | ||||
179 | _cursorBlinkMutex.unlock(); | ||||
180 | | ||||
179 | _rowContent = list; | 181 | _rowContent = list; | ||
180 | _rowStarts = rowStarts; | 182 | _rowStarts = rowStarts; | ||
183 | if (_rowStarts.size() < _sizeY) { | ||||
184 | _rowStarts << _screenEndPos; | ||||
185 | } | ||||
181 | } | 186 | } | ||
182 | } | 187 | } | ||
183 | 188 | | |||
184 | qint64 ListerTextArea::textToFilePosition(int x, int y, bool &isfirst) | 189 | qint64 ListerTextArea::textToFilePositionOnScreen(const int x, const int y, bool &isfirst) | ||
185 | { | 190 | { | ||
186 | isfirst = (x == 0); | 191 | isfirst = (x == 0); | ||
187 | if (y >= _rowStarts.count()) | 192 | if (y >= _rowStarts.count()) { | ||
188 | return -1; | 193 | return -1; | ||
189 | qint64 rowStart = _rowStarts[ y ]; | 194 | } | ||
190 | if (x == 0) | 195 | const qint64 rowStart = _rowStarts[ y ]; | ||
196 | if (x == 0) { | ||||
191 | return rowStart; | 197 | return rowStart; | ||
198 | } | ||||
192 | 199 | | |||
193 | if (_hexMode) { | 200 | if (_hexMode) { | ||
194 | qint64 pos = rowStart + _lister->hexPositionToIndex(_sizeX, x); | 201 | const qint64 pos = rowStart + _lister->hexPositionToIndex(_sizeX, x); | ||
195 | if (pos > _lister->fileSize()) | 202 | if (pos > _lister->fileSize()) { | ||
196 | pos = _lister->fileSize(); | 203 | return _lister->fileSize(); | ||
204 | } | ||||
197 | return pos; | 205 | return pos; | ||
198 | } | 206 | } | ||
199 | 207 | | |||
200 | // we can't use fromUnicode because of the invalid encoded chars | 208 | // we can't use fromUnicode because of the invalid encoded chars | ||
201 | int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH; | 209 | int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH; | ||
202 | char * cache = _lister->cacheRef(rowStart, maxBytes); | 210 | QByteArray cache = _lister->cacheChunk(rowStart, maxBytes); | ||
203 | QByteArray cachedBuffer(cache, maxBytes); | | |||
204 | 211 | | |||
205 | QTextStream stream(&cachedBuffer); | 212 | QTextStream stream(&cache); | ||
206 | stream.setCodec(codec()); | 213 | stream.setCodec(_lister->codec()); | ||
207 | stream.read(x); | 214 | stream.read(x); | ||
208 | return rowStart + stream.pos(); | 215 | return rowStart + stream.pos(); | ||
209 | } | 216 | } | ||
210 | 217 | | |||
211 | void ListerTextArea::fileToTextPosition(qint64 p, bool isfirst, int &x, int &y) | 218 | void ListerTextArea::fileToTextPositionOnScreen(const qint64 p, const bool isfirst, int &x, int &y) | ||
212 | { | 219 | { | ||
220 | // check if cursor is outside of visible area | ||||
213 | if (p < _screenStartPos || p > _screenEndPos || _rowStarts.count() < 1) { | 221 | if (p < _screenStartPos || p > _screenEndPos || _rowStarts.count() < 1) { | ||
214 | x = -1; | 222 | x = -1; | ||
215 | y = (p > _screenEndPos) ? -2 : -1; | 223 | y = (p > _screenEndPos) ? -2 : -1; | ||
216 | } else { | 224 | return; | ||
217 | y = 0; | 225 | } | ||
218 | while (y < _rowStarts.count() && _rowStarts[ y ] <= p) | | |||
219 | y++; | | |||
220 | y--; | | |||
221 | if (y < 0) { | | |||
222 | x = y = -1; | | |||
223 | return; | | |||
224 | } | | |||
225 | 226 | | |||
226 | qint64 rowStart = _rowStarts[ y ]; | 227 | // find row | ||
227 | if (_hexMode) { | 228 | y = 0; | ||
228 | x = _lister->hexIndexToPosition(_sizeX, (int)(p - rowStart)); | 229 | while (y < _rowStarts.count() && _rowStarts[ y ] <= p) { | ||
229 | return; | 230 | y++; | ||
230 | } | 231 | } | ||
232 | y--; | ||||
233 | if (y < 0) { | ||||
234 | x = y = -1; | ||||
235 | return; | ||||
236 | } | ||||
231 | 237 | | |||
232 | int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH; | 238 | const qint64 rowStart = _rowStarts[ y ]; | ||
233 | x = 0; | 239 | if (_hexMode) { | ||
234 | if (rowStart >= p) { | 240 | x = _lister->hexIndexToPosition(_sizeX, (int)(p - rowStart)); | ||
235 | if ((rowStart == p) && !isfirst && y > 0) { | 241 | return; | ||
236 | qint64 previousRow = _rowStarts[ y - 1 ]; | 242 | } | ||
237 | char * cache = _lister->cacheRef(previousRow, maxBytes); | 243 | | ||
238 | QByteArray cachedBuffer(cache, p - previousRow); | 244 | // find column | ||
239 | 245 | int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH; | |||
240 | QTextStream stream(&cachedBuffer); | 246 | x = 0; | ||
241 | stream.setCodec(codec()); | 247 | if (rowStart >= p) { | ||
242 | stream.read(_rowContent[ y - 1].length()); | 248 | if ((rowStart == p) && !isfirst && y > 0) { | ||
243 | if (previousRow + stream.pos() == p) { | 249 | const qint64 previousRow = _rowStarts[ y - 1 ]; | ||
244 | y--; | 250 | const QByteArray cache = _lister->cacheChunk(previousRow, maxBytes); | ||
245 | x = _rowContent[ y ].length(); | 251 | QByteArray cachedBuffer = cache.left(p - previousRow); | ||
246 | } | 252 | | ||
253 | QTextStream stream(&cachedBuffer); | ||||
254 | stream.setCodec(_lister->codec()); | ||||
255 | stream.read(_rowContent[ y - 1].length()); | ||||
256 | if (previousRow + stream.pos() == p) { | ||||
257 | y--; | ||||
258 | x = _rowContent[ y ].length(); | ||||
247 | } | 259 | } | ||
248 | return; | | |||
249 | } | 260 | } | ||
261 | return; | ||||
262 | } | ||||
250 | 263 | | |||
251 | char * cache = _lister->cacheRef(rowStart, maxBytes); | 264 | const QByteArray cache = _lister->cacheChunk(rowStart, maxBytes); | ||
252 | QByteArray cachedBuffer(cache, p - rowStart); | 265 | const QByteArray cachedBuffer = cache.left(p - rowStart); | ||
253 | 266 | | |||
254 | QString res = codec()->toUnicode(cachedBuffer); | 267 | x = _lister->codec()->toUnicode(cachedBuffer).length(); | ||
255 | x = res.length(); | | |||
256 | } | | |||
257 | } | 268 | } | ||
258 | 269 | | |||
259 | void ListerTextArea::getCursorPosition(int &x, int &y) | 270 | void ListerTextArea::getCursorPosition(int &x, int &y) | ||
Context not available. | |||||
261 | getScreenPosition(textCursor().position(), x, y); | 272 | getScreenPosition(textCursor().position(), x, y); | ||
262 | } | 273 | } | ||
263 | 274 | | |||
264 | void ListerTextArea::getScreenPosition(int position, int &x, int &y) | 275 | void ListerTextArea::getScreenPosition(const int position, int &x, int &y) | ||
265 | { | 276 | { | ||
266 | x = position; | 277 | x = position; | ||
267 | y = 0; | 278 | y = 0; | ||
268 | for (int i = 0; i < _rowContent.count(); i++) { | 279 | foreach (const QString &row, _rowContent) { | ||
269 | int rowLen = _rowContent[ i ].length() + 1; | 280 | const int rowLen = row.length() + 1; | ||
270 | if (x >= rowLen) { | 281 | if (x < rowLen) { | ||
271 | x -= rowLen; | 282 | return; | ||
272 | y++; | 283 | } | ||
273 | } else | 284 | x -= rowLen; | ||
274 | break; | 285 | y++; | ||
275 | } | 286 | } | ||
276 | } | 287 | } | ||
277 | 288 | | |||
278 | void ListerTextArea::setCursorPosition(int x, int y, int anchorX, int anchorY) | 289 | void ListerTextArea::setCursorPositionOnScreen(const int x, const int y, const int anchorX, const int anchorY) | ||
279 | { | 290 | { | ||
280 | _inCursorUpdate = true; | 291 | setCursorWidth(0); | ||
281 | if (x == -1 || y < 0) { | 292 | | ||
282 | setCursorWidth(0); | 293 | int finalX = x; | ||
294 | int finalY = y; | ||||
295 | | ||||
296 | if (finalX == -1 || finalY < 0) { | ||||
283 | if (anchorY == -1) { | 297 | if (anchorY == -1) { | ||
284 | _inCursorUpdate = false; | | |||
285 | return; | 298 | return; | ||
286 | } | 299 | } | ||
287 | 300 | | |||
288 | if (y == -2) { | 301 | if (finalY == -2) { | ||
289 | y = _sizeY; | 302 | finalY = _sizeY; | ||
290 | x = (_rowContent.count() > _sizeY) ? _rowContent[ _sizeY ].length() : 0; | 303 | finalX = (_rowContent.count() > _sizeY) ? _rowContent[ _sizeY ].length() : 0; | ||
291 | } else | 304 | } else | ||
292 | x = y = 0; | 305 | finalX = finalY = 0; | ||
293 | } | 306 | } | ||
294 | 307 | | |||
295 | QTextCursor::MoveMode mode = QTextCursor::MoveAnchor; | 308 | const int realSizeY = std::min(_sizeY + 1, _rowContent.count()); | ||
296 | if (anchorX != -1 && anchorY != -1) { | 309 | | ||
297 | if (anchorY >= _sizeY) { | 310 | const auto setUpCursor = [&] (const int cursorX, const int cursorY, const QTextCursor::MoveMode mode) -> bool { | ||
298 | moveCursor(QTextCursor::End, mode); | 311 | if (cursorY >= realSizeY) { | ||
299 | moveCursor(QTextCursor::StartOfLine, mode); | 312 | return false; | ||
300 | } else { | 313 | } | ||
301 | moveCursor(QTextCursor::Start, mode); | 314 | | ||
302 | for (int i = 0; i < anchorY; i++) | 315 | _skipCursorChangedListener = true; | ||
303 | moveCursor(QTextCursor::Down, mode); | 316 | | ||
317 | moveCursor(QTextCursor::Start, mode); | ||||
318 | for (int i = 0; i < cursorY; i++) { | ||||
319 | moveCursor(QTextCursor::Down, mode); | ||||
304 | } | 320 | } | ||
305 | 321 | | |||
306 | if (_rowContent.count() > anchorY && anchorX > _rowContent[ anchorY ].length()) | 322 | int finalCursorX = cursorX; | ||
307 | anchorX = _rowContent[ anchorY ].length(); | 323 | if (_rowContent.count() > cursorY && finalCursorX > _rowContent[ cursorY ].length()) { | ||
324 | finalCursorX = _rowContent[ cursorY ].length(); | ||||
325 | } | ||||
308 | 326 | | |||
309 | for (int j = 0; j < anchorX; j++) | 327 | for (int i = 0; i < finalCursorX; i++) { | ||
310 | moveCursor(QTextCursor::Right, mode); | 328 | moveCursor(QTextCursor::Right, mode); | ||
329 | } | ||||
311 | 330 | | |||
312 | mode = QTextCursor::KeepAnchor; | 331 | _skipCursorChangedListener = false; | ||
313 | } | | |||
314 | 332 | | |||
315 | if (y >= _sizeY) { | 333 | return true; | ||
316 | moveCursor(QTextCursor::End, mode); | 334 | }; | ||
317 | moveCursor(QTextCursor::StartOfLine, mode); | | |||
318 | } else { | | |||
319 | moveCursor(QTextCursor::Start, mode); | | |||
320 | for (int i = 0; i < y; i++) | | |||
321 | moveCursor(QTextCursor::Down, mode); | | |||
322 | } | | |||
323 | 335 | | |||
324 | if (_rowContent.count() > y && x > _rowContent[ y ].length()) | 336 | QTextCursor::MoveMode mode = QTextCursor::MoveAnchor; | ||
325 | x = _rowContent[ y ].length(); | | |||
326 | 337 | | |||
327 | for (int j = 0; j < x; j++) | 338 | // set cursor anchor | ||
328 | moveCursor(QTextCursor::Right, mode); | 339 | if (anchorX != -1 && anchorY != -1) { | ||
329 | 340 | | |||
330 | _inCursorUpdate = false; | 341 | const bool canContinue = setUpCursor(anchorX, anchorY, mode); | ||
342 | if (!canContinue) { | ||||
343 | return; | ||||
344 | } | ||||
345 | | ||||
346 | mode = QTextCursor::KeepAnchor; | ||||
347 | } | ||||
348 | | ||||
349 | // set cursor position | ||||
350 | setUpCursor(finalX, finalY, mode); | ||||
331 | } | 351 | } | ||
332 | 352 | | |||
333 | qint64 ListerTextArea::getCursorPosition(bool &isfirst) | 353 | qint64 ListerTextArea::getCursorPosition(bool &isfirst) | ||
Context not available. | |||||
339 | 359 | | |||
340 | int x, y; | 360 | int x, y; | ||
341 | getCursorPosition(x, y); | 361 | getCursorPosition(x, y); | ||
342 | return textToFilePosition(x, y, isfirst); | 362 | return textToFilePositionOnScreen(x, y, isfirst); | ||
343 | } | 363 | } | ||
344 | 364 | | |||
345 | void ListerTextArea::setCursorPosition(qint64 p, bool isfirst) | 365 | void ListerTextArea::setCursorPositionInDocument(const qint64 p, const bool isfirst) | ||
346 | { | 366 | { | ||
347 | _cursorPos = p; | 367 | _cursorPos = p; | ||
348 | int x, y; | 368 | int x, y; | ||
349 | fileToTextPosition(p, isfirst, x, y); | 369 | fileToTextPositionOnScreen(p, isfirst, x, y); | ||
350 | 370 | | |||
371 | bool startBlinkTimer = _screenStartPos <= _cursorPos && _cursorPos <= _screenEndPos; | ||||
351 | int anchorX = -1, anchorY = -1; | 372 | int anchorX = -1, anchorY = -1; | ||
352 | if (_cursorAnchorPos != -1 && _cursorAnchorPos != p) { | 373 | if (_cursorAnchorPos != -1 && _cursorAnchorPos != p) { | ||
353 | int anchPos = _cursorAnchorPos; | 374 | int anchPos = _cursorAnchorPos; | ||
Context not available. | |||||
363 | anchorBelow = true; | 384 | anchorBelow = true; | ||
364 | } | 385 | } | ||
365 | 386 | | |||
366 | fileToTextPosition(anchPos, isfirst, anchorX, anchorY); | 387 | fileToTextPositionOnScreen(anchPos, isfirst, anchorX, anchorY); | ||
367 | if (anchorAbove && _hexMode) | 388 | | ||
368 | anchorX = 0; | 389 | if (_hexMode) { | ||
369 | if (anchorBelow && _hexMode && _rowContent.count() > 0) | 390 | if (anchorAbove) { | ||
370 | anchorX = _rowContent[ 0 ].length(); | 391 | anchorX = 0; | ||
392 | } | ||||
393 | if (anchorBelow && _rowContent.count() > 0) { | ||||
394 | anchorX = _rowContent[ 0 ].length(); | ||||
395 | } | ||||
396 | } | ||||
397 | | ||||
398 | startBlinkTimer = startBlinkTimer && !anchorAbove && !anchorBelow; | ||||
371 | } | 399 | } | ||
372 | setCursorPosition(x, y, anchorX, anchorY); | 400 | if (startBlinkTimer) { | ||
401 | _blinkTimer->start(500); | ||||
402 | } | ||||
403 | setCursorPositionOnScreen(x, y, anchorX, anchorY); | ||||
404 | _lister->slotUpdate(); | ||||
373 | } | 405 | } | ||
374 | 406 | | |||
375 | void ListerTextArea::slotCursorPositionChanged() | 407 | void ListerTextArea::slotCursorPositionChanged() | ||
376 | { | 408 | { | ||
377 | if (_inCursorUpdate) | 409 | if (_skipCursorChangedListener) { | ||
378 | return; | 410 | return; | ||
411 | } | ||||
379 | int cursorX, cursorY; | 412 | int cursorX, cursorY; | ||
380 | getCursorPosition(cursorX, cursorY); | 413 | getCursorPosition(cursorX, cursorY); | ||
381 | _cursorAtFirstColumn = (cursorX == 0); | 414 | _cursorAtFirstColumn = (cursorX == 0); | ||
382 | _cursorPos = textToFilePosition(cursorX, cursorY, _cursorAtFirstColumn); | 415 | _cursorPos = textToFilePositionOnScreen(cursorX, cursorY, _cursorAtFirstColumn); | ||
383 | //fprintf( stderr, "Cursor pos: %d %d %Ld\n", cursorX, cursorY, _cursorPos ); | 416 | _lister->slotUpdate(); | ||
384 | } | 417 | } | ||
385 | 418 | | |||
386 | QString ListerTextArea::readSection(qint64 p1, qint64 p2) | 419 | QString ListerTextArea::readSection(const qint64 p1, const qint64 p2) | ||
387 | { | 420 | { | ||
388 | if (p1 == p2) | 421 | if (p1 == p2) | ||
389 | return QString(); | 422 | return QString(); | ||
390 | 423 | | |||
391 | if (p1 > p2) { | 424 | qint64 sel1 = p1; | ||
392 | qint64 tmp = p1; | 425 | qint64 sel2 = p2; | ||
393 | p1 = p2; | 426 | if (sel1 > sel2) { | ||
394 | p2 = tmp; | 427 | std::swap(sel1, sel2); | ||
395 | } | 428 | } | ||
396 | 429 | | |||
397 | QString section; | 430 | QString section; | ||
398 | qint64 pos = p1; | | |||
399 | 431 | | |||
400 | if (_hexMode) { | 432 | if (_hexMode) { | ||
401 | while (p1 != p2) { | 433 | while (sel1 != sel2) { | ||
402 | QStringList list = _lister->readHexLines(p1, p2, _sizeX, 1); | 434 | const QStringList list = _lister->readHexLines(sel1, sel2, _sizeX, 1); | ||
403 | if (list.count() == 0) | 435 | if (list.isEmpty()) { | ||
404 | break; | 436 | break; | ||
405 | if (!section.isEmpty()) | 437 | } | ||
438 | if (!section.isEmpty()) { | ||||
406 | section += QChar('\n'); | 439 | section += QChar('\n'); | ||
407 | section += list[ 0 ]; | 440 | } | ||
441 | section += list.at(0); | ||||
408 | } | 442 | } | ||
409 | return section; | 443 | return section; | ||
410 | } | 444 | } | ||
411 | 445 | | |||
412 | QTextCodec * textCodec = codec(); | 446 | qint64 pos = sel1; | ||
413 | QTextDecoder * decoder = textCodec->makeDecoder(); | | |||
414 | 447 | | |||
415 | do { | 448 | do { | ||
416 | int maxBytes = _sizeX * _sizeY * MAX_CHAR_LENGTH; | 449 | int maxBytes = std::min(_sizeX * _sizeY * MAX_CHAR_LENGTH, (int) (sel2 - pos)); | ||
417 | if (maxBytes > (p2 - pos)) | 450 | const QByteArray cache = _lister->cacheChunk(pos, maxBytes); | ||
418 | maxBytes = (int)(p2 - pos); | 451 | if (cache.isEmpty() || maxBytes == 0) | ||
419 | char * cache = _lister->cacheRef(pos, maxBytes); | | |||
420 | if (cache == 0 || maxBytes == 0) | | |||
421 | break; | 452 | break; | ||
422 | section += decoder->toUnicode(cache, maxBytes); | 453 | section += _lister->codec()->toUnicode(cache); | ||
423 | pos += maxBytes; | 454 | pos += maxBytes; | ||
424 | } while (pos < p2); | 455 | } while (pos < sel2); | ||
425 | 456 | | |||
426 | delete decoder; | | |||
427 | return section; | 457 | return section; | ||
428 | } | 458 | } | ||
429 | 459 | | |||
430 | QStringList ListerTextArea::readLines(qint64 filePos, qint64 &endPos, int lines, QList<qint64> * locs) | 460 | QStringList ListerTextArea::readLines(qint64 filePos, qint64 &endPos, const int lines, QList<qint64> * locs) | ||
431 | { | 461 | { | ||
432 | endPos = filePos; | | |||
433 | QStringList list; | 462 | QStringList list; | ||
434 | 463 | | |||
435 | if (_hexMode) { | 464 | if (_hexMode) { | ||
436 | endPos = _lister->fileSize(); | 465 | endPos = _lister->fileSize(); | ||
437 | if (filePos >= endPos) | 466 | if (filePos >= endPos) { | ||
438 | return list; | 467 | return list; | ||
439 | qint64 startPos = filePos; | 468 | } | ||
440 | int bytes = _lister->hexBytesPerLine(_sizeX); | 469 | const int bytes = _lister->hexBytesPerLine(_sizeX); | ||
441 | filePos = startPos = ((startPos) / bytes) * bytes; | 470 | qint64 startPos = (filePos / bytes) * bytes; | ||
442 | list = _lister->readHexLines(filePos, endPos, _sizeX, lines); | 471 | qint64 shiftPos = startPos; | ||
443 | endPos = filePos; | 472 | list = _lister->readHexLines(shiftPos, endPos, _sizeX, lines); | ||
473 | endPos = shiftPos; | ||||
444 | if (locs) { | 474 | if (locs) { | ||
445 | for (int i = 0; i != list.count(); i++) { | 475 | for (int i = 0; i < list.count(); i++) { | ||
446 | (*locs) << startPos; | 476 | (*locs) << startPos; | ||
447 | startPos += bytes; | 477 | startPos += bytes; | ||
448 | } | 478 | } | ||
Context not available. | |||||
450 | return list; | 480 | return list; | ||
451 | } | 481 | } | ||
452 | 482 | | |||
483 | endPos = filePos; | ||||
453 | int maxBytes = _sizeX * _sizeY * MAX_CHAR_LENGTH; | 484 | int maxBytes = _sizeX * _sizeY * MAX_CHAR_LENGTH; | ||
454 | char * cache = _lister->cacheRef(filePos, maxBytes); | 485 | const QByteArray cache = _lister->cacheChunk(filePos, maxBytes); | ||
455 | if (cache == 0 || maxBytes == 0) | 486 | if (cache.isEmpty() || maxBytes == 0) | ||
456 | return list; | 487 | return list; | ||
457 | 488 | | |||
458 | QTextCodec * textCodec = codec(); | 489 | int byteCounter = 0; | ||
459 | QTextDecoder * decoder = textCodec->makeDecoder(); | | |||
460 | | ||||
461 | int cnt = 0; | | |||
462 | int y = 0; | | |||
463 | QString row = ""; | 490 | QString row = ""; | ||
464 | int effLength = 0; | 491 | int effLength = 0; | ||
465 | if (locs) | 492 | if (locs) | ||
466 | (*locs) << filePos; | 493 | (*locs) << filePos; | ||
467 | bool isLastLongLine = false; | 494 | bool skipImmediateNewline = false; | ||
468 | while (cnt < maxBytes && y < lines) { | 495 | | ||
469 | int lastCnt = cnt; | 496 | const auto performNewline = [&] (qint64 nextRowStartOffset) { | ||
470 | QString chr = decoder->toUnicode(cache + (cnt++), 1); | 497 | list << row; | ||
471 | if (!chr.isEmpty()) { | 498 | effLength = 0; | ||
472 | if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) | 499 | row = ""; | ||
473 | chr = QChar(CONTROL_CHAR); | 500 | if (locs) { | ||
474 | if (chr == "\n") { | 501 | (*locs) << (filePos + nextRowStartOffset); | ||
475 | if (!isLastLongLine) { | 502 | } | ||
476 | list << row; | 503 | }; | ||
477 | effLength = 0; | 504 | | ||
478 | row = ""; | 505 | while (byteCounter < maxBytes && list.size() < lines) { | ||
479 | y++; | 506 | const int lastCnt = byteCounter; | ||
480 | if (locs) | 507 | QString chr = _lister->codec()->toUnicode(cache.mid(byteCounter++, 1)); | ||
481 | (*locs) << filePos + cnt; | 508 | if (chr.isEmpty()) { | ||
482 | } | 509 | continue; | ||
483 | isLastLongLine = false; | 510 | } | ||
484 | } else { | 511 | | ||
485 | isLastLongLine = false; | 512 | if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) { | ||
486 | if (chr == "\t") { | 513 | chr = QChar(CONTROL_CHAR); | ||
487 | effLength += _tabWidth - (effLength % _tabWidth) - 1; | 514 | } | ||
488 | if (effLength > _sizeX) { | 515 | | ||
489 | list << row; | 516 | if (chr == "\n") { | ||
490 | effLength = 0; | 517 | if (!skipImmediateNewline) { | ||
491 | row = ""; | 518 | performNewline(byteCounter); | ||
492 | y++; | | |||
493 | if (locs) | | |||
494 | (*locs) << filePos + lastCnt; | | |||
495 | } | | |||
496 | } | | |||
497 | row += chr; | | |||
498 | effLength++; | | |||
499 | if (effLength >= _sizeX) { | | |||
500 | list << row; | | |||
501 | effLength = 0; | | |||
502 | row = ""; | | |||
503 | y++; | | |||
504 | if (locs) | | |||
505 | (*locs) << filePos + cnt; | | |||
506 | isLastLongLine = true; | | |||
507 | } | | |||
508 | } | 519 | } | ||
520 | skipImmediateNewline = false; | ||||
521 | continue; | ||||
509 | } | 522 | } | ||
510 | } | | |||
511 | 523 | | |||
512 | if (y < lines) | 524 | skipImmediateNewline = false; | ||
513 | list << row; | | |||
514 | 525 | | |||
515 | if (locs) { | 526 | if (chr == "\t") { | ||
516 | while (locs->count() > lines) { | 527 | effLength += _tabWidth - (effLength % _tabWidth) - 1; | ||
517 | locs->removeLast(); | 528 | if (effLength > _sizeX) { | ||
529 | performNewline(lastCnt); | ||||
530 | } | ||||
531 | } | ||||
532 | row += chr; | ||||
533 | effLength++; | ||||
534 | if (effLength >= _sizeX) { | ||||
535 | performNewline(byteCounter); | ||||
536 | skipImmediateNewline = true; | ||||
518 | } | 537 | } | ||
519 | } | 538 | } | ||
520 | 539 | | |||
521 | endPos = filePos + cnt; | 540 | if (list.size() < lines) | ||
541 | list << row; | ||||
522 | 542 | | |||
523 | delete decoder; | 543 | endPos = filePos + byteCounter; | ||
524 | return list; | | |||
525 | } | | |||
526 | 544 | | |||
527 | QTextCodec * ListerTextArea::codec() | 545 | return list; | ||
528 | { | | |||
529 | QString cs = _lister->characterSet(); | | |||
530 | if (cs.isEmpty()) | | |||
531 | return QTextCodec::codecForLocale(); | | |||
532 | else | | |||
533 | return KCharsets::charsets()->codecForName(cs); | | |||
534 | } | 546 | } | ||
535 | 547 | | |||
536 | void ListerTextArea::setUpScrollBar() | 548 | void ListerTextArea::setUpScrollBar() | ||
Context not available. | |||||
541 | _lister->scrollBar()->hide(); | 553 | _lister->scrollBar()->hide(); | ||
542 | _lastPageStartPos = 0; | 554 | _lastPageStartPos = 0; | ||
543 | } else { | 555 | } else { | ||
544 | int maxPage = MAX_CHAR_LENGTH * _sizeX * _sizeY; | 556 | const int maxPage = MAX_CHAR_LENGTH * _sizeX * _sizeY; | ||
545 | qint64 pageStartPos = _lister->fileSize() - maxPage; | 557 | qint64 pageStartPos = _lister->fileSize() - maxPage; | ||
546 | qint64 endPos; | 558 | qint64 endPos; | ||
547 | if (pageStartPos < 0) | 559 | if (pageStartPos < 0) | ||
Context not available. | |||||
553 | readLines(pageStartPos, _lastPageStartPos, list.count() - _sizeY); | 565 | readLines(pageStartPos, _lastPageStartPos, list.count() - _sizeY); | ||
554 | } | 566 | } | ||
555 | 567 | | |||
556 | int maximum = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX : _lastPageStartPos; | 568 | const int maximum = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX : _lastPageStartPos; | ||
557 | int pageSize = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _averagePageSize / _lastPageStartPos : _averagePageSize; | 569 | int pageSize = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _averagePageSize / _lastPageStartPos : _averagePageSize; | ||
558 | if (pageSize == 0) | 570 | if (pageSize == 0) | ||
559 | pageSize++; | 571 | pageSize++; | ||
Context not available. | |||||
622 | ensureVisibleCursor(); | 634 | ensureVisibleCursor(); | ||
623 | int x, y; | 635 | int x, y; | ||
624 | getCursorPosition(x, y); | 636 | getCursorPosition(x, y); | ||
625 | if (y >= _sizeY) | 637 | if (y >= _sizeY-1) | ||
626 | slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); | 638 | slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); | ||
627 | } | 639 | } | ||
628 | break; | 640 | break; | ||
Context not available. | |||||
641 | else | 653 | else | ||
642 | x = 0; | 654 | x = 0; | ||
643 | } | 655 | } | ||
644 | _cursorPos = textToFilePosition(x, y, _cursorAtFirstColumn); | 656 | _cursorPos = textToFilePositionOnScreen(x, y, _cursorAtFirstColumn); | ||
645 | setCursorPosition(_cursorPos, _cursorAtFirstColumn); | 657 | setCursorPositionInDocument(_cursorPos, _cursorAtFirstColumn); | ||
646 | } | 658 | } | ||
647 | return; | 659 | return; | ||
648 | case Qt::Key_PageUp: { | 660 | case Qt::Key_PageUp: { | ||
Context not available. | |||||
657 | y = 0; | 669 | y = 0; | ||
658 | x = 0; | 670 | x = 0; | ||
659 | } | 671 | } | ||
660 | _cursorPos = textToFilePosition(x, y, _cursorAtFirstColumn); | 672 | _cursorPos = textToFilePositionOnScreen(x, y, _cursorAtFirstColumn); | ||
661 | setCursorPosition(_cursorPos, _cursorAtFirstColumn); | 673 | setCursorPositionInDocument(_cursorPos, _cursorAtFirstColumn); | ||
662 | } | 674 | } | ||
663 | return; | 675 | return; | ||
664 | } | 676 | } | ||
Context not available. | |||||
677 | _cursorAnchorPos = -1; | 689 | _cursorAnchorPos = -1; | ||
678 | ke->accept(); | 690 | ke->accept(); | ||
679 | slotActionTriggered(QAbstractSlider::SliderToMinimum); | 691 | slotActionTriggered(QAbstractSlider::SliderToMinimum); | ||
680 | setCursorPosition((qint64)0, true); | 692 | setCursorPositionInDocument((qint64)0, true); | ||
681 | return; | 693 | return; | ||
682 | case Qt::Key_A: | 694 | case Qt::Key_A: | ||
683 | case Qt::Key_End: { | 695 | case Qt::Key_End: { | ||
684 | _cursorAnchorPos = (ke->key() == Qt::Key_A) ? 0 : -1; | 696 | _cursorAnchorPos = (ke->key() == Qt::Key_A) ? 0 : -1; | ||
685 | ke->accept(); | 697 | ke->accept(); | ||
686 | slotActionTriggered(QAbstractSlider::SliderToMaximum); | 698 | slotActionTriggered(QAbstractSlider::SliderToMaximum); | ||
687 | qint64 endPos = _lister->fileSize(); | 699 | const qint64 endPos = _lister->fileSize(); | ||
688 | setCursorPosition(endPos, true); | 700 | setCursorPositionInDocument(endPos, true); | ||
689 | return; | 701 | return; | ||
690 | } | 702 | } | ||
691 | case Qt::Key_Down: | 703 | case Qt::Key_Down: | ||
Context not available. | |||||
706 | return; | 718 | return; | ||
707 | } | 719 | } | ||
708 | } | 720 | } | ||
709 | int oldAnchor = textCursor().anchor(); | 721 | const int oldAnchor = textCursor().anchor(); | ||
710 | KTextEdit::keyPressEvent(ke); | 722 | KTextEdit::keyPressEvent(ke); | ||
711 | handleAnchorChange(oldAnchor); | 723 | handleAnchorChange(oldAnchor); | ||
712 | } | 724 | } | ||
Context not available. | |||||
723 | void ListerTextArea::mouseDoubleClickEvent(QMouseEvent * e) | 735 | void ListerTextArea::mouseDoubleClickEvent(QMouseEvent * e) | ||
724 | { | 736 | { | ||
725 | _cursorAnchorPos = -1; | 737 | _cursorAnchorPos = -1; | ||
726 | int oldAnchor = textCursor().anchor(); | 738 | const int oldAnchor = textCursor().anchor(); | ||
727 | KTextEdit::mouseDoubleClickEvent(e); | 739 | KTextEdit::mouseDoubleClickEvent(e); | ||
728 | handleAnchorChange(oldAnchor); | 740 | handleAnchorChange(oldAnchor); | ||
729 | } | 741 | } | ||
Context not available. | |||||
771 | delta += 120; | 783 | delta += 120; | ||
772 | } | 784 | } | ||
773 | } | 785 | } | ||
786 | | ||||
787 | setCursorPositionInDocument(_cursorPos, false); | ||||
774 | } | 788 | } | ||
775 | } | 789 | } | ||
776 | 790 | | |||
Context not available. | |||||
786 | } | 800 | } | ||
787 | break; | 801 | break; | ||
788 | case QAbstractSlider::SliderSingleStepSub: { | 802 | case QAbstractSlider::SliderSingleStepSub: { | ||
789 | if (_screenStartPos == 0) | 803 | if (_screenStartPos == 0) { | ||
790 | break; | 804 | break; | ||
805 | } | ||||
791 | 806 | | |||
792 | if (_hexMode) { | 807 | if (_hexMode) { | ||
793 | int bytesPerRow = _lister->hexBytesPerLine(_sizeX); | 808 | int bytesPerRow = _lister->hexBytesPerLine(_sizeX); | ||
794 | _screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow; | 809 | _screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow; | ||
795 | _screenStartPos -= bytesPerRow; | 810 | _screenStartPos -= bytesPerRow; | ||
796 | if (_screenStartPos < 0) | 811 | if (_screenStartPos < 0) { | ||
797 | _screenStartPos = 0; | 812 | _screenStartPos = 0; | ||
798 | } else { | 813 | } | ||
799 | int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH; | 814 | break; | ||
800 | QByteArray encodedEnter = codec()->fromUnicode(QString("\n")); | 815 | } | ||
801 | 816 | | |||
802 | qint64 readPos = _screenStartPos - maxSize; | 817 | int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH; | ||
803 | if (readPos < 0) | 818 | const QByteArray encodedEnter = _lister->codec()->fromUnicode(QString("\n")); | ||
804 | readPos = 0; | | |||
805 | maxSize = _screenStartPos - readPos; | | |||
806 | 819 | | |||
807 | char * cache = _lister->cacheRef(readPos, maxSize); | 820 | qint64 readPos = _screenStartPos - maxSize; | ||
808 | QByteArray backBuffer(cache, maxSize); | 821 | if (readPos < 0) { | ||
822 | readPos = 0; | ||||
823 | } | ||||
824 | maxSize = _screenStartPos - readPos; | ||||
809 | 825 | | |||
810 | int from = maxSize; | 826 | const QByteArray cache = _lister->cacheChunk(readPos, maxSize); | ||
811 | while (from > 0) { | | |||
812 | from--; | | |||
813 | from = backBuffer.lastIndexOf(encodedEnter, from); | | |||
814 | if (from == -1) | | |||
815 | break; | | |||
816 | int backRef = from - 20; | | |||
817 | if (backRef < 0) | | |||
818 | backRef = 0; | | |||
819 | int size = from - backRef + encodedEnter.size(); | | |||
820 | QString decoded = codec()->toUnicode(cache + backRef, size); | | |||
821 | if (decoded.endsWith(QLatin1String("\n"))) { | | |||
822 | if (from < (maxSize - encodedEnter.size())) { | | |||
823 | from += encodedEnter.size(); | | |||
824 | break; | | |||
825 | } | | |||
826 | } | | |||
827 | } | | |||
828 | 827 | | |||
829 | if (from == -1) | 828 | int from = maxSize; | ||
829 | while (from > 0) { | ||||
830 | from--; | ||||
831 | from = cache.lastIndexOf(encodedEnter, from); | ||||
832 | if (from == -1) { | ||||
830 | from = 0; | 833 | from = 0; | ||
831 | readPos += from; | 834 | break; | ||
832 | | ||||
833 | qint64 previousPos = readPos; | | |||
834 | | ||||
835 | while (readPos < _screenStartPos) { | | |||
836 | previousPos = readPos; | | |||
837 | readLines(readPos, readPos, 1); | | |||
838 | } | 835 | } | ||
836 | const int backRef = std::max(from - 20, 0); | ||||
837 | const int size = from - backRef + encodedEnter.size(); | ||||
838 | const QString decoded = _lister->codec()->toUnicode(cache.mid(backRef, size)); | ||||
839 | if (decoded.endsWith(QLatin1String("\n"))) { | ||||
840 | if (from < (maxSize - encodedEnter.size())) { | ||||
841 | from += encodedEnter.size(); | ||||
842 | break; | ||||
843 | } | ||||
844 | } | ||||
845 | } | ||||
839 | 846 | | |||
840 | _screenStartPos = previousPos; | 847 | readPos += from; | ||
848 | qint64 previousPos = readPos; | ||||
849 | while (readPos < _screenStartPos) { | ||||
850 | previousPos = readPos; | ||||
851 | readLines(readPos, readPos, 1); | ||||
841 | } | 852 | } | ||
853 | _screenStartPos = previousPos; | ||||
842 | } | 854 | } | ||
843 | break; | 855 | break; | ||
844 | case QAbstractSlider::SliderPageStepAdd: { | 856 | case QAbstractSlider::SliderPageStepAdd: { | ||
Context not available. | |||||
859 | case QAbstractSlider::SliderPageStepSub: { | 871 | case QAbstractSlider::SliderPageStepSub: { | ||
860 | _skippedLines = 0; | 872 | _skippedLines = 0; | ||
861 | 873 | | |||
862 | if (_screenStartPos == 0) | 874 | if (_screenStartPos == 0) { | ||
863 | break; | 875 | break; | ||
876 | } | ||||
864 | 877 | | |||
865 | if (_hexMode) { | 878 | if (_hexMode) { | ||
866 | int bytesPerRow = _lister->hexBytesPerLine(_sizeX); | 879 | const int bytesPerRow = _lister->hexBytesPerLine(_sizeX); | ||
867 | _screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow; | 880 | _screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow; | ||
868 | _screenStartPos -= _sizeY * bytesPerRow; | 881 | _screenStartPos -= _sizeY * bytesPerRow; | ||
869 | if (_screenStartPos < 0) | 882 | if (_screenStartPos < 0) { | ||
870 | _screenStartPos = 0; | 883 | _screenStartPos = 0; | ||
871 | } else { | 884 | } | ||
872 | int maxSize = 2 * _sizeX * _sizeY * MAX_CHAR_LENGTH; | 885 | break; | ||
873 | QByteArray encodedEnter = codec()->fromUnicode(QString("\n")); | 886 | } | ||
874 | 887 | | |||
875 | qint64 readPos = _screenStartPos - maxSize; | 888 | // text lister mode | ||
876 | if (readPos < 0) | 889 | int maxSize = 2 * _sizeX * _sizeY * MAX_CHAR_LENGTH; | ||
877 | readPos = 0; | 890 | const QByteArray encodedEnter = _lister->codec()->fromUnicode(QString("\n")); | ||
878 | maxSize = _screenStartPos - readPos; | | |||
879 | 891 | | |||
880 | char * cache = _lister->cacheRef(readPos, maxSize); | 892 | qint64 readPos = _screenStartPos - maxSize; | ||
881 | QByteArray backBuffer(cache, maxSize); | 893 | if (readPos < 0) | ||
894 | readPos = 0; | ||||
895 | maxSize = _screenStartPos - readPos; | ||||
882 | 896 | | |||
883 | int sizeY = _sizeY + 1; | 897 | const QByteArray cache = _lister->cacheChunk(readPos, maxSize); | ||
884 | int origSizeY = sizeY; | | |||
885 | int from = maxSize; | | |||
886 | int lastEnter = maxSize; | | |||
887 | 898 | | |||
888 | repeat: while (from > 0) { | 899 | int sizeY = _sizeY + 1; | ||
900 | int origSizeY = sizeY; | ||||
901 | int from = maxSize; | ||||
902 | int lastEnter = maxSize; | ||||
903 | | ||||
904 | bool readNext = true; | ||||
905 | while (readNext) { | ||||
906 | readNext = false; | ||||
907 | while (from > 0) { | ||||
889 | from--; | 908 | from--; | ||
890 | from = backBuffer.lastIndexOf(encodedEnter, from); | 909 | from = cache.lastIndexOf(encodedEnter, from); | ||
891 | if (from == -1) | 910 | if (from == -1) { | ||
911 | from = 0; | ||||
892 | break; | 912 | break; | ||
893 | int backRef = from - 20; | 913 | } | ||
894 | if (backRef < 0) | 914 | const int backRef = std::max(from - 20, 0); | ||
895 | backRef = 0; | 915 | const int size = from - backRef + encodedEnter.size(); | ||
896 | int size = from - backRef + encodedEnter.size(); | 916 | QString decoded = _lister->codec()->toUnicode(cache.mid(backRef, size)); | ||
897 | QString decoded = codec()->toUnicode(cache + backRef, size); | | |||
898 | if (decoded.endsWith(QLatin1String("\n"))) { | 917 | if (decoded.endsWith(QLatin1String("\n"))) { | ||
899 | if (from < (maxSize - encodedEnter.size())) { | 918 | if (from < (maxSize - encodedEnter.size())) { | ||
900 | int arrayStart = from + encodedEnter.size(); | 919 | int arrayStart = from + encodedEnter.size(); | ||
901 | decoded = codec()->toUnicode(cache + arrayStart, lastEnter - arrayStart); | 920 | decoded = _lister->codec()->toUnicode(cache.mid(arrayStart, lastEnter - arrayStart)); | ||
902 | sizeY -= ((decoded.length() / (_sizeX + 1)) + 1); | 921 | sizeY -= ((decoded.length() / (_sizeX + 1)) + 1); | ||
903 | if (sizeY < 0) { | 922 | if (sizeY < 0) { | ||
904 | from = arrayStart; | 923 | from = arrayStart; | ||
Context not available. | |||||
909 | } | 928 | } | ||
910 | } | 929 | } | ||
911 | 930 | | |||
912 | if (from == -1) | | |||
913 | from = 0; | | |||
914 | qint64 searchPos = readPos + from; | 931 | qint64 searchPos = readPos + from; | ||
915 | | ||||
916 | QList<qint64> locs; | 932 | QList<qint64> locs; | ||
917 | while (searchPos < _screenStartPos) { | 933 | while (searchPos < _screenStartPos) { | ||
918 | locs << searchPos; | 934 | locs << searchPos; | ||
919 | readLines(searchPos, searchPos, 1); | 935 | readLines(searchPos, searchPos, 1); | ||
920 | } | 936 | } | ||
921 | 937 | | |||
922 | if (locs.count() >= _sizeY) | 938 | if (locs.count() >= _sizeY) { | ||
923 | _screenStartPos = locs[ locs.count() - _sizeY ]; | 939 | _screenStartPos = locs[ locs.count() - _sizeY ]; | ||
924 | else if (from != 0) { | 940 | } else if (from != 0) { | ||
925 | origSizeY += locs.count() + 1; | 941 | origSizeY += locs.count() + 1; | ||
926 | sizeY = origSizeY; | 942 | sizeY = origSizeY; | ||
927 | goto repeat; | 943 | readNext = true; | ||
928 | } else if (readPos == 0) | 944 | } else if (readPos == 0) { | ||
929 | _screenStartPos = 0; | 945 | _screenStartPos = 0; | ||
946 | } | ||||
930 | } | 947 | } | ||
948 | | ||||
931 | } | 949 | } | ||
932 | break; | 950 | break; | ||
933 | case QAbstractSlider::SliderToMinimum: | 951 | case QAbstractSlider::SliderToMinimum: | ||
Context not available. | |||||
954 | 972 | | |||
955 | if (pos != 0) { | 973 | if (pos != 0) { | ||
956 | if (_hexMode) { | 974 | if (_hexMode) { | ||
957 | int bytesPerRow = _lister->hexBytesPerLine(_sizeX); | 975 | const int bytesPerRow = _lister->hexBytesPerLine(_sizeX); | ||
958 | pos = (pos / bytesPerRow) * bytesPerRow; | 976 | pos = (pos / bytesPerRow) * bytesPerRow; | ||
959 | } else { | 977 | } else { | ||
960 | int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH; | 978 | const int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH; | ||
961 | qint64 readPos = pos - maxSize; | 979 | qint64 readPos = pos - maxSize; | ||
962 | if (readPos < 0) | 980 | if (readPos < 0) | ||
963 | readPos = 0; | 981 | readPos = 0; | ||
Context not available. | |||||
980 | }; | 998 | }; | ||
981 | 999 | | |||
982 | _inSliderOp = true; | 1000 | _inSliderOp = true; | ||
983 | int value = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _screenStartPos / _lastPageStartPos : _screenStartPos; | 1001 | const int value = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _screenStartPos / _lastPageStartPos : _screenStartPos; | ||
984 | _lister->scrollBar()->setSliderPosition(value); | 1002 | _lister->scrollBar()->setSliderPosition(value); | ||
985 | _inSliderOp = false; | 1003 | _inSliderOp = false; | ||
986 | 1004 | | |||
Context not available. | |||||
990 | void ListerTextArea::redrawTextArea(bool forcedUpdate) | 1008 | void ListerTextArea::redrawTextArea(bool forcedUpdate) | ||
991 | { | 1009 | { | ||
992 | bool isfirst; | 1010 | bool isfirst; | ||
993 | qint64 pos = getCursorPosition(isfirst); | 1011 | const qint64 pos = getCursorPosition(isfirst); | ||
994 | calculateText(forcedUpdate); | 1012 | calculateText(forcedUpdate); | ||
995 | setCursorPosition(pos, isfirst); | 1013 | setCursorPositionInDocument(pos, isfirst); | ||
996 | } | 1014 | } | ||
997 | 1015 | | |||
998 | void ListerTextArea::ensureVisibleCursor() | 1016 | void ListerTextArea::ensureVisibleCursor() | ||
999 | { | 1017 | { | ||
1000 | if (_cursorPos < _screenStartPos || _cursorPos > _screenEndPos) { | 1018 | if (_screenStartPos <= _cursorPos && _cursorPos <= _screenEndPos) { | ||
1001 | int delta = _sizeY / 2; | 1019 | return; | ||
1002 | if (delta == 0) | 1020 | } | ||
1003 | delta++; | | |||
1004 | 1021 | | |||
1005 | qint64 newScreenStart = _cursorPos; | 1022 | int delta = _sizeY / 2; | ||
1006 | while (delta) { | 1023 | if (delta == 0) | ||
1007 | int maxSize = _sizeX * MAX_CHAR_LENGTH; | 1024 | delta++; | ||
1008 | qint64 readPos = newScreenStart - maxSize; | | |||
1009 | if (readPos < 0) | | |||
1010 | readPos = 0; | | |||
1011 | 1025 | | |||
1012 | qint64 previousPos = readPos; | 1026 | qint64 newScreenStart = _cursorPos; | ||
1027 | while (delta) { | ||||
1028 | const int maxSize = _sizeX * MAX_CHAR_LENGTH; | ||||
1029 | qint64 readPos = newScreenStart - maxSize; | ||||
1030 | if (readPos < 0) | ||||
1031 | readPos = 0; | ||||
1013 | 1032 | | |||
1014 | while (readPos < newScreenStart) { | 1033 | qint64 previousPos = readPos; | ||
1015 | previousPos = readPos; | | |||
1016 | readLines(readPos, readPos, 1); | | |||
1017 | if (readPos == previousPos) | | |||
1018 | break; | | |||
1019 | } | | |||
1020 | 1034 | | |||
1021 | newScreenStart = previousPos; | 1035 | while (readPos < newScreenStart) { | ||
1022 | delta--; | 1036 | previousPos = readPos; | ||
1037 | readLines(readPos, readPos, 1); | ||||
1038 | if (readPos == previousPos) | ||||
1039 | break; | ||||
1023 | } | 1040 | } | ||
1024 | if (newScreenStart > _lastPageStartPos) | | |||
1025 | newScreenStart = _lastPageStartPos; | | |||
1026 | 1041 | | |||
1027 | _screenStartPos = newScreenStart; | 1042 | newScreenStart = previousPos; | ||
1028 | slotActionTriggered(QAbstractSlider::SliderNoAction); | 1043 | delta--; | ||
1044 | } | ||||
1045 | if (newScreenStart > _lastPageStartPos) { | ||||
1046 | newScreenStart = _lastPageStartPos; | ||||
1029 | } | 1047 | } | ||
1048 | | ||||
1049 | _screenStartPos = newScreenStart; | ||||
1050 | slotActionTriggered(QAbstractSlider::SliderNoAction); | ||||
1030 | } | 1051 | } | ||
1031 | 1052 | | |||
1032 | void ListerTextArea::setAnchorAndCursor(qint64 anchor, qint64 cursor) | 1053 | void ListerTextArea::setAnchorAndCursor(qint64 anchor, qint64 cursor) | ||
1033 | { | 1054 | { | ||
1055 | _cursorPos = cursor; | ||||
1034 | _cursorAnchorPos = anchor; | 1056 | _cursorAnchorPos = anchor; | ||
1035 | setCursorPosition(cursor, false); | | |||
1036 | ensureVisibleCursor(); | 1057 | ensureVisibleCursor(); | ||
1058 | setCursorPositionInDocument(cursor, false); | ||||
1037 | } | 1059 | } | ||
1038 | 1060 | | |||
1039 | QString ListerTextArea::getSelectedText() | 1061 | QString ListerTextArea::getSelectedText() | ||
Context not available. | |||||
1046 | 1068 | | |||
1047 | void ListerTextArea::copySelectedToClipboard() | 1069 | void ListerTextArea::copySelectedToClipboard() | ||
1048 | { | 1070 | { | ||
1049 | QString selection = getSelectedText(); | 1071 | const QString selection = getSelectedText(); | ||
1050 | if (!selection.isEmpty()) { | 1072 | if (!selection.isEmpty()) { | ||
1051 | QApplication::clipboard()->setText(selection); | 1073 | QApplication::clipboard()->setText(selection); | ||
1052 | } | 1074 | } | ||
Context not available. | |||||
1065 | int x, y; | 1087 | int x, y; | ||
1066 | bool isfirst; | 1088 | bool isfirst; | ||
1067 | getScreenPosition(anchor, x, y); | 1089 | getScreenPosition(anchor, x, y); | ||
1068 | _cursorAnchorPos = textToFilePosition(x, y, isfirst); | 1090 | _cursorAnchorPos = textToFilePositionOnScreen(x, y, isfirst); | ||
1069 | } | 1091 | } | ||
1070 | 1092 | | |||
1071 | void ListerTextArea::handleAnchorChange(int oldAnchor) | 1093 | void ListerTextArea::handleAnchorChange(int oldAnchor) | ||
1072 | { | 1094 | { | ||
1073 | int anchor = textCursor().anchor(); | 1095 | const int anchor = textCursor().anchor(); | ||
1074 | 1096 | | |||
1075 | if (oldAnchor != anchor) { | 1097 | if (oldAnchor != anchor) { | ||
1076 | performAnchorChange(anchor); | 1098 | performAnchorChange(anchor); | ||
Context not available. | |||||
1080 | void ListerTextArea::setHexMode(bool hexMode) | 1102 | void ListerTextArea::setHexMode(bool hexMode) | ||
1081 | { | 1103 | { | ||
1082 | bool isfirst; | 1104 | bool isfirst; | ||
1083 | qint64 pos = getCursorPosition(isfirst); | 1105 | const qint64 pos = getCursorPosition(isfirst); | ||
1084 | _hexMode = hexMode; | 1106 | _hexMode = hexMode; | ||
1085 | _screenStartPos = 0; | 1107 | _screenStartPos = 0; | ||
1086 | calculateText(true); | 1108 | calculateText(true); | ||
1087 | setCursorPosition(pos, isfirst); | 1109 | setCursorPositionInDocument(pos, isfirst); | ||
1088 | ensureVisibleCursor(); | 1110 | ensureVisibleCursor(); | ||
1089 | } | 1111 | } | ||
1090 | 1112 | | |||
Context not available. | |||||
1106 | 1128 | | |||
1107 | bool ListerPane::event(QEvent *e) | 1129 | bool ListerPane::event(QEvent *e) | ||
1108 | { | 1130 | { | ||
1109 | bool handled = ListerPane::handleCloseEvent(e); | 1131 | const bool handled = ListerPane::handleCloseEvent(e); | ||
1110 | if (!handled) { | 1132 | if (!handled) { | ||
1111 | return QWidget::event(e); | 1133 | return QWidget::event(e); | ||
1112 | } | 1134 | } | ||
Context not available. | |||||
1176 | Lister * _lister; | 1198 | Lister * _lister; | ||
1177 | }; | 1199 | }; | ||
1178 | 1200 | | |||
1179 | Lister::Lister(QWidget *parent) : KParts::ReadOnlyPart(parent), _searchInProgress(false), _cache(0), _active(false), _searchLastFailedPosition(-1), | 1201 | Lister::Lister(QWidget *parent) : KParts::ReadOnlyPart(parent), _searchInProgress(false), _cache(0), _searchLastFailedPosition(-1), | ||
1180 | _searchProgressCounter(0), _tempFile(0), _downloading(false) | 1202 | _searchProgressCounter(0), _tempFile(0), _downloading(false) | ||
1181 | { | 1203 | { | ||
1182 | setXMLFile("krusaderlisterui.rc"); | 1204 | setXMLFile("krusaderlisterui.rc"); | ||
Context not available. | |||||
1290 | 1312 | | |||
1291 | hbox->addWidget(_searchOptions); | 1313 | hbox->addWidget(_searchOptions); | ||
1292 | 1314 | | |||
1293 | QSpacerItem* cbSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); | 1315 | hbox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); | ||
1294 | hbox->addItem(cbSpacer); | | |||
1295 | 1316 | | |||
1296 | _statusLabel = new QLabel(statusWidget); | 1317 | _statusLabel = new QLabel(statusWidget); | ||
1297 | hbox->addWidget(_statusLabel); | 1318 | hbox->addWidget(_statusLabel); | ||
Context not available. | |||||
1300 | setWidget(widget); | 1321 | setWidget(widget); | ||
1301 | 1322 | | |||
1302 | connect(_scrollBar, SIGNAL(actionTriggered(int)), _textArea, SLOT(slotActionTriggered(int))); | 1323 | connect(_scrollBar, SIGNAL(actionTriggered(int)), _textArea, SLOT(slotActionTriggered(int))); | ||
1303 | connect(&_updateTimer, SIGNAL(timeout()), this, SLOT(slotUpdate())); | 1324 | connect(&_searchUpdateTimer, &QTimer::timeout, this, &Lister::slotUpdate); | ||
1304 | | ||||
1305 | _updateTimer.setSingleShot(false); | | |||
1306 | 1325 | | |||
1307 | new ListerBrowserExtension(this); | 1326 | new ListerBrowserExtension(this); | ||
1308 | enableSearch(false); | 1327 | enableSearch(false); | ||
1309 | } | | |||
1310 | 1328 | | |||
1311 | Lister::~Lister() | 1329 | _tempFile = new QTemporaryFile(this); | ||
1312 | { | 1330 | _tempFile->setFileTemplate(QDir::tempPath() + QLatin1String("/krusader_lister.XXXXXX")); | ||
1313 | if (_cache != 0) { | | |||
1314 | delete []_cache; | | |||
1315 | _cache = 0; | | |||
1316 | } | | |||
1317 | if (_tempFile != 0) { | | |||
1318 | delete _tempFile; | | |||
1319 | _tempFile = 0; | | |||
1320 | } | | |||
1321 | } | 1331 | } | ||
1322 | 1332 | | |||
1323 | bool Lister::openUrl(const QUrl &listerUrl) | 1333 | bool Lister::openUrl(const QUrl &listerUrl) | ||
Context not available. | |||||
1325 | _downloading = false; | 1335 | _downloading = false; | ||
1326 | setUrl(listerUrl); | 1336 | setUrl(listerUrl); | ||
1327 | 1337 | | |||
1328 | if (_tempFile) { | | |||
1329 | delete _tempFile; | | |||
1330 | _tempFile = 0; | | |||
1331 | } | | |||
1332 | _fileSize = 0; | 1338 | _fileSize = 0; | ||
1333 | 1339 | | |||
1334 | if (listerUrl.isLocalFile()) { | 1340 | if (listerUrl.isLocalFile()) { | ||
Context not available. | |||||
1337 | return false; | 1343 | return false; | ||
1338 | _fileSize = getFileSize(); | 1344 | _fileSize = getFileSize(); | ||
1339 | } else { | 1345 | } else { | ||
1340 | _tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX_") + listerUrl.fileName()); | 1346 | if (_tempFile->isOpen()) { | ||
1347 | _tempFile->close(); | ||||
1348 | } | ||||
1341 | _tempFile->open(); | 1349 | _tempFile->open(); | ||
1342 | 1350 | | |||
1343 | _filePath = _tempFile->fileName(); | 1351 | _filePath = _tempFile->fileName(); | ||
1344 | 1352 | | |||
1345 | KIO::Job * downloadJob = KIO::get(listerUrl, KIO::NoReload, KIO::HideProgressInfo); | 1353 | KIO::TransferJob *downloadJob = KIO::get(listerUrl, KIO::NoReload, KIO::HideProgressInfo); | ||
1346 | 1354 | | |||
1347 | connect(downloadJob, SIGNAL(data(KIO::Job*,QByteArray)), | 1355 | connect(downloadJob, &KIO::TransferJob::data, this, [=](KIO::Job*, QByteArray array) { | ||
1348 | this, SLOT(slotFileDataReceived(KIO::Job*,QByteArray))); | 1356 | if (array.size() != 0) { | ||
1349 | connect(downloadJob, SIGNAL(result(KJob*)), | 1357 | _tempFile->write(array); | ||
1350 | this, SLOT(slotFileFinished(KJob*))); | 1358 | } }); | ||
1351 | _downloading = false; | 1359 | connect(downloadJob, &KIO::TransferJob::result, this, [=](KJob *job) { | ||
1352 | } | 1360 | _tempFile->flush(); | ||
1353 | if (_cache) { | 1361 | if (job->error()) { /* any error occurred? */ | ||
1354 | delete []_cache; | 1362 | KIO::TransferJob *kioJob = (KIO::TransferJob *)job; | ||
1355 | _cache = 0; | 1363 | KMessageBox::error(_textArea, i18n("Error reading file %1.", kioJob->url().toDisplayString(QUrl::PreferLocalFile))); | ||
1364 | } | ||||
1365 | _downloading = false; | ||||
1366 | }); | ||||
1367 | _downloading = true; | ||||
1356 | } | 1368 | } | ||
1369 | | ||||
1370 | // invalidate cache | ||||
1371 | _cache.clear(); | ||||
1372 | | ||||
1357 | _textArea->reset(); | 1373 | _textArea->reset(); | ||
1358 | emit started(0); | 1374 | emit started(0); | ||
1359 | emit setWindowCaption(listerUrl.toDisplayString()); | 1375 | emit setWindowCaption(listerUrl.toDisplayString()); | ||
Context not available. | |||||
1361 | return true; | 1377 | return true; | ||
1362 | } | 1378 | } | ||
1363 | 1379 | | |||
1364 | void Lister::slotFileDataReceived(KIO::Job *, const QByteArray &array) | 1380 | QByteArray Lister::cacheChunk(const qint64 filePos, int &size) | ||
1365 | { | 1381 | { | ||
1366 | if (array.size() != 0) | 1382 | if (filePos >= _fileSize) { | ||
1367 | _tempFile->write(array); | 1383 | return QByteArray(); | ||
1368 | } | | |||
1369 | | ||||
1370 | void Lister::slotFileFinished(KJob *job) | | |||
1371 | { | | |||
1372 | _tempFile->flush(); | | |||
1373 | if (job->error()) { /* any error occurred? */ | | |||
1374 | KIO::TransferJob *kioJob = (KIO::TransferJob *)job; | | |||
1375 | KMessageBox::error(_textArea, i18n("Error reading file %1.", kioJob->url().toDisplayString(QUrl::PreferLocalFile))); | | |||
1376 | } | 1384 | } | ||
1377 | _downloading = false; | | |||
1378 | } | | |||
1379 | | ||||
1380 | 1385 | | |||
1381 | char * Lister::cacheRef(qint64 filePos, int &size) | 1386 | if (_fileSize - filePos < size) { | ||
1382 | { | | |||
1383 | if (filePos >= _fileSize) | | |||
1384 | return 0; | | |||
1385 | if (_fileSize - filePos < size) | | |||
1386 | size = _fileSize - filePos; | 1387 | size = _fileSize - filePos; | ||
1387 | if ((_cache != 0) && (filePos >= _cachePos) && (filePos + size <= _cachePos + _cacheSize)) | 1388 | } | ||
1388 | return _cache + (filePos - _cachePos); | 1389 | | ||
1390 | if (!_cache.isEmpty() && (filePos >= _cachePos) && (filePos + size <= _cachePos + _cache.size())) { | ||||
1391 | return _cache.mid(filePos - _cachePos, size); | ||||
1392 | } | ||||
1389 | 1393 | | |||
1390 | int cacheSize = CACHE_SIZE; | 1394 | const int negativeOffset = CACHE_SIZE * 2 / 5; | ||
1391 | int negativeOffset = CACHE_SIZE * 2 / 5; | | |||
1392 | qint64 cachePos = filePos - negativeOffset; | 1395 | qint64 cachePos = filePos - negativeOffset; | ||
1393 | if (cachePos < 0) | 1396 | if (cachePos < 0) | ||
1394 | cachePos = 0; | 1397 | cachePos = 0; | ||
1395 | 1398 | | |||
1396 | QFile myfile(_filePath); | 1399 | QFile sourceFile(_filePath); | ||
1397 | if (!myfile.open(QIODevice::ReadOnly)) { | 1400 | if (!sourceFile.open(QIODevice::ReadOnly)) { | ||
1398 | myfile.close(); | 1401 | return QByteArray(); | ||
1399 | return 0; | | |||
1400 | } | 1402 | } | ||
1401 | 1403 | | |||
1402 | if (!myfile.seek(cachePos)) { | 1404 | if (!sourceFile.seek(cachePos)) { | ||
1403 | myfile.close(); | 1405 | return QByteArray(); | ||
1404 | return 0; | | |||
1405 | } | 1406 | } | ||
1406 | 1407 | | |||
1407 | char * newCache = new char [ cacheSize ]; | 1408 | const QByteArray bytes = sourceFile.read(CACHE_SIZE); | ||
1408 | 1409 | if (bytes.size() == 0) { | |||
1409 | qint64 bytes = myfile.read(newCache, cacheSize); | 1410 | return QByteArray(); | ||
1410 | if (bytes == -1) { | | |||
1411 | delete []newCache; | | |||
1412 | myfile.close(); | | |||
1413 | return 0; | | |||
1414 | } | 1411 | } | ||
1415 | if (_cache) | | |||
1416 | delete []_cache; | | |||
1417 | 1412 | | |||
1418 | _cache = newCache; | 1413 | _cache = bytes; | ||
1419 | _cacheSize = bytes; | | |||
1420 | _cachePos = cachePos; | 1414 | _cachePos = cachePos; | ||
1421 | int newSize = _cacheSize - (filePos - _cachePos); | 1415 | const qint64 cacheRefIndex = filePos - _cachePos; | ||
1416 | int newSize = bytes.size() - cacheRefIndex; | ||||
1422 | if (newSize < size) | 1417 | if (newSize < size) | ||
1423 | size = newSize; | 1418 | size = newSize; | ||
1424 | 1419 | | |||
1425 | return _cache + (filePos - _cachePos); | 1420 | return _cache.mid(cacheRefIndex, size); | ||
1426 | } | 1421 | } | ||
1427 | 1422 | | |||
1428 | qint64 Lister::getFileSize() | 1423 | qint64 Lister::getFileSize() | ||
Context not available. | |||||
1433 | void Lister::guiActivateEvent(KParts::GUIActivateEvent * event) | 1428 | void Lister::guiActivateEvent(KParts::GUIActivateEvent * event) | ||
1434 | { | 1429 | { | ||
1435 | if (event->activated()) { | 1430 | if (event->activated()) { | ||
1436 | _active = true; | | |||
1437 | _updateTimer.setInterval(150); | | |||
1438 | _updateTimer.start(); | | |||
1439 | slotUpdate(); | 1431 | slotUpdate(); | ||
1440 | _textArea->redrawTextArea(true); | 1432 | _textArea->redrawTextArea(true); | ||
1441 | } else { | 1433 | } else { | ||
1442 | enableSearch(false); | 1434 | enableSearch(false); | ||
1443 | _active = false; | | |||
1444 | _updateTimer.stop(); | | |||
1445 | } | 1435 | } | ||
1446 | KParts::ReadOnlyPart::guiActivateEvent(event); | 1436 | KParts::ReadOnlyPart::guiActivateEvent(event); | ||
1447 | } | 1437 | } | ||
1448 | 1438 | | |||
1449 | void Lister::slotUpdate() | 1439 | void Lister::slotUpdate() | ||
1450 | { | 1440 | { | ||
1451 | qint64 oldSize = _fileSize; | 1441 | const qint64 oldSize = _fileSize; | ||
1452 | _fileSize = getFileSize(); | 1442 | _fileSize = getFileSize(); | ||
1453 | if (oldSize != _fileSize) | 1443 | if (oldSize != _fileSize) | ||
1454 | _textArea->sizeChanged(); | 1444 | _textArea->sizeChanged(); | ||
Context not available. | |||||
1456 | int cursorX = 0, cursorY = 0; | 1446 | int cursorX = 0, cursorY = 0; | ||
1457 | _textArea->getCursorPosition(cursorX, cursorY); | 1447 | _textArea->getCursorPosition(cursorX, cursorY); | ||
1458 | bool isfirst = false; | 1448 | bool isfirst = false; | ||
1459 | qint64 cursor = _textArea->getCursorPosition(isfirst); | 1449 | const qint64 cursor = _textArea->getCursorPosition(isfirst); | ||
1460 | 1450 | | |||
1461 | int percent = (_fileSize == 0) ? 0 : (int)((201 * cursor) / _fileSize / 2); | 1451 | const int percent = (_fileSize == 0) ? 0 : (int)((201 * cursor) / _fileSize / 2); | ||
1462 | 1452 | | |||
1463 | QString status = i18n("Column: %1, Position: %2 (%3, %4%)", | 1453 | const QString status = i18n("Column: %1, Position: %2 (%3, %4%)", cursorX, cursor, _fileSize, percent); | ||
1464 | cursorX, cursor, _fileSize, percent); | | |||
1465 | _statusLabel->setText(status); | 1454 | _statusLabel->setText(status); | ||
1466 | 1455 | | |||
1467 | if (_searchProgressCounter) | 1456 | if (_searchProgressCounter) | ||
Context not available. | |||||
1473 | return !_searchLineEdit->isHidden() || !_searchProgressBar->isHidden(); | 1462 | return !_searchLineEdit->isHidden() || !_searchProgressBar->isHidden(); | ||
1474 | } | 1463 | } | ||
1475 | 1464 | | |||
1476 | void Lister::enableSearch(bool enable) | 1465 | void Lister::enableSearch(const bool enable) | ||
1477 | { | 1466 | { | ||
1478 | if (enable) { | 1467 | if (enable) { | ||
1479 | _listerLabel->setText(i18n("Search:")); | 1468 | _listerLabel->setText(i18n("Search:")); | ||
Context not available. | |||||
1483 | _searchOptions->show(); | 1472 | _searchOptions->show(); | ||
1484 | if (!_searchLineEdit->hasFocus()) { | 1473 | if (!_searchLineEdit->hasFocus()) { | ||
1485 | _searchLineEdit->setFocus(); | 1474 | _searchLineEdit->setFocus(); | ||
1486 | QString selection = _textArea->getSelectedText(); | 1475 | const QString selection = _textArea->getSelectedText(); | ||
1487 | if (!selection.isEmpty()) { | 1476 | if (!selection.isEmpty()) { | ||
1488 | _searchLineEdit->setText(selection); | 1477 | _searchLineEdit->setText(selection); | ||
1489 | } | 1478 | } | ||
Context not available. | |||||
1509 | search(false); | 1498 | search(false); | ||
1510 | } | 1499 | } | ||
1511 | 1500 | | |||
1512 | void Lister::search(bool forward, bool restart) | 1501 | void Lister::search(const bool forward, const bool restart) | ||
1513 | { | 1502 | { | ||
1514 | _restartFromBeginning = restart; | 1503 | _restartFromBeginning = restart; | ||
1515 | if (_searchInProgress || _searchLineEdit->text().isEmpty()) | 1504 | if (_searchInProgress || _searchLineEdit->text().isEmpty()) | ||
Context not available. | |||||
1526 | if (_searchLastFailedPosition == -1 || _searchLastFailedPosition != cursor) | 1515 | if (_searchLastFailedPosition == -1 || _searchLastFailedPosition != cursor) | ||
1527 | _searchPosition = cursor; | 1516 | _searchPosition = cursor; | ||
1528 | } | 1517 | } | ||
1529 | bool caseSensitive = _caseSensitiveAction->isChecked(); | 1518 | const bool caseSensitive = _caseSensitiveAction->isChecked(); | ||
1530 | bool matchWholeWord = _matchWholeWordsOnlyAction->isChecked(); | 1519 | const bool matchWholeWord = _matchWholeWordsOnlyAction->isChecked(); | ||
1531 | bool regExp = _regExpAction->isChecked(); | 1520 | const bool regExp = _regExpAction->isChecked(); | ||
1532 | bool hex = _hexAction->isChecked(); | 1521 | const bool hex = _hexAction->isChecked(); | ||
1533 | 1522 | | |||
1534 | if (hex) { | 1523 | if (hex) { | ||
1535 | QString hexcontent = _searchLineEdit->text(); | 1524 | QString hexcontent = _searchLineEdit->text(); | ||
Context not available. | |||||
1547 | } | 1536 | } | ||
1548 | 1537 | | |||
1549 | while (!hexcontent.isEmpty()) { | 1538 | while (!hexcontent.isEmpty()) { | ||
1550 | QString hexData = hexcontent.left(2); | 1539 | const QString hexData = hexcontent.left(2); | ||
1551 | hexcontent = hexcontent.mid(2); | 1540 | hexcontent = hexcontent.mid(2); | ||
1552 | bool ok = true; | 1541 | bool ok = true; | ||
1553 | int c = hexData.toUInt(&ok, 16); | 1542 | const int c = hexData.toUInt(&ok, 16); | ||
1554 | if (!ok) { | 1543 | if (!ok) { | ||
1555 | setColor(false, false); | 1544 | setColor(false, false); | ||
1556 | return; | 1545 | return; | ||
Context not available. | |||||
1558 | _searchHexQuery.push_back((char) c); | 1547 | _searchHexQuery.push_back((char) c); | ||
1559 | } | 1548 | } | ||
1560 | } else { | 1549 | } else { | ||
1561 | _searchQuery.setContent(_searchLineEdit->text(), caseSensitive, matchWholeWord, _textArea->codec()->name(), regExp); | 1550 | _searchQuery.setContent(_searchLineEdit->text(), caseSensitive, matchWholeWord, codec()->name(), regExp); | ||
1562 | } | 1551 | } | ||
1563 | _searchIsForward = forward; | 1552 | _searchIsForward = forward; | ||
1564 | _searchHexadecimal = hex; | 1553 | _searchHexadecimal = hex; | ||
Context not available. | |||||
1570 | enableActions(false); | 1559 | enableActions(false); | ||
1571 | } | 1560 | } | ||
1572 | 1561 | | |||
1573 | void Lister::enableActions(bool state) | 1562 | void Lister::enableActions(const bool state) | ||
1574 | { | 1563 | { | ||
1575 | _actionSearch->setEnabled(state); | 1564 | _actionSearch->setEnabled(state); | ||
1576 | _actionSearchNext->setEnabled(state); | 1565 | _actionSearchNext->setEnabled(state); | ||
1577 | _actionSearchPrev->setEnabled(state); | 1566 | _actionSearchPrev->setEnabled(state); | ||
1578 | _actionJumpToPosition->setEnabled(state); | 1567 | _actionJumpToPosition->setEnabled(state); | ||
1568 | if (state) { | ||||
1569 | _searchUpdateTimer.stop(); | ||||
1570 | } else { | ||||
1571 | slotUpdate(); | ||||
1572 | } | ||||
1579 | } | 1573 | } | ||
1580 | 1574 | | |||
1581 | void Lister::slotSearchMore() | 1575 | void Lister::slotSearchMore() | ||
Context not available. | |||||
1583 | if (!_searchInProgress) | 1577 | if (!_searchInProgress) | ||
1584 | return; | 1578 | return; | ||
1585 | 1579 | | |||
1580 | if (!_searchUpdateTimer.isActive()) { | ||||
1581 | _searchUpdateTimer.start(200); | ||||
1582 | } | ||||
1583 | | ||||
1586 | updateProgressBar(); | 1584 | updateProgressBar(); | ||
1587 | if (!_searchIsForward) | 1585 | if (!_searchIsForward) | ||
1588 | _searchPosition--; | 1586 | _searchPosition--; | ||
Context not available. | |||||
1612 | maxCacheSize = diff; | 1610 | maxCacheSize = diff; | ||
1613 | } | 1611 | } | ||
1614 | 1612 | | |||
1615 | char * cache = cacheRef(searchPos, maxCacheSize); | 1613 | const QByteArray chunkData = cacheChunk(searchPos, maxCacheSize); | ||
1616 | if (cache == 0 || maxCacheSize == 0) { | 1614 | if (chunkData.isEmpty() || maxCacheSize == 0) { | ||
1617 | searchFailed(); | 1615 | searchFailed(); | ||
1618 | return; | 1616 | return; | ||
1619 | } | 1617 | } | ||
1620 | 1618 | | |||
1621 | qint64 foundAnchor = -1; | 1619 | qint64 foundAnchor = -1; | ||
1622 | qint64 foundCursor = -1; | 1620 | qint64 foundCursor = -1; | ||
1623 | int cnt = 0; | 1621 | int byteCounter = 0; | ||
1624 | 1622 | | |||
1625 | if (_searchHexadecimal) { | 1623 | if (_searchHexadecimal) { | ||
1626 | QByteArray cacheItems(cache, maxCacheSize); | 1624 | const int ndx = _searchIsForward ? chunkData.indexOf(_searchHexQuery) : chunkData.lastIndexOf(_searchHexQuery); | ||
1627 | int ndx = _searchIsForward ? cacheItems.indexOf(_searchHexQuery) : cacheItems.lastIndexOf(_searchHexQuery); | | |||
1628 | if (maxCacheSize > _searchHexQuery.length()) { | 1625 | if (maxCacheSize > _searchHexQuery.length()) { | ||
1629 | if (_searchIsForward) { | 1626 | if (_searchIsForward) { | ||
1630 | _searchPosition = searchPos + maxCacheSize; | 1627 | _searchPosition = searchPos + maxCacheSize; | ||
1631 | if ((_searchPosition < _fileSize) && (maxCacheSize > _searchHexQuery.length())) | 1628 | if ((_searchPosition < _fileSize) && (maxCacheSize > _searchHexQuery.length())) | ||
1632 | _searchPosition -= _searchHexQuery.length(); | 1629 | _searchPosition -= _searchHexQuery.length(); | ||
1633 | cnt = _searchPosition - searchPos; | 1630 | byteCounter = _searchPosition - searchPos; | ||
1634 | } else { | 1631 | } else { | ||
1635 | if (_searchPosition > 0) | 1632 | if (_searchPosition > 0) | ||
1636 | _searchPosition += _searchHexQuery.length(); | 1633 | _searchPosition += _searchHexQuery.length(); | ||
Context not available. | |||||
1641 | foundCursor = foundAnchor + _searchHexQuery.length(); | 1638 | foundCursor = foundAnchor + _searchHexQuery.length(); | ||
1642 | } | 1639 | } | ||
1643 | } else { | 1640 | } else { | ||
1644 | QTextCodec * textCodec = _textArea->codec(); | | |||
1645 | QTextDecoder * decoder = textCodec->makeDecoder(); | | |||
1646 | | ||||
1647 | int rowStart = 0; | 1641 | int rowStart = 0; | ||
1648 | | ||||
1649 | QString row = ""; | 1642 | QString row = ""; | ||
1650 | 1643 | | |||
1651 | while (cnt < maxCacheSize) { | 1644 | while (byteCounter < maxCacheSize) { | ||
1652 | QString chr = decoder->toUnicode(cache + (cnt++), 1); | 1645 | const QString chr = _codec->toUnicode(chunkData.mid(byteCounter++, 1)); | ||
1653 | if (!chr.isEmpty() || cnt >= maxCacheSize) { | 1646 | if (chr.isEmpty() && byteCounter < maxCacheSize) { | ||
1654 | if (chr != "\n") | 1647 | continue; | ||
1655 | row += chr; | 1648 | } | ||
1656 | | ||||
1657 | if (chr == "\n" || row.length() >= SEARCH_MAX_ROW_LEN || cnt >= maxCacheSize) { | | |||
1658 | if (setPosition) { | | |||
1659 | _searchPosition = searchPos + cnt; | | |||
1660 | if (!_searchIsForward) { | | |||
1661 | _searchPosition ++; | | |||
1662 | setPosition = false; | | |||
1663 | } | | |||
1664 | } | | |||
1665 | 1649 | | |||
1666 | if (_searchQuery.checkLine(row, !_searchIsForward)) { | 1650 | if (chr != "\n") | ||
1667 | QByteArray cachedBuffer(cache + rowStart, maxCacheSize - rowStart); | 1651 | row += chr; | ||
1668 | 1652 | | |||
1669 | QTextStream stream(&cachedBuffer); | 1653 | if (chr == "\n" || row.length() >= SEARCH_MAX_ROW_LEN || byteCounter >= maxCacheSize) { | ||
1670 | stream.setCodec(textCodec); | 1654 | if (setPosition) { | ||
1655 | _searchPosition = searchPos + byteCounter; | ||||
1656 | if (!_searchIsForward) { | ||||
1657 | _searchPosition++; | ||||
1658 | setPosition = false; | ||||
1659 | } | ||||
1660 | } | ||||
1671 | 1661 | | |||
1672 | stream.read(_searchQuery.matchIndex()); | 1662 | if (_searchQuery.checkLine(row, !_searchIsForward)) { | ||
1673 | foundAnchor = searchPos + rowStart + stream.pos(); | 1663 | QByteArray cachedBuffer = chunkData.mid(rowStart, maxCacheSize - rowStart); | ||
1674 | 1664 | | |||
1675 | stream.read(_searchQuery.matchLength()); | 1665 | QTextStream stream(&cachedBuffer); | ||
1676 | foundCursor = searchPos + rowStart + stream.pos(); | 1666 | stream.setCodec(_codec); | ||
1677 | 1667 | | |||
1678 | if (_searchIsForward) | 1668 | stream.read(_searchQuery.matchIndex()); | ||
1679 | break; | 1669 | foundAnchor = searchPos + rowStart + stream.pos(); | ||
1680 | } | | |||
1681 | 1670 | | |||
1682 | row = ""; | 1671 | stream.read(_searchQuery.matchLength()); | ||
1683 | rowStart = cnt; | 1672 | foundCursor = searchPos + rowStart + stream.pos(); | ||
1673 | | ||||
1674 | if (_searchIsForward) | ||||
1675 | break; | ||||
1684 | } | 1676 | } | ||
1677 | | ||||
1678 | row = ""; | ||||
1679 | rowStart = byteCounter; | ||||
1685 | } | 1680 | } | ||
1686 | } | 1681 | } | ||
1687 | | ||||
1688 | delete decoder; | | |||
1689 | } | 1682 | } | ||
1690 | 1683 | | |||
1691 | if (foundAnchor != -1 && foundCursor != -1) { | 1684 | if (foundAnchor != -1 && foundCursor != -1) { | ||
Context not available. | |||||
1694 | return; | 1687 | return; | ||
1695 | } | 1688 | } | ||
1696 | 1689 | | |||
1697 | if (_searchIsForward && searchPos + cnt >= _fileSize) { | 1690 | if (_searchIsForward && searchPos + byteCounter >= _fileSize) { | ||
1698 | if (_restartFromBeginning) | 1691 | if (_restartFromBeginning) | ||
1699 | resetSearchPosition(); | 1692 | resetSearchPosition(); | ||
1700 | else { | 1693 | else { | ||
Context not available. | |||||
1758 | if (_fileSize < 0x10000) { // autosearch files less than 64k | 1751 | if (_fileSize < 0x10000) { // autosearch files less than 64k | ||
1759 | if (!_searchLineEdit->text().isEmpty()) { | 1752 | if (!_searchLineEdit->text().isEmpty()) { | ||
1760 | bool isfirst; | 1753 | bool isfirst; | ||
1761 | qint64 anchor = _textArea->getCursorAnchor(); | 1754 | const qint64 anchor = _textArea->getCursorAnchor(); | ||
1762 | qint64 cursor = _textArea->getCursorPosition(isfirst); | 1755 | const qint64 cursor = _textArea->getCursorPosition(isfirst); | ||
1763 | if (cursor > anchor && anchor != -1) { | 1756 | if (cursor > anchor && anchor != -1) { | ||
1764 | _textArea->setCursorPosition(anchor, true); | 1757 | _textArea->setCursorPositionInDocument(anchor, true); | ||
1765 | } | 1758 | } | ||
1766 | search(true, true); | 1759 | search(true, true); | ||
1767 | } | 1760 | } | ||
1768 | } | 1761 | } | ||
1769 | } | 1762 | } | ||
1770 | 1763 | | |||
1771 | void Lister::setColor(bool match, bool restore) | 1764 | void Lister::setColor(const bool match, const bool restore) | ||
1772 | { | 1765 | { | ||
1773 | QColor fore, back; | 1766 | QColor fore, back; | ||
1774 | 1767 | | |||
1775 | if (!restore) { | 1768 | if (!restore) { | ||
1776 | KConfigGroup gc(krConfig, "Colors"); | 1769 | const KConfigGroup gc(krConfig, "Colors"); | ||
1777 | 1770 | | |||
1778 | QString foreground, background; | 1771 | QString foreground, background; | ||
1779 | QPalette p = QGuiApplication::palette(); | 1772 | const QPalette p = QGuiApplication::palette(); | ||
1780 | 1773 | | |||
1781 | if (match) { | 1774 | if (match) { | ||
1782 | foreground = "Quicksearch Match Foreground"; | 1775 | foreground = "Quicksearch Match Foreground"; | ||
Context not available. | |||||
1841 | _textArea->setFocus(); | 1834 | _textArea->setFocus(); | ||
1842 | } | 1835 | } | ||
1843 | 1836 | | |||
1844 | qint64 pcnt = (_fileSize == 0) ? 1000 : (2001 * _searchPosition) / _fileSize / 2; | 1837 | const qint64 pcnt = (_fileSize == 0) ? 1000 : (2001 * _searchPosition) / _fileSize / 2; | ||
1845 | int pctInt = (int)pcnt; | 1838 | const int pctInt = (int) pcnt; | ||
1846 | if (_searchProgressBar->value() != pctInt) | 1839 | if (_searchProgressBar->value() != pctInt) | ||
1847 | _searchProgressBar->setValue(pctInt); | 1840 | _searchProgressBar->setValue(pctInt); | ||
1848 | } | 1841 | } | ||
Context not available. | |||||
1860 | if (res.startsWith(QLatin1String("0x"))) { | 1853 | if (res.startsWith(QLatin1String("0x"))) { | ||
1861 | res = res.mid(2); | 1854 | res = res.mid(2); | ||
1862 | bool ok; | 1855 | bool ok; | ||
1863 | qulonglong upos = res.toULongLong(&ok, 16); | 1856 | const qulonglong upos = res.toULongLong(&ok, 16); | ||
1864 | if (!ok) { | 1857 | if (!ok) { | ||
1865 | KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position")); | 1858 | KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position")); | ||
1866 | return; | 1859 | return; | ||
Context not available. | |||||
1868 | pos = (qint64)upos; | 1861 | pos = (qint64)upos; | ||
1869 | } else { | 1862 | } else { | ||
1870 | bool ok; | 1863 | bool ok; | ||
1871 | qulonglong upos = res.toULongLong(&ok); | 1864 | const qulonglong upos = res.toULongLong(&ok); | ||
1872 | if (!ok) { | 1865 | if (!ok) { | ||
1873 | KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position")); | 1866 | KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position")); | ||
1874 | return; | 1867 | return; | ||
Context not available. | |||||
1882 | } | 1875 | } | ||
1883 | 1876 | | |||
1884 | _textArea->deleteAnchor(); | 1877 | _textArea->deleteAnchor(); | ||
1885 | _textArea->setCursorPosition(pos, true); | 1878 | _textArea->setCursorPositionInDocument(pos, true); | ||
1886 | _textArea->ensureVisibleCursor(); | 1879 | _textArea->ensureVisibleCursor(); | ||
1887 | } | 1880 | } | ||
1888 | 1881 | | |||
1889 | void Lister::saveAs() | 1882 | void Lister::saveAs() | ||
1890 | { | 1883 | { | ||
1891 | QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister")); | 1884 | const QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister")); | ||
1892 | if (url.isEmpty()) | 1885 | if (url.isEmpty()) | ||
1893 | return; | 1886 | return; | ||
1894 | QUrl sourceUrl; | 1887 | QUrl sourceUrl; | ||
Context not available. | |||||
1909 | void Lister::saveSelected() | 1902 | void Lister::saveSelected() | ||
1910 | { | 1903 | { | ||
1911 | bool isfirst; | 1904 | bool isfirst; | ||
1912 | qint64 start = _textArea->getCursorAnchor(); | 1905 | const qint64 start = _textArea->getCursorAnchor(); | ||
1913 | qint64 end = _textArea->getCursorPosition(isfirst); | 1906 | const qint64 end = _textArea->getCursorPosition(isfirst); | ||
1914 | if (start == -1 || start == end) { | 1907 | if (start == -1 || start == end) { | ||
1915 | KMessageBox::error(_textArea, i18n("Nothing is selected."), i18n("Save selection...")); | 1908 | KMessageBox::error(_textArea, i18n("Nothing is selected."), i18n("Save selection...")); | ||
1916 | return; | 1909 | return; | ||
Context not available. | |||||
1923 | _saveEnd = end; | 1916 | _saveEnd = end; | ||
1924 | } | 1917 | } | ||
1925 | 1918 | | |||
1926 | QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister")); | 1919 | const QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister")); | ||
1927 | if (url.isEmpty()) | 1920 | if (url.isEmpty()) | ||
1928 | return; | 1921 | return; | ||
1929 | 1922 | | |||
Context not available. | |||||
1950 | if (max > 1000) | 1943 | if (max > 1000) | ||
1951 | max = 1000; | 1944 | max = 1000; | ||
1952 | int maxBytes = (int)max; | 1945 | int maxBytes = (int)max; | ||
1953 | char * cache = cacheRef(_savePosition, maxBytes); | 1946 | array = cacheChunk(_savePosition, maxBytes); | ||
1954 | _savePosition += maxBytes; | 1947 | _savePosition += maxBytes; | ||
1955 | | ||||
1956 | array = QByteArray(cache, maxBytes); | | |||
1957 | } | 1948 | } | ||
1958 | 1949 | | |||
1959 | void Lister::slotSendFinished(KJob *) | 1950 | void Lister::slotSendFinished(KJob *) | ||
Context not available. | |||||
1961 | _actionSaveSelected->setEnabled(true); | 1952 | _actionSaveSelected->setEnabled(true); | ||
1962 | } | 1953 | } | ||
1963 | 1954 | | |||
1964 | void Lister::setCharacterSet(QString set) | 1955 | void Lister::setCharacterSet(const QString set) | ||
1965 | { | 1956 | { | ||
1966 | _characterSet = set; | 1957 | _characterSet = set; | ||
1958 | if (_characterSet.isEmpty()) { | ||||
1959 | _codec = QTextCodec::codecForLocale(); | ||||
1960 | } else { | ||||
1961 | _codec = KCharsets::charsets()->codecForName(_characterSet); | ||||
1962 | } | ||||
1967 | _textArea->redrawTextArea(true); | 1963 | _textArea->redrawTextArea(true); | ||
1968 | } | 1964 | } | ||
1969 | 1965 | | |||
1970 | void Lister::print() | 1966 | void Lister::print() | ||
1971 | { | 1967 | { | ||
1972 | bool isfirst; | 1968 | bool isfirst; | ||
1973 | qint64 anchor = _textArea->getCursorAnchor(); | 1969 | const qint64 anchor = _textArea->getCursorAnchor(); | ||
1974 | qint64 cursor = _textArea->getCursorPosition(isfirst); | 1970 | const qint64 cursor = _textArea->getCursorPosition(isfirst); | ||
1975 | bool hasSelection = (anchor != -1 && anchor != cursor); | 1971 | const bool hasSelection = (anchor != -1 && anchor != cursor); | ||
1976 | 1972 | | |||
1977 | QString docName = url().fileName(); | 1973 | const QString docName = url().fileName(); | ||
1978 | QPrinter printer; | 1974 | QPrinter printer; | ||
1979 | printer.setDocName(docName); | 1975 | printer.setDocName(docName); | ||
1980 | 1976 | | |||
1981 | QPointer<QPrintDialog> printDialog = new QPrintDialog(&printer, _textArea); | 1977 | QScopedPointer<QPrintDialog> printDialog(new QPrintDialog(&printer, _textArea)); | ||
1982 | 1978 | | |||
1983 | if (hasSelection) | 1979 | if (hasSelection) { | ||
1984 | printDialog->addEnabledOption(QAbstractPrintDialog::PrintSelection); | 1980 | printDialog->addEnabledOption(QAbstractPrintDialog::PrintSelection); | ||
1981 | } | ||||
1985 | 1982 | | |||
1986 | if (printDialog->exec()) { | 1983 | if (!printDialog->exec()) { | ||
1987 | if (printer.pageOrder() == QPrinter::LastPageFirst) { | 1984 | return; | ||
1988 | switch (KMessageBox::warningContinueCancel(_textArea, | 1985 | } | ||
1989 | i18n("Reverse printing is not supported. Continue with normal printing?"))) { | 1986 | | ||
1990 | case KMessageBox::Continue : | 1987 | if (printer.pageOrder() == QPrinter::LastPageFirst) { | ||
1991 | break; | 1988 | switch (KMessageBox::warningContinueCancel(_textArea, | ||
1992 | default: | 1989 | i18n("Reverse printing is not supported. Continue with normal printing?"))) { | ||
1993 | return; | 1990 | case KMessageBox::Continue : | ||
1994 | } | 1991 | break; | ||
1992 | default: | ||||
1993 | return; | ||||
1995 | } | 1994 | } | ||
1996 | QPainter painter; | 1995 | } | ||
1997 | painter.begin(&printer); | 1996 | QPainter painter; | ||
1997 | painter.begin(&printer); | ||||
1998 | 1998 | | |||
1999 | QDate date = QDate::currentDate(); | 1999 | const QString dateString = QDate::currentDate().toString(Qt::SystemLocaleShortDate); | ||
2000 | QString dateString = date.toString(Qt::SystemLocaleShortDate); | | |||
2001 | 2000 | | |||
2002 | QRect pageRect = printer.pageRect(); | 2001 | const QRect pageRect = printer.pageRect(); | ||
2003 | QRect drawingRect(0, 0, pageRect.width(), pageRect.height()); | 2002 | const QRect drawingRect(0, 0, pageRect.width(), pageRect.height()); | ||
2004 | 2003 | | |||
2005 | QFont normalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); | 2004 | const QFont normalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); | ||
2006 | QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); | 2005 | const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); | ||
2007 | 2006 | | |||
2008 | QFontMetrics fmNormal(normalFont); | 2007 | const QFontMetrics fmNormal(normalFont); | ||
2009 | int normalFontHeight = fmNormal.height(); | 2008 | const int normalFontHeight = fmNormal.height(); | ||
2010 | 2009 | | |||
2011 | QFontMetrics fmFixed(fixedFont); | 2010 | const QFontMetrics fmFixed(fixedFont); | ||
2012 | int fixedFontHeight = fmFixed.height(); | 2011 | const int fixedFontHeight = std::max(fmFixed.height(), 1); | ||
2013 | int fixedFontWidth = fmFixed.width("W"); | 2012 | const int fixedFontWidth = std::max(fmFixed.width("W"), 1); | ||
2014 | if (fixedFontHeight <= 0) | | |||
2015 | fixedFontHeight = 1; | | |||
2016 | if (fixedFontWidth <= 0) | | |||
2017 | fixedFontWidth = 1; | | |||
2018 | 2013 | | |||
2019 | int effPageSize = drawingRect.height() - normalFontHeight - 1; | 2014 | const int effPageSize = drawingRect.height() - normalFontHeight - 1; | ||
2020 | int rowsPerPage = effPageSize / fixedFontHeight; | 2015 | const int rowsPerPage = std::max(effPageSize / fixedFontHeight, 1); | ||
2021 | if (rowsPerPage <= 0) | 2016 | const int columnsPerPage = std::max(drawingRect.width() / fixedFontWidth, 1); | ||
2022 | rowsPerPage = 1; | | |||
2023 | int columnsPerPage = drawingRect.width() / fixedFontWidth; | | |||
2024 | if (columnsPerPage <= 0) | | |||
2025 | columnsPerPage = 1; | | |||
2026 | 2017 | | |||
2027 | bool firstPage = true; | 2018 | bool firstPage = true; | ||
2028 | 2019 | | |||
2029 | qint64 startPos = 0; | 2020 | qint64 startPos = 0; | ||
2030 | qint64 endPos = _fileSize; | 2021 | qint64 endPos = _fileSize; | ||
2031 | if (printer.printRange() == QPrinter::Selection) { | 2022 | if (printer.printRange() == QPrinter::Selection) { | ||
2032 | if (anchor > cursor) | 2023 | if (anchor > cursor) | ||
2033 | startPos = cursor, endPos = anchor; | 2024 | startPos = cursor, endPos = anchor; | ||
2034 | else | 2025 | else | ||
2035 | startPos = anchor, endPos = cursor; | 2026 | startPos = anchor, endPos = cursor; | ||
2036 | } | 2027 | } | ||
2037 | 2028 | | |||
2038 | for (int page = 1;; ++page) { | 2029 | int page = 0; | ||
2039 | QStringList rows = readLines(startPos, endPos, columnsPerPage, rowsPerPage); | 2030 | while (startPos < endPos) { | ||
2031 | page++; | ||||
2040 | 2032 | | |||
2041 | bool visible = true; | 2033 | QStringList rows = readLines(startPos, endPos, columnsPerPage, rowsPerPage); | ||
2042 | if (printer.fromPage() && page < printer.fromPage()) | | |||
2043 | visible = false; | | |||
2044 | if (printer.toPage() && printer.toPage() >= printer.fromPage() && page > printer.toPage()) | | |||
2045 | visible = false; | | |||
2046 | 2034 | | |||
2047 | if (visible) { | 2035 | // print since set-up fromPage number | ||
2048 | if (!firstPage) | 2036 | if (printer.fromPage() && page < printer.fromPage()) { | ||
2049 | printer.newPage(); | 2037 | continue; | ||
2050 | firstPage = false; | 2038 | } | ||
2051 | // Use the painter to draw on the page. | | |||
2052 | painter.setFont(normalFont); | | |||
2053 | 2039 | | |||
2054 | painter.drawText(drawingRect, Qt::AlignLeft, dateString); | 2040 | // print until set-up toPage number | ||
2055 | painter.drawText(drawingRect, Qt::AlignHCenter, docName); | 2041 | if (printer.toPage() && printer.toPage() >= printer.fromPage() && page > printer.toPage()) | ||
2056 | painter.drawText(drawingRect, Qt::AlignRight, QString("%1").arg(page)); | 2042 | break; | ||
2057 | 2043 | | |||
2058 | painter.drawLine(0, normalFontHeight, drawingRect.width(), normalFontHeight); | 2044 | if (!firstPage) { | ||
2045 | printer.newPage(); | ||||
2046 | } | ||||
2047 | firstPage = false; | ||||
2048 | // Use the painter to draw on the page. | ||||
2049 | painter.setFont(normalFont); | ||||
2059 | 2050 | | |||
2060 | painter.setFont(fixedFont); | 2051 | painter.drawText(drawingRect, Qt::AlignLeft, dateString); | ||
2061 | int yoffset = normalFontHeight + 1; | 2052 | painter.drawText(drawingRect, Qt::AlignHCenter, docName); | ||
2062 | foreach(const QString &row, rows) { | 2053 | painter.drawText(drawingRect, Qt::AlignRight, QString("%1").arg(page)); | ||
2063 | painter.drawText(0, yoffset + fixedFontHeight, row); | 2054 | | ||
2064 | yoffset += fixedFontHeight; | 2055 | painter.drawLine(0, normalFontHeight, drawingRect.width(), normalFontHeight); | ||
2065 | } | 2056 | | ||
2066 | } | 2057 | painter.setFont(fixedFont); | ||
2067 | if (startPos >= endPos) | 2058 | int yOffset = normalFontHeight + 1; | ||
2068 | break; | 2059 | foreach (const QString &row, rows) { | ||
2060 | painter.drawText(0, yOffset + fixedFontHeight, row); | ||||
2061 | yOffset += fixedFontHeight; | ||||
2069 | } | 2062 | } | ||
2070 | } | 2063 | } | ||
2071 | | ||||
2072 | delete printDialog; | | |||
2073 | } | 2064 | } | ||
2074 | 2065 | | |||
2075 | QStringList Lister::readLines(qint64 &filePos, qint64 endPos, int columns, int lines) | 2066 | QStringList Lister::readLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines) | ||
2076 | { | 2067 | { | ||
2077 | if (_textArea->hexMode()) | 2068 | if (_textArea->hexMode()) { | ||
2078 | return readHexLines(filePos, endPos, columns, lines); | 2069 | return readHexLines(filePos, endPos, columns, lines); | ||
2070 | } | ||||
2079 | QStringList list; | 2071 | QStringList list; | ||
2080 | int maxBytes = columns * lines * MAX_CHAR_LENGTH; | 2072 | int maxBytes = std::min(columns * lines * MAX_CHAR_LENGTH, (int) (endPos - filePos)); | ||
2081 | if (maxBytes > (endPos - filePos)) | 2073 | if (maxBytes <= 0) { | ||
2082 | maxBytes = (int)(endPos - filePos); | | |||
2083 | if (maxBytes <= 0) | | |||
2084 | return list; | 2074 | return list; | ||
2085 | char * cache = cacheRef(filePos, maxBytes); | 2075 | } | ||
2086 | if (cache == 0 || maxBytes == 0) | 2076 | const QByteArray cache = cacheChunk(filePos, maxBytes); | ||
2077 | if (cache.isEmpty() || maxBytes == 0) { | ||||
2087 | return list; | 2078 | return list; | ||
2079 | } | ||||
2088 | 2080 | | |||
2089 | QTextCodec * textCodec = _textArea->codec(); | 2081 | int byteCounter = 0; | ||
2090 | QTextDecoder * decoder = textCodec->makeDecoder(); | | |||
2091 | | ||||
2092 | int cnt = 0; | | |||
2093 | int y = 0; | | |||
2094 | QString row = ""; | 2082 | QString row = ""; | ||
2095 | bool isLastLongLine = false; | 2083 | bool skipImmediateNewline = false; | ||
2096 | while (cnt < maxBytes && y < lines) { | 2084 | while (byteCounter < maxBytes && list.size() < lines) { | ||
2097 | QString chr = decoder->toUnicode(cache + (cnt++), 1); | 2085 | QString chr = _codec->toUnicode(cache.mid(byteCounter++, 1)); | ||
2098 | if (!chr.isEmpty()) { | 2086 | if (chr.isEmpty()) { | ||
2099 | if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) | 2087 | continue; | ||
2100 | chr = QChar(' '); | 2088 | } | ||
2101 | if (chr == "\n") { | 2089 | | ||
2102 | if (!isLastLongLine) { | 2090 | // replace unreadable characters | ||
2103 | list << row; | 2091 | if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) { | ||
2104 | row = ""; | 2092 | chr = QChar(' '); | ||
2105 | y++; | 2093 | } | ||
2106 | } | 2094 | | ||
2107 | isLastLongLine = false; | 2095 | // handle newline | ||
2108 | } else { | 2096 | if (chr == "\n") { | ||
2109 | isLastLongLine = false; | 2097 | if (!skipImmediateNewline) { | ||
2110 | if (chr == "\t") { | 2098 | list << row; | ||
2111 | int tabLength = _textArea->tabWidth() - (row.length() % _textArea->tabWidth()); | 2099 | row = ""; | ||
2112 | if (row.length() + tabLength > columns) { | | |||
2113 | list << row; | | |||
2114 | row = ""; | | |||
2115 | y++; | | |||
2116 | } | | |||
2117 | row += QString(tabLength, QChar(' ')); | | |||
2118 | } else | | |||
2119 | row += chr; | | |||
2120 | | ||||
2121 | if (row.length() >= columns) { | | |||
2122 | list << row; | | |||
2123 | row = ""; | | |||
2124 | y++; | | |||
2125 | isLastLongLine = true; | | |||
2126 | } | | |||
2127 | } | 2100 | } | ||
2101 | skipImmediateNewline = false; | ||||
2102 | continue; | ||||
2103 | } | ||||
2104 | | ||||
2105 | skipImmediateNewline = false; | ||||
2106 | | ||||
2107 | // handle tab | ||||
2108 | if (chr == "\t") { | ||||
2109 | const int tabLength = _textArea->tabWidth() - (row.length() % _textArea->tabWidth()); | ||||
2110 | if (row.length() + tabLength > columns) { | ||||
2111 | list << row; | ||||
2112 | row = ""; | ||||
2113 | } | ||||
2114 | row += QString(tabLength, QChar(' ')); | ||||
2115 | } else { | ||||
2116 | // normal printable character | ||||
2117 | row += chr; | ||||
2118 | } | ||||
2119 | | ||||
2120 | if (row.length() >= columns) { | ||||
2121 | list << row; | ||||
2122 | row = ""; | ||||
2123 | skipImmediateNewline = true; | ||||
2128 | } | 2124 | } | ||
2129 | } | 2125 | } | ||
2130 | 2126 | | |||
2131 | if (y < lines) | 2127 | if (list.size() < lines) { | ||
2132 | list << row; | 2128 | list << row; | ||
2129 | } | ||||
2133 | 2130 | | |||
2134 | filePos += cnt; | 2131 | filePos += byteCounter; | ||
2135 | 2132 | | |||
2136 | delete decoder; | | |||
2137 | return list; | 2133 | return list; | ||
2138 | } | 2134 | } | ||
2139 | 2135 | | |||
Context not available. | |||||
2145 | positionDigits++; | 2141 | positionDigits++; | ||
2146 | checker /= 16; | 2142 | checker /= 16; | ||
2147 | } | 2143 | } | ||
2148 | if (positionDigits < 8) | 2144 | if (positionDigits < 8) { | ||
2149 | positionDigits = 8; | 2145 | return 8; | ||
2146 | } | ||||
2150 | return positionDigits; | 2147 | return positionDigits; | ||
2151 | } | 2148 | } | ||
2152 | 2149 | | |||
2153 | int Lister::hexBytesPerLine(int columns) | 2150 | int Lister::hexBytesPerLine(const int columns) | ||
2154 | { | 2151 | { | ||
2155 | int positionDigits = hexPositionDigits(); | 2152 | const int positionDigits = hexPositionDigits(); | ||
2156 | int bytesPerRow = 8; | 2153 | if (columns >= positionDigits + 5 + 128) { | ||
2157 | if (columns >= positionDigits + 5 + 64) | 2154 | return 32; | ||
2158 | bytesPerRow = 16; | 2155 | } | ||
2159 | if (columns >= positionDigits + 5 + 128) | 2156 | if (columns >= positionDigits + 5 + 64) { | ||
2160 | bytesPerRow = 32; | 2157 | return 16; | ||
2161 | 2158 | } | |||
2162 | return bytesPerRow; | 2159 | return 8; | ||
2163 | } | 2160 | } | ||
2164 | 2161 | | |||
2165 | QStringList Lister::readHexLines(qint64 &filePos, qint64 endPos, int columns, int lines) | 2162 | QStringList Lister::readHexLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines) | ||
2166 | { | 2163 | { | ||
2167 | int positionDigits = hexPositionDigits(); | 2164 | const int positionDigits = hexPositionDigits(); | ||
2168 | int bytesPerRow = hexBytesPerLine(columns); | 2165 | const int bytesPerRow = hexBytesPerLine(columns); | ||
2169 | 2166 | | |||
2170 | QStringList list; | 2167 | QStringList list; | ||
2171 | 2168 | | |||
2172 | qint64 choppedPos = (filePos / bytesPerRow) * bytesPerRow; | 2169 | const qint64 choppedPos = (filePos / bytesPerRow) * bytesPerRow; | ||
2173 | int maxBytes = bytesPerRow * lines; | 2170 | int maxBytes = std::min(bytesPerRow * lines, (int) (endPos - choppedPos)); | ||
2174 | if (maxBytes > (endPos - choppedPos)) | | |||
2175 | maxBytes = (int)(endPos - choppedPos); | | |||
2176 | if (maxBytes <= 0) | 2171 | if (maxBytes <= 0) | ||
2177 | return list; | 2172 | return list; | ||
2178 | 2173 | | |||
2179 | char * cache = cacheRef(choppedPos, maxBytes); | 2174 | const QByteArray chunkData = cacheChunk(choppedPos, maxBytes); | ||
2180 | 2175 | | |||
2181 | if (cache == 0 || maxBytes == 0) | 2176 | if (chunkData.isEmpty() || maxBytes == 0) | ||
2182 | return list; | 2177 | return list; | ||
2183 | 2178 | | |||
2184 | int cnt = 0; | 2179 | int cnt = 0; | ||
2185 | for (int l = 0; l < lines; l++) { | 2180 | for (int l = 0; l < lines; l++) { | ||
2186 | if (filePos >= endPos) | 2181 | if (filePos >= endPos) { | ||
2187 | break; | 2182 | break; | ||
2188 | qint64 printPos = (filePos / bytesPerRow) * bytesPerRow; | 2183 | } | ||
2184 | | ||||
2185 | const qint64 printPos = (filePos / bytesPerRow) * bytesPerRow; | ||||
2189 | QString pos; | 2186 | QString pos; | ||
2190 | pos.setNum(printPos, 16); | 2187 | pos.setNum(printPos, 16); | ||
2191 | while (pos.length() < positionDigits) | 2188 | while (pos.length() < positionDigits) | ||
Context not available. | |||||
2196 | QString charData; | 2193 | QString charData; | ||
2197 | 2194 | | |||
2198 | for (int i = 0; i != bytesPerRow; ++i, ++cnt) { | 2195 | for (int i = 0; i != bytesPerRow; ++i, ++cnt) { | ||
2199 | qint64 currentPos = printPos + i; | 2196 | const qint64 currentPos = printPos + i; | ||
2200 | if (currentPos < filePos || currentPos >= endPos) { | 2197 | if (currentPos < filePos || currentPos >= endPos) { | ||
2201 | pos += QString(" "); | 2198 | pos += QString(" "); | ||
2202 | charData += QString(" "); | 2199 | charData += QString(" "); | ||
2203 | } else { | 2200 | } else { | ||
2204 | char c = cache[ cnt ]; | 2201 | char c = chunkData.at(cnt); | ||
2205 | int charCode = (int)c; | 2202 | int charCode = (int)c; | ||
2206 | if (charCode < 0) | 2203 | if (charCode < 0) | ||
2207 | charCode += 256; | 2204 | charCode += 256; | ||
Context not available. | |||||
2221 | filePos = printPos + bytesPerRow; | 2218 | filePos = printPos + bytesPerRow; | ||
2222 | } | 2219 | } | ||
2223 | 2220 | | |||
2224 | if (filePos > endPos) | 2221 | if (filePos > endPos) { | ||
2225 | filePos = endPos; | 2222 | filePos = endPos; | ||
2223 | } | ||||
2226 | 2224 | | |||
2227 | return list; | 2225 | return list; | ||
2228 | } | 2226 | } | ||
2229 | 2227 | | |||
2230 | int Lister::hexIndexToPosition(int columns, int index) | 2228 | int Lister::hexIndexToPosition(const int columns, const int index) | ||
2231 | { | 2229 | { | ||
2232 | int positionDigits = hexPositionDigits(); | 2230 | const int positionDigits = hexPositionDigits(); | ||
2233 | int bytesPerRow = hexBytesPerLine(columns); | 2231 | const int bytesPerRow = hexBytesPerLine(columns); | ||
2234 | 2232 | const int finalIndex = std::min(index, bytesPerRow); | |||
2235 | if (index >= bytesPerRow) | | |||
2236 | index = bytesPerRow; | | |||
2237 | 2233 | | |||
2238 | return positionDigits + 4 + (3*index); | 2234 | return positionDigits + 4 + (3*finalIndex); | ||
2239 | } | 2235 | } | ||
2240 | 2236 | | |||
2241 | int Lister::hexPositionToIndex(int columns, int position) | 2237 | int Lister::hexPositionToIndex(const int columns, const int position) | ||
2242 | { | 2238 | { | ||
2243 | int positionDigits = hexPositionDigits(); | 2239 | const int positionDigits = hexPositionDigits(); | ||
2244 | int bytesPerRow = hexBytesPerLine(columns); | 2240 | const int bytesPerRow = hexBytesPerLine(columns); | ||
2245 | 2241 | | |||
2246 | position -= 4 + positionDigits; | 2242 | int finalPosition = position; | ||
2247 | if (position <= 0) | 2243 | finalPosition -= 4 + positionDigits; | ||
2244 | if (finalPosition <= 0) | ||||
2248 | return 0; | 2245 | return 0; | ||
2249 | 2246 | | |||
2250 | position /= 3; | 2247 | finalPosition /= 3; | ||
2251 | if (position >= bytesPerRow) | 2248 | if (finalPosition >= bytesPerRow) | ||
2252 | return bytesPerRow; | 2249 | return bytesPerRow; | ||
2253 | return position; | 2250 | return finalPosition; | ||
2254 | } | 2251 | } | ||
2255 | 2252 | | |||
2256 | void Lister::toggleHexMode() | 2253 | void Lister::toggleHexMode() | ||
Context not available. | |||||
2258 | setHexMode(!_textArea->hexMode()); | 2255 | setHexMode(!_textArea->hexMode()); | ||
2259 | } | 2256 | } | ||
2260 | 2257 | | |||
2261 | void Lister::setHexMode(bool mode) | 2258 | void Lister::setHexMode(const bool mode) | ||
2262 | { | 2259 | { | ||
2263 | if (mode) { | 2260 | if (mode) { | ||
2264 | _textArea->setHexMode(true); | 2261 | _textArea->setHexMode(true); | ||
Context not available. |