diff --git a/src/controls/AbstractSideBar.qml b/src/controls/AbstractSideBar.qml index 1aa489e..7f950bf 100644 --- a/src/controls/AbstractSideBar.qml +++ b/src/controls/AbstractSideBar.qml @@ -1,119 +1,119 @@ /* * 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. */ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import "private" Drawer { id: control edge: Qt.LeftEdge implicitHeight: window().internalHeight height: implicitHeight y: (window().header ? window().header.height : 0) leftPadding: 100 // closePolicy: modal || collapsed ? Popup.CloseOnEscape | Popup.CloseOnPressOutside : Popup.NoAutoClose interactive: modal || collapsed || !visible dragMargin: Maui.Style.space.big modal: false property bool collapsible: false property bool collapsed: false property int collapsedSize: 0 property int preferredWidth : Kirigami.Units.gridUnit * 12 property alias overlay : _overlay onCollapsedChanged: position = (collapsed && collapsedSize < 1) ? 0 : 1 default property alias content : _content.data signal contentDropped(var drop) // background: null MouseArea { id: _overlay anchors.fill: parent anchors.margins: 0 anchors.leftMargin: (control.width * control.position) parent: window().contentItem preventStealing: true propagateComposedEvents: false visible: false Rectangle { color: Qt.rgba(control.Kirigami.Theme.backgroundColor.r,control.Kirigami.Theme.backgroundColor.g,control.Kirigami.Theme.backgroundColor.b, 0.5) opacity: control.position anchors.fill: parent } } // onVisibleChanged: // { // if(control.visible && !control.modal) // control.position = 1 // } contentItem: Item { id: _content anchors.fill: parent Kirigami.Separator { - z: control.z + 999 + z: parent.z + 999 anchors.right: parent.right anchors.top: parent.top anchors.bottom: parent.bottom } } Component.onCompleted: { if(!control.collapsed) { control.open() control.position = 1; } } Behavior on position { enabled: control.collapsible && control.position === 1 NumberAnimation { duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } opacity: _dropArea.containsDrag ? 0.5 : 1 DropArea { id: _dropArea anchors.fill: parent onDropped: { control.contentDropped(drop) } } } diff --git a/src/controls/labs/Page.qml b/src/controls/labs/Page.qml index a4c4187..9799e01 100644 --- a/src/controls/labs/Page.qml +++ b/src/controls/labs/Page.qml @@ -1,761 +1,761 @@ /* * Copyright 2019 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. */ import QtQuick 2.13 import QtQml 2.14 import QtQuick.Controls 2.13 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 Pane { id: control focus: true padding: 0 leftPadding: control.padding rightPadding: control.padding topPadding: control.padding bottomPadding: control.padding default property alias content: _content.data property alias headerBackground : _headerBackground readonly property alias internalHeight : _content.height property Flickable flickable : null property int footerPositioning : ListView.InlineFooter property int headerPositioning : Kirigami.Settings.isMobile && flickable ? ListView.PullBackHeader : ListView.InlineHeader property string title property int margins: 0 property int leftMargin : margins property int rightMargin: margins property int topMargin: margins property int bottomMargin: margins property bool altHeader : false property bool autoHideHeader : false property bool autoHideFooter : false property int autoHideHeaderMargins : Maui.Style.toolBarHeight property int autoHideFooterMargins : Maui.Style.toolBarHeight property int autoHideFooterDelay : 1000 property int autoHideHeaderDelay : 1000 property bool floatingHeader : control.flickable && control.flickable.contentHeight > control.height && !altHeader ? !_private.flickableAtStart : false property bool floatingFooter: control.flickable QtObject { id: _private property bool flickableAtStart : control.flickable ? true : true property int topMargin : !control.altHeader ? (control.floatingHeader ? 0 : _headerContent.height) : 0 property int bottomMargin: control.floatingFooter && control.footerPositioning === ListView.InlineFooter ? control.bottomMargin : control.bottomMargin + _footerContent.height -// Behavior on topMargin -// { -// enabled: control.header.visible && control.headerPositioning === ListView.InlineHeader -// NumberAnimation -// { -// duration: Kirigami.Units.shortDuration -// easing.type: Easing.InOutQuad -// } -// } + Behavior on topMargin + { + enabled: control.header.visible && control.headerPositioning === ListView.InlineHeader + NumberAnimation + { + duration: Kirigami.Units.shortDuration + easing.type: Easing.InOutQuad + } + } } Binding { delayed: false when: control.floatingFooter target: control.flickable property: "bottomMargin" value: control.flickable && control.footer.visible && control.footerPositioning === ListView.InlineFooter ? _footerContent.height : 0 restoreMode: Binding.RestoreBindingOrValue } Connections { target: control.flickable enabled: control.flickable && control.flickable.contentHeight > _content.height onAtYBeginningChanged: { if(control.headerPositioning !== ListView.InlineHeader || !control.header.visible || control.altHeader || control.flickable.contentHeight <= control.height) { return } if(control.flickable.atYBeginning && !control.floatingHeader) { return } if(!control.flickable.atYBeginning && control.floatingHeader) { return } if(_private.flickableAtStart === control.flickable.atYBeginning) { return } _private.flickableAtStart = flickable.atYBeginning console.log("AT START CHANGES", _private.flickableAtStart, control.flickable.atYBeginning, control.floatingHeader) } } property bool showTitle : true property alias headBar : _headBar property alias footBar: _footBar Kirigami.Theme.colorSet: Kirigami.Theme.View signal goBackTriggered() signal goForwardTriggered() background: Rectangle { color: Kirigami.Theme.backgroundColor } onFlickableChanged: { // control.flickable.bottomMargin += control.floatingFooter && control.footer.visible ? _footerContent.height : 0 returnToBounds() } Connections { target: control.flickable ? control.flickable : null enabled: control.flickable && ((control.header && control.headerPositioning === ListView.PullBackHeader) || (control.footer && control.footerPositioning === ListView.PullBackFooter)) property int oldContentY property bool updatingContentY: false onContentYChanged: { _headerAnimation.enabled = false _footerAnimation.enabled = false if(!control.flickable.dragging && control.flickable.atYBeginning) { control.returnToBounds() } if (updatingContentY || !control.flickable || !control.flickable.dragging) { oldContentY = control.flickable.contentY; return; //TODO: merge //if moves but not dragging, just update oldContentY } if(control.flickable.contentHeight < control.height) { return } var oldFHeight var oldHHeight if (control.footer && control.footerPositioning === ListView.PullBackFooter && control.footer.visible) { oldFHeight = control.footer.height control.footer.height = Math.max(0, Math.min(control.footer.implicitHeight, control.footer.height + oldContentY - control.flickable.contentY)); } if (control.header && control.headerPositioning === ListView.PullBackHeader && control.header.visible && !control.altHeader) { oldHHeight = control.header.height control.header.height = Math.max(0, Math.min(control.header.implicitHeight, control.header.height + oldContentY - control.flickable.contentY)); } //if the implicitHeight is changed, use that to simulate scroll if (control.header && oldHHeight !== control.header.height && control.header.visible && !control.altHeader) { updatingContentY = true control.flickable.contentY -= (oldHHeight - control.header.height) updatingContentY = false } else { oldContentY = control.flickable.contentY } } onMovementEnded: { if (control.header && control.header.visible && control.headerPositioning === ListView.PullBackHeader && !control.altHeader) { _headerAnimation.enabled = true if (control.header.height >= (control.header.implicitHeight/2) || control.flickable.atYBeginning ) { control.header.height = control.header.implicitHeight } else { control.header.height = 0 } } if (control.footer && control.footer.visible && control.footerPositioning === ListView.PullBackFooter) { _footerAnimation.enabled = true if (control.footer.height >= (control.footer.implicitHeight/2) || control.flickable.atYEnd) { if(control.flickable.atYEnd) { control.footer.height = control.footer.implicitHeight control.flickable.contentY = control.flickable.contentHeight - control.flickable.height oldContentY = control.flickable.contentY }else { control.footer.height = control.footer.implicitHeight } } else { control.footer.height = 0 } } } } /* Component.onCompleted: { if(control.header && control.header instanceof Maui.ToolBar) { control.header.visible = header.visibleCount > 0 } }*/ property Item header : Maui.ToolBar { id: _headBar visible: visibleCount > 0 width: visible ? parent.width : 0 height: visible ? implicitHeight : 0 Kirigami.Theme.inherit: false Kirigami.Theme.colorSet: Kirigami.Theme.Window /** to not break the visible binding just check the count state of the header and act upon it **/ // readonly property bool hide : visibleCount === 0 // onHideChanged: // { // if(!header.visible) // { // return // } // // if(hide) // { // pullBackHeader() // }else // { // pullDownHeader() // } // } // Label // { // visible: false // color: "yellow" // text: _headBar.visibleCount + " / " + _headBar.count + " - " + _headBar.height + " / " + header.height + " - " + _headBar.visible + " / " + header.visible // } Behavior on height { id: _headerAnimation enabled: false NumberAnimation { duration: Kirigami.Units.shortDuration easing.type: Easing.InOutQuad } } Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration easing.type: Easing.InOutQuad } } Component { id: _titleComponent Label { text: control.title elide : Text.ElideRight font.bold : false font.weight: Font.Bold color : Kirigami.Theme.textColor font.pointSize: Maui.Style.fontSizes.big horizontalAlignment : Text.AlignHCenter verticalAlignment : Text.AlignVCenter } } middleContent: Loader { visible: item Layout.fillWidth: sourceComponent === _titleComponent Layout.fillHeight: sourceComponent === _titleComponent sourceComponent: control.title && control.showTitle ? _titleComponent : null } background: Rectangle { id: _headerBackground color: _headBar.Kirigami.Theme.backgroundColor Kirigami.Separator { id: _border opacity: 0.6 color: Qt.darker(parent.color, 2) anchors.left: parent.left anchors.right: parent.right } Kirigami.Separator { id: _border2 opacity: 0.4 color: Qt.lighter(parent.color, 2.5) anchors.left: parent.left anchors.right: parent.right anchors.bottomMargin: 1 } FastBlur { anchors.fill: parent visible: control.floatingHeader && !altHeader opacity: 0.25 transparentBorder: false source: ShaderEffectSource { samples : 0 recursive: true sourceItem: _content sourceRect: Qt.rect(0, 0-control.topMargin, headBar.width, headBar.height) } radius: 64 } } } // Label // { // // visible: false // z: 999999999999 // color: "yellow" // text: _footBar.visibleCount + " / " + _footBar.count + " - " + _footBar.height + " / " + footer.height + " - " + _footBar.visible + " / " + footer.visible // } property Item footer : Maui.ToolBar { id: _footBar visible: visibleCount > 0 width: visible ? parent.width : 0 height: visible ? implicitHeight : 0 position: ToolBar.Footer Behavior on height { id: _footerAnimation enabled: false NumberAnimation { duration: Kirigami.Units.shortDuration easing.type: Easing.InOutQuad } } background: Rectangle { color: _footBar.Kirigami.Theme.backgroundColor Kirigami.Separator { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right } FastBlur { anchors.fill: parent visible: control.floatingFooter opacity: 0.4 transparentBorder: false source: ShaderEffectSource { samples : 0 recursive: true sourceItem: _content sourceRect: Qt.rect(0, control.height - (footBar.height), footBar.width, footBar.height) } radius: 64 } } } states: [ State { when: !altHeader && header.visible AnchorChanges { target: _headerContent anchors.top: parent.top anchors.bottom: undefined } AnchorChanges { target: _border anchors.top: undefined anchors.bottom: parent.bottom } AnchorChanges { target: _border2 anchors.top: undefined anchors.bottom: parent.bottom } PropertyChanges { target: _headBar position: ToolBar.Header } }, State { when: altHeader && header.visible AnchorChanges { target: _headerContent anchors.top: undefined anchors.bottom: parent.bottom } AnchorChanges { target: _border anchors.top: parent.top anchors.bottom: undefined } AnchorChanges { target: _border2 anchors.top: parent.top anchors.bottom: undefined } PropertyChanges { target: header height: header.implicitHeight } PropertyChanges { target: _headBar position: ToolBar.Footer } } ] onAutoHideHeaderChanged: pullDownHeader() onAutoHideFooterChanged: pullDownFooter() onAltHeaderChanged: pullDownHeader() Column { id: _headerContent anchors.left: parent.left anchors.right: parent.right children: header z: _content.z+1 } // Label // { // anchors.centerIn: _headerContent // text: header.height + "/" + _headerContent.height + " - " + _layout.anchors.topMargin // color: "orange" // z: _headerContent.z + 1 // visible: header.visible // } Item { id: _layout anchors.fill: parent anchors.bottomMargin: control.altHeader ? _headerContent.height : 0 anchors.topMargin: _private.topMargin Item { id: _content anchors.fill: parent anchors.margins: control.margins anchors.leftMargin: control.leftMargin anchors.rightMargin: control.rightMargin anchors.topMargin: control.topMargin anchors.bottomMargin: _private.bottomMargin } Column { id: _footerContent anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom children: footer } } Timer { id: _autoHideHeaderTimer interval: autoHideHeaderDelay onTriggered: { if(control.autoHideHeader && !control.altHeader) { pullBackHeader() } stop() } } Timer { id: _autoHideFooterTimer interval: control.autoHideFooterDelay onTriggered: { if(control.autoHideFooter) { pullBackFooter() } stop() } } Item { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right height: visible ? _headerContent.height + control.autoHideHeaderMargins : 0 z: _content.z +1 visible: control.autoHideHeader && !control.altHeader && !Kirigami.Settings.isMobile HoverHandler { target: parent acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus onHoveredChanged: { if(!control.autoHideHeader || control.altHeader) { _autoHideHeaderTimer.stop() return } if(!hovered) { _autoHideHeaderTimer.start() }else { pullDownHeader() _autoHideHeaderTimer.stop() } } } } Item { anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right height: visible ? _footerContent.height + control.autoHideFooterMargins : 0 z: _footerContent.z - 1 visible: control.autoHideFooter && !control.altHeader && !Kirigami.Settings.isMobile HoverHandler { target: parent acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus onHoveredChanged: { if(!control.autoHideFooter) { return } if(!hovered) { _autoHideFooterTimer.start() }else { pullDownFooter() _autoHideFooterTimer.stop() } } } } // Item // { // anchors.fill: parent // anchors.topMargin: header.height // anchors.bottomMargin: footer.height // z: _content.z + 9999 // // TapHandler // { // target: parent // enabled: control.autoHideHeader && !control.altHeader // // grabPermissions: PointerHandler.TakeOverForbidden | PointerHandler.ApprovesTakeOverByHandlersOfSameType | PointerHandler.CanTakeOverFromAnything // // onSingleTapped: // { // if(!control.autoHideHeader) // { // return // } // console.log("Pgae tapped") // header.visible = !header.visible // } // } // } Keys.onBackPressed: { control.goBackTriggered(); } Shortcut { sequence: "Forward" onActivated: control.goForwardTriggered(); } Shortcut { sequence: StandardKey.Forward onActivated: control.goForwardTriggered(); } Shortcut { sequence: StandardKey.Back onActivated: control.goBackTriggered(); } function returnToBounds() { if(control.header) { pullDownHeader() } if(control.footer) { pullDownFooter() } } function pullBackHeader() { _headerAnimation.enabled = true header.height= 0 } function pullDownHeader() { _headerAnimation.enabled = true header.height = header.implicitHeight } function pullBackFooter() { _footerAnimation.enabled = true footer.height= 0 } function pullDownFooter() { _footerAnimation.enabled = true footer.height = footer.implicitHeight } } diff --git a/src/fm/fm.cpp b/src/fm/fm.cpp index 225d9df..d1302a7 100644 --- a/src/fm/fm.cpp +++ b/src/fm/fm.cpp @@ -1,479 +1,480 @@ /* * 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 "fm.h" #ifdef COMPONENT_TAGGING #include "tagging.h" #endif #ifdef COMPONENT_SYNCING #include "syncing.h" #endif #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_OS_ANDROID) #include "mauiandroid.h" #elif defined Q_OS_LINUX #include "mauikde.h" #include #include #include #include #include #include #include #include #endif QDirLister::QDirLister(QObject* parent) : QObject(parent) {} bool QDirLister::openUrl(QUrl url) { qDebug() << "GET FILES <<" << m_nameFilters.split(" "); FMH::MODEL_LIST content; if (FMStatic::isDir(url)) { QDir::Filters dirFilter; dirFilter = (m_dirOnly ? QDir::AllDirs | QDir::NoDotDot | QDir::NoDot : QDir::Files | QDir::AllDirs | QDir::NoDotDot | QDir::NoDot); if(m_showDotFiles) dirFilter = dirFilter | QDir::Hidden | QDir::System; QDirIterator it (url.toLocalFile(), m_nameFilters.isEmpty() ? QStringList() : m_nameFilters.split(" "), dirFilter, QDirIterator::NoIteratorFlags); while (it.hasNext()) { const auto item = FMH::getFileInfoModel(QUrl::fromLocalFile(it.next())); content << item; emit itemReady(item, url); } } else return false; emit itemsReady(content, url); return true; } void QDirLister::setDirOnlyMode(bool value) { m_dirOnly = value; } void QDirLister::setShowingDotFiles(bool value) { m_showDotFiles = value; } void QDirLister::setNameFilter(QString filters) { m_nameFilters = filters; } FM::FM(QObject *parent) : QObject(parent) #ifdef COMPONENT_SYNCING ,sync(new Syncing(this)) #endif #ifdef COMPONENT_TAGGING ,tag(Tagging::getInstance()) #endif #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) ,dirLister( new KCoreDirLister(this)) #else ,dirLister( new QDirLister) #endif { #ifdef Q_OS_ANDROID MAUIAndroid::checkRunTimePermissions({"android.permission.WRITE_EXTERNAL_STORAGE"}); #endif #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) this->dirLister->setAutoUpdate(true); const static auto packItem = [](const KFileItem &kfile) -> FMH::MODEL { return FMH::MODEL{ {FMH::MODEL_KEY::LABEL, kfile.name()}, {FMH::MODEL_KEY::NAME, kfile.name()}, {FMH::MODEL_KEY::DATE, kfile.time(KFileItem::FileTimes::CreationTime).toString(Qt::TextDate)}, {FMH::MODEL_KEY::MODIFIED, kfile.time(KFileItem::FileTimes::ModificationTime).toString(Qt::TextDate)}, {FMH::MODEL_KEY::LAST_READ, kfile.time(KFileItem::FileTimes::AccessTime).toString(Qt::TextDate)}, {FMH::MODEL_KEY::PATH, kfile.mostLocalUrl().toString()}, {FMH::MODEL_KEY::THUMBNAIL, kfile.localPath()}, {FMH::MODEL_KEY::SYMLINK, kfile.linkDest()}, {FMH::MODEL_KEY::IS_SYMLINK, QVariant(kfile.isLink()).toString()}, {FMH::MODEL_KEY::HIDDEN, QVariant(kfile.isHidden()).toString()}, {FMH::MODEL_KEY::IS_DIR, QVariant(kfile.isDir()).toString()}, {FMH::MODEL_KEY::IS_FILE, QVariant(kfile.isFile()).toString()}, {FMH::MODEL_KEY::WRITABLE, QVariant(kfile.isWritable()).toString()}, {FMH::MODEL_KEY::READABLE, QVariant(kfile.isReadable()).toString()}, {FMH::MODEL_KEY::EXECUTABLE, QVariant(kfile.isDesktopFile()).toString()}, {FMH::MODEL_KEY::MIME, kfile.mimetype()}, {FMH::MODEL_KEY::GROUP, kfile.group()}, {FMH::MODEL_KEY::ICON, kfile.iconName()}, {FMH::MODEL_KEY::SIZE, QString::number(kfile.size())}, {FMH::MODEL_KEY::THUMBNAIL, kfile.mostLocalUrl().toString()}, {FMH::MODEL_KEY::OWNER, kfile.user()}, // {FMH::MODEL_KEY::FAVORITE, QVariant(this->urlTagExists(kfile.mostLocalUrl().toString(), "fav")).toString()}, {FMH::MODEL_KEY::COUNT, kfile.isLocalFile() && kfile.isDir() ? QString::number(QDir(kfile.localPath()).count() - 2) : "0"} }; }; const static auto packItems = [](const KFileItemList &items) -> FMH::MODEL_LIST { return std::accumulate(items.constBegin(), items.constEnd(), FMH::MODEL_LIST(), [](FMH::MODEL_LIST &res, const KFileItem &item) ->FMH::MODEL_LIST { res << packItem(item); return res; }); }; connect(dirLister, static_cast(&KCoreDirLister::completed), this, [&](QUrl url) { qDebug()<< "PATH CONTENT READY" << url; emit this->pathContentReady(url); }); connect(dirLister, static_cast(&KCoreDirLister::itemsAdded), this, [&](QUrl dirUrl, KFileItemList items) { qDebug()<< "MORE ITEMS WERE ADDED"; emit this->pathContentItemsReady({dirUrl, packItems(items)}); }); // connect(dirLister, static_cast(&KCoreDirLister::newItems), [&](KFileItemList items) // { // qDebug()<< "MORE NEW ITEMS WERE ADDED"; // for(const auto &item : items) // qDebug()<< "MORE <<" << item.url(); // // emit this->pathContentChanged(dirLister->url()); // }); connect(dirLister, static_cast(&KCoreDirLister::itemsDeleted), this, [&](KFileItemList items) { qDebug()<< "ITEMS WERE DELETED"; emit this->pathContentItemsRemoved({dirLister->url(), packItems(items)}); }); connect(dirLister, static_cast > &items)>(&KCoreDirLister::refreshItems), this, [&](QList< QPair< KFileItem, KFileItem > > items) { qDebug()<< "ITEMS WERE REFRESHED"; const auto res = std::accumulate(items.constBegin(), items.constEnd(), QVector>(), [](QVector> &list, const QPair &pair) -> QVector> { list << QPair{packItem(pair.first), packItem(pair.second)}; return list; }); emit this->pathContentItemsChanged(res); }); #else connect(dirLister, &QDirLister::itemReady, this, [&](FMH::MODEL item, QUrl url) { emit this->pathContentItemsReady(FMH::PATH_CONTENT {url, {item}}); }); connect(dirLister, &QDirLister::itemsReady, this, [&](FMH::MODEL_LIST, QUrl url) { emit this->pathContentReady(url); }); #endif #ifdef COMPONENT_SYNCING connect(this->sync, &Syncing::listReady, [this](const FMH::MODEL_LIST &list, const QUrl &url) { emit this->cloudServerContentReady(list, url); }); connect(this->sync, &Syncing::itemReady, [this](const FMH::MODEL &item, const QUrl &url, const Syncing::SIGNAL_TYPE &signalType) { switch(signalType) { case Syncing::SIGNAL_TYPE::OPEN: FMStatic::openUrl(item[FMH::MODEL_KEY::PATH]); break; case Syncing::SIGNAL_TYPE::DOWNLOAD: emit this->cloudItemReady(item, url); break; case Syncing::SIGNAL_TYPE::COPY: { QVariantMap data; for(auto key : item.keys()) data.insert(FMH::MODEL_NAME[key], item[key]); // this->copy(QVariantList {data}, this->sync->getCopyTo()); break; } default: return; } }); connect(this->sync, &Syncing::error, [this](const QString &message) { emit this->warningMessage(message); }); connect(this->sync, &Syncing::progress, [this](const int &percent) { emit this->loadProgress(percent); }); connect(this->sync, &Syncing::dirCreated, [this](const FMH::MODEL &dir, const QUrl &url) { emit this->newItem(dir, url); }); connect(this->sync, &Syncing::uploadReady, [this](const FMH::MODEL &item, const QUrl &url) { emit this->newItem(item, url); }); #endif } void FM::getPathContent(const QUrl& path, const bool &hidden, const bool &onlyDirs, const QStringList& filters, const QDirIterator::IteratorFlags &iteratorFlags) { qDebug()<< "Getting async path contents"; this->dirLister->setShowingDotFiles(hidden); this->dirLister->setDirOnlyMode(onlyDirs); this->dirLister->setNameFilter(filters.join(" ")); if(this->dirLister->openUrl(path)) qDebug()<< "GETTING PATH CONTENT" << path; } FMH::MODEL_LIST FM::getAppsPath() { #if defined Q_OS_ANDROID || defined Q_OS_WIN32 || defined Q_OS_MACOS || defined Q_OS_IOS //for android, windows and mac use this for now return FMH::MODEL_LIST(); #else return FMH::MODEL_LIST { FMH::MODEL { {FMH::MODEL_KEY::ICON, "system-run"}, {FMH::MODEL_KEY::LABEL, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::APPS_PATH]}, {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::APPS_PATH]}, {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]} } }; #endif } FMH::MODEL_LIST FM::getTags(const int &limit) { Q_UNUSED(limit); FMH::MODEL_LIST data; #ifdef COMPONENT_TAGGING if(this->tag) { for(const auto &tag : this->tag->getAllTags(false)) { - QVariantMap item = tag.toMap(); + const QVariantMap item = tag.toMap(); const auto label = item.value(TAG::KEYMAP[TAG::KEYS::TAG]).toString(); + data << FMH::MODEL { {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::TAGS_PATH]+label}, - {FMH::MODEL_KEY::ICON, "tag"}, + {FMH::MODEL_KEY::ICON, item.value(TAG::KEYMAP[TAG::KEYS::ICON], "tag").toString()}, {FMH::MODEL_KEY::MODIFIED, QDateTime::fromString(item.value(TAG::KEYMAP[TAG::KEYS::ADD_DATE]).toString(), Qt::TextDate).toString()}, {FMH::MODEL_KEY::IS_DIR, "true"}, {FMH::MODEL_KEY::LABEL, label}, {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::TAGS_PATH]} }; } } #endif return data; } bool FM::getCloudServerContent(const QUrl &path, const QStringList &filters, const int &depth) { #ifdef COMPONENT_SYNCING const auto __list = path.toString().replace("cloud:///", "/").split("/"); if(__list.isEmpty() || __list.size() < 2) { qWarning()<< "Could not parse username to get cloud server content"; return false; } auto user = __list[1]; // auto data = this->get(QString("select * from clouds where user = '%1'").arg(user)); QVariantList data; if(data.isEmpty()) return false; auto map = data.first().toMap(); user = map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString(); auto server = map[FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER]].toString(); auto password = map[FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD]].toString(); this->sync->setCredentials(server, user, password); this->sync->listContent(path, filters, depth); return true; #else return false; #endif } void FM::createCloudDir(const QString &path, const QString &name) { #ifdef COMPONENT_SYNCING this->sync->createDir(path, name); #endif } void FM::openCloudItem(const QVariantMap &item) { #ifdef COMPONENT_SYNCING FMH::MODEL data; for(const auto &key : item.keys()) data.insert(FMH::MODEL_NAME_KEY[key], item[key].toString()); this->sync->resolveFile(data, Syncing::SIGNAL_TYPE::OPEN); #endif } void FM::getCloudItem(const QVariantMap &item) { #ifdef COMPONENT_SYNCING this->sync->resolveFile(FMH::toModel(item), Syncing::SIGNAL_TYPE::DOWNLOAD); #endif } QString FM::resolveUserCloudCachePath(const QString &server, const QString &user) { return FMH::CloudCachePath+"opendesktop/"+user; } QString FM::resolveLocalCloudPath(const QString& path) { #ifdef COMPONENT_SYNCING return QString(path).replace(FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::CLOUD_PATH]+this->sync->getUser(), ""); #else return QString(); #endif } FMH::MODEL_LIST FM::getTagContent(const QString &tag, const QStringList &filters) { FMH::MODEL_LIST content; #ifdef COMPONENT_TAGGING if(tag.isEmpty()) { return this->getTags(); }else { for(const auto &url : FMStatic::getTagUrls(tag, filters, false)) { content << FMH::getFileInfoModel(url); } } #endif return content; } FMH::MODEL_LIST FM::getUrlTags(const QUrl &url) { FMH::MODEL_LIST content; #ifdef COMPONENT_TAGGING content = FMH::toModelList(this->tag->getUrlTags(url.toString(), false)); #endif return content; } bool FM::urlTagExists(const QUrl& url, const QString tag) { #ifdef COMPONENT_TAGGING return this->tag->urlTagExists(url.toString(), tag, false); #endif } bool FM::addTagToUrl(const QString tag, const QUrl& url) { #ifdef COMPONENT_TAGGING return this->tag->tagUrl(url.toString(), tag); #endif } bool FM::removeTagToUrl(const QString tag, const QUrl& url) { #ifdef COMPONENT_TAGGING return this->tag->removeUrlTag(url.toString(), tag); #endif } bool FM::cut(const QList &urls, const QUrl &where) { return FMStatic::cut(urls, where); } bool FM::copy(const QList &urls, const QUrl &where) { // QStringList cloudPaths; return FMStatic::copy(urls, where, false); #ifdef COMPONENT_SYNCING // if(!cloudPaths.isEmpty()) // { // qDebug()<<"UPLOAD QUEUE" << cloudPaths; // const auto firstPath = cloudPaths.takeLast(); // this->sync->setUploadQueue(cloudPaths); // // if(where.toString().split("/").last().contains(".")) // { // QStringList whereList = where.toString().split("/"); // whereList.removeLast(); // auto whereDir = whereList.join("/"); // qDebug()<< "Trying ot copy to cloud" << where << whereDir; // // this->sync->upload(this->resolveLocalCloudPath(whereDir), firstPath); // } else // this->sync->upload(this->resolveLocalCloudPath(where.toString()), firstPath); // } #endif } diff --git a/src/utils/tagging/tag.h b/src/utils/tagging/tag.h index 57ef4b0..17a55e2 100644 --- a/src/utils/tagging/tag.h +++ b/src/utils/tagging/tag.h @@ -1,127 +1,130 @@ /* * 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. */ #ifndef TAG_H #define TAG_H #include #include #include #include #include #include #include #include #include namespace TAG { enum class TABLE : uint8_t { USERS, TAGS_USERS, APPS_USERS, TAGS, TAGS_URLS, APPS, ABSTRACT, TAGS_ABSTRACT, NONE }; static const QMap TABLEMAP = { {TABLE::TAGS, "tags"}, {TABLE::TAGS_URLS,"tags_urls"}, {TABLE::USERS, "users"}, {TABLE::TAGS_USERS,"tags_users"}, {TABLE::APPS, "apps"}, {TABLE::ABSTRACT,"abstract"}, {TABLE::TAGS_ABSTRACT, "tags_abstract"}, {TABLE::APPS_USERS,"apps_users"} }; enum KEYS : uint_fast8_t { URL, + ICON, APP, URI, MAC, LAST_SYNC, NAME, VERSION, LOT, TAG, COLOR, ADD_DATE, COMMENT, MIME, TITLE, DEVICE, KEY };/* Q_ENUM_NS(KEYS);*/ typedef QMap DB; typedef QList DB_LIST; static const DB KEYMAP = { {TAG::KEYS::URL, "url"}, {TAG::KEYS::TAG, "tag"}, + {TAG::KEYS::ICON, "icon"}, {TAG::KEYS::COLOR, "color"}, {TAG::KEYS::ADD_DATE, "addDate"}, {TAG::KEYS::COMMENT, "comment"}, {TAG::KEYS::MIME, "mime"}, {TAG::KEYS::TITLE, "title"}, {TAG::KEYS::NAME, "name"}, {TAG::KEYS::DEVICE, "device"}, {TAG::KEYS::MAC, "mac"}, {TAG::KEYS::LAST_SYNC, "lastSync"}, {TAG::KEYS::LOT, "lot"}, {TAG::KEYS::KEY, "key"}, {TAG::KEYS::APP, "app"}, {TAG::KEYS::URI, "uri"}, {TAG::KEYS::VERSION, "version"} }; static const QMap MAPKEY = { {TAG::KEYMAP[KEYS::URL], KEYS::URL}, {TAG::KEYMAP[KEYS::TAG], KEYS::TAG}, + {TAG::KEYMAP[KEYS::ICON], KEYS::ICON}, {TAG::KEYMAP[KEYS::COLOR], KEYS::COLOR}, {TAG::KEYMAP[KEYS::ADD_DATE], KEYS::ADD_DATE}, {TAG::KEYMAP[KEYS::COMMENT], KEYS::COMMENT}, {TAG::KEYMAP[KEYS::MIME], KEYS::MIME}, {TAG::KEYMAP[KEYS::TITLE], KEYS::TITLE}, {TAG::KEYMAP[KEYS::NAME], KEYS::NAME}, {TAG::KEYMAP[KEYS::DEVICE], KEYS::DEVICE}, {TAG::KEYMAP[KEYS::MAC], KEYS::MAC}, {TAG::KEYMAP[KEYS::LAST_SYNC], KEYS::LAST_SYNC}, {TAG::KEYMAP[KEYS::LOT], KEYS::LOT}, {TAG::KEYMAP[KEYS::KEY], KEYS::KEY}, {TAG::KEYMAP[KEYS::APP], KEYS::APP}, {TAG::KEYMAP[KEYS::URI], KEYS::URI}, {TAG::KEYMAP[KEYS::VERSION], KEYS::VERSION} }; const QString TaggingPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/maui/tagging/"; const QString DBName = "tagging.db"; } #endif // TAG_H diff --git a/src/utils/tagging/tagging.cpp b/src/utils/tagging/tagging.cpp index 50c86b3..f63ab82 100644 --- a/src/utils/tagging/tagging.cpp +++ b/src/utils/tagging/tagging.cpp @@ -1,359 +1,365 @@ /* * 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 "tagging.h" #include #include #include "utils.h" Tagging::Tagging() : TAGDB() { this->setApp(); } const QVariantList Tagging::get(const QString &queryTxt, std::function modifier) { QVariantList mapList; auto query = this->getQuery(queryTxt); if(query.exec()) { while(query.next()) { QVariantMap data; for(const auto &key : TAG::KEYMAP.keys()) { if(query.record().indexOf(TAG::KEYMAP[key]) > -1) data[TAG::KEYMAP[key]] = query.value(TAG::KEYMAP[key]).toString(); } if(modifier) { if(!modifier(data)) continue; } mapList<< data; } }else qDebug()<< query.lastError()<< query.lastQuery(); return mapList; } bool Tagging::tagExists(const QString &tag, const bool &strict) { return !strict ? this->checkExistance(TAG::TABLEMAP[TAG::TABLE::TAGS], TAG::KEYMAP[TAG::KEYS::TAG], tag) : this->checkExistance(QString("select t.tag from TAGS t inner join TAGS_USERS tu on t.tag = tu.tag inner join APPS_USERS au on au.mac = tu.mac " "where au.app = '%1' and au.uri = '%2' and t.tag = '%3'").arg(this->application, this->uri, tag)); } bool Tagging::urlTagExists(const QString &url,const QString &tag, const bool &strict) { return !strict ? this->checkExistance(QString("select * from TAGS_URLS where url = '%1' and tag = '%2'").arg(url, tag)) : this->checkExistance(QString("select t.tag from TAGS t inner join TAGS_USERS tu on t.tag = tu.tag inner join APPS_USERS au on au.mac = tu.mac " "where au.app = '%1' and au.uri = '%2' and t.tag = '%3'").arg(this->application, this->uri, tag)); } void Tagging::setApp() { this->application = UTIL::app->applicationName(); this->version = UTIL::app->applicationVersion(); this->comment = QString(); this->uri = UTIL::app->organizationDomain().isEmpty() ? QString("org.maui.%1").arg(this->application) : UTIL::app->organizationDomain(); this->app(); //here register the app } bool Tagging::tag(const QString &tag, const QString &color, const QString &comment) { if(tag.isEmpty()) return false; QVariantMap tag_map { {TAG::KEYMAP[TAG::KEYS::TAG], tag}, {TAG::KEYMAP[TAG::KEYS::APP], this->application}, {TAG::KEYMAP[TAG::KEYS::COLOR], color}, {TAG::KEYMAP[TAG::KEYS::ADD_DATE], QDateTime::currentDateTime().toString(Qt::TextDate)}, {TAG::KEYMAP[TAG::KEYS::COMMENT], comment}, }; this->insert(TAG::TABLEMAP[TAG::TABLE::TAGS], tag_map); QVariantMap tag_user_map { {TAG::KEYMAP[TAG::KEYS::TAG], tag}, {TAG::KEYMAP[TAG::KEYS::MAC], this->id()} }; if(this->insert(TAG::TABLEMAP[TAG::TABLE::TAGS_USERS], tag_user_map)) { emit this->tagged(tag); return true; } return false; } bool Tagging::tagUrl(const QString &url, const QString &tag, const QString &color, const QString &comment) { auto myTag = tag.trimmed(); this->tag(myTag, color, comment); QMimeDatabase mimedb; auto mime = mimedb.mimeTypeForFile(url); QVariantMap tag_url_map { {TAG::KEYMAP[TAG::KEYS::URL], url}, {TAG::KEYMAP[TAG::KEYS::TAG], myTag}, {TAG::KEYMAP[TAG::KEYS::TITLE], QFileInfo(url).baseName()}, {TAG::KEYMAP[TAG::KEYS::MIME], mime.name()}, {TAG::KEYMAP[TAG::KEYS::ADD_DATE], QDateTime::currentDateTime()}, {TAG::KEYMAP[TAG::KEYS::COMMENT], comment} }; emit this->urlTagged(url, myTag); return this->insert(TAG::TABLEMAP[TAG::TABLE::TAGS_URLS], tag_url_map); } bool Tagging::tagAbstract(const QString &tag, const QString &key, const QString &lot, const QString &color, const QString &comment) { this->abstract(key, lot, comment); this->tag(tag, color, comment); QVariantMap tag_abstract_map { {TAG::KEYMAP[TAG::KEYS::APP], this->application}, {TAG::KEYMAP[TAG::KEYS::URI], this->uri}, {TAG::KEYMAP[TAG::KEYS::TAG], tag}, {TAG::KEYMAP[TAG::KEYS::KEY], key}, {TAG::KEYMAP[TAG::KEYS::LOT], lot}, {TAG::KEYMAP[TAG::KEYS::ADD_DATE], QDateTime::currentDateTime()}, {TAG::KEYMAP[TAG::KEYS::COMMENT], comment}, }; emit this->abstractTagged(key, lot, tag); return this->insert(TAG::TABLEMAP[TAG::TABLE::TAGS_ABSTRACT], tag_abstract_map); } bool Tagging::updateUrlTags(const QString &url, const QStringList &tags) { this->removeUrlTags(url); for(const auto &tag : tags) this->tagUrl(url, tag); return true; } bool Tagging::updateUrl(const QString& url, const QString& newUrl) { return this->update(TAG::TABLEMAP[TAG::TABLE::TAGS_URLS], {{TAG::KEYS::URL, newUrl}}, {{TAG::KEYMAP[TAG::KEYS::URL], url}}); } bool Tagging::updateAbstractTags(const QString &key, const QString &lot, const QStringList &tags) { this->removeAbstractTags(key, lot); for(const auto &tag : tags) this->tagAbstract(tag, key, lot); return true; } QVariantList Tagging::getUrlsTags(const bool &strict) { const auto query = QString("select distinct t.* from TAGS t inner join TAGS_USERS tu on t.tag = tu.tag " "inner join APPS_USERS au on au.mac = tu.mac " "inner join TAGS_URLS turl on turl.tag = t.tag " "where au.app = '%1' and au.uri = '%2'").arg(this->application, this->uri); return !strict ? this->get("select distinct t.* from tags t inner join TAGS_URLS turl on turl.tag = t.tag") : this->get(query); } QVariantList Tagging::getAbstractsTags(const bool &strict) { return !strict ? this->get("select t.* from tags t inner join TAGS_ABSTRACT tab on tab.tag = t.tag") : this->get(QString("select t.* from TAGS t inner join TAGS_USERS tu on t.tag = tu.tag " "inner join APPS_USERS au on au.mac = tu.mac " "inner join TAGS_ABSTRACT tab on tab.tag = t.tag " "where au.app = '%1' and au.uri = '%2'").arg(this->application, this->uri)); } +static bool setTagIconName(QVariantMap &item) +{ + item.insert("icon", item.value("tag").toString() == "fav" ? "love" : "tag"); + return true; +} + QVariantList Tagging::getAllTags(const bool &strict) { - return !strict ? this->get("select * from tags group by tag") : + return !strict ? this->get("select * from tags group by tag", &setTagIconName) : this->get(QString("select t.* from TAGS t inner join TAGS_USERS tu on t.tag = tu.tag inner join APPS_USERS au on au.mac = tu.mac and au.app = t.app " - "where au.app = '%1' and au.uri = '%2'").arg(this->application, this->uri)); + "where au.app = '%1' and au.uri = '%2'").arg(this->application, this->uri), &setTagIconName); } QVariantList Tagging::getUrls(const QString &tag, const bool &strict, std::function modifier) { return !strict ? this->get(QString("select distinct * from TAGS_URLS where tag = '%1'").arg(tag), modifier): this->get(QString("select distinct turl.*, t.color, t.comment as tagComment from TAGS t " "inner join TAGS_USERS tu on t.tag = tu.tag " "inner join APPS_USERS au on au.mac = tu.mac and au.app = t.app " "inner join TAGS_URLS turl on turl.tag = t.tag " "where au.app = '%1' and au.uri = '%2' " "and t.tag = '%3'").arg(this->application, this->uri, tag), modifier); } QVariantList Tagging::getUrlTags(const QString &url, const bool &strict) { return !strict ? this->get(QString("select distinct turl.*, t.color, t.comment as tagComment from tags t inner join TAGS_URLS turl on turl.tag = t.tag where turl.url = '%1'").arg(url)) : this->get(QString("select distinct t.* from TAGS t inner join TAGS_USERS tu on t.tag = tu.tag inner join APPS_USERS au on au.mac = tu.mac and au.app = t.app inner join TAGS_URLS turl on turl.tag = t.tag " "where au.app = '%1' and au.uri = '%2' and turl.url = '%3'").arg(this->application, this->uri, url)); } QVariantList Tagging::getAbstractTags(const QString &key, const QString &lot, const bool &strict) { return !strict ? this->get(QString("select t.* from TAGS t inner join TAGS_ABSTRACT ta on ta.tag = t.tag where ta.key = '%1' and ta.lot = '%2'").arg(key, lot)) : this->get(QString("select distinct t.* from TAGS t inner join TAGS_ABSTRACT ta on ta.tag = t.tag " "inner join TAGS_USERS tu on t.tag = tu.tag " "inner join APPS_USERS au on au.mac = tu.mac " "where au.app = '%1' and au.uri = '%2' and ta.key = '%3' and ta.lot = '%4'").arg(this->application, this->uri, key, lot)); } bool Tagging::removeAbstractTag(const QString& key, const QString& lot, const QString &tag) { TAG::DB data {{TAG::KEYS::KEY, key}, {TAG::KEYS::LOT, lot}, {TAG::KEYS::TAG, tag}}; return this->remove(TAG::TABLEMAP[TAG::TABLE::TAGS_ABSTRACT], data); } bool Tagging::removeAbstractTags(const QString& key, const QString& lot) { for(const auto &map : this->getAbstractTags(key, lot)) { auto tag = map.toMap().value(TAG::KEYMAP[TAG::KEYS::TAG]).toString(); this->removeAbstractTag(key, lot, tag); } return true; } bool Tagging::removeUrlTags(const QString &url) { for(const auto &map : this->getUrlTags(url)) { auto tag = map.toMap().value(TAG::KEYMAP[TAG::KEYS::TAG]).toString(); this->removeUrlTag(url, tag); } return true; } bool Tagging::removeUrlTag(const QString& url, const QString& tag) { TAG::DB data {{TAG::KEYS::URL, url}, {TAG::KEYS::TAG, tag}}; return this->remove(TAG::TABLEMAP[TAG::TABLE::TAGS_URLS], data); } bool Tagging::removeUrl(const QString &url) { return this->remove(TAG::TABLEMAP[TAG::TABLE::TAGS_URLS], {{TAG::KEYS::URL, url}}); } QString Tagging::mac() { QNetworkInterface mac; qDebug()<< "MAC ADDRES:"<< mac.hardwareAddress(); return mac.hardwareAddress(); } QString Tagging::device() { return QSysInfo::prettyProductName(); } QString Tagging::id() { return QSysInfo::machineHostName(); // qDebug()<< "VERSION IS LES THAN "<< QT_VERSION; //#if QT_VERSION < QT_VERSION_CHECK(5, 1, 1) // return QSysInfo::machineHostName(); //#else // return QString(QSysInfo::machineUniqueId()); //#endif } bool Tagging::app() { qDebug()<<"REGISTER APP" << this->application<< this->uri<< this->version<< this->comment; QVariantMap app_map { {TAG::KEYMAP[TAG::KEYS::APP], this->application}, {TAG::KEYMAP[TAG::KEYS::URI], this->uri}, {TAG::KEYMAP[TAG::KEYS::VERSION], this->version}, {TAG::KEYMAP[TAG::KEYS::ADD_DATE], QDateTime::currentDateTime()}, {TAG::KEYMAP[TAG::KEYS::COMMENT], this->comment}, }; this->insert(TAG::TABLEMAP[TAG::TABLE::APPS], app_map); this->user(); QVariantMap users_apps_map { {TAG::KEYMAP[TAG::KEYS::APP], this->application}, {TAG::KEYMAP[TAG::KEYS::URI], this->uri}, {TAG::KEYMAP[TAG::KEYS::MAC], this->id()}, {TAG::KEYMAP[TAG::KEYS::ADD_DATE], QDateTime::currentDateTime()}, }; return this->insert(TAG::TABLEMAP[TAG::TABLE::APPS_USERS], users_apps_map); } bool Tagging::user() { QVariantMap user_map { {TAG::KEYMAP[TAG::KEYS::MAC], this->id()}, {TAG::KEYMAP[TAG::KEYS::NAME], UTIL::whoami()}, {TAG::KEYMAP[TAG::KEYS::LAST_SYNC], QDateTime::currentDateTime()}, {TAG::KEYMAP[TAG::KEYS::ADD_DATE], QDateTime::currentDateTime()}, {TAG::KEYMAP[TAG::KEYS::DEVICE], this->device()}, }; return this->insert(TAG::TABLEMAP[TAG::TABLE::USERS], user_map); } bool Tagging::abstract(const QString &key, const QString &lot, const QString &comment) { QVariantMap abstract_map { {TAG::KEYMAP[TAG::KEYS::APP], this->application}, {TAG::KEYMAP[TAG::KEYS::URI], this->uri}, {TAG::KEYMAP[TAG::KEYS::KEY], key}, {TAG::KEYMAP[TAG::KEYS::LOT], lot}, {TAG::KEYMAP[TAG::KEYS::ADD_DATE], QDateTime::currentDateTime()}, {TAG::KEYMAP[TAG::KEYS::COMMENT], comment}, }; return this->insert(TAG::TABLEMAP[TAG::TABLE::ABSTRACT], abstract_map); }