Warning, /maui/index-fm/src/main.qml is written in an unsupported language. File is not indexed.

0001 // Copyright 2018-2020 Camilo Higuita <milo.h@aol.com>
0002 // Copyright 2018-2020 Nitrux Latinoamericana S.C.
0003 //
0004 // SPDX-License-Identifier: GPL-3.0-or-later
0005 
0006 import QtQuick 2.15
0007 import QtQuick.Controls 2.15
0008 import QtQuick.Layouts 1.3
0009 
0010 import Qt.labs.settings 1.0
0011 
0012 import org.mauikit.controls 1.3 as Maui
0013 
0014 import org.mauikit.filebrowsing 1.3 as FB
0015 import org.maui.index 1.0 as Index
0016 
0017 import "widgets"
0018 import "widgets/views"
0019 import "widgets/previewer"
0020 
0021 Maui.ApplicationWindow
0022 {
0023     id: root
0024     title: currentTab ? currentTab.title : ""
0025 
0026     Maui.Style.accentColor : Maui.Handy.isAndroid ? "#6765C2": undefined
0027 
0028     readonly property alias dialog : dialogLoader.item
0029     readonly property alias selectionBar : _browserView.selectionBar
0030     readonly property alias pathBar: _pathBarLoader.item
0031 
0032     readonly property alias currentTab : _browserView.currentTab
0033     readonly property alias currentSplit : _browserView.currentSplit
0034     readonly property FB.FileBrowser currentBrowser : currentSplit.browser
0035 
0036     readonly property alias appSettings : settings
0037 
0038     property alias currentTabIndex : _browserView.currentTabIndex
0039     property bool selectionMode: false
0040 
0041     Maui.Notify
0042     {
0043         id: _notifyOperation
0044         componentName: "org.kde.index"
0045         eventId: "fileOperation"
0046     }
0047 
0048     Settings
0049     {
0050         id: settings
0051         category: "Browser"
0052 
0053         property bool showHiddenFiles: false
0054         property bool showThumbnails: true
0055         property bool previewFiles : Maui.Handy.isMobile
0056         property bool restoreSession:  false
0057         property bool overviewStart : false
0058 
0059         property int viewType : FB.FMList.LIST_VIEW
0060         property int listSize : 0 // s-m-l-x-xl
0061         property int gridSize : 3 // s-m-l-x-xl
0062 
0063         property var lastSession : [[({'path': FB.FM.homePath()})]]
0064         property int lastTabIndex : 0
0065 
0066         property bool quickSidebarSection : true
0067         property var sidebarSections : [
0068             FB.FMList.BOOKMARKS_PATH,
0069             FB.FMList.REMOTE_PATH,
0070             FB.FMList.REMOVABLE_PATH,
0071             FB.FMList.DRIVES_PATH]
0072 
0073 
0074         property alias sideBarWidth : _sideBarView.sideBar.preferredWidth
0075 
0076         property bool dirConf : true
0077         property bool syncTerminal: true
0078         property bool previewerWindow: Maui.Handy.isLinux && !Maui.Handy.isMobile
0079         property bool autoPlayPreviews: true
0080         property bool terminalFollowsColorScheme: true
0081         property string terminalColorScheme: "Maui-Dark"
0082     }
0083 
0084     Settings
0085     {
0086         id: sortSettings
0087         category: "Sorting"
0088         property bool foldersFirst: true
0089         property int sortBy: FB.FMList.MODIFIED
0090         property int sortOrder: Qt.AscendingOrder
0091         property bool group: false
0092     }
0093 
0094     onClosing: (close) =>
0095     {
0096         close.accepted = !settings.restoreSession
0097         var tabs = []
0098 
0099         for(var i = 0; i < _browserView.browserList.count; i ++)
0100         {
0101             const tab = _browserView.browserList.contentModel.get(i)
0102             var tabPaths = []
0103 
0104             for(var j = 0; j < tab.model.count; j++)
0105             {
0106                 const browser = tab.model.get(j)
0107                 const tabMap = {'path': browser.currentPath}
0108                 tabPaths.push(tabMap)
0109 
0110                 console.log("saving tabs", browser.currentPath)
0111 
0112             }
0113 
0114             tabs.push(tabPaths)
0115         }
0116 
0117         console.log("saving tabs", tabs.length)
0118 
0119         settings.lastSession = tabs
0120         settings.lastTabIndex = currentTabIndex
0121 
0122         close.accepted = true
0123     }
0124 
0125     Component
0126     {
0127         id: _tagsDialogComponent
0128 
0129         FB.TagsDialog
0130         {
0131             taglist.strict: false
0132             composerList.strict: false
0133 
0134             onTagsReady:
0135             {
0136                 composerList.updateToUrls(tags)
0137             }
0138         }
0139     }
0140 
0141     Component
0142     {
0143         id: _openWithDialogComponent
0144         FB.OpenWithDialog {}
0145     }
0146 
0147     Component
0148     {
0149         id: _configDialogComponent
0150         SettingsDialog {}
0151     }
0152 
0153     Component
0154     {
0155         id: _shortcutsDialogComponent
0156         ShortcutsDialog {}
0157     }
0158 
0159     Component
0160     {
0161         id: _extractDialogComponent
0162 
0163         Maui.InputDialog
0164         {
0165             id: _extractDialog
0166 
0167             title: i18n("Extract")
0168             message: i18n("Extract the content of the compressed file into a new or existing subdirectory or inside the current directory.")
0169 
0170             onFinished:
0171             {
0172                 _compressedFile.extract(currentBrowser.currentPath, text)
0173             }
0174         }
0175     }
0176 
0177     Component
0178     {
0179         id: _compressDialogComponent
0180 
0181         Maui.FileListingDialog
0182         {
0183             id: _compressDialog
0184 
0185             title: i18np("Compress %1 file", "Compress %1 files", urls.length)
0186             message: i18n("Compress selected files into a new file.")
0187 
0188             TextField
0189             {
0190                 id: _textEntry
0191                 Layout.fillWidth: true
0192                 placeholderText: i18n("Archive name...")
0193             }
0194 
0195             function clear()
0196             {
0197                 _textEntry.clear()
0198                 compressType.type = "zip"
0199                 urls = []
0200                 _showCompressedFiles.checked = false
0201             }
0202 
0203             Maui.ToolActions
0204             {
0205                 id: compressType
0206                 autoExclusive: true
0207                 expanded: true
0208                 property string type: "zip"
0209 
0210                 Action
0211                 {
0212                     text: ".ZIP"
0213                     checked: compressType.type === "zip"
0214                 }
0215 
0216                 Action
0217                 {
0218                     text: ".TAR"
0219                     checked: compressType.type === "tar"
0220                 }
0221 
0222                 Action
0223                 {
0224                     text: ".7ZIP"
0225                     checked: compressType.type === "7zip"
0226                 }
0227             }
0228 
0229             actions:
0230                 [
0231                 Action
0232                 {
0233                     text: i18n("Close")
0234                     onTriggered:  _compressDialog.close()
0235                 },
0236 
0237                 Action
0238                 {
0239                     text: i18n("Compress")
0240                     onTriggered:
0241                     {
0242                         var error = _compressedFile.compress(urls, currentBrowser.currentPath, _textEntry.text, compressType.currentIndex)
0243 
0244                         if(error)
0245                         {
0246                             root.notify("","Compress Error", "Some error occurs. Maybe current user does not have permission for writing in this directory.")
0247                         }
0248                         else
0249                         {
0250                             _compressDialog.close()
0251                         }
0252                     }
0253                 }
0254             ]
0255         }
0256     }
0257 
0258     Component
0259     {
0260         id: _previewerComponent
0261 
0262         PreviewerDialog
0263         {
0264             onClosed:
0265             {
0266                 dialogLoader.sourceComponent = null
0267             }
0268         }
0269     }
0270 
0271     Component
0272     {
0273         id: _previewerWindowComponent
0274         PreviewerWindow
0275         {
0276             onClosing: destroy()
0277         }
0278     }
0279 
0280     Component
0281     {
0282         id: _browserComponent
0283         BrowserLayout {}
0284     }
0285 
0286     Maui.NotifyAction
0287     {
0288         id: _extractionFinishedAction
0289         text: i18n("Open folder")
0290     }
0291 
0292     Index.CompressedFile
0293     {
0294         id: _compressedFile
0295 
0296         onExtractionFinished:
0297         {
0298             _notifyOperation.title = i18n("Extracted")
0299             _notifyOperation.message = i18n("File was extracted")
0300             _notifyOperation.defaultAction = _extractionFinishedAction
0301             _notifyOperation.iconName = "application-x-archive"
0302             _notifyOperation.send()
0303         }
0304     }
0305 
0306     Loader
0307     {
0308         id: dialogLoader
0309     }
0310 
0311     Maui.SideBarView
0312     {
0313         id: _sideBarView
0314         anchors.fill: parent
0315         sideBar.preferredWidth: 200
0316 
0317         sideBar.minimumWidth: 200
0318         sideBar.autoShow: true
0319         sideBar.autoHide: true
0320         sideBarContent: PlacesSideBar
0321         {
0322             id: placesSidebar
0323             anchors.fill: parent
0324         }
0325 
0326         Maui.Page
0327         {
0328             anchors.fill: parent
0329             headBar.visible: false
0330             footer: Loader
0331             {
0332                 id: _actionBarLoader
0333                 width: parent.width
0334                 asynchronous: true
0335                 visible: active && !_homeViewComponent.visible
0336                 sourceComponent: ActionBar {}
0337             }
0338 
0339             StackView
0340             {
0341                 id: _stackView
0342                 anchors.fill: parent
0343                 clip: false
0344 
0345                 initialItem: BrowserView
0346                 {
0347                     id: _browserView
0348 
0349                     flickable: currentBrowser.flickable
0350 
0351                     headBar.forceCenterMiddleContent: width > 1000
0352                     altHeader: Maui.Handy.isMobile
0353                     showCSDControls: true
0354 
0355                     headBar.farLeftContent: Loader
0356                     {
0357                         asynchronous: true
0358                         active: _sideBarView.sideBar.collapsed
0359                         visible: active
0360 
0361                         sourceComponent: ToolButton
0362                         {
0363                             icon.name: _sideBarView.sideBar.visible ? "sidebar-collapse" : "sidebar-expand"
0364                             onClicked: _sideBarView.sideBar.toggle()
0365                             checked: _sideBarView.sideBar.visible
0366                             ToolTip.delay: 1000
0367                             ToolTip.timeout: 5000
0368                             ToolTip.visible: hovered
0369                             ToolTip.text: i18n("Toggle sidebar")
0370                         }
0371                     }
0372 
0373                     headBar.middleContent: Loader
0374                     {
0375                         id: _pathBarLoader
0376 
0377                         asynchronous: true
0378 
0379                         Layout.fillWidth: true
0380                         Layout.minimumWidth: 100
0381 
0382                         sourceComponent: Item
0383                         {
0384                             implicitHeight: _pathBar.implicitHeight
0385                             readonly property alias pathBar: _pathBar
0386 
0387                             PathBar
0388                             {
0389                                 id: _pathBar
0390                                 anchors.centerIn: parent
0391                                 width: Math.min(parent.width, implicitWidth)
0392 
0393                                 url: currentBrowser.currentPath
0394                                 onPathChanged: (path) => currentBrowser.openFolder(path)
0395 
0396                                 onHomeClicked: currentBrowser.openFolder(FB.FM.homePath())
0397                                 onPlaceClicked: (path) =>
0398                                 {
0399                                     if(path === currentBrowser.currentPath)
0400                                     {
0401                                         openMenu()
0402                                     }
0403                                     else
0404                                     {
0405                                         currentBrowser.openFolder(path)
0406                                     }
0407                                 }
0408 
0409                                 onPlaceRightClicked: (path) =>
0410                                 {
0411                                     _pathBarmenu.path = path
0412                                     _pathBarmenu.show()
0413                                 }
0414 
0415                                 function openMenu()
0416                                 {
0417                                     _actionBarLoader.item.openMainMenu()
0418                                 }
0419 
0420                                 Maui.ContextualMenu
0421                                 {
0422                                     id: _pathBarmenu
0423                                     property url path
0424 
0425                                     MenuItem
0426                                     {
0427                                         text: i18n("Bookmark")
0428                                         icon.name: "bookmark-new"
0429                                         onTriggered: currentBrowser.bookmarkFolder([_pathBarmenu.path])
0430                                     }
0431 
0432                                     MenuItem
0433                                     {
0434                                         text: i18n("Open in New Tab")
0435                                         icon.name: "tab-new"
0436                                         onTriggered: openTab(_pathBarmenu.path)
0437                                     }
0438 
0439                                     MenuItem
0440                                     {
0441                                         visible: root.currentTab.count === 1
0442                                         text: i18n("Open in Split View")
0443                                         icon.name: "view-split-left-right"
0444                                         onTriggered: currentTab.split(_pathBarmenu.path, Qt.Horizontal)
0445                                     }
0446 
0447                                 }
0448                             }
0449                         }
0450                     }
0451                 }
0452 
0453                 Loader
0454                 {
0455                     id: _homeViewComponent
0456                     asynchronous: true
0457                     visible: StackView.status === StackView.Active
0458                     active: StackView.status === StackView.Active || item
0459 
0460                     sourceComponent: HomeView {}
0461 
0462                     BusyIndicator
0463                     {
0464                         running: parent.status === Loader.Loading
0465                         anchors.centerIn: parent
0466                     }
0467                 }
0468             }
0469         }
0470     }
0471 
0472     Component.onCompleted:
0473     {
0474         setAndroidStatusBarColor()
0475 
0476         if(settings.overviewStart)
0477         {
0478             root.openTab(FB.FM.homePath())
0479 
0480             _stackView.push(_homeViewComponent)
0481             return
0482         }
0483 
0484         if(initPaths.length)
0485         {
0486             for(var path of initPaths)
0487                 root.openTab(path)
0488             return;
0489         }
0490 
0491         const tabs = settings.lastSession
0492         if(settings.restoreSession && tabs.length)
0493         {
0494             console.log("restore", tabs.length)
0495             restoreSession(tabs)
0496             return
0497         }
0498 
0499         root.openTab(FB.FM.homePath())
0500     }
0501 
0502     function setAndroidStatusBarColor()
0503     {
0504         if(Maui.Handy.isAndroid)
0505         {
0506             const dark = Maui.Style.styleType === Maui.Style.Dark
0507             Maui.Android.statusbarColor( Maui.Theme.backgroundColor, !dark)
0508             Maui.Android.navBarColor( Maui.Theme.backgroundColor, !dark)
0509         }
0510     }
0511 
0512     function toogleSplitView()
0513     {
0514         if(currentTab.count === 2)
0515             currentTab.pop()
0516         else
0517             currentTab.split(currentBrowser.currentPath, Qt.Horizontal)
0518     }
0519 
0520     function openConfigDialog()
0521     {
0522         dialogLoader.sourceComponent = _configDialogComponent
0523         dialog.open()
0524     }
0525 
0526     function closeTab(index)
0527     {
0528         _browserView.browserList.closeTab(index)
0529     }
0530 
0531     function openDirs(paths)
0532     {
0533         for(var path of paths)
0534             root.openTab(path)
0535     }
0536 
0537     function openTab(path, path2 = "")
0538     {
0539         if(path)
0540         {
0541             if(_stackView.depth === 2)
0542                 _stackView.pop()
0543 
0544 
0545             _browserView.browserList.addTab(_browserComponent, {'path': path, 'path2': path2}, false)
0546         }
0547     }
0548 
0549     function tagFiles(urls)
0550     {
0551         if(urls.length <= 0)
0552         {
0553             return
0554         }
0555 
0556         dialogLoader.sourceComponent = _tagsDialogComponent
0557         dialog.composerList.urls =urls
0558         dialog.open()
0559     }
0560 
0561     /**
0562      * For this to work the implementation needs to have passed a selectionBar
0563      **/
0564     function openWith(urls)
0565     {
0566         if(urls.length <= 0)
0567         {
0568             return
0569         }
0570 
0571         if(Maui.Handy.isAndroid)
0572         {
0573             FB.FM.openUrl(urls[0])
0574             return
0575         }
0576 
0577         dialogLoader.sourceComponent = _openWithDialogComponent
0578         dialog.urls = urls
0579         dialog.open()
0580     }
0581 
0582     /**
0583       *
0584       **/
0585     function shareFiles(urls)
0586     {
0587         if(urls.length <= 0)
0588         {
0589             return
0590         }
0591 
0592         Maui.Platform.shareFiles(urls)
0593     }
0594 
0595     function openPreview(model, index)
0596     {
0597         if(appSettings.previewerWindow)
0598         {
0599             var previewer = _previewerWindowComponent.createObject(root)
0600             previewer.previewer.setData(model, index)
0601         }else
0602         {
0603             dialogLoader.sourceComponent = _previewerComponent
0604             dialog.previewer.setData(model, index)
0605             dialog.open()
0606         }
0607     }
0608 
0609     function restoreSession(tabs)
0610     {
0611         for(var i = 0; i < tabs.length; i++ )
0612         {
0613             const tab = tabs[i]
0614 
0615             if(tab.length === 2)
0616             {
0617                 root.openTab(tab[0].path, tab[1].path)
0618             }else
0619             {
0620                 root.openTab(tab[0].path)
0621             }
0622         }
0623 
0624         currentTabIndex = settings.lastTabIndex
0625     }
0626 
0627     function toggleSection(section)
0628     {
0629         placesSidebar.list.toggleSection(section)
0630         appSettings.sidebarSections = placesSidebar.list.groups
0631     }
0632 
0633     function isUrlOpen(url : string) : bool
0634     {
0635         return _browserView.isUrlOpen(url);
0636     }
0637     }