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
250 property var spellcheckhighlighter: null
251 property var spellcheckhighlighterLoader: null
252 property int restoredCursorPosition: 0
253 property int restoredSelectionStart
254 property int restoredSelectionEnd
255 property var suggestions: []
256 property bool deselectWhenMenuClosed:
true
257 property var runOnMenuClose: () => {}
258 property bool persistentSelectionSetting
260 Component.onCompleted:
262 persistentSelectionSetting = body.persistentSelection
265 Maui.MenuItemActionRow
269 icon.name:
"edit-undo-symbolic"
271 shortcut: StandardKey.Undo
275 documentMenu.deselectWhenMenuClosed =
false;
276 documentMenu.runOnMenuClose = () => body.undo();
282 icon.name:
"edit-redo-symbolic"
284 shortcut: StandardKey.Redo
288 documentMenu.deselectWhenMenuClosed =
false;
289 documentMenu.runOnMenuClose = () => body.redo();
298 icon.name:
"edit-copy-symbolic"
300 shortcut: StandardKey.Copy
305 documentMenu.deselectWhenMenuClosed =
false;
306 documentMenu.runOnMenuClose = () => control.body.copy();
309 enabled: body.selectedText.length
315 icon.name:
"edit-cut-symbolic"
317 shortcut: StandardKey.Cut
321 documentMenu.deselectWhenMenuClosed =
false;
322 documentMenu.runOnMenuClose = () => control.body.cut();
324 enabled: !body.readOnly && body.selectedText.length
331 icon.name:
"edit-paste-symbolic"
333 shortcut: StandardKey.Paste
338 documentMenu.deselectWhenMenuClosed =
false;
339 documentMenu.runOnMenuClose = () => control.body.paste();
342 enabled: !body.readOnly
349 icon.name:
"edit-select-all-symbolic"
350 text:
i18n(
"Select All")
351 shortcut: StandardKey.SelectAll
356 documentMenu.deselectWhenMenuClosed =
false
357 documentMenu.runOnMenuClose = () => control.body.selectAll();
363 text:
i18nd(
"mauikittexteditor",
"Search Selected Text on Google...")
364 onTriggered:
Qt.openUrlExternally(
"https://www.google.com/search?q="+body.selectedText)
365 enabled: body.selectedText.length
370 enabled: !control.body.readOnly && control.body.selectedText
373 icon.name:
"edit-delete-symbolic"
375 shortcut: StandardKey.Delete
380 documentMenu.deselectWhenMenuClosed =
false;
381 documentMenu.runOnMenuClose = () => control.body.remove(control.body.selectionStart, control.body.selectionEnd);
392 title:
i18nd(
"mauikittexteditor",
"Spelling")
393 enabled: control.spellcheckEnabled
398 active: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
399 model: documentMenu.suggestions
405 documentMenu.deselectWhenMenuClosed =
false;
406 documentMenu.runOnMenuClose = () => documentMenu.spellcheckhighlighter.replaceWord(modelData);
410 onObjectAdded: (index, object) =>
412 _spellingMenu.insertItem(0,
object)
415 onObjectRemoved: (index, object) =>
417 _spellingMenu.removeItem(_spellingMenu.itemAt(0))
423 enabled: !control.body.readOnly && ((documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled) || (documentMenu.spellcheckhighlighterLoader && documentMenu.spellcheckhighlighterLoader.activable))
428 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled && documentMenu.suggestions.length === 0
431 text: documentMenu.spellcheckhighlighter ?
i18n(
"No suggestions for \"%1\"").arg(documentMenu.spellcheckhighlighter.wordUnderMouse) :
''
438 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
441 text: documentMenu.spellcheckhighlighter ?
i18n(
"Add \"%1\" to dictionary").arg(documentMenu.spellcheckhighlighter.wordUnderMouse) :
''
444 documentMenu.deselectWhenMenuClosed =
false;
445 documentMenu.runOnMenuClose = () => spellcheckhighlighter.addWordToDictionary(documentMenu.spellcheckhighlighter.wordUnderMouse);
452 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
458 documentMenu.deselectWhenMenuClosed =
false;
459 documentMenu.runOnMenuClose = () => documentMenu.spellcheckhighlighter.ignoreWord(documentMenu.spellcheckhighlighter.wordUnderMouse);
466 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighterLoader && documentMenu.spellcheckhighlighterLoader.activable
468 checked: documentMenu.spellcheckhighlighter ? documentMenu.spellcheckhighlighter.active :
false
469 text:
i18n(
"Enable Spellchecker")
472 spellcheckhighlighterLoader.active = checked;
473 documentMenu.spellcheckhighlighter = documentMenu.spellcheckhighlighterLoader.item;
478 function targetClick(spellcheckhighlighter, mousePosition)
480 control.body.persistentSelection =
true;
481 documentMenu.spellcheckhighlighterLoader = spellcheckhighlighter;
482 if (spellcheckhighlighter && spellcheckhighlighter.active) {
483 documentMenu.spellcheckhighlighter = spellcheckhighlighter.item;
484 documentMenu.suggestions = mousePosition ? spellcheckhighlighter.item.suggestions(mousePosition) : [];
486 documentMenu.spellcheckhighlighter = null;
487 documentMenu.suggestions = [];
490 storeCursorAndSelection();
494 function storeCursorAndSelection()
496 documentMenu.restoredCursorPosition = control.body.cursorPosition;
497 documentMenu.restoredSelectionStart = control.body.selectionStart;
498 documentMenu.restoredSelectionEnd = control.body.selectionEnd;
503 runOnMenuClose = () => {};
509 body.persistentSelection = documentMenu.persistentSelectionSetting
511 if (documentMenu.deselectWhenMenuClosed)
515 documentMenu.deselectWhenMenuClosed =
true;
518 body.forceActiveFocus();
519 body.cursorPosition = documentMenu.restoredCursorPosition;
520 body.select(documentMenu.restoredSelectionStart, documentMenu.restoredSelectionEnd);
524 runOnMenuClose = () => {};
540 rightContent: ToolButton
543 icon.name:
"edit-find-replace"
548 leftContent:
Maui.ToolButtonMenu
550 icon.name:
"overflow-menu"
554 id: _findCaseSensitively
556 text:
i18nd(
"mauikittexteditor",
"Case Sensitive")
563 text:
i18nd(
"mauikittexteditor",
"Whole Words Only")
567 middleContent:
Maui.SearchField
570 Layout.fillWidth:
true
571 Layout.maximumWidth: 500
572 Layout.alignment:
Qt.AlignCenter
573 placeholderText:
i18nd(
"mauikittexteditor",
"Find")
584 enabled: _findField.text.length
585 icon.name:
"arrow-up"
586 onTriggered: document.find(_findField.text,
false)
596 visible: _replaceButton.checked && _findToolBar.visible
598 enabled: !body.readOnly
599 forceCenterMiddleContent:
false
601 middleContent:
Maui.SearchField
604 placeholderText:
i18nd(
"mauikittexteditor",
"Replace")
605 Layout.fillWidth: true
606 Layout.maximumWidth: 500
607 Layout.alignment:
Qt.AlignCenter
608 icon.source:
"edit-find-replace"
611 text:
i18nd(
"mauikittexteditor",
"Replace")
612 enabled: _replaceField.text.length
613 icon.name:
"checkmark"
614 onTriggered: document.replace(_findField.text, _replaceField.text)
620 enabled: _replaceField.text.length
621 text:
i18nd(
"mauikittexteditor",
"Replace All")
622 onClicked: document.replaceAll(_findField.text, _replaceField.text)
633 model: document.alerts
638 property var alert : model.alert
639 readonly
property int index_ : index
642 Maui.Theme.backgroundColor:
646 case 0:
return Maui.Theme.positiveBackgroundColor
647 case 1:
return Maui.Theme.neutralBackgroundColor
648 case 2:
return Maui.Theme.negativeBackgroundColor
652 Maui.Theme.textColor:
656 case 0:
return Maui.Theme.positiveTextColor
657 case 1:
return Maui.Theme.neutralTextColor
658 case 2:
return Maui.Theme.negativeTextColor
662 forceCenterMiddleContent:
false
663 middleContent:
Maui.ListItemTemplate
665 Maui.Theme.inherit:
true
666 Layout.fillWidth:
true
667 Layout.fillHeight:
true
668 label1.text: alert.title
669 label2.text: alert.body
672 rightContent: Repeater
674 model: alert.actionLabels
679 property int index_ : index
681 onClicked: alert.triggerAction(_alertAction.index_, _alertBar.index_)
683 Maui.Theme.backgroundColor:
Qt.lighter(_alertBar.Maui.Theme.backgroundColor, 1.2)
684 Maui.Theme.hoverColor:
Qt.lighter(_alertBar.Maui.Theme.backgroundColor, 1)
685 Maui.Theme.textColor:
Qt.darker(
Maui.Theme.backgroundColor)
694 id: _linesCounterComponent
699 anchors.topMargin: body.topPadding + body.textMargin
701 color:
Qt.darker(
Maui.Theme.backgroundColor, 1.2)
705 id: _linesCounterList
712 value: _flickable.contentY
713 restoreMode: Binding.RestoreBindingOrValue
716 model: TE.LineNumberModel
718 lineCount: body.text !==
"" ? document.lineCount : 0
725 readonly
property int line : index
728 width: ListView.view.width
729 height: Math.max(Math.ceil(fontMetrics.lineSpacing), document.lineHeight(line))
731 readonly
property bool isCurrentItem : document.currentLineIndex === index
737 function onContentHeightChanged()
739 if(body.wrapMode !==
Text.NoWrap)
741 _delegate.height = control.document.lineHeight(_delegate.line)
744 if(_delegate.isCurrentItem)
746 console.log(
"Updating line height")
750 _linesCounterList.contentY = _flickable.contentY
753 function onWrapModeChanged()
755 _delegate.height = control.document.lineHeight(_delegate.line)
761 Layout.fillWidth:
true
762 Layout.fillHeight:
true
764 opacity: isCurrentItem ? 1 : 0.7
765 color: isCurrentItem ? control.Maui.Theme.highlightedTextColor : control.body.color
766 font.pointSize: Math.min(
Maui.Style.fontSizes.medium, body.font.pointSize)
767 horizontalAlignment:
Text.AlignHCenter
768 verticalAlignment:
Text.AlignTop
770 font.family:
"Monospace"
773 background: Rectangle
775 visible: isCurrentItem
776 color:
Maui.Theme.highlightColor
815 active: control.showLineNumbers && !document.isRich && body.lineCount > 1 && body.wrapMode ===
Text.NoWrap
817 Layout.fillHeight:
true
818 Layout.preferredWidth: active ? fontMetrics.averageCharacterWidth
819 * (Math.floor(Math.log10(body.lineCount)) + 1) + 10 : 0
822 sourceComponent: _linesCounterComponent
829 Layout.fillHeight:
true
830 Layout.fillWidth:
true
838 Keys.onPressed: (
event) =>
840 if((
event.key ===
Qt.Key_F) && (
event.modifiers &
Qt.ControlModifier))
842 control.showFindBar =
true
844 if(control.body.selectedText.length)
846 _findField.text = control.body.selectedText
849 _findField.selectAll()
852 _findField.forceActiveFocus()
853 event.accepted =
true
856 if((
event.key ===
Qt.Key_R) && (
event.modifiers &
Qt.ControlModifier))
858 control.showFindBar =
true
859 _replaceButton.checked =
true
860 _findField.text = control.body.selectedText
861 _replaceField.forceActiveFocus()
862 event.accepted =
true
872 boundsBehavior : Flickable.StopAtBounds
873 boundsMovement : Flickable.StopAtBounds
875 TextArea.flickable: TextArea
878 Maui.Theme.inherit:
true
881 placeholderText:
i18nd(
"mauikittexteditor",
"Body")
883 textFormat: TextEdit.PlainText
885 tabStopDistance: fontMetrics.averageCharacterWidth * 4
886 renderType: Text.QtRendering
888 activeFocusOnPress: true
889 focusPolicy:
Qt.StrongFocus
891 Keys.onReturnPressed: (event) =>
893 body.insert(body.cursorPosition,
"\n")
894 if(
Maui.Handy.isAndroid)
899 Qt.inputMethod.show();
900 event.accepted = true
904 Keys.onPressed: (
event) =>
906 if(
event.key ===
Qt.Key_PageUp)
908 _flickable.flick(0, 60*Math.sqrt(_flickable.height))
909 event.accepted =
true
912 if(
event.key ===
Qt.Key_PageDown)
914 _flickable.flick(0, -60*Math.sqrt(_flickable.height))
915 event.accepted =
true
919 onPressAndHold: (
event) =>
921 if(
Maui.Handy.isAndroid)
926 if(
Maui.Handy.isMobile ||
Maui.Handy.isTouch)
928 documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(
event.x,
event.y))
929 event.accepted =
true
932 event.accepted =
false
935 onPressed: (
event) =>
937 if(
Maui.Handy.isMobile)
942 if(
event.button ===
Qt.RightButton)
944 documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(
event.x,
event.y))
945 event.accepted =
true
955 active:
Maui.Handy.isTouch
958 anchors.bottom: parent.bottom
959 anchors.right: parent.right
960 anchors.margins:
Maui.Style.space.big
962 sourceComponent:
Maui.FloatingButton
964 icon.name:
"edit-menu"
965 onClicked: documentMenu.targetClick(spellcheckhighlighterLoader, body.cursorPosition)
973 function forceActiveFocus()
982 function goToLine(line)
984 if(line>0 && line <= body.lineCount)
986 body.cursorPosition = document.goToLine(line-1)
987 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()