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()
112 readonly
property alias body : body
118 readonly
property alias document : document
124 readonly
property alias scrollView: _scrollView
130 readonly
property alias documentMenu : _documentMenuLoader.item
136 property alias text: body.text
142 property alias uppercase: document.uppercase
148 property alias underline: document.underline
154 property alias italic: document.italic
160 property alias bold: document.bold
166 property alias canRedo: body.canRedo
173 property alias fileUrl : document.fileUrl
179 property bool showLineNumbers :
false
185 property bool spellcheckEnabled:
false
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:
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()
Q_SCRIPTABLE Q_NOREPLY void start()
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()
QString arg(Args &&... args) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)