1 // The implementation of the Qt specific subclass of ScintillaBase.
2 //
3 // Copyright (c) 2019 Riverbank Computing Limited <info@riverbankcomputing.com>
4 //
5 // This file is part of QScintilla.
6 //
7 // This file may be used under the terms of the GNU General Public License
8 // version 3.0 as published by the Free Software Foundation and appearing in
9 // the file LICENSE included in the packaging of this file. Please review the
10 // following information to ensure the GNU General Public License version 3.0
11 // requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 //
13 // If you do not wish to use this file under the terms of the GPL version 3.0
14 // then you may purchase a commercial license. For more information contact
15 // info@riverbankcomputing.com.
16 //
17 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19
20
21 #include <string.h>
22
23 #include <qapplication.h>
24 #include <qbytearray.h>
25 #include <qdrag.h>
26 #include <qevent.h>
27 #include <qmimedata.h>
28 #include <qpainter.h>
29 #include <qscrollbar.h>
30 #include <qstring.h>
31
32 #include "Qsci/qsciscintillabase.h"
33 #include "ScintillaQt.h"
34 #if !defined(QT_NO_ACCESSIBILITY)
35 #include "SciAccessibility.h"
36 #endif
37 #include "SciClasses.h"
38
39
40 // We want to use the Scintilla notification names as Qt signal names.
41 #undef SCEN_CHANGE
42 #undef SCN_AUTOCCANCELLED
43 #undef SCN_AUTOCCHARDELETED
44 #undef SCN_AUTOCCOMPLETED
45 #undef SCN_AUTOCSELECTION
46 #undef SCN_AUTOCSELECTIONCHANGE
47 #undef SCN_CALLTIPCLICK
48 #undef SCN_CHARADDED
49 #undef SCN_DOUBLECLICK
50 #undef SCN_DWELLEND
51 #undef SCN_DWELLSTART
52 #undef SCN_FOCUSIN
53 #undef SCN_FOCUSOUT
54 #undef SCN_HOTSPOTCLICK
55 #undef SCN_HOTSPOTDOUBLECLICK
56 #undef SCN_HOTSPOTRELEASECLICK
57 #undef SCN_INDICATORCLICK
58 #undef SCN_INDICATORRELEASE
59 #undef SCN_MACRORECORD
60 #undef SCN_MARGINCLICK
61 #undef SCN_MARGINRIGHTCLICK
62 #undef SCN_MODIFIED
63 #undef SCN_MODIFYATTEMPTRO
64 #undef SCN_NEEDSHOWN
65 #undef SCN_PAINTED
66 #undef SCN_SAVEPOINTLEFT
67 #undef SCN_SAVEPOINTREACHED
68 #undef SCN_STYLENEEDED
69 #undef SCN_UPDATEUI
70 #undef SCN_USERLISTSELECTION
71 #undef SCN_ZOOM
72
73 enum
74 {
75 SCEN_CHANGE = 768,
76 SCN_AUTOCCANCELLED = 2025,
77 SCN_AUTOCCHARDELETED = 2026,
78 SCN_AUTOCCOMPLETED = 2030,
79 SCN_AUTOCSELECTION = 2022,
80 SCN_AUTOCSELECTIONCHANGE = 2032,
81 SCN_CALLTIPCLICK = 2021,
82 SCN_CHARADDED = 2001,
83 SCN_DOUBLECLICK = 2006,
84 SCN_DWELLEND = 2017,
85 SCN_DWELLSTART = 2016,
86 SCN_FOCUSIN = 2028,
87 SCN_FOCUSOUT = 2029,
88 SCN_HOTSPOTCLICK = 2019,
89 SCN_HOTSPOTDOUBLECLICK = 2020,
90 SCN_HOTSPOTRELEASECLICK = 2027,
91 SCN_INDICATORCLICK = 2023,
92 SCN_INDICATORRELEASE = 2024,
93 SCN_MACRORECORD = 2009,
94 SCN_MARGINCLICK = 2010,
95 SCN_MARGINRIGHTCLICK = 2031,
96 SCN_MODIFIED = 2008,
97 SCN_MODIFYATTEMPTRO = 2004,
98 SCN_NEEDSHOWN = 2011,
99 SCN_PAINTED = 2013,
100 SCN_SAVEPOINTLEFT = 2003,
101 SCN_SAVEPOINTREACHED = 2002,
102 SCN_STYLENEEDED = 2000,
103 SCN_UPDATEUI = 2007,
104 SCN_USERLISTSELECTION = 2014,
105 SCN_ZOOM = 2018
106 };
107
108
109 // The ctor.
QsciScintillaQt(QsciScintillaBase * qsb_)110 QsciScintillaQt::QsciScintillaQt(QsciScintillaBase *qsb_)
111 : vMax(0), hMax(0), vPage(0), hPage(0), capturedMouse(false), qsb(qsb_)
112 {
113 wMain = qsb->viewport();
114
115 // This is ignored.
116 imeInteraction = imeInline;
117
118 // Using pixmaps screws things up when moving to a different display
119 // (although this could be because we haven't got the pixmap code right).
120 // However Qt shouldn't need buffered drawing anyway.
121 WndProc(SCI_SETBUFFEREDDRAW, 0, 0);
122
123 for (int i = 0; i <= static_cast<int>(tickPlatform); ++i)
124 timers[i] = 0;
125
126 Initialise();
127 }
128
129
130 // The dtor.
~QsciScintillaQt()131 QsciScintillaQt::~QsciScintillaQt()
132 {
133 Finalise();
134 }
135
136
137 // Initialise the instance.
Initialise()138 void QsciScintillaQt::Initialise()
139 {
140 }
141
142
143 // Tidy up the instance.
Finalise()144 void QsciScintillaQt::Finalise()
145 {
146 for (int i = 0; i <= static_cast<int>(tickPlatform); ++i)
147 FineTickerCancel(static_cast<TickReason>(i));
148
149 ScintillaBase::Finalise();
150 }
151
152
153 // Start a drag.
StartDrag()154 void QsciScintillaQt::StartDrag()
155 {
156 inDragDrop = ddDragging;
157
158 QDrag *qdrag = new QDrag(qsb);
159 qdrag->setMimeData(mimeSelection(drag));
160
161 #if QT_VERSION >= 0x040300
162 Qt::DropAction action = qdrag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
163 #else
164 Qt::DropAction action = qdrag->start(Qt::MoveAction);
165 #endif
166
167 // Remove the dragged text if it was a move to another widget or
168 // application.
169 if (action == Qt::MoveAction && qdrag->target() != qsb->viewport())
170 ClearSelection();
171
172 SetDragPosition(Scintilla::SelectionPosition());
173 inDragDrop = ddNone;
174 }
175
176
177 // Re-implement to trap certain messages.
WndProc(unsigned int iMessage,uptr_t wParam,sptr_t lParam)178 sptr_t QsciScintillaQt::WndProc(unsigned int iMessage, uptr_t wParam,
179 sptr_t lParam)
180 {
181 switch (iMessage)
182 {
183 case SCI_GETDIRECTFUNCTION:
184 return reinterpret_cast<sptr_t>(DirectFunction);
185
186 case SCI_GETDIRECTPOINTER:
187 return reinterpret_cast<sptr_t>(this);
188 }
189
190 return ScintillaBase::WndProc(iMessage, wParam, lParam);
191 }
192
193
194 // Windows nonsense.
DefWndProc(unsigned int,uptr_t,sptr_t)195 sptr_t QsciScintillaQt::DefWndProc(unsigned int, uptr_t, sptr_t)
196 {
197 return 0;
198 }
199
200
201 // Grab or release the mouse (and keyboard).
SetMouseCapture(bool on)202 void QsciScintillaQt::SetMouseCapture(bool on)
203 {
204 if (mouseDownCaptures)
205 {
206 if (on)
207 qsb->viewport()->grabMouse();
208 else
209 qsb->viewport()->releaseMouse();
210 }
211
212 capturedMouse = on;
213 }
214
215
216 // Return true if the mouse/keyboard are currently grabbed.
HaveMouseCapture()217 bool QsciScintillaQt::HaveMouseCapture()
218 {
219 return capturedMouse;
220 }
221
222
223 // Set the position of the vertical scrollbar.
SetVerticalScrollPos()224 void QsciScintillaQt::SetVerticalScrollPos()
225 {
226 QScrollBar *sb = qsb->verticalScrollBar();
227 bool was_blocked = sb->blockSignals(true);
228
229 sb->setValue(topLine);
230
231 sb->blockSignals(was_blocked);
232 }
233
234
235 // Set the position of the horizontal scrollbar.
SetHorizontalScrollPos()236 void QsciScintillaQt::SetHorizontalScrollPos()
237 {
238 QScrollBar *sb = qsb->horizontalScrollBar();
239 bool was_blocked = sb->blockSignals(true);
240
241 sb->setValue(xOffset);
242
243 sb->blockSignals(was_blocked);
244 }
245
246
247 // Set the extent of the vertical and horizontal scrollbars and return true if
248 // the view needs re-drawing.
ModifyScrollBars(Sci::Line nMax,Sci::Line nPage)249 bool QsciScintillaQt::ModifyScrollBars(Sci::Line nMax, Sci::Line nPage)
250 {
251 bool modified = false;
252 QScrollBar *sb;
253
254 int vNewPage = nPage;
255 int vNewMax = nMax - vNewPage + 1;
256
257 if (vMax != vNewMax || vPage != vNewPage)
258 {
259 vMax = vNewMax;
260 vPage = vNewPage;
261 modified = true;
262
263 sb = qsb->verticalScrollBar();
264 sb->setMaximum(vMax);
265 sb->setPageStep(vPage);
266 }
267
268 int hNewPage = GetTextRectangle().Width();
269 int hNewMax = (scrollWidth > hNewPage) ? scrollWidth - hNewPage : 0;
270 int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
271
272 sb = qsb->horizontalScrollBar();
273
274 if (hMax != hNewMax || hPage != hNewPage || sb->singleStep() != charWidth)
275 {
276 hMax = hNewMax;
277 hPage = hNewPage;
278 modified = true;
279
280 sb->setMaximum(hMax);
281 sb->setPageStep(hPage);
282 sb->setSingleStep(charWidth);
283 }
284
285 return modified;
286 }
287
288
289 // Called after SCI_SETWRAPMODE and SCI_SETHSCROLLBAR.
ReconfigureScrollBars()290 void QsciScintillaQt::ReconfigureScrollBars()
291 {
292 // Hide or show the scrollbars if needed.
293 bool hsb = (horizontalScrollBarVisible && !Wrapping());
294
295 qsb->setHorizontalScrollBarPolicy(hsb ? Qt::ScrollBarAsNeeded : Qt::ScrollBarAlwaysOff);
296 qsb->setVerticalScrollBarPolicy(verticalScrollBarVisible ? Qt::ScrollBarAsNeeded : Qt::ScrollBarAlwaysOff);
297 }
298
299
300 // Notify interested parties of any change in the document.
NotifyChange()301 void QsciScintillaQt::NotifyChange()
302 {
303 emit qsb->SCEN_CHANGE();
304 }
305
306
307 // Notify interested parties of various events. This is the main mapping
308 // between Scintilla notifications and Qt signals.
NotifyParent(SCNotification scn)309 void QsciScintillaQt::NotifyParent(SCNotification scn)
310 {
311 switch (scn.nmhdr.code)
312 {
313 case SCN_CALLTIPCLICK:
314 emit qsb->SCN_CALLTIPCLICK(scn.position);
315 break;
316
317 case SCN_AUTOCCANCELLED:
318 emit qsb->SCN_AUTOCCANCELLED();
319 break;
320
321 case SCN_AUTOCCHARDELETED:
322 emit qsb->SCN_AUTOCCHARDELETED();
323 break;
324
325 case SCN_AUTOCCOMPLETED:
326 emit qsb->SCN_AUTOCCOMPLETED(scn.text, scn.position, scn.ch,
327 scn.listCompletionMethod);
328 break;
329
330 case SCN_AUTOCSELECTION:
331 emit qsb->SCN_AUTOCSELECTION(scn.text, scn.position, scn.ch,
332 scn.listCompletionMethod);
333 emit qsb->SCN_AUTOCSELECTION(scn.text, scn.position);
334 break;
335
336 case SCN_AUTOCSELECTIONCHANGE:
337 emit qsb->SCN_AUTOCSELECTIONCHANGE(scn.text, scn.listType,
338 scn.position);
339 break;
340
341 case SCN_CHARADDED:
342 emit qsb->SCN_CHARADDED(scn.ch);
343 break;
344
345 case SCN_DOUBLECLICK:
346 emit qsb->SCN_DOUBLECLICK(scn.position, scn.line, scn.modifiers);
347 break;
348
349 case SCN_DWELLEND:
350 emit qsb->SCN_DWELLEND(scn.position, scn.x, scn.y);
351 break;
352
353 case SCN_DWELLSTART:
354 emit qsb->SCN_DWELLSTART(scn.position, scn.x, scn.y);
355 break;
356
357 case SCN_FOCUSIN:
358 emit qsb->SCN_FOCUSIN();
359 break;
360
361 case SCN_FOCUSOUT:
362 emit qsb->SCN_FOCUSOUT();
363 break;
364
365 case SCN_HOTSPOTCLICK:
366 emit qsb->SCN_HOTSPOTCLICK(scn.position, scn.modifiers);
367 break;
368
369 case SCN_HOTSPOTDOUBLECLICK:
370 emit qsb->SCN_HOTSPOTDOUBLECLICK(scn.position, scn.modifiers);
371 break;
372
373 case SCN_HOTSPOTRELEASECLICK:
374 emit qsb->SCN_HOTSPOTRELEASECLICK(scn.position, scn.modifiers);
375 break;
376
377 case SCN_INDICATORCLICK:
378 emit qsb->SCN_INDICATORCLICK(scn.position, scn.modifiers);
379 break;
380
381 case SCN_INDICATORRELEASE:
382 emit qsb->SCN_INDICATORRELEASE(scn.position, scn.modifiers);
383 break;
384
385 case SCN_MACRORECORD:
386 emit qsb->SCN_MACRORECORD(scn.message, scn.wParam,
387 reinterpret_cast<void *>(scn.lParam));
388 break;
389
390 case SCN_MARGINCLICK:
391 emit qsb->SCN_MARGINCLICK(scn.position, scn.modifiers, scn.margin);
392 break;
393
394 case SCN_MARGINRIGHTCLICK:
395 emit qsb->SCN_MARGINRIGHTCLICK(scn.position, scn.modifiers,
396 scn.margin);
397 break;
398
399 case SCN_MODIFIED:
400 {
401 char *text;
402
403 #if !defined(QT_NO_ACCESSIBILITY)
404 if ((scn.modificationType & SC_MOD_INSERTTEXT) != 0)
405 QsciAccessibleScintillaBase::textInserted(qsb, scn.position,
406 scn.text, scn.length);
407 else if ((scn.modificationType & SC_MOD_DELETETEXT) != 0)
408 QsciAccessibleScintillaBase::textDeleted(qsb, scn.position,
409 scn.text, scn.length);
410 #endif
411
412 // Give some protection to the Python bindings.
413 if (scn.text && (scn.modificationType & (SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)) != 0)
414 {
415 text = new char[scn.length + 1];
416 memcpy(text, scn.text, scn.length);
417 text[scn.length] = '\0';
418 }
419 else
420 {
421 text = 0;
422 }
423
424 emit qsb->SCN_MODIFIED(scn.position, scn.modificationType, text,
425 scn.length, scn.linesAdded, scn.line, scn.foldLevelNow,
426 scn.foldLevelPrev, scn.token, scn.annotationLinesAdded);
427
428 if (text)
429 delete[] text;
430
431 break;
432 }
433
434 case SCN_MODIFYATTEMPTRO:
435 emit qsb->SCN_MODIFYATTEMPTRO();
436 break;
437
438 case SCN_NEEDSHOWN:
439 emit qsb->SCN_NEEDSHOWN(scn.position, scn.length);
440 break;
441
442 case SCN_PAINTED:
443 emit qsb->SCN_PAINTED();
444 break;
445
446 case SCN_SAVEPOINTLEFT:
447 emit qsb->SCN_SAVEPOINTLEFT();
448 break;
449
450 case SCN_SAVEPOINTREACHED:
451 emit qsb->SCN_SAVEPOINTREACHED();
452 break;
453
454 case SCN_STYLENEEDED:
455 emit qsb->SCN_STYLENEEDED(scn.position);
456 break;
457
458 case SCN_UPDATEUI:
459 #if !defined(QT_NO_ACCESSIBILITY)
460 QsciAccessibleScintillaBase::updated(qsb);
461 #endif
462 emit qsb->SCN_UPDATEUI(scn.updated);
463 break;
464
465 case SCN_USERLISTSELECTION:
466 emit qsb->SCN_USERLISTSELECTION(scn.text, scn.listType, scn.ch,
467 scn.listCompletionMethod, scn.position);
468 emit qsb->SCN_USERLISTSELECTION(scn.text, scn.listType, scn.ch,
469 scn.listCompletionMethod);
470 emit qsb->SCN_USERLISTSELECTION(scn.text, scn.listType);
471 break;
472
473 case SCN_ZOOM:
474 emit qsb->SCN_ZOOM();
475 break;
476
477 default:
478 qWarning("Unknown notification: %u", scn.nmhdr.code);
479 }
480 }
481
482
483 // Convert a selection to mime data.
mimeSelection(const Scintilla::SelectionText & text) const484 QMimeData *QsciScintillaQt::mimeSelection(
485 const Scintilla::SelectionText &text) const
486 {
487 return qsb->toMimeData(QByteArray(text.Data()), text.rectangular);
488 }
489
490
491 // Copy the selected text to the clipboard.
CopyToClipboard(const Scintilla::SelectionText & selectedText)492 void QsciScintillaQt::CopyToClipboard(
493 const Scintilla::SelectionText &selectedText)
494 {
495 QApplication::clipboard()->setMimeData(mimeSelection(selectedText));
496 }
497
498
499 // Implement copy.
Copy()500 void QsciScintillaQt::Copy()
501 {
502 if (!sel.Empty())
503 {
504 Scintilla::SelectionText text;
505
506 CopySelectionRange(&text);
507 CopyToClipboard(text);
508 }
509 }
510
511
512 // Implement pasting text.
Paste()513 void QsciScintillaQt::Paste()
514 {
515 pasteFromClipboard(QClipboard::Clipboard);
516 }
517
518
519 // Paste text from either the clipboard or selection.
pasteFromClipboard(QClipboard::Mode mode)520 void QsciScintillaQt::pasteFromClipboard(QClipboard::Mode mode)
521 {
522 int len;
523 const char *s;
524 bool rectangular;
525
526 const QMimeData *source = QApplication::clipboard()->mimeData(mode);
527
528 if (!source || !qsb->canInsertFromMimeData(source))
529 return;
530
531 QByteArray text = qsb->fromMimeData(source, rectangular);
532 len = text.length();
533 s = text.data();
534
535 std::string dest = Scintilla::Document::TransformLineEnds(s, len,
536 pdoc->eolMode);
537
538 Scintilla::SelectionText selText;
539 selText.Copy(dest, (IsUnicodeMode() ? SC_CP_UTF8 : 0),
540 vs.styles[STYLE_DEFAULT].characterSet, rectangular, false);
541
542 Scintilla::UndoGroup ug(pdoc);
543
544 ClearSelection();
545 InsertPasteShape(selText.Data(), selText.Length(),
546 selText.rectangular ? pasteRectangular : pasteStream);
547 EnsureCaretVisible();
548 }
549
550
551 // Create a call tip window.
CreateCallTipWindow(Scintilla::PRectangle rc)552 void QsciScintillaQt::CreateCallTipWindow(Scintilla::PRectangle rc)
553 {
554 if (!ct.wCallTip.Created())
555 ct.wCallTip = new QsciSciCallTip(qsb, this);
556
557 QsciSciCallTip *w = reinterpret_cast<QsciSciCallTip *>(ct.wCallTip.GetID());
558
559 w->resize(rc.right - rc.left, rc.bottom - rc.top);
560 ct.wCallTip.Show();
561 }
562
563
564 // Add an item to the right button menu.
AddToPopUp(const char * label,int cmd,bool enabled)565 void QsciScintillaQt::AddToPopUp(const char *label, int cmd, bool enabled)
566 {
567 QsciSciPopup *pm = static_cast<QsciSciPopup *>(popup.GetID());
568
569 if (*label)
570 pm->addItem(qApp->translate("ContextMenu", label), cmd, enabled, this);
571 else
572 pm->addSeparator();
573 }
574
575
576 // Claim the selection.
ClaimSelection()577 void QsciScintillaQt::ClaimSelection()
578 {
579 bool isSel = !sel.Empty();
580
581 if (isSel)
582 {
583 QClipboard *cb = QApplication::clipboard();
584
585 // If we support X11 style selection then make it available now.
586 if (cb->supportsSelection())
587 {
588 Scintilla::SelectionText text;
589
590 CopySelectionRange(&text);
591
592 if (text.Data())
593 cb->setMimeData(mimeSelection(text), QClipboard::Selection);
594 }
595
596 primarySelection = true;
597 }
598 else
599 primarySelection = false;
600
601 #if !defined(QT_NO_ACCESSIBILITY)
602 QsciAccessibleScintillaBase::selectionChanged(qsb, isSel);
603 #endif
604
605 emit qsb->QSCN_SELCHANGED(isSel);
606 }
607
608
609 // Unclaim the selection.
UnclaimSelection()610 void QsciScintillaQt::UnclaimSelection()
611 {
612 if (primarySelection)
613 {
614 primarySelection = false;
615 qsb->viewport()->update();
616 }
617 }
618
619
620 // Implemented to provide compatibility with the Windows version.
DirectFunction(QsciScintillaQt * sciThis,unsigned int iMessage,uptr_t wParam,sptr_t lParam)621 sptr_t QsciScintillaQt::DirectFunction(QsciScintillaQt *sciThis, unsigned int iMessage,
622 uptr_t wParam, sptr_t lParam)
623 {
624 return sciThis->WndProc(iMessage,wParam,lParam);
625 }
626
627
628 // Draw the contents of the widget.
paintEvent(QPaintEvent * e)629 void QsciScintillaQt::paintEvent(QPaintEvent *e)
630 {
631 Scintilla::Surface *sw;
632
633 const QRect &qr = e->rect();
634
635 rcPaint.left = qr.left();
636 rcPaint.top = qr.top();
637 rcPaint.right = qr.right() + 1;
638 rcPaint.bottom = qr.bottom() + 1;
639
640 Scintilla::PRectangle rcClient = GetClientRectangle();
641 paintingAllText = rcPaint.Contains(rcClient);
642
643 sw = Scintilla::Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
644 if (!sw)
645 return;
646
647 QPainter painter(qsb->viewport());
648
649 paintState = painting;
650 sw->Init(&painter);
651 sw->SetUnicodeMode(CodePage() == SC_CP_UTF8);
652 Paint(sw, rcPaint);
653
654 delete sw;
655
656 // If the painting area was insufficient to cover the new style or brace
657 // highlight positions then repaint the whole thing.
658 if (paintState == paintAbandoned)
659 {
660 // Do a full re-paint immediately. This may only be needed on OS X (to
661 // avoid flicker).
662 paintingAllText = true;
663
664 sw = Scintilla::Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
665 if (!sw)
666 return;
667
668 QPainter painter(qsb->viewport());
669
670 paintState = painting;
671 sw->Init(&painter);
672 sw->SetUnicodeMode(CodePage() == SC_CP_UTF8);
673 Paint(sw, rcPaint);
674
675 delete sw;
676
677 qsb->viewport()->update();
678 }
679
680 paintState = notPainting;
681 }
682
683
684 // Re-implemented to drive the tickers.
timerEvent(QTimerEvent * e)685 void QsciScintillaQt::timerEvent(QTimerEvent *e)
686 {
687 for (int i = 0; i <= static_cast<int>(tickPlatform); ++i)
688 if (timers[i] == e->timerId())
689 TickFor(static_cast<TickReason>(i));
690 }
691
692
693 // Re-implemented to say we support fine tickers.
FineTickerAvailable()694 bool QsciScintillaQt::FineTickerAvailable()
695 {
696 return true;
697 }
698
699
700 // Re-implemented to stop a ticker.
FineTickerCancel(TickReason reason)701 void QsciScintillaQt::FineTickerCancel(TickReason reason)
702 {
703 int &ticker = timers[static_cast<int>(reason)];
704
705 if (ticker != 0)
706 {
707 killTimer(ticker);
708 ticker = 0;
709 }
710 }
711
712
713 // Re-implemented to check if a particular ticker is running.
FineTickerRunning(TickReason reason)714 bool QsciScintillaQt::FineTickerRunning(TickReason reason)
715 {
716 return (timers[static_cast<int>(reason)] != 0);
717 }
718
719
720 // Re-implemented to start a ticker.
FineTickerStart(TickReason reason,int ms,int)721 void QsciScintillaQt::FineTickerStart(TickReason reason, int ms, int)
722 {
723 int &ticker = timers[static_cast<int>(reason)];
724
725 if (ticker != 0)
726 killTimer(ticker);
727
728 ticker = startTimer(ms);
729 }
730
731
732 // Re-implemented to support idle processing.
SetIdle(bool on)733 bool QsciScintillaQt::SetIdle(bool on)
734 {
735 if (on)
736 {
737 if (!idler.state)
738 {
739 QTimer *timer = reinterpret_cast<QTimer *>(idler.idlerID);
740
741 if (!timer)
742 {
743 idler.idlerID = timer = new QTimer(this);
744 connect(timer, SIGNAL(timeout()), this, SLOT(onIdle()));
745 }
746
747 timer->start(0);
748 idler.state = true;
749 }
750 }
751 else if (idler.state)
752 {
753 reinterpret_cast<QTimer *>(idler.idlerID)->stop();
754 idler.state = false;
755 }
756
757 return true;
758 }
759
760
761 // Invoked to trigger any idle processing.
onIdle()762 void QsciScintillaQt::onIdle()
763 {
764 if (!Idle())
765 SetIdle(false);
766 }
767