Warning, /maui/nota/src/views/editor/EditorView.qml is written in an unsupported language. File is not indexed.
0001 import QtQuick 2.14 0002 import QtQuick.Controls 2.13 0003 import QtQuick.Layouts 1.3 0004 0005 import org.mauikit.controls 1.3 as Maui 0006 import org.mauikit.filebrowsing 1.3 as FB 0007 import org.mauikit.texteditor 1.0 as TE 0008 0009 import org.maui.nota 1.0 as Nota 0010 0011 Pane 0012 { 0013 id: control 0014 0015 readonly property alias count: _tabView.count 0016 0017 readonly property alias currentTab : _tabView.currentItem 0018 readonly property bool currentFileExistsLocally : FB.FM.fileExists(control.currentEditor.fileUrl) 0019 readonly property TE.TextEditor currentEditor: currentTab ? currentTab.currentItem.editor : null 0020 0021 readonly property alias listView: _tabView 0022 readonly property alias plugin: _pluginLayout 0023 readonly property alias model : _tabView.contentModel 0024 readonly property alias tabView : _tabView 0025 0026 padding: 0 0027 0028 Action 0029 { 0030 id: _openFileAction 0031 icon.name: "folder-open" 0032 text: i18n("Open Files") 0033 onTriggered: 0034 { 0035 openFileDialog() 0036 } 0037 } 0038 0039 Action 0040 { 0041 id: _openRecentFileAction 0042 icon.name: "folder-recent" 0043 text: i18n("Open Recent Files") 0044 onTriggered: 0045 { 0046 _stackView.push(historyViewComponent) 0047 } 0048 } 0049 0050 Action 0051 { 0052 id: _newFileAction 0053 icon.name: "list-add" 0054 text: i18n("New") 0055 onTriggered: 0056 { 0057 editorView.openTab("") 0058 } 0059 } 0060 0061 contentItem: ColumnLayout 0062 { 0063 id: _pluginLayout 0064 spacing: 0 0065 0066 Maui.TabView 0067 { 0068 id: _tabView 0069 Layout.fillWidth: true 0070 Layout.fillHeight: true 0071 0072 altTabBar: !root.isWide 0073 0074 holder.emoji: "qrc:/img/document-edit.svg" 0075 0076 holder.title: i18n("Create a New Document") 0077 holder.body: i18n("You can create or open a new document.") 0078 holder.actions: [_newFileAction, _openFileAction, _openRecentFileAction] 0079 0080 Connections 0081 { 0082 target: _tabView.holder 0083 function onContentDropped(drop) 0084 { 0085 if(drop.urls) 0086 { 0087 for(var url of drop.urls) 0088 control.openTab(url) 0089 } 0090 } 0091 } 0092 tabBar.visible: true 0093 tabBar.showNewTabButton: false 0094 tabBar.leftContent: Loader 0095 { 0096 active: settings.enableSidebar 0097 visible: active 0098 asynchronous: true 0099 0100 sourceComponent: ToolButton 0101 { 0102 icon.name: _sideBarView.sideBar.visible ? "sidebar-collapse" : "sidebar-expand" 0103 onClicked: _sideBarView.sideBar.toggle() 0104 0105 text: i18n("Places") 0106 display: isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly 0107 0108 checked: _sideBarView.sideBar.visible 0109 0110 ToolTip.delay: 1000 0111 ToolTip.timeout: 5000 0112 ToolTip.visible: hovered 0113 ToolTip.text: i18n("Toogle SideBar") 0114 } 0115 } 0116 0117 tabBar.rightContent: [ 0118 0119 ToolButton 0120 { 0121 text: _tabView.count 0122 visible: _tabView.count > 1 0123 font.bold: true 0124 font.pointSize: Maui.Style.fontSizes.small 0125 onClicked: _tabView.openOverview() 0126 background: Rectangle 0127 { 0128 color: Maui.Theme.alternateBackgroundColor 0129 radius: Maui.Style.radiusV 0130 } 0131 }, 0132 0133 Loader 0134 { 0135 asynchronous: true 0136 sourceComponent: Maui.ToolButtonMenu 0137 { 0138 icon.name: "list-add" 0139 0140 MenuItem 0141 { 0142 action: _newFileAction 0143 } 0144 0145 MenuItem 0146 { 0147 action: _openFileAction 0148 } 0149 0150 MenuItem 0151 { 0152 action: _openRecentFileAction 0153 } 0154 0155 MenuSeparator {} 0156 0157 Maui.MenuItemActionRow 0158 { 0159 Action 0160 { 0161 icon.name: checked ? "view-readermode-active" : "view-readermode" 0162 text: i18n("Focus") 0163 checked: root.focusMode 0164 checkable: true 0165 onTriggered: root.focusMode = !root.focusMode 0166 } 0167 0168 Action 0169 { 0170 text: i18n("Terminal") 0171 icon.name: "dialog-scripts" 0172 enabled: Maui.Handy.isLinux 0173 onTriggered: currentTab.toggleTerminal() 0174 checkable: true 0175 checked: currentTab ? currentTab.terminalVisible : false 0176 } 0177 0178 Action 0179 { 0180 enabled: settings.supportSplit 0181 text: i18n("Split View") 0182 icon.name: root.currentTab.orientation === Qt.Horizontal ? "view-split-left-right" : "view-split-top-bottom" 0183 checked: root.currentTab && root.currentTab.count === 2 0184 checkable: true 0185 onTriggered: 0186 { 0187 if(root.currentTab.count === 2) 0188 { 0189 root.currentTab.pop() 0190 return 0191 }//close the inactive split 0192 0193 root.currentTab.split("") 0194 } 0195 } 0196 } 0197 0198 MenuSeparator {} 0199 0200 MenuItem 0201 { 0202 text: i18n("Shortcuts") 0203 icon.name: "configure-shortcuts" 0204 onTriggered: 0205 { 0206 _dialogLoader.sourceComponent = _shortcutsDialogComponent 0207 dialog.open() 0208 } 0209 } 0210 0211 MenuItem 0212 { 0213 text: i18n("Settings") 0214 icon.name: "settings-configure" 0215 onTriggered: 0216 { 0217 _dialogLoader.sourceComponent = _settingsDialogComponent 0218 dialog.open() 0219 } 0220 } 0221 0222 MenuItem 0223 { 0224 text: i18n("Plugins") 0225 icon.name: "system-run" 0226 onTriggered: 0227 { 0228 _dialogLoader.sourceComponent = _plugingsDialogComponent 0229 dialog.open() 0230 } 0231 } 0232 0233 MenuItem 0234 { 0235 text: i18n("About") 0236 icon.name: "documentinfo" 0237 onTriggered: root.about() 0238 } 0239 } 0240 }, 0241 0242 Maui.WindowControls {} 0243 ] 0244 0245 tabViewButton: Maui.TabViewButton 0246 { 0247 id: _tabButton 0248 tabView: _tabView 0249 onClicked: 0250 { 0251 if(_tabButton.mindex === _tabView.currentIndex) 0252 { 0253 _docMenuLoader.item.show((width*0.5)-(_docMenuLoader.item.width*0.5), height + Maui.Style.space.medium) 0254 return 0255 } 0256 0257 _tabView.setCurrentIndex(_tabButton.mindex) 0258 _tabView.currentItem.forceActiveFocus() 0259 } 0260 0261 rightContent: Maui.Icon 0262 { 0263 visible: _tabButton.checked 0264 source: "overflow-menu" 0265 height: Maui.Style.iconSizes.small 0266 width: height 0267 } 0268 0269 onCloseClicked: 0270 { 0271 _tabView.closeTabClicked(_tabButton.mindex) 0272 } 0273 0274 Component 0275 { 0276 id: _infoDialogComponent 0277 0278 Maui.PopupPage 0279 { 0280 id: _infoDialog 0281 property var info: FB.FM.getFileInfo(currentEditor.fileUrl) 0282 0283 onClosed: destroy() 0284 Maui.SectionItem 0285 { 0286 label1.text: i18n("Name") 0287 label2.text: _infoDialog.info.name 0288 } 0289 0290 Maui.SectionItem 0291 { 0292 label1.text: i18n("Date") 0293 label2.text: _infoDialog.info.date 0294 } 0295 0296 Maui.SectionItem 0297 { 0298 label1.text: i18n("Modified") 0299 label2.text: _infoDialog.info.modified 0300 } 0301 0302 Maui.SectionItem 0303 { 0304 label1.text: i18n("Size") 0305 label2.text: Maui.Handy.formatSize(_infoDialog.info.size) 0306 } 0307 0308 Maui.SectionItem 0309 { 0310 label1.text: i18n("Type") 0311 label2.text:_infoDialog.info.mime 0312 } 0313 } 0314 } 0315 0316 Component 0317 { 0318 id: _goToLineDialogComponent 0319 0320 Maui.InputDialog 0321 { 0322 title: i18n("Go to Line") 0323 textEntry.text: currentEditor.document.currentLineIndex+1 0324 textEntry.placeholderText: i18n("Line number") 0325 onFinished: currentEditor.goToLine(text) 0326 } 0327 } 0328 0329 Component 0330 { 0331 id: _removeDialogComponent 0332 0333 Maui.InfoDialog 0334 { 0335 0336 title: i18n("Delete File?") 0337 message: i18n("Are sure you want to delete \n%1", currentEditor.fileUrl) 0338 0339 standardButtons: Dialog.Yes | Dialog.Cancel 0340 0341 template.iconSource: "dialog-question" 0342 template.iconVisible: true 0343 0344 onRejected: close() 0345 onAccepted: 0346 { 0347 FB.FM.deleteFile(currentEditor.fileUrl) 0348 } 0349 } 0350 } 0351 0352 Loader 0353 { 0354 id: _docMenuLoader 0355 asynchronous: true 0356 sourceComponent: Maui.ContextualMenu 0357 { 0358 Maui.MenuItemActionRow 0359 { 0360 Action 0361 { 0362 icon.name: "edit-undo" 0363 text: i18n("Undo") 0364 enabled: currentEditor.body.canUndo 0365 onTriggered: currentEditor.body.undo() 0366 } 0367 0368 Action 0369 { 0370 icon.name: "edit-redo" 0371 text: i18n("Redo") 0372 enabled: currentEditor.body.canRedo 0373 onTriggered: currentEditor.body.redo() 0374 } 0375 0376 0377 Action 0378 { 0379 text: i18n("Save") 0380 icon.name: "document-save" 0381 enabled: currentEditor ? currentEditor.document.modified : false 0382 onTriggered: saveFile(currentEditor.fileUrl, currentEditor) 0383 } 0384 0385 Action 0386 { 0387 icon.name: "document-save-as" 0388 text: i18n("Save as") 0389 onTriggered: saveFile("", currentEditor) 0390 } 0391 } 0392 0393 MenuSeparator {} 0394 0395 MenuItem 0396 { 0397 icon.name: "edit-find" 0398 text: i18n("Find and Replace") 0399 checkable: true 0400 0401 onTriggered: 0402 { 0403 currentEditor.showFindBar = !currentEditor.showFindBar 0404 } 0405 checked: currentEditor.showFindBar 0406 } 0407 0408 MenuItem 0409 { 0410 icon.name: "document-edit" 0411 text: i18n("Line/Word Counter") 0412 checkable: true 0413 0414 onTriggered: 0415 { 0416 settings.showWordCount = !settings.showWordCount 0417 } 0418 0419 checked: settings.showWordCount 0420 } 0421 0422 MenuSeparator {} 0423 0424 Maui.MenuItemActionRow 0425 { 0426 Action 0427 { 0428 property bool isFav: FB.Tagging.isFav(currentEditor.fileUrl) 0429 text: i18n(isFav ? "UnFav it": "Fav it") 0430 checked: isFav 0431 checkable: true 0432 icon.name: "love" 0433 enabled: currentFileExistsLocally 0434 onTriggered: 0435 { 0436 FB.Tagging.toggleFav(currentEditor.fileUrl) 0437 isFav = FB.Tagging.isFav(currentEditor.fileUrl) 0438 } 0439 } 0440 0441 Action 0442 { 0443 enabled: currentFileExistsLocally 0444 text: i18n("Info") 0445 icon.name: "documentinfo" 0446 onTriggered: 0447 { 0448 0449 var dialog = _infoDialogComponent.createObject(control) 0450 dialog.open() 0451 0452 } 0453 } 0454 0455 Action 0456 { 0457 text: i18n("Share") 0458 enabled: currentFileExistsLocally 0459 icon.name: "document-share" 0460 onTriggered: Maui.Platform.shareFiles([currentEditor.fileUrl]) 0461 0462 } 0463 } 0464 0465 MenuSeparator {} 0466 0467 MenuItem 0468 { 0469 icon.name: "go-jump" 0470 text: i18n("Go to Line") 0471 0472 onTriggered: 0473 { 0474 _dialogLoader.sourceComponent = _goToLineDialogComponent 0475 dialog.open() 0476 } 0477 } 0478 0479 MenuItem 0480 { 0481 enabled: currentFileExistsLocally 0482 text: i18n("Show in Folder") 0483 icon.name: "folder-open" 0484 onTriggered: 0485 { 0486 FB.FM.openLocation([currentEditor.fileUrl]) 0487 } 0488 } 0489 0490 MenuItem 0491 { 0492 text: i18n("Delete File") 0493 icon.name: "edit-delete" 0494 enabled: currentFileExistsLocally 0495 Maui.Theme.textColor: Maui.Theme.negativeTextColor 0496 0497 onTriggered: 0498 { 0499 _dialogLoader.sourceComponent = _removeDialogComponent 0500 dialog.open() 0501 } 0502 } 0503 } 0504 } 0505 } 0506 0507 onNewTabClicked: control.openTab("") 0508 onCloseTabClicked: (index) => 0509 { 0510 if( tabHasUnsavedFiles(index)) 0511 { 0512 _dialogLoader.sourceComponent = _unsavedDialogComponent 0513 dialog.callback = function () { closeTab(index) } 0514 0515 if(tabHasUnsavedFiles(index)) 0516 { 0517 dialog.open() 0518 return 0519 } 0520 } 0521 else 0522 { 0523 closeTab(index) 0524 } 0525 } 0526 } 0527 } 0528 0529 Component 0530 { 0531 id: _editorLayoutComponent 0532 EditorLayout {} 0533 } 0534 0535 function unsavedTabSplits(index) //which split indexes are unsaved 0536 { 0537 var indexes = [] 0538 const tab = control.model.get(index) 0539 for(var i = 0; i < tab.count; i++) 0540 { 0541 if(tab.model.get(i).editor.document.modified) 0542 { 0543 indexes.push(i) 0544 } 0545 } 0546 return indexes 0547 } 0548 0549 function tabHasUnsavedFiles(index) //if a tab has at least one unsaved file in a split 0550 { 0551 return unsavedTabSplits(index).length 0552 } 0553 0554 function fileIndex(path) //find the [tab, split] index for a path 0555 { 0556 if(path.length === 0) 0557 { 0558 return [-1, -1] 0559 } 0560 0561 for(var i = 0; i < control.count; i++) 0562 { 0563 const tab = control.model.get(i) 0564 for(var j = 0; j < tab.count; j++) 0565 { 0566 const doc = tab.model.get(j) 0567 if(doc.fileUrl.toString() === path) 0568 { 0569 return [i, j] 0570 } 0571 } 0572 } 0573 return [-1,-1] 0574 } 0575 0576 function openTab(path) 0577 { 0578 if(_stackView.depth === 2) 0579 { 0580 _stackView.pop() 0581 } 0582 0583 const index = fileIndex(path) 0584 0585 if(index[0] >= 0) 0586 { 0587 _tabView.currentIndex = index[0] 0588 currentTab.currentIndex = index[1] 0589 return 0590 } 0591 0592 _tabView.addTab(_editorLayoutComponent, {"path": path}) 0593 historyList.append(path) 0594 } 0595 0596 function closeTab(index) //no questions asked 0597 { 0598 _tabView.closeTab(index) 0599 } 0600 0601 function saveFile(path, item) 0602 { 0603 if(!item) 0604 return 0605 0606 if (path && FB.FM.fileExists(path)) 0607 { 0608 item.document.saveAs(path) 0609 } else 0610 { 0611 _dialogLoader.sourceComponent = _fileDialogComponent 0612 dialog.mode = dialog.modes.SAVE; 0613 // fileDialog.settings.singleSelection = true 0614 dialog.callback = function (paths) 0615 { 0616 item.document.saveAs(paths[0]) 0617 historyList.append(paths[0]) 0618 }; 0619 0620 dialog.open() 0621 } 0622 } 0623 0624 function isUrlOpen(url : string) : bool 0625 { 0626 return fileIndex(url)[0] >= 0; 0627 } 0628 }