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
704 value: _flickable.contentY
705 restoreMode: Binding.RestoreBindingOrValue
711 anchors.topMargin: body.topPadding + body.textMargin
713 implicitHeight: Math.max(_linesCounterList.contentHeight, control.height)
715 color:
Qt.darker(
Maui.Theme.backgroundColor, 1)
720 id: _linesCounterList
750 model: TE.LineNumberModel
752 lineCount: body.text !==
"" ? document.lineCount : 0
759 readonly
property int line : index
760 property bool foldable : control.document.isFoldable(line)
763 height: Math.max(Math.ceil(fontMetrics.lineSpacing), document.lineHeight(line))
765 readonly
property bool isCurrentItem : document.currentLineIndex === index
771 function onContentHeightChanged()
773 if(body.wrapMode !==
Text.NoWrap)
775 _delegate.height = control.document.lineHeight(_delegate.line)
778 if(_delegate.isCurrentItem)
780 console.log(
"Updating line height")
781 _delegate.foldable = control.document.isFoldable(_delegate.line)
784 _linesFlickable.contentY = _flickable.contentY
787 function onWrapModeChanged()
789 _delegate.height = control.document.lineHeight(_delegate.line)
796 height: parent.height
797 opacity: isCurrentItem ? 1 : 0.7
798 color: isCurrentItem ? control.Maui.Theme.highlightedTextColor : control.body.color
799 font.pointSize: Math.min(
Maui.Style.fontSizes.medium, body.font.pointSize)
800 horizontalAlignment:
Text.AlignHCenter
801 verticalAlignment:
Text.AlignVCenter
803 font.family:
"Monospace"
806 background: Rectangle
808 visible: isCurrentItem
809 color:
Maui.Theme.highlightColor
816 anchors.verticalCenter: parent.verticalCenter
824 contentItem:
Maui.Icon
847 active: control.showLineNumbers && !document.isRich
849 Layout.fillHeight:
true
850 Layout.preferredWidth: active ? fontMetrics.averageCharacterWidth
851 * (Math.floor(Math.log10(body.lineCount)) + 1) + 10 : 0
854 sourceComponent: _linesCounterComponent
861 Layout.fillHeight:
true
862 Layout.fillWidth:
true
870 Keys.onPressed: (
event) =>
872 if((
event.key ===
Qt.Key_F) && (
event.modifiers &
Qt.ControlModifier))
874 control.showFindBar =
true
876 if(control.body.selectedText.length)
878 _findField.text = control.body.selectedText
881 _findField.selectAll()
884 _findField.forceActiveFocus()
885 event.accepted =
true
888 if((
event.key ===
Qt.Key_R) && (
event.modifiers &
Qt.ControlModifier))
890 control.showFindBar =
true
891 _replaceButton.checked =
true
892 _findField.text = control.body.selectedText
893 _replaceField.forceActiveFocus()
894 event.accepted =
true
904 boundsBehavior : Flickable.StopAtBounds
905 boundsMovement : Flickable.StopAtBounds
907 TextArea.flickable: TextArea
910 Maui.Theme.inherit:
true
913 placeholderText:
i18nd(
"mauikittexteditor",
"Body")
915 textFormat: TextEdit.PlainText
917 leftPadding: _linesCounter.width + padding
919 tabStopDistance: fontMetrics.averageCharacterWidth * 4
920 renderType: Text.QtRendering
922 activeFocusOnPress: true
923 focusPolicy:
Qt.StrongFocus
924 Keys.onReturnPressed:
927 if(
Maui.Handy.isAndroid)
929 body.insert(body.cursorPosition,
"\n")
930 Qt.inputMethod.show();
934 Keys.onPressed: (
event) =>
936 if(
event.key ===
Qt.Key_PageUp)
938 _flickable.flick(0, 60*Math.sqrt(_flickable.height))
939 event.accepted =
true
942 if(
event.key ===
Qt.Key_PageDown)
944 _flickable.flick(0, -60*Math.sqrt(_flickable.height))
945 event.accepted =
true
949 onPressAndHold: (
event) =>
951 if(
Maui.Handy.isAndroid)
956 if(
Maui.Handy.isMobile ||
Maui.Handy.isTouch)
958 documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(
event.x,
event.y))
959 event.accepted =
true
962 event.accepted =
false
965 onPressed: (
event) =>
967 if(
Maui.Handy.isMobile)
972 if(
event.button ===
Qt.RightButton)
974 documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(
event.x,
event.y))
975 event.accepted =
true
985 active:
Maui.Handy.isTouch
988 anchors.bottom: parent.bottom
989 anchors.right: parent.right
990 anchors.margins:
Maui.Style.space.big
992 sourceComponent:
Maui.FloatingButton
994 icon.name:
"edit-menu"
995 onClicked: documentMenu.targetClick(spellcheckhighlighterLoader, body.cursorPosition)
1003 function forceActiveFocus()
1012 function goToLine(line)
1014 if(line>0 && line <= body.lineCount)
1016 body.cursorPosition = document.goToLine(line-1)
1017 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)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
QString arg(Args &&... args) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)