diff --git a/3rdparty/openssl b/3rdparty/openssl deleted file mode 160000 index a93e066..0000000 --- a/3rdparty/openssl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a93e0663dda470e0de063b39a7cd5ffa4e9c18ae diff --git a/android_files/AndroidManifest.xml b/android_files/AndroidManifest.xml index bf34ae8..43021e2 100644 --- a/android_files/AndroidManifest.xml +++ b/android_files/AndroidManifest.xml @@ -1,90 +1,157 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - - - + + + + + + + + + diff --git a/android_files/build.gradle b/android_files/build.gradle index 989d079..843af57 100644 --- a/android_files/build.gradle +++ b/android_files/build.gradle @@ -1,57 +1,58 @@ buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.0' } } repositories { google() jcenter() } apply plugin: 'com.android.application' dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + compile fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + compile 'com.android.support:support-v4:25.3.1' } android { /******************************************************* * The following variables: * - androidBuildToolsVersion, * - androidCompileSdkVersion * - qt5AndroidDir - holds the path to qt android files * needed to build any Qt application * on Android. * * are defined in gradle.properties file. This file is * updated by QtCreator and androiddeployqt tools. * Changing them manually might break the compilation! *******************************************************/ compileSdkVersion androidCompileSdkVersion.toInteger() buildToolsVersion androidBuildToolsVersion sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] res.srcDirs = [qt5AndroidDir + '/res', 'res'] resources.srcDirs = ['src'] renderscript.srcDirs = ['src'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] } } lintOptions { abortOnError false } } diff --git a/android_files/res/xml/filepaths.xml b/android_files/res/xml/filepaths.xml new file mode 100644 index 0000000..28c4156 --- /dev/null +++ b/android_files/res/xml/filepaths.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/nota.pro b/nota.pro index aa48730..a6e94e5 100644 --- a/nota.pro +++ b/nota.pro @@ -1,64 +1,61 @@ -QT += qml -QT += quick -QT += sql -QT += widgets -QT += quickcontrols2 +QT *= qml \ + quick \ + sql CONFIG += ordered CONFIG += c++17 -QMAKE_LINK += -nostdlib++ TARGET = nota TEMPLATE = app linux:unix:!android { message(Building for Linux KDE) QT += webengine LIBS += -lMauiKit } else:android { message(Building for Android) + QMAKE_LINK += -nostdlib++ + ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android_files + + DEFINES *= \ + COMPONENT_FM \ + COMPONENT_TAGGING \ + COMPONENT_EDITOR \ + MAUIKIT_STYLE \ + ANDROID_OPENSSL + include($$PWD/3rdparty/kirigami/kirigami.pri) include($$PWD/3rdparty/mauikit/mauikit.pri) DEFINES += STATIC_KIRIGAMI } else { message("Unknown configuration") } DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ - $$PWD/src/main.cpp + $$PWD/src/main.cpp \ + $$PWD/src/models/documentsmodel.cpp + +HEADERS += \ + $$PWD/src/models/documentsmodel.h RESOURCES += \ $$PWD/src/qml.qrc \ $$PWD/assets/img_assets.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 - -DISTFILES += \ - 3rdparty/mauikit/src/android/AndroidManifest.xml \ - 3rdparty/mauikit/src/android/build.gradle \ - 3rdparty/mauikit/src/android/gradle/wrapper/gradle-wrapper.jar \ - 3rdparty/mauikit/src/android/gradle/wrapper/gradle-wrapper.properties \ - 3rdparty/mauikit/src/android/gradlew \ - 3rdparty/mauikit/src/android/gradlew.bat \ - 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/Editor.qml b/src/Editor.qml index ea6b6de..3b91537 100644 --- a/src/Editor.qml +++ b/src/Editor.qml @@ -1,59 +1,45 @@ import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami Maui.Editor { height: _editorList.height width: _editorList.width footBar.visible: false - headBar.rightContent: Kirigami.ActionToolBar - { - position: ToolBar.Header - Layout.fillWidth: true - // hiddenActions: t_actions - - display: isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly - - actions :[ - Kirigami.Action - { - id: saveBtn - icon.name: "document-save" - onTriggered: { - saveFile(document.fileUrl) - } - }, - - Kirigami.Action - { - icon.name: "document-save-as" - text: "Save as..." - onTriggered: saveFile() - } - ] - } + headBar.rightContent: [ + ToolButton + { + id: saveBtn + icon.name: "document-save" + onClicked: saveFile(document.fileUrl) + }, + ToolButton + { + icon.name: "document-save-as" + text: qsTr("Save as...") + onClicked: saveFile() + } + ] function saveFile(path) { if (path && Maui.FM.fileExists(path)) { document.saveAs(path); } else { fileDialog.mode = fileDialog.modes.SAVE; - fileDialog.singleSelection = true - fileDialog.show(function (paths) { - - console.log("save as", paths) - + fileDialog.settings.singleSelection = true + fileDialog.show(function (paths) + { document.saveAs(paths[0]); setTabMetadata(paths[0]); }); } } } diff --git a/src/main.cpp b/src/main.cpp index a83585d..c7af893 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,52 +1,55 @@ #include #include #include #ifdef Q_OS_ANDROID #include #else #include #endif #ifdef STATIC_KIRIGAMI #include "3rdparty/kirigami/src/kirigamiplugin.h" #endif #ifdef STATIC_MAUIKIT #include "3rdparty/mauikit/src/mauikit.h" #endif #include "src/models/documentsmodel.h" Q_DECL_EXPORT int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #ifdef Q_OS_ANDROID QGuiApplication app(argc, argv); + if (!MAUIAndroid::checkRunTimePermissions()) + return -1; #else QApplication app(argc, argv); #endif app.setApplicationName("nota"); app.setApplicationVersion("1.0"); app.setApplicationDisplayName("Nota"); - + app.setOrganizationName("Maui"); + app.setOrganizationDomain("org.maui.nota"); app.setWindowIcon(QIcon(":/nota.svg")); #ifdef STATIC_KIRIGAMI KirigamiPlugin::getInstance().registerTypes(); #endif #ifdef STATIC_MAUIKIT MauiKit::getInstance().registerTypes(); #endif qmlRegisterType ("org.maui.nota", 1, 0, "Documents"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } diff --git a/src/main.qml b/src/main.qml index 9713fe2..c1eb072 100644 --- a/src/main.qml +++ b/src/main.qml @@ -1,327 +1,328 @@ import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 import QtQml.Models 2.3 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import QtQuick.Window 2.0 import "views" Maui.ApplicationWindow { id: root title: qsTr("Nota") // property bool terminalVisible: Maui.FM.loadSettings("TERMINAL", "MAINVIEW", false) == "true" // property alias terminal : terminalLoader.item property var views : ({editor: 0, documents: 1, recent: 2}) Maui.App.iconName: "qrc:/img/nota.svg" Maui.App.description: qsTr("Nota is a simple text editor for Plasma Mobile, GNU/Linux distros and Android") ObjectModel { id: tabsObjectModel } rightIcon.visible: false // mainMenu: [ // MenuItem // { // text: qsTr("Show terminal") // checkable: true // checked: terminal.visible // onTriggered: // { // terminalVisible = !terminalVisible // Maui.FM.saveSettings("TERMINAL",terminalVisible, "MAINVIEW") // } // } // ] Maui.FileDialog { id: fileDialog settings.onlyDirs: false settings.filterType: Maui.FMList.TEXT settings.sortBy: Maui.FMList.MODIFIED mode: modes.OPEN } Maui.FloatingButton { id: _overlayButton z: 999 anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: Maui.Style.toolBarHeight anchors.bottomMargin: Maui.Style.toolBarHeight height: Maui.Style.toolBarHeight width: height icon.name: "document-new" icon.color: Kirigami.Theme.highlightedTextColor onClicked: openTab("") Maui.Badge { iconName: "list-add" anchors { horizontalCenter: parent.right verticalCenter: parent.top } } } headBar.rightContent: [ ToolButton { icon.name: "document-open" onClicked: { fileDialog.mode = fileDialog.modes.OPEN fileDialog.settings.onlyDirs = false fileDialog.settings.singleSelection = false fileDialog.show(function (paths) { for(var i in paths) openTab(paths[i]) }); } } ] headBar.middleContent: Maui.ActionGroup { id: _actionGroup currentIndex: _swipeView.currentIndex Layout.fillHeight: true width: implicitWidth Action { text: qsTr("Editor") icon.name: "document-edit" } Action { text: qsTr("Documents") icon.name: "view-pim-journal" // to do } Action { text: qsTr("Recent") icon.name: "view-media-recent" // to do } } sideBar: Maui.AbstractSideBar { id : _drawer - width: Kirigami.Units.gridUnit * 14 - visible: _actionGroup.currentIndex === views.editor - // height: root.height - headBar.height - ( modal ? _editorList.currentItem.footBar.height : 0) - modal: root.width < Kirigami.Units.gridUnit * 62 + focus: true + width: visible ? Math.min(Kirigami.Units.gridUnit * (Kirigami.Settings.isMobile? 14 : 18), root.width) : 0 + modal: !isWide + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + dragMargin: Maui.Style.space.big Maui.Page { anchors.fill: parent headBar.middleContent: ComboBox { Layout.fillWidth: true z : _drawer.z + 9999 model: Maui.BaseModel { list: Maui.PlacesList { groups: [ Maui.FMList.PLACES_PATH, Maui.FMList.DRIVES_PATH, Maui.FMList.TAGS_PATH] } } textRole: "label" onActivated: { currentIndex = index browserView.openFolder(model.list.get(index).path) } } Maui.FileBrowser { id: browserView anchors.fill: parent headBar.position: ToolBar.Footer headBar.visible: true viewType : Maui.FMList.LIST_VIEW settings.filterType: Maui.FMList.TEXT headBar.rightLayout.visible: false headBar.rightLayout.width: 0 onItemClicked: { var item = currentFMList.get(index) if(item.isdir == "true") openFolder(item.path) else root.openTab(item.path) } } } } SwipeView { id: _swipeView anchors.fill: parent currentIndex: _actionGroup.currentIndex onCurrentItemChanged: currentItem.forceActiveFocus() onCurrentIndexChanged: _actionGroup.currentIndex = currentIndex ColumnLayout { id: editorView spacing: 0 Maui.TabBar { id: _tabBar visible: _editorList.count > 1 Layout.fillWidth: true Layout.preferredHeight: _tabBar.implicitHeight position: TabBar.Header currentIndex : _editorList.currentIndex ListModel { id: tabsListModel } // Keys.onPressed: // { // if(event.key == Qt.Key_Return) // { // _browserList.currentIndex = currentIndex // control.currentPath = tabsObjectModel.get(currentIndex).path // } // } Repeater { id: _repeater model: tabsListModel Maui.TabButton { id: _tabButton implicitHeight: _tabBar.implicitHeight implicitWidth: Math.max(_tabBar.width / _repeater.count, 120) checked: index === _tabBar.currentIndex text: title onClicked: _editorList.currentIndex = index onCloseClicked: { const removedIndex = index tabsObjectModel.remove(removedIndex) tabsListModel.remove(removedIndex) } } } } Kirigami.Separator { 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 visible: _tabBar.visible } ListView { id: _editorList Layout.fillHeight: true Layout.fillWidth: true orientation: ListView.Horizontal model: tabsObjectModel snapMode: ListView.SnapOneItem spacing: 0 interactive: isMobile highlightFollowsCurrentItem: true highlightMoveDuration: 0 Maui.Holder { id: _holder visible: !tabsListModel.count emoji: "qrc:/img/document-edit.svg" emojiSize: Maui.Style.iconSizes.huge isMask: true onActionTriggered: openTab() title: qsTr("Create a new document") body: qsTr("You can create a new document by clicking the New File button, or here.
Alternative you can open existing files from the left places sidebar or by clicking the Open button") } } // Loader // { // id: terminalLoader // visible: terminalVisible // focus: true // Layout.fillWidth: true // Layout.alignment: Qt.AlignBottom // Layout.minimumHeight: 100 // Layout.maximumHeight: 200 // // anchors.bottom: parent.bottom // // anchors.top: handle.bottom // source: !isMobile ? "Terminal.qml" : undefined // } } DocumentsView { id: _documentsView } } function openTab(path) { var component = Qt.createComponent("Editor.qml"); if (component.status === Component.Ready) { var object = component.createObject(tabsObjectModel); tabsObjectModel.append(object); } tabsListModel.append({ title: qsTr("Untitled"), path: path, }) _editorList.currentIndex = tabsObjectModel.count - 1 if(path && Maui.FM.fileExists(path)) { setTabMetadata(path) tabsObjectModel.get(tabsObjectModel.count - 1).document.load(path) browserView.openFolder(Maui.FM.fileDir(path)) } } function setTabMetadata(filepath) { tabsListModel.setProperty(_tabBar.currentIndex, "title", Maui.FM.getFileInfo(filepath).label) tabsListModel.setProperty(_tabBar.currentIndex, "path", filepath) } } diff --git a/src/models/documentsmodel.h b/src/models/documentsmodel.h index 1ab45eb..c149a63 100644 --- a/src/models/documentsmodel.h +++ b/src/models/documentsmodel.h @@ -1,50 +1,50 @@ #ifndef DOCUMENTSMODEL_H #define DOCUMENTSMODEL_H #include #include #ifdef STATIC_MAUIKIT #include "fmh.h" #include "mauilist.h" #else #include #include #endif class FileLoader : public QObject { Q_OBJECT public slots: void fetch(const QList &urls); signals: void resultReady(FMH::MODEL_LIST items); void itemReady(FMH::MODEL item); }; class DocumentsModel : public MauiList { Q_OBJECT QThread m_worker; public: DocumentsModel(QObject *parent = nullptr); - ~DocumentsModel(); + ~DocumentsModel() override; FMH::MODEL_LIST items() const override final; void componentComplete() override final; private: void setList(const FMH::MODEL_LIST &list); void append(const FMH::MODEL &item); FMH::MODEL_LIST m_list; signals: void start(QList urls); }; #endif // DOCUMENTSMODEL_H