Warning, /maui/mauikit-texteditor/src/controls.6/TextEditor.qml is written in an unsupported language. File is not indexed.

0001 import QtQuick 2.15
0002 import QtQml 2.14
0003 import QtQuick.Controls 2.15
0004 import QtQuick.Layouts 1.3
0005 import QtQuick.Templates 2.15 as T
0006 
0007 import org.mauikit.controls 1.3 as Maui
0008 import org.mauikit.texteditor 1.0 as TE
0009 
0010 import org.kde.sonnet 1.0 as Sonnet
0011 
0012 /*!
0013  * \ since org.mauikit.texteditor 1.0
0014  * \inqmlmodule org.mauikit.texteditor
0015  *  \brief Integrated text editor component
0016  *
0017  *  A text area for editing text with convinient functions.
0018  *  The Editor is controlled by the DocumentHandler which controls the files I/O,
0019  *  the syntax highlighting styles, and many more text editing properties.
0020  */
0021 Page
0022 {
0023     id: control
0024     padding: 0
0025     focus: false
0026     clip: false
0027     title: document.fileName + (document.modified ? "*" : "")
0028     //     showTitle: false
0029     
0030     property bool showFindBar: false
0031     
0032     onShowFindBarChanged:
0033     {
0034         if(showFindBar)
0035         {
0036             _findField.forceActiveFocus()
0037         }else
0038         {
0039             body.forceActiveFocus()
0040         }
0041     }
0042     
0043     /*!
0044      *      \qmlproperty TextArea Editor::body
0045      * Access to the editor text area.
0046      */
0047     property alias body : body
0048     
0049     /*!
0050      *      \qmlproperty DocumentHandler Editor::document
0051      */
0052     property alias document : document
0053     
0054     /*!
0055      *      \qmlproperty ScrollablePage Editor::scrollView
0056      */
0057     property alias scrollView: _scrollView
0058     
0059     /*!
0060      *      \qmlproperty string Editor::text
0061      */
0062     property alias text: body.text
0063     
0064     /*!
0065      *      \qmlproperty bool Editor::uppercase
0066      */
0067     property alias uppercase: document.uppercase
0068     
0069     /*!
0070      *      \qmlproperty bool Editor::underline
0071      */
0072     property alias underline: document.underline
0073     
0074     /*!
0075      *      \qmlproperty bool Editor::italic
0076      */
0077     property alias italic: document.italic
0078     
0079     /*!
0080      *      \qmlproperty bool Editor::bold
0081      */
0082     property alias bold: document.bold
0083     
0084     /*!
0085      *      \qmlproperty bool Editor::canRedo
0086      */
0087     property alias canRedo: body.canRedo
0088     
0089     /*!
0090      *      \qmlproperty url Editor::fileUrl
0091      *
0092      *      If a file url is provided the DocumentHandler will try to open its contents and display it.
0093      */
0094     property alias fileUrl : document.fileUrl
0095     
0096     /*!
0097      *      \qmlproperty bool Editor::showLineNumbers
0098      *
0099      *      If a sidebar listing each line number should be visible.
0100      */
0101     property bool showLineNumbers : false
0102     
0103     property bool spellcheckEnabled: false
0104     
0105     TE.DocumentHandler
0106     {
0107         id: document
0108         document: body.textDocument
0109         cursorPosition: body.cursorPosition
0110         selectionStart: body.selectionStart
0111         selectionEnd: body.selectionEnd
0112         backgroundColor: control.Maui.Theme.backgroundColor
0113         enableSyntaxHighlighting: false
0114         findCaseSensitively:  _findCaseSensitively.checked
0115         findWholeWords: _findWholeWords.checked
0116         
0117         onSearchFound:
0118         {
0119             body.select(start, end)
0120         }
0121     }
0122     
0123     Loader
0124     {
0125         id: spellcheckhighlighterLoader
0126         property bool activable: control.spellcheckEnabled
0127         property Sonnet.Settings settings: Sonnet.Settings {}
0128         active: activable && settings.checkerEnabledByDefault
0129         onActiveChanged: if (active) {
0130             item.active = true;
0131         }
0132         sourceComponent: Sonnet.SpellcheckHighlighter {
0133             id: spellcheckhighlighter
0134             document:  body.textDocument
0135             cursorPosition: body.cursorPosition
0136             selectionStart: body.selectionStart
0137             selectionEnd: body.selectionEnd
0138             misspelledColor: Maui.Theme.negativeTextColor
0139             active: spellcheckhighlighterLoader.activable && settings.checkerEnabledByDefault
0140             
0141             onChangeCursorPosition: {
0142                 body.cursorPosition = start;
0143                 body.moveCursorSelection(end, TextEdit.SelectCharacters);
0144             }
0145         }
0146     }
0147     
0148     Maui.ContextualMenu
0149     {
0150         id: documentMenu
0151         property var spellcheckhighlighter: null
0152         property var spellcheckhighlighterLoader: null
0153         property int restoredCursorPosition: 0
0154         property int restoredSelectionStart
0155         property int restoredSelectionEnd
0156         property var suggestions: []
0157         property bool deselectWhenMenuClosed: true
0158         property var runOnMenuClose: () => {}
0159         property bool persistentSelectionSetting
0160         Component.onCompleted: persistentSelectionSetting = body.persistentSelection              
0161       
0162         Maui.MenuItemActionRow
0163         {
0164             Action 
0165             {
0166                 icon.name: "edit-undo-symbolic"
0167                 text: qsTr("Undo")
0168                 shortcut: StandardKey.Undo
0169                 
0170                 onTriggered: 
0171                 {
0172                     documentMenu.deselectWhenMenuClosed = false;
0173                     documentMenu.runOnMenuClose = () => body.undo();
0174                 }
0175             }            
0176             
0177             Action 
0178             {
0179                 icon.name: "edit-redo-symbolic"
0180                 text: qsTr("Redo")
0181                 shortcut: StandardKey.Redo
0182                 
0183                 onTriggered:
0184                 {
0185                     documentMenu.deselectWhenMenuClosed = false;
0186                     documentMenu.runOnMenuClose = () => body.redo();
0187                 }
0188             }            
0189         }        
0190         
0191         MenuItem
0192         {
0193             action: Action {
0194                 icon.name: "edit-copy-symbolic"
0195                 text: qsTr("Copy")
0196                 shortcut: StandardKey.Copy
0197             }
0198             onTriggered:
0199             {
0200                 documentMenu.deselectWhenMenuClosed = false;
0201                 documentMenu.runOnMenuClose = () => control.body.copy();
0202             }         
0203             enabled: body.selectedText.length
0204         }
0205         
0206         MenuItem
0207         {
0208             action: Action {
0209                 icon.name: "edit-cut-symbolic"
0210                 text: qsTr("Cut")
0211                 shortcut: StandardKey.Cut
0212             }
0213             onTriggered:
0214             {
0215                 documentMenu.deselectWhenMenuClosed = false;
0216                 documentMenu.runOnMenuClose = () => control.body.cut();
0217             }       
0218             enabled: !body.readOnly && body.selectedText.length
0219         }
0220         
0221         MenuItem
0222         {
0223             action: Action {
0224                 icon.name: "edit-paste-symbolic"
0225                 text: qsTr("Paste")
0226                 shortcut: StandardKey.Paste
0227             }
0228             onTriggered:
0229             {
0230                 documentMenu.deselectWhenMenuClosed = false;
0231                 documentMenu.runOnMenuClose = () => control.body.paste();
0232             }          
0233             enabled: !body.readOnly
0234         }
0235         
0236         
0237         MenuItem
0238         {
0239             action: Action {
0240                 icon.name: "edit-select-all-symbolic"
0241                 text: qsTr("Select All")
0242                 shortcut: StandardKey.SelectAll
0243             }
0244             onTriggered: 
0245             {
0246                 documentMenu.deselectWhenMenuClosed = false
0247                 documentMenu.runOnMenuClose = () => control.body.selectAll();
0248             }
0249         }       
0250         
0251         MenuItem
0252         {
0253             text: i18nd("mauikittexteditor","Search Selected Text on Google...")
0254             onTriggered: Qt.openUrlExternally("https://www.google.com/search?q="+body.selectedText)
0255             enabled: body.selectedText.length
0256         }
0257         
0258         MenuItem 
0259         {
0260             enabled: !control.body.readOnly && control.body.selectedText
0261             action: Action {
0262                 icon.name: "edit-delete-symbolic"
0263                 text: qsTr("Delete")
0264                 shortcut: StandardKey.Delete
0265             }
0266             onTriggered: {
0267                 documentMenu.deselectWhenMenuClosed = false;
0268                 documentMenu.runOnMenuClose = () => control.body.remove(control.body.selectionStart, control.body.selectionEnd);
0269             }
0270         }   
0271         
0272         
0273         MenuSeparator 
0274         {
0275         }
0276         
0277         Menu
0278         {
0279             id: _spellingMenu
0280             title: i18nd("mauikittexteditor","Spelling")
0281             enabled: control.spellcheckEnabled
0282            
0283             Instantiator
0284             {
0285                 id: _suggestions
0286                 active: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
0287                 model: documentMenu.suggestions
0288                 delegate: MenuItem 
0289                 {
0290                     text: modelData
0291                     onClicked:
0292                     {
0293                         documentMenu.deselectWhenMenuClosed = false;
0294                         documentMenu.runOnMenuClose = () => documentMenu.spellcheckhighlighter.replaceWord(modelData);
0295                     }
0296                 }
0297                 onObjectAdded: 
0298                 {
0299                     _spellingMenu.insertItem(0, object)
0300                 }
0301                 onObjectRemoved: _spellingMenu.removeItem(0)
0302             }            
0303             
0304             MenuSeparator 
0305             {
0306                 enabled: !control.body.readOnly && ((documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled) || (documentMenu.spellcheckhighlighterLoader && documentMenu.spellcheckhighlighterLoader.activable))
0307             }
0308             
0309             MenuItem {
0310                 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled && documentMenu.suggestions.length === 0
0311                 action: Action {
0312                     text: documentMenu.spellcheckhighlighter ? qsTr("No suggestions for \"%1\"").arg(documentMenu.spellcheckhighlighter.wordUnderMouse) : ''
0313                     enabled: false
0314                 }
0315             }
0316             MenuItem {
0317                 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
0318                 action: Action {
0319                     text: documentMenu.spellcheckhighlighter ? qsTr("Add \"%1\" to dictionary").arg(documentMenu.spellcheckhighlighter.wordUnderMouse) : ''
0320                     onTriggered: {
0321                         documentMenu.deselectWhenMenuClosed = false;
0322                         documentMenu.runOnMenuClose = () => spellcheckhighlighter.addWordToDictionary(documentMenu.spellcheckhighlighter.wordUnderMouse);
0323                     }
0324                 }
0325             }
0326             
0327             MenuItem {
0328                 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighter !== null && documentMenu.spellcheckhighlighter.active && documentMenu.spellcheckhighlighter.wordIsMisspelled
0329                 action: Action {
0330                     text: qsTr("Ignore")
0331                     onTriggered: {
0332                         documentMenu.deselectWhenMenuClosed = false;
0333                         documentMenu.runOnMenuClose = () => documentMenu.spellcheckhighlighter.ignoreWord(documentMenu.spellcheckhighlighter.wordUnderMouse);
0334                     }
0335                 }
0336             }
0337             
0338             MenuItem 
0339             {
0340                 enabled: !control.body.readOnly && documentMenu.spellcheckhighlighterLoader && documentMenu.spellcheckhighlighterLoader.activable
0341                 checkable: true
0342                 checked: documentMenu.spellcheckhighlighter ? documentMenu.spellcheckhighlighter.active : false
0343                 text: qsTr("Enable Spellchecker")
0344                 onCheckedChanged: {
0345                     spellcheckhighlighterLoader.active = checked;
0346                     documentMenu.spellcheckhighlighter = documentMenu.spellcheckhighlighterLoader.item;
0347                 }
0348             }
0349         }
0350         
0351         function targetClick(spellcheckhighlighter, mousePosition)
0352         {
0353             control.body.persistentSelection = true; // persist selection when menu is opened
0354             documentMenu.spellcheckhighlighterLoader = spellcheckhighlighter;
0355             if (spellcheckhighlighter && spellcheckhighlighter.active) {
0356                 documentMenu.spellcheckhighlighter = spellcheckhighlighter.item;
0357                 documentMenu.suggestions = mousePosition ? spellcheckhighlighter.item.suggestions(mousePosition) : [];
0358             } else {
0359                 documentMenu.spellcheckhighlighter = null;
0360                 documentMenu.suggestions = [];
0361             }
0362             
0363             storeCursorAndSelection();            
0364             documentMenu.show()            
0365         }
0366         
0367         function storeCursorAndSelection()
0368         {
0369             documentMenu.restoredCursorPosition = control.body.cursorPosition;
0370             documentMenu.restoredSelectionStart = control.body.selectionStart;
0371             documentMenu.restoredSelectionEnd = control.body.selectionEnd;
0372         }        
0373         
0374         onOpened: 
0375         {
0376             runOnMenuClose = () => {};
0377         }
0378         
0379         onClosed: 
0380         {
0381             // restore text field's original persistent selection setting
0382             body.persistentSelection = documentMenu.persistentSelectionSetting
0383             // deselect text field text if menu is closed not because of a right click on the text field
0384             if (documentMenu.deselectWhenMenuClosed) 
0385             {
0386                 body.deselect();
0387             }
0388             documentMenu.deselectWhenMenuClosed = true;
0389             
0390             // restore cursor position
0391             body.forceActiveFocus();
0392             body.cursorPosition = documentMenu.restoredCursorPosition;
0393             body.select(documentMenu.restoredSelectionStart, documentMenu.restoredSelectionEnd);
0394             
0395             // run action, and free memory
0396             runOnMenuClose();
0397             runOnMenuClose = () => {};
0398         }
0399     }
0400     
0401     footer: Column
0402     {
0403         width: parent.width
0404         
0405         Maui.ToolBar
0406         {
0407             id: _findToolBar
0408             visible: showFindBar
0409             width: parent.width
0410             position: ToolBar.Footer
0411             
0412             rightContent: ToolButton
0413             {
0414                 id: _replaceButton
0415                 icon.name: "edit-find-replace"
0416                 checkable: true
0417                 checked: false
0418             }
0419             
0420             leftContent: Maui.ToolButtonMenu
0421             {
0422                 icon.name: "overflow-menu"
0423                 
0424                 MenuItem
0425                 {
0426                     id: _findCaseSensitively
0427                     checkable: true
0428                     text: i18nd("mauikittexteditor","Case Sensitive")
0429                 }
0430                 
0431                 MenuItem
0432                 {
0433                     id: _findWholeWords
0434                     checkable: true
0435                     text: i18nd("mauikittexteditor","Whole Words Only")
0436                 }
0437             }
0438             
0439             middleContent: Maui.SearchField
0440             {
0441                 id: _findField
0442                 Layout.fillWidth: true
0443                 Layout.maximumWidth: 500
0444                 Layout.alignment: Qt.AlignCenter
0445                 placeholderText: i18nd("mauikittexteditor","Find")
0446                 
0447                 onAccepted:
0448                 {
0449                     document.find(text)
0450                 }
0451                 
0452                 actions:[
0453                 
0454                 Action
0455                 {
0456                     enabled: _findField.text.length
0457                     icon.name: "arrow-up"
0458                     onTriggered: document.find(_findField.text, false)
0459                 }
0460                 
0461                 //                    Action
0462                 //                    {
0463                 //                        enabled: _findField.text.length
0464                 //                        icon.name: "arrow-down"
0465                 //                        onTriggered: document.find(_findField.text, true)
0466                 //                    }
0467                 ]
0468             }
0469         }
0470         
0471         Maui.ToolBar
0472         {
0473             id: _replaceToolBar
0474             position: ToolBar.Footer
0475             visible: _replaceButton.checked && _findToolBar.visible
0476             width: parent.width
0477             enabled: !body.readOnly
0478             
0479             middleContent: Maui.SearchField
0480             {
0481                 id: _replaceField
0482                 placeholderText: i18nd("mauikittexteditor","Replace")
0483                 Layout.fillWidth: true
0484                 Layout.maximumWidth: 500
0485                 Layout.alignment: Qt.AlignCenter
0486                 icon.source: "edit-find-replace"
0487                 actions: Action
0488                 {
0489                     text: i18nd("mauikittexteditor","Replace")
0490                     enabled: _replaceField.text.length
0491                     icon.name: "checkmark"
0492                     onTriggered: document.replace(_findField.text, _replaceField.text)
0493                 }
0494             }
0495             
0496             rightContent: [
0497             Button
0498             {
0499                 enabled: _replaceField.text.length
0500                 text: i18nd("mauikittexteditor","Replace All")
0501                 onClicked: document.replaceAll(_findField.text, _replaceField.text)
0502             }
0503             ]
0504         }
0505     }
0506     
0507     header: Column
0508     {
0509         width: parent.width
0510         
0511         Repeater
0512         {
0513             model: document.alerts
0514             
0515             Maui.ToolBar
0516             {
0517                 id: _alertBar
0518                 property var alert : model.alert
0519                 readonly property int index_ : index
0520                 width: parent.width
0521                 
0522                 Maui.Theme.backgroundColor:
0523                 {
0524                     switch(alert.level)
0525                     {
0526                         case 0: return Maui.Theme.positiveBackgroundColor
0527                         case 1: return Maui.Theme.neutralBackgroundColor
0528                         case 2: return Maui.Theme.negativeBackgroundColor
0529                     }
0530                 }
0531                 
0532                 Maui.Theme.textColor:
0533                 {
0534                     switch(alert.level)
0535                     {
0536                         case 0: return Maui.Theme.positiveTextColor
0537                         case 1: return Maui.Theme.neutralTextColor
0538                         case 2: return Maui.Theme.negativeTextColor
0539                     }
0540                 }
0541                 
0542                 forceCenterMiddleContent: false
0543                     middleContent: Maui.ListItemTemplate
0544                     {
0545                         Maui.Theme.inherit: true
0546                         Layout.fillWidth: true
0547                         Layout.fillHeight: true
0548                         label1.text: alert.title
0549                         label2.text: alert.body
0550                     }
0551                     
0552                     rightContent: Repeater
0553                     {
0554                         model: alert.actionLabels
0555                         
0556                         Button
0557                         {
0558                             id: _alertAction
0559                             property int index_ : index
0560                             text: modelData
0561                             onClicked: alert.triggerAction(_alertAction.index_, _alertBar.index_)
0562                             
0563                             Maui.Theme.backgroundColor: Qt.lighter(_alertBar.Maui.Theme.backgroundColor, 1.2)
0564                             Maui.Theme.hoverColor: Qt.lighter(_alertBar.Maui.Theme.backgroundColor, 1)
0565                             Maui.Theme.textColor: Qt.darker(Maui.Theme.backgroundColor)
0566                         }
0567                     }
0568             }
0569         }    
0570     }
0571     
0572     contentItem: Item
0573     {   
0574         clip: false                   
0575         
0576         ScrollView
0577         {
0578             id: _scrollView
0579             anchors.fill: parent
0580             clip: false
0581             contentWidth: availableWidth
0582             
0583             Keys.enabled: true
0584             Keys.forwardTo: body
0585             Keys.onPressed:
0586             {
0587                 if((event.key === Qt.Key_F) && (event.modifiers & Qt.ControlModifier))
0588                 {
0589                     control.showFindBar = true
0590                     
0591                     if(control.body.selectedText.length)
0592                     {
0593                         _findField.text =  control.body.selectedText
0594                     }else
0595                     {
0596                         _findField.selectAll()
0597                     }
0598                     
0599                     _findField.forceActiveFocus()
0600                     event.accepted = true
0601                 }
0602                 
0603                 if((event.key === Qt.Key_R) && (event.modifiers & Qt.ControlModifier))
0604                 {
0605                     control.showFindBar = true
0606                     _replaceButton.checked = true
0607                     _findField.text = control.body.selectedText
0608                     _replaceField.forceActiveFocus()
0609                     event.accepted = true
0610                 }
0611             }
0612             
0613             Flickable
0614             {
0615                 id: _flickable
0616                 clip: false
0617                 interactive: true
0618                 boundsBehavior : Flickable.StopAtBounds
0619                 boundsMovement : Flickable.StopAtBounds
0620                 
0621                 TextArea.flickable: TextArea
0622                 {
0623                     id: body
0624                     Maui.Theme.inherit: true
0625                     text: document.text
0626                     
0627                     placeholderText: i18nd("mauikittexteditor","Body")
0628                     
0629                     textFormat: TextEdit.PlainText
0630                     
0631                     leftPadding: _linesCounter.width + padding
0632                     
0633                     Keys.onPressed:
0634                     {
0635                         if(event.key === Qt.Key_PageUp)
0636                         {
0637                             _flickable.flick(0,  60*Math.sqrt(_flickable.height))
0638                             event.accepted = true
0639                         }
0640                         
0641                         if(event.key === Qt.Key_PageDown)
0642                         {
0643                             _flickable.flick(0, -60*Math.sqrt(_flickable.height))
0644                             event.accepted = true
0645                         }                                    // TODO: Move cursor
0646                     }
0647                     
0648 <<<<<<< HEAD
0649 =======
0650                     onPressAndHold:
0651                     {
0652 //                         if(Maui.Handy.isMobile)
0653 //                         {
0654 //                             return
0655 //                         }
0656 //                         
0657                         documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(point.position.x, point.position.y));
0658                     }
0659                     
0660 >>>>>>> fa82aef (test fixes to mobile contetxualmenu)
0661                     onPressed:
0662                     {
0663                         if(Maui.Handy.isMobile)
0664                         {
0665                             return
0666                         }
0667                         
0668                         if(event.button === Qt.RightButton)
0669                         {
0670                             documentMenu.targetClick(spellcheckhighlighterLoader, body.positionAt(event.x, event.y))
0671                         }
0672                     }                       
0673                     
0674                     Loader
0675                     {
0676                         id: _linesCounter
0677                         asynchronous: true
0678                         active: control.showLineNumbers && !document.isRich
0679                         
0680                         anchors.left: parent.left
0681                         anchors.top: parent.top
0682                         
0683                         height: Math.max(_flickable.contentHeight, control.height)
0684                         width: active ? 48 : 0
0685                         sourceComponent: _linesCounterComponent
0686                     }
0687                     
0688                     Component
0689                     {
0690                         id: _linesCounterComponent
0691                         
0692                         Rectangle
0693                         {
0694                             color: Qt.darker(Maui.Theme.backgroundColor, 1)
0695                             
0696                             ListView
0697                             {
0698                                 id: _linesCounterList
0699                                 
0700                                 anchors.fill: parent
0701                                 anchors.topMargin: body.topPadding + body.textMargin
0702                                 
0703                                 model: document.lineCount
0704                                 
0705                                 Binding on currentIndex
0706                                 {
0707                                     value: document.currentLineIndex
0708                                     restoreMode: Binding.RestoreBindingOrValue
0709                                 }
0710                                 
0711                                 Timer
0712                                 {
0713                                     id: _lineIndexTimer
0714                                     interval: 250
0715                                     onTriggered: _linesCounterList.currentIndex= document.currentLineIndex
0716                                 }
0717                                 
0718                                 Connections
0719                                 {
0720                                     target: document
0721                                     function onLineCountChanged()
0722                                     {
0723                                         _lineIndexTimer.restart()
0724                                     }
0725                                 }
0726                                 
0727                                 orientation: ListView.Vertical
0728                                 interactive: false
0729                                 snapMode: ListView.NoSnap
0730                                 
0731                                 boundsBehavior: Flickable.StopAtBounds
0732                                 boundsMovement :Flickable.StopAtBounds
0733                                 
0734                                 preferredHighlightBegin: 0
0735                                 preferredHighlightEnd: width
0736                                 
0737                                 highlightRangeMode: ListView.StrictlyEnforceRange
0738                                 highlightMoveDuration: 0
0739                                 highlightFollowsCurrentItem: false
0740                                 highlightResizeDuration: 0
0741                                 highlightMoveVelocity: -1
0742                                 highlightResizeVelocity: -1
0743                                 
0744                                 maximumFlickVelocity: 0
0745                                 
0746                                 delegate: Row
0747                                 {
0748                                     id: _delegate
0749                                     readonly property int line : index
0750                                     property bool foldable : control.document.isFoldable(line)
0751                                     width:  ListView.view.width
0752                                     height: Math.max(fontSize, document.lineHeight(line))
0753                                     
0754                                     readonly property real fontSize : control.body.font.pointSize
0755                                     
0756                                     readonly property bool isCurrentItem : ListView.isCurrentItem
0757                                     
0758                                     Connections
0759                                     {
0760                                         target: control.body
0761                                         
0762                                         function onContentHeightChanged()
0763                                         {
0764                                             if(_delegate.isCurrentItem)
0765                                             {
0766                                                 console.log("Updating line height")
0767                                                 _delegate.height = control.document.lineHeight(_delegate.line)
0768                                                 _delegate.foldable = control.document.isFoldable(_delegate.line)
0769                                             }
0770                                         }
0771                                     }
0772                                     
0773                                     Label
0774                                     {
0775                                         width: 32
0776                                         height: parent.height
0777                                         opacity: isCurrentItem  ? 1 : 0.7
0778                                         color: isCurrentItem ? control.Maui.Theme.highlightColor : control.body.color
0779                                         font.pointSize: Math.min(Maui.Style.fontSizes.medium, body.font.pointSize)
0780                                         horizontalAlignment: Text.AlignHCenter
0781                                         verticalAlignment: Text.AlignVCenter
0782                                         //                                         renderType: Text.NativeRendering
0783                                         font.family: "Monospace"
0784                                         text: index+1
0785                                     }
0786                                     
0787                                     AbstractButton
0788                                     {
0789                                         visible: foldable
0790                                         anchors.verticalCenter: parent.verticalCenter
0791                                         height: 8
0792                                         width: 8
0793                                         //onClicked:
0794                                         //{
0795                                         //control.goToLine(_delegate.line)
0796                                         //control.document.toggleFold(_delegate.line)
0797                                         //}
0798                                         contentItem: Maui.Icon
0799                                         {
0800                                             source: "go-down"
0801                                         }
0802                                     }
0803                                 }
0804                             }
0805                             
0806                             //                            Maui.Separator
0807                             //                            {
0808                             //                                anchors.top: parent.top
0809                             //                                anchors.bottom: parent.bottom
0810                             //                                anchors.right: parent.right
0811                             //                                width: 0.5
0812                             //                                weight: Maui.Separator.Weight.Light
0813                             //                            }
0814                         }
0815                     }
0816                 }
0817             }
0818         }          
0819 
0820             
0821             Maui.FloatingButton
0822             {
0823                 visible: Maui.Handy.isTouch
0824                 icon.name: "edit-menu"
0825                 onClicked: documentMenu.targetClick(spellcheckhighlighterLoader, body.cursorPosition)
0826                 anchors.bottom: parent.bottom
0827                 anchors.right: parent.right
0828                 anchors.margins: Maui.Style.space.big
0829             }
0830     }
0831     
0832     function forceActiveFocus()
0833     {
0834         body.forceActiveFocus()
0835     }
0836     
0837     function goToLine(line)
0838     {
0839         if(line>0 && line <= body.lineCount)
0840         {
0841             body.cursorPosition = document.goToLine(line-1)
0842             body.forceActiveFocus()
0843         }
0844     }
0845 }