diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4d42a5e..27c2996 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,143 +1,155 @@
-
-
+
+
+
+
+
+
- android:name="com.example.android.tools.NotificationClient"
+
+
+
+
+
-
+
+
-
diff --git a/index.pro b/index.pro
index d15db32..9f41b84 100644
--- a/index.pro
+++ b/index.pro
@@ -1,71 +1,77 @@
QT += qml
QT += quick
QT += sql
CONFIG += c++17
QMAKE_LINK += -nostdlib++
#DESTDIR = $$OUT_PWD/../
linux:unix:!android {
} else:android {
message(Building helpers for Android)
include($$PWD/3rdparty/kirigami/kirigami.pri)
include($$PWD/3rdparty/mauikit/mauikit.pri)
DEFINES += STATIC_KIRIGAMI
} else {
message("Unknown configuration")
}
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
$$PWD/src/main.cpp \
$$PWD/src/index.cpp \
HEADERS += \
$$PWD/src/index.h \
$$PWD/src/inx.h \
RESOURCES += \
$$PWD/src/qml.qrc \
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
include($$PWD/install.pri)
DISTFILES += \
$$PWD/org.kde.index.desktop \
3rdparty/mauikit/src/android/AndroidManifest.xml \
3rdparty/mauikit/src/android/build.gradle \
+ 3rdparty/mauikit/src/android/build.gradle \
+ 3rdparty/mauikit/src/android/gradle/wrapper/gradle-wrapper.jar \
3rdparty/mauikit/src/android/gradle/wrapper/gradle-wrapper.jar \
3rdparty/mauikit/src/android/gradle/wrapper/gradle-wrapper.properties \
+ 3rdparty/mauikit/src/android/gradle/wrapper/gradle-wrapper.properties \
3rdparty/mauikit/src/android/gradlew \
+ 3rdparty/mauikit/src/android/gradlew \
+ 3rdparty/mauikit/src/android/gradlew.bat \
3rdparty/mauikit/src/android/gradlew.bat \
+ 3rdparty/mauikit/src/android/res/values/libs.xml \
3rdparty/mauikit/src/android/res/values/libs.xml
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_PACKAGE_SOURCE_DIR = \
$$PWD/3rdparty/mauikit/src/android
}
diff --git a/src/main.cpp b/src/main.cpp
index b4de984..4b59699 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,78 +1,78 @@
#include
#include
#include
#include
#include
#include "index.h"
#include "inx.h"
#ifdef Q_OS_ANDROID
#include
#include
#else
#include
#endif
#ifdef STATIC_KIRIGAMI
#include "3rdparty/kirigami/src/kirigamiplugin.h"
#endif
#ifdef STATIC_MAUIKIT
#include "3rdparty/mauikit/src/mauikit.h"
#endif
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#ifdef Q_OS_ANDROID
QGuiApplication app(argc, argv);
#else
QApplication app(argc, argv);
#endif
app.setApplicationName(INX::app);
app.setApplicationVersion(INX::version);
app.setApplicationDisplayName(INX::app);
app.setOrganizationName("org.maui.index");
app.setWindowIcon(QIcon(":/index.png"));
QCommandLineParser parser;
parser.setApplicationDescription(INX::description);
const QCommandLineOption versionOption = parser.addVersionOption();
parser.addOption(versionOption);
parser.process(app);
const QStringList args = parser.positionalArguments();
QStringList paths;
if(!args.isEmpty())
paths = args;
#ifdef STATIC_KIRIGAMI
KirigamiPlugin::getInstance().registerTypes();
#endif
#ifdef STATIC_MAUIKIT
MauiKit::getInstance().registerTypes();
#endif
Index index;
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url, paths, &index](QObject *obj, const QUrl &objUrl)
{
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
if(!paths.isEmpty())
index.openPaths(paths);
}, Qt::QueuedConnection);
- auto context = engine.rootContext();
+ const auto context = engine.rootContext();
context->setContextProperty("inx", &index);
engine.load(url);
return app.exec();
}
diff --git a/src/main.qml b/src/main.qml
index 721aa76..a771862 100644
--- a/src/main.qml
+++ b/src/main.qml
@@ -1,215 +1,349 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import org.kde.kirigami 2.7 as Kirigami
import org.kde.mauikit 1.0 as Maui
+import QtQml.Models 2.3
import QtQuick.Window 2.0
import "widgets"
import "widgets/views"
Maui.ApplicationWindow
{
id: root
title: browser.currentPath
- property alias browser: browserView.browser
showAccounts: false
- about.appDescription: qsTr("Index is a file manager that works on desktops, Android and Plasma Mobile. Index lets you browse your system files and applications and preview your music, text, image and video files and share them with external applications.")
- about.appIcon: "qrc:/assets/index.svg"
+ Maui.App.description: qsTr("Index is a file manager that works on desktops, Android and Plasma Mobile. Index lets you browse your system files and applications and preview your music, text, image and video files and share them with external applications.")
+ Maui.App.iconName: "qrc:/assets/index.svg"
- property alias dialog : dialogLoader.item
+ property bool terminalVisible : true
+ property alias terminal : terminalLoader.item
+ property alias browser: _browserList.currentItem
+ property alias dialog : dialogLoader.item
property bool searchBar: false
-// accentColor: "#303952"
+ // accentColor: "#303952"
// highlightColor: "#64B5F6"
-// altColorText: "#ffffff"
+ // altColorText: "#ffffff"
// headBarBGColor: "#64B5F6"
// headBarFGColor: altColorText
// headBar.colorScheme.borderColor: Qt.darker(headBarBGColor, 1.4)
searchButton.checked: searchBar
onSearchButtonClicked:
{
searchBar = !searchBar
if(searchBar)
_pathBarLoader.item.forceActiveFocus()
}
- onGoBackTriggered: browser.goBack()
-
// headBarBGColor: viewBackgroundColor
// headBar.drawBorder: false
// footBar.visible: false
-// headBar.leftContent: ToolButton
-// {
-// visible: _drawer.modal
-// icon.name: "view-right-new"
-// onClicked: _drawer.visible = !_drawer.visible
-// checkable: true
-// checked: _drawer.visible
-// }
+ // headBar.leftContent: ToolButton
+ // {
+ // visible: _drawer.modal
+ // icon.name: "view-right-new"
+ // onClicked: _drawer.visible = !_drawer.visible
+ // checkable: true
+ // checked: _drawer.visible
+ // }
-// leftIcon.visible: false
- // leftIcon.onClicked: _drawer.visible = !_drawer.visible
- // leftIcon.checkable: true
- // leftIcon.checked: _drawer.visible
- // headBar.strech: false
Component
{
id: _pathBarComponent
Maui.PathBar
{
anchors.fill: parent
- // colorScheme.backgroundColor: "#fff"
- // colorScheme.textColor: "#333"
- // colorScheme.borderColor: Qt.darker(headBarBGColor, 1.4)
onPathChanged: browser.openFolder(path)
url: browser.currentPath
onHomeClicked: browser.openFolder(Maui.FM.homePath())
onPlaceClicked: browser.openFolder(path)
}
}
Component
{
id: _searchFieldComponent
Maui.TextField
{
anchors.fill: parent
placeholderText: qsTr("Search for files... ")
onAccepted: browser.openFolder("search://"+text)
- // onCleared: browser.goBack()
onGoBackTriggered:
{
searchBar = false
clear()
- // browser.goBack()
}
background: Rectangle
{
border.color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.7))
radius: radiusV
color: Kirigami.Theme.backgroundColor
}
}
}
headBar.implicitHeight: toolBarHeight * 1.2
headBar.middleContent: Loader
{
id: _pathBarLoader
-
Layout.fillWidth: true
Layout.margins: space.medium
Layout.preferredHeight: iconSizes.big
sourceComponent: searchBar ? _searchFieldComponent : _pathBarComponent
-// onLoaded:
-// {
-// if(sourceComponent === _pathBarComponent)
-// item.url =browser.currentPath
-// }
}
Loader
{
id: dialogLoader
}
globalDrawer: Maui.GlobalDrawer
{
id: _drawer
- width: Math.min(Kirigami.Units.gridUnit * 11, root.width)
- handleClosedIcon.source: "view-right-new"
- handleOpenIcon.source: "view-right-new"
-// height: 200 /*- root.header.height - browser.header.height*/
-// y: 0
+ property bool collapsed : !root.isWide
+
+ width: collapsed ? placesSidebar.iconSize * 2.5 : Math.min(Kirigami.Units.gridUnit * 11, root.width)
+ // handleClosedIcon.source: "view-right-new"
+ // handleOpenIcon.source: "view-right-new"
height: root.height - root.header.height - (browser.headBar.position === ToolBar.Footer && _drawer.modal ? browser.footer.height : 0)
- modal: !root.isWide
- handleVisible: modal
+ modal: false
+ handleVisible: false
contentItem: Maui.PlacesSidebar
{
id: placesSidebar
+ property bool collapsed : !root.isWide
+ showLabels: !collapsed
+ section.property: collapsed ? "" : "type"
+ ScrollBar.vertical.policy: collapsed ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
+
// height: _drawer.height
anchors.fill: parent
onPlaceClicked:
{
if(_drawer.modal)
_drawer.close()
browser.openFolder(path)
if(searchBar)
searchBar = false
}
list.groups: [
Maui.FMList.PLACES_PATH,
Maui.FMList.APPS_PATH,
Maui.FMList.CLOUD_PATH,
Maui.FMList.REMOTE_PATH,
Maui.FMList.REMOVABLE_PATH,
Maui.FMList.DRIVES_PATH,
Maui.FMList.TAGS_PATH]
- // width: isCollapsed ? iconSize*2 : parent.width
- // height: parent.height
-
-
}
}
+ ObjectModel { id: tabsObjectModel }
-
- Browser
+ ColumnLayout
{
- id: browserView
anchors.fill: parent
- }
+ spacing: 0
+ 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
- // Rectangle
- // {
- // color: "pink"
- // width: iconSizes.big
- // height: width * 1.5
+ currentIndex : _browserList.currentIndex
+ clip: true
- // anchors.left: parent.left
- // anchors.bottom: parent.bottom
+ ListModel { id: tabsListModel }
- // anchors.bottomMargin: toolBarHeight
+ background: Rectangle
+ {
+ color: "transparent"
+ }
- // Maui.ToolButton
- // {
+ Repeater
+ {
+ model: tabsListModel
+
+ TabButton
+ {
+ id: _tabButton
+ readonly property int tabWidth: 150 * unit
+ implicitWidth: Math.min(tabWidth, root.width)
+ implicitHeight: Maui.Style.rowHeight
+ checked: index === _browserList.currentIndex
+
+ onClicked:
+ {
+ _browserList.currentIndex = index
+ if(terminal && terminalVisible && !isMobile)
+ terminal.session.sendText("cd '" + path.replace("file://", "") + "'\n")
+ }
+
+ background: Rectangle
+ {
+ color: checked ? Kirigami.Theme.focusColor : Kirigami.Theme.backgroundColor
+ opacity: checked ? 0.4 : 1
+
+ Kirigami.Separator
+ {
+ color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.7))
+ z: tabsBar.z + 1
+ width : 1
+ // visible: tabsListModel.count > 1
+ anchors
+ {
+ bottom: parent.bottom
+ top: parent.top
+ right: parent.right
+ }
+ }
+ }
+
+ contentItem: RowLayout
+ {
+ spacing: 0
+
+ Label
+ {
+ text: tabsObjectModel.get(index).list.pathName
+ font.pointSize: fontSizes.default
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: space.small
+ Layout.alignment: Qt.AlignCenter
+ verticalAlignment: Qt.AlignVCenter
+ horizontalAlignment: Qt.AlignHCenter
+ color: Kirigami.Theme.textColor
+ wrapMode: Text.NoWrap
+ elide: Text.ElideRight
+ }
+
+ ToolButton
+ {
+ Layout.preferredHeight: iconSizes.medium
+ Layout.preferredWidth: iconSizes.medium
+ icon.height: iconSizes.medium
+ icon.width: iconSizes.width
+ Layout.margins: space.medium
+ Layout.alignment: Qt.AlignRight
+
+ icon.name: "dialog-close"
+
+ onClicked:
+ {
+ var 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.fillHeight: true
+ Layout.fillWidth: true
+ orientation: ListView.Horizontal
+ model: tabsObjectModel
+ snapMode: ListView.SnapOneItem
+ spacing: 0
+ interactive: isMobile && tabsObjectModel.count > 1
+ highlightFollowsCurrentItem: true
+ highlightMoveDuration: 0
+ onMovementEnded: _browserList.currentIndex = indexAt(contentX, contentY)
+ }
+
+ Loader
+ {
+ id: terminalLoader
+ visible: terminalVisible && terminal
+ focus: true
+ Layout.fillWidth: true
+ Layout.minimumHeight: visible && terminal ? 100 : 0
+ Layout.maximumHeight: visible && terminal ? 500 : 0
+ Layout.preferredHeight : visible && terminal ? 200 : 0
+ source: !isMobile ? "widgets/views/Terminal.qml" : undefined
+ }
+ }
- // }
- // }
Component
{
id:fmDialogComponent
Maui.FileDialog
{
onlyDirs: false
filterType: Maui.FMList.AUDIO
sortBy: Maui.FMList.MODIFIED
mode: modes.OPEN
}
}
Connections
{
target: inx
onOpenPath: browser.openFolder(paths[0])
}
Component.onCompleted:
{
if(isAndroid)
Maui.Android.statusbarColor(Kirigami.Theme.backgroundColor, true)
+ openTab(Maui.FM.homePath())
+ }
+
+ function openTab(path)
+ {
+ var component = Qt.createComponent("widgets/views/Browser.qml");
+ if (component.status === Component.Ready)
+ {
+ var object = component.createObject(tabsObjectModel);
+ tabsObjectModel.append(object);
+ }
+
+ tabsListModel.append({
+ title: qsTr("Untitled"),
+ path: path,
+ })
+
+ _browserList.currentIndex = tabsObjectModel.count - 1
+
+ if(path && Maui.FM.fileExists(path))
+ {
+ setTabMetadata(path)
+ tabsObjectModel.get(tabsObjectModel.count - 1).openFolder(path)
+ }
+ }
+
+ function setTabMetadata(filepath)
+ {
+ tabsListModel.setProperty(tabsBar.currentIndex, "path", filepath)
}
}
diff --git a/src/widgets/views/Browser.qml b/src/widgets/views/Browser.qml
index 8e01d04..004e1dc 100644
--- a/src/widgets/views/Browser.qml
+++ b/src/widgets/views/Browser.qml
@@ -1,132 +1,76 @@
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import org.kde.kirigami 2.0 as Kirigami
import org.kde.mauikit 1.0 as Maui
-//import FMH 1.0
-
-ColumnLayout
+Maui.FileBrowser
{
id: control
-// orientation: Qt.Vertical
- property alias browser : browser
- property bool terminalVisible : true
- property alias terminal : terminalLoader.item
-
- Maui.FileBrowser
- {
- id: browser
- Layout.fillWidth: true
- Layout.fillHeight: true
- headBar.visible: true
- headBar.drawBorder: true
- headBar.plegable: false
- menu:[
- MenuItem
- {
- visible: !isMobile
- text: qsTr("Show terminal")
- checkable: true
- checked: terminalVisible
- onTriggered:
- {
- terminalVisible = !terminalVisible
- Maui.FM.setDirConf(browser.currentPath+"/.directory", "MAUIFM", "ShowTerminal", terminalVisible)
- }
- }
- ]
- headBar.rightContent: ToolButton
- {
- visible: control.terminal
- icon.name: "akonadiconsole"
- onClicked: control.terminalVisible = !control.terminalVisible
- checked : control.terminalVisible
- checkable: false
- }
+ height: _browserList.height
+ width: _browserList.width
- onNewBookmark:
+ headBar.visible: true
+ itemMenu.contentData: [
+ MenuItem
{
- for(var index in paths)
- placesSidebar.list.addPlace(paths[index])
+ visible: control.itemMenu.isDir
+ text: qsTr("Open in tab")
+ onTriggered: openTab(control.itemMenu.item.path)
}
+ ]
- onCurrentPathChanged:
+ menu: [
+ MenuItem
{
-// if(!isAndroid)
-// terminalVisible = Maui.FM.dirConf(currentPath+"/.directory")["showterminal"] === "true" ? true : false
-
- if(terminalVisible && !isMobile)
- terminal.session.sendText("cd '" + currentPath + "'\n")
-
- for(var i = 0; i < placesSidebar.count; i++)
- if(currentPath === placesSidebar.list.get(i).path)
- placesSidebar.currentIndex = i
+ visible: !isMobile
+ text: qsTr("Show terminal")
+ checkable: true
+ checked: terminalVisible
+ onTriggered:
+ {
+ terminalVisible = !terminalVisible
+ Maui.FM.setDirConf(control.currentPath+"/.directory", "MAUIFM", "ShowTerminal", terminalVisible)
+ }
}
+ ]
- onItemClicked: openItem(index)
-
- onItemDoubleClicked:
- {
- var item = list.get(index)
- console.log(item.mime)
- if(Maui.FM.isDir(item.path) || item.mime === "inode/directory")
- browser.openFolder(item.path)
- else
- browser.openFile(item.path)
- }
+ headBar.rightContent: ToolButton
+ {
+ visible: terminal
+ icon.name: "utilities-terminal"
+ onClicked: terminalVisible = !terminalVisible
+ checked : terminalVisible
+ checkable: false
}
-// Rectangle
-// {
-// id: handle
-// visible: true
-
-// Layout.fillWidth: true
-// height: 5
-// color: "transparent"
-
-// Kirigami.Separator
-// {
-// visible: terminalLoader.visible
-
-// anchors
-// {
-// bottom: parent.bottom
-// right: parent.right
-// left: parent.left
-// }
-// }
+ onNewBookmark:
+ {
+ for(var index in paths)
+ placesSidebar.list.addPlace(paths[index])
+ }
-// MouseArea
-// {
-// visible: terminalLoader.visible
+ onCurrentPathChanged:
+ {
+ if(terminalVisible && !isMobile)
+ terminal.session.sendText("cd '" + currentPath.replace("file://", "") + "'\n")
-// anchors.fill: parent
-// drag.target: parent
-// drag.axis: Drag.YAxis
-// drag.smoothed: true
-// cursorShape: Qt.SizeVerCursor
-// }
-// }
+ for(var i = 0; i < placesSidebar.count; i++)
+ if(currentPath === placesSidebar.list.get(i).path)
+ placesSidebar.currentIndex = i
+ }
-// handle: Rectangle
-// {
-// color: "yellow"
-// }
+ onItemClicked: openItem(index)
- Loader
+ onItemDoubleClicked:
{
- id: terminalLoader
- visible: terminalVisible && terminal
- focus: true
- Layout.fillWidth: true
-// Layout.fillHeight: true
- Layout.minimumHeight: visible && terminal ? 100 : 0
- Layout.maximumHeight: visible && terminal ? 500 : 0
- Layout.preferredHeight : visible && terminal ? 200 : 0
- source: !isMobile ? "Terminal.qml" : undefined
+ var item = list.get(index)
+ console.log(item.mime)
+ if(Maui.FM.isDir(item.path) || item.mime === "inode/directory")
+ control.openFolder(item.path)
+ else
+ control.openFile(item.path)
}
-
}
+