Quick GUI: Allow filtering entries
So far all operations on entries are disabled when in filtered state and switching between normal and filtered view invalidates the stack.
This commit is contained in:
parent
c3775775d1
commit
fa050a422a
|
@ -1,6 +1,8 @@
|
|||
#include "./entryfiltermodel.h"
|
||||
#include "./entrymodel.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
/*!
|
||||
|
@ -15,9 +17,43 @@ namespace QtGui {
|
|||
*/
|
||||
EntryFilterModel::EntryFilterModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, m_sourceModel(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool EntryFilterModel::isNode(const QModelIndex &parent) const
|
||||
{
|
||||
return m_sourceModel->isNode(mapToSource(parent));
|
||||
}
|
||||
|
||||
void EntryFilterModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
if (!sourceModel) {
|
||||
QSortFilterProxyModel::setSourceModel(sourceModel);
|
||||
m_sourceModel = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
auto *const entryModel = qobject_cast<EntryModel *>(sourceModel);
|
||||
assert(entryModel);
|
||||
QSortFilterProxyModel::setSourceModel(sourceModel);
|
||||
m_sourceModel = entryModel;
|
||||
}
|
||||
|
||||
void EntryFilterModel::setInsertTypeToNode()
|
||||
{
|
||||
if (m_sourceModel) {
|
||||
m_sourceModel->setInsertTypeToNode();
|
||||
}
|
||||
}
|
||||
|
||||
void EntryFilterModel::setInsertTypeToAccount()
|
||||
{
|
||||
if (m_sourceModel) {
|
||||
m_sourceModel->setInsertTypeToAccount();
|
||||
}
|
||||
}
|
||||
|
||||
bool EntryFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
// just use default implementation
|
||||
|
|
|
@ -5,17 +5,26 @@
|
|||
|
||||
namespace QtGui {
|
||||
|
||||
class EntryModel;
|
||||
|
||||
class EntryFilterModel : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EntryFilterModel(QObject *parent = nullptr);
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
Q_INVOKABLE bool isNode(const QModelIndex &parent) const;
|
||||
Q_INVOKABLE void setInsertTypeToNode();
|
||||
Q_INVOKABLE void setInsertTypeToAccount();
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
private:
|
||||
bool hasAcceptedChildren(const QModelIndex &index) const;
|
||||
|
||||
EntryModel *m_sourceModel;
|
||||
};
|
||||
|
||||
} // namespace QtGui
|
||||
|
||||
#endif // ENTRYFILTERMODEL_H
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
explicit EntryModel(QUndoStack *undoStack, QObject *parent = nullptr);
|
||||
#endif
|
||||
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
Io::NodeEntry *rootEntry();
|
||||
void setRootEntry(Io::NodeEntry *entry);
|
||||
Q_INVOKABLE Io::Entry *entry(const QModelIndex &index);
|
||||
|
@ -49,26 +49,27 @@ public:
|
|||
Q_INVOKABLE bool insertEntries(int row, const QModelIndex &parent, const QList<Io::Entry *> &entries);
|
||||
Io::EntryType insertType() const;
|
||||
void setInsertType(Io::EntryType type);
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
|
||||
QModelIndex index(Io::Entry *entry) const;
|
||||
QModelIndex parent(const QModelIndex &child) const;
|
||||
bool hasChildren(const QModelIndex &parent) const;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
bool hasChildren(const QModelIndex &parent) const override;
|
||||
Q_INVOKABLE bool isNode(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QMap<int, QVariant> itemData(const QModelIndex &index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
Q_INVOKABLE int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
Q_INVOKABLE bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
Q_INVOKABLE bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild);
|
||||
QStringList mimeTypes() const;
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
Qt::DropActions supportedDropActions() const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QMap<int, QVariant> itemData(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
Q_INVOKABLE bool moveRows(
|
||||
const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
|
||||
QStringList mimeTypes() const override;
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
Q_INVOKABLE void setInsertTypeToNode();
|
||||
Q_INVOKABLE void setInsertTypeToAccount();
|
||||
|
||||
|
|
|
@ -53,25 +53,26 @@ public:
|
|||
explicit FieldModel(QUndoStack *undoStack, QObject *parent = nullptr);
|
||||
#endif
|
||||
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
Io::AccountEntry *accountEntry();
|
||||
const Io::AccountEntry *accountEntry() const;
|
||||
void setAccountEntry(Io::AccountEntry *entry);
|
||||
std::vector<Io::Field> *fields();
|
||||
PasswordVisibility passwordVisibility() const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
QMap<int, QVariant> itemData(const QModelIndex &index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
Q_INVOKABLE int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
Q_INVOKABLE bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
|
||||
Q_INVOKABLE bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild);
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
QStringList mimeTypes() const;
|
||||
QMimeData *mimeData(const QModelIndexList &indices) const;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QMap<int, QVariant> itemData(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
Q_INVOKABLE bool moveRows(
|
||||
const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
QStringList mimeTypes() const override;
|
||||
QMimeData *mimeData(const QModelIndexList &indices) const override;
|
||||
Q_INVOKABLE const Io::Field *field(std::size_t row) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
|
|
@ -11,18 +11,24 @@ Kirigami.ScrollablePage {
|
|||
property alias rootIndex: delegateModel.rootIndex
|
||||
|
||||
Layout.fillWidth: true
|
||||
title: entryModel.data(rootIndex)
|
||||
title: {
|
||||
var currentEntryName = entryModel.data(rootIndex)
|
||||
return currentEntryName ? currentEntryName : ""
|
||||
}
|
||||
actions {
|
||||
main: Kirigami.Action {
|
||||
iconName: "list-add"
|
||||
text: qsTr("Add account")
|
||||
visible: !nativeInterface.hasEntryFilter
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: insertEntry("Account")
|
||||
shortcut: "Ctrl+A"
|
||||
}
|
||||
left: Kirigami.Action {
|
||||
iconName: "edit-paste"
|
||||
text: qsTr("Paste account")
|
||||
enabled: nativeInterface.canPaste
|
||||
visible: !nativeInterface.hasEntryFilter
|
||||
enabled: nativeInterface.canPaste && !nativeInterface.hasEntryFilter
|
||||
onTriggered: {
|
||||
var pastedEntries = nativeInterface.pasteEntries(rootIndex)
|
||||
if (pastedEntries.length < 1) {
|
||||
|
@ -38,6 +44,8 @@ Kirigami.ScrollablePage {
|
|||
right: Kirigami.Action {
|
||||
iconName: "folder-add"
|
||||
text: qsTr("Add category")
|
||||
visible: !nativeInterface.hasEntryFilter
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: insertEntry("Node")
|
||||
shortcut: "Ctrl+Shift+A"
|
||||
}
|
||||
|
@ -127,6 +135,7 @@ Kirigami.ScrollablePage {
|
|||
Kirigami.ListItemDragHandle {
|
||||
listItem: listItem
|
||||
listView: entriesListView
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
// FIXME: not sure why newIndex + 1 is required to be able to move a row at the end
|
||||
onMoveRequested: entryModel.moveRows(
|
||||
rootIndex, oldIndex, 1, rootIndex,
|
||||
|
@ -167,6 +176,7 @@ Kirigami.ScrollablePage {
|
|||
Controls.MenuItem {
|
||||
icon.name: "edit-cut"
|
||||
text: qsTr("Cut")
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: {
|
||||
nativeInterface.cutEntry(
|
||||
entryModel.index(index, 0,
|
||||
|
@ -177,12 +187,14 @@ Kirigami.ScrollablePage {
|
|||
Controls.MenuItem {
|
||||
icon.name: "edit-delete"
|
||||
text: qsTr("Delete")
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: confirmDeletionDialog.confirmDeletion(
|
||||
model.name, index)
|
||||
}
|
||||
Controls.MenuItem {
|
||||
icon.name: "edit-rename"
|
||||
text: qsTr("Rename")
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: renameDialog.renameEntry(model.name,
|
||||
index)
|
||||
}
|
||||
|
@ -193,6 +205,7 @@ Kirigami.ScrollablePage {
|
|||
Kirigami.Action {
|
||||
iconName: "edit-cut"
|
||||
text: qsTr("Cut")
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: {
|
||||
nativeInterface.cutEntry(entryModel.index(index, 0,
|
||||
rootIndex))
|
||||
|
@ -203,6 +216,7 @@ Kirigami.ScrollablePage {
|
|||
Kirigami.Action {
|
||||
iconName: "edit-delete"
|
||||
text: qsTr("Delete")
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: confirmDeletionDialog.confirmDeletion(
|
||||
model.name, index)
|
||||
shortcut: StandardKey.Delete
|
||||
|
@ -210,6 +224,7 @@ Kirigami.ScrollablePage {
|
|||
Kirigami.Action {
|
||||
iconName: "edit-rename"
|
||||
text: qsTr("Rename")
|
||||
enabled: !nativeInterface.hasEntryFilter
|
||||
onTriggered: renameDialog.renameEntry(model.name, index)
|
||||
shortcut: "F2"
|
||||
}
|
||||
|
|
61
qml/main.qml
61
qml/main.qml
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Templates 2.0 as T2
|
||||
import QtQuick.Controls 2.1 as Controls
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
@ -15,15 +16,6 @@ Kirigami.ApplicationWindow {
|
|||
minimumHeight: 0
|
||||
preferredHeight: Kirigami.Units.gridUnit * 2.3
|
||||
maximumHeight: Kirigami.Units.gridUnit * 3
|
||||
|
||||
/*
|
||||
Controls.TextField {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
placeholderText: qsTr("Filter")
|
||||
width: Kirigami.Units.gridUnit * 8
|
||||
}
|
||||
*/
|
||||
}
|
||||
globalDrawer: Kirigami.GlobalDrawer {
|
||||
id: leftMenu
|
||||
|
@ -37,6 +29,35 @@ Kirigami.ApplicationWindow {
|
|||
topContent: ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Item {
|
||||
Layout.preferredHeight: 4
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: filterTextField.implicitHeight
|
||||
enabled: nativeInterface.fileOpen
|
||||
|
||||
Controls.TextField {
|
||||
id: filterTextField
|
||||
anchors.fill: parent
|
||||
placeholderText: qsTr("Filter")
|
||||
onTextChanged: nativeInterface.entryFilter = text
|
||||
}
|
||||
Kirigami.Icon {
|
||||
source: "edit-clear"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 6
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Kirigami.Units.iconSizes.small
|
||||
height: Kirigami.Units.iconSizes.small
|
||||
visible: filterTextField.text.length !== 0
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: filterTextField.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Controls.MenuSeparator {
|
||||
padding: 0
|
||||
topPadding: 8
|
||||
|
@ -104,6 +125,7 @@ Kirigami.ApplicationWindow {
|
|||
shortcut: StandardKey.Open
|
||||
},
|
||||
Kirigami.Action {
|
||||
id: recentlyOpenedAction
|
||||
text: qsTr("Recently opened ...")
|
||||
iconName: "document-open-recent"
|
||||
children: createRecentlyOpenedActions(
|
||||
|
@ -210,9 +232,7 @@ Kirigami.ApplicationWindow {
|
|||
nativeInterface.fileName))
|
||||
return
|
||||
}
|
||||
var entryModel = nativeInterface.entryModel
|
||||
var rootIndex = entryModel.index(0, 0)
|
||||
pushStackEntry(entryModel, rootIndex)
|
||||
initStack()
|
||||
showPassiveNotification(qsTr("%1 opened").arg(
|
||||
nativeInterface.fileName))
|
||||
leftMenu.close()
|
||||
|
@ -231,6 +251,11 @@ Kirigami.ApplicationWindow {
|
|||
}
|
||||
}
|
||||
onEntryAboutToBeRemoved: {
|
||||
// get the filter entry index
|
||||
if (nativeInterface.hasEntryFilter) {
|
||||
removedIndex = nativeInterface.filterEntryIndex(removedIndex)
|
||||
}
|
||||
|
||||
// remove all possibly open stack pages of the removed entry and its children
|
||||
for (var i = pageStack.depth - 1; i >= 0; --i) {
|
||||
var stackPage = pageStack.get(i)
|
||||
|
@ -243,6 +268,12 @@ Kirigami.ApplicationWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
onHasEntryFilterChanged: {
|
||||
if (nativeInterface.fileOpen) {
|
||||
pageStack.clear()
|
||||
initStack()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
|
@ -285,6 +316,12 @@ Kirigami.ApplicationWindow {
|
|||
onActivated: leftMenu.visible = !leftMenu.visible
|
||||
}
|
||||
|
||||
function initStack() {
|
||||
var entryModel = nativeInterface.hasEntryFilter ? nativeInterface.entryFilterModel : nativeInterface.entryModel
|
||||
var rootIndex = entryModel.index(0, 0)
|
||||
pushStackEntry(entryModel, rootIndex)
|
||||
}
|
||||
|
||||
function clearStack() {
|
||||
pageStack.pop(lastEntriesPage = root.pageStack.initialPage,
|
||||
Controls.StackView.Immediate)
|
||||
|
|
|
@ -309,15 +309,41 @@ void Controller::handleRecentFilesChanged()
|
|||
m_settings.setValue(QStringLiteral("recententries"), m_recentFiles);
|
||||
}
|
||||
|
||||
QStringList Controller::pasteEntries(const QModelIndex &destinationParent, int row)
|
||||
QStringList Controller::pasteEntries(const QModelIndex &destinationParentMaybeFromFilterModel, int row)
|
||||
{
|
||||
if (m_cutEntries.isEmpty() || !m_entryModel.isNode(destinationParent)) {
|
||||
// skip if no entries have been cut
|
||||
if (m_cutEntries.isEmpty()) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
// determine destinationParent and row in the source model
|
||||
QModelIndex destinationParent;
|
||||
if (destinationParentMaybeFromFilterModel.model() == &m_entryFilterModel) {
|
||||
if (row < 0) {
|
||||
row = m_entryFilterModel.rowCount(destinationParentMaybeFromFilterModel);
|
||||
}
|
||||
const auto destinationIndexInFilter = m_entryFilterModel.index(row, 0, destinationParentMaybeFromFilterModel);
|
||||
if (destinationIndexInFilter.isValid()) {
|
||||
const auto destinationIndex = m_entryFilterModel.mapToSource(destinationIndexInFilter);
|
||||
destinationParent = destinationIndex.parent();
|
||||
row = destinationIndex.row();
|
||||
} else {
|
||||
destinationParent = m_entryFilterModel.mapToSource(destinationParentMaybeFromFilterModel);
|
||||
row = -1;
|
||||
}
|
||||
} else {
|
||||
destinationParent = destinationParentMaybeFromFilterModel;
|
||||
}
|
||||
if (row < 0) {
|
||||
row = m_entryModel.rowCount(destinationParent);
|
||||
}
|
||||
|
||||
// skip if destination is no node
|
||||
if (!m_entryModel.isNode(destinationParent)) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
// move the entries
|
||||
QStringList successfullyMovedEntries;
|
||||
successfullyMovedEntries.reserve(m_cutEntries.size());
|
||||
for (const QPersistentModelIndex &cutIndex : m_cutEntries) {
|
||||
|
@ -401,4 +427,17 @@ void Controller::setUseNativeFileDialog(bool useNativeFileDialog)
|
|||
m_settings.setValue(QStringLiteral("usenativefiledialog"), m_useNativeFileDialog);
|
||||
}
|
||||
|
||||
void Controller::setEntryFilter(const QString &filter)
|
||||
{
|
||||
const auto previousFilter(m_entryFilterModel.filterRegExp().pattern());
|
||||
if (filter == previousFilter) {
|
||||
return;
|
||||
}
|
||||
m_entryFilterModel.setFilterRegExp(filter);
|
||||
emit entryFilterChanged(filter);
|
||||
if (previousFilter.isEmpty() != filter.isEmpty()) {
|
||||
emit hasEntryFilterChanged(!filter.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QtGui
|
||||
|
|
|
@ -34,6 +34,8 @@ class Controller : public QObject {
|
|||
Q_PROPERTY(QStringList recentFiles READ recentFiles RESET clearRecentFiles NOTIFY recentFilesChanged)
|
||||
Q_PROPERTY(bool useNativeFileDialog READ useNativeFileDialog WRITE setUseNativeFileDialog NOTIFY useNativeFileDialogChanged)
|
||||
Q_PROPERTY(bool supportsNativeFileDialog READ supportsNativeFileDialog NOTIFY supportsNativeFileDialogChanged)
|
||||
Q_PROPERTY(QString entryFilter READ entryFilter WRITE setEntryFilter NOTIFY entryFilterChanged)
|
||||
Q_PROPERTY(bool hasEntryFilter READ hasEntryFilter NOTIFY hasEntryFilterChanged)
|
||||
|
||||
public:
|
||||
explicit Controller(QSettings &settings, const QString &filePath = QString(), QObject *parent = nullptr);
|
||||
|
@ -53,12 +55,12 @@ public:
|
|||
Io::AccountEntry *currentAccount();
|
||||
void setCurrentAccount(Io::AccountEntry *entry);
|
||||
QModelIndex currentAccountIndex() const;
|
||||
void setCurrentAccountIndex(const QModelIndex &accountIndex);
|
||||
void setCurrentAccountIndex(const QModelIndex &accountIndexMaybeFromFilterModel);
|
||||
bool hasCurrentAccount() const;
|
||||
const QList<QPersistentModelIndex> &cutEntries() const;
|
||||
void setCutEntries(const QList<QPersistentModelIndex> &cutEntries);
|
||||
QString currentAccountName() const;
|
||||
Q_INVOKABLE void cutEntry(const QModelIndex &entryIndex);
|
||||
Q_INVOKABLE void cutEntry(const QModelIndex &entryIndexMaybeFromFilterModel);
|
||||
Q_INVOKABLE QStringList pasteEntries(const QModelIndex &destinationParent, int row = -1);
|
||||
Q_INVOKABLE bool copyToClipboard(const QString &text) const;
|
||||
bool canPaste() const;
|
||||
|
@ -67,6 +69,10 @@ public:
|
|||
bool useNativeFileDialog() const;
|
||||
void setUseNativeFileDialog(bool useNativeFileDialog);
|
||||
bool supportsNativeFileDialog() const;
|
||||
Q_INVOKABLE QModelIndex filterEntryIndex(const QModelIndex &entryIndex) const;
|
||||
QString entryFilter() const;
|
||||
void setEntryFilter(const QString &filter);
|
||||
bool hasEntryFilter() const;
|
||||
|
||||
public slots:
|
||||
void init();
|
||||
|
@ -99,6 +105,8 @@ signals:
|
|||
void useNativeFileDialogChanged(bool useNativeFileDialog);
|
||||
void supportsNativeFileDialogChanged();
|
||||
void entryAboutToBeRemoved(const QModelIndex &removedIndex);
|
||||
void entryFilterChanged(const QString &newFilter);
|
||||
void hasEntryFilterChanged(bool hasEntryFilter);
|
||||
|
||||
private slots:
|
||||
void handleEntriesRemoved(const QModelIndex &parentIndex, int first, int last);
|
||||
|
@ -109,6 +117,7 @@ private:
|
|||
void updateWindowTitle();
|
||||
void setFileOpen(bool fileOpen);
|
||||
void emitIoError(const QString &when);
|
||||
QModelIndex ensureSourceEntryIndex(const QModelIndex &entryIndexMaybeFromFilterModel) const;
|
||||
|
||||
QSettings &m_settings;
|
||||
QString m_filePath;
|
||||
|
@ -127,6 +136,12 @@ private:
|
|||
bool m_useNativeFileDialog;
|
||||
};
|
||||
|
||||
inline QModelIndex Controller::ensureSourceEntryIndex(const QModelIndex &entryIndexMaybeFromFilterModel) const
|
||||
{
|
||||
return entryIndexMaybeFromFilterModel.model() == &m_entryFilterModel ? m_entryFilterModel.mapToSource(entryIndexMaybeFromFilterModel)
|
||||
: entryIndexMaybeFromFilterModel;
|
||||
}
|
||||
|
||||
inline const QString &Controller::filePath() const
|
||||
{
|
||||
return m_filePath;
|
||||
|
@ -193,8 +208,9 @@ inline QModelIndex Controller::currentAccountIndex() const
|
|||
return m_fieldModel.accountEntry() ? m_entryModel.index(const_cast<Io::AccountEntry *>(m_fieldModel.accountEntry())) : QModelIndex();
|
||||
}
|
||||
|
||||
inline void Controller::setCurrentAccountIndex(const QModelIndex &accountIndex)
|
||||
inline void Controller::setCurrentAccountIndex(const QModelIndex &accountIndexMaybeFromFilterModel)
|
||||
{
|
||||
const auto accountIndex = ensureSourceEntryIndex(accountIndexMaybeFromFilterModel);
|
||||
m_fieldModel.setAccountEntry(m_entryModel.isNode(accountIndex) ? nullptr : static_cast<Io::AccountEntry *>(m_entryModel.entry(accountIndex)));
|
||||
emit currentAccountChanged();
|
||||
}
|
||||
|
@ -221,7 +237,7 @@ inline QString Controller::currentAccountName() const
|
|||
|
||||
inline void Controller::cutEntry(const QModelIndex &entryIndex)
|
||||
{
|
||||
cutEntriesChanged(m_cutEntries << QPersistentModelIndex(entryIndex));
|
||||
cutEntriesChanged(m_cutEntries << QPersistentModelIndex(ensureSourceEntryIndex(entryIndex)));
|
||||
}
|
||||
|
||||
inline bool Controller::canPaste() const
|
||||
|
@ -248,6 +264,21 @@ inline bool Controller::supportsNativeFileDialog() const
|
|||
#endif
|
||||
}
|
||||
|
||||
inline QModelIndex Controller::filterEntryIndex(const QModelIndex &entryIndex) const
|
||||
{
|
||||
return m_entryFilterModel.mapFromSource(entryIndex);
|
||||
}
|
||||
|
||||
inline QString Controller::entryFilter() const
|
||||
{
|
||||
return m_entryFilterModel.filterRegExp().pattern();
|
||||
}
|
||||
|
||||
inline bool Controller::hasEntryFilter() const
|
||||
{
|
||||
return !m_entryFilterModel.filterRegExp().isEmpty();
|
||||
}
|
||||
|
||||
} // namespace QtGui
|
||||
|
||||
#endif // QT_QUICK_GUI_CONTROLLER_H
|
||||
|
|
Loading…
Reference in New Issue