6import org.mauikit.controls as Maui
7import org.mauikit.texteditor as TE
9import org.kde.sonnet as Sonnet
86 title: document.fileName + (document.modified ? "*" :
"")
91 property
bool showFindBar: false
97 _findField.forceActiveFocus()
100 body.forceActiveFocus()
104 onWidthChanged: body.update()
106 onHeightChanged: body.update()
130 readonly
property alias
documentMenu : _documentMenuLoader.item
196 document: body.textDocument
197 cursorPosition: body.cursorPosition
198 selectionStart: body.selectionStart
199 selectionEnd: body.selectionEnd
200 backgroundColor: control.Maui.Theme.backgroundColor
201 enableSyntaxHighlighting:
false
202 findCaseSensitively: _findCaseSensitively.checked
203 findWholeWords: _findWholeWords.checked
205 onSearchFound: (
start, end) =>
207 body.select(
start, end)
213 id: spellcheckhighlighterLoader
214 property bool activable: control.spellcheckEnabled
216 active: activable && settings.checkerEnabledByDefault
225 sourceComponent:
Sonnet.SpellcheckHighlighter
227 id: spellcheckhighlighter
228 document: body.textDocument
229 cursorPosition: body.cursorPosition
230 selectionStart: body.selectionStart
231 selectionEnd: body.selectionEnd
232 misspelledColor:
Maui.Theme.negativeTextColor
233 active: spellcheckhighlighterLoader.activable && settings.checkerEnabledByDefault
235 onChangeCursorPosition: (
start,
end) =>
237 body.cursorPosition =
start;
238 body.moveCursorSelection(end, TextEdit.SelectCharacters);
245 id: _documentMenuLoader
248 sourceComponent:
Maui.ContextualMenu
251 property var spellcheckhighlighter: null
252 property var spellcheckhighlighterLoader: null
253 property int restoredCursorPosition: 0
254 property int restoredSelectionStart
255 property int restoredSelectionEnd
256 property var suggestions: []
257 property bool deselectWhenMenuClosed:
true
258 property var runOnMenuClose: () => {}
259 property bool persistentSelectionSetting
261 Component.onCompleted:
263 persistentSelectionSetting = body.persistentSelection
266 Maui.MenuItemActionRow
270 icon.name:
"edit-undo-symbolic"
272 shortcut: StandardKey.Undo
276 documentMenu.deselectWhenMenuClosed =
false;
277 documentMenu.runOnMenuClose = () => body.undo();
283 icon.name:
"edit-redo-symbolic"
285 shortcut: StandardKey.Redo
289 documentMenu.deselectWhenMenuClosed =
false;
290 documentMenu.runOnMenuClose = () => body.redo();
299 icon.name:
"edit-copy-symbolic"
301 shortcut: StandardKey.Copy
306 documentMenu.deselectWhenMenuClosed =
false;
307 documentMenu.runOnMenuClose = () => control.body.copy();
310 enabled: body.selectedText.length
312 height: visible ? implicitHeight : -_menu.spacing
318 icon.name:
"edit-cut-symbolic"
320 shortcut: StandardKey.Cut
324 documentMenu.deselectWhenMenuClosed =
false;
325 documentMenu.runOnMenuClose = () => control.body.cut();
327 enabled: !body.readOnly && body.selectedText.length
329 height: visible ? implicitHeight : -_menu.spacing
336 icon.name:
"edit-paste-symbolic"
338 shortcut: StandardKey.Paste
343 documentMenu.deselectWhenMenuClosed =
false;
344 documentMenu.runOnMenuClose = () => control.body.paste();
347 enabled: !body.readOnly
354 icon.name:
"edit-select-all-symbolic"
355 text:
i18n(
"Select All")
356 shortcut: StandardKey.SelectAll
361 documentMenu.deselectWhenMenuClosed =
false
362 documentMenu.runOnMenuClose = () => control.body.selectAll();
370 text:
i18nd(
"mauikittexteditor",
"Search Selected Text on Google...")
371 onTriggered:
Qt.openUrlExternally(
"https://www.google.com/search?q="+body.selectedText)
372 enabled: body.selectedText.length
374 height: visible ? implicitHeight : -_menu.spacing
379 enabled: control.body.selectedText.length > 0 &&
Maui.Handy.isEmail(control.body.selectedText)
381 height: visible ? implicitHeight : -_menu.spacing
383 icon.name:
"mail-sent"
384 onTriggered:
Qt.openUrlExternally(
"mailto:"+control.body.selectedText)
389 enabled: control.body.selectedText.length > 0 &&
Maui.Handy.isPhoneNumber(control.body.selectedText)
391 height: visible ? implicitHeight : -_menu.spacing
392 text:
i18n(
"Save as Contact")
393 icon.name:
"contact-new-symbolic"
394 onTriggered:
Qt.openUrlExternally(
"tel:"+control.body.selectedText)
399 enabled: control.body.selectedText.length > 0 &&
Maui.Handy.isWebLink(control.body.selectedText)
401 height: visible ? implicitHeight : -_menu.spacing
402 text:
i18n(
"Open Link")
403 icon.name:
"website-symbolic"
404 onTriggered:
Qt.openUrlExternally(control.body.selectedText)
411 enabled: !control.body.readOnly && control.body.selectedText
413 height: visible ? implicitHeight : -_menu.spacing
416 icon.name:
"edit-delete-symbolic"
418 shortcut: StandardKey.Delete
423 documentMenu.deselectWhenMenuClosed =
false;
424 documentMenu.runOnMenuClose = () => control.body.remove(control.body.selectionStart, control.body.selectionEnd);
431 title:
i18nd(
"mauikittexteditor",
"Spelling")
432 enabled: control.spellcheckEnabled
434 height: visible ? implicitHeight : -_menu.spacing
439 active: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
440 model: documentMenu.suggestions
446 documentMenu.deselectWhenMenuClosed =
false;
447 documentMenu.runOnMenuClose = () => documentMenu.spellcheckhighlighter.replaceWord(modelData);
451 onObjectAdded: (index, object) =>
453 _spellingMenu.insertItem(0,
object)
456 onObjectRemoved: (index, object) =>
458 _spellingMenu.removeItem(_spellingMenu.itemAt(0))
464 enabled: !control.body.readOnly && ((documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled) || (documentMenu.spellcheckhighlighterLoader && documentMenu.spellcheckhighlighterLoader.activable))
469 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled && documentMenu.suggestions.length === 0
472 text: documentMenu.spellcheckhighlighter ?
i18n(
"No suggestions for \"%1\"").arg(documentMenu.spellcheckhighlighter.wordUnderMouse) :
''
479 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
482 text: documentMenu.spellcheckhighlighter ?
i18n(
"Add \"%1\" to dictionary").arg(documentMenu.spellcheckhighlighter.wordUnderMouse) :
''
485 documentMenu.deselectWhenMenuClosed =
false;
486 documentMenu.runOnMenuClose = () => spellcheckhighlighter.addWordToDictionary(documentMenu.spellcheckhighlighter.wordUnderMouse);
493 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
499 documentMenu.deselectWhenMenuClosed =
false;
500 documentMenu.runOnMenuClose = () => documentMenu.spellcheckhighlighter.ignoreWord(documentMenu.spellcheckhighlighter.wordUnderMouse);
507 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighterLoader && documentMenu.spellcheckhighlighterLoader.activable
509 checked: documentMenu.spellcheckhighlighter ? documentMenu.spellcheckhighlighter.active :
false
510 text:
i18n(
"Enable Spellchecker")
513 spellcheckhighlighterLoader.active = checked;
514 documentMenu.spellcheckhighlighter = documentMenu.spellcheckhighlighterLoader.item;
519 function targetClick(spellcheckhighlighter, mousePosition)
521 control.body.persistentSelection =
true;
522 documentMenu.spellcheckhighlighterLoader = spellcheckhighlighter;
523 if (spellcheckhighlighter && spellcheckhighlighter.active) {
524 documentMenu.spellcheckhighlighter = spellcheckhighlighter.item;
525 documentMenu.suggestions = mousePosition ? spellcheckhighlighter.item.suggestions(mousePosition) : [];
527 documentMenu.spellcheckhighlighter = null;
528 documentMenu.suggestions = [];
531 storeCursorAndSelection();
535 function storeCursorAndSelection()
537 documentMenu.restoredCursorPosition = control.body.cursorPosition;
538 documentMenu.restoredSelectionStart = control.body.selectionStart;
539 documentMenu.restoredSelectionEnd = control.body.selectionEnd;
544 runOnMenuClose = () => {};
550 body.persistentSelection = documentMenu.persistentSelectionSetting
552 if (documentMenu.deselectWhenMenuClosed)
556 documentMenu.deselectWhenMenuClosed =
true;
559 body.forceActiveFocus();
560 body.cursorPosition = documentMenu.restoredCursorPosition;
561 body.select(documentMenu.restoredSelectionStart, documentMenu.restoredSelectionEnd);
565 runOnMenuClose = () => {};
581 rightContent: ToolButton
584 icon.name:
"edit-find-replace"
589 leftContent:
Maui.ToolButtonMenu
591 icon.name:
"overflow-menu"
595 id: _findCaseSensitively
597 text:
i18nd(
"mauikittexteditor",
"Case Sensitive")
604 text:
i18nd(
"mauikittexteditor",
"Whole Words Only")
608 middleContent:
Maui.SearchField
611 Layout.fillWidth:
true
612 Layout.maximumWidth: 500
613 Layout.alignment:
Qt.AlignCenter
614 placeholderText:
i18nd(
"mauikittexteditor",
"Find")
625 enabled: _findField.text.length
626 icon.name:
"arrow-up"
627 onTriggered: document.find(_findField.text,
false)
637 visible: _replaceButton.checked && _findToolBar.visible
639 enabled: !body.readOnly
640 forceCenterMiddleContent:
false
642 middleContent:
Maui.SearchField
645 placeholderText:
i18nd(
"mauikittexteditor",
"Replace")
646 Layout.fillWidth: true
647 Layout.maximumWidth: 500
648 Layout.alignment:
Qt.AlignCenter
649 icon.source:
"edit-find-replace"
652 text:
i18nd(
"mauikittexteditor",
"Replace")
653 enabled: _replaceField.text.length
654 icon.name:
"checkmark"
655 onTriggered: document.replace(_findField.text, _replaceField.text)
661 enabled: _replaceField.text.length
662 text:
i18nd(
"mauikittexteditor",
"Replace All")
663 onClicked: document.replaceAll(_findField.text, _replaceField.text)
674 model: document.alerts
679 property var alert : model.alert
680 readonly
property int index_ : index
683 Maui.Theme.backgroundColor:
687 case 0:
return Maui.Theme.positiveBackgroundColor
688 case 1:
return Maui.Theme.neutralBackgroundColor
689 case 2:
return Maui.Theme.negativeBackgroundColor
693 Maui.Theme.textColor:
697 case 0:
return Maui.Theme.positiveTextColor
698 case 1:
return Maui.Theme.neutralTextColor
699 case 2:
return Maui.Theme.negativeTextColor
703 forceCenterMiddleContent:
false
704 middleContent:
Maui.ListItemTemplate
706 Maui.Theme.inherit:
true
707 Layout.fillWidth:
true
708 Layout.fillHeight:
true
709 label1.text: alert.title
710 label2.text: alert.body
713 rightContent: Repeater
715 model: alert.actionLabels
720 property int index_ : index
722 onClicked: alert.triggerAction(_alertAction.index_, _alertBar.index_)
724 Maui.Theme.backgroundColor:
Qt.lighter(_alertBar.Maui.Theme.backgroundColor, 1.2)
725 Maui.Theme.hoverColor:
Qt.lighter(_alertBar.Maui.Theme.backgroundColor, 1)
726 Maui.Theme.textColor:
Qt.darker(
Maui.Theme.backgroundColor)
735 id: _linesCounterComponent
740 anchors.topMargin: body.topPadding + body.textMargin
742 color:
Qt.darker(
Maui.Theme.backgroundColor, 1.2)
746 id: _linesCounterList
753 value: _flickable.contentY
754 restoreMode: Binding.RestoreBindingOrValue
757 model: TE.LineNumberModel
759 lineCount: body.text !==
"" ? document.lineCount : 0
766 readonly
property int line : index
769 width: ListView.view.width
770 height: Math.max(Math.ceil(fontMetrics.lineSpacing), document.lineHeight(line))
772 readonly
property bool isCurrentItem : document.currentLineIndex === index
778 function onContentHeightChanged()
780 if(body.wrapMode !==
Text.NoWrap)
782 _delegate.height = control.document.lineHeight(_delegate.line)
785 if(_delegate.isCurrentItem)
787 console.log(
"Updating line height")
791 _linesCounterList.contentY = _flickable.contentY
794 function onWrapModeChanged()
796 _delegate.height = control.document.lineHeight(_delegate.line)
802 Layout.fillWidth:
true
803 Layout.fillHeight:
true
805 opacity: isCurrentItem ? 1 : 0.7
806 color: isCurrentItem ? control.Maui.Theme.highlightedTextColor : control.body.color
807 font.pointSize: Math.min(
Maui.Style.fontSizes.medium, body.font.pointSize)
808 horizontalAlignment:
Text.AlignHCenter
809 verticalAlignment:
Text.AlignTop
811 font.family:
"Monospace"
814 background: Rectangle
816 visible: isCurrentItem
817 color:
Maui.Theme.highlightColor
856 active: control.showLineNumbers && !document.isRich && body.lineCount > 1 && body.wrapMode ===
Text.NoWrap
858 Layout.fillHeight:
true
859 Layout.preferredWidth: active ? fontMetrics.averageCharacterWidth
860 * (Math.floor(Math.log10(body.lineCount)) + 1) + 10 : 0
863 sourceComponent: _linesCounterComponent
870 Layout.fillHeight:
true
871 Layout.fillWidth:
true
879 Keys.onPressed: (
event) =>
881 if((
event.key ===
Qt.Key_F) && (
event.modifiers &
Qt.ControlModifier))
883 control.showFindBar =
true
885 if(control.body.selectedText.length)
887 _findField.text = control.body.selectedText
890 _findField.selectAll()
893 _findField.forceActiveFocus()
894 event.accepted =
true
897 if((
event.key ===
Qt.Key_R) && (
event.modifiers &
Qt.ControlModifier))
899 control.showFindBar =
true
900 _replaceButton.checked =
true
901 _findField.text = control.body.selectedText
902 _replaceField.forceActiveFocus()
903 event.accepted =
true
913 boundsBehavior : Flickable.StopAtBounds
914 boundsMovement : Flickable.StopAtBounds
916 TextArea.flickable: TextArea
919 Maui.Theme.inherit:
true
922 placeholderText:
i18nd(
"mauikittexteditor",
"Body")
924 textFormat: TextEdit.PlainText
926 tabStopDistance: fontMetrics.averageCharacterWidth * 4
927 renderType: Text.QtRendering
929 activeFocusOnPress: true
930 focusPolicy:
Qt.StrongFocus
932 Keys.onReturnPressed: (event) =>
934 body.insert(body.cursorPosition,
"\n")
935 if(
Maui.Handy.isAndroid)
940 Qt.inputMethod.show();
941 event.accepted = true
945 Keys.onPressed: (
event) =>
947 if(
event.key ===
Qt.Key_PageUp)
949 _flickable.flick(0, 60*Math.sqrt(_flickable.height))
950 event.accepted =
true
953 if(
event.key ===
Qt.Key_PageDown)
955 _flickable.flick(0, -60*Math.sqrt(_flickable.height))
956 event.accepted =
true
960 onPressAndHold: (
event) =>
962 if(
Maui.Handy.isAndroid)
967 if(
Maui.Handy.isMobile ||
Maui.Handy.isTouch)
969 documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(
event.x,
event.y))
970 event.accepted =
true
973 event.accepted =
false
976 onPressed: (
event) =>
978 if(
Maui.Handy.isMobile)
983 if(
event.button ===
Qt.RightButton)
985 documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(
event.x,
event.y))
986 event.accepted =
true
996 active:
Maui.Handy.isTouch
999 anchors.bottom: parent.bottom
1000 anchors.right: parent.right
1001 anchors.margins:
Maui.Style.space.big
1003 sourceComponent:
Maui.FloatingButton
1005 icon.name:
"edit-menu"
1006 onClicked: documentMenu.targetClick(spellcheckhighlighterLoader, body.cursorPosition)
1014 function forceActiveFocus()
1023 function goToLine(line)
1025 if(line>0 && line <= body.lineCount)
1027 body.cursorPosition = document.goToLine(line-1)
1028 body.forceActiveFocus()
alias text
Alias to the text area text content.
alias document
Alias to access the DocumentHandler.
alias documentMenu
Alias to the contextual menu.
alias fileUrl
If a file url is provided the DocumentHandler will try to open its contents and display it.
bool spellcheckEnabled
Whether to enable the spell checker.
alias scrollView
Alias to the ScrollView.
bool showLineNumbers
If a sidebar listing each line number should be visible.
alias canRedo
Whether there are modifications to the document that can be redo.
alias body
Access to the editor text area.
Q_SCRIPTABLE QString start(QString train="")
QString i18nd(const char *domain, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
const QList< QKeySequence > & end()