diff --git a/mauikit.qrc b/mauikit.qrc index d98a972..478780f 100644 --- a/mauikit.qrc +++ b/mauikit.qrc @@ -1,60 +1,62 @@ src/controls/ToolBar.qml src/controls/AbstractSideBar.qml src/controls/SideBar.qml src/controls/ApplicationWindow.qml src/controls/Style.qml src/controls/ShareDialog.qml src/controls/PieButton.qml src/controls/Page.qml src/controls/private/PathBarDelegate.qml src/controls/private/EdgeShadow.qml src/controls/private/BrowserMenu.qml src/controls/private/BrowserView.qml src/controls/private/BrowserSettings.qml src/controls/private/BrowserHolder.qml src/controls/private/FileMenu.qml src/controls/private/AudioPreview.qml src/controls/private/ImagePreview.qml src/controls/private/TextPreview.qml src/controls/private/VideoPreview.qml src/controls/private/AccountsHelper.qml src/controls/Holder.qml src/controls/ListDelegate.qml src/controls/ItemDelegate.qml src/controls/SwipeItemDelegate.qml src/controls/SwipeBrowserDelegate.qml src/controls/GridBrowserDelegate.qml src/controls/ListBrowserDelegate.qml src/controls/GlobalDrawer.qml src/controls/SelectionBar.qml src/controls/LabelDelegate.qml src/controls/NewDialog.qml src/controls/TagsBar.qml src/controls/TagsDialog.qml src/controls/private/TagList.qml src/controls/private/TagDelegate.qml src/controls/ColorsBar.qml src/controls/FileBrowser.qml src/controls/FilePreviewer.qml src/controls/FileDialog.qml src/controls/ListBrowser.qml src/controls/PathBar.qml src/controls/GridBrowser.qml src/controls/Dialog.qml src/controls/AboutDialog.qml src/controls/Popup.qml src/controls/TextField.qml src/controls/Badge.qml src/controls/GridView.qml src/controls/SyncDialog.qml src/controls/Terminal.qml src/controls/Editor.qml src/controls/PlacesSidebar.qml src/controls/PlacesListBrowser.qml src/controls/Store.qml - src/controls/ImageViewer.qml - src/controls/private/StoreDelegate.qml + src/controls/ImageViewer.qml + src/controls/TabBar.qml + src/controls/TabButton.qml + src/controls/private/StoreDelegate.qml diff --git a/src/controls/FileBrowser.qml b/src/controls/FileBrowser.qml index 006e742..027be13 100644 --- a/src/controls/FileBrowser.qml +++ b/src/controls/FileBrowser.qml @@ -1,1099 +1,1021 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import QtQml.Models 2.3 import QtQml 2.1 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import "private" Maui.Page { id: control property url currentPath onCurrentPathChanged: control.browserView.path = control.currentPath property int viewType : Maui.FMList.LIST_VIEW onViewTypeChanged: browserView.viewType = control.viewType property int currentPathType : control.currentFMList.pathType property int thumbnailsSize : Maui.Style.iconSizes.large * 1.7 property bool showThumbnails: true property var clipboardItems : [] property var indexHistory : [] property bool isCopy : false property bool isCut : false property bool selectionMode : false property bool singleSelection: false property bool group : false property bool showEmblems: true //group properties from the browser since the browser views are loaded async and //their properties can not be accesed inmediately property BrowserSettings settings : BrowserSettings {} property alias selectionBar : selectionBarLoader.item property alias browserView : _browserList.currentItem property Maui.FMList currentFMList : browserView.currentFMList property alias previewer : previewer property alias menu : browserMenu.contentData property alias itemMenu: itemMenu property alias dialog : dialogLoader.item signal itemClicked(int index) signal itemDoubleClicked(int index) signal itemRightClicked(int index) signal itemLeftEmblemClicked(int index) signal itemRightEmblemClicked(int index) signal rightClicked() signal newBookmark(var paths) signal newTag(var tag) Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.inherit: false onGoBackTriggered: control.goBack() onGoForwardTriggered: control.goNext() focus: true footBar.visible: false footBar.leftContent: Label { Layout.fillWidth: true text: control.currentFMList.count + " " + qsTr("items") } footBar.rightContent: [ ToolButton { icon.name: "zoom-in" onClicked: zoomIn() }, ToolButton { icon.name: "zoom-out" onClicked: zoomOut() } ] headBar.position: Kirigami.Settings.isMobile ? ToolBar.Footer : ToolBar.Header property list t_actions: [ Action { id: _previewAction icon.name: "image-preview" text: qsTr("Previews") checkable: true checked: control.showThumbnails onTriggered: control.showThumbnails = !control.showThumbnails }, Action { id: _hiddenAction icon.name: "visibility" text: qsTr("Hidden files") checkable: true checked: control.currentFMList.hidden onTriggered: control.currentFMList.hidden = !control.currentFMList.hidden }, Action { id: _bookmarkAction icon.name: "bookmark-new" text: qsTr("Bookmark") onTriggered: control.bookmarkFolder([currentPath]) }, Action { id: _newFolderAction icon.name: "folder-add" text: qsTr("New folder") onTriggered: { dialogLoader.sourceComponent= newFolderDialogComponent dialog.open() } }, Action { id: _newDocumentAction icon.name: "document-new" text: qsTr("New file") onTriggered: { dialogLoader.sourceComponent= newFileDialogComponent dialog.open() } }, Action { id: _pasteAction text: qsTr("Paste ")+"["+control.clipboardItems.length+"]" icon.name: "edit-paste" enabled: control.clipboardItems.length > 0 onTriggered: paste() }, Action { id: _selectAllAction text: qsTr("Select all") icon.name: "edit-select-all" onTriggered: selectAll() }, Action { text: qsTr("Status bar") icon.name: "settings-configure" checkable: true checked: control.footBar.visible onTriggered: control.footBar.visible = !control.footBar.visible } ] Loader { id: dialogLoader } Component { id: removeDialogComponent Maui.Dialog { property var items: [] title: qsTr(String("Removing %1 files").arg(items.length.toString())) message: isAndroid ? qsTr("This action will completely remove your files from your system. This action can not be undone.") : qsTr("You can move the file to the Trash or Delete it completely from your system. Which one you preffer?") rejectButton.text: qsTr("Delete") acceptButton.text: qsTr("Trash") acceptButton.visible: !Kirigami.Settings.isMobile page.padding: Maui.Style.space.huge onRejected: { if(control.selectionBar && control.selectionBar.visible) { control.selectionBar.clear() control.selectionBar.animate(Maui.Style.dangerColor) } control.remove(items) close() } onAccepted: { if(control.selectionBar && control.selectionBar.visible) { control.selectionBar.clear() control.selectionBar.animate(Maui.Style.dangerColor) } control.trash(items) close() } } } Component { id: newFolderDialogComponent Maui.NewDialog { title: qsTr("New folder") message: qsTr("Create a new folder with a custom name") acceptButton.text: qsTr("Create") onFinished: control.currentFMList.createDir(text) rejectButton.visible: false textEntry.placeholderText: qsTr("Folder name...") } } Component { id: newFileDialogComponent Maui.NewDialog { title: qsTr("New file") message: qsTr("Create a new file with a custom name and extension") acceptButton.text: qsTr("Create") onFinished: Maui.FM.createFile(control.currentPath, text) rejectButton.visible: false textEntry.placeholderText: qsTr("File name...") } } Component { id: renameDialogComponent Maui.NewDialog { title: qsTr("Rename file") message: qsTr("Rename a file or folder to a new custom name") textEntry.text: itemMenu.item.label textEntry.placeholderText: qsTr("New name...") onFinished: Maui.FM.rename(itemMenu.item.path, textEntry.text) onRejected: close() acceptText: qsTr("Rename") rejectText: qsTr("Cancel") } } Component { id: shareDialogComponent Maui.ShareDialog {} } Component { id: tagsDialogComponent Maui.TagsDialog { onTagsReady: { composerList.updateToUrls(tags) if(previewer.visible) previewer.tagBar.list.refresh() control.newTag(tags) } } } BrowserMenu { id: browserMenu } Maui.FilePreviewer { id: previewer onShareButtonClicked: control.shareFiles([url]) } FileMenu { id: itemMenu width: Maui.Style.unit *200 onBookmarkClicked: control.bookmarkFolder([item.path]) onCopyClicked: { if(item) control.copy([item]) } onCutClicked: { if(item) control.cut([item]) } onTagsClicked: { if(item) { dialogLoader.sourceComponent = tagsDialogComponent dialog.composerList.urls = [item.path] dialog.open() } } onRenameClicked: { dialogLoader.sourceComponent = renameDialogComponent dialog.open() } onRemoveClicked: { dialogLoader.sourceComponent= removeDialogComponent dialog.items = [item] dialog.open() } onShareClicked: control.shareFiles([item.path]) } Connections { target: browserView.currentView onItemClicked: { console.log("item clicked connections:", index) browserView.currentView.currentIndex = index indexHistory.push(index) control.itemClicked(index) } onItemDoubleClicked: { browserView.currentView.currentIndex = index indexHistory.push(index) control.itemDoubleClicked(index) } onItemRightClicked: { if(currentFMList.pathType !== Maui.FMList.TRASH_PATH && currentFMList.pathType !== Maui.FMList.REMOTE_PATH ) itemMenu.show(index) control.itemRightClicked(index) } onLeftEmblemClicked: { const item = control.currentFMList.get(index) if(control.selectionBar && control.selectionBar.contains(item.path)) { control.selectionBar.removeAtPath(item.path) }else { control.addToSelection(item) } control.itemLeftEmblemClicked(index) } onRightEmblemClicked: { isAndroid ? Maui.Android.shareDialog([control.currentFMList.get(index).path]) : shareDialog.show([control.currentFMList.get(index).path]) control.itemRightEmblemClicked(index) } onAreaClicked: { if(!Kirigami.Settings.isMobile && mouse.button === Qt.RightButton) browserMenu.show() else return control.rightClicked() } onAreaRightClicked: browserMenu.show() } headBar.rightContent:[ Kirigami.ActionToolBar { position: ToolBar.Header Layout.fillWidth: true hiddenActions: t_actions display: ToolButton.IconOnly actions: [ Action { icon.name: "view-list-icons" onTriggered: control.viewType = Maui.FMList.ICON_VIEW checkable: false checked: browserView.viewType === Maui.FMList.ICON_VIEW icon.width: Maui.Style.iconSizes.medium text: qsTr("Grid view") // autoExclusive: true }, Action { icon.name: "view-list-details" onTriggered: control.viewType = Maui.FMList.LIST_VIEW icon.width: Maui.Style.iconSizes.medium checked: browserView.viewType === Maui.FMList.LIST_VIEW text: qsTr("List view") // autoExclusive: true }, Action { icon.name: "view-file-columns" onTriggered: control.viewType = Maui.FMList.MILLERS_VIEW icon.width: Maui.Style.iconSizes.medium checked: browserView.viewType === Maui.FMList.MILLERS_VIEW text: qsTr("Column view") // autoExclusive: true }, Kirigami.Action { icon.name: "view-sort" text: qsTr("Sort") Kirigami.Action { text: qsTr("Folders first") checked: control.currentFMList.foldersFirst checkable: true onTriggered: control.currentFMList.foldersFirst = !control.currentFMList.foldersFirst } Kirigami.Action { text: qsTr("Type") checked: control.currentFMList.sortBy === Maui.FMList.MIME checkable: true onTriggered: control.currentFMList.sortBy = Maui.FMList.MIME } Kirigami.Action { text: qsTr("Date") checked: control.currentFMList.sortBy === Maui.FMList.DATE checkable: true onTriggered: control.currentFMList.sortBy = Maui.FMList.DATE } Kirigami.Action { text: qsTr("Modified") checkable: true checked: control.currentFMList.sortBy === Maui.FMList.MODIFIED onTriggered: control.currentFMList.sortBy = Maui.FMList.MODIFIED } Kirigami.Action { text: qsTr("Size") checkable: true checked: control.currentFMList.sortBy === Maui.FMList.SIZE onTriggered: control.currentFMList.sortBy = Maui.FMList.SIZE } Kirigami.Action { text: qsTr("Name") checkable: true checked: control.currentFMList.sortBy === Maui.FMList.LABEL onTriggered: control.currentFMList.sortBy = Maui.FMList.LABEL } Kirigami.Action { id: groupAction text: qsTr("Group") checkable: true checked: control.group onTriggered: { control.group = !control.group if(control.group) groupBy() else browserView.currentView.section.property = "" } } }, Kirigami.Action { text: qsTr("Select mode") icon.name: "item-select" checkable: true checked: control.selectionMode onTriggered: control.selectionMode = !control.selectionMode } ] } ] headBar.leftContent: [ ToolButton { icon.name: "go-previous" onClicked: control.goBack() }, ToolButton { icon.name: "go-next" onClicked: control.goNext() } ] Component { id: selectionBarComponent Maui.SelectionBar { anchors.fill: parent onIconClicked: _selectionBarmenu.popup() onExitClicked: { clean() control.selectionMode = false } onRightClicked: _selectionBarmenu.popup() onItemClicked: { previewer.show(itemAt(index).path) } onItemPressAndHold: { removeAtIndex(index) } Menu { id: _selectionBarmenu MenuItem { text: qsTr("Copy") onTriggered: if(control.selectionBar) { control.selectionBar.animate("#6fff80") control.copy(selectedItems) _selectionBarmenu.close() } } MenuItem { text: qsTr("Cut") onTriggered: if(control.selectionBar) { control.selectionBar.animate("#fff44f") control.cut(selectedItems) _selectionBarmenu.close() } } MenuItem { text: qsTr("Share") onTriggered: { control.shareFiles(selectedPaths) _selectionBarmenu.close() } } MenuItem { text: qsTr("Tags") onTriggered: if(control.selectionBar) { dialogLoader.sourceComponent = tagsDialogComponent dialog.composerList.urls = selectedPaths dialog.open() _selectionBarmenu.close() } } MenuSeparator{} MenuItem { text: qsTr("Remove") Kirigami.Theme.textColor: Kirigami.Theme.negativeTextColor onTriggered: { dialogLoader.sourceComponent= removeDialogComponent dialog.items = selectedItems dialog.open() _selectionBarmenu.close() } } } } } ObjectModel { id: tabsObjectModel } ColumnLayout { anchors.fill: parent spacing: 0 - TabBar + Maui.TabBar { id: tabsBar visible: _browserList.count > 1 Layout.fillWidth: true - Layout.preferredHeight: visible ? Maui.Style.rowHeight : 0 - Kirigami.Theme.colorSet: Kirigami.Theme.View - Kirigami.Theme.inherit: false - + Layout.preferredHeight: tabsBar.implicitHeight + position: TabBar.Header currentIndex : _browserList.currentIndex - clip: true - - ListModel { id: tabsListModel } - background: null + ListModel { id: tabsListModel } Repeater { id: _repeater model: tabsListModel - TabButton + Maui.TabButton { id: _tabButton - readonly property int minTabWidth: 150 * Maui.Style.unit + implicitHeight: tabsBar.implicitHeight implicitWidth: control.width / _repeater.count - implicitHeight: Maui.Style.rowHeight checked: index === _browserList.currentIndex + text: tabsObjectModel.get(index).currentFMList.pathName + onClicked: { - _browserList.currentIndex = index - + _browserList.currentIndex = index control.currentPath = tabsObjectModel.get(index).path } - background: Rectangle + onCloseClicked: { - color: "transparent" - - - Kirigami.Separator - { - z: tabsBar.z + 1 - width: Maui.Style.unit - anchors - { - bottom: parent.bottom - top: parent.top - right: parent.right - } - } - - Kirigami.Separator - { - color: Kirigami.Theme.highlightColor - z: tabsBar.z + 1 - height: Maui.Style.unit * 2 - visible: checked - anchors - { - bottom: parent.bottom - left: parent.left - right: parent.right - } - } - } - - contentItem: RowLayout - { - spacing: 0 - - Label - { - text: tabsObjectModel.get(index).currentFMList.pathName - font.pointSize: Maui.Style.fontSizes.default - Layout.fillWidth: true - Layout.fillHeight: true - Layout.margins: Maui.Style.space.small - Layout.alignment: Qt.AlignCenter - verticalAlignment: Qt.AlignVCenter - horizontalAlignment: Qt.AlignHCenter - color: checked ? Kirigami.Theme.highlightColor : Kirigami.Theme.textColor - wrapMode: Text.NoWrap - elide: Text.ElideRight - } - - ToolButton - { - Layout.preferredHeight: Maui.Style.iconSizes.medium - Layout.preferredWidth: Maui.Style.iconSizes.medium - icon.height: Maui.Style.iconSizes.medium - icon.width: Maui.Style.iconSizes.width - Layout.margins: Maui.Style.space.medium - Layout.alignment: Qt.AlignRight - - icon.name: "dialog-close" - - onClicked: - { - const removedIndex = index - tabsObjectModel.remove(removedIndex) - tabsListModel.remove(removedIndex) - } - } + const removedIndex = index + tabsObjectModel.remove(removedIndex) + tabsListModel.remove(removedIndex) } } } } - - Kirigami.Separator - { - visible: tabsBar.visible - color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.7)) - Layout.fillWidth: true - Layout.preferredHeight: 1 - } - ListView { id: _browserList Layout.margins: 0 Layout.fillWidth: true Layout.fillHeight: true clip: true focus: true orientation: ListView.Horizontal model: tabsObjectModel snapMode: ListView.SnapOneItem spacing: 0 interactive: Kirigami.Settings.isMobile && tabsObjectModel.count > 1 highlightFollowsCurrentItem: true highlightMoveDuration: 0 onMovementEnded: _browserList.currentIndex = indexAt(contentX, contentY) // DropArea // { // id: _dropArea // anchors.fill: parent // z: parent.z -2 // onDropped: // { // const urls = drop.urls // for(var i in urls) // { // const item = Maui.FM.getFileInfo(urls[i]) // if(item.isdir == "true") // { // control.openTab(urls[i]) // } // } // } // } } Loader { id: selectionBarLoader Layout.fillWidth: true Layout.preferredHeight: control.selectionBar && control.selectionBar.visible ? control.selectionBar.barHeight: 0 Layout.leftMargin: Maui.Style.contentMargins * (Kirigami.Settings.isMobile ? 3 : 2) Layout.rightMargin: Maui.Style.contentMargins * (Kirigami.Settings.isMobile ? 3 : 2) Layout.bottomMargin: control.selectionBar && control.selectionBar.visible ? Maui.Style.contentMargins*2 : 0 } ProgressBar { id: _progressBar Layout.fillWidth: true Layout.alignment: Qt.AlignBottom Layout.preferredHeight: visible ? Maui.Style.iconSizes.medium : 0 visible: value > 0 } } Component.onCompleted: { openTab(Maui.FM.homePath()) // browserView.viewType = control.viewType control.setSettings() } onThumbnailsSizeChanged: { if(settings.trackChanges && settings.saveDirProps) Maui.FM.setDirConf(currentPath+"/.directory", "MAUIFM", "IconSize", thumbnailsSize) else Maui.FM.saveSettings("IconSize", thumbnailsSize, "SETTINGS") if(control.viewType === Maui.FMList.ICON_VIEW) browserView.currentView.adaptGrid() } function setSettings() { if(control.currentFMList !== null) { control.currentFMList.onlyDirs= control.settings.onlyDirs control.currentFMList.filters= control.settings.filters control.currentFMList.sortBy= control.settings.sortBy control.currentFMList.filterType= control.settings.filterType control.currentFMList.trackChanges= control.settings.trackChanges control.currentFMList.saveDirProps= control.settings.saveDirProps } } function openTab(path) { const component = Qt.createComponent("private/BrowserView.qml"); if (component.status === Component.Ready) { const object = component.createObject(tabsObjectModel); tabsObjectModel.append(object); } tabsListModel.append({title: qsTr("Untitled"), path: path}) _browserList.currentIndex = tabsObjectModel.count - 1 if(path) { setTabMetadata(path) browserView.viewType = control.viewType openFolder(path) } } function setTabMetadata(filepath) { tabsListModel.setProperty(tabsBar.currentIndex, "path", filepath) } function shareFiles(urls) { if(urls.length <= 0) return; if(isAndroid) { Maui.Android.shareDialog(urls[0]) } else { dialogLoader.sourceComponent= shareDialogComponent dialog.show(urls) } } function openItem(index) { const item = control.currentFMList.get(index) const path = item.path switch(currentPathType) { case Maui.FMList.CLOUD_PATH: if(item.mime === "inode/directory") { control.openFolder(path) } else { Maui.FM.openCloudItem(item) } break; default: if(selectionMode && item.mime !== "inode/directory") { if(control.selectionBar && control.selectionBar.contains(item.path)) { control.selectionBar.removeAtPath(item.path) }else { control.addToSelection(item) } } else { if(item.mime === "inode/directory") { control.openFolder(path) } else { if (Kirigami.Settings.isMobile) { previewer.show(path) } else { control.openFile(path) } } } } } function openFile(path) { Maui.FM.openUrl(path) } function openFolder(path) { populate(path) } function setPath(path) { control.currentPath = path } function populate(path) { if(!String(path).length) return; browserView.currentView.currentIndex = -1 setPath(path) } function goBack() { openFolder(control.currentFMList.previousPath) browserView.currentView.currentIndex = indexHistory.pop() } function goNext() { openFolder(control.currentFMList.posteriorPath) } function goUp() { openFolder(control.currentFMList.parentPath) } function refresh() { const pos = browserView.currentView.contentY browserView.currentView.contentY = pos } function addToSelection(item) { if(!control.selectionBar) selectionBarLoader.sourceComponent = selectionBarComponent control.selectionBar.singleSelection = control.singleSelection control.selectionBar.append(item) } function clean() { control.clipboardItems = [] if(control.selectionBar && control.selectionBar.visible) selectionBar.clear() } function copy(items) { control.clipboardItems = items control.isCut = false control.isCopy = true } function cut(items) { control.clipboardItems = items control.isCut = true control.isCopy = false } function paste() { if(control.isCopy) { control.currentFMList.copyInto(control.clipboardItems) } else if(control.isCut) { control.currentFMList.cutInto(control.clipboardItems) control.clean() } } function remove(items) { for(var i in items) Maui.FM.removeFile(items[i].path) } function selectAll() //TODO for now dont select more than 100 items so things dont freeze or break { for(var i = 0; i < Math.min(control.currentFMList.count, 100); i++) addToSelection(control.currentFMList.get(i)) } function trash(items) { for(var i in items) Maui.FM.moveToTrash(items[i].path) } function bookmarkFolder(paths) //multiple paths { control.newBookmark(paths) } function zoomIn() { control.thumbnailsSize = control.thumbnailsSize + 8 } function zoomOut() { const newSize = control.thumbnailsSize - 8 if(newSize >= Maui.Style.iconSizes.small) control.thumbnailsSize = newSize } function groupBy() { var prop = "" var criteria = ViewSection.FullString switch(control.currentFMList.sortBy) { case Maui.FMList.LABEL: prop = "label" criteria = ViewSection.FirstCharacter break; case Maui.FMList.MIME: prop = "mime" break; case Maui.FMList.SIZE: prop = "size" break; case Maui.FMList.DATE: prop = "date" break; case Maui.FMList.MODIFIED: prop = "modified" break; } if(!prop) { control.browserView.currentView.section.property = "" return } control.browserView.viewType = Maui.FMList.LIST_VIEW control.browserView.currentView.section.property = prop control.browserView.currentView.section.criteria = criteria } } diff --git a/src/controls/TabBar.qml b/src/controls/TabBar.qml new file mode 100644 index 0000000..826f014 --- /dev/null +++ b/src/controls/TabBar.qml @@ -0,0 +1,33 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.3 +import org.kde.kirigami 2.7 as Kirigami +import org.kde.mauikit 1.0 as Maui + +TabBar +{ + id: control + implicitHeight: Maui.Style.rowHeight + Maui.Style.space.small + Kirigami.Theme.colorSet: Kirigami.Theme.View + Kirigami.Theme.inherit: false + clip: true + + background: Rectangle + { + color: Kirigami.Theme.backgroundColor + + Kirigami.Separator + { + color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.7)) + + anchors + { + left: parent.left + right: parent.right + top: control.position === TabBar.Footer ? parent.top : undefined + bottom: control.position == TabBar.Header ? parent.bottom : undefined + } + height: Maui.Style.unit + } + } +} diff --git a/src/controls/TabButton.qml b/src/controls/TabButton.qml new file mode 100644 index 0000000..e4dbcbe --- /dev/null +++ b/src/controls/TabButton.qml @@ -0,0 +1,76 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.3 +import org.kde.kirigami 2.7 as Kirigami +import org.kde.mauikit 1.0 as Maui + +TabButton +{ + id: control + implicitWidth: 150 * Maui.Style.unit + + signal closeClicked(int index) + + Kirigami.Separator + { + color: Kirigami.Theme.highlightColor + height: Maui.Style.unit * 2 + visible: checked + anchors + { + + bottom: parent.bottom + left: parent.left + right: parent.right + } + } + + background: Rectangle + { + color: "transparent" + + Kirigami.Separator + { + width: Maui.Style.unit + anchors + { + bottom: parent.bottom + top: parent.top + right: parent.right + } + } + } + + contentItem: RowLayout + { + anchors.fill: control + spacing: Maui.Style.space.small + anchors.margins: Maui.Style.space.small + + Label + { + text: control.text + font.pointSize: Maui.Style.fontSizes.default + Layout.fillWidth: true + Layout.fillHeight: true + verticalAlignment: Qt.AlignVCenter + horizontalAlignment: Qt.AlignHCenter + color: control.checked ? Kirigami.Theme.highlightColor : Kirigami.Theme.textColor + wrapMode: Text.NoWrap + elide: Text.ElideMiddle + } + + ToolButton + { + Layout.fillHeight: true + Layout.preferredWidth: Maui.Style.iconSizes.medium + icon.height: Maui.Style.iconSizes.medium + icon.width: width + Layout.alignment: Qt.AlignRight + + icon.name: "dialog-close" + + onClicked: control.closeClicked(index) + } + } +} diff --git a/src/controls/qmldir b/src/controls/qmldir index 95b8638..bf847e0 100644 --- a/src/controls/qmldir +++ b/src/controls/qmldir @@ -1,54 +1,56 @@ module org.kde.mauikit plugin MauiKit classname MauiKit depends QtQuick.Controls 1.4 depends QtQuick.Controls.Private 1.0 depends QtQuick.Controls 2.0 depends QtGraphicalEffects 1.0 designersupported typeinfo plugins.qmltypes singleton Style 1.0 Style.qml ApplicationWindow 1.0 ApplicationWindow.qml ToolBar 1.0 ToolBar.qml Page 1.0 Page.qml ShareDialog 1.0 ShareDialog.qml PieButton 1.0 PieButton.qml SideBar 1.0 SideBar.qml AbstractSideBar 1.0 AbstractSideBar.qml GlobalDrawer 1.0 GlobalDrawer.qml ListDelegate 1.0 ListDelegate.qml ItemDelegate 1.0 ItemDelegate.qml SwipeItemDelegate 1.0 SwipeItemDelegate.qml SwipeBrowserDelegate 1.0 SwipeBrowserDelegate.qml ListBrowserDelegate 1.0 ListBrowserDelegate.qml GridBrowserDelegate 1.0 GridBrowserDelegate.qml SelectionBar 1.0 SelectionBar.qml LabelDelegate 1.0 LabelDelegate.qml NewDialog 1.0 NewDialog.qml TagsBar 1.0 TagsBar.qml TagsDialog 1.0 TagsDialog.qml Taglist 1.0 private/TagList.qml GridBrowser 1.0 GridBrowser.qml ListBrowser 1.0 ListBrowser.qml FileBrowser 1.0 FileBrowser.qml FilePreviewer 1.0 FilePreviewer.qml FileDialog 1.0 FileDialog.qml PlacesSidebar 1.0 PlacesSidebar.qml PlacesListBrowser 1.0 PlacesListBrowser.qml PathBar 1.0 PathBar.qml Dialog 1.0 Dialog.qml Popup 1.0 Popup.qml AboutDialog 1.0 AboutDialog.qml TextField 1.0 TextField.qml Badge 1.0 Badge.qml GridView 1.0 GridView.qml Terminal 1.0 Terminal.qml SyncDialog 1.0 SyncDialog.qml SyncDialog 1.0 SyncDialogA.qml Editor 1.0 Editor.qml ColorsBar 1.0 ColorsBar.qml Holder 1.0 Holder.qml ImageViewer 1.0 ImageViewer.qml +TabBar 1.0 TabBar.qml +TabButton 1.0 TabButton.qml diff --git a/src/mauikit.cpp b/src/mauikit.cpp index feda4aa..6ed7d13 100644 --- a/src/mauikit.cpp +++ b/src/mauikit.cpp @@ -1,220 +1,222 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mauikit.h" #include #include "handy.h" #include "mauimodel.h" #include "mauilist.h" #include "pathlist.h" #include "mauiapp.h" #include "fmstatic.h" #ifdef COMPONENT_ACCOUNTS #include "mauiaccounts.h" #endif #ifdef COMPONENT_FM #include "fm.h" #include "placeslist.h" #include "fmlist.h" #endif #ifdef COMPONENT_TAGGING #include "tagsmodel.h" #include "tagslist.h" #endif #ifdef COMPONENT_STORE #include "storemodel.h" #include "storelist.h" #endif #ifdef COMPONENT_EDITOR #include "documenthandler.h" #include "syntaxhighlighterutil.h" #ifdef STATIC_MAUIKIT #include "kquicksyntaxhighlighter/kquicksyntaxhighlighter.h" #endif #endif #ifdef Q_OS_ANDROID #include "mauiandroid.h" #else #include "mauikde.h" #endif #if defined Q_OS_ANDROID || defined APPIMAGE_PACKAGE || defined MAUIKIT_STYLE #include #include #endif QUrl MauiKit::componentUrl(const QString &fileName) const { #ifdef MAUI_APP return QUrl(QStringLiteral("qrc:/maui/kit/") + fileName); #else return QUrl(resolveFileUrl(fileName)); #endif } void MauiKit::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("org.kde.mauikit")); qmlRegisterSingletonType(componentUrl(QStringLiteral("Style.qml")), uri, 1, 0, "Style"); qmlRegisterType(componentUrl(QStringLiteral("ToolBar.qml")), uri, 1, 0, "ToolBar"); qmlRegisterType(componentUrl(QStringLiteral("ApplicationWindow.qml")), uri, 1, 0, "ApplicationWindow"); qmlRegisterType(componentUrl(QStringLiteral("Page.qml")), uri, 1, 0, "Page"); qmlRegisterType(componentUrl(QStringLiteral("ShareDialog.qml")), uri, 1, 0, "ShareDialog"); qmlRegisterType(componentUrl(QStringLiteral("PieButton.qml")), uri, 1, 0, "PieButton"); qmlRegisterType(componentUrl(QStringLiteral("SideBar.qml")), uri, 1, 0, "SideBar"); qmlRegisterType(componentUrl(QStringLiteral("AbstractSideBar.qml")), uri, 1, 0, "AbstractSideBar"); qmlRegisterType(componentUrl(QStringLiteral("Holder.qml")), uri, 1, 0, "Holder"); qmlRegisterType(componentUrl(QStringLiteral("GlobalDrawer.qml")), uri, 1, 0, "GlobalDrawer"); qmlRegisterType(componentUrl(QStringLiteral("ListDelegate.qml")), uri, 1, 0, "ListDelegate"); qmlRegisterType(componentUrl(QStringLiteral("ListBrowserDelegate.qml")), uri, 1, 0, "ListBrowserDelegate"); qmlRegisterType(componentUrl(QStringLiteral("SwipeItemDelegate.qml")), uri, 1, 0, "SwipeItemDelegate"); qmlRegisterType(componentUrl(QStringLiteral("SwipeBrowserDelegate.qml")), uri, 1, 0, "SwipeBrowserDelegate"); qmlRegisterType(componentUrl(QStringLiteral("ItemDelegate.qml")), uri, 1, 0, "ItemDelegate"); qmlRegisterType(componentUrl(QStringLiteral("GridBrowserDelegate.qml")), uri, 1, 0, "GridBrowserDelegate"); qmlRegisterType(componentUrl(QStringLiteral("SelectionBar.qml")), uri, 1, 0, "SelectionBar"); qmlRegisterType(componentUrl(QStringLiteral("LabelDelegate.qml")), uri, 1, 0, "LabelDelegate"); qmlRegisterType(componentUrl(QStringLiteral("NewDialog.qml")), uri, 1, 0, "NewDialog"); qmlRegisterType(componentUrl(QStringLiteral("Dialog.qml")), uri, 1, 0, "Dialog"); qmlRegisterType(componentUrl(QStringLiteral("AboutDialog.qml")), uri, 1, 0, "AboutDialog"); qmlRegisterType(componentUrl(QStringLiteral("Popup.qml")), uri, 1, 0, "Popup"); qmlRegisterType(componentUrl(QStringLiteral("TextField.qml")), uri, 1, 0, "TextField"); qmlRegisterType(componentUrl(QStringLiteral("Badge.qml")), uri, 1, 0, "Badge"); qmlRegisterType(componentUrl(QStringLiteral("GridView.qml")), uri, 1, 0, "GridView"); qmlRegisterType(componentUrl(QStringLiteral("ColorsBar.qml")), uri, 1, 0, "ColorsBar"); - qmlRegisterType(componentUrl(QStringLiteral("ImageViewer.qml")), uri, 1, 0, "ImageViewer"); - + qmlRegisterType(componentUrl(QStringLiteral("ImageViewer.qml")), uri, 1, 0, "ImageViewer"); + qmlRegisterType(componentUrl(QStringLiteral("TabBar.qml")), uri, 1, 0, "TabBar"); + qmlRegisterType(componentUrl(QStringLiteral("TabButton.qml")), uri, 1, 0, "TabButton"); + qmlRegisterType(componentUrl(QStringLiteral("PathBar.qml")), uri, 1, 0, "PathBar"); qmlRegisterType(uri, 1, 0, "PathList"); /** STORE CONTROLS, MODELS AND INTERFACES **/ #ifdef COMPONENT_STORE qmlRegisterType("StoreList", 1, 0, "StoreList"); qmlRegisterType("StoreModel", 1, 0, "StoreModel"); qmlRegisterType(componentUrl(QStringLiteral("private/StoreDelegate.qml")), uri, 1, 0, "StoreDelegate"); qmlRegisterType(componentUrl(QStringLiteral("Store.qml")), uri, 1, 0, "Store"); #endif /** BROWSING CONTROLS **/ qmlRegisterType(componentUrl(QStringLiteral("ListBrowser.qml")), uri, 1, 0, "ListBrowser"); qmlRegisterType(componentUrl(QStringLiteral("GridBrowser.qml")), uri, 1, 0, "GridBrowser"); /** FM CONTROLS, MODELS AND INTERFACES **/ #ifdef COMPONENT_FM qmlRegisterType(uri, 1, 0, "PlacesList"); qmlRegisterType(uri, 1, 0, "FMList"); qmlRegisterSingletonType(uri, 1, 0, "FM", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return new FMStatic; }); // qmlRegisterSingletonType(componentUrl(QStringLiteral("private/FileBrowser.qml")), uri, 1, 0, "FileMenu"); qmlRegisterType(componentUrl(QStringLiteral("FileBrowser.qml")), uri, 1, 0, "FileBrowser"); qmlRegisterType(componentUrl(QStringLiteral("PlacesSidebar.qml")), uri, 1, 0, "PlacesSidebar"); qmlRegisterType(componentUrl(QStringLiteral("PlacesListBrowser.qml")), uri, 1, 0, "PlacesListBrowser"); qmlRegisterType(componentUrl(QStringLiteral("FilePreviewer.qml")), uri, 1, 0, "FilePreviewer"); qmlRegisterType(componentUrl(QStringLiteral("FileDialog.qml")), uri, 1, 0, "FileDialog"); #endif /** EDITOR CONTROLS **/ qmlRegisterType(uri, 1, 0, "DocumentHandler"); qmlRegisterType(); qmlRegisterType(componentUrl(QStringLiteral("Editor.qml")), uri, 1, 0, "Editor"); #ifdef STATIC_MAUIKIT qmlRegisterType("org.kde.kquicksyntaxhighlighter", 0, 1, "KQuickSyntaxHighlighter"); #endif /** PLATFORMS SPECIFIC CONTROLS **/ #ifdef Q_OS_ANDROID qmlRegisterSingletonType(uri, 1, 0, "Android", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return new MAUIAndroid; }); #else qmlRegisterType(componentUrl(QStringLiteral("Terminal.qml")), uri, 1, 0, "Terminal"); qmlRegisterSingletonType(uri, 1, 0, "KDE", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return new MAUIKDE; }); #endif /** DATA MODELING TEMPLATED INTERFACES **/ qmlRegisterType(); //ABSTRACT BASE LIST qmlRegisterType(uri, 1, 0, "BaseModel"); //BASE MODEL /** TAGGING INTERFACES AND MODELS **/ #ifdef COMPONENT_TAGGING qmlRegisterType("TagsList", 1, 0, "TagsList"); qmlRegisterType("TagsModel", 1, 0, "TagsModel"); qmlRegisterType(componentUrl(QStringLiteral("private/TagList.qml")), uri, 1, 0, "TagList"); qmlRegisterType(componentUrl(QStringLiteral("TagsBar.qml")), uri, 1, 0, "TagsBar"); qmlRegisterType(componentUrl(QStringLiteral("TagsDialog.qml")), uri, 1, 0, "TagsDialog"); #endif /** MAUI APPLICATION SPECIFIC PROPS **/ #ifdef COMPONENT_ACCOUNTS qmlRegisterType(); qmlRegisterType(componentUrl(QStringLiteral("SyncDialog.qml")), uri, 1, 0, "SyncDialog"); //to be rename to accountsDialog #endif qmlRegisterUncreatableType(uri, 1, 0, "App", "Cannot be created App"); /** HELPERS **/ qmlRegisterSingletonType(uri, 1, 0, "Handy", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return new Handy; }); #if defined Q_OS_ANDROID || defined APPIMAGE_PACKAGE || defined MAUIKIT_STYLE this->initResources(); #endif qmlProtectModule(uri, 1); } void MauiKit::initResources() { #if defined QICON_H && defined QQUICKSTYLE_H Q_INIT_RESOURCE(mauikit); Q_INIT_RESOURCE(icons); Q_INIT_RESOURCE(style); QIcon::setThemeSearchPaths({":/icons/luv-icon-theme"}); QIcon::setThemeName("Luv"); QQuickStyle::setStyle(":/style"); #endif } #include "moc_mauikit.cpp"