Sort devices by name

This commit is contained in:
Martchus 2020-10-20 19:16:53 +02:00
parent a4f6b62a62
commit 57e9865ace
14 changed files with 111 additions and 82 deletions

View File

@ -15,7 +15,7 @@ set(HEADER_FILES
syncthingdevicemodel.h
syncthingdownloadmodel.h
syncthingrecentchangesmodel.h
syncthingsortfilterdirectorymodel.h
syncthingsortfiltermodel.h
syncthingstatusselectionmodel.h
syncthingicons.h
colors.h)
@ -25,7 +25,7 @@ set(SRC_FILES
syncthingdevicemodel.cpp
syncthingdownloadmodel.cpp
syncthingrecentchangesmodel.cpp
syncthingsortfilterdirectorymodel.cpp
syncthingsortfiltermodel.cpp
syncthingstatusselectionmodel.cpp
syncthingicons.cpp)
set(RES_FILES resources/${META_PROJECT_NAME}icons.qrc)

View File

@ -1,10 +1,10 @@
#include "./syncthingsortfilterdirectorymodel.h"
#include "./syncthingsortfiltermodel.h"
#include <QSortFilterProxyModel>
namespace Data {
bool SyncthingSortFilterDirectoryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
bool SyncthingSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
// show all nested structures
if (sourceParent.isValid()) {
@ -14,10 +14,10 @@ bool SyncthingSortFilterDirectoryModel::filterAcceptsRow(int sourceRow, const QM
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
bool SyncthingSortFilterDirectoryModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
bool SyncthingSortFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
// keep order within nested structures
if (m_behavior == SyncthingDirectorySortBehavior::KeepRawOrder || left.parent().isValid() || right.parent().isValid()) {
if (m_behavior == SyncthingSortBehavior::KeepRawOrder || left.parent().isValid() || right.parent().isValid()) {
return left.row() < right.row();
}
// use the default sorting for the top-level

View File

@ -7,42 +7,42 @@
namespace Data {
enum class SyncthingDirectorySortBehavior {
enum class SyncthingSortBehavior {
KeepRawOrder,
Alphabetically,
};
class LIB_SYNCTHING_MODEL_EXPORT SyncthingSortFilterDirectoryModel : public QSortFilterProxyModel {
class LIB_SYNCTHING_MODEL_EXPORT SyncthingSortFilterModel : public QSortFilterProxyModel {
Q_OBJECT
public:
explicit SyncthingSortFilterDirectoryModel(QAbstractItemModel *sourceModel = nullptr, QObject *parent = nullptr);
explicit SyncthingSortFilterModel(QAbstractItemModel *sourceModel = nullptr, QObject *parent = nullptr);
SyncthingDirectorySortBehavior behavior() const;
void setBehavior(SyncthingDirectorySortBehavior behavior);
SyncthingSortBehavior behavior() const;
void setBehavior(SyncthingSortBehavior behavior);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
private:
SyncthingDirectorySortBehavior m_behavior;
SyncthingSortBehavior m_behavior;
};
inline SyncthingSortFilterDirectoryModel::SyncthingSortFilterDirectoryModel(QAbstractItemModel *sourceModel, QObject *parent)
inline SyncthingSortFilterModel::SyncthingSortFilterModel(QAbstractItemModel *sourceModel, QObject *parent)
: QSortFilterProxyModel(parent)
, m_behavior(SyncthingDirectorySortBehavior::Alphabetically)
, m_behavior(SyncthingSortBehavior::Alphabetically)
{
setSortCaseSensitivity(Qt::CaseInsensitive);
setFilterCaseSensitivity(Qt::CaseInsensitive);
setSourceModel(sourceModel);
}
inline SyncthingDirectorySortBehavior SyncthingSortFilterDirectoryModel::behavior() const
inline SyncthingSortBehavior SyncthingSortFilterModel::behavior() const
{
return m_behavior;
}
inline void SyncthingSortFilterDirectoryModel::setBehavior(SyncthingDirectorySortBehavior behavior)
inline void SyncthingSortFilterModel::setBehavior(SyncthingSortBehavior behavior)
{
if (behavior != m_behavior) {
m_behavior = behavior;

View File

@ -55,6 +55,7 @@ SyncthingApplet::SyncthingApplet(QObject *parent, const QVariantList &data)
, m_dirModel(m_connection)
, m_sortFilterDirModel(&m_dirModel)
, m_devModel(m_connection)
, m_sortFilterDevModel(&m_devModel)
, m_downloadModel(m_connection)
, m_recentChangesModel(m_connection)
, m_settingsDlg(nullptr)
@ -68,6 +69,7 @@ SyncthingApplet::SyncthingApplet(QObject *parent, const QVariantList &data)
m_notifier.setService(&m_service);
#endif
m_sortFilterDirModel.sort(0, Qt::AscendingOrder);
m_sortFilterDevModel.sort(0, Qt::AscendingOrder);
qmlRegisterUncreatableMetaObject(Data::staticMetaObject, "martchus.syncthingplasmoid", 0, 6, "Data", QStringLiteral("only enums"));
}

View File

@ -9,7 +9,7 @@
#include "../../model/syncthingdirectorymodel.h"
#include "../../model/syncthingdownloadmodel.h"
#include "../../model/syncthingrecentchangesmodel.h"
#include "../../model/syncthingsortfilterdirectorymodel.h"
#include "../../model/syncthingsortfiltermodel.h"
#include "../../model/syncthingstatusselectionmodel.h"
#include "../../connector/syncthingconnection.h"
@ -39,8 +39,9 @@ class SyncthingApplet : public Plasma::Applet {
Q_OBJECT
Q_PROPERTY(Data::SyncthingConnection *connection READ connection NOTIFY connectionChanged)
Q_PROPERTY(Data::SyncthingDirectoryModel *dirModel READ dirModel NOTIFY dirModelChanged)
Q_PROPERTY(Data::SyncthingSortFilterDirectoryModel *sortFilterDirModel READ sortFilterDirModel NOTIFY dirModelChanged)
Q_PROPERTY(Data::SyncthingSortFilterModel *sortFilterDirModel READ sortFilterDirModel NOTIFY dirModelChanged)
Q_PROPERTY(Data::SyncthingDeviceModel *devModel READ devModel NOTIFY devModelChanged)
Q_PROPERTY(Data::SyncthingSortFilterModel *sortFilterDevModel READ sortFilterDevModel NOTIFY devModelChanged)
Q_PROPERTY(Data::SyncthingDownloadModel *downloadModel READ downloadModel NOTIFY downloadModelChanged)
Q_PROPERTY(Data::SyncthingRecentChangesModel *recentChangesModel READ recentChangesModel NOTIFY recentChangesModelChanged)
Q_PROPERTY(Data::SyncthingStatusSelectionModel *passiveSelectionModel READ passiveSelectionModel NOTIFY passiveSelectionModelChanged)
@ -73,8 +74,9 @@ public:
public:
Data::SyncthingConnection *connection() const;
Data::SyncthingDirectoryModel *dirModel() const;
Data::SyncthingSortFilterDirectoryModel *sortFilterDirModel() const;
Data::SyncthingSortFilterModel *sortFilterDirModel() const;
Data::SyncthingDeviceModel *devModel() const;
Data::SyncthingSortFilterModel *sortFilterDevModel() const;
Data::SyncthingDownloadModel *downloadModel() const;
Data::SyncthingRecentChangesModel *recentChangesModel() const;
Data::SyncthingStatusSelectionModel *passiveSelectionModel() const;
@ -174,8 +176,9 @@ private:
#endif
QtGui::StatusInfo m_statusInfo;
Data::SyncthingDirectoryModel m_dirModel;
Data::SyncthingSortFilterDirectoryModel m_sortFilterDirModel;
Data::SyncthingSortFilterModel m_sortFilterDirModel;
Data::SyncthingDeviceModel m_devModel;
Data::SyncthingSortFilterModel m_sortFilterDevModel;
Data::SyncthingDownloadModel m_downloadModel;
Data::SyncthingRecentChangesModel m_recentChangesModel;
Data::SyncthingStatusSelectionModel m_passiveSelectionModel;
@ -200,9 +203,9 @@ inline Data::SyncthingDirectoryModel *SyncthingApplet::dirModel() const
return const_cast<Data::SyncthingDirectoryModel *>(&m_dirModel);
}
inline Data::SyncthingSortFilterDirectoryModel *SyncthingApplet::sortFilterDirModel() const
inline Data::SyncthingSortFilterModel *SyncthingApplet::sortFilterDirModel() const
{
return const_cast<Data::SyncthingSortFilterDirectoryModel *>(&m_sortFilterDirModel);
return const_cast<Data::SyncthingSortFilterModel *>(&m_sortFilterDirModel);
}
inline Data::SyncthingDeviceModel *SyncthingApplet::devModel() const
@ -210,6 +213,11 @@ inline Data::SyncthingDeviceModel *SyncthingApplet::devModel() const
return const_cast<Data::SyncthingDeviceModel *>(&m_devModel);
}
inline Data::SyncthingSortFilterModel *SyncthingApplet::sortFilterDevModel() const
{
return const_cast<Data::SyncthingSortFilterModel *>(&m_sortFilterDevModel);
}
inline Data::SyncthingDownloadModel *SyncthingApplet::downloadModel() const
{
return const_cast<Data::SyncthingDownloadModel *>(&m_downloadModel);

View File

@ -18,7 +18,7 @@ Item {
TopLevelView {
id: deviceView
width: parent.width
model: plasmoid.nativeInterface.devModel
model: plasmoid.nativeInterface.sortFilterDevModel
delegate: TopLevelItem {
id: item
@ -79,7 +79,7 @@ Item {
model: DelegateModel {
model: plasmoid.nativeInterface.devModel
rootIndex: detailsView.model.modelIndex(index)
rootIndex: deviceView.model.mapToSource(deviceView.model.index(index, 0))
delegate: DetailItem {
width: detailsView.width
}

View File

@ -4,6 +4,7 @@
#include "../../connector/syncthingdev.h"
#include "../../model/syncthingdevicemodel.h"
#include "../../model/syncthingsortfiltermodel.h"
#include <QClipboard>
#include <QGuiApplication>
@ -28,22 +29,19 @@ DevView::DevView(QWidget *parent)
void DevView::mouseReleaseEvent(QMouseEvent *event)
{
QTreeView::mouseReleaseEvent(event);
const auto *const devModel = qobject_cast<const SyncthingDeviceModel *>(model());
if (!devModel) {
const auto pos = event->pos();
const auto clickedRow = ClickedRow(this, pos);
if (!clickedRow) {
return;
}
const QPoint pos(event->pos());
const QModelIndex clickedIndex(indexAt(event->pos()));
if (!clickedIndex.isValid() || clickedIndex.column() != 1 || clickedIndex.parent().isValid()) {
if (clickedRow.index.parent().isValid()) {
return;
}
const SyncthingDev *const devInfo = devModel->devInfo(clickedIndex);
if (!devInfo) {
return;
}
const QRect itemRect(visualRect(clickedIndex));
const auto itemRect = visualRect(clickedRow.proxyIndex);
if (pos.x() > itemRect.right() - 17) {
emit pauseResumeDev(*devInfo);
emit pauseResumeDev(*clickedRow.data);
}
}

View File

@ -6,6 +6,7 @@
namespace Data {
struct SyncthingDev;
class SyncthingDeviceModel;
class SyncthingSortFilterModel;
} // namespace Data
namespace QtGui {
@ -14,7 +15,7 @@ class DevView : public QTreeView {
Q_OBJECT
public:
using ModelType = Data::SyncthingDeviceModel;
using SortFilterModelType = void;
using SortFilterModelType = Data::SyncthingSortFilterModel;
DevView(QWidget *parent = nullptr);

View File

@ -4,7 +4,7 @@
#include "../../connector/syncthingconnection.h"
#include "../../model/syncthingdirectorymodel.h"
#include "../../model/syncthingsortfilterdirectorymodel.h"
#include "../../model/syncthingsortfiltermodel.h"
#include "../../widgets/misc/direrrorsdialog.h"
#include <QClipboard>
@ -31,43 +31,32 @@ void DirView::mouseReleaseEvent(QMouseEvent *event)
{
QTreeView::mouseReleaseEvent(event);
// get SyncthingDir object for clicked index
auto *const sortDirModel = qobject_cast<SortFilterModelType *>(model());
auto *const dirModel = qobject_cast<ModelType *>(sortDirModel ? sortDirModel->sourceModel() : model());
if (!dirModel) {
return;
}
const auto pos = event->pos();
const auto clickedProxyIndex = indexAt(event->pos());
const auto clickedIndex = sortDirModel ? sortDirModel->mapToSource(clickedProxyIndex) : clickedProxyIndex;
if (!clickedIndex.isValid() || clickedIndex.column() != 1) {
return;
}
const auto *const dir = dirModel->dirInfo(clickedIndex);
if (!dir) {
const auto clickedRow = ClickedRow(this, pos);
if (!clickedRow) {
return;
}
if (!clickedIndex.parent().isValid()) {
if (!clickedRow.index.parent().isValid()) {
// open/scan dir buttons
const QRect itemRect = visualRect(clickedProxyIndex);
const QRect itemRect = visualRect(clickedRow.proxyIndex);
if (pos.x() <= itemRect.right() - 58) {
return;
}
if (pos.x() < itemRect.right() - 34) {
if (!dir->paused) {
emit scanDir(*dir);
if (!clickedRow.data->paused) {
emit scanDir(*clickedRow.data);
}
} else if (pos.x() < itemRect.right() - 17) {
emit pauseResumeDir(*dir);
emit pauseResumeDir(*clickedRow.data);
} else {
emit openDir(*dir);
emit openDir(*clickedRow.data);
}
} else if (clickedIndex.row() == 9 && dir->pullErrorCount) {
auto &connection(*dirModel->connection());
connection.requestDirPullErrors(dir->id);
} else if (clickedRow.index.row() == 9 && clickedRow.data->pullErrorCount) {
auto &connection(*clickedRow.model->connection());
connection.requestDirPullErrors(clickedRow.data->id);
auto *const textViewDlg = new DirectoryErrorsDialog(connection, *dir);
auto *const textViewDlg = new DirectoryErrorsDialog(connection, *clickedRow.data);
textViewDlg->setAttribute(Qt::WA_DeleteOnClose);
textViewDlg->show();
}

View File

@ -6,7 +6,7 @@
namespace Data {
struct SyncthingDir;
class SyncthingDirectoryModel;
class SyncthingSortFilterDirectoryModel;
class SyncthingSortFilterModel;
} // namespace Data
namespace QtGui {
@ -15,7 +15,7 @@ class DirView : public QTreeView {
Q_OBJECT
public:
using ModelType = Data::SyncthingDirectoryModel;
using SortFilterModelType = Data::SyncthingSortFilterDirectoryModel;
using SortFilterModelType = Data::SyncthingSortFilterModel;
DirView(QWidget *parent = nullptr);

View File

@ -6,6 +6,7 @@
#include <QClipboard>
#include <QGuiApplication>
#include <QModelIndex>
#include <QPoint>
#include <QTreeView>
#include <functional>
@ -23,8 +24,7 @@ inline auto copyToClipboard(const QString &text)
return [=] { QGuiApplication::clipboard()->setText(text); };
}
template <typename ViewType> struct SelectedRow {
explicit SelectedRow(ViewType *view);
template <typename ViewType> struct BasicRowData {
operator bool() const;
typename ViewType::ModelType *model = nullptr;
@ -32,6 +32,22 @@ template <typename ViewType> struct SelectedRow {
decltype(model->info(index)) data = decltype(model->info(index))();
};
template <typename ViewType> BasicRowData<ViewType>::operator bool() const
{
if (!model || !index.isValid()) {
return false;
}
if constexpr (CppUtilities::Traits::IsSpecializationOf<decltype(data), QPair>::value) {
return data.first;
} else {
return data;
}
}
template <typename ViewType> struct SelectedRow : public BasicRowData<ViewType> {
explicit SelectedRow(ViewType *view);
};
template <typename ViewType> SelectedRow<ViewType>::SelectedRow(ViewType *view)
{
auto *const selectionModel = view->selectionModel();
@ -42,30 +58,38 @@ template <typename ViewType> SelectedRow<ViewType>::SelectedRow(ViewType *view)
if (selectedRows.size() != 1) {
return;
}
index = selectedRows.at(0);
this->index = selectedRows.at(0);
if constexpr (std::is_void_v<typename ViewType::SortFilterModelType>) {
model = qobject_cast<typename ViewType::ModelType *>(view->model());
this->model = qobject_cast<typename ViewType::ModelType *>(view->model());
} else {
const auto *const sortFilterModel = qobject_cast<typename ViewType::SortFilterModelType *>(view->model());
if (sortFilterModel) {
index = sortFilterModel->mapToSource(index);
model = qobject_cast<typename ViewType::ModelType *>(sortFilterModel->sourceModel());
this->index = sortFilterModel->mapToSource(this->index);
this->model = qobject_cast<typename ViewType::ModelType *>(sortFilterModel->sourceModel());
}
}
if (model) {
data = model->info(index);
if (this->model) {
this->data = this->model->info(this->index);
}
}
template <typename ViewType> SelectedRow<ViewType>::operator bool() const
template <typename ViewType> struct ClickedRow : public BasicRowData<ViewType> {
explicit ClickedRow(ViewType *view, const QPoint &clickPoint);
typename ViewType::SortFilterModelType *proxyModel = nullptr;
QModelIndex proxyIndex;
};
template <typename ViewType> ClickedRow<ViewType>::ClickedRow(ViewType *view, const QPoint &clickPoint)
{
if (!model || !index.isValid()) {
return false;
if constexpr (!std::is_void_v<typename ViewType::SortFilterModelType>) {
proxyModel = qobject_cast<typename ViewType::SortFilterModelType *>(view->model());
}
if constexpr (CppUtilities::Traits::IsSpecializationOf<decltype(data), QPair>::value) {
return data.first;
} else {
return data;
this->model = qobject_cast<typename ViewType::ModelType *>(proxyModel ? proxyModel->sourceModel() : view->model());
proxyIndex = view->indexAt(clickPoint);
this->index = proxyModel ? proxyModel->mapToSource(proxyIndex) : proxyIndex;
if (this->model && this->index.isValid() && this->index.column() == 1) {
this->data = this->model->info(this->index);
}
}

View File

@ -79,6 +79,7 @@ TrayWidget::TrayWidget(TrayMenu *parent)
, m_dirModel(m_connection)
, m_sortFilterDirModel(&m_dirModel)
, m_devModel(m_connection)
, m_sortFilterDevModel(&m_devModel)
, m_dlModel(m_connection)
, m_recentChangesModel(m_connection)
, m_selectedConnection(nullptr)
@ -102,7 +103,8 @@ TrayWidget::TrayWidget(TrayMenu *parent)
// setup models and views
m_ui->dirsTreeView->header()->setSortIndicator(0, Qt::AscendingOrder);
m_ui->dirsTreeView->setModel(&m_sortFilterDirModel);
m_ui->devsTreeView->setModel(&m_devModel);
m_ui->devsTreeView->header()->setSortIndicator(0, Qt::AscendingOrder);
m_ui->devsTreeView->setModel(&m_sortFilterDevModel);
m_ui->downloadsTreeView->setModel(&m_dlModel);
m_ui->recentChangesTreeView->setModel(&m_recentChangesModel);
m_ui->recentChangesTreeView->setContextMenuPolicy(Qt::CustomContextMenu);

View File

@ -8,7 +8,7 @@
#include "../../model/syncthingdirectorymodel.h"
#include "../../model/syncthingdownloadmodel.h"
#include "../../model/syncthingrecentchangesmodel.h"
#include "../../model/syncthingsortfilterdirectorymodel.h"
#include "../../model/syncthingsortfiltermodel.h"
#include "../../connector/syncthingconnection.h"
#include "../../connector/syncthingnotifier.h"
@ -121,8 +121,9 @@ private:
Data::SyncthingConnection m_connection;
Data::SyncthingNotifier m_notifier;
Data::SyncthingDirectoryModel m_dirModel;
Data::SyncthingSortFilterDirectoryModel m_sortFilterDirModel;
Data::SyncthingSortFilterModel m_sortFilterDirModel;
Data::SyncthingDeviceModel m_devModel;
Data::SyncthingSortFilterModel m_sortFilterDevModel;
Data::SyncthingDownloadModel m_dlModel;
Data::SyncthingRecentChangesModel m_recentChangesModel;
QMenu *m_connectionsMenu;

View File

@ -436,7 +436,11 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</string>
<number>0</number>
</property>
<item>
<widget class="QtGui::DevView" name="devsTreeView"/>
<widget class="QtGui::DevView" name="devsTreeView">
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
@ -545,8 +549,8 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</string>
</customwidgets>
<resources>
<include location="../../model/resources/syncthingmodelicons.qrc"/>
<include location="../../widgets/resources/syncthingwidgetsicons.qrc"/>
<include location="../resources/syncthingtrayicons.qrc"/>
<include location="../../widgets/resources/syncthingwidgetsicons.qrc"/>
</resources>
<connections/>
</ui>